Check-in [dee8e3e8ea]
Not logged in
Overview
Comment:wiki reference upgrade
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: dee8e3e8ea17f684cbf3c10e90764aba5b34d879
User & Date: vhost7825ssh on 2017-05-19 18:47:53
Other Links: manifest | tags
Context
2017-05-20 10:29
wiki reference upgrade check-in: c8c4e6985d user: vhost7825ssh tags: trunk
2017-05-19 18:47
wiki reference upgrade check-in: dee8e3e8ea user: vhost7825ssh tags: trunk
2017-05-16 00:49
wiki references check-in: 58fe99e749 user: martin_vahi tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/MaidSafe-DHT/.git/index from [e1ac45c7a8] to [84780b31ca].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/MaidSafe-Transport/.git/index from [a58e9471da] to [d9c32def59].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/FETCH_HEAD from [1940f29399] to [3fbb55906c].

1
20110d496e1cfece1bfe80018f456aebf7ab511c		branch 'master' of https://github.com/maidsafe/QA
|
1
b139cda6169d9a9a19b8eef034986b4671f8fd5f		branch 'master' of https://github.com/maidsafe/QA

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/index from [272fdb8450] to [5c28798b7f].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/logs/HEAD from [8eab62ac89] to [10fa464b82].

1
2

0000000000000000000000000000000000000000 5414fefe5b7c68838702e025215dae62a809db4d Martin Vahi <martin.vahi@softf1.com> 1490070070 +0200	clone: from https://github.com/maidsafe/QA.git
5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c Martin Vahi <martin.vahi@softf1.com> 1490143786 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 5414fefe5b7c68838702e025215dae62a809db4d Martin Vahi <martin.vahi@softf1.com> 1490070070 +0200	clone: from https://github.com/maidsafe/QA.git
5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c Martin Vahi <martin.vahi@softf1.com> 1490143786 +0200	pull --recurse-submodules: Fast-forward
20110d496e1cfece1bfe80018f456aebf7ab511c b139cda6169d9a9a19b8eef034986b4671f8fd5f Martin Vahi <martin.vahi@softf1.com> 1494899368 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/logs/refs/heads/master from [8eab62ac89] to [10fa464b82].

1
2

0000000000000000000000000000000000000000 5414fefe5b7c68838702e025215dae62a809db4d Martin Vahi <martin.vahi@softf1.com> 1490070070 +0200	clone: from https://github.com/maidsafe/QA.git
5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c Martin Vahi <martin.vahi@softf1.com> 1490143786 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 5414fefe5b7c68838702e025215dae62a809db4d Martin Vahi <martin.vahi@softf1.com> 1490070070 +0200	clone: from https://github.com/maidsafe/QA.git
5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c Martin Vahi <martin.vahi@softf1.com> 1490143786 +0200	pull --recurse-submodules: Fast-forward
20110d496e1cfece1bfe80018f456aebf7ab511c b139cda6169d9a9a19b8eef034986b4671f8fd5f Martin Vahi <martin.vahi@softf1.com> 1494899368 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/logs/refs/remotes/origin/master from [f15315715c] to [de5c8f6b9a].

1

5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c ts2 <ts2@linux-0fiz.(none)> 1490143677 +0200	pull --recurse-submodules: fast-forward


>
1
2
5414fefe5b7c68838702e025215dae62a809db4d 20110d496e1cfece1bfe80018f456aebf7ab511c ts2 <ts2@linux-0fiz.(none)> 1490143677 +0200	pull --recurse-submodules: fast-forward
20110d496e1cfece1bfe80018f456aebf7ab511c b139cda6169d9a9a19b8eef034986b4671f8fd5f ts2 <ts2@linux-0fiz.(none)> 1494899368 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/objects/03/bc9b1760cf1e3f7c676db83af24130e1598599 version [e21df08d05].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/objects/98/c6dbb485f68e32d61a9ab5e3ad7cb47148918a version [ee651c3b1f].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/objects/b1/39cda6169d9a9a19b8eef034986b4671f8fd5f version [221e829b5f].





>
>
1
2
xJ@=S4xQ0M&XOy;CFML&y~âgoUEG2M@UAbm&ľ(R,mDc&6w1^>()+=k@:؁iV%[U3oǴ.3T_:QLY>xq9 i+}~me8i:-
l*kOyvWk

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/objects/d8/2ffd63c07abc0de1a87f69581dd4018dcdcacf version [a684a2622c].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/refs/heads/master from [e5ee27f3c4] to [dee064cdf2].

1
20110d496e1cfece1bfe80018f456aebf7ab511c
|
1
b139cda6169d9a9a19b8eef034986b4671f8fd5f

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/.git/refs/remotes/origin/master from [e5ee27f3c4] to [dee064cdf2].

1
20110d496e1cfece1bfe80018f456aebf7ab511c
|
1
b139cda6169d9a9a19b8eef034986b4671f8fd5f

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Add New Repository.md version [84bb4c199f].







































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
## Add a New GitHub Repository - QA Steps

New GitHub repo created? Then this document should walk you through the QA steps to standardise your repo, alongside all the other MaidSafe GitHub repositories. For steps and tools please use the MaidSafe-QA user unless instructions specify otherwise.

### Fork the New Repository

While logged into GitHub under your own account, fork the new repo and clone it locally.

### Login to GitHub as MaidSafe-QA

Log out of your own account and log back in as the MaidSafe-QA user.

*At this stage you need to request temporary GitHub "Admin" privileges from Fraser, Viv or David.*

### Add Repository to Travis

Login to [Travis](https://travis-ci.org/), sync account, find the new repository you want to add and flick the switch to on.

![Sync Account](Images/01.png)

### Add Repository to AppVeyor

Login to [AppVeyor](https://ci.appveyor.com/login) and select  `+ NEW PROJECT`

![AppVeyor](Images/02.png)

Then select the repository you would like to add

![AppVeyor select repo](Images/03.png)

Add appveyor.yml and .travis.yml scripts to new repository.

From another [MaidSafe GitHub repository](https://github.com/maidsafe), copy and add the `appveyor.yml` and `.travis.yml` files to the root of your newly-forked local clone of the new repository. The `.travis.yml` will require minor tweaking (more of which in the following steps) especially creating and updating the secure token, which is used to upload rust documentation.

### Give Travis Permissions

While still logged into GitHub as the MaidSafe-QA user, go to settings and select "Personal access tokens". Now click `Generate new token` and create a new "Travis Deploy Token - <new repo name>"

![Travis permissions](Images/04.png)

and limit scopes to `public_repo` as shown below

![Limit scopes](Images/05.png)

Once you have clicked on "Generate token", copy the output as you will not see it again.

[Install Travis gem](https://github.com/travis-ci/travis.rb#installation) to encrypt secure GitHub access

Run this, where `<YOUR_TOKEN>` is the one we copied in the previous step.

`travis encrypt -r maidsafe/<new_repo> GH_TOKEN=<YOUR_TOKEN>`

Edit the `.travis.yml` file you added to the new repo and replace the long string in the line `-secure:` with the output you have just generated - example of what this looks like is below (the string has been shortened in this image).

![travis.yml](Images/06.png)

If you are not at this point going to update the repository's `README.md` then you can push all your local changes upstream and issue a PR to add them to the main repository.

### Webhooks - Add Highfive

Go to the project's settings (the `maidsafe` fork - not your fork) *> Settings > Webhooks & services > Add webhook*

The Payload URL is

```
http://visualiser.maidsafe.net/cgi-bin/highfive/newpr.py
```

![Webhooks](Images/07.png)

![Manage webhook](Images/08.png)


### Highfive Backend Configuration

SSH (details in private assets GitHub repository) to the droplet hosting Highfive

![Droplet](Images/09.png)

Navigate to `/usr/lib/cgi-bin/highfive/configs/`

![ls](Images/10.png)

create a new `<repository_name>.json` file (copy an existing .json file)

![json edit](Images/11.png)

Edit the new `<repository_name>.json` file and update the maintainers' names.

The important section is "groups" - note that entries & file names are case sensitive.

### Add Coverage

Login to [coveralls.io](https://coveralls.io/) using the MaidSafe-QA GitHub account and click `RE-SYNC REPOS`

![coveralls](Images/12.png)

Click `ADD REPOS`

![add repo](Images/13.png)

Flick the switch on your new repository

![flick the switch](Images/14.png)

### Update New Repo's `README.md`

![repo example](Images/15.png)

Above is a screenshot and below is a template, best take the markdown from another repository and edit to fit the purposes of the new repository.

# < repository_name >

[![](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/crust/blob/master/COPYING)


**Primary Maintainer:** < name > (< email_address >)

**Secondary Maintainer:** < name > (< email_address >)

Reliable peer-to-peer network connections in Rust with NAT traversal.

|Crate|Linux/OS X|Windows|Coverage|Issues|
|:---:|:--------:|:-----:|:------:|:----:|
|[![](http://meritbadge.herokuapp.com/crust)](https://crates.io/crates/crust)|[![Build Status](https://travis-ci.org/maidsafe/crust.svg?branch=master)](https://travis-ci.org/maidsafe/crust)|[![Build status](https://ci.appveyor.com/api/projects/status/ajw6ab26p86jdac4/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/crust/branch/master)|[![Coverage Status](https://coveralls.io/repos/maidsafe/crust/badge.svg)](https://coveralls.io/r/maidsafe/crust)|[![Stories in Ready](https://badge.waffle.io/maidsafe/crust.png?label=ready&title=Ready)](https://waffle.io/maidsafe/crust)|

|[API Documentation - master branch](http://maidsafe.net/crust/master)|[SAFE Network System Documentation](http://systemdocs.maidsafe.net)|[MaidSafe website](http://maidsafe.net)| [SAFE Network Forum](https://forum.safenetwork.io)|
|:------:|:-------:|:-------:|:-------:|


## Overview
< insert_overview >
## Todo Items
< insert_todo_items >

*In the above example the badges and links are for `crust` just for illustrative purposes*

One niggle worth noting for AppVeyor badges that has caught a few folk out: you need to grab the markdown for master branch badge - this can be found on the AppVeyor site in the new repo page under: *Settings > Badges* and is the 6th or last entry on the page see below.
This is the one that needs pasted into the project's `README.md` and the QA `README.md`

![AppVeyor badge](Images/16.png)

### Switch On "Build only if .travis.yml / appveyor.yml is present"

Log into Travis and go to repository *> settings > general settings* and switch `ON` *Build only if .travis.yml is present* setting.

![Travis yml present switch](Images/17.png)

Log into Appveyor and go to repository *> settings > general* and tick the *Do not build tags* , *Skip branches without appveyor.yml* and *Rolling builds* check boxes.

![Appveyor yml present switch](Images/19.png)

![Appveyor yml present switch](Images/18.png)

### Add Reviewable

Login to https://reviewable.io using the MaidSafe-QA GitHub account and go to *Repositories* section and toggle to green to enable Reviewable for pull requests.

![Reviewable switch](Images/20.png)


### Update QA readme.md

Finally add a new entry to https://github.com/maidsafe/QA/blob/master/README.md and issue a PR for this.

### Revoke Github "Admin" from MaidSafe-QA user

Once everything is complete, we need to revoke elevated privileges and reduce them back to "Write".

*Ensure `Owners` have "Admin" privileges and `Bots` and `Developers` have "Write" privileges.*

### Checklist to see if everything is ok:

* Did Travis run?
* Did AppVeyor run?
* Does Highfive allocate a reviewer for a PR?
* Do all the links and badges go to the correct places?
* On a successful merge to master did Travis create and publish the documentation?
* Did Coverage run?

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Installers/Vault/Draft Tests/Linux Process.md version [579123b592].



































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# Create Package for Vault on Linux

- [ ] Run the package creation script ` safe_vault/installer/linux/scripts/create_packages.sh` in the `safe_vault` repository
- Check RPM (on e.g. a Fedora test machine)
  - Check installer can upgrade an existing version which is running
    - [ ] Check test machine has older version already installed and `safe_vault` is running
    - [ ] Copy the current bootstrap and config files
    - [ ] New installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check installer can upgrade an existing version which is not running
    - [ ] Check test machine has older version already installed and `safe_vault` is NOT running
    - [ ] Copy the current bootstrap and config files
    - [ ] New installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check installer succeeds on machine with no previous version installed
    - [ ] Check test machine has no version already installed
    - [ ] Installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check repair where current version already installed
    - [ ] Kill and remove existing version of `maidsafe_vault`
    - [ ] Copy the current bootstrap and config files
    - [ ] Installer should rerun without errors
    - [ ] Check `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files haven't been overwritten
    - [ ] Remove bootstrap and config files
    - [ ] Installer should rerun without errors
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check config file is installed in `/var/cache/safe_vault/` has `-rw-r--r--` permissions and `safe` owner name and `root` group name
  - Check uninstall
    - [ ] Check `safe_vault` is running
    - [ ] Uninstall should run without errors
    - [ ] Check `safe_vault` is not running
    - [ ] Check `safe_vault`, bootstrap and config files have all been removed
  - [ ] Copy installer from slave to yum repository machine
  - [ ] Update yum repository
  - [ ] Check `yum install safe-vault` works on a clean machine
  - [ ] Check `yum update` updates existing version
- Check .deb (on e.g. an Ubuntu test machine)
  - Check installer can upgrade an existing version which is running
    - [ ] Check test machine has older version already installed and `safe_vault` is running
    - [ ] Copy the current bootstrap and config files
    - [ ] New installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check installer can upgrade an existing version which is not running
    - [ ] Check test machine has older version already installed and `safe_vault` is NOT running
    - [ ] Copy the current bootstrap and config files
    - [ ] New installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check installer succeeds on machine with no previous version installed
    - [ ] Check test machine has no version already installed
    - [ ] Installer should run without errors
    - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
    - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
  - Check repair where current version already installed
    - [ ] Kill and remove existing version of `safe_vault`
    - [ ] Copy the current bootstrap and config files
    - [ ] Installer should rerun without errors
    - [ ] Check `safe_vault` is running and is installed in `/usr/bin/`
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check bootstrap and config files haven't been overwritten
    - [ ] Remove bootstrap and config files
    - [ ] Installer should rerun without errors
    - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
    - [ ] Check config file is installed in `/var/cache/safe_vault/` has `-rw-r--r--` permissions and `safe` owner name and `root` group name
  - Check uninstall
    - [ ] Check `safe_vault` is running
    - [ ] Uninstall should run without errors
    - [ ] Check `safe_vault` is not running
    - [ ] Check `safe_vault`, bootstrap and config files have all been removed
  - [ ] Copy installer from slave to apt repository machine
  - [ ] Update apt repository
  - [ ] Check `apt-get install safe-vault` works on a clean machine
  - [ ] Check `apt-get update && apt-get upgrade` updates existing version

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Installers/Vault/Draft Tests/OS X Process.md version [d121b73ad8].



































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# Create Package for Vault on OS X

- [ ] Run the package creation script safe_vault/installer/osx/scripts/create_packages.sh in the safe_vault repository
- Check installer can upgrade an existing version which is running
  - [ ] Check test machine has older version already installed and `safe_vault` is running
  - [ ] Copy the current bootstrap and config files
  - [ ] New installer should run without errors
  - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
  - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
  - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
  - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
  - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
- Check installer can upgrade an existing version which is not running
  - [ ] Check test machine has older version already installed and `safe_vault` is NOT running
  - [ ] Copy the current bootstrap and config files
  - [ ] New installer should run without errors
  - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
  - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
  - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
  - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
  - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
- Check installer succeeds on machine with no previous version installed
  - [ ] Check test machine has no version already installed
  - [ ] Installer should run without errors
  - [ ] Check new version of `safe_vault` is running and is installed in `/usr/bin/`
  - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
  - [ ] Check correct config file(s) are installed to the system cache dir `/var/cache/safe_vault`
  - [ ] Check `safe_vault.crust.config` file has `-rw-r--r--` permissions and `safe` owner name and group name
  - [ ] Check bootstrap and config files are not present in app support dir `$HOME/.config/safe_vault/`
- Check repair where current version already installed
  - [ ] Kill and remove existing version of `safe_vault`
  - [ ] Copy the current bootstrap and config files
  - [ ] Installer should rerun without errors
  - [ ] Check `safe_vault` is running and is installed in `/usr/bin/`
  - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
  - [ ] Check bootstrap and config files haven't been overwritten
  - [ ] Remove bootstrap and config files
  - [ ] Installer should rerun without errors
  - [ ] Check `safe_vault` has `-rwxr-xr-x` permissions and `safe` owner name and group name
  - [ ] Check config file is installed in `/var/cache/safe_vault/` has `-rw-r--r--` permissions and `safe` owner name and `root` group name
- Check uninstall
  - [ ] Check `safe_vault` is running
  - [ ] Uninstall should run without errors
  - [ ] Check `safe_vault` is not running
  - [ ] Check `safe_vault`, bootstrap and config files have all been removed
- Check installer can be downloaded
  - [ ] Webpage should detect OS and show link to appropriate installer
  - [ ] Download installer and hash check it against original
  - [ ] Check downloaded filename is meaningful

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Installers/Vault/Draft Tests/Windows Process.md version [8e241a7f6a].





























































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
# Create Package for Vault on Windows

- [ ] Run the installer creation script `safe_vault/installer/windows/create_installer.ps1` in the safe_vault repository
- Check installer can upgrade (using default options) an existing version installed to default location which is running
  - [ ] Check test machine has older version already installed using default options and `safe_vault.exe` is running
  - [ ] Copy the current bootstrap and config files
  - [ ] New installer should run without errors
  - [ ] Check new version of `safe_vault.exe` is running and is installed in default location
  - [ ] Check bootstrap and config files haven't been overwritten
- Check installer can upgrade (using default options) an existing version installed to default location which is not running
  - [ ] Check test machine has older version already installed using default options and `safe_vault.exe` is NOT running
  - [ ] Copy the current bootstrap and config files
  - [ ] New installer should run without errors
  - [ ] Check new version of `safe_vault.exe` is running and is installed in default location
  - [ ] Check bootstrap and config files haven't been overwritten
- Check installer can upgrade (using default options) an existing version installed to non-default location which is running
  - [ ] Check test machine has older version already installed using NON-default options and `safe_vault.exe` is running
  - [ ] Copy the current bootstrap and config files
  - [ ] New installer should run without errors
  - [ ] Check new version of `safe_vault.exe` is running and is installed in default location
  - [ ] Check old version of `safe_vault.exe` has been deleted from non-default location
  - [ ] Check bootstrap and config files haven't been overwritten
- Check installer succeeds using default options on machine with no previous version installed
  - [ ] Check test machine has no version already installed
  - [ ] Installer should run without errors
  - [ ] Check new version of `safe_vault.exe` is running and is installed in default location
  - [ ] Check bootstrap and config files are installed in their default locations
- Check repair where current version installed using defaults
  - [ ] Kill and remove existing version of `safe_vault.exe`
  - [ ] Copy the current bootstrap and config files
  - [ ] Installer should run repair without errors
  - [ ] Check `safe_vault.exe` is running and has been re-installed to previous location
  - [ ] Check bootstrap and config files haven't been overwritten
  - [ ] Remove bootstrap and config files
  - [ ] Installer should run repair without errors
  - [ ] Check `safe_vault.exe` is running and is installed in previous location
- Check repair where current version installed to non-default location
  - [ ] Kill and remove existing version of `safe_vault.exe`
  - [ ] Copy the current bootstrap and config files
  - [ ] Installer should run repair without errors
  - [ ] Check `safe_vault.exe` is running and has been re-installed to previous location
  - [ ] Check bootstrap and config files haven't been overwritten
  - [ ] Remove bootstrap and config files
  - [ ] Installer should run repair without errors
  - [ ] Check `safe_vault.exe` is running and is installed in previous location
- Check uninstall where current version installed using defaults
  - [ ] Check `safe_vault.exe` is running
  - [ ] Uninstall should run without errors
  - [ ] Check `safe_vault.exe` is not running
  - [ ] Check `safe_vault.exe`, bootstrap and config files have all been removed
- Check uninstall where current version installed to non-default location
  - [ ] Check `safe_vault.exe` is running
  - [ ] Uninstall should run without errors
  - [ ] Check `safe_vault.exe` is not running
  - [ ] Check `safe_vault.exe`, bootstrap and config files have all been removed
- [ ] Copy installer from slave to website
- [ ] Update website to link to new installer
- Check installer can be downloaded
  - [ ] Webpage should detect OS and show link to appropriate installer
  - [ ] Download installer and hash check it against original
  - [ ] Check downloaded filename is meaningful
  - [ ] Check installer has appropriate high-res icon

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Installers/Vault/Update Apt and Yum Repos.md version [bf7f894505].

























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
# Update Apt and Yum Repos

##### Build and Transfer 32-bit Package

```sh
ssh maidsafe@178.62.25.205

rustup update
git -C QA pull

cd safe_vault
git pull

~/QA/Bash\ Scripts/create_linux_vault_package.sh
```


##### Build and Transfer 64-bit Package
```sh
ssh maidsafe@178.62.85.248

rustup update
git -C QA pull

cd safe_vault
git pull

~/QA/Bash\ Scripts/create_linux_vault_package.sh
```


##### Update Apt Repo

```sh
ssh maidsafe@apt.maidsafe.net
Version=$(cat safe_vault_latest_version.txt)
cd /var/www/repos/apt/debian

# sudo reprepro remove jessie safe-vault
# sudo reprepro remove wheezy safe-vault

sudo reprepro includedeb jessie ~/SysV-style/safe-vault_"$Version"_amd64.deb
sudo reprepro includedeb jessie ~/SysV-style/safe-vault_"$Version"_i386.deb
sudo reprepro includedeb wheezy ~/SysV-style/safe-vault_"$Version"_amd64.deb
sudo reprepro includedeb wheezy ~/SysV-style/safe-vault_"$Version"_i386.deb

mv ~/safe_*.tar.gz /var/www/tarballs/
```

##### Update Yum Repo

```sh
ssh maidsafe@yum.maidsafe.net
cd /var/www/repos
cp ~/SysV-style/* .
rpm --resign *.rpm
createrepo .  # need '--checksum sha' for at least CentOS <= 5.10  See http://linux.die.net/man/8/createrepo
gpg2 --detach-sign --armor repodata/repomd.xml
```

---

##### Apt Links

- http://www.jejik.com/articles/2006/09/setting_up_and_managing_an_apt_repository_with_reprepro/
- https://mirrorer.alioth.debian.org/reprepro.1.html
- https://wiki.debian.org/HowToSetupADebianRepository#reprepro_for_new_packages
- https://wiki.debian.org/SettingUpSignedAptRepositoryWithReprepro
- https://scotbofh.wordpress.com/2011/04/26/creating-your-own-signed-apt-repository-and-debian-packages/

##### Yum Links

- http://www.idimmu.net/2009/10/20/creating-a-local-and-http-redhat-yum-repository/
- http://yum.baseurl.org/wiki/RepoCreate
- http://fedoranews.org/tchung/gpg/
- https://iuscommunity.org/pages/CreatingAGPGKeyandSigningRPMs.html

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Installers/Vault/Windows Installers.md version [1d5cc36384].







































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Windows Installers

On each of the Windows build machines in the office (one 32-bit, one 64-bit, both Windows 7) do the following process:

- Open C:\MaidSafe\safe_vault\installer\windows\safe_vault_32_and_64_bit.aip in a text editor
- Search for the phrase `Enter path to certificate.p12` and replace it with the actual path to the certificate
- Open a **Powershell** terminal and run the following commands:

```batch
. rustup update
. "C:\Program Files\Git\bin\git.exe" -C C:\MaidSafe\QA pull

cd C:\MaidSafe\safe_vault
. "C:\Program Files\Git\bin\git.exe" pull

. installer\windows\create_installer.ps1

. "C:\Program Files\Git\bin\git.exe" checkout .
```

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Managing Remote Servers.md version [fb67971f79].



































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# Managing Remote Servers

The objective of this document is to detail a standard process for handling remote servers (e.g.
Droplets), so that all MaidSafe remote servers are secure and can be accessed in a similar way.
This should make working with and scripting for these simpler.

Note that this does not apply to "throw-away" remote servers which are used for short-term testing,
and need not be secure.

### Setting up a New Server

Where there is a choice, we should never allow the host to send us a root password via email.  If a
root or sudo user's password _is_ ever emailed (even internally between two MaidSafe employees), it
should immediately be treated as compromised and changed.

In the case of Droplets, we should add all QA members' SSH keys by default.  This allows any QA
member to ssh into the droplet as root.  However, this should generally only ever be done once, in
order to create the new `qa` user as detailed below.  Working as root is not a good practice and
should be kept to a minimum.

As soon as a new server is created, the following steps should be taken:

1. ssh into the server as root
1. create a sudo user named `qa` with a strong, unique, random password.  On Ubuntu:

    ```bash
    adduser qa
    adduser qa sudo
    ```

    or on Fedora:

    ```bash
    useradd qa
    passwd qa
    usermod qa -a -G wheel
    ```

1. exit the ssh session
1. add details of the server to an existing or new document in the QA folder of the private
[Assets](https://github.com/maidsafe/Assets/tree/master/QA) repository

### Managing the Servers

#### Compromised Password

If the password of a sudo user is compromised (e.g. laptop lost/stolen, password emailed), all
affected servers should be updated as soon as possible.  As passwords should be unique, this should
apply to just a single user account on a single server.

The fix can either be to change the password, or to delete the user.

#### Compromised SSH Key

If the private SSH key of a sudo user is compromised (e.g. laptop lost/stolen, private key
emailed!), all affected servers should be updated as soon as possible.

The hard part will be identifying all the accounts to which this key has access.  For a QA team
member, this will likely include the root user, their own user account and perhaps other users'
accounts on every remote server.

The fix is to remove the affected key from the relevant `authorized_keys` files.  This will be in
`/home/<USER>/.ssh/` or `/root/.ssh/`.

#### Adding new Users

If for whatever reason, a non-QA team member wants to access a remote server, don't share
credentials with that member; instead create a new user account for them.  Normally, the only shared
account should be the `qa` one (an exception is the `peer1` account on the `peer_prog.maidsafe.net`
Droplet).

Before creating an account for them, ensure that they really need access to the secure server.  If
their work can be done on a non-secure, throw-away Droplet for example, then that is the best
option.

Don't give the new user sudo access if not required.  If sudo access _is_ required, then create the
new user with a strong, unique, random password, but **don't email this password** to the team
member.  Instead, send it via a mumble message.

The team member should be asked to never change the password to a weak one, nor to one which they
use elsewhere.  They should also notify QA once the account can be deleted.

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Rust Style.md version [7401f55d1a].

































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# Contributing Rust code to MaidSafe

We don't maintain a separate style guide but in general try to follow [common good practice](https://aturon.github.io/), write readable and idiomatic code and aim for full test coverage. In addition, this document lists a few decisions we've reached in discussions about specific topics.

## Rust version

We currently use Rust stable 1.16.0.

## Unwrap

Don't unwrap [`Option`](https://doc.rust-lang.org/std/option/enum.Option.html)s or [`Result`](https://doc.rust-lang.org/std/result/enum.Result.html)s, except possibly when:

1. locking a mutex,
2. spawning a thread,
3. joining a thread

or in other patterns where using them makes the code _much simpler_ and it is _obvious at first glance_ to the reader (even one unfamiliar with the code) that the value cannot be `None`/`Err`.

In these cases, as well as in tests, consider using the macros from the [`unwrap` crate](https://crates.io/crates/unwrap).

## Threads

Generally avoid detached threads. Give child threads meaningful names.

This can easily be achieved by preferring to create child threads using [`maidsafe_utilities::thread::named()`](http://docs.maidsafe.net/maidsafe_utilities/master/maidsafe_utilities/thread/fn.named.html).

* it returns a [`Joiner`](http://docs.maidsafe.net/maidsafe_utilities/master/maidsafe_utilities/thread/struct.Joiner.html) which helps to avoid detached threads
* it requires that the child thread is given a name

## Rustfmt

Apply the latest `rustfmt` to new code before committing, using the default configuration or, if present, the repository's `rustfmt.toml` file.

## Function ordering

In `impl`s, always put public functions before private ones.

## Clippy

If a crate has that feature, make sure your code does not produce any new errors when compiling with `--features=clippy`. If you don't agree with a [Clippy lint](https://github.com/Manishearth/rust-clippy#lints), discuss it with the team before explicitly adding an `#[allow(lint)]` attribute.

For clippy, we currently use Clippy 0.0.120 and nightly installed by `rustup install nightly-2017-03-16`:
```rust
rustc --version
rustc 1.17.0-nightly (0aeb9c129 2017-03-15)
```

**Note for Windows users:** Due to a recent bug in rustup, you may get a missing dll error when trying to run `cargo clippy`.  In this case, you can work around the issue by modifying your `PATH` environment variable:

```
setx PATH "%USERPROFILE%\.multirust\toolchains\nightly-2017-03-16-x86_64-pc-windows-gnu\bin;%PATH%"
```

## Cargo

Use `cargo-edit` to update dependencies or keep the `Cargo.toml` in the formatting that `cargo-edit` uses.

## Other crates

Adding new dependencies to MaidSafe crates in general should be discussed in the team first, except if other MaidSafe crates already have the same dependency. E.g. [quick-error](https://crates.io/crates/quick-error) and [unwrap](https://crates.io/crates/unwrap) are fine to use.

## Git Commit Messages

The first line of the commit message should have the format `<type>/<scope>: <subject>`. For details see the [Leaf project's guidelines](https://github.com/autumnai/leaf/blob/master/CONTRIBUTING.md#git-commit-guidelines).

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Documentation/Update Snapshot Used by Droplet Deployer.md version [d8b1fae71f].





















































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
## Update Snapshot Used by Droplet Deployer

1. Create a new droplet from the existing "Droplet Deployer" [snapshot][0].
1. Make whatever changes are required (user is `qa`, password is held in [release_config repo][1]).
1. On the droplet, run `sudo rm -rf /root/.ssh/ && sudo shutdown -h now`
1. Once the droplet has shut down, take a new snapshot called `Droplet Deployer`.
1. Replicate [the snapshot][0] to all regions (click the "More" option, then "Add to Region").
1. Rename the [old snapshot][0] to `Old Droplet Deployer` (check "Created" values).
1. [Generate a new Personal Access Token][2].
1. To get the ID of the newly-created snapshot, run `curl -sX GET -H "Content-Type: application/json" -H "Authorization: Bearer <token here>" "https://api.digitalocean.com/v2/images?private=true" | sed -n 's/.*"id":\([^,]*\),"name":"Droplet Deployer".*/\n\1\n\n/p'`
1. If this doesn't yield an ID, it may be due to pagination of the response; you may need to add `&page=2` (or whatever value the last page has) to the end of the URL after `private=true`.  Alternatively, check that the [new snapshot][0] has finished being created.
1. Replace the existing value of `"imageId"` in [Droplet Deployer's config.json file][3] with the new one.
1. Test the [Droplet Deployer][4] tool.
1. Commit and push the change.
1. [Delete the Personal Access Token][5].
1. [Delete the `Old Droplet Deployer` snapshot][0].
1. [Delete the freshly-shutdown Droplet][6] used to create the new snapshot.


[0]: https://cloud.digitalocean.com/images/snapshots
[1]: https://github.com/maidsafe/release_config/blob/master/droplets/credentials.json#L3
[2]: https://cloud.digitalocean.com/settings/api/tokens/new
[3]: https://github.com/maidsafe/QA/blob/master/droplet_deployer/config.json#L37
[4]: https://github.com/maidsafe/QA/tree/master/droplet_deployer
[5]: https://cloud.digitalocean.com/settings/api/tokens
[6]: https://cloud.digitalocean.com/droplets

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Adam.pub version [92584adc12].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYrVCkGerTtN6QDfZK30PMORBO7Up6Cbg3fikqIaGlLFN+osMn6NjZvfKBXb2JOnlPGRtuzb8KUYl14gtHo/eQ9BT5ASKbKp+LUw6eEmfcaZdd7H3x9GfsbH3+EG9ALm/NPqUBDXNshRq563yfPJMkz4Rk/hcTVURl0E3IPcLHE5ymjCz8Ar8NMdvmWAD7ft/QqoRRG4Bnx3Tc6uSi5s35jHdj66zQlLpoDpZ+IW3z7mk03nE7B8in1quHfNKwRYNIb0vBoV5nKSFwquGpYfB+M0/g1R9a8JRrLeMGv+XkGVGt6Ltja76fxYygZZDP99XrFqw89bEL4mOzrDCGTwDZ adam@higgsboson

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Andreas.pub version [c2c9b6e8ef].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDUwyrjDbQQhVzXk2mdMLm80/+2eHW1L4fw/flmmee+4FI3WF7b8L1bMjl7TApeMNU+HXc3KxBupkni5LjuXLZOS2L/Zo6yIcrudQpyAb8275phueT3KS36Q4oNLEv+E3IXQiyfNeE8hsvqoFdoo+V9FyR9SFPlDndfUsTC4O/nANWv+jO+1K6Iyd4b5OhZUP+Iw563OtSXFwFGxpgEhz3dUOqL6C0i5M2hxnqdx0FesBowE6uu4Npsjf1KUE/aNcM/+9+loD1PCnQja634V5m6jKy2y121h7n5S/y0gbusoml9Kfe8z30CMwyP4SkHwtBIPG1bf38N08/LUfbr83p7CpIz6wOCcDdY8mx2SsfCoyb0eJcCP7czlqHe70i6F9o77SWWdRX/m25x9bcKug6MUYgVNB5BXbN3nj0RxmitNQ7MpPcs6YD0WxtY8KDh1XZ2a73bie+h/bjN2FqT92AnC9mmZ82YP/v/4l0GI3854dxB5uGGG3m9j1TqYg1I/GVpuqiF7lGRvnR7ip+ahpOVnmaV/pUOQPZGuYps/0hSo5UIo8G1o89nk4eICScwU9h6cSx+MrUjVciPssIadiL4SZ8KU55arkyzXb6zZRhm3MKKBTmB3FIU6/9MW/2N2LcoTurwcC8+wELvGTfYXOIxUVjvpIZ21ZfR7F1n61XRAQ== AndreasFackler@gmx.de

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Bart.pub version [c76b5d6893].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnf8sXey8Q5tBPKEAkJAErTIYgluP/NnMpqG86dcSWDbJOXay5PKQh5iXwRLCJ+ZJLvft2a/QGMVXain/yF9wKugUPosFg7dqgQKyFQk0Y3nKK/I4OGyKd3XJtOBVckYow/wEPDLkAWThf2VimDudUbsJ6VPDbAlWBg8NTiDJRaPzohpkru7c/y+yyuFVxmRi4m+1YzM00R12HJr5jqf/qNOZI/pUccNEhMnchFlU7t++Pk0ZhwOgvLEeGfLGfI622HdNVToVNJ7VVxVMr+qyvqBXiIVfIdRVGvoBeoIboTpUxEcYvkgPouxQxkJOSrbxOF/b+3nQ6bff9UTUDL9zf bartek@bartek

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/David.pub version [d28b9b3b21].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAynpCS4y8Yvvd8w1ZeDlXTjjdgTxTsStqNl9lDWxjlwd8dyIWSOfSyJowB0gz1PAS7/gyuz1+RfOP6n3NmJCg1l1TQI6CXt/0HFTp5ucdL5bvfmUM786rOH4jKxQUbw8Mk6p9upVNaEF6R/WyQP2UwPyQgV+wNBIdheR7ytu5YXXmvaE1bCZ3gXbWvhY0PKQYgpX6dVkTJTYvRPFnffw3M99gIFOkk2lvDhuh/GQeeMC+LMml+NskQfiw+oBxKU4ws756HKr0ZlwyrBfH0SmTW+YxXZl5gsnxz32g2wSc7N/jjnJGZ9CAY/7UrARNfXVg7SByNAf38qqwl6TiFtkjyw== dirvine@dirvine-desktop

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/DiggoryHome.pub version [023e024fb8].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXPPVjQWY1A66cXlZIi7xrmwMa8TPIeYKMX9xWL5rW4IN1FJ0c6smL7qDRKs6eZP5XWYWV+aaeMoV5vBtCEEnA63xnEgQYgiY8UjLxWTY/0owpJWYg6WJNp26b8eKb/5Kwbpy88ETi52mSDTjJY+djfz30SPBOmHRV34Cmpi1paxWxSEzsxblCEU1Hv9WnE/fjt0E1VCKMKS6YGBEFuTRAnfOKIu7wlrbHkB5NaqGTqaj6ChO73TQe77qFnxQOp9Ph2jERaWFwvIZdFH0cD7+WpgmOaSjdzEYUESicqanZSgY2nN23zgMt16rigkuSoUWKhQavHpUFar17tAuQ7HQr dhardy@TPH-L13071

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/DiggoryLaptop.pub version [73f3ce665d].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN0PnwrwauBsFhuDz1I86Dq/yyteYU+qDYdnYcwyknbx8RrDJ9zzf2rPvFgyQwPPE/HZxXO2jp2nRrUnobucC8nFPFU+owf0mgKkWyT+UD1iVvqT3QHvpKgVzcsM4mSKYoQSf0OymPUNbYRRy01BHdNLXrqHFnC6YshPejuLpijiFsKe0OSQIkjcUffx+Xe/iTFmXHSaZTb23wjTwInBNA7ZofTZCJ94uQRxGXqW0hGqeCr6lw5rL18iomX8IhCFSPZnBzVBET9ll4QLVpadeq35noXy+ArgmCoyS60cPnbX/ZpMDleNgV8ClSzjoE0+N7FPb/7OL3L7ZRCgTqO9Pt dhardy@yoga.dhardy

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/DiggoryWork.pub version [7217746439].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDbHl0Nu0wXbj0WFVACmG12uQcNduZsgMpLxL0ANoKMvue4VWhhW/nhIK1AIyW+iSvgf1DVQGduWkoeh7SGWN/eHzAqJ2/o4UFbmsl8mL0bcvSakz9xrwhhZQpaK/Vy2N8319cF3uUwujg3SA9S4Q7tu0UKVYA9YF2AN070z5jnJyqK2VVROoWHM48cm/zwHZJBWsqRya7GxpvG70NsyzR+Ap8oe7NKXynZr8bxnQ3JPJr7PsWnnQiiTlzWhjSInoLU1+5xxvnZe0xPhB8K1BBzoOvJDqeI9IrDVGFcxu5PduIyEP9G43swjU/dMuY7Y87WKzHUCU5EMYx4/R5R/I1 dhardy@localhost.localdomain

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/FraserHomeWindows.pub version [4e917b90c0].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDUwgBg3rxrbI/SBm25Q1tIXV9iym7xBIspRtyY3yhxaPBcggVNU63cwfbjXFUCIHAkA3ZZBHAn+4P6uXYqyz0c7ticl9LOfDQm/mPCyZw3gOrGtcI6/xV5dwvYJpOd8pBFS5jIUXto3EG0YOmSqvxIPllHhzd+6IeK/5QKJPNqaEKYXWtgA55iBUq0JqNOWfJx/whJPzOJVdeWeHQjMg++DBrbBFpbLSh3S3qAda88jKBNL9LtOfXK/VJsdJ7/yW1xYeSA3Zu770y60fvzHOUUTpPuvMKqamHKubU54A8/aSzpaHpNIHuFdAfmwKYT3DfeFIR8644+6GTVVd5jVvF7TBg5+lDABcRqruSx6kc4rFxMWzkcHWZA9dXW2B4KP1WrRzSUmXOMWXcbgdZeCMR9QVP3K/AZdBwhXp8LEJXhOlcsEXplGEcp3FrR6SKtut/dOpLur8z/SOTctgmctHrNKJ145Mmu8ws5b1UNRBmVY+CMNvXHw2pXgz1LACaKx3R2dhTouZiGX19eN6V/Qaa+06hizX6ybsBh/zukdTkHtbLzzaMO46RZISFRFZ+zZzLQtenBTSFlR+8V9e5VhfVy8CxQKupLMeeADKoqrGUEGtouYZ1XoAmAAbX2ctO3sSPqeSYusI3F6tVZ38UpcOjwlWUattLXAL8miF7Pbzixdw== Fraser-Home-Windows

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/FraserOfficeLinux.pub version [b5a3047fff].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDeTwVlMND8ubS3U7OmMhxXg0x+pLIr47JV2+Ks86QKR4uGxby2/CcH18lPydwPSmvM2vWuSL1WvHTItX5jmq2BA6guEMY4GBgs3l/2nAR+rN1A5JKgI1T2HgAOL2tRYrAboNIna0KAl1lMMJPsNv26b9PK6w6NhFl/U8qG8iJkv9FbZClvw34UrDw0qpydrGfS/2xikTSXqcjlofZvzUiK0kaD3R5yDqPc3Sz64UhiLKos/gSKQHNbeNc9W/C1Em/DDM8WneVRfmYMbPru2/6DG1F6z4QIaFm/AeyYlRN5PWtVdH6ycg+WB85ZJyjQvN9JtUGdBJ3rvGHALpm5fCxAwmsR6PGI8r4xJVKOMGf3jYkDLdfNgKgKCuQKV4JL7QMMQxCz5HeoMrBjXbQfoTjkQ3Py2C2iz17Aol6BSyYAdZuD2dIEwV0ds81iRfYVTCw+Hd17iUkWoIS2R74EOYfjMkbdkaMz7Dpoqgn6p5FjSrvwHmkQ+b7zXTlWgmAURYMe67gt8ndm16m+/qyFTy0O6AXK2bo2lpxfq68f4bkWQWY7md7YWE7JRaMH+pu/VFfD/mSeNBN8cWljzlC3iSfT6vBnbLxoPsFdX7GZceks9AQvZMgvpWKjMeJmWmdDVhULBSJH1LjLA1/ddmFRoT036FL3he7+b7GYwZ+mR5RTrw== Fraser-Office-Linux

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Krishna.pub version [1590b2d723].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDXT3Mawk2S1O1sMLSkr/k2E1LERCc9AxSM3SK+asHaNTHPceBFiOyOn+QwePWO8o87lIww4/cNv+lY3aglFfGRyRaJ6mcL0H8Ccoz2AwBdUEbJSY75CJWGZTBFmeL4q3sYU71mdUBYDZwYxWSUSmEmxfATxZG9MZKlvxElCQQXDSDorj/TPPMYaWzhwSl1jhC2wxTrxcU/e9sSm67hBi8hNFxdNlooNhAWYl/pq39/uzRyWrH+lCfq17yuil+1cVQVDs5MF8/caK+jO6mTeHgkO+q+NdEObtijkhQEOZc0+eH0t7/RPdDvUSXe6W9JMYgjFDK4DKn0lFBHPcupjiWSVCVBpbUKbBUHPh75GIN8CYmO/w5VGWgjP5SBQrGtMiPHcFNELDSvcEp5gBQAmjKTbCycD1O6NffejhAcvRMKHMU08EUqHg9phzMbkuh4HUtrTBmf6xYyWLKCzgZSwddt5zRHuPNbca2kH6AFVaCVeuCvNeGlirti6JEVlcxYG1oD2kM0tFKa4UsDuNHmJbEUJW28S5diurXJVpo+iIJ2rLfoCGWnfXYzTyAPXT1t/Wjo3AmJHWym16XGNHmwnjrVXqmLumc+VwOS3xc7nR/utQiH1UZzKlBgUYfXN6pkdq2JNj3awFMLlHSYmAxUlNR7YrpZwZL4nEuRekJOxQFcxQ== krishnaof1988@gmail.com

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Michael.pub version [9a49a43de4].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCoMq7SaKOpcan3UlMqP9CYSrF1IkNekjQ3BKVV7fF0LTN5lxQ9rOi3knEEuFCvH2VMbYEKFGAieJa3OuZHlBQMfv66LChZCeAiBaG68iRww84DXBiGWDTuUOBmwepOhXfKIO4I2Qr/st3sPWbD4ddprHd7TJdFqpnTmGwG61m4wf0m3jWZygfqxA85UlweUjWsP6DerMVrfG7F+kNYGdpFcDR0CjPKC2cHwGyIhmBI9jhLHfR1k03+qLKLAcPIIjh8+iAep4FELpnPkrC222DmAL7X9KDuYeh+V2GWc/jcaERFzk3xUx59L4Q6YGnLcO2EoRlGiBOITdrut9DBCIjCcyd/MCkHovL+zdmWCqxYT4ITFsOW91a5UlAAStQLRtCkHbprmIaNEsu6mWAW6owTAIAj0u5f5wyBOEkb7BSifPpbg0jN1EqbKnx+YuXN5MvrKmRQzARpJCIGyhJBpvP7Uh+IJHtULoJNbd5XzWN0F6Z+szlIsPUt31NbPLIeLzqqHuW+rmf1Cl/wcEX8BzOnP3PtTH6TfxfwcwP3v4n2HchPdzY9ZJRd+E5zuEAW4hJL3iWtTM5ARWZC2RSk1wCXggbUkhUQxpPS4GpTzmaBiHNirNZUJU0SDnHcsYuEsQditSqrh01ss9Y8HQRYJ0n2Qh/soV4sUCoe5dyGp3SfHw== michael@michael-macbook.local

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/QiLinux.pub version [6de8d8a8d9].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCm34L9WS2OpYeJ8caQ3Z6dNrjIB1AZOCzejPJW33CeYMSN153l0p9pAlLNJPgOET/JcSHv07gOsdTzAqWZvEcuaLhCeX3X/WBXg1ZaqPvxXLsJLW4EtXDuENaQQ18oRpKFBuHULjkI4wopw34JMHWh6WIQrPVOLDcXsX9cfknviCGdlBScHahxB5ZZ9w5wKxdRDFqJEkit8rQlJR5grVrUq9SYb9zWUUBE0/YeULD6wIhrm5bDepfuTuELdhXF1nzUNQb6Kis5lsi9N1jeG5jMDWsP0cLYvUg1zkB4COiiI95ZT7Rwggbvj2/qrHG3P4LhJlXjaZTzyxjxZojMG+Tfjd0su3J+cnMGhkwj++f4CeFVo7Vbox6U5WT8E+UCXVqRcgvCOePdO76EI17bkHshhDef2RDGvBCYrkSy4f6iqCoKXRnPav2buEI+/pQgacfdxz3CeBrhuL1mXETO4BWf/YvDZYiX6L2+NgVcAVJEDXFrDNsMR2zRkqAKL3ysBOhGKJY20MxL6DuWMZv3byT3f8W3wnLDOQgN+k4HNtg/q5hi4a5KwoLPMTat/dD9lAgRpUhcdxh1AhkTmWxc12CrCpbVCc8kyzu4gdZLPE7ZGKP5YtbbHMJw5p2TzLMs9w8ZkB/WycTqZsqyYcHDPM5UDIh18/ncbITEhDyZIX6iHQ== qi.ma@maidsafe.net

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/QiWindows.pub version [4a751e88d0].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDX2xmkt7sgPmh13dG51YC2QMrznFWEHeMCqzUfP96mSh1dRPZB6nOFhEvMvHmJhqy6oyxWYChttPtSzWZf3o68+ur/YkRbFONV3Kn8sP9qfQHDGa7scT9n5EDxTLzGm1yN4RlQDD2bdhVkYmdkfLcdsEYntOi4Zj45N+xMziH1NQou02iwHuJTIHOscCxWyuTbKFYydNw1NWbCOX8AA0lZoqtrYTsZMceQ/AkLkG1N/dCZtQxMbfSBuRM9cbLsDK58n9PI+1c6OflIba2pb8lHiq7ThrZY8CcZolvFYRWlVYMfPysjKiiCQzegNQkGvKrb7r89swr6QAd/wGldqGab qi.ma@maidsafe.net

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Ross.pub version [78b91b0f6e].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl0HFTx1cmWG94LxtxYyr0Go4K0kJI3Kd9DU97qPuqrbRnb3Sym8+5C4Xqe4QflqRhluJiWtyZ+XzIiEb0uNGvS2peP7Gb4sdRdfGKFuYg8vfQumv/JhRRn1tw45dOQNDGTAUKFcZmBdpTG8R990LN8991ORSA4jSCzJ3KPbIErhHFI2IknNyURUcopeIu1B3HOwu5WFdC3gWo6XzzgKsenKCQJdlZ1SRSJrHY5L4a4eGTDnkuguE78jx+DpIOJ5UJC1NxfwKOhSG1O34GsBur1lonae5Fx1HwyMRgTmTYGUDNyCo+gqV65y5352wQZrQFc++0YU8cJi3496PQUgWR user@QA-ROSS

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Spandan.pub version [6966862f9b].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpG3EOW3aKzk0NHR6dsP4ORd/gUpttGwECd7IRx4mxUkDYM3cROqy0kbT4IJzUri44EGiKDk5EUhuoNUhA1yW4SgqecE+1AbFfBxUHmzJemqSkctjIxZSuYA+R4c3kbeMLAlk+nEcxxZqTBzyPhNQVqhtLlWYqYVVp41y4HSybInHn4q7vkoUsyAqp+taQX5tafEI2VmokMFdUbVsJDUSGxrzIlj5hPxL4kXzMxMcPMCeuxIKBOJsb/+KjrlsHMrfSrMIdM677Qx4ycoCt1hMpndVXECvBPFT7y/CpXdF3xMT5+hFsdrwYsu4uG8ggi+NZUqFjgcW7FJVDAx0CYr9L ustulation@gmail.com

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Vinicius.pub version [f6ff062577].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMVwr0GWuka5X+GDUyamKe8zFvUVblNce4/p1j/O9bFnHs9d8N+OkYkz6CkBsXsfJpb0+YYwpYdl55/Lg4ohP5mJjWnMDB0pacooSYLwpJSZnlV0+aJgu4gMMRfpP4amYnBVm80iPkZZ42OC/ZVNW5Hd0yTuAFUtdnwDKgV57Rk6rhT5pGWSPYrchIGWJCQzMHAkNMmmA5xPdRzAKo7tTy3mGqdWJfiyqM1J1NSDi7UgQCm8ehu2rN2/Gs+I2E3N08MQnJUOAcMrxe1X3lgA6kXEnYEWurEq5ZhC3sOXw8erOWmNtXvqI2O6C/rXBQgzlVliNxtubl8yWnmNPX8UXF vinipsmaker@vinipsmaker-netbook

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/Viv.pub version [48138a48c3].



>
1
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/s9I/3XYObaipr54raYtt/f1StRcuybWWCfB03rv0yG1duNrIrpSP8dv1uscmt/OXMvUSLdaGURTZZ8XytD6SFwisVSkTQD4tqqk1NmTQt8DEUZ9KErbQCiyEAAcI02QMJ5IeqvismdyvRnfcNV9Nx2vaaCftppJ2R9rTtm9hNOsa4eoLCnuUACvef6jiAa0Fzn5GV7y91dcrVuWiKnUIdBRtxwv1sJRPT6epm6l6AZcpyA+2Qc4kgS2ak4tAjmSlAWUAIoyYECSweCiIwKJL7WLNSNVV3omhljNLONrckOlfglg7LqUrLYMNh2gHPAdUTCPHFuMlIW4rWvSZi9E0JNTZ7o7+x4PWu+SI8a0faXQ1i8S5qSBhNl3HUbChPH7VxktHrZ4rohOpd4WbV75PrzOoycJwplyuyLzLluWOtE/P+a/EmDV/2iUrlYujQQKHaXhbVIaffI8fct+BuPQAN+EmmMIx/h8BSoeWIBMK/ZdxCcDAuCXeoqonYp3QCFef2+dL8CM5EAjGKkxKHPUcFagf/RsM1VMgb0k3Q30jXqc45k8e5XxsI1cXegRrj6z6ZZmLjPOZrdNxclNDz4xigzZwqf6s9uG+0RxgqCvZZoIJpkfGtGviN6Pm1o8/PPGHI3bmrOv8r/ktjy+V2xjKae6Q5Sw/h83gd1csFoosCQ== viv.rajkumar@maidsafe.net

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/Public Keys/authorized_keys version [6d38c40df4].





































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAynpCS4y8Yvvd8w1ZeDlXTjjdgTxTsStqNl9lDWxjlwd8dyIWSOfSyJowB0gz1PAS7/gyuz1+RfOP6n3NmJCg1l1TQI6CXt/0HFTp5ucdL5bvfmUM786rOH4jKxQUbw8Mk6p9upVNaEF6R/WyQP2UwPyQgV+wNBIdheR7ytu5YXXmvaE1bCZ3gXbWvhY0PKQYgpX6dVkTJTYvRPFnffw3M99gIFOkk2lvDhuh/GQeeMC+LMml+NskQfiw+oBxKU4ws756HKr0ZlwyrBfH0SmTW+YxXZl5gsnxz32g2wSc7N/jjnJGZ9CAY/7UrARNfXVg7SByNAf38qqwl6TiFtkjyw== dirvine@dirvine-desktop
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDUwgBg3rxrbI/SBm25Q1tIXV9iym7xBIspRtyY3yhxaPBcggVNU63cwfbjXFUCIHAkA3ZZBHAn+4P6uXYqyz0c7ticl9LOfDQm/mPCyZw3gOrGtcI6/xV5dwvYJpOd8pBFS5jIUXto3EG0YOmSqvxIPllHhzd+6IeK/5QKJPNqaEKYXWtgA55iBUq0JqNOWfJx/whJPzOJVdeWeHQjMg++DBrbBFpbLSh3S3qAda88jKBNL9LtOfXK/VJsdJ7/yW1xYeSA3Zu770y60fvzHOUUTpPuvMKqamHKubU54A8/aSzpaHpNIHuFdAfmwKYT3DfeFIR8644+6GTVVd5jVvF7TBg5+lDABcRqruSx6kc4rFxMWzkcHWZA9dXW2B4KP1WrRzSUmXOMWXcbgdZeCMR9QVP3K/AZdBwhXp8LEJXhOlcsEXplGEcp3FrR6SKtut/dOpLur8z/SOTctgmctHrNKJ145Mmu8ws5b1UNRBmVY+CMNvXHw2pXgz1LACaKx3R2dhTouZiGX19eN6V/Qaa+06hizX6ybsBh/zukdTkHtbLzzaMO46RZISFRFZ+zZzLQtenBTSFlR+8V9e5VhfVy8CxQKupLMeeADKoqrGUEGtouYZ1XoAmAAbX2ctO3sSPqeSYusI3F6tVZ38UpcOjwlWUattLXAL8miF7Pbzixdw== Fraser-Home-Windows
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDeTwVlMND8ubS3U7OmMhxXg0x+pLIr47JV2+Ks86QKR4uGxby2/CcH18lPydwPSmvM2vWuSL1WvHTItX5jmq2BA6guEMY4GBgs3l/2nAR+rN1A5JKgI1T2HgAOL2tRYrAboNIna0KAl1lMMJPsNv26b9PK6w6NhFl/U8qG8iJkv9FbZClvw34UrDw0qpydrGfS/2xikTSXqcjlofZvzUiK0kaD3R5yDqPc3Sz64UhiLKos/gSKQHNbeNc9W/C1Em/DDM8WneVRfmYMbPru2/6DG1F6z4QIaFm/AeyYlRN5PWtVdH6ycg+WB85ZJyjQvN9JtUGdBJ3rvGHALpm5fCxAwmsR6PGI8r4xJVKOMGf3jYkDLdfNgKgKCuQKV4JL7QMMQxCz5HeoMrBjXbQfoTjkQ3Py2C2iz17Aol6BSyYAdZuD2dIEwV0ds81iRfYVTCw+Hd17iUkWoIS2R74EOYfjMkbdkaMz7Dpoqgn6p5FjSrvwHmkQ+b7zXTlWgmAURYMe67gt8ndm16m+/qyFTy0O6AXK2bo2lpxfq68f4bkWQWY7md7YWE7JRaMH+pu/VFfD/mSeNBN8cWljzlC3iSfT6vBnbLxoPsFdX7GZceks9AQvZMgvpWKjMeJmWmdDVhULBSJH1LjLA1/ddmFRoT036FL3he7+b7GYwZ+mR5RTrw== Fraser-Office-Linux
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDXT3Mawk2S1O1sMLSkr/k2E1LERCc9AxSM3SK+asHaNTHPceBFiOyOn+QwePWO8o87lIww4/cNv+lY3aglFfGRyRaJ6mcL0H8Ccoz2AwBdUEbJSY75CJWGZTBFmeL4q3sYU71mdUBYDZwYxWSUSmEmxfATxZG9MZKlvxElCQQXDSDorj/TPPMYaWzhwSl1jhC2wxTrxcU/e9sSm67hBi8hNFxdNlooNhAWYl/pq39/uzRyWrH+lCfq17yuil+1cVQVDs5MF8/caK+jO6mTeHgkO+q+NdEObtijkhQEOZc0+eH0t7/RPdDvUSXe6W9JMYgjFDK4DKn0lFBHPcupjiWSVCVBpbUKbBUHPh75GIN8CYmO/w5VGWgjP5SBQrGtMiPHcFNELDSvcEp5gBQAmjKTbCycD1O6NffejhAcvRMKHMU08EUqHg9phzMbkuh4HUtrTBmf6xYyWLKCzgZSwddt5zRHuPNbca2kH6AFVaCVeuCvNeGlirti6JEVlcxYG1oD2kM0tFKa4UsDuNHmJbEUJW28S5diurXJVpo+iIJ2rLfoCGWnfXYzTyAPXT1t/Wjo3AmJHWym16XGNHmwnjrVXqmLumc+VwOS3xc7nR/utQiH1UZzKlBgUYfXN6pkdq2JNj3awFMLlHSYmAxUlNR7YrpZwZL4nEuRekJOxQFcxQ== krishnaof1988@gmail.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCwTp0j1PVpCCi8L6OV0VzCl8tP8eyRBM/eBuud+uEjna6HtpEsvtnTzQmp0Tqx62ktGFKEYqKL/F9m0gNgP1nBC6LqExNXkR7+YVXRNgAoF1J8JF+zdIBOyTaGcFqB1R8/1iL7Aybl8u+eS0wM2I++kgAi5npRQDmNgA/b5AotoSsSwgIatmq6c4PY0wiNr9NF9C58VFHiw+p4IIFO1Jfnx3pkSjaL/DmXvawwbeOit/ik4V7ESvM5Ioao2F1Gydim8DEIKfH/r8FHpaE4TlwuIuveP/Fcz9iS5K/pqVNEQlvwLAyrYrjwOc01JRKQE1q1oF6aaryd2UjzbqtKN2Xt qi.ma@maidsafe.net
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCl0HFTx1cmWG94LxtxYyr0Go4K0kJI3Kd9DU97qPuqrbRnb3Sym8+5C4Xqe4QflqRhluJiWtyZ+XzIiEb0uNGvS2peP7Gb4sdRdfGKFuYg8vfQumv/JhRRn1tw45dOQNDGTAUKFcZmBdpTG8R990LN8991ORSA4jSCzJ3KPbIErhHFI2IknNyURUcopeIu1B3HOwu5WFdC3gWo6XzzgKsenKCQJdlZ1SRSJrHY5L4a4eGTDnkuguE78jx+DpIOJ5UJC1NxfwKOhSG1O34GsBur1lonae5Fx1HwyMRgTmTYGUDNyCo+gqV65y5352wQZrQFc++0YU8cJi3496PQUgWR user@QA-ROSS
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCpG3EOW3aKzk0NHR6dsP4ORd/gUpttGwECd7IRx4mxUkDYM3cROqy0kbT4IJzUri44EGiKDk5EUhuoNUhA1yW4SgqecE+1AbFfBxUHmzJemqSkctjIxZSuYA+R4c3kbeMLAlk+nEcxxZqTBzyPhNQVqhtLlWYqYVVp41y4HSybInHn4q7vkoUsyAqp+taQX5tafEI2VmokMFdUbVsJDUSGxrzIlj5hPxL4kXzMxMcPMCeuxIKBOJsb/+KjrlsHMrfSrMIdM677Qx4ycoCt1hMpndVXECvBPFT7y/CpXdF3xMT5+hFsdrwYsu4uG8ggi+NZUqFjgcW7FJVDAx0CYr9L ustulation@gmail.com
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDMVwr0GWuka5X+GDUyamKe8zFvUVblNce4/p1j/O9bFnHs9d8N+OkYkz6CkBsXsfJpb0+YYwpYdl55/Lg4ohP5mJjWnMDB0pacooSYLwpJSZnlV0+aJgu4gMMRfpP4amYnBVm80iPkZZ42OC/ZVNW5Hd0yTuAFUtdnwDKgV57Rk6rhT5pGWSPYrchIGWJCQzMHAkNMmmA5xPdRzAKo7tTy3mGqdWJfiyqM1J1NSDi7UgQCm8ehu2rN2/Gs+I2E3N08MQnJUOAcMrxe1X3lgA6kXEnYEWurEq5ZhC3sOXw8erOWmNtXvqI2O6C/rXBQgzlVliNxtubl8yWnmNPX8UXF vinipsmaker@vinipsmaker-netbook
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQC/s9I/3XYObaipr54raYtt/f1StRcuybWWCfB03rv0yG1duNrIrpSP8dv1uscmt/OXMvUSLdaGURTZZ8XytD6SFwisVSkTQD4tqqk1NmTQt8DEUZ9KErbQCiyEAAcI02QMJ5IeqvismdyvRnfcNV9Nx2vaaCftppJ2R9rTtm9hNOsa4eoLCnuUACvef6jiAa0Fzn5GV7y91dcrVuWiKnUIdBRtxwv1sJRPT6epm6l6AZcpyA+2Qc4kgS2ak4tAjmSlAWUAIoyYECSweCiIwKJL7WLNSNVV3omhljNLONrckOlfglg7LqUrLYMNh2gHPAdUTCPHFuMlIW4rWvSZi9E0JNTZ7o7+x4PWu+SI8a0faXQ1i8S5qSBhNl3HUbChPH7VxktHrZ4rohOpd4WbV75PrzOoycJwplyuyLzLluWOtE/P+a/EmDV/2iUrlYujQQKHaXhbVIaffI8fct+BuPQAN+EmmMIx/h8BSoeWIBMK/ZdxCcDAuCXeoqonYp3QCFef2+dL8CM5EAjGKkxKHPUcFagf/RsM1VMgb0k3Q30jXqc45k8e5XxsI1cXegRrj6z6ZZmLjPOZrdNxclNDz4xigzZwqf6s9uG+0RxgqCvZZoIJpkfGtGviN6Pm1o8/PPGHI3bmrOv8r/ktjy+V2xjKae6Q5Sw/h83gd1csFoosCQ== viv.rajkumar@maidsafe.net
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDUwyrjDbQQhVzXk2mdMLm80/+2eHW1L4fw/flmmee+4FI3WF7b8L1bMjl7TApeMNU+HXc3KxBupkni5LjuXLZOS2L/Zo6yIcrudQpyAb8275phueT3KS36Q4oNLEv+E3IXQiyfNeE8hsvqoFdoo+V9FyR9SFPlDndfUsTC4O/nANWv+jO+1K6Iyd4b5OhZUP+Iw563OtSXFwFGxpgEhz3dUOqL6C0i5M2hxnqdx0FesBowE6uu4Npsjf1KUE/aNcM/+9+loD1PCnQja634V5m6jKy2y121h7n5S/y0gbusoml9Kfe8z30CMwyP4SkHwtBIPG1bf38N08/LUfbr83p7CpIz6wOCcDdY8mx2SsfCoyb0eJcCP7czlqHe70i6F9o77SWWdRX/m25x9bcKug6MUYgVNB5BXbN3nj0RxmitNQ7MpPcs6YD0WxtY8KDh1XZ2a73bie+h/bjN2FqT92AnC9mmZ82YP/v/4l0GI3854dxB5uGGG3m9j1TqYg1I/GVpuqiF7lGRvnR7ip+ahpOVnmaV/pUOQPZGuYps/0hSo5UIo8G1o89nk4eICScwU9h6cSx+MrUjVciPssIadiL4SZ8KU55arkyzXb6zZRhm3MKKBTmB3FIU6/9MW/2N2LcoTurwcC8+wELvGTfYXOIxUVjvpIZ21ZfR7F1n61XRAQ== AndreasFackler@gmx.de
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDYrVCkGerTtN6QDfZK30PMORBO7Up6Cbg3fikqIaGlLFN+osMn6NjZvfKBXb2JOnlPGRtuzb8KUYl14gtHo/eQ9BT5ASKbKp+LUw6eEmfcaZdd7H3x9GfsbH3+EG9ALm/NPqUBDXNshRq563yfPJMkz4Rk/hcTVURl0E3IPcLHE5ymjCz8Ar8NMdvmWAD7ft/QqoRRG4Bnx3Tc6uSi5s35jHdj66zQlLpoDpZ+IW3z7mk03nE7B8in1quHfNKwRYNIb0vBoV5nKSFwquGpYfB+M0/g1R9a8JRrLeMGv+XkGVGt6Ltja76fxYygZZDP99XrFqw89bEL4mOzrDCGTwDZ adam@higgsboson
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCnf8sXey8Q5tBPKEAkJAErTIYgluP/NnMpqG86dcSWDbJOXay5PKQh5iXwRLCJ+ZJLvft2a/QGMVXain/yF9wKugUPosFg7dqgQKyFQk0Y3nKK/I4OGyKd3XJtOBVckYow/wEPDLkAWThf2VimDudUbsJ6VPDbAlWBg8NTiDJRaPzohpkru7c/y+yyuFVxmRi4m+1YzM00R12HJr5jqf/qNOZI/pUccNEhMnchFlU7t++Pk0ZhwOgvLEeGfLGfI622HdNVToVNJ7VVxVMr+qyvqBXiIVfIdRVGvoBeoIboTpUxEcYvkgPouxQxkJOSrbxOF/b+3nQ6bff9UTUDL9zf bart@home
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCm34L9WS2OpYeJ8caQ3Z6dNrjIB1AZOCzejPJW33CeYMSN153l0p9pAlLNJPgOET/JcSHv07gOsdTzAqWZvEcuaLhCeX3X/WBXg1ZaqPvxXLsJLW4EtXDuENaQQ18oRpKFBuHULjkI4wopw34JMHWh6WIQrPVOLDcXsX9cfknviCGdlBScHahxB5ZZ9w5wKxdRDFqJEkit8rQlJR5grVrUq9SYb9zWUUBE0/YeULD6wIhrm5bDepfuTuELdhXF1nzUNQb6Kis5lsi9N1jeG5jMDWsP0cLYvUg1zkB4COiiI95ZT7Rwggbvj2/qrHG3P4LhJlXjaZTzyxjxZojMG+Tfjd0su3J+cnMGhkwj++f4CeFVo7Vbox6U5WT8E+UCXVqRcgvCOePdO76EI17bkHshhDef2RDGvBCYrkSy4f6iqCoKXRnPav2buEI+/pQgacfdxz3CeBrhuL1mXETO4BWf/YvDZYiX6L2+NgVcAVJEDXFrDNsMR2zRkqAKL3ysBOhGKJY20MxL6DuWMZv3byT3f8W3wnLDOQgN+k4HNtg/q5hi4a5KwoLPMTat/dD9lAgRpUhcdxh1AhkTmWxc12CrCpbVCc8kyzu4gdZLPE7ZGKP5YtbbHMJw5p2TzLMs9w8ZkB/WycTqZsqyYcHDPM5UDIh18/ncbITEhDyZIX6iHQ== qi.ma@maidsafe.net
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDX2xmkt7sgPmh13dG51YC2QMrznFWEHeMCqzUfP96mSh1dRPZB6nOFhEvMvHmJhqy6oyxWYChttPtSzWZf3o68+ur/YkRbFONV3Kn8sP9qfQHDGa7scT9n5EDxTLzGm1yN4RlQDD2bdhVkYmdkfLcdsEYntOi4Zj45N+xMziH1NQou02iwHuJTIHOscCxWyuTbKFYydNw1NWbCOX8AA0lZoqtrYTsZMceQ/AkLkG1N/dCZtQxMbfSBuRM9cbLsDK58n9PI+1c6OflIba2pb8lHiq7ThrZY8CcZolvFYRWlVYMfPysjKiiCQzegNQkGvKrb7r89swr6QAd/wGldqGab qi.ma@maidsafe.net
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDXPPVjQWY1A66cXlZIi7xrmwMa8TPIeYKMX9xWL5rW4IN1FJ0c6smL7qDRKs6eZP5XWYWV+aaeMoV5vBtCEEnA63xnEgQYgiY8UjLxWTY/0owpJWYg6WJNp26b8eKb/5Kwbpy88ETi52mSDTjJY+djfz30SPBOmHRV34Cmpi1paxWxSEzsxblCEU1Hv9WnE/fjt0E1VCKMKS6YGBEFuTRAnfOKIu7wlrbHkB5NaqGTqaj6ChO73TQe77qFnxQOp9Ph2jERaWFwvIZdFH0cD7+WpgmOaSjdzEYUESicqanZSgY2nN23zgMt16rigkuSoUWKhQavHpUFar17tAuQ7HQr dhardy@TPH-L13071
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDN0PnwrwauBsFhuDz1I86Dq/yyteYU+qDYdnYcwyknbx8RrDJ9zzf2rPvFgyQwPPE/HZxXO2jp2nRrUnobucC8nFPFU+owf0mgKkWyT+UD1iVvqT3QHvpKgVzcsM4mSKYoQSf0OymPUNbYRRy01BHdNLXrqHFnC6YshPejuLpijiFsKe0OSQIkjcUffx+Xe/iTFmXHSaZTb23wjTwInBNA7ZofTZCJ94uQRxGXqW0hGqeCr6lw5rL18iomX8IhCFSPZnBzVBET9ll4QLVpadeq35noXy+ArgmCoyS60cPnbX/ZpMDleNgV8ClSzjoE0+N7FPb/7OL3L7ZRCgTqO9Pt dhardy@yoga.dhardy
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDDbHl0Nu0wXbj0WFVACmG12uQcNduZsgMpLxL0ANoKMvue4VWhhW/nhIK1AIyW+iSvgf1DVQGduWkoeh7SGWN/eHzAqJ2/o4UFbmsl8mL0bcvSakz9xrwhhZQpaK/Vy2N8319cF3uUwujg3SA9S4Q7tu0UKVYA9YF2AN070z5jnJyqK2VVROoWHM48cm/zwHZJBWsqRya7GxpvG70NsyzR+Ap8oe7NKXynZr8bxnQ3JPJr7PsWnnQiiTlzWhjSInoLU1+5xxvnZe0xPhB8K1BBzoOvJDqeI9IrDVGFcxu5PduIyEP9G43swjU/dMuY7Y87WKzHUCU5EMYx4/R5R/I1 dhardy@localhost.localdomain
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCoMq7SaKOpcan3UlMqP9CYSrF1IkNekjQ3BKVV7fF0LTN5lxQ9rOi3knEEuFCvH2VMbYEKFGAieJa3OuZHlBQMfv66LChZCeAiBaG68iRww84DXBiGWDTuUOBmwepOhXfKIO4I2Qr/st3sPWbD4ddprHd7TJdFqpnTmGwG61m4wf0m3jWZygfqxA85UlweUjWsP6DerMVrfG7F+kNYGdpFcDR0CjPKC2cHwGyIhmBI9jhLHfR1k03+qLKLAcPIIjh8+iAep4FELpnPkrC222DmAL7X9KDuYeh+V2GWc/jcaERFzk3xUx59L4Q6YGnLcO2EoRlGiBOITdrut9DBCIjCcyd/MCkHovL+zdmWCqxYT4ITFsOW91a5UlAAStQLRtCkHbprmIaNEsu6mWAW6owTAIAj0u5f5wyBOEkb7BSifPpbg0jN1EqbKnx+YuXN5MvrKmRQzARpJCIGyhJBpvP7Uh+IJHtULoJNbd5XzWN0F6Z+szlIsPUt31NbPLIeLzqqHuW+rmf1Cl/wcEX8BzOnP3PtTH6TfxfwcwP3v4n2HchPdzY9ZJRd+E5zuEAW4hJL3iWtTM5ARWZC2RSk1wCXggbUkhUQxpPS4GpTzmaBiHNirNZUJU0SDnHcsYuEsQditSqrh01ss9Y8HQRYJ0n2Qh/soV4sUCoe5dyGp3SfHw== michael@michael-macbook.local

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/QA/README.md from [23f156eea6] to [82c67d06d2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

| Repo                                                                         | Crate                                                                                                          | Linux/OS X                                                                                                                                        | ARM (Linux)                                                                                                                                                             | Windows                                                                                                                                                                                  | Coverage                                                                                                                                                                                           | Issues                                                                                                                                                        |
|:-----------------------------------------------------------------------------|:--------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------:|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------------------------------------------------------------------------------------------------------------------:|
| [accumulator](https://github.com/maidsafe/accumulator)                       | [![](http://meritbadge.herokuapp.com/accumulator)](https://crates.io/crates/accumulator)                       | [![Build Status](https://travis-ci.org/maidsafe/accumulator.svg?branch=master)](https://travis-ci.org/maidsafe/accumulator)                       |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/1imtexgsshnpxnvn/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/accumulator/branch/master)            | [![Coverage Status](https://coveralls.io/repos/maidsafe/accumulator/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/accumulator?branch=master)                       | [![Stories in Ready](https://badge.waffle.io/maidsafe/accumulator.png?label=ready&title=Ready)](https://waffle.io/maidsafe/accumulator)                       |
| [config_file_handler](https://github.com/maidsafe/config_file_handler)       | [![](http://meritbadge.herokuapp.com/config_file_handler)](https://crates.io/crates/config_file_handler)       | [![Build Status](https://travis-ci.org/maidsafe/config_file_handler.svg?branch=master)](https://travis-ci.org/maidsafe/config_file_handler)       |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/22gb4w9fhvhv3hn4/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/config-file-handler/branch/master)    | [![Coverage Status](https://coveralls.io/repos/maidsafe/config_file_handler/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/config_file_handler?branch=master)       | [![Stories in Ready](https://badge.waffle.io/maidsafe/config_file_handler.png?label=ready&title=Ready)](https://waffle.io/maidsafe/config_file_handler)       |
| [crust](https://github.com/maidsafe/crust)                                   | [![](http://meritbadge.herokuapp.com/crust)](https://crates.io/crates/crust)                                   | [![Build Status](https://travis-ci.org/maidsafe/crust.svg?branch=master)](https://travis-ci.org/maidsafe/crust)                                   | [![Build Status](http://ci.maidsafe.net:8080/buildStatus/icon?job=crust_arm_status_badge)](http://ci.maidsafe.net:8080/job/crust_arm_status_badge/)                     | [![Build status](https://ci.appveyor.com/api/projects/status/ajw6ab26p86jdac4/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/crust/branch/master)                  | [![Coverage Status](https://coveralls.io/repos/maidsafe/crust/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/crust?branch=master)                                   | [![Stories in Ready](https://badge.waffle.io/maidsafe/crust.png?label=ready&title=Ready)](https://waffle.io/maidsafe/crust)                                   |
| [kademlia_routing_table](https://github.com/maidsafe/kademlia_routing_table) | [![](http://meritbadge.herokuapp.com/kademlia_routing_table)](https://crates.io/crates/kademlia_routing_table) | [![Build Status](https://travis-ci.org/maidsafe/kademlia_routing_table.svg?branch=master)](https://travis-ci.org/maidsafe/kademlia_routing_table) |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/ex67c1t4d24vwc29/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/kademlia-routing-table/branch/master) | [![Coverage Status](https://coveralls.io/repos/maidsafe/kademlia_routing_table/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/kademlia_routing_table?branch=master) | [![Stories in Ready](https://badge.waffle.io/maidsafe/kademlia_routing_table.png?label=ready&title=Ready)](https://waffle.io/maidsafe/kademlia_routing_table) |
| [lru_time_cache](https://github.com/maidsafe/lru_time_cache)                 | [![](http://meritbadge.herokuapp.com/lru_time_cache)](https://crates.io/crates/lru_time_cache)                 | [![Build Status](https://travis-ci.org/maidsafe/lru_time_cache.svg?branch=master)](https://travis-ci.org/maidsafe/lru_time_cache)                 |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/15km1vxtg83qgvb5/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/lru-time-cache/branch/master)         | [![Coverage Status](https://coveralls.io/repos/maidsafe/lru_time_cache/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/lru_time_cache?branch=master)                 | [![Stories in Ready](https://badge.waffle.io/maidsafe/lru_time_cache.png?label=ready&title=Ready)](https://waffle.io/maidsafe/lru_time_cache)                 |
| [maidsafe_utilities](https://github.com/maidsafe/maidsafe_utilities)         | [![](http://meritbadge.herokuapp.com/maidsafe_utilities)](https://crates.io/crates/maidsafe_utilities)         | [![Build Status](https://travis-ci.org/maidsafe/maidsafe_utilities.svg?branch=master)](https://travis-ci.org/maidsafe/maidsafe_utilities)         |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/f7x8p4y66lwua38t/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/maidsafe-utilities/branch/master)     | [![Coverage Status](https://coveralls.io/repos/maidsafe/maidsafe_utilities/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/maidsafe_utilities?branch=master)         | [![Stories in Ready](https://badge.waffle.io/maidsafe/maidsafe_utilities.png?label=ready&title=Ready)](https://waffle.io/maidsafe/maidsafe_utilities)         |
| [routing](https://github.com/maidsafe/routing)                               | [![](http://meritbadge.herokuapp.com/routing)](https://crates.io/crates/routing)                               | [![Build Status](https://travis-ci.org/maidsafe/routing.svg?branch=master)](https://travis-ci.org/maidsafe/routing)                               | [![Build Status](http://ci.maidsafe.net:8080/buildStatus/icon?job=routing_arm_status_badge)](http://ci.maidsafe.net:8080/job/routing_arm_status_badge/)                 | [![Build status](https://ci.appveyor.com/api/projects/status/2w1joqd2h64o4xrh/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/routing/branch/master)                | [![Coverage Status](https://coveralls.io/repos/maidsafe/routing/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/routing?branch=master)                               | [![Stories in Ready](https://badge.waffle.io/maidsafe/routing.png?label=ready&title=Ready)](https://waffle.io/maidsafe/routing)                               |
| [rust_sodium](https://github.com/maidsafe/rust_sodium)                       | [![](http://meritbadge.herokuapp.com/rust_sodium)](https://crates.io/crates/rust_sodium)                       | [![Build Status](https://travis-ci.org/maidsafe/rust_sodium.svg?branch=master)](https://travis-ci.org/maidsafe/rust_sodium)                       |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/kkgtqnx263xgk0c3/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/rust-sodium/branch/master)            | [![Coverage Status](https://coveralls.io/repos/maidsafe/rust_sodium/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/rust_sodium?branch=master)                       | [![Stories in Ready](https://badge.waffle.io/maidsafe/rust_sodium.png?label=ready&title=Ready)](https://waffle.io/maidsafe/rust_sodium)                       |
| [safe_core](https://github.com/maidsafe/safe_core)                           | [![](http://meritbadge.herokuapp.com/safe_core)](https://crates.io/crates/safe_core)                           | [![Build Status](https://travis-ci.org/maidsafe/safe_core.svg?branch=master)](https://travis-ci.org/maidsafe/safe_core)                           |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/c61jthx04us5j57j/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-core/branch/master)              | [![Coverage Status](https://coveralls.io/repos/maidsafe/safe_core/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/safe_core?branch=master)                           | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_core.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_core)                           |
| [safe_launcher](https://github.com/maidsafe/safe_launcher)                   | [![](http://meritbadge.herokuapp.com/safe_launcher)](https://crates.io/crates/safe_launcher)                   | [![Build Status](https://travis-ci.org/maidsafe/safe_launcher.svg?branch=master)](https://travis-ci.org/maidsafe/safe_launcher)                   |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/xnsjhx27snoh4lmy/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-launcher/branch/master)          | [![Coverage Status](https://coveralls.io/repos/maidsafe/safe_launcher/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/safe_launcher?branch=master)                   | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_launcher.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_launcher)                   |
| [safe_vault](https://github.com/maidsafe/safe_vault)                         | [![](http://meritbadge.herokuapp.com/safe_vault)](https://crates.io/crates/safe_vault)                         | [![Build Status](https://travis-ci.org/maidsafe/safe_vault.svg?branch=master)](https://travis-ci.org/maidsafe/safe_vault)                         | [![Build Status](http://ci.maidsafe.net:8080/buildStatus/icon?job=safe_vault_arm_status_badge)](http://ci.maidsafe.net:8080/job/safe_vault_arm_status_badge/)           | [![Build status](https://ci.appveyor.com/api/projects/status/ohu678c6ufw8b2bn/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-vault/branch/master)             | [![Coverage Status](https://coveralls.io/repos/maidsafe/safe_vault/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/safe_vault?branch=master)                         | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_vault.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_vault)                         |
| [secure_serialisation](https://github.com/maidsafe/secure_serialisation)     | [![](http://meritbadge.herokuapp.com/secure_serialisation)](https://crates.io/crates/secure_serialisation)     | [![Build Status](https://travis-ci.org/maidsafe/secure_serialisation.svg?branch=master)](https://travis-ci.org/maidsafe/secure_serialisation)     |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/fw4t0s9dkipefjuy/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/secure-serialisation/branch/master)   | [![Coverage Status](https://coveralls.io/repos/maidsafe/secure_serialisation/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/secure_serialisation?branch=master)     | [![Stories in Ready](https://badge.waffle.io/maidsafe/secure_serialisation.png?label=ready&title=Ready)](https://waffle.io/maidsafe/secure_serialisation)     |
| [self_encryption](https://github.com/maidsafe/self_encryption)               | [![](http://meritbadge.herokuapp.com/self_encryption)](https://crates.io/crates/self_encryption)               | [![Build Status](https://travis-ci.org/maidsafe/self_encryption.svg?branch=master)](https://travis-ci.org/maidsafe/self_encryption)               |                                                                                                                                                                         | [![Build status](https://ci.appveyor.com/api/projects/status/htljxqrosx1i237s/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/self-encryption/branch/master)        | [![Coverage Status](https://coveralls.io/repos/maidsafe/self_encryption/badge.svg?branch=master&service=github)](https://coveralls.io/github/maidsafe/self_encryption?branch=master)               | [![Stories in Ready](https://badge.waffle.io/maidsafe/self_encryption.png?label=ready&title=Ready)](https://waffle.io/maidsafe/self_encryption)               |

|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| Repo                                                                     | Crate                                                                                                      | Linux/OS X                                                                                                                                    | Windows                                                                                                                                                                                | Issues                                                                                                                                                    |
|:------------------------------------------------------------------------:|:----------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------:|:--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------:|
| [accumulator](https://github.com/maidsafe/accumulator)                   | [![](http://meritbadge.herokuapp.com/accumulator)](https://crates.io/crates/accumulator)                   | [![Build Status](https://travis-ci.org/maidsafe/accumulator.svg?branch=master)](https://travis-ci.org/maidsafe/accumulator)                   | [![Build status](https://ci.appveyor.com/api/projects/status/1imtexgsshnpxnvn/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/accumulator/branch/master)          | [![Stories in Ready](https://badge.waffle.io/maidsafe/accumulator.png?label=ready&title=Ready)](https://waffle.io/maidsafe/accumulator)                   |
| [config_file_handler](https://github.com/maidsafe/config_file_handler)   | [![](http://meritbadge.herokuapp.com/config_file_handler)](https://crates.io/crates/config_file_handler)   | [![Build Status](https://travis-ci.org/maidsafe/config_file_handler.svg?branch=master)](https://travis-ci.org/maidsafe/config_file_handler)   | [![Build status](https://ci.appveyor.com/api/projects/status/22gb4w9fhvhv3hn4/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/config-file-handler/branch/master)  | [![Stories in Ready](https://badge.waffle.io/maidsafe/config_file_handler.png?label=ready&title=Ready)](https://waffle.io/maidsafe/config_file_handler)   |
| [crust](https://github.com/maidsafe/crust)                               | [![](http://meritbadge.herokuapp.com/crust)](https://crates.io/crates/crust)                               | [![Build Status](https://travis-ci.org/maidsafe/crust.svg?branch=master)](https://travis-ci.org/maidsafe/crust)                               | [![Build status](https://ci.appveyor.com/api/projects/status/ajw6ab26p86jdac4/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/crust/branch/master)                | [![Stories in Ready](https://badge.waffle.io/maidsafe/crust.png?label=ready&title=Ready)](https://waffle.io/maidsafe/crust)                               |
| [fake_clock](https://github.com/maidsafe/fake_clock)                     | [![](http://meritbadge.herokuapp.com/fake_clock)](https://crates.io/crates/fake_clock)                     | [![Build Status](https://travis-ci.org/maidsafe/fake_clock.svg?branch=master)](https://travis-ci.org/maidsafe/fake_clock)                     | [![Build status](https://ci.appveyor.com/api/projects/status/oq5s0j82ykvb52du/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/fake-clock/branch/master)           | [![Stories in Ready](https://badge.waffle.io/maidsafe/fake_clock.png?label=ready&title=Ready)](https://waffle.io/maidsafe/fake_clock)                     |
| [lru_time_cache](https://github.com/maidsafe/lru_time_cache)             | [![](http://meritbadge.herokuapp.com/lru_time_cache)](https://crates.io/crates/lru_time_cache)             | [![Build Status](https://travis-ci.org/maidsafe/lru_time_cache.svg?branch=master)](https://travis-ci.org/maidsafe/lru_time_cache)             | [![Build status](https://ci.appveyor.com/api/projects/status/15km1vxtg83qgvb5/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/lru-time-cache/branch/master)       | [![Stories in Ready](https://badge.waffle.io/maidsafe/lru_time_cache.png?label=ready&title=Ready)](https://waffle.io/maidsafe/lru_time_cache)             |
| [maidsafe_utilities](https://github.com/maidsafe/maidsafe_utilities)     | [![](http://meritbadge.herokuapp.com/maidsafe_utilities)](https://crates.io/crates/maidsafe_utilities)     | [![Build Status](https://travis-ci.org/maidsafe/maidsafe_utilities.svg?branch=master)](https://travis-ci.org/maidsafe/maidsafe_utilities)     | [![Build status](https://ci.appveyor.com/api/projects/status/f7x8p4y66lwua38t/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/maidsafe-utilities/branch/master)   | [![Stories in Ready](https://badge.waffle.io/maidsafe/maidsafe_utilities.png?label=ready&title=Ready)](https://waffle.io/maidsafe/maidsafe_utilities)     |
| [routing](https://github.com/maidsafe/routing)                           | [![](http://meritbadge.herokuapp.com/routing)](https://crates.io/crates/routing)                           | [![Build Status](https://travis-ci.org/maidsafe/routing.svg?branch=master)](https://travis-ci.org/maidsafe/routing)                           | [![Build status](https://ci.appveyor.com/api/projects/status/2w1joqd2h64o4xrh/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/routing/branch/master)              | [![Stories in Ready](https://badge.waffle.io/maidsafe/routing.png?label=ready&title=Ready)](https://waffle.io/maidsafe/routing)                           |
| [rust_sodium](https://github.com/maidsafe/rust_sodium)                   | [![](http://meritbadge.herokuapp.com/rust_sodium)](https://crates.io/crates/rust_sodium)                   | [![Build Status](https://travis-ci.org/maidsafe/rust_sodium.svg?branch=master)](https://travis-ci.org/maidsafe/rust_sodium)                   | [![Build status](https://ci.appveyor.com/api/projects/status/kkgtqnx263xgk0c3/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/rust-sodium/branch/master)          | [![Stories in Ready](https://badge.waffle.io/maidsafe/rust_sodium.png?label=ready&title=Ready)](https://waffle.io/maidsafe/rust_sodium)                   |
| [safe_client_libs](https://github.com/maidsafe/safe_client_libs)         | [![](http://meritbadge.herokuapp.com/safe_core)](https://crates.io/crates/safe_core)                       | [![Build Status](https://travis-ci.org/maidsafe/safe_client_libs.svg?branch=master)](https://travis-ci.org/maidsafe/safe_client_libs)         | [![Build status](https://ci.appveyor.com/api/projects/status/c61jthx04us5j57j/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-client-libs/branch/master)     | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_client_libs.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_client_libs)         |
| [safe_launcher](https://github.com/maidsafe/safe_launcher)               | [![](http://meritbadge.herokuapp.com/safe_launcher)](https://crates.io/crates/safe_launcher)               | [![Build Status](https://travis-ci.org/maidsafe/safe_launcher.svg?branch=master)](https://travis-ci.org/maidsafe/safe_launcher)               | [![Build status](https://ci.appveyor.com/api/projects/status/xnsjhx27snoh4lmy/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-launcher/branch/master)        | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_launcher.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_launcher)               |
| [safe_vault](https://github.com/maidsafe/safe_vault)                     | [![](http://meritbadge.herokuapp.com/safe_vault)](https://crates.io/crates/safe_vault)                     | [![Build Status](https://travis-ci.org/maidsafe/safe_vault.svg?branch=master)](https://travis-ci.org/maidsafe/safe_vault)                     | [![Build status](https://ci.appveyor.com/api/projects/status/ohu678c6ufw8b2bn/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/safe-vault/branch/master)           | [![Stories in Ready](https://badge.waffle.io/maidsafe/safe_vault.png?label=ready&title=Ready)](https://waffle.io/maidsafe/safe_vault)                     |
| [secure_serialisation](https://github.com/maidsafe/secure_serialisation) | [![](http://meritbadge.herokuapp.com/secure_serialisation)](https://crates.io/crates/secure_serialisation) | [![Build Status](https://travis-ci.org/maidsafe/secure_serialisation.svg?branch=master)](https://travis-ci.org/maidsafe/secure_serialisation) | [![Build status](https://ci.appveyor.com/api/projects/status/fw4t0s9dkipefjuy/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/secure-serialisation/branch/master) | [![Stories in Ready](https://badge.waffle.io/maidsafe/secure_serialisation.png?label=ready&title=Ready)](https://waffle.io/maidsafe/secure_serialisation) |
| [self_encryption](https://github.com/maidsafe/self_encryption)           | [![](http://meritbadge.herokuapp.com/self_encryption)](https://crates.io/crates/self_encryption)           | [![Build Status](https://travis-ci.org/maidsafe/self_encryption.svg?branch=master)](https://travis-ci.org/maidsafe/self_encryption)           | [![Build status](https://ci.appveyor.com/api/projects/status/htljxqrosx1i237s/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/self-encryption/branch/master)      | [![Stories in Ready](https://badge.waffle.io/maidsafe/self_encryption.png?label=ready&title=Ready)](https://waffle.io/maidsafe/self_encryption)           |
| [system_uri](https://github.com/maidsafe/system_uri)                     | [![](http://meritbadge.herokuapp.com/system_uri)](https://crates.io/crates/system_uri)                     | [![Build Status](https://travis-ci.org/maidsafe/system_uri.svg?branch=master)](https://travis-ci.org/maidsafe/system_uri)                     | [![Build status](https://ci.appveyor.com/api/projects/status/qpnwete63eakcipn/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/system-uri/branch/master)           | [![Stories in Ready](https://badge.waffle.io/maidsafe/system_uri.png?label=ready&title=Ready)](https://waffle.io/maidsafe/system_uri)                     |

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Simulation/.git/index from [ea466e68f9] to [822819be32].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Whitepapers/.git/index from [3d4ef0a994] to [51ffc227b3].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Whitepapers/technical_papers/img/safecoin farming speed.png version [590e37927e].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Whitepapers/technical_papers/img/safecoin resources.png version [ab4b3bd4f0].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Whitepapers/technical_papers/img/safecoin transfer mech.png version [0940833af9].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/Whitepapers/technical_papers/safecoin citations.bib version [c35882d830].



































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
%% This BibTeX bibliography file was created using BibDesk.
%% http://bibdesk.sourceforge.net/


%% Created for Nick Lambert at 2015-01-07 10:11:39 +0000 


%% Saved with string encoding Unicode (UTF-8) 



@jurthesis{19,
	Date-Added = {2015-01-07 10:07:00 +0000},
	Date-Modified = {2015-01-07 10:11:29 +0000},
	Lastchecked = {7},
	Month = {January},
	Title = {Kademlia wikipedia page},
	Url = {http://en.wikipedia.org/wiki/Kademlia},
	Year = {2015}}

@webpage{18,
	Author = {John Aziz},
	Date-Added = {2014-12-11 16:38:39 +0000},
	Date-Modified = {2014-12-11 16:40:04 +0000},
	Lastchecked = {11},
	Month = {December},
	Title = {Does the Federal Reserve really control the money supply?},
	Url = {http://theweek.com/article/index/244899/does-the-federal-reserve-really-control-the-money-supply},
	Year = {2014},
	Bdsk-Url-1 = {http://theweek.com/article/index/244899/does-the-federal-reserve-really-control-the-money-supply}}

@webpage{17,
	Author = {Paul Krugman},
	Date-Added = {2014-12-11 15:08:47 +0000},
	Date-Modified = {2014-12-11 15:10:58 +0000},
	Lastchecked = {11},
	Month = {December},
	Title = {The textbook economics of cap-and-trade},
	Url = {http://krugman.blogs.nytimes.com/2009/09/27/the-textbook-economics-of-cap-and-trade/?_r=0},
	Year = {2014},
	Bdsk-Url-1 = {http://krugman.blogs.nytimes.com/2009/09/27/the-textbook-economics-of-cap-and-trade/?_r=0}}

@webpage{16,
	Author = {The Atlantic},
	Date-Added = {2014-11-28 11:03:07 +0000},
	Date-Modified = {2014-11-28 11:03:45 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {The Internet's Original Sin},
	Url = {http://www.theatlantic.com/technology/archive/2014/08/advertising-is-the-internets-original-sin/376041/},
	Year = {2014},
	Bdsk-Url-1 = {http://www.theatlantic.com/technology/archive/2014/08/advertising-is-the-internets-original-sin/376041/}}

@webpage{15,
	Author = {Facebook Inc},
	Date-Added = {2014-11-28 11:00:05 +0000},
	Date-Modified = {2014-11-28 11:00:53 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Facebook Reports Fourth Quarter and Full Year 2013 Results},
	Url = {http://investor.fb.com/releasedetail.cfm?ReleaseID=821954},
	Year = {2014},
	Bdsk-Url-1 = {http://investor.fb.com/releasedetail.cfm?ReleaseID=821954}}

@jurthesis{14,
	Author = {Google Inc},
	Date-Added = {2014-11-28 10:58:41 +0000},
	Date-Modified = {2014-12-11 16:48:12 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {2013 Financial Tables},
	Url = {https://investor.google.com/financial/2013/tables.html},
	Year = {2014},
	Bdsk-Url-1 = {https://investor.google.com/financial/2013/tables.html}}

@webpage{13,
	Author = {Joe McCann},
	Date-Added = {2014-11-28 10:55:50 +0000},
	Date-Modified = {2014-11-28 11:01:03 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Data Is The Most Valuable Commodity On Earth},
	Url = {http://subprint.com/blog/data-is-the-most-valuable-commodity-on-earth},
	Year = {2014},
	Bdsk-Url-1 = {http://subprint.com/blog/data-is-the-most-valuable-commodity-on-earth}}

@webpage{12,
	Author = {World Economic Forum},
	Date-Added = {2014-11-28 10:51:45 +0000},
	Date-Modified = {2014-11-28 10:52:51 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Personal Data: The Emergence of a New Asset Class},
	Url = {http://www3.weforum.org/docs/WEF_ITTC_PersonalDataNewAsset_Report_2011.pdf},
	Year = {2014},
	Bdsk-Url-1 = {http://www3.weforum.org/docs/WEF_ITTC_PersonalDataNewAsset_Report_2011.pdf}}

@webpage{11,
	Author = {BBC News Web Page},
	Date-Added = {2014-11-28 10:36:05 +0000},
	Date-Modified = {2014-11-28 10:36:58 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Gold v paper money},
	Url = {http://www.bbc.co.uk/news/business-18644230},
	Year = {2014},
	Bdsk-Url-1 = {http://www.bbc.co.uk/news/business-18644230}}

@webpage{10,
	Date-Added = {2014-11-28 10:34:17 +0000},
	Date-Modified = {2014-11-28 10:35:07 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {ECR Research Web Page},
	Url = {http://www.ecrresearch.com/world-economy/dangers-and-drawbacks-quantitative-easing},
	Year = {2014},
	Bdsk-Url-1 = {http://www.ecrresearch.com/world-economy/dangers-and-drawbacks-quantitative-easing}}

@webpage{9,
	Date-Added = {2014-11-28 10:31:55 +0000},
	Date-Modified = {2014-11-28 10:32:47 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Federal Reserve Web Site},
	Url = {http://www.federalreserve.gov/faqs/currency_12773.htm},
	Year = {2014},
	Bdsk-Url-1 = {http://www.federalreserve.gov/faqs/currency_12773.htm}}

@webpage{8,
	Date-Added = {2014-11-28 10:29:03 +0000},
	Date-Modified = {2014-11-28 11:01:10 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Bountify Web Page},
	Url = {https://bountify.co/},
	Year = {2014},
	Bdsk-Url-1 = {https://bountify.co/}}

@webpage{7,
	Date-Added = {2014-11-28 10:27:49 +0000},
	Date-Modified = {2014-11-28 10:28:30 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Bounty Source Web Page},
	Url = {https://www.bountysource.com/},
	Year = {2014},
	Bdsk-Url-1 = {https://www.bountysource.com/}}

@webpage{6,
	Date-Added = {2014-11-28 10:25:36 +0000},
	Date-Modified = {2014-11-28 11:01:22 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {MaidSafe Wikipedia},
	Url = {http://en.wikipedia.org/wiki/MaidSafe},
	Year = {2014},
	Bdsk-Url-1 = {http://en.wikipedia.org/wiki/MaidSafe}}

@webpage{5,
	Date-Added = {2014-11-28 10:23:00 +0000},
	Date-Modified = {2014-11-28 10:24:14 +0000},
	Lastchecked = {28},
	Month = {November},
	Title = {Tor Incentives Roundup},
	Url = {https://blog.torproject.org/blog/tor-incentives-research-roundup-goldstar-par-braids-lira-tears-and-torcoin},
	Year = {2014},
	Bdsk-Url-1 = {https://blog.torproject.org/blog/tor-incentives-research-roundup-goldstar-par-braids-lira-tears-and-torcoin}}

@webpage{4,
	Date-Added = {2014-11-27 16:52:58 +0000},
	Date-Modified = {2014-11-28 11:01:57 +0000},
	Lastchecked = {27},
	Month = {November},
	Title = {Tor Metrics --- Direct users by country},
	Url = {https://metrics.torproject.org/userstats-relay-country.html},
	Year = {2014},
	Bdsk-Url-1 = {https://metrics.torproject.org/userstats-relay-country.html}}

@webpage{3,
	Date-Added = {2014-11-27 16:49:37 +0000},
	Date-Modified = {2014-11-27 16:51:52 +0000},
	Lastchecked = {27},
	Month = {November},
	Title = {Tor Metrics --- Relays and bridges in the network},
	Url = {https://metrics.torproject.org/networksize.html},
	Year = {2014},
	Bdsk-Url-1 = {https://metrics.torproject.org/networksize.html}}

@url{2,
	Author = {Christopher Doll, T. F. McLaughlin, Anjali Barretto},
	Date-Added = {2014-11-27 16:29:54 +0000},
	Date-Modified = {2015-01-06 10:07:32 +0000},
	Journal = {The International Journal of Basic and Applied Science},
	Month = {July},
	Number = {01},
	Pages = {131-149},
	Title = {The Token Economy: A Recent Review and Evaluation},
	Url = {http://www.insikapub.com/Vol-02/No-01/12IJBAS(2)(1).pdf},
	Volume = {02},
	Year = {2013},
	Bdsk-Url-1 = {http://www.insikapub.com/Vol-02/No-01/12IJBAS(2)(1).pdf}}

@webpage{1,
	Date-Modified = {2014-11-27 16:36:09 +0000},
	Owner = {nicklambert},
	Timestamp = {2014.11.27},
	Title = {Crypto-Currency Market Capitalizations},
	Url = {https://coinmarketcap.com/all/},
	Bdsk-Url-1 = {https://coinmarketcap.com/all/}}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/FETCH_HEAD from [85ab917d1b] to [3f4372cd9d].

1
2
005b4c3b9156bbc0616ac41a65787edd7d577573		branch 'master' of https://github.com/maidsafe/accumulator
e7f3922a412f496080b73ef818d4f8fed4c77708	not-for-merge	branch 'gh-pages' of https://github.com/maidsafe/accumulator
|

1
2
4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6		branch 'master' of https://github.com/maidsafe/accumulator
e7f3922a412f496080b73ef818d4f8fed4c77708	not-for-merge	branch 'gh-pages' of https://github.com/maidsafe/accumulator

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/index from [921d90ee2e] to [ab2877ab27].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/logs/HEAD from [2cae1d6eea] to [f9939e4b39].

1
2

0000000000000000000000000000000000000000 11daee9a345b49015e07576bd83c5474cdf0f2b7 Martin Vahi <martin.vahi@softf1.com> 1490069799 +0200	clone: from https://github.com/maidsafe/accumulator.git
11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 Martin Vahi <martin.vahi@softf1.com> 1490143840 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 11daee9a345b49015e07576bd83c5474cdf0f2b7 Martin Vahi <martin.vahi@softf1.com> 1490069799 +0200	clone: from https://github.com/maidsafe/accumulator.git
11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 Martin Vahi <martin.vahi@softf1.com> 1490143840 +0200	pull --recurse-submodules: Fast-forward
005b4c3b9156bbc0616ac41a65787edd7d577573 4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6 Martin Vahi <martin.vahi@softf1.com> 1494899449 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/logs/refs/heads/master from [2cae1d6eea] to [f9939e4b39].

1
2

0000000000000000000000000000000000000000 11daee9a345b49015e07576bd83c5474cdf0f2b7 Martin Vahi <martin.vahi@softf1.com> 1490069799 +0200	clone: from https://github.com/maidsafe/accumulator.git
11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 Martin Vahi <martin.vahi@softf1.com> 1490143840 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 11daee9a345b49015e07576bd83c5474cdf0f2b7 Martin Vahi <martin.vahi@softf1.com> 1490069799 +0200	clone: from https://github.com/maidsafe/accumulator.git
11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 Martin Vahi <martin.vahi@softf1.com> 1490143840 +0200	pull --recurse-submodules: Fast-forward
005b4c3b9156bbc0616ac41a65787edd7d577573 4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6 Martin Vahi <martin.vahi@softf1.com> 1494899449 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/logs/refs/remotes/origin/master from [15c3fa6c6b] to [63094421fc].

1

11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 ts2 <ts2@linux-0fiz.(none)> 1490143736 +0200	pull --recurse-submodules: fast-forward


>
1
2
11daee9a345b49015e07576bd83c5474cdf0f2b7 005b4c3b9156bbc0616ac41a65787edd7d577573 ts2 <ts2@linux-0fiz.(none)> 1490143736 +0200	pull --recurse-submodules: fast-forward
005b4c3b9156bbc0616ac41a65787edd7d577573 4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6 ts2 <ts2@linux-0fiz.(none)> 1494899449 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/20/4ccb322f3e69855c530bf09b5ebabad74e3975 version [c723a23f84].



>
1
x[J1E*_L"".=Tj0tIf{ph]:4`0,2֤"{acT-ڰK/%J!L@rXY>_Z''^=ȩ+ȩ|㲶lY=K$/T_a@$@mw>چ^

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/2b/d1de578214383c39bb91cceafc9f018cd2830c version [a243f2bb70].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/41/17033068e8f0100dc3e3ce1ce20e30f9fb04ad version [cc22fb6bd6].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/4a/9da2a2dcfbbf8c1a025e74a3decc6be4517cc6 version [ec7b43e370].





>
>
1
2
x]MN0YOb5bUpg:΢'曙0c }lg[ h5"蔰)z',Xh)FI%^*Ӆ)\Fe82<b+&bOh[ΛV
?îOTV6ͅ.g;JUMطoy-+Aw[+LQ|yYgS|dXw2	/F64`

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/52/b6c98a5edd8af4f3d023b3476ccaff79dbb048 version [f15b79b175].



>
1
xuN0+Q"uP7wñqCɔ7-K*`PPqʰ3X= .D/Q@1n,k<94jutK!H/oc&kd[E!a N|ܶ ׈+\nS=Jm=_L3oh7*땶TSvHT>*iݲ|MVZ)*y,UAÔV¯;u+=bȍ!i#h/}q)

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/7a/cb7e766ab3ad0a5921ced7d202275ba5cad571 version [484962ac52].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/86/813a3e73ca8387fe94ebd795a9428fdbb50be5 version [b2e4fce9aa].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/9c/b1c0e3fbd8cd0197c9b9c7009a618c4dc4a875 version [6c3de0ff97].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/objects/b6/1a9d02c42dbc1218847d5ed06c5a65f8bdd2cc version [9f7afe3038].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/refs/heads/master from [a696adc035] to [2a19634715].

1
005b4c3b9156bbc0616ac41a65787edd7d577573
|
1
4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.git/refs/remotes/origin/master from [a696adc035] to [2a19634715].

1
005b4c3b9156bbc0616ac41a65787edd7d577573
|
1
4a9da2a2dcfbbf8c1a025e74a3decc6be4517cc6

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/.travis.yml from [719aa1a92e] to [0907d43e2c].

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22



23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    - RUST_BACKTRACE=1
    - PATH=$PATH:$HOME/.cargo/bin
os:
  - linux
  - osx
language: rust
rust:
  - stable
  - nightly-2016-12-19
sudo: false
branches:
  only:
    - master
cache:
  cargo: true
before_script:
  - (which cargo-install-update && cargo install-update cargo-update) || cargo install cargo-update
  - (which cargo-prune && cargo install-update cargo-prune) || cargo install cargo-prune
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
      (which rustfmt && cargo install-update rustfmt) || cargo install rustfmt;



    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      clippy_vers=0.0.104;
      if ! cargo clippy --version | grep -q $clippy_vers; then
        cargo install clippy --vers=$clippy_vers --force;
      fi
    fi
script:
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
      (
        set -x;
        cargo fmt -- --write-mode=diff &&
        cargo test --release --verbose
      );
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      (
        set -x;
        cargo clippy && cargo clippy --profile test
      );
    fi
before_cache:
 - cargo prune







|
|









|
|
>
>
>

|





|













3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
    - RUST_BACKTRACE=1
    - PATH=$PATH:$HOME/.cargo/bin
os:
  - linux
  - osx
language: rust
rust:
  - 1.17.0
  - nightly-2017-04-28
sudo: false
branches:
  only:
    - master
cache:
  cargo: true
before_script:
  - (which cargo-install-update && cargo install-update cargo-update) || cargo install cargo-update
  - (which cargo-prune && cargo install-update cargo-prune) || cargo install cargo-prune
  - if [ "${TRAVIS_RUST_VERSION}" = 1.17.0 ]; then
      rustfmt_vers=0.8.3;
      if ! rustfmt --version | grep -q $rustfmt_vers; then
        cargo install rustfmt --vers=$rustfmt_vers --force;
      fi
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      clippy_vers=0.0.128;
      if ! cargo clippy --version | grep -q $clippy_vers; then
        cargo install clippy --vers=$clippy_vers --force;
      fi
    fi
script:
  - if [ "${TRAVIS_RUST_VERSION}" = 1.17.0 ]; then
      (
        set -x;
        cargo fmt -- --write-mode=diff &&
        cargo test --release --verbose
      );
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      (
        set -x;
        cargo clippy && cargo clippy --profile test
      );
    fi
before_cache:
 - cargo prune

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/accumulator/src/lib.rs from [83cce218e4] to [da4ec5c465].

176
177
178
179
180
181
182


183
184
185
186
187
188
189


190
191
192
193
194
195
196
197
...
232
233
234
235
236
237
238
239

240
241
242
243
244
245
246
...
251
252
253
254
255
256
257
258

259
260
261
262
263
264
265
...
277
278
279
280
281
282
283


284
285
286
287
288
289
290
291
...
292
293
294
295
296
297
298


299
300
301
302
303
304
305
306
    fn add_single_value_quorum() {
        let quorum_size = 19;
        let mut accumulator = Accumulator::with_capacity(quorum_size, 100);
        let key = random::<i32>();
        for i in 0..quorum_size - 1 {
            let value = random::<u32>();
            assert!(accumulator.add(key, value).is_none());


            let retrieved_value = accumulator.get(&key).expect("entry `key` does not exist");
            assert_eq!(retrieved_value.len(), i + 1);
            // for response in value { assert_eq!(response, value); };
            assert_eq!(accumulator.is_quorum_reached(&key), false);
        }
        assert!(accumulator.add(key, random()).is_some());
        assert_eq!(accumulator.is_quorum_reached(&key), true);


        let retrieved_value = accumulator.get(&key).expect("entry `key` does not exist");
        assert_eq!(retrieved_value.len(), quorum_size);
        // for response in value { assert_eq!(response, value); };
    }

    #[test]
    fn add_multiple_values_quorum() {
        let quorum_size = 19;
................................................................................
    fn delete() {
        let mut accumulator = Accumulator::with_capacity(2, 100);

        assert!(accumulator.add(1, 1).is_none());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), false);

        let mut responses: Vec<_> = accumulator.get(&1)

            .expect("entry 1 does not exist")
            .iter()
            .cloned()
            .collect();

        assert_eq!(responses, vec![1]);

................................................................................
        assert!(accumulator.add(1, 1).is_none());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), false);
        assert!(accumulator.add(1, 2).is_some());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), true);

        responses = accumulator.get(&1)

            .expect("entry 1 does not exist")
            .iter()
            .cloned()
            .collect();

        assert_eq!(responses.len(), 2);
        assert!(responses.contains(&1));
................................................................................
        for count in 0..1000 {
            assert!(accumulator.add(count, 1).is_some());
            assert_eq!(accumulator.contains_key(&count), true);
            assert_eq!(accumulator.is_quorum_reached(&count), true);
        }

        for count in 0..1000 {


            let responses = accumulator.get(&count).expect("entry `count` does not exist");
            assert_eq!(responses.len(), 1);
            assert!(responses.contains(&1));
        }
    }

    #[test]
    fn cache_removals() {
................................................................................
        let mut accumulator = Accumulator::with_capacity(2, 1000);

        for count in 0..1000 {
            assert!(accumulator.add(count, 1).is_none());
            assert_eq!(accumulator.contains_key(&count), true);
            assert_eq!(accumulator.is_quorum_reached(&count), false);



            let responses = accumulator.get(&count).expect("entry `count` does not exist");

            assert_eq!(responses.len(), 1);
            assert!(responses.contains(&1));
        }

        assert!(accumulator.add(1000, 1).is_none());
        assert_eq!(accumulator.contains_key(&1000), true);







>
>
|






>
>
|







 







|
>







 







|
>







 







>
>
|







 







>
>
|







176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
...
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
...
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
...
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
    fn add_single_value_quorum() {
        let quorum_size = 19;
        let mut accumulator = Accumulator::with_capacity(quorum_size, 100);
        let key = random::<i32>();
        for i in 0..quorum_size - 1 {
            let value = random::<u32>();
            assert!(accumulator.add(key, value).is_none());
            let retrieved_value = accumulator
                .get(&key)
                .expect("entry `key` does not exist");
            assert_eq!(retrieved_value.len(), i + 1);
            // for response in value { assert_eq!(response, value); };
            assert_eq!(accumulator.is_quorum_reached(&key), false);
        }
        assert!(accumulator.add(key, random()).is_some());
        assert_eq!(accumulator.is_quorum_reached(&key), true);
        let retrieved_value = accumulator
            .get(&key)
            .expect("entry `key` does not exist");
        assert_eq!(retrieved_value.len(), quorum_size);
        // for response in value { assert_eq!(response, value); };
    }

    #[test]
    fn add_multiple_values_quorum() {
        let quorum_size = 19;
................................................................................
    fn delete() {
        let mut accumulator = Accumulator::with_capacity(2, 100);

        assert!(accumulator.add(1, 1).is_none());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), false);

        let mut responses: Vec<_> = accumulator
            .get(&1)
            .expect("entry 1 does not exist")
            .iter()
            .cloned()
            .collect();

        assert_eq!(responses, vec![1]);

................................................................................
        assert!(accumulator.add(1, 1).is_none());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), false);
        assert!(accumulator.add(1, 2).is_some());
        assert_eq!(accumulator.contains_key(&1), true);
        assert_eq!(accumulator.is_quorum_reached(&1), true);

        responses = accumulator
            .get(&1)
            .expect("entry 1 does not exist")
            .iter()
            .cloned()
            .collect();

        assert_eq!(responses.len(), 2);
        assert!(responses.contains(&1));
................................................................................
        for count in 0..1000 {
            assert!(accumulator.add(count, 1).is_some());
            assert_eq!(accumulator.contains_key(&count), true);
            assert_eq!(accumulator.is_quorum_reached(&count), true);
        }

        for count in 0..1000 {
            let responses = accumulator
                .get(&count)
                .expect("entry `count` does not exist");
            assert_eq!(responses.len(), 1);
            assert!(responses.contains(&1));
        }
    }

    #[test]
    fn cache_removals() {
................................................................................
        let mut accumulator = Accumulator::with_capacity(2, 1000);

        for count in 0..1000 {
            assert!(accumulator.add(count, 1).is_none());
            assert_eq!(accumulator.contains_key(&count), true);
            assert_eq!(accumulator.is_quorum_reached(&count), false);

            let responses = accumulator
                .get(&count)
                .expect("entry `count` does not exist");

            assert_eq!(responses.len(), 1);
            assert!(responses.contains(&1));
        }

        assert!(accumulator.add(1000, 1).is_none());
        assert_eq!(accumulator.contains_key(&1000), true);

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.babelrc version [d3b08bfa2d].









>
>
>
>
1
2
3
4
{
  "presets": ["es2015", "stage-0"],
  "plugins": ["add-module-exports"]
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.eslintrc from [cfc8f6f01b] to [39f2f4d4d9].

1
2
3

4
5
6

7
8

9
10
11
12
13
14
{
  "env": {
    "es6": true

  },
  "rules": {
    "arrow-parens": [2, "always"],

    "consistent-return": 0,
    "comma-dangle": 0,

    "no-use-before-define": 0,
    "generator-star-spacing": 0,
    "no-console": ["error", { allow: ["warn", "error"] }],
    "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }]
  }
}

|
|
>



>


>






1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
  "extends": "airbnb",
  "parserOptions": {
    "sourceType": "module"
  },
  "rules": {
    "arrow-parens": [2, "always"],
    "arrow-body-style": [0, "always"],
    "consistent-return": 0,
    "comma-dangle": 0,
    "no-param-reassign": 0,
    "no-use-before-define": 0,
    "generator-star-spacing": 0,
    "no-console": ["error", { allow: ["warn", "error"] }],
    "no-plusplus": ["error", { "allowForLoopAfterthoughts": true }]
  }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/FETCH_HEAD from [a071ebed73] to [3b2f9fdce9].

1
2
600db293e378a9fd2d66166466e49a237d7b5176		branch 'master' of https://github.com/maidsafe/beaker-plugin-safe-app
ba5657ea36970c0985b297b371c172e78185e25c	not-for-merge	branch 'dev' of https://github.com/maidsafe/beaker-plugin-safe-app
|
<
1

c3208af2f553dcd0866b50aed770ee670657e0b3		branch 'master' of https://github.com/maidsafe/beaker-plugin-safe-app

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/index from [f714a2de98] to [682164df13].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/logs/HEAD from [0fb71b5274] to [d11d537b45].

1

0000000000000000000000000000000000000000 600db293e378a9fd2d66166466e49a237d7b5176 Martin Vahi <martin.vahi@softf1.com> 1490069749 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-app.git


>
1
2
0000000000000000000000000000000000000000 600db293e378a9fd2d66166466e49a237d7b5176 Martin Vahi <martin.vahi@softf1.com> 1490069749 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-app.git
600db293e378a9fd2d66166466e49a237d7b5176 c3208af2f553dcd0866b50aed770ee670657e0b3 Martin Vahi <martin.vahi@softf1.com> 1494899407 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/logs/refs/heads/master from [0fb71b5274] to [d11d537b45].

1

0000000000000000000000000000000000000000 600db293e378a9fd2d66166466e49a237d7b5176 Martin Vahi <martin.vahi@softf1.com> 1490069749 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-app.git


>
1
2
0000000000000000000000000000000000000000 600db293e378a9fd2d66166466e49a237d7b5176 Martin Vahi <martin.vahi@softf1.com> 1490069749 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-app.git
600db293e378a9fd2d66166466e49a237d7b5176 c3208af2f553dcd0866b50aed770ee670657e0b3 Martin Vahi <martin.vahi@softf1.com> 1494899407 +0300	pull --all --recurse-submodules --force: Fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/logs/refs/remotes/origin/master version [71d026d4ff].



>
1
600db293e378a9fd2d66166466e49a237d7b5176 c3208af2f553dcd0866b50aed770ee670657e0b3 ts2 <ts2@linux-0fiz.(none)> 1494899407 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/objects/pack/pack-01eb5c144d224659d2c5343db1a2f9bc0b9c96ca.idx version [d87b2f7706].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/objects/pack/pack-01eb5c144d224659d2c5343db1a2f9bc0b9c96ca.pack version [424c6583d0].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/refs/heads/master from [17c8da2403] to [223056fdd8].

1
600db293e378a9fd2d66166466e49a237d7b5176
|
1
c3208af2f553dcd0866b50aed770ee670657e0b3

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.git/refs/remotes/origin/master version [223056fdd8].



>
1
c3208af2f553dcd0866b50aed770ee670657e0b3

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/.gitignore from [a254f0381c] to [7343b5e618].

33
34
35
36
37
38
39

# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

.idea








>
33
34
35
36
37
38
39
40
# Optional npm cache directory
.npm

# Optional REPL history
.node_repl_history

.idea
dist

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/README.md from [4474c7c4e2] to [b14d388460].

4
5
6
7
8
9
10













11
12
13
14
15
16
17

SAFE App API plugin for SAFE Browser.

|Linux/OS X|Windows|
|:---:|:--------:|
|[![Build Status](https://travis-ci.org/maidsafe/beaker-plugin-safe-app.svg?branch=master)](https://travis-ci.org/maidsafe/beaker-plugin-safe-app)|[![Build status](https://ci.appveyor.com/api/projects/status/684fxjpg88vu87hf/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/beaker-plugin-safe-app/branch/master)|















# License

Licensed under either of

* the MaidSafe.net Commercial License, version 1.0 or later ([LICENSE](LICENSE))
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)







>
>
>
>
>
>
>
>
>
>
>
>
>







4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

SAFE App API plugin for SAFE Browser.

|Linux/OS X|Windows|
|:---:|:--------:|
|[![Build Status](https://travis-ci.org/maidsafe/beaker-plugin-safe-app.svg?branch=master)](https://travis-ci.org/maidsafe/beaker-plugin-safe-app)|[![Build status](https://ci.appveyor.com/api/projects/status/684fxjpg88vu87hf/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/beaker-plugin-safe-app/branch/master)|

## Dependency

Project depends on [safe_app_nodejs](https://github.com/maidsafe/safe_app_nodejs). The dependency is specified as a git submodule.

## Development

Rust and Nodejs are required for development.

1. Clone the project
2. Run `npm i` to install the nodejs dependency
3. `npm run build` will build the project to the `dist` folder.

In [safe_browser](https://github.com/maidsafe/safe_browser/) `app/node_modules`, create a folder `beaker-plugin-safe-app` and add `index.js` file and the `dist` folder obtained after building the plugin.

# License

Licensed under either of

* the MaidSafe.net Commercial License, version 1.0 or later ([LICENSE](LICENSE))
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/index.js from [1815f97d6c] to [345894618c].

1

2
3
4
5
6
7
8
9
10
11
12
const safeProtocol = require('./src/protocol');


module.exports = {
  configure() {
  },
  homePages: [{
    label: 'SAFE Network',
    href: 'https://safenetforum.org/t/safe-network-alpha-release/10687/1'
  }],
  protocols: [safeProtocol],
  webAPIs: {}
};
|
>





|



|

1
2
3
4
5
6
7
8
9
10
11
12
13
const safeProtocol = require('./dist/protocol');
const api = require('./dist/api');

module.exports = {
  configure() {
  },
  homePages: [{
    label: 'SAFE App',
    href: 'https://safenetforum.org/t/safe-network-alpha-release/10687/1'
  }],
  protocols: [safeProtocol],
  webAPIs: api
};

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/package.json from [77aa9fa3d8] to [c78d8fbcd2].

1
2
3
4
5
6
7
8



9
10
11
12
13
14
15
..
32
33
34
35
36
37
38








39





40
41
{
  "name": "beaker-plugin-safe-app",
  "version": "0.1.0",
  "description": "SAFE Browser add-on for web clientr to access SAFE Network",
  "main": "index.js",
  "scripts": {
    "lint": "eslint src *.js",
    "test": "npm run lint"



  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/maidsafe/beaker-plugin-safe-app.git"
  },
  "keywords": [
    "maidsafe",
................................................................................
  "homepage": "https://github.com/maidsafe/beaker-plugin-safe-app#readme",
  "dependencies": {
    "mime": "^1.3.4",
    "safe-app": "git+https://github.com/maidsafe/safe_app_nodejs.git",
    "url": "^0.11.0"
  },
  "devDependencies": {








    "eslint": "^3.15.0"





  }
}



|



|
>
>
>







 







>
>
>
>
>
>
>
>
|
>
>
>
>
>


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
..
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
{
  "name": "beaker-plugin-safe-app",
  "version": "0.1.0",
  "description": "SAFE Browser add-on for web client to access SAFE Network",
  "main": "index.js",
  "scripts": {
    "lint": "eslint src *.js",
    "test": "npm run lint",
    "build-api": "cross-env NODE_ENV=production node -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.api.js --progress --profile --colors",
    "build-protocol": "cross-env NODE_ENV=production node -r babel-register ./node_modules/webpack/bin/webpack --config webpack.config.protocol.js --progress --profile --colors",
    "build": "concurrently \"npm run build-protocol\" \"npm run build-api\""
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/maidsafe/beaker-plugin-safe-app.git"
  },
  "keywords": [
    "maidsafe",
................................................................................
  "homepage": "https://github.com/maidsafe/beaker-plugin-safe-app#readme",
  "dependencies": {
    "mime": "^1.3.4",
    "safe-app": "git+https://github.com/maidsafe/safe_app_nodejs.git",
    "url": "^0.11.0"
  },
  "devDependencies": {
    "babel-loader": "^6.4.0",
    "babel-plugin-add-module-exports": "^0.2.1",
    "babel-preset-es2015": "^6.24.0",
    "babel-preset-stage-0": "^6.22.0",
    "babel-register": "^6.24.0",
    "concurrently": "^3.4.0",
    "copy-webpack-plugin": "^4.0.1",
    "cross-env": "^3.2.4",
    "eslint": "^3.17.1",
    "eslint-config-airbnb": "^14.1.0",
    "eslint-plugin-import": "^2.2.0",
    "eslint-plugin-jsx-a11y": "^4.0.0",
    "eslint-plugin-react": "^6.10.0",
    "webpack": "^2.2.1"
  }
}

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/app.js version [90cdc5db04].

























































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
const safeApp = require('safe-app');
const ipc = require('./ipc');
const { genHandle, getObj, freeObj } = require('./helpers');

module.exports.manifest = {
  initialise: 'promise',
  connect: 'promise',
  authorise: 'promise',
  connectAuthorised: 'promise',
  webFetch: 'promise',
  isRegistered: 'promise',
  canAccessContainer: 'promise',
  getContainer: 'promise',
  getPubSignKey: 'promise',
  getEncKey: 'promise',
  getSignKeyFromRaw: 'promise',
  getEncKeyKeyFromRaw: 'promise',
  refreshContainerAccess: 'promise',
  getHomeContainer: 'promise',
};

/**
 * Create a new SAFEApp instance without a connection to the network
 * @returns {Promise<SAFEAppToken>} new instace
 */
module.exports.initialise = (appInfo) => {
  if (this && this.sender) {
    const wholeUrl = this.sender.getURL();
    appInfo.scope = wholeUrl;
  } else {
    appInfo.scope = null;
  }

  return safeApp.initializeApp(appInfo)
    .then(genHandle);
};

/**
 * Create a new, unregistered Session (read-only)
 * @returns {Promise<SAFEAppToken>} same instace
 */
module.exports.connect = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.connectUnregistered())
    .then(() => appToken);
};

/**
 * With the options object it can be opt for getting a container
 * for the app itself: opts.own_container=true
 * @returns {Promise<AuthURI>} auth granted URI
 */
module.exports.authorise = (appToken, permissions, options) => {
  return new Promise((resolve, reject) => {
    getObj(appToken)
      .then((app) => app.auth.genAuthUri(permissions, options)
        .then((authReq) => ipc.sendAuthReq(authReq, (err, res) => {
          if (err) {
            return reject(new Error('Unable to authorise the application: ', err)); // TODO send Error in specific
          }
          return resolve(res);
        })))
      .catch(reject);
  });
};

/**
 * Create a new, registered Session (read-write)
 * @returns {Promise<SAFEAppToken>} same instace
 */
module.exports.connectAuthorised = (appToken, authUri) => {
  return getObj(appToken)
    .then((app) => app.auth.loginFromURI(authUri))
    .then((connectedApp) => appToken);
};

/**
 * Authorise container request
 * @returns {Promise<AuthURI>} auth granted URI
 */
module.exports.authoriseContainer = (appToken, permissions) => {
  return new Promise((resolve, reject) => {
    getObj(appToken)
      .then((app) => app.auth.genContainerAuthUri(permissions)
        .then((authReq) => ipc.sendAuthReq(authReq, (err, res) => {
          if (err) {
            return reject(new Error('Unable to authorise the application: ', err)); // TODO send Error in specific
          }
          return resolve(res);
        })))
      .catch(reject);
  });
};

module.exports.webFetch = (appToken, url) => {
  return getObj(appToken)
    .then((app) => app.webFetch(url)
      .then((f) => app.immutableData.fetch(f.dataMapName))
      .then((i) => i.read())
    );
};

/**
 * Whether or not this is a registered/authenticated
 * session.
 *
 * @param {String} appToken - the application token
 * @returns {Boolean} true if this is an authenticated session
 **/
module.exports.isRegistered = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.registered);
};

/**
 * Whether or not this session has specifc permission access of a given
 * container.
 * @param {String} appToken - the application token
 * @arg {String} name  name of the container, e.g. `_public`
 * @arg {(String||Array<String>)} [permissions=['Read']] permissions to check for
 * @returns {Promise<Boolean>}
 **/
module.exports.canAccessContainer = (appToken, name, permissions) => {
  return getObj(appToken)
    .then((app) => app.auth.canAccessContainer(name, permissions));
};

/**
 * Refresh accessible containers
 * @param appToken
 */
module.exports.refreshContainerAccess = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.refreshContainerAccess());
};

/**
 * Get the MData for the apps own container generated by Authenticator
 * @param appToken
 * @return {*}
 */
module.exports.getHomeContainer = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.getHomeContainer())
    .then(genHandle);
};

/**
 * Lookup and return the information necessary to access a container.
 * @param {String} appToken - the application token
 * @arg name {String} name of the container, e.g. `'_public'`
 * @returns {Promise<MutableDataHandle>} the handle for the Mutable Data behind that object
 */
module.exports.getContainer = (appToken, name) => {
  return getObj(appToken)
    .then((app) => app.auth.getAccessContainerInfo(name))
    .then(genHandle);
};

/**
 * Get the public signing key of this session
 * @param {String} appToken - the application token
 * @returns {Promise<SignKeyHandle>}
 **/
module.exports.getPubSignKey = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.getPubSignKey())
    .then(genHandle);
};

/**
 * Get the public encryption key of this session
 * @param {String} appToken - the application token
 * @returns {Promise<EncKeyHandle>}
 **/
module.exports.getEncKey = (appToken) => {
  return getObj(appToken)
    .then((app) => app.auth.getEncKey())
    .then(genHandle);
};

/**
 * Interprete the SignKey from a given raw string
 * @param {String} appToken - the application token
 * @param {String} raw
 * @returns {Promise<SignKeyHandle>}
 **/
module.exports.getSignKeyFromRaw = (appToken, raw) => {
  return getObj(appToken)
    .then((app) => app.auth.getSignKeyFromRaw(raw))
    .then(genHandle);
};

/**
 * Interprete the encryption Key from a given raw string
 * @param {String} appToken - the application token
 * @arg {String} raw
 * @returns {Promise<EncKeyHandle>}
 **/
module.exports.getEncKeyKeyFromRaw = (appToken, raw) => {
  return getObj(appToken)
    .then((app) => app.auth.getEncKeyKeyFromRaw(raw))
    .then(genHandle);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/cipher_opt.js version [fba3cdfab8].























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const { genHandle, getObj } = require('./helpers');

module.exports.manifest = {
  newPlainText: 'promise',
  newSymmetric: 'promise',
  newAsymmetric: 'promise',
};

/**
 * Create a PlainText Cipher Opt
 * @param {String} appToken - the application token
 * @returns {CipherOptHandle}
 **/
module.exports.newPlainText = (appToken) => {
  return getObj(appToken)
    .then((app) => app.cipherOpt.newPlainText())
    .then(genHandle);
};

/**
 * Create a new Symmetric Cipher
 * @param {String} appToken - the application token
 * @returns {CipherOptHandle}
 **/
module.exports.newSymmetric = (appToken) => {
  return getObj(appToken)
    .then((app) => app.cipherOpt.newSymmetric())
    .then(genHandle);
};

/**
 * Create a new Asymmetric Cipher for the given key
 * @param {String} appToken - the application token
 * @param {EncKeyHandle} keyHandle
 * @returns {CipherOptHandle}
 **/
module.exports.newAsymmetric = (appToken, keyHandle) => {
  return getObj(appToken)
    .then((app) => getObj(keyHandle)
      .then((key) => app.cipherOpt.newAsymmetric(key))
      .then(genHandle)
    );
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/crypto.js version [9cdf88f229].















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const { genHandle, getObj } = require('./helpers');

module.exports.manifest = {
  sha3Hash: 'promise',
  getAppPubSignKey: 'promise',
  getAppPubEncKey: 'promise',
  generateEncKeyPair: 'promise',
  getSignKeyFromRaw: 'promise',
  pubEncKeyKeyFromRaw: 'promise'
};

/**
 * Hash the given input with SHA3 Hash
 * @param appToken - the application token
 * @param inpt - input string
 * @return {Promise<Buffer>}
 */
module.exports.sha3Hash = (appToken, inpt) => {
  return getObj(appToken)
    .then((app) => app.crypto.sha3Hash(inpt));
};

/**
 * Get the public signing key
 * @param appToken - the application token
 * @return {Promise<SignKeyHandle>}
 */
module.exports.getAppPubSignKey = (appToken) => {
  return getObj(appToken)
    .then((app) => app.crypto.getAppPubSignKey())
    .then(genHandle);
};

/**
 * Get the public encryption key
 * @param appToken - the application token
 * @return {Promise<PubEncKeyHandle>}
 */
module.exports.getAppPubEncKey = (appToken) => {
  return getObj(appToken)
    .then((app) => app.crypto.getAppPubEncKey())
    .then(genHandle);
};

/**
 * Generate a new Asymmetric EncryptionKeyPair
 * @param appToken - the application token
 * @return {Promise<KeyPairHandle>}
 */
module.exports.generateEncKeyPair = (appToken) => {
  return getObj(appToken)
    .then((app) => app.crypto.generateEncKeyPair())
    .then(genHandle);
};

/**
 * Interpret the SignKey from a given raw string
 * @param appToken - the application token
 * @param raw - raw input string
 * @return {Promise<SignKeyHandle>}
 */
module.exports.getSignKeyFromRaw = (appToken, raw) => {
  return getObj(appToken)
    .then((app) => app.crypto.getSignKeyFromRaw(raw))
    .then(genHandle);
};

/**
 * Interprete the encryption Key from a given raw string
 * @param appToken - the application token
 * @param raw - raw input string
 * @return {Promise<PubEncKeyHandle>}
 */
module.exports.pubEncKeyKeyFromRaw = (appToken, raw) => {
  return getObj(appToken)
    .then((app) => app.crypto.pubEncKeyKeyFromRaw(raw))
    .then(genHandle);
};

/**
 * Interpret the secret encryption Key from a given raw string
 * @param appToken - the application token
 * @param raw - raw input string
 * @return {Promise<SecEncKey>}
 */
module.exports.secEncKeyKeyFromRaw = (appToken, raw) => {
  return getObj(appToken)
    .then((app) => app.crypto.secEncKeyKeyFromRaw(raw))
    .then(genHandle);
};

/**
 * Generate a new Asymmetric EncryptionKeyPair from raw secret and public keys
 * @param appToken - the application token
 * @param rawPublicKey
 * @param rawSecretKey
 * @return {Promise<KeyPair>}
 */
module.exports.generateEncKeyPairFromRaw = (appToken, rawPublicKey, rawSecretKey) => {
  return getObj(appToken)
    .then((app) => app.crypto.generateEncKeyPairFromRaw(rawPublicKey, rawSecretKey))
    .then(genHandle);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/crypto_key_pair.js version [4fd784953a].

























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
const { genHandle, getObj } = require('./helpers');

module.exports.manifest = {
  getPubEncKey: 'promise',
  getSecEncKey: 'promise',
  decryptSealed: 'promise'
};

/**
 * Get the Public Encryption key instance of this keypair
 * @param appToken - application token
 * @param keyPairHandle - keyPair handle
 * @return {Promise<PubEncKey>}
 */
module.exports.getPubEncKey = (appToken, keyPairHandle) => {
  return getObj(appToken)
    .then(() => getObj(keyPairHandle))
    .then((keyPair) => genHandle(keyPair.pubEncKey));
};

/**
 * Get the Secrect Encryption key instance of this keypair
 * @param appToken - application token
 * @param keyPairHandle - keyPair handle
 * @return {Promise<SecEncKey>}
 */
module.exports.getSecEncKey = (appToken, keyPairHandle) => {
  return getObj(appToken)
    .then(() => getObj(keyPairHandle))
    .then((keyPair) => genHandle(keyPair.secEncKey));
};

/**
 * Decrypt the given ciphertext with a seal (buffer or string) using the private and public key
 * @param appToken - application token
 * @param keyPairHandle - keyPair handle
 * @param cipher
 * @return {Promise<Buffer>}
 */
module.exports.decryptSealed = (appToken, keyPairHandle, cipher) => {
  return getObj(appToken)
    .then(() => getObj(keyPairHandle))
    .then((keyPair) => keyPair.decryptSealed(cipher));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/crypto_public_encryption_key.js version [d8d5b91c25].





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const { getObj } = require('./helpers');

module.exports.manifest = {
  getRaw: 'promise',
  encryptSealed: 'promise',
  encrypt: 'promise'
};

/**
 * Generate raw string copy of encryption key
 * @param appToken - application token
 * @param pubEncKeyHandle - public encrypted key handle
 * @return {Promise<String>}
 */
module.exports.getRaw = (appToken, pubEncKeyHandle) => {
  return getObj(appToken)
    .then(() => getObj(pubEncKeyHandle))
    .then((pubEncKey) => pubEncKey.getRaw());
};

/**
 * Encrypt the input (buffer or string) using the private and public key with a seal
 * @param appToken - application token
 * @param pubEncKeyHandle - public encrypted key handle
 * @param str
 * @return {Promise<Buffer>}
 */
module.exports.encryptSealed = (appToken, pubEncKeyHandle, str) => {
  return getObj(appToken)
    .then(() => getObj(pubEncKeyHandle))
    .then((pubEncKey) => pubEncKey.encryptSealed(str));
};

/**
 * Encrypt the input (buffer or string) using the private and public key and the given privateKey
 * @param appToken - application token
 * @param pubEncKeyHandle - public encrypted key handle
 * @param str
 * @param secretKey
 * @return {Promise<Buffer>}
 */
module.exports.encrypt = (appToken, pubEncKeyHandle, str, secretKey) => {
  return getObj(appToken)
    .then(() => getObj(pubEncKeyHandle))
    .then((pubEncKey) => pubEncKey.encrypt(str, secretKey));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/crypto_secret_encryption_key.js version [264ef0a94b].

































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
const { getObj } = require('./helpers');

module.exports.manifest = {
  getRaw: 'promise',
  decrypt: 'promise'
};

/**
 * Generate raw string copy of encryption key
 * @param appToken - application token
 * @param secEncKeyHandle - secret encrypted key handle
 * @return {Promise<String>}
 */
module.exports.getRaw = (appToken, secEncKeyHandle) => {
  return getObj(appToken)
    .then(() => getObj(secEncKeyHandle))
    .then((secEncKey) => secEncKey.getRaw());
};

/**
 * Decrypt the given ciphertext (buffer or string) using the private and public key
 * @param appToken - application token
 * @param secEncKeyHandle - secret encrypted key handle
 * @param cipher
 * @param theirPubKey
 * @return {Promise<Buffer>}
 */
module.exports.decrypt = (appToken, secEncKeyHandle, cipher, theirPubKey) => {
  return getObj(appToken)
    .then(() => getObj(secEncKeyHandle))
    .then((secEncKey) => secEncKey.decrypt(cipher, theirPubKey));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/crypto_sign_key.js version [ec94697d8c].



































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
const { getObj } = require('./helpers');

module.exports.manifest = {
  getRaw: 'promise'
};

/**
 * Generate raw string copy of encryption key
 * @param appToken - application token
 * @param signKeyHandle - public encrypted key handle
 * @return {Promise<String>}
 */
module.exports.getRaw = (appToken, signKeyHandle) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle))
    .then((signKey) => signKey.getRaw());
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/emulations/nfs.js version [499747b23d].











































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
const { genHandle, getObj } = require('../helpers');

module.exports.manifest = {
  create: 'promise',
  fetch: 'promise',
  insert: 'promise',
  update: 'promise',
  getFileMeta: 'promise'
};

module.exports.create = (appToken, nfsHandle, content) => {
  return getObj(appToken)
    .then(() => getObj(nfsHandle))
    .then((nfs) => nfs.create(content))
    .then(genHandle);
};

module.exports.fetch = (appToken, nfsHandle, fileName) => {
  return getObj(appToken)
    .then(() => getObj(nfsHandle))
    .then((nfs) => nfs.fetch(fileName))
    .then(genHandle);
};

module.exports.insert = (appToken, nfsHandle, fileHandle, fileName) => {
  return getObj(appToken)
    .then(() => getObj(nfsHandle))
    .then((nfs) => {
      return getObj(fileHandle).then((file) => nfs.insert(fileName, file));
    })
    .then(() => fileHandle);
};

module.exports.update = (appToken, nfsHandle, fileHandle, fileName, version) => {
  return getObj(appToken)
    .then(() => getObj(nfsHandle))
    .then((nfs) => {
      return getObj(fileHandle).then((file) => nfs.update(fileName, file, version));
    })
    .then(() => fileHandle);
};

module.exports.getFileMeta = (fileHandle) => {
  return getObj(fileHandle).then((file) => (
    {
      dataMapName: file.dataMapName,
      created: file.created,
      modified: file.modified,
      size: file.size,
      version: file.version
    }
  ))
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/helpers.js version [5525a0ad41].













































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
const crypto = require('crypto'); // electron deps will be available inside browser
const { Readable } = require('stream');

const handles = new Map();

export const genRandomString = () => (crypto.randomBytes(32).toString('hex'));

export const genHandle = (obj) => {
  const randHandle = genRandomString();
  handles.set(randHandle, obj);
  return randHandle;
};

export const getObj = (handle) => {
  return new Promise((resolve, reject) => {
    const obj = handles.get(handle);
    if (obj) {
      return resolve(obj);
    }
    return reject(new Error('Invalid handle'));
  });
};

export const freeObj = (handle) => {
  handles.delete(handle);
};

export const forEachHelper = (appToken, containerHandle, sendHandles) => {
  var readable = new Readable({ objectMode: true, read() {} })
  getObj(appToken)
    .then(() => getObj(containerHandle))
    .then((container) => container.forEach((arg1, arg2) => {
        setImmediate(() => {
          if (sendHandles) {
            arg1 = genHandle(arg1);
          }
          let args = [arg1];
          if (arg2) {
            if (sendHandles) {
              arg2 = genHandle(arg2);
            }
            args.push(arg2);
          }
          readable.push(args)
        })
      })
      .then(() => {
        setImmediate(() => {
          readable.push(null)
        })
      })
    );
  return readable;
}

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/immutable_data.js version [b614556b3a].















































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
const { genHandle, getObj, freeObj } = require('./helpers');

module.exports.manifest = {
  create: 'promise',
  fetch: 'promise',
  write: 'promise',
  closeWriter: 'promise',
  read: 'promise',
  size: 'promise',
  closeReader: 'promise',
};

/**
 * Create a new ImmutableData Writer
 * @param {String} appToken - the application token
 * @returns {Promise<Handle>} - the ImmutableData Writer Handle
 **/
module.exports.create = (appToken) => {
  return getObj(appToken)
    .then((app) => app.immutableData.create())
    .then(genHandle);
};

/**
 * Look up an existing Immutable Data for the given address
 * @param {String} appToken - the application token
 * @param {Buffer} address - the XorName on the network
 * @returns {Promise<Handle>} - the ImmutableData Reader Handle
 **/
module.exports.fetch = (appToken, address) => {
  return getObj(appToken)
    .then((app) => app.immutableData.fetch(address))
    .then(genHandle);
};

/**
 * Append the given data to immutable Data.
 *
 * @param {String} appToken - the application token
 * @param {Handle} writerHandle - the writer handle
 * @param {String} string
 * @returns {Promise<()>}
 **/
module.exports.write = (appToken, writerHandle, string) => {
  return getObj(appToken)
    .then(() => getObj(writerHandle))
    .then((writer) => writer.write(string));
};

/**
 * Close and write the immutable Data to the network.
 * @param {String} appToken - the application token
 * @param {Handle} writerHandle - the writer handle
 * @returns {Promise<String>} the address to the data once written to the network
 **/
module.exports.closeWriter = (appToken, writerHandle) => {
  return getObj(appToken)
    .then(() => getObj(writerHandle))
    .then((writer) => writer.close())
    .then((addr) => {
      freeObj(writerHandle);
      return addr;
    });
};

/**
 * Read the given amount of bytes from the network
 * @param {String} appToken - the application token
 * @param {Handle} readerHandle - the reader handle
 * @param {Object=} options
 * @param {Number} [options.offset=0] start position
 * @param {Number} [options.end=size] end position or end of data
 **/
module.exports.read = (appToken, readerHandle, options) => {
  return getObj(appToken)
    .then(() => getObj(readerHandle))
    .then((reader) => reader.read(options));
};

/**
 * The size of the mutable data on the network
 * @param {String} appToken - the application token
 * @param {Handle} readerHandle - the reader handle
 * @returns {Promise<Number>} length in bytes
 **/
module.exports.size = (appToken, readerHandle) => {
  return getObj(appToken)
    .then(() => getObj(readerHandle))
    .then((reader) => reader.size());
};

/**
 * Close the Reader handle
 * @param {String} appToken - the application token
 * @param {Handle} readerHandle - the reader handle
 * @returns {Promise<()>}
 */
module.exports.closeReader = (appToken, readerHandle) => {
  return getObj(appToken)
    .then(() => getObj(readerHandle))
    .then((reader) => reader.close())
    .then(() => freeObj(readerHandle));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/index.js version [be805f4bdc].







































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
const app = require('./app');
const cipherOpt = require('./cipher_opt');
const imdata = require('./immutable_data');
const crypto = require('./crypto');
const cryptoKeyPair = require('./crypto_key_pair');
const cryptoSecEncKey = require('./crypto_secret_encryption_key');
const cryptoPubEncKey = require('./crypto_public_encryption_key');
const cryptoSignKey = require('./crypto_sign_key');
const mdata = require('./mutable_data');
const mdataEntries = require('./mutable_data_entries');
const mdataKeys = require('./mutable_data_keys');
const mdataValues = require('./mutable_data_values');
const mdataMutation = require('./mutable_data_mutation');
const mdataPermissions = require('./mutable_data_permissions');
const mdataPermissionsSet = require('./mutable_data_permissions_set');
const nfs = require('./emulations/nfs');

module.exports = [
  {
    name: 'safeApp',
    isInternal: true,
    manifest: app.manifest,
    methods: app
  },
  {
    name: 'safeCipherOpt',
    isInternal: true,
    manifest: cipherOpt.manifest,
    methods: cipherOpt
  },
  {
    name: 'safeImmutableData',
    isInternal: true,
    manifest: imdata.manifest,
    methods: imdata
  },
  {
    name: 'safeCrypto',
    isInternal: true,
    manifest: crypto.manifest,
    methods: crypto
  },
  {
    name: 'safeCryptoKeyPair',
    isInternal: true,
    manifest: cryptoKeyPair.manifest,
    methods: cryptoKeyPair
  },
  {
    name: 'safeCryptoSecEncKey',
    isInternal: true,
    manifest: cryptoSecEncKey.manifest,
    methods: cryptoSecEncKey
  },
  {
    name: 'safeCryptoPubEncKey',
    isInternal: true,
    manifest: cryptoPubEncKey.manifest,
    methods: cryptoPubEncKey
  },
  {
    name: 'safeCryptoSignKey',
    isInternal: true,
    manifest: cryptoSignKey.manifest,
    methods: cryptoSignKey
  },
  {
    name: 'safeMutableData',
    isInternal: true,
    manifest: mdata.manifest,
    methods: mdata
  },
  {
    name: 'safeMutableDataEntries',
    isInternal: true,
    manifest: mdataEntries.manifest,
    methods: mdataEntries
  },
  {
    name: 'safeMutableDataKeys',
    isInternal: true,
    manifest: mdataKeys.manifest,
    methods: mdataKeys
  },
  {
    name: 'safeMutableDataValues',
    isInternal: true,
    manifest: mdataValues.manifest,
    methods: mdataValues
  },
  {
    name: 'safeMutableDataMutation',
    isInternal: true,
    manifest: mdataMutation.manifest,
    methods: mdataMutation
  },
  {
    name: 'safeMutableDataPermissions',
    isInternal: true,
    manifest: mdataPermissions.manifest,
    methods: mdataPermissions
  },
  {
    name: 'safeMutableDataPermissionsSet',
    isInternal: true,
    manifest: mdataPermissionsSet.manifest,
    methods: mdataPermissionsSet
  },
  {
    name: 'safeNfs',
    isInternal: true,
    manifest: nfs.manifest,
    methods: nfs
  }
];

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/ipc.js version [f7ad755519].



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved */
const ipcMain = require('electron').ipcMain; // electron deps will be avaible inside browser
/* eslint-enable import/no-extraneous-dependencies, import/no-unresolved */
const genRandomString = require('./helpers').genRandomString;

class IpcTask {
  constructor() {
    this.tasks = [];
    this.tasksInfo = {};
    this.isProcessing = false;
    this.currentTaskId = null;
    this.currentTaskInfo = null;
    this.currentTaskCb = null;
  }

  add(info, cb) {
    const token = genRandomString();
    this.tasks.push(token);
    this.tasksInfo[token] = { info, cb };
    this.next();
  }

  remove() {
    const index = this.tasks.indexOf(this.currentTaskId);
    this.tasks.splice(index, 1);
    delete this.tasksInfo[this.currentTaskId];
    this.isProcessing = false;
    return this;
  }

  next() {
    if (this.isProcessing || this.tasks.length === 0) {
      return;
    }
    this.isProcessing = true;
    this.currentTaskId = this.tasks[0];
    this.currentTaskInfo = this.tasksInfo[this.currentTaskId].info;
    this.currentTaskCb = this.tasksInfo[this.currentTaskId].cb;
    ipcEvent.sender.send('webClientAuthReq', this.currentTaskInfo);
  }
}

const ipcTask = new IpcTask();

let ipcEvent = null;

ipcMain.on('registerSafeApp', (event) => {
  ipcEvent = event;
});

ipcMain.on('webClientContainerRes', (event, res) => {
  // handle response
  if (typeof ipcTask.currentTaskCb === 'function') {
    ipcTask.currentTaskCb(null, res);
  }
  ipcTask.remove().next();
});

ipcMain.on('webClientAuthRes', (event, res) => {
  // handle response
  if (typeof ipcTask.currentTaskCb === 'function') {
    ipcTask.currentTaskCb(null, res);
  }
  ipcTask.remove().next();
});

ipcMain.on('webClientErrorRes', (event, err) => {
  // handle Error
  if (typeof ipcTask.currentTaskCb === 'function') {
    ipcTask.currentTaskCb(err);
  }
  ipcTask.remove().next();
});

module.exports.sendAuthReq = (req, cb) => {
  ipcTask.add(req.uri, cb);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data.js version [7fae846629].























































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
const { genHandle, getObj } = require('./helpers');

module.exports.manifest = {
  newRandomPrivate: 'promise',
  newRandomPublic: 'promise',
  newPrivate: 'promise',
  newPublic: 'promise',
  newPermissions: 'promise',
  newPermissionSet: 'promise',
  newMutation: 'promise',
  newEntries: 'promise',
  quickSetup: 'promise',
  encryptKey: 'promise',
  encryptValue: 'promise',
  getNameAndTag: 'promise',
  getVersion: 'promise',
  get: 'promise',
  put: 'promise',
  getEntries: 'promise',
  getKeys: 'promise',
  getValues: 'promise',
  getPermissions: 'promise',
  getUserPermissions: 'promise',
  delUserPermissions: 'promise',
  setUserPermissions: 'promise',
  applyEntriesMutation: 'promise',
  serialise: 'promise',
  fromSerial: 'promise',
  emulateAs: 'promise',
};

/**
 * Create a new mutuable data at a random address with private
 * access.
 * @param {String} appToken - the application token
 * @param {Number} typeTag - the typeTag to use
 * @returns {Promise<MutableDataHandle>}
 **/
module.exports.newRandomPrivate = (appToken, typeTag) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newRandomPrivate(typeTag))
    .then(genHandle);
};

/**
 * Create a new mutuable data at a random address with public
 * access.
 * @param {String} appToken - the application token
 * @param {Number} typeTag - the typeTag to use
 * @returns {Promise<MutableDataHandle>}
 **/
module.exports.newRandomPublic = (appToken, typeTag) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newRandomPublic(typeTag))
    .then(genHandle);
};

/**
 * Initiate a mutuable data at the given address with private
 * access.
 * @param {String} appToken - the application token
 * @param {Buffer|String}
 * @param {Number} typeTag - the typeTag to use
 * @returns {Promise<MutableDataHandle>}
 **/
module.exports.newPrivate = (appToken, name, typeTag) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newPrivate(name, typeTag))
    .then(genHandle);
};

/**
 * Initiate a mutuable data at the given address with public
 * access.
 * @param {String} appToken - the application token
 * @param {Buffer|String}
 * @param {Number} typeTag - the typeTag to use
 * @returns {Promise<MutableDataHandle>}
 **/
module.exports.newPublic = (appToken, name, typeTag) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newPublic(name, typeTag))
    .then(genHandle);
};

/**
 * Create a new Permissions object.
 * @param {String} appToken - the application token
 * @returns {Promise<PermissionsHandle>}
 **/
module.exports.newPermissions = (appToken) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newPermissions())
    .then(genHandle);
};

/**
 * Create a new PermissionsSet object.
 * @param {String} appToken - the application token
 * @returns {Promise<PermissionsSetHandle>}
 **/
module.exports.newPermissionSet = (appToken) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newPermissionSet())
    .then(genHandle);
};

/**
 * Create a new Mutation object.
 * @param {String} appToken - the application token
 * @returns {Promise<MutationHandle>}
 **/
module.exports.newMutation = (appToken) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newMutation())
    .then(genHandle);
};

/**
 * Create a new Entries object.
 * @param {String} appToken - the application token
 * @returns {Promise<EntriesHandle>}
 **/
module.exports.newEntries = (appToken) => {
  return getObj(appToken)
    .then((app) => app.mutableData.newEntries())
    .then(genHandle);
};

// MutableData functions
/**
 * Quickly set up a newly (not yet created) MutableData with
 * the app having full-access permissions (and no other).
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {Object=} data - a key-value payload it should
 *        create the data with
 * @returns {Promise<MutableDataHandle>} - self
 **/
module.exports.quickSetup = (appToken, mdHandle, data) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.quickSetup(data))
    .then(() => mdHandle);
};

/**
 * Encrypt the entry key provided as parameter with the encryption key
 * contained in a Private MutableData. If the MutableData is Public, the same
 * (and unencrypted) value is returned.
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {(String|Buffer)} key - the key you want to encrypt
 * @returns {Promise<Key>} - the encrypted entry key
 **/
module.exports.encryptKey = (appToken, mdHandle, key) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.encryptKey(key));
};

/**
 * Encrypt the entry value provided as parameter with the encryption key
 * contained in a Private MutableData. If the MutableData is Public, the same
 * (and unencrypted) value is returned.
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {(String|Buffer)} value - the data you want to encrypt
 * @returns {Promise<Value>} - the encrypted entry value
 **/
module.exports.encryptValue = (appToken, mdHandle, value) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.encryptValue(value));
};

/**
 * Look up the name and tag of the MutableData as required to look it
 * up on the network.
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<NameAndTag>}
 **/
module.exports.getNameAndTag = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getNameAndTag());
};

/**
 * Look up the mutable data object version on the network
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<Number>} the version
 **/
module.exports.getVersion = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getVersion());
};

/**
 * Look up the value of a specific key
 *
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {String} key - the entry's key
 * @returns {Promise<ValueVersion>} - the value at the current version
 **/
module.exports.get = (appToken, mdHandle, key) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.get(key));
};

/**
 * Create this MutableData on the network.
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {PermissionsHandle} permissionsHandle - the permissions to create the mdata with
 * @param {EntriesHandle} entriesHandle - data payload to create the mdata with
 * @returns {Promise<()>}
 **/
module.exports.put = (appToken, mdHandle, permissionsHandle, entriesHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => getObj(permissionsHandle)
      .then((permissions) => getObj(entriesHandle)
        .then((entries) => md.put(permissions, entries))
      ));
};

/**
 * Get a Handle to the entries associated with this mdata
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<(EntriesHandle)>}
 **/
module.exports.getEntries = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getEntries())
    .then(genHandle);
};

/**
 * Get a Handle to the keys associated with this mdata
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<(KeysHandle)>}
 **/
module.exports.getKeys = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getKeys())
    .then(genHandle);
};

/**
 * Get a Handle to the values associated with this mdata
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<(ValuesHandle)>}
 **/
module.exports.getValues = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getValues())
    .then(genHandle);
};

/**
 * Get a Handle to the permissions associated with this mdata
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<(PermissionsHandle)>}
 **/
module.exports.getPermissions = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.getPermissions())
    .then(genHandle);
};

/**
 * Get a Handle to the permissions associated with this mdata for
 * a specifc key
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {SignKeyHandle} signKeyHandle - the sign key to look up
 * @returns {Promise<(PermissionsSetHandle)>}
 **/
module.exports.getUserPermissions = (appToken, mdHandle, signKeyHandle) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle))
    .then((signKey) => getObj(mdHandle)
      .then((md) => md.getUserPermissions(signKey))
      .then(genHandle)
    );
};

/**
 * Delete the permissions of a specifc key. Directly commits to the network.
 * Requires 'ManagePermissions'-Permission for the app.
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {SignKeyHandle} signKeyHandle - the sign key to lookup for
 * @param {Number} version - the current version, to confirm you are
 *        actually asking for the right state
 * @returns {Promise} - once finished
 **/
module.exports.delUserPermissions = (appToken, mdHandle, signKeyHandle, version) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle))
    .then((signKey) => getObj(mdHandle)
      .then((md) => md.delUserPermissions(signKey, version))
    );
};

/**
 * Set the permissions of a specifc key. Directly commits to the network.
 * Requires 'ManagePermissions'-Permission for the app.
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {SignKeyHandle} signKeyHandle - the sign key to lookup for
 * @param {PermissionsSetHandle} pmSetHandle - the PermissionsSet to set to
 * @param {Number} version - the current version, to confirm you are
 *        actually asking for the right state
 * @returns {Promise} - once finished
 **/
module.exports.setUserPermissions = (appToken, mdHandle, signKeyHandle, pmSetHandle, version) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle)
      .then((signKey) => getObj(pmSetHandle)
        .then((pmSet) => getObj(mdHandle)
          .then((md) => md.setUserPermissions(signKey, pmSet, version))
        )));
};

/**
 * Commit the transaction to the network
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {MutationHandle} mutationHandle - the Mutation you want to apply
 * @return {Promise}
 **/
module.exports.applyEntriesMutation = (appToken, mdHandle, mutationHandle) => {
  return getObj(appToken)
    .then(() => getObj(mutationHandle))
    .then((mutation) => getObj(mdHandle)
      .then((md) => md.applyEntriesMutation(mutation))
    );
};

/**
 * Serialise the current mdata
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @returns {Promise<(String)>}
 **/
module.exports.serialise = (appToken, mdHandle) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.serialise());
};

/**
 * Deserialize the mdata
 * @param {String} appToken - the application token
 * @returns {Promise<MutableDataHandle>}
 */
module.exports.fromSerial = (appToken, data) => {
  return getObj(appToken)
    .then((app) => app.mutableData.fromSerial(data))
    .then(genHandle);
};

/**
 * Wrap this MData into a known abstraction. Currently known: `NFS`
 * @param {String} appToken - the application token
 * @param {MutableDataHandle} mdHandle - the MutableData handle
 * @param {String} eml - name of the emulation
 * @returns {EmulationHandle} the Emulation you are asking for
 **/
module.exports.emulateAs = (appToken, mdHandle, eml) => {
  return getObj(appToken)
    .then(() => getObj(mdHandle))
    .then((md) => md.emulateAs(eml))
    .then(genHandle);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_entries.js version [cade73984c].



























































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
const { genHandle, getObj, forEachHelper } = require('./helpers');

module.exports.manifest = {
  len: 'promise',
  get: 'promise',
  _with_cb_forEach: 'readable',
  insert: 'promise',
  mutate: 'promise',
};


/**
 * Get the total number of entries in the Mdata
 * @param {String} appToken - the application token
 * @param {EntriesHandle} entriesHandle - the Entries obj handle
 * @returns {Promise<Number>}
 **/
module.exports.len = (appToken, entriesHandle) => {
  return getObj(appToken)
    .then(() => getObj(entriesHandle))
    .then((entries) => entries.len());
};

/**
 * Look up the value of a specific key
 *
 * @param {String} appToken - the application token
 * @param {EntriesHandle} entriesHandle - the Entries obj handle
 * @param {String} keyName - the entry's key
 * @returns {Promise<ValueVersion>} - the value at the current version
 **/
module.exports.get = (appToken, entriesHandle, keyName) => {
  return getObj(appToken)
    .then(() => getObj(entriesHandle))
    .then((entries) => entries.get(keyName));
};

/**
 * Iterate over the entries, execute the function every time
 * @param {String} appToken - the application token
 * @param {EntriesHandle} entriesHandle - the Entries obj handle
 * @param {function(Buffer, ValueVersion)} fn - the function to call
 * @returns {Promise<()>} - resolves once the iteration is done
 **/
module.exports._with_cb_forEach = (appToken, entriesHandle) => {
  return forEachHelper(appToken, entriesHandle);
};

/**
 * Insert a new entry. Will directly commit that transaction to the network.
 * Will fail if the entry already exists or the current app doesn't have the
 * permissions to edit that mdata.
 *
 * @param {String} appToken - the application token
 * @param {EntriesHandle} entriesHandle - the Entries obj handle
 * @param {(String|Buffer)} keyName - the key you want store the data under
 * @param {(String|Buffer)} value - the data you want to store
 * @returns {Promise<>}
 **/
module.exports.insert = (appToken, entriesHandle, keyName, value) => {
  return getObj(appToken)
    .then(() => getObj(entriesHandle))
    .then((entries) => entries.insert(keyName, value));
};

/**
 * Start a new transaction of mutation of the entries
 * @param {String} appToken - the application token
 * @param {EntriesHandle} entriesHandle - the Entries obj handle
 * @return {Promise<MutationHandle>}
 **/
module.exports.mutate = (appToken, entriesHandle) => {
  return getObj(appToken)
    .then(() => getObj(entriesHandle))
    .then((entries) => entries.mutate())
    .then(genHandle);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_keys.js version [42cae9ae98].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const { getObj, forEachHelper } = require('./helpers');

module.exports.manifest = {
  len: 'promise',
  _with_cb_forEach: 'readable',
};

/**
 * Get the total number of keys in the Mdata
 * @param {String} appToken - the application token
 * @param {KeysHandle} keysHandle - the Keys obj handle
 * @returns {Promise<Number>}
 **/
module.exports.len = (appToken, keysHandle) => {
  return getObj(appToken)
    .then(() => getObj(keysHandle))
    .then((keys) => keys.len());
};

/**
 * Iterate over the value, execute the function every time
 * @param {String} appToken - the application token
 * @param {KeysHandle} keysHandle - the Keys obj handle
 * @param {function(Buffer)} fn - the function to call with the key in the buffer
 * @returns {Promise<()>} - resolves once the iteration is done
 **/
module.exports._with_cb_forEach = (appToken, keysHandle) => {
  return forEachHelper(appToken, keysHandle);
}

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_mutation.js version [4679f850dc].















































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
const { getObj } = require('./helpers');

module.exports.manifest = {
  insert: 'promise',
  remove: 'promise',
  update: 'promise',
};

/**
 * Store a new `Insert`-Action in the transaction.
 *
 * @param {String} appToken - the application token
 * @param {MutationHandle} mutationHandle - the Mutation obj handle
 * @param {(String|Buffer)} keyName
 * @param {(String|Buffer)} value
 * @returns {Promise} resolves once the storing is done
 **/
module.exports.insert = (appToken, mutationHandle, keyName, value) => {
  return getObj(appToken)
    .then(() => getObj(mutationHandle))
    .then((mutation) => mutation.insert(keyName, value));
};

/**
 * Store a new `Remove`-Action in the transaction
 *
 * @param {String} appToken - the application token
 * @param {MutationHandle} mutationHandle - the Mutation obj handle
 * @param {(String|Buffer)} keyName - the key you want to remove
 * @param {Number} version - the current version, to confirm you are
 *        actually asking for the right state
 * @returns {Promise} resolves once the storing is done
 **/
module.exports.remove = (appToken, mutationHandle, keyName, version) => {
  return getObj(appToken)
    .then(() => getObj(mutationHandle))
    .then((mutation) => mutation.remove(keyName, version));
};

/**
 * Store a `Update`-Action in the transaction
 *
 * @param {String} appToken - the application token
 * @param {MutationHandle} mutationHandle - the Mutation obj handle
 * @param {(String|Buffer)} keyName - the key you want to remove
 * @param {(String|Buffer)} value - the value to upate to
 * @param {Number} version - the current version, to confirm you are
 *        actually asking for the right state
 * @returns {Promise} resolves once the storing is done
 **/
module.exports.update = (appToken, mutationHandle, keyName, value, version) => {
  return getObj(appToken)
    .then(() => getObj(mutationHandle))
    .then((mutation) => mutation.update(keyName, value, version));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_permissions.js version [d360e65f45].



































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
const { genHandle, getObj, forEachHelper } = require('./helpers');

module.exports.manifest = {
  len: 'promise',
  getPermissionsSet: 'promise',
  insertPermissionsSet: 'promise',
  _with_cb_forEach: 'readable',
};

/**
 * Total number of permission entries
 * @param {String} appToken - the application token
 * @param {PermissionsHandle} permissionsHandle - the Permissions obj handle
 * @returns {Promise<Number>}
 **/
module.exports.len = (appToken, permissionsHandle) => {
  return getObj(appToken)
    .then(() => getObj(permissionsHandle))
    .then((permissions) => permissions.len());
};

/**
 * Lookup the permissions of a specifc key
 * @param {String} appToken - the application token
 * @param {PermissionsHandle} permissionsHandle - the Permissions obj handle
 * @param {SignKeyHandle} signKeyHandle - the key to lookup for
 * @returns {Promise<PermissionsSetHandle>} - the permissions set for that key
 **/
module.exports.getPermissionsSet = (appToken, permissionsHandle, signKeyHandle) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle))
    .then((signKey) => getObj(permissionsHandle)
      .then((permissions) => permissions.getPermissionSet(signKey))
      .then(genHandle)
    );
};

/**
 * Insert a new permissions to a specifc key. Directly commits to the network.
 * Requires 'ManagePermissions'-Permission for the app.
 * @param {String} appToken - the application token
 * @param {PermissionsHandle} permissionsHandle - the Permissions obj handle
 * @param {SignKeyHandle} signKeyHandle - the key to lookup for
 * @param {PermissionsSetHandle} pmSetHandle - the permissions set you'd like insert
 * @returns {Promise} - once finished
 **/
module.exports.insertPermissionsSet = (appToken, permissionsHandle, signKeyHandle, pmSetHandle) => {
  return getObj(appToken)
    .then(() => getObj(signKeyHandle))
    .then((signKey) => getObj(pmSetHandle)
      .then((pmSet) => getObj(permissionsHandle)
        .then((permissions) => permissions.insertPermissionSet(signKey, pmSet))
      ));
};

/**
 * Iterate over the entries, execute the function every time
 * @param {String} appToken - the application token
 * @param {PermissionsHandle} permissionsHandle - the Permissions obj handle
 * @param {function(Buffer, ValueVersion)} fn - the function to call
 * @returns {Promise<()>} - resolves once the iteration is done
 **/
module.exports._with_cb_forEach = (appToken, permissionsHandle) => {
  return forEachHelper(appToken, permissionsHandle, true);
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_permissions_set.js version [65f3ff4419].





























































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
const { getObj } = require('./helpers');

module.exports.manifest = {
  setAllow: 'promise',
  setDeny: 'promise',
  clear: 'promise',
};

/**
 * Set the action as allowed
 * @param {String} appToken - the application token
 * @param {PermissionsSetHandle} permissionsSetHandle - the PermissionsSet obj handle
 * @param {MDataAction} action
 * @returns {Promise}
 **/
module.exports.setAllow = (appToken, permissionsSetHandle, action) => {
  return getObj(appToken)
    .then(() => getObj(permissionsSetHandle))
    .then((pmSet) => pmSet.setAllow(action));
};

/**
 * Set the action as denied
 * @param {String} appToken - the application token
 * @param {PermissionsSetHandle} permissionsSetHandle - the PermissionsSet obj handle
 * @param {MDataAction} action
 * @returns {Promise}
 **/
module.exports.setDeny = (appToken, permissionsSetHandle, action) => {
  return getObj(appToken)
    .then(() => getObj(permissionsSetHandle))
    .then((pmSet) => pmSet.setDeny(action));
};

/**
 * Remove action from the set
 * @param {String} appToken - the application token
 * @param {PermissionsSetHandle} permissionsSetHandle - the PermissionsSet obj handle
 * @param {MDataAction} action
 * @returns {Promise}
 **/
module.exports.clear = (appToken, permissionsSetHandle, action) => {
  return getObj(appToken)
    .then(() => getObj(permissionsSetHandle))
    .then((pmSet) => pmSet.clear(action));
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/api/mutable_data_values.js version [aee2e0dea8].



























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
const { getObj, forEachHelper } = require('./helpers');

module.exports.manifest = {
  len: 'promise',
  _with_cb_forEach: 'readable',
};

/**
 * Get the total number of values in the Mdata
 * @param {String} appToken - the application token
 * @param {ValuesHandle} valuesHandle - the Values obj handle
 * @returns {Promise<Number>}
 **/
module.exports.len = (appToken, valuesHandle) => {
  return getObj(appToken)
    .then(() => getObj(valuesHandle))
    .then((values) => values.len());
};

/**
 * Iterate over the value, execute the function every time
 * @param {String} appToken - the application token
 * @param {ValuesHandle} valuesHandle - the Values obj handle
 * @param {function(Buffer, ValueVersion)} fn - the function to call
 * @returns {Promise<()>} - resolves once the iteration is done
 **/
module.exports._with_cb_forEach = (appToken, valuesHandle) => {
  return forEachHelper(appToken, valuesHandle);
};

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/src/protocol.js from [83d7c32309] to [41fb54a3e0].


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
..
26
27
28
29
30
31
32
33
34
35
36
37
38
39








40
41
42
43

44
45
46
47
48
49
50
51
52
53
54
55

const safeApp = require('safe-app');
const urlParse = require('url').parse;
const mime = require('mime');
/* eslint-disable import/extensions */
const protocol = require('electron').protocol;
/* eslint-enable import/extensions */

const safeScheme = 'safe';

const appInfo = {
  'id': 'net.maidsafe.app.browser',
  'name': 'SAFE Browser',
  'vendor': 'MaidSafe'
};

let appObj = null;

const authoriseApp = () => {
  if (appObj) {
    return Promise.resolve(true);
................................................................................

const fetchData = (url) => {
  if (!appObj) {
    return Promise.reject(new Error('Unable to create unregistered client'));
  }
  return appObj.webFetch(url)
    .then((f) => appObj.immutableData.fetch(f.dataMapName))
    .then((i) => i.read())
};

const registerSafeAuthProtocol = () => {
  protocol.registerBufferProtocol(safeScheme, (req, cb) => {
    const parsedUrl = urlParse(req.url);
    const fileExt = parsedUrl.pathname.split('/').slice(-1)[0].split('.')[1] || 'html';








    authoriseApp()
      .then(() => fetchData(req.url))
      .then((co) => cb({ mimeType: mime.lookup(fileExt), data: co }))
      .catch(console.error);

  }, (err) => {
    if (err) console.error('Failed to register protocol');
  });
};

module.exports = {
  scheme: safeScheme,
  label: 'SAFE',
  isStandardURL: true,
  isInternal: true,
  register: registerSafeAuthProtocol
};
>



|

|




|
|
|







 







|





|
>
>
>
>
>
>
>
>


|
<
>












1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
..
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51

52
53
54
55
56
57
58
59
60
61
62
63
64
const path = require('path');
const safeApp = require('safe-app');
const urlParse = require('url').parse;
const mime = require('mime');
/* eslint-disable import/no-extraneous-dependencies, import/no-unresolved */
const protocol = require('electron').protocol;
/* eslint-enable import/no-extraneous-dependencies, import/no-unresolved */

const safeScheme = 'safe';

const appInfo = {
  id: 'net.maidsafe.app.browser',
  name: 'SAFE Browser',
  vendor: 'MaidSafe'
};

let appObj = null;

const authoriseApp = () => {
  if (appObj) {
    return Promise.resolve(true);
................................................................................

const fetchData = (url) => {
  if (!appObj) {
    return Promise.reject(new Error('Unable to create unregistered client'));
  }
  return appObj.webFetch(url)
    .then((f) => appObj.immutableData.fetch(f.dataMapName))
    .then((i) => i.read());
};

const registerSafeAuthProtocol = () => {
  protocol.registerBufferProtocol(safeScheme, (req, cb) => {
    const parsedUrl = urlParse(req.url);
    const fileExt = path.basename(parsedUrl.pathname) || 'html';
    const mimeType = mime.lookup(fileExt);
    const handleError = (err) => {
      if (mimeType === 'html') {
        return cb({ mimeType, data: err.message });
      }
      cb(null);
    };

    authoriseApp()
      .then(() => fetchData(req.url))
      .then((co) => cb({ mimeType, data: co }))

      .catch(handleError);
  }, (err) => {
    if (err) console.error('Failed to register protocol');
  });
};

module.exports = {
  scheme: safeScheme,
  label: 'SAFE',
  isStandardURL: true,
  isInternal: true,
  register: registerSafeAuthProtocol
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/webpack.config.api.js version [8da8338b65].









































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import path from 'path';
import os from 'os';
import CopyWebpackPlugin from 'copy-webpack-plugin';

const SAFE_APP = {
  win32: '*.dll',
  darwin: '*.dylib',
  linux: '*.so'
};

const dependenciesToCopy = [
    { context: 'node_modules/safe-app/src/native', from: SAFE_APP[os.platform()], flatten: true }
];

if (os.platform() === 'win32') {
  dependenciesToCopy.push({ context: 'node_modules/safe-app/src/native', from: 'libwinpthread-1.dll', flatten: true });
}

export default {
  devtool: 'cheap-module-source-map',
  entry: path.resolve(__dirname, 'src/api/index.js'),
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'api.js',
    libraryTarget: 'commonjs2'
  },
  module: {
    loaders: [
      {
        test: /\.js?$/,
        loader: 'babel-loader',
        exclude: /node_modules/,
        query: {
          presets: ['es2015']
        }
      }
    ]
  },
  target: 'node',
  node: {
    __dirname: false,
    __filename: false
  },
  externals: {
    electron: 'electron',
    crypto: 'crypto',
    'safe-app': 'safe-app'
  },
  plugins: [
    new CopyWebpackPlugin(dependenciesToCopy)
  ]
};

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-app/webpack.config.protocol.js version [c958dacc03].





























































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import path from 'path';

export default {
  devtool: 'cheap-module-source-map',
  entry: path.resolve(__dirname, 'src/protocol.js'),
  output: {
    path: path.join(__dirname, 'dist'),
    filename: 'protocol.js',
    libraryTarget: 'commonjs2'
  },
  module: {
    loaders: [
      {
        test: /\.js?$/,
        loader: 'babel-loader',
        exclude: /node_modules/
      }
    ]
  },
  target: 'node',
  node: {
    __dirname: false,
    __filename: false,
  },
  externals: {
    electron: 'electron',
    crypto: 'crypto',
    'safe-app': 'safe-app'
  }
};

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.eslintrc from [74c33513bd] to [f0dc3848c9].

6
7
8
9
10
11
12

13
14
15
16
17
18
19
    "mocha": true,
    "node": true
  },
  "rules": {
    "arrow-parens": [2, "always"],
    "consistent-return": 0,
    "comma-dangle": 0,

    "no-use-before-define": 0,
    "import/no-unresolved": [2, { "ignore": ["electron"] }],
    "import/no-extraneous-dependencies": 0,
    "react/jsx-no-bind": 0,
    "react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx"] }],
    "react/prefer-stateless-function": 0,
    # https://github.com/eslint/eslint/issues/6274







>







6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
    "mocha": true,
    "node": true
  },
  "rules": {
    "arrow-parens": [2, "always"],
    "consistent-return": 0,
    "comma-dangle": 0,
    "no-param-reassign": 0,
    "no-use-before-define": 0,
    "import/no-unresolved": [2, { "ignore": ["electron"] }],
    "import/no-extraneous-dependencies": 0,
    "react/jsx-no-bind": 0,
    "react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx"] }],
    "react/prefer-stateless-function": 0,
    # https://github.com/eslint/eslint/issues/6274

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/FETCH_HEAD from [e6e056eddd] to [e9eb53f6b5].

1
2
3
e953a1291995b53342460d81ffde47ca684a0b24		branch 'master' of https://github.com/maidsafe/beaker-plugin-safe-authenticator
5b2115692a85423ada7946ee0ad741e533e80442	not-for-merge	branch 'dev' of https://github.com/maidsafe/beaker-plugin-safe-authenticator
99dc797cfe58a780ade1701be747ebed180bd089	not-for-merge	branch 'revert-54-update_readme' of https://github.com/maidsafe/beaker-plugin-safe-authenticator
|
|

1
2
3
7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f		branch 'master' of https://github.com/maidsafe/beaker-plugin-safe-authenticator
0e439486e74f83d70434a4782bc4a75ec5054340	not-for-merge	branch 'dev' of https://github.com/maidsafe/beaker-plugin-safe-authenticator
99dc797cfe58a780ade1701be747ebed180bd089	not-for-merge	branch 'revert-54-update_readme' of https://github.com/maidsafe/beaker-plugin-safe-authenticator

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/index from [a7a1edb538] to [6384afe05d].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/logs/HEAD from [905f07da32] to [e6cfbc4beb].

1
2

0000000000000000000000000000000000000000 1cadae79fd6a99f8f96595baca45be549c351683 Martin Vahi <martin.vahi@softf1.com> 1490069948 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-authenticator.git
1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 Martin Vahi <martin.vahi@softf1.com> 1490143807 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 1cadae79fd6a99f8f96595baca45be549c351683 Martin Vahi <martin.vahi@softf1.com> 1490069948 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-authenticator.git
1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 Martin Vahi <martin.vahi@softf1.com> 1490143807 +0200	pull --recurse-submodules: Fast-forward
e953a1291995b53342460d81ffde47ca684a0b24 7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f Martin Vahi <martin.vahi@softf1.com> 1494899402 +0300	pull --all --recurse-submodules --force: Fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/logs/refs/heads/master from [905f07da32] to [e6cfbc4beb].

1
2

0000000000000000000000000000000000000000 1cadae79fd6a99f8f96595baca45be549c351683 Martin Vahi <martin.vahi@softf1.com> 1490069948 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-authenticator.git
1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 Martin Vahi <martin.vahi@softf1.com> 1490143807 +0200	pull --recurse-submodules: Fast-forward



>
1
2
3
0000000000000000000000000000000000000000 1cadae79fd6a99f8f96595baca45be549c351683 Martin Vahi <martin.vahi@softf1.com> 1490069948 +0200	clone: from https://github.com/maidsafe/beaker-plugin-safe-authenticator.git
1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 Martin Vahi <martin.vahi@softf1.com> 1490143807 +0200	pull --recurse-submodules: Fast-forward
e953a1291995b53342460d81ffde47ca684a0b24 7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f Martin Vahi <martin.vahi@softf1.com> 1494899402 +0300	pull --all --recurse-submodules --force: Fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/logs/refs/remotes/origin/dev version [391d84290f].



>
1
5b2115692a85423ada7946ee0ad741e533e80442 0e439486e74f83d70434a4782bc4a75ec5054340 ts2 <ts2@linux-0fiz.(none)> 1494899397 +0300	pull --all --recurse-submodules --force: fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/logs/refs/remotes/origin/master from [2f7d6f8e9e] to [365e02cb4c].

1

1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 ts2 <ts2@linux-0fiz.(none)> 1490143699 +0200	pull --recurse-submodules: fast-forward


>
1
2
1cadae79fd6a99f8f96595baca45be549c351683 e953a1291995b53342460d81ffde47ca684a0b24 ts2 <ts2@linux-0fiz.(none)> 1490143699 +0200	pull --recurse-submodules: fast-forward
e953a1291995b53342460d81ffde47ca684a0b24 7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f ts2 <ts2@linux-0fiz.(none)> 1494899397 +0300	pull --all --recurse-submodules --force: fast-forward

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/FETCH_HEAD from [9e2be9f247] to [0bd037c7ec].

1
2
3
4
7919df86ba5c620d768fa194184cdf11270abf7c	not-for-merge	branch 'async' of https://github.com/maidsafe/safe_client_libs
c3df9b89239bef1d14a124b7bed0a636c4ac52ee	not-for-merge	branch 'dev' of https://github.com/maidsafe/safe_client_libs
4f695e76945e08263816a82a62fc9c3a63af6637	not-for-merge	branch 'gh-pages' of https://github.com/maidsafe/safe_client_libs
513bd44c1923ad628961ddbef504ef93dc5dd963	not-for-merge	branch 'master' of https://github.com/maidsafe/safe_client_libs

|

|
1
2
3
4
7919df86ba5c620d768fa194184cdf11270abf7c	not-for-merge	branch 'async' of https://github.com/maidsafe/safe_client_libs
590f8542a0abeaefcd144729968378bc13cdfab5	not-for-merge	branch 'dev' of https://github.com/maidsafe/safe_client_libs
4f695e76945e08263816a82a62fc9c3a63af6637	not-for-merge	branch 'gh-pages' of https://github.com/maidsafe/safe_client_libs
4efef2582cd52ea27b02c7e784e015a4ab0a7bfb	not-for-merge	branch 'master' of https://github.com/maidsafe/safe_client_libs

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/HEAD from [9a84ad1e64] to [c3f639259b].

1
28978cd10aad433332950284a49e96d881242ef9
|
1
590f8542a0abeaefcd144729968378bc13cdfab5

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/index from [7be71a14f7] to [477bd139f7].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/logs/HEAD from [ceb37a5559] to [57a2b2c382].

1
2

0000000000000000000000000000000000000000 513bd44c1923ad628961ddbef504ef93dc5dd963 Martin Vahi <martin.vahi@softf1.com> 1490070014 +0200	clone: from https://github.com/maidsafe/safe_client_libs.git
513bd44c1923ad628961ddbef504ef93dc5dd963 28978cd10aad433332950284a49e96d881242ef9 Martin Vahi <martin.vahi@softf1.com> 1490070015 +0200	checkout: moving from master to 28978cd10aad433332950284a49e96d881242ef9



>
1
2
3
0000000000000000000000000000000000000000 513bd44c1923ad628961ddbef504ef93dc5dd963 Martin Vahi <martin.vahi@softf1.com> 1490070014 +0200	clone: from https://github.com/maidsafe/safe_client_libs.git
513bd44c1923ad628961ddbef504ef93dc5dd963 28978cd10aad433332950284a49e96d881242ef9 Martin Vahi <martin.vahi@softf1.com> 1490070015 +0200	checkout: moving from master to 28978cd10aad433332950284a49e96d881242ef9
28978cd10aad433332950284a49e96d881242ef9 590f8542a0abeaefcd144729968378bc13cdfab5 Martin Vahi <martin.vahi@softf1.com> 1494899404 +0300	checkout: moving from 28978cd10aad433332950284a49e96d881242ef9 to 590f8542a0abeaefcd144729968378bc13cdfab5

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/logs/refs/remotes/origin/dev from [e5bcdea0dc] to [4d51ae54a3].

1

43f0eeeabc77f5718ca87a3e91997db0d17e5db2 c3df9b89239bef1d14a124b7bed0a636c4ac52ee ts2 <ts2@linux-0fiz.(none)> 1490143700 +0200	pull --recurse-submodules: fast-forward


>
1
2
43f0eeeabc77f5718ca87a3e91997db0d17e5db2 c3df9b89239bef1d14a124b7bed0a636c4ac52ee ts2 <ts2@linux-0fiz.(none)> 1490143700 +0200	pull --recurse-submodules: fast-forward
c3df9b89239bef1d14a124b7bed0a636c4ac52ee 590f8542a0abeaefcd144729968378bc13cdfab5 ts2 <ts2@linux-0fiz.(none)> 1494899399 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/logs/refs/remotes/origin/master version [1b21fee789].



>
1
513bd44c1923ad628961ddbef504ef93dc5dd963 4efef2582cd52ea27b02c7e784e015a4ab0a7bfb ts2 <ts2@linux-0fiz.(none)> 1494899399 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/objects/pack/pack-7e7786fbd646474f53b6bbcbe457bf64d11e3286.idx version [18b8346bd4].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/objects/pack/pack-7e7786fbd646474f53b6bbcbe457bf64d11e3286.pack version [2beca18894].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/refs/remotes/origin/dev from [0ace44983c] to [c3f639259b].

1
c3df9b89239bef1d14a124b7bed0a636c4ac52ee
|
1
590f8542a0abeaefcd144729968378bc13cdfab5

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/refs/remotes/origin/master version [8c90962689].



>
1
4efef2582cd52ea27b02c7e784e015a4ab0a7bfb

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/refs/tags/0.22.4 version [e23eff39f8].



>
1
edddb6c556269e59ac22bc61e4edfc164d74158f

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/native/refs/tags/0.23.0 version [f0e574a6c0].



>
1
cc0211eab7b183bca97c85b2857d80f6e92c35f2

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/FETCH_HEAD from [d73179b860] to [dfad5130bb].

1
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9	not-for-merge	branch 'master' of https://github.com/maidsafe/system_uri
|
1
ba75371306c1cac044c0b4d769bbaf7372240449	not-for-merge	branch 'master' of https://github.com/maidsafe/system_uri

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/HEAD from [df2b890873] to [b241696842].

1
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9
|
1
ba75371306c1cac044c0b4d769bbaf7372240449

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/index from [5018777124] to [b9a20995a4].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/logs/HEAD from [9344092d78] to [831d71fef7].

1
2

0000000000000000000000000000000000000000 adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 Martin Vahi <martin.vahi@softf1.com> 1490070017 +0200	clone: from https://github.com/maidsafe/system_uri.git
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 Martin Vahi <martin.vahi@softf1.com> 1490070017 +0200	checkout: moving from master to adf2617c98e13ac9aa69ac727f47ccb7e92b0df9



>
1
2
3
0000000000000000000000000000000000000000 adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 Martin Vahi <martin.vahi@softf1.com> 1490070017 +0200	clone: from https://github.com/maidsafe/system_uri.git
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 Martin Vahi <martin.vahi@softf1.com> 1490070017 +0200	checkout: moving from master to adf2617c98e13ac9aa69ac727f47ccb7e92b0df9
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 ba75371306c1cac044c0b4d769bbaf7372240449 Martin Vahi <martin.vahi@softf1.com> 1494899404 +0300	checkout: moving from adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 to ba75371306c1cac044c0b4d769bbaf7372240449

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/logs/refs/remotes/origin/master version [c4ae4f6823].



>
1
adf2617c98e13ac9aa69ac727f47ccb7e92b0df9 ba75371306c1cac044c0b4d769bbaf7372240449 ts2 <ts2@linux-0fiz.(none)> 1494899400 +0300	pull --all --recurse-submodules --force: fast-forward

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/03/4ca710cc27d202bd41fb988451e3c9d82c2a36 version [6c11c50ea9].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/03/ae2ca2424eab4eb1e20191cb03a62e2f3647e0 version [06c42faded].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/05/c183fbf6536d6878595eaf8fd7d2307dad212b version [9429184169].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/09/3c02e02c3b405aed0da293dd37ac9f1344102f version [641468edc1].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/11/586fe7fc0d48085d621a47d672a3e87163f175 version [bc628c598b].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/14/5a4f4a86c04c014f4b56d367b49f2345e77267 version [7b16031440].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/14/83a9940b8c67954a49c07f2b8bf01f7e6bb267 version [d769d7d64d].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/1f/7914298fd3954e352ba49d24dd077d24329bb3 version [a1104bc6be].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/20/bb6712efb89f58bc2c7b54fc76231ac4a3b5c4 version [86b901af4d].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/27/b760f46923be92f288115691bc6036f6ae7fe0 version [56a049eae9].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/2d/e7ba9ed0a9ed381a324d319187ea21d26ad6e9 version [f33799f3e4].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/2e/eedc486ab709b373bbcbff704b53d5283388c0 version [94c39628fc].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/32/c35343ba091f9db74ca812abbf5ad8d726eda0 version [797f7bae33].





>
>
1
2
x+)JMU025c040031QH,(+*f8Zq*B{">f"--N-' lJ8l$wmL8--{7;[ި;#*J+@j}QĴ'ohAMML/i/<[3]($5 '$U/%8$aJRn֣
!@Ֆg䗃M4*tX)Kzc

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/36/8d7a730e3c6940a912b7f0121214e93791e08d version [3bea1e11cc].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/38/141dd838151bc26c5b5ac0aacf83e00d685ee5 version [ccb8f54a05].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/3d/c0db27b3175771569a26b4594f93accc5a7f12 version [99b9f0e825].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/3e/29ebda13e48065e23c1274083d5e19f78a72b4 version [616e929800].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/45/1f96d334b2fd7e4d398837c35c181c59c2e423 version [646a2c88a5].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/46/d1ecec9fe06d6597f2e30871336c47371f7695 version [41756f58a7].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/53/4518ef5392d1144eb06effe02b0b415392d92b version [adc88efb93].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/54/c570ffd31176b4be1fcfe9855716ffb88ec638 version [9d8ec47768].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/61/70a113616656927372d94af97056de984d8a3f version [ebb6985b45].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/63/fa59a9accc2f919cde860c5dc34a9642c1323b version [418cc1f8ba].



>
1
xAj0E)f_peI4#yvNjܾ&7u'I3!{B Vĕ\8b2wj(0XJ$sƒGX >6A >'i7֯#9	ެg̦}SHʠ+.w]g

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/65/d2adb0a980a5ac687ab3c689a2ca8aadde0b36 version [7f9b7b8375].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/68/9894f6fc74597b621d191af5599916ab4dc479 version [35866b4438].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/69/dacae18a2ef517c9d4297ba77e604f036491f8 version [15e2584e21].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/72/aeb65f8177872b125b7df61b02f30e39009f63 version [ba4fe891a6].



>
1
xm0}OlO'T<C<8U)%MmM$ݻ"~w']UߴL~f ݓrRbj?R(kU60	H@ ~34)ZP/!ȿ]k>.\T>)_)$uȅVޏ0HIpwWjp!'|z)P	AJF0=. :ڏ}6`wB\0VpB z\^ٌoRVzvH\pߦDփ%Z5jsN S1l<g?	Jyrdn}:_̓QaQ{=>]C<XgCȫDu[5*TΉ4: TNf4u\LJc$ kSu5gL6ЪyH,*-I)<

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/77/47de09393286e8389512283ad4b47b321a0476 version [590f801109].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/78/482a89782bc185cb93f30bbd1952067b364905 version [f0f839addf].







>
>
>
1
2
3
xλN0aj?Hg2&!. %kIb9bߞ(o@s8:ϥ|כ*伞y	>
	(zaly Jӥ %Df kj)xDȵ >˥t7lsO!'/IӢFoXeޤ<µ&
Vj׾_W\

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/85/ff1d039f740decdc3d0e9d790d99f6c5a11df8 version [da4b93e9b3].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/8d/f438710b7cce5e1bf9011ee5df5508f39f1995 version [8ed5853c01].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/90/b35860cce488c9316e4ce4574b128ff2b70e34 version [b069017feb].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/94/a9ed024d3859793618152ea559a168bbcbb5e2 version [1c2d080a86].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/9f/ab8b216de1d02ff96464562687747eb89d5f9b version [fdfcd951f6].





>
>
1
2
xuON1_1GctPZ8B`Lڕ	^ɖe˶+כNDӒuKSDcF)V(PBTki=nXjHFVZeTN~-V&emjC.::f8O4|l\jҍS?lQQ
iNH!E]nڕ`;tZ?0Ք gK3"NýKOG/{yE)-41 uZu/w}2r>4s

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/a4/97e316049b2c96aafb6689b2a2955fc1104e3f version [f005efcf19].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/a5/5fe3ee72cb0f54a50ec34accaf9571b0522e2d version [f44224922e].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/a9/ee16eaf524e1baffc92b6df05a61dc72b2d650 version [b4e5c6b462].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/aa/a178d56e7156ab6ca2a41ae2216a44640d26eb version [0b2b831d94].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/af/4beb5bbcff74ac2265efc38d68dff9875de64a version [b0aa5690dc].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/b4/2fdaa28ab9a44d6fb6fdd90b14128c780ecb73 version [079fa2fa27].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/b4/9f838bbe64a2db53ddba22537f5bc51bae19c3 version [fa1574594d].





>
>
1
2
x+)JMU01`040031QK,L/JeL)ޯ7%צ3?и(,X27y"'~1N<ͼLOT_HShΥkvQ1aWڴ"\Y@;Ôo|-"+$DF.}z#Ģ||}E7kE~fg0?/ؕA$߫w-]C:0d:K+S&*J,((K/ob,uֹi~&@Z[ZŢ\OFC9>ϗ
5$-t7R?y͙z!QE wU*]wkDfܺ[!%% n߼ 7u9eSH~Q

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/b5/2909088daed20a588b57ec8b04549cc039905e version [ce8cf67251].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/b9/a5ad1ab9ee7b082c254c34023f22942582b4d1 version [b70de8220e].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/ba/75371306c1cac044c0b4d769bbaf7372240449 version [00196c6f82].





>
>
1
2
xuN0DW	lvlik:kiICI;s4Z!D䓙+N{(9\ZYhrÎR"nlZ)l-iSPFscs3J0=QKԀ]sˎi+ k+y0/>oo18cÑ;8\h_%kw``
~:\A(yza=oPۜ{t01-=Jroyrt

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/bf/f88bc78040bd8cdf18b8c1e7825bb9172c4076 version [6da08464c0].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/c1/8bc8544c33f0da0fa2ab055c04a9d35468d7b5 version [57f9a6f224].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/c3/ea4f9c18f01d4e7dd80ccc10a47edc70898ced version [9a0a7888ef].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/c6/ab465fed078bf63e3d08228d5adc40a35933b4 version [4b9efbfa27].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/cb/eb219dffcb2412a78c66596ff9eb8bc638a045 version [916f9177c9].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/d0/c7c6b5d457e4a9989e86a69295504f0ff48c53 version [6bb7bec22f].

















>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
xVnFY_1щT:vТB\ɐdAQ(+j$&ҲK/=_'Rs;3o޼,gtWg_P7/6&Y=?~P|jv&Yx6NNGUbiGv8_2Lx&1ksr9mJ=gCi܊v,c'*ʪ-$t>P<g-gdF v\^_ڵ6͹`=OnJcTs@'XdZ/Y5=Povt\l(ε3ɬt*\?Œ{]Ѳ)ݴ+\Kˌ,4xD#/E@TG3.$_64uVjKXiB,|D&dT*GWno0;~\p0/n&ю
)砊%PQ۵V	^_A/2'N%1)PރsR`쌩?nEg]fB:Qg04Iopw o7mb09}a$-`O2do딕e{z5C8Y@R-94E<jXSN0AA>%lE$KaЊؠnlZA 'Q4s2Gw+Y&>q[wp)6=ՉN)Z
獅ߛT}FlԽ N^CK1ґ=TЧ
Z)GА^FYSEFQƠu8R*)Dws?$EAC30ALPW79x,nҕiӫ"Y
ak>+҃|3MUͶbzE[]v]aЯ
*Kc9C7TM=TnUa!
Eh%| ZQO-1yןܡ'f*=<F$C+ⓓbGJcl.(^D3@3A}fxzzĿG@4Mw88(MB%̕YZYc,@ЋF.Hw<<`:*Qc^m<Аin=|M/OHLs3l\2_MiyWrlh_C^eEGu<:	`R'Sa
Jb[&&&q+~|NNoTqLp{T|댪.Xn?`3MrAR>& !“WӇx2tNFn釰>s(:oX/k<QANѷBRs  Bn1Vi76q

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/d8/83e01c3a64967da359a12ce021bcc59d2e27ea version [26f5c0101a].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/ee/19bb6a09f6622bb2ef7fed99e6bcfb503536ff version [494d61e6dd].



>
1
xuN0E#Q"_V@C_0c8xm	PRޫ{scY׹Uf מAh)*5jG$dv5ɓ6LBfzc!9>h1I,R Jȉ1zOHZ*\vnpb]Nm.yZq^cY_@ (xRh[+Ry_ܮޗ*v5r-+Vq !<Uƴ0Ð3r9,[[lI

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/f7/ba78d80a720da38e0e5ed2f55869589d7edae7 version [81d8c13727].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/objects/fd/c6244d04baf76abd0e7319238cedeac88bab0e version [89f4072eea].





>
>
1
2
xKJ1a9E1QTY{Hg; x}MiMf _$Lѣm\k$P MN]qR&kbcӴ)G9%riA
)9	_U~;ɣ\1/;w0䳶Z#T?dl_A1oZ

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/modules/system_uri/refs/remotes/origin/master version [b241696842].



>
1
ba75371306c1cac044c0b4d769bbaf7372240449

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/objects/pack/pack-b089013fb2ae5f80e1b9779b97a8552a16be0743.idx version [64fe9a040b].

cannot compute difference between binary files

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/objects/pack/pack-b089013fb2ae5f80e1b9779b97a8552a16be0743.pack version [6a384dc618].

cannot compute difference between binary files

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/refs/heads/master from [b876703f2d] to [20bbe99838].

1
e953a1291995b53342460d81ffde47ca684a0b24
|
1
7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/refs/remotes/origin/dev version [ef4c517157].



>
1
0e439486e74f83d70434a4782bc4a75ec5054340

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.git/refs/remotes/origin/master from [b876703f2d] to [20bbe99838].

1
e953a1291995b53342460d81ffde47ca684a0b24
|
1
7841d952bd4f4150b6b09c9f80a1ebd9e9a5093f

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/.travis.yml from [762430ed0a] to [5b174339fe].

28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
      - g++-4.8
cache:
  cargo: true
  directories:
    - node_modules

before_install:
  - curl -s https://static.rust-lang.org/rustup.sh > rustup.sh && sh rustup.sh --prefix=~/rust --spec=1.14.0 -y --disable-sudo
  - "[[ ${TRAVIS_OS_NAME} = linux ]] && export CXX=g++-4.8 || echo 'skipped'"

install:
  - node --version
  - npm --version
  - npm i

before_script:
  - npm run build-libs:mock
  - npm run copy-binaries:unix
  - npm run grep-error-codes

script:
  - npm run lint
  - npm test







|








|
<





28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
      - g++-4.8
cache:
  cargo: true
  directories:
    - node_modules

before_install:
  - curl -s https://static.rust-lang.org/rustup.sh > rustup.sh && sh rustup.sh --prefix=~/rust --spec=1.17.0 -y --disable-sudo
  - "[[ ${TRAVIS_OS_NAME} = linux ]] && export CXX=g++-4.8 || echo 'skipped'"

install:
  - node --version
  - npm --version
  - npm i

before_script:
  - travis_wait 30 npm run build-libs -- --features="mock-routing" --clean

  - npm run grep-error-codes

script:
  - npm run lint
  - npm test

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/README.md from [d00b690d1e] to [fae4fc0c6e].

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19




20
21




22




23
24
25
26








27
28
29
30
31
32
33

SAFE Authenticator plugin for SAFE Browser.

|Linux/OS X|Windows|
|:---:|:--------:|
|[![Build Status](https://travis-ci.org/maidsafe/beaker-plugin-safe-authenticator.svg?branch=master)](https://travis-ci.org/maidsafe/beaker-plugin-safe-authenticator)|[![Build status](https://ci.appveyor.com/api/projects/status/04100mp7gtjnr3c1/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/beaker-plugin-safe-authenticator/branch/master)|


## Dependency

This project depends on [safe_client_libs](https://github.com/maidsafe/safe_client_libs). The dependency is specified as a git submodule.

## Development

Rust and Node.js are required for development.





1. Clone the project
2. Run `git submodule update --init`




3. Run `npm install` to install the Node.js dependencies




4. Build the native modules `npm run build-native-mock && npm run build-system-uri`
5. `npm run build` will build the project to the `dist` folder

In [safe_browser](https://github.com/maidsafe/safe_browser/) `app/node_modules`, create a folder called `beaker-plugin-safe-authenticator` and add the `index.js` file and the `dist` folder obtained after building the plugin.









# License

Licensed under either of

* the MaidSafe.net Commercial License, version 1.0 or later ([LICENSE](LICENSE))
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)







<


|



|

>
>
>
>

<
>
>
>
>
|
>
>
>
>
|
<
|
<
>
>
>
>
>
>
>
>







4
5
6
7
8
9
10

11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33

34

35
36
37
38
39
40
41
42
43
44
45
46
47
48
49

SAFE Authenticator plugin for SAFE Browser.

|Linux/OS X|Windows|
|:---:|:--------:|
|[![Build Status](https://travis-ci.org/maidsafe/beaker-plugin-safe-authenticator.svg?branch=master)](https://travis-ci.org/maidsafe/beaker-plugin-safe-authenticator)|[![Build status](https://ci.appveyor.com/api/projects/status/04100mp7gtjnr3c1/branch/master?svg=true)](https://ci.appveyor.com/project/MaidSafe-QA/beaker-plugin-safe-authenticator/branch/master)|


## Dependency

This project depends on [safe_client_libs](https://github.com/maidsafe/safe_client_libs) and [system_uri](https://github.com/maidsafe/system_uri). The dependencies are specified as git submodule.

## Development

### Prerequisites

  * Node.js 6.5.0 (we recommend installing it via [nvm](https://github.com/creationix/nvm))
  * Rust stable (we recommend installing it from [rust-lang.org](https://www.rust-lang.org/en-US/))
  * [Git](https://git-scm.com/)

1. Clone the project

    ```bash
    $ git clone https://github.com/maidsafe/beaker-plugin-safe-authenticator.git
    ```

2. Install the Node.js dependencies.
    ```bash
    $ npm i
    ```

3. Build the native modules

   

   ```
   $ npm run build-libs
   ``` 
   > Add `--` before using following options.
   * If you specify `--features=mock-routing` binary will use mock routing or else actual routing will be used.
   * If you specify `--clean`, will clean all the cargo dependencies installed and do a fresh build. To manually clean the dependencies run `npm run clean-libs`.
   
4. `npm run build` will build the project to the `dist` folder.

# License

Licensed under either of

* the MaidSafe.net Commercial License, version 1.0 or later ([LICENSE](LICENSE))
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/appveyor.yml from [f7d0d24123] to [147fa9628e].

1
2
3
4
5
6
7
8
9
10
11
12
13
..
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
environment:
  nodejs_version: "6.9.1"
  global:
    RUST_BACKTRACE: 1
  matrix:
    - RUST_VERSION: 1.14.0

platform:
  - x86
  - x64

cache:
  - node_modules
................................................................................
  - Release

install:
  - ps: Install-Product node $env:nodejs_version $env:platform
  - node --version
  - npm --version
  - ps: |
          $url = "https://github.com/maidsafe/QA/raw/master/Powershell%20Scripts/AppVeyor"
          cmd /c curl -fsSL -o "Install Rustup.ps1" "$url/Install%20Rustup.ps1"
          . ".\Install Rustup.ps1"
  - ps: cd $env:APPVEYOR_BUILD_FOLDER
  - git submodule update --init --recursive
  - npm i

build: off

before_test:
  - npm run build-libs:mock
  - npm run copy-binaries:win
  - npm run grep-error-codes
  - ps: |
          if($env:platform -eq "x86") {
            Copy-Item C:\MinGW\bin\pthreadGC*.dll $env:APPVEYOR_BUILD_FOLDER\src\ffi\libwinpthread-1.dll -Force
          } Else {
            Copy-Item C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin\libwinpthread-1.dll $env:APPVEYOR_BUILD_FOLDER\src\ffi -Force
          }

test_script:
  - npm run lint
  - npm test





|







 







|
|
|







|
<











1
2
3
4
5
6
7
8
9
10
11
12
13
..
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38

39
40
41
42
43
44
45
46
47
48
49
environment:
  nodejs_version: "6.9.1"
  global:
    RUST_BACKTRACE: 1
  matrix:
    - RUST_VERSION: 1.17.0

platform:
  - x86
  - x64

cache:
  - node_modules
................................................................................
  - Release

install:
  - ps: Install-Product node $env:nodejs_version $env:platform
  - node --version
  - npm --version
  - ps: |
          $url = "https://github.com/maidsafe/QA/raw/master/appveyor/install_rustup.ps1"
          Invoke-WebRequest $url -OutFile "install_rustup.ps1"
          . ".\install_rustup.ps1"
  - ps: cd $env:APPVEYOR_BUILD_FOLDER
  - git submodule update --init --recursive
  - npm i

build: off

before_test:
  - npm run build-libs -- --features="mock-routing" --clean

  - npm run grep-error-codes
  - ps: |
          if($env:platform -eq "x86") {
            Copy-Item C:\MinGW\bin\pthreadGC*.dll $env:APPVEYOR_BUILD_FOLDER\src\ffi\libwinpthread-1.dll -Force
          } Else {
            Copy-Item C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin\libwinpthread-1.dll $env:APPVEYOR_BUILD_FOLDER\src\ffi -Force
          }

test_script:
  - npm run lint
  - npm test

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/build_libs.js version [21180b5609].











































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
const spawn = require('child_process').spawn;
const os = require('os');

const osPlatform = os.platform();
let params = {};

const runSpawn = (title, cmdStr) => (
  new Promise((resolve) => {
    cmdStr = cmdStr.split(' ');
    if (osPlatform === 'win32') {
      cmdStr[0] += '.cmd';
    }
    const build = spawn(cmdStr[0], cmdStr.slice(1));

    build.stdout.on('data', (data) => {
      console.warn(data.toString());
    });

    build.stderr.on('data', (data) => {
      console.error(data.toString());
    });

    build.on('close', (code) => {
      console.warn(`${title} exited with code ${code}`);
      if (code !== 0) {
        process.exit(code);
        return;
      }
      resolve();
    });
  })
);

const parseCmdParams = () => {
  const argv = process.argv;
  const features = argv.filter((e) => (e.indexOf('--features') !== -1))
    .toString()
    .split('=')
    .slice(1)
    .toString();
  const cleanLibs = (argv.indexOf('--clean') !== -1);
  params = {
    features,
    cleanLibs
  };
};

const cleanLibs = () => {
  const cmd = 'npm run clean-libs';
  if (!params.cleanLibs) {
    return Promise.resolve(true);
  }
  return runSpawn('Cleaning native modules', cmd);
};

const buildAuthenticator = () => {
  const cmd = `npm run build-libs:${(params.features === 'mock-routing') ? 'mock' : 'actual'}`;
  return runSpawn('Build Authenticator', cmd);
};

const copyLibs = () => {
  const cmd = `npm run copy-binaries:${(osPlatform === 'win32') ? 'win' : 'unix'}`;
  return runSpawn('Copy Authenticator files', cmd);
};

parseCmdParams();
cleanLibs()
  .then(() => buildAuthenticator())
  .then(() => copyLibs());

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/locales/en.json from [4d61977548] to [18ee59a057].

5
6
7
8
9
10
11

12
13
14
15
16
17
18
..
27
28
29
30
31
32
33
34

35
36
37
38
39
40
41
42
43
44
45
46
47
48

49
50
  "Secret": "Secret",
  "Client handle key": "Client handle key",
  "Client handle": "Client handle",
  "AppId": "AppId",
  "URL": "URL",
  "Account Secret": "Account Secret",
  "Account Password": "Account Password",

  "Login": "Login",
  "Create Account": "Create Account",
  "Back": "Back",
  "Continue": "Continue",
  "Ok": "Ok",
  "Cancel": "Cancel",
  "Don't have a account?": "Don't have a account?",
................................................................................
  "No Apps Found": "No Apps Found",
  "loginFailed": "Failed to login user",
  "createAccFailed": "Failed to create user account",
  "AuthIntro": {
    "desc": {
      "welcome": "Authenticator will act as your gateway to the SAFE Network, you can use it to access data on the network and to authorise apps to connect on your behalf.",
      "secret": "Your 'account secret' is private and should not be shared with anyone.",
      "password": "Your 'account password' is never stored or transmitted, it will not leave your computer."

    }
  },
  "invalid_network_state": "Invalid network state",
  "entries_mismatch": "Entries don't match.",
  "messages": {
    "must_be_function": "%s must be a function",
    "must_be_string": "%s must be string",
    "should_not_be_empty": "%s should not be empty",
    "key_not_found": "%s key not found",
    "unauthorised": "Unauthorised",
    "need_to_be_stronger": "%{name} needs to be stronger",
    "plugin_not_found": "%{name} plugin not found",
    "invalid_params": "Invalid params",
    "invalid_req": "Invalid Request"

  }
}







>







 







|
>













|
>


5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
  "Secret": "Secret",
  "Client handle key": "Client handle key",
  "Client handle": "Client handle",
  "AppId": "AppId",
  "URL": "URL",
  "Account Secret": "Account Secret",
  "Account Password": "Account Password",
  "Invite Code": "Invite Code",
  "Login": "Login",
  "Create Account": "Create Account",
  "Back": "Back",
  "Continue": "Continue",
  "Ok": "Ok",
  "Cancel": "Cancel",
  "Don't have a account?": "Don't have a account?",
................................................................................
  "No Apps Found": "No Apps Found",
  "loginFailed": "Failed to login user",
  "createAccFailed": "Failed to create user account",
  "AuthIntro": {
    "desc": {
      "welcome": "Authenticator will act as your gateway to the SAFE Network, you can use it to access data on the network and to authorise apps to connect on your behalf.",
      "secret": "Your 'account secret' is private and should not be shared with anyone.",
      "password": "Your 'account password' is never stored or transmitted, it will not leave your computer.",
      "inviteCode": "Enter an invitation token or click on the 'Claim an invitation' button."
    }
  },
  "invalid_network_state": "Invalid network state",
  "entries_mismatch": "Entries don't match.",
  "messages": {
    "must_be_function": "%s must be a function",
    "must_be_string": "%s must be string",
    "should_not_be_empty": "%s should not be empty",
    "key_not_found": "%s key not found",
    "unauthorised": "Unauthorised",
    "need_to_be_stronger": "%{name} needs to be stronger",
    "plugin_not_found": "%{name} plugin not found",
    "invalid_params": "Invalid params",
    "invalid_req": "Invalid Request",
    "invalid_invite_code": "Invalid Invite code"
  }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/.travis.yml from [f0e4eca5f0] to [d9a67cceed].

5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    - PATH=$PATH:$HOME/.cargo/bin
os:
  - linux
  - osx
language: rust
rust:
  - stable
  - nightly-2016-11-17
sudo: false
branches:
  only:
    - master
    - dev
cache:
  cargo: true
................................................................................

before_script:
  - (which cargo-install-update && cargo install-update cargo-update) || cargo install cargo-update
  - (which cargo-prune && cargo install-update cargo-prune) || cargo install cargo-prune
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
      (which rustfmt && cargo install-update rustfmt) || cargo install rustfmt;
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      clippy_vers=0.0.99;
      if ! cargo clippy --version | grep -q $clippy_vers; then
        cargo install clippy --vers=$clippy_vers --force;
      fi
    fi
script:
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
        (
................................................................................
            cargo fmt -- --write-mode=diff &&
            echo "--- Test ffi_utils ---" &&
            cd ../ffi_utils &&
            cargo test  --verbose --release &&
            echo "--- Check compilation against actual routing ---" &&
            cd ../safe_core &&
            cargo rustc --verbose --release &&
            cargo rustc --verbose --features testing --release -- --test -Zno-trans &&
            cd ../safe_app &&
            cargo rustc --verbose --features testing --release -- --test -Zno-trans &&
            cd ../safe_authenticator &&
            cargo rustc --verbose --features testing --release -- --test -Zno-trans &&
            echo "--- Test against mock ---" &&
            cd ../safe_core &&
            cargo test --verbose --release --features "$Features" &&
            cd ../safe_app &&
            cargo test --verbose --release --features "$Features" &&
            cd ../safe_authenticator &&
            cargo test --verbose --release --features "$Features";
        );
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
        (
            set -x;
            cd ffi_utils && unset Features && cargo clippy && cargo clippy --profile=test && export Features="use-mock-routing testing" &&
            cd ../safe_core && cargo clippy && cargo clippy --profile=test --features="$Features" &&
            cd ../safe_app && cargo clippy && cargo clippy --profile=test --features="$Features" &&
            cd ../safe_authenticator && cargo clippy && cargo clippy --profile=test --features="$Features";
        )
    fi
before_cache:
  - cargo prune







|







 







|







 







|

|

|













|
|




5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
..
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
    - PATH=$PATH:$HOME/.cargo/bin
os:
  - linux
  - osx
language: rust
rust:
  - stable
  - nightly-2017-04-28
sudo: false
branches:
  only:
    - master
    - dev
cache:
  cargo: true
................................................................................

before_script:
  - (which cargo-install-update && cargo install-update cargo-update) || cargo install cargo-update
  - (which cargo-prune && cargo install-update cargo-prune) || cargo install cargo-prune
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
      (which rustfmt && cargo install-update rustfmt) || cargo install rustfmt;
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
      clippy_vers=0.0.128;
      if ! cargo clippy --version | grep -q $clippy_vers; then
        cargo install clippy --vers=$clippy_vers --force;
      fi
    fi
script:
  - if [ "${TRAVIS_RUST_VERSION}" = stable ]; then
        (
................................................................................
            cargo fmt -- --write-mode=diff &&
            echo "--- Test ffi_utils ---" &&
            cd ../ffi_utils &&
            cargo test  --verbose --release &&
            echo "--- Check compilation against actual routing ---" &&
            cd ../safe_core &&
            cargo rustc --verbose --release &&
            cargo rustc --verbose --features testing --release --profile test --lib -- -Zno-trans &&
            cd ../safe_app &&
            cargo rustc --verbose --features testing --release --profile test --lib -- -Zno-trans &&
            cd ../safe_authenticator &&
            cargo rustc --verbose --features testing --release --profile test --lib -- -Zno-trans &&
            echo "--- Test against mock ---" &&
            cd ../safe_core &&
            cargo test --verbose --release --features "$Features" &&
            cd ../safe_app &&
            cargo test --verbose --release --features "$Features" &&
            cd ../safe_authenticator &&
            cargo test --verbose --release --features "$Features";
        );
    elif [ "${TRAVIS_OS_NAME}" = linux ]; then
        (
            set -x;
            cd ffi_utils && unset Features && cargo clippy && cargo clippy --profile=test && export Features="use-mock-routing testing" &&
            cd ../safe_core && cargo clippy && cargo clippy --profile=test --features="$Features" &&
            cd ../safe_app && cargo clippy --profile=test --features="$Features" &&
            cd ../safe_authenticator && cargo clippy --profile=test --features="$Features";
        )
    fi
before_cache:
  - cargo prune

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/Cargo.toml from [a0dc5fa8c6] to [2de94f4370].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# Copyright 2016 MaidSafe.net limited.
#
# This SAFE Network Software is licensed to you under (1) the MaidSafe.net
# Commercial License, version 1.0 or later, or (2) The General Public License
# (GPL), version 3, depending on which licence you accepted on initial access
# to the Software (the "Licences").
#
# By contributing code to the SAFE Network Software, or to this project
# generally, you agree to be bound by the terms of the MaidSafe Contributor
# Agreement, version 1.0.  This, along with the Licenses can be found in the
# root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
#
# Unless required by applicable law or agreed to in writing, the SAFE Network
# Software distributed under the GPL Licence is distributed on an "AS IS"
# BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
# implied.
#
# Please review the Licences for the specific language governing permissions
# and limitations relating to use of the SAFE Network Software.

[workspace]
members = ["ffi_utils", "safe_app", "safe_authenticator", "safe_core"]


|
|
<
|

|
|
<
|

|
|
|
<

|
|



1
2
3
4

5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
# Copyright 2016 MaidSafe.net limited.
#
# This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
# version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

# licence you accepted on initial access to the Software (the "Licences").
#
# By contributing code to the SAFE Network Software, or to this project generally, you agree to be
# bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be

# found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
#
# Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
# under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.

#
# Please review the Licences for the specific language governing permissions and limitations
# relating to use of the SAFE Network Software.

[workspace]
members = ["ffi_utils", "safe_app", "safe_authenticator", "safe_core"]

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/README.md from [3483ad2bbd] to [3f55b3dc85].

24
25
26
27
28
29
30
31
32
33
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement, version 1.1 ([CONTRIBUTOR]
(CONTRIBUTOR)), shall be dual licensed as above, and you agree to be bound by the terms of the
MaidSafe Contributor Agreement, version 1.1.







|
|
<
24
25
26
27
28
29
30
31
32

* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement ([CONTRIBUTOR](CONTRIBUTOR)), shall be
dual licensed as above, and you agree to be bound by the terms of the MaidSafe Contributor Agreement.

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/appveyor.yml from [9f848c80dc] to [93e8cedaa9].

5
6
7
8
9
10
11




12
13
14
15
16
17
18
19
20
21
22



23
24
25
26
27
28
29
30
31
32
33
34
35
36
    - RUST_VERSION: stable

branches:
  only:
    - master
    - dev





clone_depth: 1

install:
  - ps: |
        $url = "https://github.com/maidsafe/QA/raw/master/Powershell%20Scripts/AppVeyor"
        cmd /c curl -fsSL -o "Install Rustup.ps1" "$url/Install%20Rustup.ps1"
        . ".\Install Rustup.ps1"

platform:
  - x86
  - x64




build_script:
  - |-
    cd ffi_utils && cargo build --verbose --release
    cd ..\safe_core && cargo rustc --verbose --release --features testing -- --test -Zno-trans
    cd ..\safe_app && cargo rustc --verbose --release --features testing -- --test -Zno-trans
    cd ..\safe_authenticator && cargo rustc --verbose --features testing --release -- --test -Zno-trans

test_script:
  - |-
    cd ..\ffi_utils && cargo test --verbose --release
    cd ..\safe_core && cargo test --verbose --release --features "use-mock-routing testing"
    cd ..\safe_app && cargo test --verbose --release --features "use-mock-routing testing"
    cd ..\safe_authenticator && cargo test --verbose --release --features "use-mock-routing testing"







>
>
>
>




|
|
|




>
>
>




|
|
|







5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
    - RUST_VERSION: stable

branches:
  only:
    - master
    - dev

cache:
  - '%USERPROFILE%\.cargo'
  - '%APPVEYOR_BUILD_FOLDER%\target'

clone_depth: 1

install:
  - ps: |
        $url = "https://github.com/maidsafe/QA/raw/master/appveyor/install_rustup.ps1"
        Invoke-WebRequest $url -OutFile "install_rustup.ps1"
        . ".\install_rustup.ps1"

platform:
  - x86
  - x64

configuration:
  - Release

build_script:
  - |-
    cd ffi_utils && cargo build --verbose --release
    cd ..\safe_core && cargo rustc --verbose --release --features testing --profile test --lib -- -Zno-trans
    cd ..\safe_app && cargo rustc --verbose --release --features testing --profile test --lib -- -Zno-trans
    cd ..\safe_authenticator && cargo rustc --verbose --features testing --release --profile test --lib -- -Zno-trans

test_script:
  - |-
    cd ..\ffi_utils && cargo test --verbose --release
    cd ..\safe_core && cargo test --verbose --release --features "use-mock-routing testing"
    cd ..\safe_app && cargo test --verbose --release --features "use-mock-routing testing"
    cd ..\safe_authenticator && cargo test --verbose --release --features "use-mock-routing testing"

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/examples/client_stress_test.rs from [8c5f3e1866] to [a09bf57a52].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0. This, along with the Licenses can be found in the
// root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Safe client example.

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, clippy_pedantic))]
#![cfg_attr(feature="clippy", allow(use_debug, print_stdout))]

/*

extern crate docopt;
extern crate futures;
extern crate rand;
extern crate routing;


|
|
<
|

|
|
<
|

|
|
|
<

|
|







 







<
<
|
|







1
2
3
4

5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be

// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Safe client example.

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]



#![cfg_attr(feature="cargo-clippy", deny(clippy, clippy_pedantic))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, print_stdout))]

/*

extern crate docopt;
extern crate futures;
extern crate rand;
extern crate routing;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/examples/email.rs from [43ce631446] to [b41e809877].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0. This, along with the Licenses can be found in the
// root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Email Example

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                   option_unwrap_used))]
#![cfg_attr(feature="clippy", allow(use_debug, doc_markdown))]

/*

#[macro_use]
extern crate maidsafe_utilities;
#[macro_use]
extern crate unwrap;


|
|
<
|

|
|
<
|

|
|
|
<

|
|







 







<
<
|

|







1
2
3
4

5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
44
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be

// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Email Example

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]



#![cfg_attr(feature="cargo-clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                   option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, doc_markdown))]

/*

#[macro_use]
extern crate maidsafe_utilities;
#[macro_use]
extern crate unwrap;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/examples/email_stress_test.rs from [ca895d6c5c] to [a0d56bdbcc].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
31
32
33
34
35
36
37
38
39
40
41

42
43
44
45
46
47
48
49
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0. This, along with the Licenses can be found in the
// root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Email Stress Test

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                   option_unwrap_used))]

#![cfg_attr(feature="clippy", allow(use_debug, doc_markdown))] // TODO: Fix doc_markdown errors.

/*

#[macro_use]
extern crate log;
#[macro_use]
extern crate unwrap;


|
|
<
|

|
|
<
|

|
|
|
<

|
|







 







<
<
|

>
|







1
2
3
4

5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
44
45
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be

// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Email Stress Test

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]



#![cfg_attr(feature="cargo-clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                   option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, doc_markdown))]
// TODO: Fix doc_markdown errors.

/*

#[macro_use]
extern crate log;
#[macro_use]
extern crate unwrap;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/examples/self_authentication.rs from [2960773b1f] to [4a293bb92f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
..
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0. This, along with the Licenses can be found in the
// root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Self-authentication example.

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="clippy", feature(plugin))]
#![cfg_attr(feature="clippy", plugin(clippy))]
#![cfg_attr(feature="clippy", deny(clippy, clippy_pedantic))]
#![cfg_attr(feature="clippy", allow(use_debug, print_stdout))]

/*

extern crate safe_core;
#[macro_use]
extern crate maidsafe_utilities;
extern crate routing;


|
|
<
|

|
|
<
|

|
|
|
<

|
|







 







<
<
|
|







1
2
3
4

5
6
7
8

9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
28
29
30
31
32
33
34


35
36
37
38
39
40
41
42
43
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be

// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Self-authentication example.

// For explanation of lint checks, run `rustc -W help` or see
// https://github.
// com/maidsafe/QA/blob/master/Documentation/Rust%20Lint%20Checks.md
#![forbid(bad_style, exceeding_bitshifts, mutable_transmutes, no_mangle_const_items,
................................................................................
        unknown_lints, unsafe_code, unused, unused_allocation, unused_attributes,
        unused_comparisons, unused_features, unused_parens, while_true)]
#![warn(trivial_casts, trivial_numeric_casts, unused_extern_crates, unused_import_braces,
        unused_qualifications, unused_results)]
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]



#![cfg_attr(feature="cargo-clippy", deny(clippy, clippy_pedantic))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, print_stdout))]

/*

extern crate safe_core;
#[macro_use]
extern crate maidsafe_utilities;
extern crate routing;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/Cargo.toml from [e91f8d5798] to [85de22076e].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
[package]
authors = ["MaidSafe Developers <dev@maidsafe.net>"]
description = "FFI utilities"
documentation = "https://docs.rs/ffi_utils"
homepage = "http://maidsafe.net"
license = "GPL-3.0"
name = "ffi_utils"
readme = "README.md"
repository = "https://github.com/maidsafe/safe_client_libs"
version = "0.1.0"

[dependencies]
log = "~0.3.6"
# TODO rand is only used by tests but putting it as dev-dependency fails to compile with
# cargo rustc --release --features clippy --verbose -- --test -Zno-trans
# cargo rustc --release -- --test -Zno-trans
# See if this is a bug with using `cargo rustc` instead of normal cargo tests and if so
# file a bug report and track it.
rand = "~0.3.14"
rustc-serialize = "~0.3.22"
unwrap = "~1.1.0"




|







|
|
|
|
|
|
|
|
<
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20

[package]
authors = ["MaidSafe Developers <dev@maidsafe.net>"]
description = "FFI utilities"
documentation = "https://docs.rs/ffi_utils"
homepage = "https://maidsafe.net"
license = "GPL-3.0"
name = "ffi_utils"
readme = "README.md"
repository = "https://github.com/maidsafe/safe_client_libs"
version = "0.1.0"

[dependencies]
base64 = "~0.4.1"
log = "~0.3.7"
serde = "~0.9.12"
serde_derive = "~0.9.12"
unwrap = "~1.1.0"

[dev-dependencies]
rand = "~0.3.15"

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/README.md from [4562155c0f] to [4759b553ec].

22
23
24
25
26
27
28
29
30
31
32
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement, version 1.1 ([CONTRIBUTOR]
(CONTRIBUTOR)), shall be dual licensed as above, and you agree to be bound by the terms of the
MaidSafe Contributor Agreement, version 1.1.
TODO: write this README.







|
|
<
<
22
23
24
25
26
27
28
29
30


* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement ([CONTRIBUTOR](CONTRIBUTOR)), shall be
dual licensed as above, and you agree to be bound by the terms of the MaidSafe Contributor Agreement.


Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/base64.rs from [4cd61ab5ed] to [aa9ed3c680].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use rustc_serialize::base64::{CharacterSet, Config, FromBase64, FromBase64Error, Newline, ToBase64};


/// Encode the data using base64 encoding.
pub fn base64_encode(input: &[u8]) -> String {
    input.to_base64(config())
}

/// Decode base64 encoded data.
pub fn base64_decode(input: &str) -> Result<Vec<u8>, FromBase64Error> {
    input.from_base64()
}

#[inline]
fn config() -> Config {
    Config {
        char_set: CharacterSet::UrlSafe,
        newline: Newline::LF,
        pad: true,
        line_length: None,
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|

<
>



|



|
|

<
<
<
<
<
<
<
<
<
<
1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17

18
19
20
21
22
23
24
25
26
27
28










// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.


use b64::{self, Base64Error, URL_SAFE};

/// Encode the data using base64 encoding.
pub fn base64_encode(input: &[u8]) -> String {
    b64::encode_config(input, URL_SAFE)
}

/// Decode base64 encoded data.
pub fn base64_decode(input: &str) -> Result<Vec<u8>, Base64Error> {
    b64::decode_config(input, URL_SAFE)
}










Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/callback.rs from [6c9bb40892] to [d5af308b42].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Helpers to work with extern "C" callbacks.


use std::os::raw::c_void;
use std::ptr;

/// This trait allows us to treat callbacks with different number and type of
/// arguments uniformly.
pub trait Callback {
    /// Arguments for the callback. Should be a tuple.
    type Args: CallbackArgs;

    /// Call the callback, passing the user data pointer, error code and any
    /// additional arguments.
    fn call(&self, user_data: *mut c_void, error: i32, args: Self::Args);
}

impl Callback for extern "C" fn(*mut c_void, i32) {
    type Args = ();
    fn call(&self, user_data: *mut c_void, error: i32, _args: Self::Args) {
        self(user_data, error)
    }
}

impl<T: CallbackArgs> Callback for extern "C" fn(*mut c_void, i32, a: T) {
    type Args = T;
    fn call(&self, user_data: *mut c_void, error: i32, args: Self::Args) {
        self(user_data, error, args)
    }
}

impl<T0: CallbackArgs, T1: CallbackArgs> Callback
    for extern "C" fn(*mut c_void, i32, a0: T0, a1: T1) {
    type Args = (T0, T1);
    fn call(&self, user_data: *mut c_void, error: i32, args: Self::Args) {
        self(user_data, error, args.0, args.1)
    }
}

impl<T0: CallbackArgs, T1: CallbackArgs, T2: CallbackArgs> Callback
    for extern "C" fn(*mut c_void, i32, a0: T0, a1: T1, a2: T2) {
    type Args = (T0, T1, T2);
    fn call(&self, user_data: *mut c_void, error: i32, args: Self::Args) {
        self(user_data, error, args.0, args.1, args.2)
    }
}

/// Trait for arguments to callbacks. This is similar to `Default`, but allows
/// us to implement it for foreign types that don't already implement `Default`.
pub trait CallbackArgs {


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|



>











|


|

|




|

|





|

|





|

|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Helpers to work with extern "C" callbacks.

use super::FfiResult;
use std::os::raw::c_void;
use std::ptr;

/// This trait allows us to treat callbacks with different number and type of
/// arguments uniformly.
pub trait Callback {
    /// Arguments for the callback. Should be a tuple.
    type Args: CallbackArgs;

    /// Call the callback, passing the user data pointer, error code and any
    /// additional arguments.
    fn call(&self, user_data: *mut c_void, error: FfiResult, args: Self::Args);
}

impl Callback for extern "C" fn(*mut c_void, FfiResult) {
    type Args = ();
    fn call(&self, user_data: *mut c_void, error: FfiResult, _args: Self::Args) {
        self(user_data, error)
    }
}

impl<T: CallbackArgs> Callback for extern "C" fn(*mut c_void, FfiResult, a: T) {
    type Args = T;
    fn call(&self, user_data: *mut c_void, error: FfiResult, args: Self::Args) {
        self(user_data, error, args)
    }
}

impl<T0: CallbackArgs, T1: CallbackArgs> Callback
    for extern "C" fn(*mut c_void, FfiResult, a0: T0, a1: T1) {
    type Args = (T0, T1);
    fn call(&self, user_data: *mut c_void, error: FfiResult, args: Self::Args) {
        self(user_data, error, args.0, args.1)
    }
}

impl<T0: CallbackArgs, T1: CallbackArgs, T2: CallbackArgs> Callback
    for extern "C" fn(*mut c_void, FfiResult, a0: T0, a1: T1, a2: T2) {
    type Args = (T0, T1, T2);
    fn call(&self, user_data: *mut c_void, error: FfiResult, args: Self::Args) {
        self(user_data, error, args.0, args.1, args.2)
    }
}

/// Trait for arguments to callbacks. This is similar to `Default`, but allows
/// us to implement it for foreign types that don't already implement `Default`.
pub trait CallbackArgs {

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/catch_unwind.rs from [97e2e65d01] to [a378d1d009].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
..
40
41
42
43
44
45
46

47
48
49
50
51
52
53

54

55


56
57
58
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use super::ErrorCode;
use super::callback::{Callback, CallbackArgs};
use std::fmt::Debug;
use std::os::raw::c_void;
use std::panic::{self, AssertUnwindSafe};

fn catch_unwind_result<'a, F, T, E>(f: F) -> Result<T, E>
    where F: FnOnce() -> Result<T, E>,
          E: Debug + From<&'a str>
{
................................................................................
    where F: FnOnce() -> Result<(), E>,
          E: Debug + ErrorCode + From<&'a str>
{
    ffi_result_code!(catch_unwind_result(f))
}

/// Catch panics. On error call the callback.

pub fn catch_unwind_cb<'a, U, C, F, E>(user_data: U, cb: C, f: F)
    where U: Into<*mut c_void>,
          C: Callback,
          F: FnOnce() -> Result<(), E>,
          E: Debug + ErrorCode + From<&'a str>
{
    if let Err(err) = catch_unwind_result(f) {

        cb.call(user_data.into(),

                ffi_error_code!(err),


                CallbackArgs::default());
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|

|

|







 







>




|


>

>
|
>
>



1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use super::{ErrorCode, FfiResult};
use super::callback::{Callback, CallbackArgs};
use std::fmt::{Debug, Display};
use std::os::raw::c_void;
use std::panic::{self, AssertUnwindSafe};

fn catch_unwind_result<'a, F, T, E>(f: F) -> Result<T, E>
    where F: FnOnce() -> Result<T, E>,
          E: Debug + From<&'a str>
{
................................................................................
    where F: FnOnce() -> Result<(), E>,
          E: Debug + ErrorCode + From<&'a str>
{
    ffi_result_code!(catch_unwind_result(f))
}

/// Catch panics. On error call the callback.
#[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
pub fn catch_unwind_cb<'a, U, C, F, E>(user_data: U, cb: C, f: F)
    where U: Into<*mut c_void>,
          C: Callback,
          F: FnOnce() -> Result<(), E>,
          E: Debug + Display + ErrorCode + From<&'a str>
{
    if let Err(err) = catch_unwind_result(f) {
        let (error_code, description) = ffi_result!(Err::<(), E>(err));
        cb.call(user_data.into(),
                FfiResult {
                    error_code,
                    description: description.as_ptr(),
                },
                CallbackArgs::default());
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/lib.rs from [2e695036e4] to [1daab6ce0f].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
41
42
43
44
45
46
47

48
49

50
51
52
53
54
55
56
57
..
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
..
81
82
83
84
85
86
87















// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI utilities

#![doc(html_logo_url =
           "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png",
       html_favicon_url = "http://maidsafe.net/img/favicon.ico",
       html_root_url = "http://maidsafe.github.io/ffi_utils")]
................................................................................
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="cargo-clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                         option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, too_many_arguments))]


#[macro_use]
extern crate log;

extern crate rustc_serialize;
#[macro_use]
extern crate unwrap;

#[macro_use]
mod macros;
mod base64;
mod catch_unwind;
................................................................................
pub mod test_utils;
pub mod string;

pub use self::base64::{base64_decode, base64_encode};
pub use self::catch_unwind::{catch_unwind_cb, catch_unwind_error_code};
pub use self::repr_c::ReprC;
pub use self::string::{StringError, from_c_str};
pub use self::vec::{vec_clone_from_raw_parts, vec_into_raw_parts};
use std::os::raw::c_void;

/// Type that holds opaque user data handed into FFI functions
#[derive(Clone, Copy)]
pub struct OpaqueCtx(pub *mut c_void);
unsafe impl Send for OpaqueCtx {}

impl Into<*mut c_void> for OpaqueCtx {
................................................................................
}

/// Trait for types that can be converted to integer error code.
pub trait ErrorCode {
    /// Return the error code corresponding to this instance.
    fn error_code(&self) -> i32;
}

















|
|
<
|

|
|
<
<
|

|
|
|
<

|
|







 







>


>
|







 







|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
..
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
..
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI utilities

#![doc(html_logo_url =
           "https://raw.githubusercontent.com/maidsafe/QA/master/Images/maidsafe_logo.png",
       html_favicon_url = "http://maidsafe.net/img/favicon.ico",
       html_root_url = "http://maidsafe.github.io/ffi_utils")]
................................................................................
#![allow(box_pointers, fat_ptr_transmutes, missing_copy_implementations,
         missing_debug_implementations, variant_size_differences)]

#![cfg_attr(feature="cargo-clippy", deny(clippy, unicode_not_nfc, wrong_pub_self_convention,
                                         option_unwrap_used))]
#![cfg_attr(feature="cargo-clippy", allow(use_debug, too_many_arguments))]

extern crate base64 as b64;
#[macro_use]
extern crate log;
#[macro_use]
extern crate serde_derive;
#[macro_use]
extern crate unwrap;

#[macro_use]
mod macros;
mod base64;
mod catch_unwind;
................................................................................
pub mod test_utils;
pub mod string;

pub use self::base64::{base64_decode, base64_encode};
pub use self::catch_unwind::{catch_unwind_cb, catch_unwind_error_code};
pub use self::repr_c::ReprC;
pub use self::string::{StringError, from_c_str};
pub use self::vec::{SafePtr, vec_clone_from_raw_parts, vec_into_raw_parts};
use std::os::raw::{c_char, c_void};

/// Type that holds opaque user data handed into FFI functions
#[derive(Clone, Copy)]
pub struct OpaqueCtx(pub *mut c_void);
unsafe impl Send for OpaqueCtx {}

impl Into<*mut c_void> for OpaqueCtx {
................................................................................
}

/// Trait for types that can be converted to integer error code.
pub trait ErrorCode {
    /// Return the error code corresponding to this instance.
    fn error_code(&self) -> i32;
}

/// FFI result wrapper
#[repr(C)]
pub struct FfiResult {
    /// Unique error code
    pub error_code: i32,
    /// Error description
    pub description: *const c_char,
}

/// Constant value to be used for OK result
pub const FFI_RESULT_OK: FfiResult = FfiResult {
    error_code: 0,
    description: 0 as *const c_char,
};

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/macros.rs from [e55041a862] to [fd0261c054].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20























21
22
23
24
25
26
27
..
52
53
54
55
56
57
58




59
60
61
62
63
64
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.
























#[macro_export]
macro_rules! ffi_result_code {
    ($res:expr) => {
        match $res {
            Ok(_) => 0,
            Err(error) => ffi_error_code!(error),
................................................................................
    ($result:expr, $user_data:expr, $cb:expr) => {
        match $result {
            Ok(value) => value,
            Err(err) => {
                #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
                #[allow(unused)]
                use $crate::callback::{Callback, CallbackArgs};




                $cb.call($user_data.into(), ffi_error_code!(err), CallbackArgs::default());
                return None;
            }
        }
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
|





1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
..
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

/// Converts a result into a pair of `(error_code: i32, description: CString)`
/// to be used in `FfiResult`
#[macro_export]
macro_rules! ffi_error {
    ($error:expr) => {{
        let err_code = ffi_error_code!($error);
        let err_desc = format!("{}", $error);
        (err_code, unwrap!(::std::ffi::CString::new(err_desc)))
    }}
}

/// Converts a result into a pair of `(error_code: i32, description: CString)`
/// to be used in `FfiResult`
#[macro_export]
macro_rules! ffi_result {
    ($res:expr) => {
        match $res {
            Ok(_) => (0, ::std::ffi::CString::default()),
            Err(error) => ffi_error!(error)
        }
    }
}

#[macro_export]
macro_rules! ffi_result_code {
    ($res:expr) => {
        match $res {
            Ok(_) => 0,
            Err(error) => ffi_error_code!(error),
................................................................................
    ($result:expr, $user_data:expr, $cb:expr) => {
        match $result {
            Ok(value) => value,
            Err(err) => {
                #[cfg_attr(feature = "cargo-clippy", allow(useless_attribute))]
                #[allow(unused)]
                use $crate::callback::{Callback, CallbackArgs};
                let (error_code, description) = ffi_error!(err);
                $cb.call($user_data.into(), FfiResult {
                    error_code,
                    description: description.as_ptr()
                }, CallbackArgs::default());
                return None;
            }
        }
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/repr_c.rs from [d000e0bbc9] to [fea2cdb0dd].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI tools

/// Trait to convert between FFI and Rust representations of types
pub trait ReprC {
    /// C representation of the type
    type C;


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI tools

/// Trait to convert between FFI and Rust representations of types
pub trait ReprC {
    /// C representation of the type
    type C;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/string.rs from [aca8f89e0a] to [c4c03bf51b].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Utilities for passing strings across FFI boundaries.

use repr_c::ReprC;
use std::error::Error;
use std::ffi::{CStr, IntoStringError, NulError};
use std::os::raw::c_char;
................................................................................

impl ReprC for String {
    type C = *const c_char;
    type Error = StringError;

    unsafe fn clone_from_repr_c(c_repr: Self::C) -> Result<String, StringError> {
        Ok(if c_repr.is_null() {
            "".to_owned()
        } else {
            from_c_str(c_repr)?
        })
    }
}

/// Error type for strings
#[derive(RustcEncodable, RustcDecodable, Debug, Eq, PartialEq)]
pub enum StringError {
    /// UTF8 error
    Utf8(String),
    /// Null error
    Null(String),
    /// IntoString error
    IntoString(String),


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|







 







|
|
|
|




|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Utilities for passing strings across FFI boundaries.

use repr_c::ReprC;
use std::error::Error;
use std::ffi::{CStr, IntoStringError, NulError};
use std::os::raw::c_char;
................................................................................

impl ReprC for String {
    type C = *const c_char;
    type Error = StringError;

    unsafe fn clone_from_repr_c(c_repr: Self::C) -> Result<String, StringError> {
        Ok(if c_repr.is_null() {
               "".to_owned()
           } else {
               from_c_str(c_repr)?
           })
    }
}

/// Error type for strings
#[derive(Serialize, Deserialize, Debug, Eq, PartialEq)]
pub enum StringError {
    /// UTF8 error
    Utf8(String),
    /// Null error
    Null(String),
    /// IntoString error
    IntoString(String),

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/test_utils.rs from [441a41c46e] to [9ed85d68a9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

24
25
26
27
28
29
30
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

77
78
79
80
81
82
83
..
85
86
87
88
89
90
91
92

93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112

113
114
115
116

117
118
119
120
121
122
123
124
125
126
127
128
129
130

131
132

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149

150



151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169

170
171
172
173
174
175

176
177
178
179
180
181
182
183
184
185
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! Test utilities.


use repr_c::ReprC;
use std::fmt::Debug;
use std::os::raw::c_void;
use std::slice;
use std::sync::mpsc::{self, Sender};

/// Convert a `mpsc::Sender<T>` to a void ptr which can be passed as user data to
................................................................................
    unwrap!((*tx).send(value));
}

/// Call a FFI function and block until its callback gets called.
/// Use this if the callback accepts no arguments in addition to `user_data`
/// and `error_code`.
pub fn call_0<F>(f: F) -> Result<(), i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, i32))
{
    let (tx, rx) = mpsc::channel::<i32>();
    f(sender_as_user_data(&tx), callback_0);

    let error = unwrap!(rx.recv());
    if error == 0 { Ok(()) } else { Err(error) }
}

/// Call an FFI function and block until its callback gets called, then return
/// the argument which were passed to that callback.
/// Use this if the callback accepts one argument in addition to `user_data`
/// and `error_code`.
pub unsafe fn call_1<F, E: Debug, T>(f: F) -> Result<T, i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, i32, T::C)),
          T: ReprC<Error = E>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<T, i32>>>();
    f(sender_as_user_data(&tx), callback_1::<E, T>);
    unwrap!(rx.recv()).0
}

/// Call a FFI function and block until its callback gets called, then return
/// the argument which were passed to that callback.
/// Use this if the callback accepts two arguments in addition to `user_data`
/// and `error_code`.
pub unsafe fn call_2<F, E0, E1, T0, T1>(f: F) -> Result<(T0, T1), i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, i32, T0::C, T1::C)),

          E0: Debug,
          E1: Debug,
          T0: ReprC<Error = E0>,
          T1: ReprC<Error = E1>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<(T0, T1), i32>>>();
    f(sender_as_user_data(&tx), callback_2::<E0, E1, T0, T1>);
................................................................................
}

/// Call a FFI function and block until its callback gets called, then copy
/// the array argument which was passed to `Vec<T>` and return the result.
/// Use this if the callback accepts `*const T` and `usize` (length) arguments in addition
/// to `user_data` and `error_code`.
pub unsafe fn call_vec<F, E, T, U>(f: F) -> Result<Vec<T>, i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, i32, T::C, usize)),

          E: Debug,
          T: ReprC<C = *const U, Error = E>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<Vec<T>, i32>>>();

    f(sender_as_user_data(&tx), callback_vec::<E, T, U>);
    unwrap!(rx.recv()).0
}

/// Call a FFI function and block until its callback gets called, then copy
/// the byte array argument which was passed to `Vec<u8>` and return the result.
pub unsafe fn call_vec_u8<F>(f: F) -> Result<Vec<u8>, i32>
    where F: FnOnce(*mut c_void,
                    extern "C" fn(*mut c_void, i32, *const u8, usize))
{
    let (tx, rx) = mpsc::channel::<Result<Vec<u8>, i32>>();
    f(sender_as_user_data(&tx), callback_vec_u8);
    unwrap!(rx.recv())
}


extern "C" fn callback_0(user_data: *mut c_void, error: i32) {
    unsafe { send_via_user_data(user_data, error) }
}


extern "C" fn callback_1<E, T>(user_data: *mut c_void, error: i32, arg: T::C)
    where E: Debug,
          T: ReprC<Error = E>
{
    unsafe {
        let result: Result<T, i32> = if error == 0 {
            Ok(unwrap!(T::clone_from_repr_c(arg)))
        } else {
            Err(error)
        };
        send_via_user_data(user_data, SendWrapper(result));
    }
}


extern "C" fn callback_2<E0, E1, T0, T1>(user_data: *mut c_void,
                                         error: i32,

                                         arg0: T0::C,
                                         arg1: T1::C)
    where E0: Debug,
          E1: Debug,
          T0: ReprC<Error = E0>,
          T1: ReprC<Error = E1>
{
    unsafe {
        let result: Result<(T0, T1), i32> = if error == 0 {
            Ok((unwrap!(T0::clone_from_repr_c(arg0)), unwrap!(T1::clone_from_repr_c(arg1))))
        } else {
            Err(error)
        };
        send_via_user_data(user_data, SendWrapper(result))
    }
}


extern "C" fn callback_vec<E, T, U>(user_data: *mut c_void, error: i32, array: T::C, size: usize)



    where E: Debug,
          T: ReprC<C = *const U, Error = E>
{
    unsafe {
        let result: Result<Vec<T>, i32> = if error == 0 {
            let slice_ffi = slice::from_raw_parts(array, size);
            let mut vec = Vec::with_capacity(slice_ffi.len());
            for elt in slice_ffi {
                vec.push(unwrap!(T::clone_from_repr_c(elt)));
            }
            Ok(vec)
        } else {
            Err(error)
        };

        send_via_user_data(user_data, SendWrapper(result))
    }
}


extern "C" fn callback_vec_u8(user_data: *mut c_void, error: i32, ptr: *const u8, len: usize) {
    unsafe {
        let result = if error == 0 {
            Ok(slice::from_raw_parts(ptr, len).to_vec())
        } else {
            Err(error)

        };

        send_via_user_data(user_data, result)
    }
}

// Unsafe wrapper for passing non-Send types through mpsc channels.
// Use with caution!
struct SendWrapper<T>(T);
unsafe impl<T> Send for SendWrapper<T> {}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|



>







 







|













|












|
>







 







|
>













|






>
|
|


>
|




|


|





>

<
>








|


|





>
|
>
>
>




|







|






>
|

|


<
>










1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133

134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181

182
183
184
185
186
187
188
189
190
191
192
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! Test utilities.

use super::FfiResult;
use repr_c::ReprC;
use std::fmt::Debug;
use std::os::raw::c_void;
use std::slice;
use std::sync::mpsc::{self, Sender};

/// Convert a `mpsc::Sender<T>` to a void ptr which can be passed as user data to
................................................................................
    unwrap!((*tx).send(value));
}

/// Call a FFI function and block until its callback gets called.
/// Use this if the callback accepts no arguments in addition to `user_data`
/// and `error_code`.
pub fn call_0<F>(f: F) -> Result<(), i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, FfiResult))
{
    let (tx, rx) = mpsc::channel::<i32>();
    f(sender_as_user_data(&tx), callback_0);

    let error = unwrap!(rx.recv());
    if error == 0 { Ok(()) } else { Err(error) }
}

/// Call an FFI function and block until its callback gets called, then return
/// the argument which were passed to that callback.
/// Use this if the callback accepts one argument in addition to `user_data`
/// and `error_code`.
pub unsafe fn call_1<F, E: Debug, T>(f: F) -> Result<T, i32>
    where F: FnOnce(*mut c_void, extern "C" fn(*mut c_void, FfiResult, T::C)),
          T: ReprC<Error = E>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<T, i32>>>();
    f(sender_as_user_data(&tx), callback_1::<E, T>);
    unwrap!(rx.recv()).0
}

/// Call a FFI function and block until its callback gets called, then return
/// the argument which were passed to that callback.
/// Use this if the callback accepts two arguments in addition to `user_data`
/// and `error_code`.
pub unsafe fn call_2<F, E0, E1, T0, T1>(f: F) -> Result<(T0, T1), i32>
    where F: FnOnce(*mut c_void,
                    extern "C" fn(*mut c_void, FfiResult, T0::C, T1::C)),
          E0: Debug,
          E1: Debug,
          T0: ReprC<Error = E0>,
          T1: ReprC<Error = E1>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<(T0, T1), i32>>>();
    f(sender_as_user_data(&tx), callback_2::<E0, E1, T0, T1>);
................................................................................
}

/// Call a FFI function and block until its callback gets called, then copy
/// the array argument which was passed to `Vec<T>` and return the result.
/// Use this if the callback accepts `*const T` and `usize` (length) arguments in addition
/// to `user_data` and `error_code`.
pub unsafe fn call_vec<F, E, T, U>(f: F) -> Result<Vec<T>, i32>
    where F: FnOnce(*mut c_void,
                    extern "C" fn(*mut c_void, FfiResult, T::C, usize)),
          E: Debug,
          T: ReprC<C = *const U, Error = E>
{
    let (tx, rx) = mpsc::channel::<SendWrapper<Result<Vec<T>, i32>>>();

    f(sender_as_user_data(&tx), callback_vec::<E, T, U>);
    unwrap!(rx.recv()).0
}

/// Call a FFI function and block until its callback gets called, then copy
/// the byte array argument which was passed to `Vec<u8>` and return the result.
pub unsafe fn call_vec_u8<F>(f: F) -> Result<Vec<u8>, i32>
    where F: FnOnce(*mut c_void,
                    extern "C" fn(*mut c_void, FfiResult, *const u8, usize))
{
    let (tx, rx) = mpsc::channel::<Result<Vec<u8>, i32>>();
    f(sender_as_user_data(&tx), callback_vec_u8);
    unwrap!(rx.recv())
}

#[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
extern "C" fn callback_0(user_data: *mut c_void, res: FfiResult) {
    unsafe { send_via_user_data(user_data, res.error_code) }
}

#[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
extern "C" fn callback_1<E, T>(user_data: *mut c_void, res: FfiResult, arg: T::C)
    where E: Debug,
          T: ReprC<Error = E>
{
    unsafe {
        let result: Result<T, i32> = if res.error_code == 0 {
            Ok(unwrap!(T::clone_from_repr_c(arg)))
        } else {
            Err(res.error_code)
        };
        send_via_user_data(user_data, SendWrapper(result));
    }
}

#[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
extern "C" fn callback_2<E0, E1, T0, T1>(user_data: *mut c_void,

                                         res: FfiResult,
                                         arg0: T0::C,
                                         arg1: T1::C)
    where E0: Debug,
          E1: Debug,
          T0: ReprC<Error = E0>,
          T1: ReprC<Error = E1>
{
    unsafe {
        let result: Result<(T0, T1), i32> = if res.error_code == 0 {
            Ok((unwrap!(T0::clone_from_repr_c(arg0)), unwrap!(T1::clone_from_repr_c(arg1))))
        } else {
            Err(res.error_code)
        };
        send_via_user_data(user_data, SendWrapper(result))
    }
}

#[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
extern "C" fn callback_vec<E, T, U>(user_data: *mut c_void,
                                    res: FfiResult,
                                    array: T::C,
                                    size: usize)
    where E: Debug,
          T: ReprC<C = *const U, Error = E>
{
    unsafe {
        let result: Result<Vec<T>, i32> = if res.error_code == 0 {
            let slice_ffi = slice::from_raw_parts(array, size);
            let mut vec = Vec::with_capacity(slice_ffi.len());
            for elt in slice_ffi {
                vec.push(unwrap!(T::clone_from_repr_c(elt)));
            }
            Ok(vec)
        } else {
            Err(res.error_code)
        };

        send_via_user_data(user_data, SendWrapper(result))
    }
}

#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))]
extern "C" fn callback_vec_u8(user_data: *mut c_void, res: FfiResult, ptr: *const u8, len: usize) {
    unsafe {
        let result = if res.error_code == 0 {
            Ok(slice::from_raw_parts(ptr, len).to_vec())
        } else {

            Err(res.error_code)
        };

        send_via_user_data(user_data, result)
    }
}

// Unsafe wrapper for passing non-Send types through mpsc channels.
// Use with caution!
struct SendWrapper<T>(T);
unsafe impl<T> Send for SendWrapper<T> {}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/ffi_utils/src/vec.rs from [bd295d9687] to [e989580770].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23

























24
25
26
27
28
29
30
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use std::mem;

use std::slice;


























/// Converts a pointer and lengts to Vec<T> by cloning the contents.
pub unsafe fn vec_clone_from_raw_parts<T: Clone>(ptr: *const T, len: usize) -> Vec<T> {
    slice::from_raw_parts(ptr, len).to_vec()
}

/// Converts a Vec<T> to (pointer, size, capacity)


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|


>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use std::mem;
use std::ptr;
use std::slice;

/// Provides FFI-safe pointers, as opposed to raw `as_ptr()` in
/// `Vec` and `String` which can return values such as `0x01` that
/// can cause segmentation faults with the automatic pointer
/// dereferencing on the front-end side (e.g. in Node.js).
pub trait SafePtr {
    /// Resulting pointer type
    type Ptr;

    /// Returns a pointer that guarantees safe dereferencing
    /// on the front-end side.
    fn as_safe_ptr(&self) -> *const Self::Ptr;
}

impl<T> SafePtr for Vec<T> {
    type Ptr = T;

    fn as_safe_ptr(&self) -> *const T {
        if self.is_empty() {
            ptr::null()
        } else {
            self.as_ptr()
        }
    }
}

/// Converts a pointer and lengts to Vec<T> by cloning the contents.
pub unsafe fn vec_clone_from_raw_parts<T: Clone>(ptr: *const T, len: usize) -> Vec<T> {
    slice::from_raw_parts(ptr, len).to_vec()
}

/// Converts a Vec<T> to (pointer, size, capacity)

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/rustfmt.toml from [43f8620098] to [0fac950cce].

1
2
3
4
5
6
reorder_imports = true
reorder_imported_names = true
use_try_shorthand = true

normalize_comments = false




<
<
<
1
2
3



reorder_imports = true
reorder_imported_names = true
use_try_shorthand = true



Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/Cargo.toml from [4415f90aa8] to [58c29f8208].

1
2
3
4
5
6
7
8
9
10
11
12

13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
[package]
authors = ["MaidSafe Developers <dev@maidsafe.net>"]
description = "SAFE App"
documentation = "https://docs.rs/safe_app"
homepage = "http://maidsafe.net"
license = "GPL-3.0"
name = "safe_app"
readme = "README.md"
repository = "https://github.com/maidsafe/safe_client_libs"
version = "0.1.0"

[dependencies]

ffi_utils = { path = "../ffi_utils", version = "~0.1.0" }
futures = "~0.1.6"
log = "~0.3.6"
lru-cache = "~0.1.0"
maidsafe_utilities = "~0.10.0"
rand = "~0.3.15"
# routing = "~0.27.1"
routing = { git = "https://github.com/maidsafe/routing.git", branch = "mutable-data" }
rust_sodium = "~0.1.2"
rustc-serialize = "~0.3.22"

safe_core = { path = "../safe_core", version = "~0.22.0" }
safe_authenticator = { path = "../safe_authenticator", version = "~0.1.0", optional = true }
self_encryption = { git = "https://github.com/maidsafe/self_encryption.git", branch = "dev" }
time = "~0.1.35"
tokio-core = "~0.1.1"
unwrap = "~1.1.0"

[dev-dependencies]
safe_authenticator = { path = "../safe_authenticator", version = "~0.1.0" }

[features]
use-mock-routing = ["safe_core/use-mock-routing"]
testing = ["safe_authenticator", "safe_authenticator/testing", "safe_core/testing"]

[lib]
crate_type = ["staticlib", "rlib", "cdylib"]




|







>

|
|

|



|
|
>



|
|











1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
[package]
authors = ["MaidSafe Developers <dev@maidsafe.net>"]
description = "SAFE App"
documentation = "https://docs.rs/safe_app"
homepage = "https://maidsafe.net"
license = "GPL-3.0"
name = "safe_app"
readme = "README.md"
repository = "https://github.com/maidsafe/safe_client_libs"
version = "0.1.0"

[dependencies]
chrono = { version = "=0.3.0", features = ["serde"] }
ffi_utils = { path = "../ffi_utils", version = "~0.1.0" }
futures = "~0.1.11"
log = "~0.3.7"
lru-cache = "~0.1.0"
maidsafe_utilities = "~0.11.0"
rand = "~0.3.15"
# routing = "~0.27.1"
routing = { git = "https://github.com/maidsafe/routing.git", branch = "mutable-data" }
rust_sodium = "~0.2.0"
serde = "~0.9.12"
serde_derive = "~0.9.12"
safe_core = { path = "../safe_core", version = "~0.22.0" }
safe_authenticator = { path = "../safe_authenticator", version = "~0.1.0", optional = true }
self_encryption = { git = "https://github.com/maidsafe/self_encryption.git", branch = "dev" }
tiny-keccak = "~1.2.1"
tokio-core = "~0.1.6"
unwrap = "~1.1.0"

[dev-dependencies]
safe_authenticator = { path = "../safe_authenticator", version = "~0.1.0" }

[features]
use-mock-routing = ["safe_core/use-mock-routing"]
testing = ["safe_authenticator", "safe_authenticator/testing", "safe_core/testing"]

[lib]
crate_type = ["staticlib", "rlib", "cdylib"]

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/README.md from [dfa15c13a3] to [21751ee57a].

31
32
33
34
35
36
37
38
39
40
* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement, version 1.1 ([CONTRIBUTOR]
(CONTRIBUTOR)), shall be dual licensed as above, and you agree to be bound by the terms of the
MaidSafe Contributor Agreement, version 1.1.







|
|
<
31
32
33
34
35
36
37
38
39

* the General Public License (GPL), version 3 ([COPYING](COPYING) or http://www.gnu.org/licenses/gpl-3.0.en.html)

at your option.

## Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the
work by you, as defined in the MaidSafe Contributor Agreement ([CONTRIBUTOR](CONTRIBUTOR)), shall be
dual licensed as above, and you agree to be bound by the terms of the MaidSafe Contributor Agreement.

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/errors.rs from [41963f611a] to [e976e3a6e0].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

33
34
35
36
37
38
39
..
68
69
70
71
72
73
74


75
76
77
78
79
80
81
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106

107
108
109
110
111
112

113
114
115
116
117
118
119
...
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
...
138
139
140
141
142
143
144


145
146
147
148
149
150
151
152
153
154
155

















































156
157
158
159
160
161
162
...
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293

294
295
296
297
298
299
300
...
326
327
328
329
330
331
332


333
334
335
336
337
338
339
340
341
342
343
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

pub use self::codes::*;
use ffi_utils::ErrorCode;
use futures::sync::mpsc::SendError;
use maidsafe_utilities::serialisation::SerialisationError;
use routing::ClientError;
use safe_core::{CoreError, SelfEncryptionStorageError};
use safe_core::ipc::IpcError;
use safe_core::nfs::NfsError;
use self_encryption::SelfEncryptionError;
use std::error::Error;
use std::ffi::NulError;

use std::io::Error as IoError;
use std::str::Utf8Error;
use std::sync::mpsc::{RecvError, RecvTimeoutError};

#[allow(missing_docs)]
mod codes {
    // Core errors
................................................................................
    pub const ERR_NO_SUCH_KEY: i32 = -109;
    pub const ERR_INVALID_OWNERS: i32 = -110;
    pub const ERR_INVALID_SUCCESSOR: i32 = -111;
    pub const ERR_INVALID_OPERATION: i32 = -112;
    pub const ERR_LOW_BALANCE: i32 = -113;
    pub const ERR_NETWORK_FULL: i32 = -114;
    pub const ERR_NETWORK_OTHER: i32 = -115;



    // IPC errors.
    pub const ERR_AUTH_DENIED: i32 = -200;
    pub const ERR_CONTAINERS_DENIED: i32 = -201;
    pub const ERR_INVALID_MSG: i32 = -202;
    pub const ERR_ALREADY_AUTHORISED: i32 = -203;
    pub const ERR_UNKNOWN_APP: i32 = -204;
................................................................................
    pub const ERR_FILE_NOT_FOUND: i32 = -305;
    pub const ERR_INVALID_RANGE: i32 = -306;
    pub const ERR_INVALID_PARAMETER: i32 = -307;

    // App errors
    pub const ERR_NO_SUCH_CONTAINER: i32 = -1002;
    pub const ERR_INVALID_CIPHER_OPT_HANDLE: i32 = -1003;
    pub const ERR_INVALID_ENCRYPT_KEY_HANDLE: i32 = -1004;
    pub const ERR_INVALID_MDATA_INFO_HANDLE: i32 = -1005;
    pub const ERR_INVALID_MDATA_ENTRIES_HANDLE: i32 = -1006;
    pub const ERR_INVALID_MDATA_ENTRY_ACTIONS_HANDLE: i32 = -1007;
    pub const ERR_INVALID_MDATA_PERMISSIONS_HANDLE: i32 = -1008;
    pub const ERR_INVALID_MDATA_PERMISSION_SET_HANDLE: i32 = -1009;
    pub const ERR_INVALID_SELF_ENCRYPTOR_HANDLE: i32 = -1010;
    pub const ERR_INVALID_SIGN_KEY_HANDLE: i32 = -1011;
    pub const ERR_INVALID_SELF_ENCRYPTOR_READ_OFFSETS: i32 = -1012;
    pub const ERR_IO_ERROR: i32 = -1013;


    pub const ERR_UNEXPECTED: i32 = -2000;
}

/// App error.
#[derive(Debug)]

pub enum AppError {
    /// Error from safe_core.
    CoreError(CoreError),
    /// IPC error.
    IpcError(IpcError),
    /// NFS error.
    NfsError(NfsError),
................................................................................
    OperationForbidden,
    /// Container not found
    NoSuchContainer,

    /// Invalid CipherOpt handle
    InvalidCipherOptHandle,
    /// Invalid encrypt (box_) key handle
    InvalidEncryptKeyHandle,
    /// Invalid `MDataInfo` handle
    InvalidMDataInfoHandle,
    /// Invalid MutableData enties handle
    InvalidMDataEntriesHandle,
    /// Invalid MutableData entry actions handle
    InvalidMDataEntryActionsHandle,
    /// Invalid MutableData permissions handle
................................................................................
    InvalidMDataPermissionsHandle,
    /// Invalid MutableData permission set handle
    InvalidMDataPermissionSetHandle,
    /// Invalid Self Encryptor handle
    InvalidSelfEncryptorHandle,
    /// Invalid sign key handle
    InvalidSignKeyHandle,



    /// Error while self-encrypting data
    SelfEncryption(SelfEncryptionError<SelfEncryptionStorageError>),
    /// Invalid offsets (from-position and lenght combination) provided for
    /// reading form SelfEncryptor. Would have probably caused an overflow.
    InvalidSelfEncryptorReadOffsets,
    /// Input/output Error
    IoError(IoError),
    /// Unexpected error
    Unexpected(String),
}


















































impl From<CoreError> for AppError {
    fn from(err: CoreError) -> Self {
        match err {
            CoreError::Unexpected(reason) => AppError::Unexpected(reason),
            _ => AppError::CoreError(err),
        }
................................................................................
                    NfsError::Unexpected(_) => ERR_UNEXPECTED,
                }
            }
            AppError::EncodeDecodeError => ERR_ENCODE_DECODE_ERROR,
            AppError::OperationForbidden => ERR_OPERATION_FORBIDDEN,
            AppError::NoSuchContainer => ERR_NO_SUCH_CONTAINER,
            AppError::InvalidCipherOptHandle => ERR_INVALID_CIPHER_OPT_HANDLE,
            AppError::InvalidEncryptKeyHandle => ERR_INVALID_ENCRYPT_KEY_HANDLE,
            AppError::InvalidMDataInfoHandle => ERR_INVALID_MDATA_INFO_HANDLE,
            AppError::InvalidMDataEntriesHandle => ERR_INVALID_MDATA_ENTRIES_HANDLE,
            AppError::InvalidMDataEntryActionsHandle => ERR_INVALID_MDATA_ENTRY_ACTIONS_HANDLE,
            AppError::InvalidMDataPermissionsHandle => ERR_INVALID_MDATA_PERMISSIONS_HANDLE,
            AppError::InvalidMDataPermissionSetHandle => ERR_INVALID_MDATA_PERMISSION_SET_HANDLE,
            AppError::InvalidSelfEncryptorHandle => ERR_INVALID_SELF_ENCRYPTOR_HANDLE,
            AppError::InvalidSignKeyHandle => ERR_INVALID_SIGN_KEY_HANDLE,

            AppError::SelfEncryption(_) => ERR_SELF_ENCRYPTION,
            AppError::InvalidSelfEncryptorReadOffsets => ERR_INVALID_SELF_ENCRYPTOR_READ_OFFSETS,
            AppError::IoError(_) => ERR_IO_ERROR,
            AppError::Unexpected(_) => ERR_UNEXPECTED,
        }
    }
}
................................................................................
                ClientError::NoSuchKey => ERR_NO_SUCH_KEY,
                ClientError::InvalidOwners => ERR_INVALID_OWNERS,
                ClientError::InvalidSuccessor => ERR_INVALID_SUCCESSOR,
                ClientError::InvalidOperation => ERR_INVALID_OPERATION,
                ClientError::LowBalance => ERR_LOW_BALANCE,
                ClientError::NetworkFull => ERR_NETWORK_FULL,
                ClientError::NetworkOther(_) => ERR_NETWORK_OTHER,


            }
        }
        CoreError::UnsupportedSaltSizeForPwHash => ERR_UNSUPPORTED_SALT_SIZE_FOR_PW_HASH,
        CoreError::UnsuccessfulPwHash => ERR_UNSUCCESSFUL_PW_HASH,
        CoreError::OperationAborted => ERR_OPERATION_ABORTED,
        CoreError::MpidMessagingError(_) => ERR_MPID_MESSAGING_ERROR,
        CoreError::SelfEncryption(_) => ERR_SELF_ENCRYPTION,
        CoreError::RequestTimeout => ERR_REQUEST_TIMEOUT,
        CoreError::Unexpected(_) => ERR_UNEXPECTED,
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|












>







 







>
>







 







|









>






>







 







|







 







>
>



|







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|







>







 







>
>











1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
..
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
..
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
...
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
...
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
...
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
...
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

pub use self::codes::*;
use ffi_utils::ErrorCode;
use futures::sync::mpsc::SendError;
use maidsafe_utilities::serialisation::SerialisationError;
use routing::ClientError;
use safe_core::{CoreError, SelfEncryptionStorageError};
use safe_core::ipc::IpcError;
use safe_core::nfs::NfsError;
use self_encryption::SelfEncryptionError;
use std::error::Error;
use std::ffi::NulError;
use std::fmt::{self, Display, Formatter};
use std::io::Error as IoError;
use std::str::Utf8Error;
use std::sync::mpsc::{RecvError, RecvTimeoutError};

#[allow(missing_docs)]
mod codes {
    // Core errors
................................................................................
    pub const ERR_NO_SUCH_KEY: i32 = -109;
    pub const ERR_INVALID_OWNERS: i32 = -110;
    pub const ERR_INVALID_SUCCESSOR: i32 = -111;
    pub const ERR_INVALID_OPERATION: i32 = -112;
    pub const ERR_LOW_BALANCE: i32 = -113;
    pub const ERR_NETWORK_FULL: i32 = -114;
    pub const ERR_NETWORK_OTHER: i32 = -115;
    pub const ERR_INVALID_INVITATION: i32 = -116;
    pub const ERR_INVITATION_ALREADY_CLAIMED: i32 = -117;

    // IPC errors.
    pub const ERR_AUTH_DENIED: i32 = -200;
    pub const ERR_CONTAINERS_DENIED: i32 = -201;
    pub const ERR_INVALID_MSG: i32 = -202;
    pub const ERR_ALREADY_AUTHORISED: i32 = -203;
    pub const ERR_UNKNOWN_APP: i32 = -204;
................................................................................
    pub const ERR_FILE_NOT_FOUND: i32 = -305;
    pub const ERR_INVALID_RANGE: i32 = -306;
    pub const ERR_INVALID_PARAMETER: i32 = -307;

    // App errors
    pub const ERR_NO_SUCH_CONTAINER: i32 = -1002;
    pub const ERR_INVALID_CIPHER_OPT_HANDLE: i32 = -1003;
    pub const ERR_INVALID_ENCRYPT_PUB_KEY_HANDLE: i32 = -1004;
    pub const ERR_INVALID_MDATA_INFO_HANDLE: i32 = -1005;
    pub const ERR_INVALID_MDATA_ENTRIES_HANDLE: i32 = -1006;
    pub const ERR_INVALID_MDATA_ENTRY_ACTIONS_HANDLE: i32 = -1007;
    pub const ERR_INVALID_MDATA_PERMISSIONS_HANDLE: i32 = -1008;
    pub const ERR_INVALID_MDATA_PERMISSION_SET_HANDLE: i32 = -1009;
    pub const ERR_INVALID_SELF_ENCRYPTOR_HANDLE: i32 = -1010;
    pub const ERR_INVALID_SIGN_KEY_HANDLE: i32 = -1011;
    pub const ERR_INVALID_SELF_ENCRYPTOR_READ_OFFSETS: i32 = -1012;
    pub const ERR_IO_ERROR: i32 = -1013;
    pub const ERR_INVALID_ENCRYPT_SEC_KEY_HANDLE: i32 = -1014;

    pub const ERR_UNEXPECTED: i32 = -2000;
}

/// App error.
#[derive(Debug)]
#[cfg_attr(feature="cargo-clippy", allow(large_enum_variant))]
pub enum AppError {
    /// Error from safe_core.
    CoreError(CoreError),
    /// IPC error.
    IpcError(IpcError),
    /// NFS error.
    NfsError(NfsError),
................................................................................
    OperationForbidden,
    /// Container not found
    NoSuchContainer,

    /// Invalid CipherOpt handle
    InvalidCipherOptHandle,
    /// Invalid encrypt (box_) key handle
    InvalidEncryptPubKeyHandle,
    /// Invalid `MDataInfo` handle
    InvalidMDataInfoHandle,
    /// Invalid MutableData enties handle
    InvalidMDataEntriesHandle,
    /// Invalid MutableData entry actions handle
    InvalidMDataEntryActionsHandle,
    /// Invalid MutableData permissions handle
................................................................................
    InvalidMDataPermissionsHandle,
    /// Invalid MutableData permission set handle
    InvalidMDataPermissionSetHandle,
    /// Invalid Self Encryptor handle
    InvalidSelfEncryptorHandle,
    /// Invalid sign key handle
    InvalidSignKeyHandle,
    /// Invalid secret key handle
    InvalidEncryptSecKeyHandle,

    /// Error while self-encrypting data
    SelfEncryption(SelfEncryptionError<SelfEncryptionStorageError>),
    /// Invalid offsets (from-position and length combination) provided for
    /// reading form SelfEncryptor. Would have probably caused an overflow.
    InvalidSelfEncryptorReadOffsets,
    /// Input/output Error
    IoError(IoError),
    /// Unexpected error
    Unexpected(String),
}

impl Display for AppError {
    fn fmt(&self, formatter: &mut Formatter) -> fmt::Result {
        match *self {
            AppError::CoreError(ref error) => write!(formatter, "Core error: {}", error),
            AppError::IpcError(ref error) => write!(formatter, "IPC error: {:?}", error),
            AppError::NfsError(ref error) => write!(formatter, "NFS error: {:?}", error),
            AppError::EncodeDecodeError => write!(formatter, "Serialisation error"),
            AppError::OperationForbidden => write!(formatter, "Forbidden operation"),
            AppError::NoSuchContainer => write!(formatter, "Container not found"),
            AppError::InvalidCipherOptHandle => write!(formatter, "Invalid CipherOpt handle"),
            AppError::InvalidEncryptPubKeyHandle => {
                write!(formatter, "Invalid encrypt (box_) key handle")
            }
            AppError::InvalidMDataInfoHandle => write!(formatter, "Invalid `MDataInfo` handle"),
            AppError::InvalidMDataEntriesHandle => {
                write!(formatter, "Invalid MutableData enties handle")
            }
            AppError::InvalidMDataEntryActionsHandle => {
                write!(formatter, "Invalid MutableData entry actions handle")
            }
            AppError::InvalidMDataPermissionsHandle => {
                write!(formatter, "Invalid MutableData permissions handle")
            }
            AppError::InvalidMDataPermissionSetHandle => {
                write!(formatter, "Invalid MutableData permission set handle")
            }
            AppError::InvalidSelfEncryptorHandle => {
                write!(formatter, "Invalid Self Encryptor handle")
            }
            AppError::InvalidSignKeyHandle => write!(formatter, "Invalid sign key handle"),
            AppError::InvalidEncryptSecKeyHandle => write!(formatter, "Invalid secret key handle"),
            AppError::SelfEncryption(ref error) => {
                write!(formatter, "Self-encryption error: {}", error)
            }
            AppError::InvalidSelfEncryptorReadOffsets => {
                write!(formatter,
                       "Invalid offsets (from-position \
                        and length combination) provided for \
                        reading form SelfEncryptor. Would have \
                        probably caused an overflow.")
            }
            AppError::IoError(ref error) => write!(formatter, "I/O error: {}", error),
            AppError::Unexpected(ref error) => {
                write!(formatter, "Unexpected (probably a logic error): {}", error)
            }
        }
    }
}

impl From<CoreError> for AppError {
    fn from(err: CoreError) -> Self {
        match err {
            CoreError::Unexpected(reason) => AppError::Unexpected(reason),
            _ => AppError::CoreError(err),
        }
................................................................................
                    NfsError::Unexpected(_) => ERR_UNEXPECTED,
                }
            }
            AppError::EncodeDecodeError => ERR_ENCODE_DECODE_ERROR,
            AppError::OperationForbidden => ERR_OPERATION_FORBIDDEN,
            AppError::NoSuchContainer => ERR_NO_SUCH_CONTAINER,
            AppError::InvalidCipherOptHandle => ERR_INVALID_CIPHER_OPT_HANDLE,
            AppError::InvalidEncryptPubKeyHandle => ERR_INVALID_ENCRYPT_PUB_KEY_HANDLE,
            AppError::InvalidMDataInfoHandle => ERR_INVALID_MDATA_INFO_HANDLE,
            AppError::InvalidMDataEntriesHandle => ERR_INVALID_MDATA_ENTRIES_HANDLE,
            AppError::InvalidMDataEntryActionsHandle => ERR_INVALID_MDATA_ENTRY_ACTIONS_HANDLE,
            AppError::InvalidMDataPermissionsHandle => ERR_INVALID_MDATA_PERMISSIONS_HANDLE,
            AppError::InvalidMDataPermissionSetHandle => ERR_INVALID_MDATA_PERMISSION_SET_HANDLE,
            AppError::InvalidSelfEncryptorHandle => ERR_INVALID_SELF_ENCRYPTOR_HANDLE,
            AppError::InvalidSignKeyHandle => ERR_INVALID_SIGN_KEY_HANDLE,
            AppError::InvalidEncryptSecKeyHandle => ERR_INVALID_ENCRYPT_SEC_KEY_HANDLE,
            AppError::SelfEncryption(_) => ERR_SELF_ENCRYPTION,
            AppError::InvalidSelfEncryptorReadOffsets => ERR_INVALID_SELF_ENCRYPTOR_READ_OFFSETS,
            AppError::IoError(_) => ERR_IO_ERROR,
            AppError::Unexpected(_) => ERR_UNEXPECTED,
        }
    }
}
................................................................................
                ClientError::NoSuchKey => ERR_NO_SUCH_KEY,
                ClientError::InvalidOwners => ERR_INVALID_OWNERS,
                ClientError::InvalidSuccessor => ERR_INVALID_SUCCESSOR,
                ClientError::InvalidOperation => ERR_INVALID_OPERATION,
                ClientError::LowBalance => ERR_LOW_BALANCE,
                ClientError::NetworkFull => ERR_NETWORK_FULL,
                ClientError::NetworkOther(_) => ERR_NETWORK_OTHER,
                ClientError::InvalidInvitation => ERR_INVALID_INVITATION,
                ClientError::InvitationAlreadyClaimed => ERR_INVITATION_ALREADY_CLAIMED,
            }
        }
        CoreError::UnsupportedSaltSizeForPwHash => ERR_UNSUPPORTED_SALT_SIZE_FOR_PW_HASH,
        CoreError::UnsuccessfulPwHash => ERR_UNSUCCESSFUL_PW_HASH,
        CoreError::OperationAborted => ERR_OPERATION_ABORTED,
        CoreError::MpidMessagingError(_) => ERR_MPID_MESSAGING_ERROR,
        CoreError::SelfEncryption(_) => ERR_SELF_ENCRYPTION,
        CoreError::RequestTimeout => ERR_REQUEST_TIMEOUT,
        CoreError::Unexpected(_) => ERR_UNEXPECTED,
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/access_container.rs from [fc0dc98dc3] to [294bf5c01d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27

28

29
30
31
32
33
34
35
36
37
38
39

40
41

42




43















































44
45
46
47
48
49
50
..
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

67
68
69
70
71
72








73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95








96
97
98
99
100
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use App;
use ffi_utils::{OpaqueCtx, catch_unwind_cb, from_c_str};
use futures::Future;
use object_cache::MDataInfoHandle;
use safe_core::FutureExt;
use safe_core::ipc::req::ffi::Permission;

use std::os::raw::{c_char, c_void};


/// Fetch access info from the network.
#[no_mangle]
pub unsafe extern "C" fn access_container_refresh_access_info(app: *const App,
                                                              user_data: *mut c_void,
                                                              o_cb: extern "C" fn(*mut c_void,
                                                                                  i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {

            context.refresh_access_info(client)
                .then(move |res| {

                    o_cb(user_data.0, ffi_result_code!(res));




                    Ok(())















































                })
                .into_box()
                .into()
        })
    })
}

................................................................................
/// Retrieve `MDataInfo` for the given container name from the access container.
#[no_mangle]
pub unsafe extern "C"
fn access_container_get_container_mdata_info(app: *const App,
                                             name: *const c_char,
                                             user_data: *mut c_void,
                                             o_cb: extern "C" fn(*mut c_void,
                                                                 i32,
                                                                 MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = from_c_str(name)?;

        (*app).send(move |client, context| {
            let context = context.clone();


            context.get_container_mdata_info(client, name)
                .map(move |info| {
                    let handle = context.object_cache().insert_mdata_info(info);
                    o_cb(user_data.0, 0, handle);
                })
                .map_err(move |err| o_cb(user_data.0, ffi_error_code!(err), 0))








                .into_box()
                .into()
        })
    })
}

/// Check whether the app has the given permission for the given container.
#[no_mangle]
pub unsafe extern "C" fn access_container_is_permitted(app: *const App,
                                                       name: *const c_char,
                                                       permission: Permission,
                                                       user_data: *mut c_void,
                                                       o_cb: extern "C" fn(*mut c_void,
                                                                           i32,
                                                                           bool)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = from_c_str(name)?;

        (*app).send(move |client, context| {

            context.is_permitted(client, name, permission)
                .map(move |answer| o_cb(user_data.0, 0, answer))
                .map_err(move |err| o_cb(user_data.0, ffi_error_code!(err), false))








                .into_box()
                .into()
        })
    })
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|


|




>

>






|




>
|

>
|
>
>
>
>

>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







 







|
|







>
|

|
|
|
|
>
>
>
>
>
>
>
>













|






>
|
|
|
>
>
>
>
>
>
>
>





1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
...
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use App;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, SafePtr, catch_unwind_cb, from_c_str};
use futures::Future;
use object_cache::MDataInfoHandle;
use safe_core::FutureExt;
use safe_core::ipc::req::ffi::Permission;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};
use std::ptr;

/// Fetch access info from the network.
#[no_mangle]
pub unsafe extern "C" fn access_container_refresh_access_info(app: *const App,
                                                              user_data: *mut c_void,
                                                              o_cb: extern "C" fn(*mut c_void,
                                                                                  FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            context
                .refresh_access_info(client)
                .then(move |res| {
                    let (error_code, description) = ffi_result!(res);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

/// Retrieve a list of container names that an app has access to.
#[no_mangle]
pub unsafe extern "C" fn access_container_get_names(app: *const App,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void,
                                                                        FfiResult,
                                                                        *const *const c_char,
                                                                        u32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            context
                .get_container_names(client)
                .and_then(move |names| {
                              let mut c_str_vec = Vec::new();
                              for name in names {
                                  c_str_vec.push(CString::new(name)?);
                              }
                              Ok(c_str_vec)
                          })
                .map(move |c_str_vec| {
                    let ptr_vec: Vec<*const c_char> = c_str_vec
                        .iter()
                        .map(|c_string| c_string.as_ptr())
                        .collect();
                    o_cb(user_data.0,
                         FFI_RESULT_OK,
                         ptr_vec.as_safe_ptr(),
                         c_str_vec.len() as u32);
                })
                .map_err(move |e| {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0);
                })
                .into_box()
                .into()
        })
    })
}

................................................................................
/// Retrieve `MDataInfo` for the given container name from the access container.
#[no_mangle]
pub unsafe extern "C"
fn access_container_get_container_mdata_info(app: *const App,
                                             name: *const c_char,
                                             user_data: *mut c_void,
                                             o_cb: extern "C" fn(*mut c_void,
                                                                 FfiResult,
MDataInfoHandle)){
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = from_c_str(name)?;

        (*app).send(move |client, context| {
            let context = context.clone();

            context
                .get_container_mdata_info(client, name)
                .map(move |info| {
                         let handle = context.object_cache().insert_mdata_info(info);
                         o_cb(user_data.0, FFI_RESULT_OK, handle);
                     })
                .map_err(move |err| {
                    let (error_code, description) = ffi_error!(err);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0)
                })
                .into_box()
                .into()
        })
    })
}

/// Check whether the app has the given permission for the given container.
#[no_mangle]
pub unsafe extern "C" fn access_container_is_permitted(app: *const App,
                                                       name: *const c_char,
                                                       permission: Permission,
                                                       user_data: *mut c_void,
                                                       o_cb: extern "C" fn(*mut c_void,
                                                                           FfiResult,
                                                                           bool)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = from_c_str(name)?;

        (*app).send(move |client, context| {
            context
                .is_permitted(client, name, permission)
                .map(move |answer| o_cb(user_data.0, FFI_RESULT_OK, answer))
                .map_err(move |err| {
                    let (error_code, description) = ffi_error!(err);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         false)
                })
                .into_box()
                .into()
        })
    })
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/cipher_opt.rs from [26fa8ce0f9] to [fc03abc11d].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
..
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
..
99
100
101
102
103
104
105
106
107
108
109
110
111


112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128


129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147


148
149
150

151





152
153
154
155

156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173

174




175
176
177
178
179
180
181
...
195
196
197
198
199
200
201
202
203
204
205
206
207
208


209

210
211
212
213
214
215
216
...
217
218
219
220
221
222
223
224
225
226
227
228
229
230


231

232
233
234
235
236
237
238
...
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use {App, AppContext};
use errors::AppError;
use ffi_utils::{OpaqueCtx, catch_unwind_cb};
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::{CipherOptHandle, EncryptKeyHandle};
use rust_sodium::crypto::{box_, sealedbox, secretbox};
use safe_core::{Client, CoreError};
use std::os::raw::c_void;

/// Cipher Options
#[derive(Debug)]
pub enum CipherOpt {
................................................................................
    /// Encrypt using asymmetric encryption (encrypting for peer to read)
    Asymmetric {
        /// PublicKey of the peer to whom we want to encrypt
        peer_encrypt_key: box_::PublicKey,
    },
}

#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
enum WireFormat {
    Plain(Vec<u8>),
    Symmetric {
        nonce: secretbox::Nonce,
        cipher_text: Vec<u8>,
    },
    Asymmetric(Vec<u8>),
................................................................................
}

/// Construct `CipherOpt::PlainText` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_plaintext(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      i32,
                                                                      CipherOptHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {


            let handle = context.object_cache().insert_cipher_opt(CipherOpt::PlainText);
            o_cb(user_data.0, 0, handle);
            None
        })
    });
}

/// Construct `CipherOpt::Symmetric` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_symmetric(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      i32,
                                                                      CipherOptHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        (*app).send(move |_, context| {


            let handle = context.object_cache().insert_cipher_opt(CipherOpt::Symmetric);
            o_cb(user_data.0, 0, handle);
            None
        })
    })
}

/// Construct `CipherOpt::Asymmetric` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_asymmetric(app: *const App,
                                                   peer_encrypt_key_h: EncryptKeyHandle,
                                                   user_data: *mut c_void,
                                                   o_cb: extern "C" fn(*mut c_void,
                                                                       i32,
                                                                       CipherOptHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {


            let pk = match context.object_cache().get_encrypt_key(peer_encrypt_key_h) {
                Ok(pk) => *pk,
                Err(e) => {

                    o_cb(user_data.0, ffi_error_code!(e), 0);





                    return None;
                }
            };
            let handle = context.object_cache()

                .insert_cipher_opt(CipherOpt::Asymmetric { peer_encrypt_key: pk });
            o_cb(user_data.0, 0, handle);
            None
        })
    });
}

/// Free `CipherOpt` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_free(app: *const App,
                                         handle: CipherOptHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_cipher_opt(handle);

            o_cb(user_data.0, ffi_result_code!(res));




            None
        })
    });
}

#[cfg(test)]
mod tests {
................................................................................
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));

        let cipher_opt_handle: CipherOptHandle =
            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_plaintext(&app_0, ud, cb))) };

        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_handle));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, &context));
            (plain_text, cipher_text)
        });
        assert!(cipher_text != plain_text);
        assert_free(&app_0, cipher_opt_handle, 0);

        run_now(&app_0, move |client, context| {


            assert!(context.object_cache().get_cipher_opt(cipher_opt_handle).is_err());

            assert!(decrypt_and_check(client, context, &cipher_text, &plain_text));
        });
    }

    #[test]
    fn app_0_to_app_0_sym() {
        let app_0 = create_app();
................................................................................

        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));
        let cipher_opt_handle: CipherOptHandle =
            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app_0, ud, cb))) };

        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_handle));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, &context));
            (plain_text, cipher_text)
        });
        assert!(cipher_text != plain_text);
        assert_free(&app_0, cipher_opt_handle, 0);

        run_now(&app_0, move |client, context| {


            assert!(context.object_cache().get_cipher_opt(cipher_opt_handle).is_err());

            assert!(decrypt_and_check(client, context, &cipher_text, &plain_text));
        });
    }

    // NOTE: rustfmt is behaving erratically on this function. Disabling it for now.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
................................................................................
            unwrap!(call_1(|ud, cb| cipher_opt_new_asymmetric(&app_0, enc_pk_h, ud, cb)))
        };

        // Encrypt the plaintext on App 0's end.
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));
        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_h));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, &context));
            (plain_text, cipher_text)
        });

        assert!(cipher_text != plain_text);
        assert_free(&app_0, cipher_opt_h, 0);

        run_now(&app_0, move |_, context| {
            assert!(context.object_cache().get_cipher_opt(cipher_opt_h).is_err());
        });

        // App 0 cannot decrypt the ciphertext, because it was encrypted with
................................................................................
        let app = create_app();

        let peer_encrypt_key_handle = run_now(&app, |_, context| {
            let (pk, _) = box_::gen_keypair();
            context.object_cache().insert_encrypt_key(pk)
        });

        let cipher_opt_handle_pt;
        let cipher_opt_handle_sym;
        let cipher_opt_handle_asym;

        unsafe {
            cipher_opt_handle_pt = unwrap!(call_1(|ud, cb| cipher_opt_new_plaintext(&app, ud, cb)));
            cipher_opt_handle_sym =
                unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app, ud, cb)));


            let err_code = AppError::InvalidEncryptKeyHandle.error_code();
            let res: Result<CipherOptHandle, _> =
                call_1(|ud, cb| cipher_opt_new_asymmetric(&app, 29293290, ud, cb));
            assert_eq!(unwrap!(res.err()), err_code);

            cipher_opt_handle_asym = unwrap!(call_1(|ud, cb| {
                cipher_opt_new_asymmetric(&app, peer_encrypt_key_handle, ud, cb)
            }));
        }

        run_now(&app, move |_, context| {
            let obj_cache = context.object_cache();
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_pt));
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_sym));
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_asym));
        });


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|



|

|







 







|







 







|





>
>
|
|
|
|








|




>
>
|
|
|
|






|


|





>
>
|


>
|
>
>
>
>
>



|
>

|










|





>
|
>
>
>
>







 







|


|



>
>
|
>







 







|


|



>
>
|
>







 







|



|







 







|
<
<
<
<
|
|
|
<
>
|




|
|
|
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
...
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
...
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
...
308
309
310
311
312
313
314
315




316
317
318

319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use {App, AppContext};
use errors::AppError;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, catch_unwind_cb};
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::{CipherOptHandle, EncryptPubKeyHandle};
use rust_sodium::crypto::{box_, sealedbox, secretbox};
use safe_core::{Client, CoreError};
use std::os::raw::c_void;

/// Cipher Options
#[derive(Debug)]
pub enum CipherOpt {
................................................................................
    /// Encrypt using asymmetric encryption (encrypting for peer to read)
    Asymmetric {
        /// PublicKey of the peer to whom we want to encrypt
        peer_encrypt_key: box_::PublicKey,
    },
}

#[derive(Debug, Clone, Serialize, Deserialize)]
enum WireFormat {
    Plain(Vec<u8>),
    Symmetric {
        nonce: secretbox::Nonce,
        cipher_text: Vec<u8>,
    },
    Asymmetric(Vec<u8>),
................................................................................
}

/// Construct `CipherOpt::PlainText` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_plaintext(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      FfiResult,
                                                                      CipherOptHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
                        let handle = context
                            .object_cache()
                            .insert_cipher_opt(CipherOpt::PlainText);
                        o_cb(user_data.0, FFI_RESULT_OK, handle);
                        None
                    })
    });
}

/// Construct `CipherOpt::Symmetric` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_symmetric(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      FfiResult,
                                                                      CipherOptHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        (*app).send(move |_, context| {
                        let handle = context
                            .object_cache()
                            .insert_cipher_opt(CipherOpt::Symmetric);
                        o_cb(user_data.0, FFI_RESULT_OK, handle);
                        None
                    })
    })
}

/// Construct `CipherOpt::Asymmetric` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_new_asymmetric(app: *const App,
                                                   peer_encrypt_key_h: EncryptPubKeyHandle,
                                                   user_data: *mut c_void,
                                                   o_cb: extern "C" fn(*mut c_void,
                                                                       FfiResult,
                                                                       CipherOptHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let pk = match context
                      .object_cache()
                      .get_encrypt_key(peer_encrypt_key_h) {
                Ok(pk) => *pk,
                Err(e) => {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0);
                    return None;
                }
            };
            let handle = context
                .object_cache()
                .insert_cipher_opt(CipherOpt::Asymmetric { peer_encrypt_key: pk });
            o_cb(user_data.0, FFI_RESULT_OK, handle);
            None
        })
    });
}

/// Free `CipherOpt` handle
#[no_mangle]
pub unsafe extern "C" fn cipher_opt_free(app: *const App,
                                         handle: CipherOptHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_cipher_opt(handle);
            let (error_code, description) = ffi_result!(res);
            o_cb(user_data.0,
                 FfiResult {
                     error_code,
                     description: description.as_ptr(),
                 });
            None
        })
    });
}

#[cfg(test)]
mod tests {
................................................................................
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));

        let cipher_opt_handle: CipherOptHandle =
            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_plaintext(&app_0, ud, cb))) };

        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_handle));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, context));
            (plain_text, cipher_text)
        });
        assert_ne!(cipher_text, plain_text);
        assert_free(&app_0, cipher_opt_handle, 0);

        run_now(&app_0, move |client, context| {
            assert!(context
                        .object_cache()
                        .get_cipher_opt(cipher_opt_handle)
                        .is_err());
            assert!(decrypt_and_check(client, context, &cipher_text, &plain_text));
        });
    }

    #[test]
    fn app_0_to_app_0_sym() {
        let app_0 = create_app();
................................................................................

        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));
        let cipher_opt_handle: CipherOptHandle =
            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app_0, ud, cb))) };

        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_handle));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, context));
            (plain_text, cipher_text)
        });
        assert_ne!(cipher_text, plain_text);
        assert_free(&app_0, cipher_opt_handle, 0);

        run_now(&app_0, move |client, context| {
            assert!(context
                        .object_cache()
                        .get_cipher_opt(cipher_opt_handle)
                        .is_err());
            assert!(decrypt_and_check(client, context, &cipher_text, &plain_text));
        });
    }

    // NOTE: rustfmt is behaving erratically on this function. Disabling it for now.
    #[cfg_attr(rustfmt, rustfmt_skip)]
    #[test]
................................................................................
            unwrap!(call_1(|ud, cb| cipher_opt_new_asymmetric(&app_0, enc_pk_h, ud, cb)))
        };

        // Encrypt the plaintext on App 0's end.
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));
        let (plain_text, cipher_text) = run_now(&app_0, move |_, context| {
            let cipher_opt = unwrap!(context.object_cache().get_cipher_opt(cipher_opt_h));
            let cipher_text = unwrap!(cipher_opt.encrypt(&plain_text, context));
            (plain_text, cipher_text)
        });

        assert_ne!(cipher_text, plain_text);
        assert_free(&app_0, cipher_opt_h, 0);

        run_now(&app_0, move |_, context| {
            assert!(context.object_cache().get_cipher_opt(cipher_opt_h).is_err());
        });

        // App 0 cannot decrypt the ciphertext, because it was encrypted with
................................................................................
        let app = create_app();

        let peer_encrypt_key_handle = run_now(&app, |_, context| {
            let (pk, _) = box_::gen_keypair();
            context.object_cache().insert_encrypt_key(pk)
        });

        let cipher_opt_handle_pt =




            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_plaintext(&app, ud, cb))) };
        let cipher_opt_handle_sym =
            unsafe { unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app, ud, cb))) };

        let cipher_opt_handle_asym = unsafe {
            let err_code = AppError::InvalidEncryptPubKeyHandle.error_code();
            let res: Result<CipherOptHandle, _> =
                call_1(|ud, cb| cipher_opt_new_asymmetric(&app, 29293290, ud, cb));
            assert_eq!(unwrap!(res.err()), err_code);

            unwrap!(call_1(|ud, cb| {
                               cipher_opt_new_asymmetric(&app, peer_encrypt_key_handle, ud, cb)
                           }))
        };

        run_now(&app, move |_, context| {
            let obj_cache = context.object_cache();
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_pt));
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_sym));
            let _ = unwrap!(obj_cache.get_cipher_opt(cipher_opt_handle_asym));
        });

Added wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/crypto.rs version [7efad1432f].























































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which
// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be
// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.
//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use App;
use errors::AppError;
use ffi::helper::send_sync;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, catch_unwind_cb};
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::{EncryptPubKeyHandle, EncryptSecKeyHandle, SignKeyHandle};
use rust_sodium::crypto::{box_, sealedbox, sign};
use std::os::raw::c_void;
use std::ptr;
use std::slice;
use tiny_keccak::sha3_256;

type SecKey = [u8; box_::SECRETKEYBYTES];
type PubKey = [u8; box_::PUBLICKEYBYTES];

/// Get the public signing key of the app.
#[no_mangle]
pub unsafe extern "C" fn app_pub_sign_key(app: *const App,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void,
                                                              FfiResult,
                                                              SignKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |client, context| {
            let key = client.public_signing_key()?;
            Ok(context.object_cache().insert_sign_key(key))
        })
    })
}

/// Create new public signing key from raw array.
#[no_mangle]
pub unsafe extern "C" fn sign_key_new(app: *const App,
                                      data: *const PubKey,
                                      user_data: *mut c_void,
                                      o_cb: extern "C" fn(*mut c_void, FfiResult, SignKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = sign::PublicKey(*data);
        send_sync(app,
                  user_data,
                  o_cb,
                  move |_, context| Ok(context.object_cache().insert_sign_key(key)))
    })
}

/// Retrieve the public signing key as raw array.
#[no_mangle]
pub unsafe extern "C" fn sign_key_get(app: *const App,
                                      handle: SignKeyHandle,
                                      user_data: *mut c_void,
                                      o_cb: extern "C" fn(*mut c_void, FfiResult, *const PubKey)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let key = context.object_cache().get_sign_key(handle)?;
            Ok(&key.0)
        })
    })
}

/// Free signing key from memory
#[no_mangle]
pub unsafe extern "C" fn sign_key_free(app: *const App,
                                       handle: SignKeyHandle,
                                       user_data: *mut c_void,
                                       o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_sign_key(handle)?;
            Ok(())
        })
    })
}

/// Get the public encryption key of the app.
#[no_mangle]
pub unsafe extern "C" fn app_pub_enc_key(app: *const App,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             EncryptPubKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |client, context| {
            let key = client.public_encryption_key()?;
            Ok(context.object_cache().insert_encrypt_key(key))
        })
    })
}

/// Generate a new encryption key pair (public & private key).
#[no_mangle]
pub unsafe extern "C" fn enc_generate_key_pair(app: *const App,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   FfiResult,
                                                                   EncryptPubKeyHandle,
                                                                   EncryptSecKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let (ourpk, oursk) = box_::gen_keypair();
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |_, context| {
                        let pk_h = context.object_cache().insert_encrypt_key(ourpk);
                        let sk_h = context.object_cache().insert_secret_key(oursk);

                        o_cb(user_data.0, FFI_RESULT_OK, pk_h, sk_h);

                        None
                    })
    })
}

/// Create new public encryption key from raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_pub_key_new(app: *const App,
                                         data: *const PubKey,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             EncryptPubKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = box_::PublicKey(*data);
        send_sync(app,
                  user_data,
                  o_cb,
                  move |_, context| Ok(context.object_cache().insert_encrypt_key(key)))
    })
}

/// Retrieve the public encryption key as raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_pub_key_get(app: *const App,
                                         handle: EncryptPubKeyHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             *const PubKey)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let key = context.object_cache().get_encrypt_key(handle)?;
            Ok(&key.0)
        })
    })
}

/// Retrieve the private encryption key as raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_secret_key_get(app: *const App,
                                            handle: EncryptSecKeyHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                *const SecKey)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let key = context.object_cache().get_secret_key(handle)?;
            Ok(&key.0)
        })
    })
}

/// Create new public encryption key from raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_secret_key_new(app: *const App,
                                            data: *const SecKey,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                EncryptSecKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = box_::SecretKey(*data);
        send_sync(app,
                  user_data,
                  o_cb,
                  move |_, context| Ok(context.object_cache().insert_secret_key(key)))
    })
}

/// Free encryption key from memory
#[no_mangle]
pub unsafe extern "C" fn enc_pub_key_free(app: *const App,
                                          handle: EncryptPubKeyHandle,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_encrypt_key(handle)?;
            Ok(())
        })
    })
}

/// Free private key from memory
#[no_mangle]
pub unsafe extern "C" fn enc_secret_key_free(app: *const App,
                                             handle: EncryptSecKeyHandle,
                                             user_data: *mut c_void,
                                             o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_secret_key(handle)?;
            Ok(())
        })
    })
}

/// Encrypts arbitrary data using a given key pair.
/// You should provide a recipient's public key and a sender's secret key.
#[no_mangle]
pub unsafe extern "C" fn encrypt(app: *const App,
                                 data: *const u8,
                                 len: usize,
                                 pk_h: EncryptPubKeyHandle,
                                 sk_h: EncryptSecKeyHandle,
                                 user_data: *mut c_void,
                                 o_cb: extern "C" fn(*mut c_void, FfiResult, *const u8, usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let plaintext = slice::from_raw_parts(data, len);

        (*app).send(move |_, context| {
            let pk = try_cb!(context.object_cache().get_encrypt_key(pk_h),
                             user_data,
                             o_cb);
            let sk = try_cb!(context.object_cache().get_secret_key(sk_h), user_data, o_cb);

            let nonce = box_::gen_nonce();

            let ciphertext = box_::seal(plaintext, &nonce, &pk, &sk);

            match serialise(&(nonce, ciphertext)) {
                Ok(result) => o_cb(user_data.0, FFI_RESULT_OK, result.as_ptr(), result.len()),
                Err(e) => {
                    let e = AppError::from(e);
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0)
                }
            }

            None
        })
    })
}

/// Decrypts arbitrary data using a given key pair.
/// You should provide a sender's public key and a recipient's secret key.
#[no_mangle]
pub unsafe extern "C" fn decrypt(app: *const App,
                                 data: *const u8,
                                 len: usize,
                                 pk_h: EncryptPubKeyHandle,
                                 sk_h: EncryptSecKeyHandle,
                                 user_data: *mut c_void,
                                 o_cb: extern "C" fn(*mut c_void, FfiResult, *const u8, usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let plaintext = slice::from_raw_parts(data, len);

        (*app).send(move |_, context| {
            let pk = try_cb!(context.object_cache().get_encrypt_key(pk_h),
                             user_data,
                             o_cb);
            let sk = try_cb!(context.object_cache().get_secret_key(sk_h), user_data, o_cb);

            match deserialise::<(box_::Nonce, Vec<u8>)>(plaintext) {
                Ok((nonce, ciphertext)) => {
                    let plaintext =
                        try_cb!(box_::open(&ciphertext, &nonce, &pk, &sk)
                                .map_err(|()| AppError::EncodeDecodeError), user_data, o_cb);
                    o_cb(user_data.0,
                         FFI_RESULT_OK,
                         plaintext.as_ptr(),
                         plaintext.len());
                }
                Err(e) => {
                    let e = AppError::from(e);
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0)
                }
            }

            None
        })
    })
}

/// Encrypts arbitrary data for a single recipient.
/// You should provide a recipient's public key.
#[no_mangle]
pub unsafe extern "C" fn encrypt_sealed_box(app: *const App,
                                            data: *const u8,
                                            len: usize,
                                            pk_h: EncryptPubKeyHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                *const u8,
                                                                usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let plaintext = slice::from_raw_parts(data, len);
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |_, context| {
            let pk = *try_cb!(context.object_cache().get_encrypt_key(pk_h),
                              user_data,
                              o_cb);

            let ciphertext = sealedbox::seal(plaintext, &pk);
            o_cb(user_data.0,
                 FFI_RESULT_OK,
                 ciphertext.as_ptr(),
                 ciphertext.len());

            None
        })
    })
}

/// Decrypts arbitrary data for a single recipient.
/// You should provide a recipients's private and public key.
#[no_mangle]
pub unsafe extern "C" fn decrypt_sealed_box(app: *const App,
                                            data: *const u8,
                                            len: usize,
                                            pk_h: EncryptPubKeyHandle,
                                            sk_h: EncryptSecKeyHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                *const u8,
                                                                usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let plaintext = slice::from_raw_parts(data, len);

        (*app).send(move |_, context| {
            let pk = try_cb!(context.object_cache().get_encrypt_key(pk_h),
                             user_data,
                             o_cb);
            let sk = try_cb!(context.object_cache().get_secret_key(sk_h), user_data, o_cb);

            let plaintext =
                try_cb!(sealedbox::open(plaintext, &pk, &sk)
                                    .map_err(|()| AppError::EncodeDecodeError), user_data, o_cb);
            o_cb(user_data.0,
                 FFI_RESULT_OK,
                 plaintext.as_ptr(),
                 plaintext.len());

            None
        })
    })
}

/// Returns a sha3 hash for a given data.
#[no_mangle]
pub unsafe extern "C" fn sha3_hash(data: *const u8,
                                   len: usize,
                                   user_data: *mut c_void,
                                   o_cb: extern "C" fn(*mut c_void, FfiResult, *const u8, usize)) {
    catch_unwind_cb(user_data, o_cb, || -> Result<(), AppError> {
        let plaintext = slice::from_raw_parts(data, len);
        let user_data = OpaqueCtx(user_data);

        let hash = sha3_256(plaintext);
        o_cb(user_data.0, FFI_RESULT_OK, hash.as_ptr(), hash.len());

        Ok(())
    });
}

#[cfg(test)]
mod tests {
    use super::*;
    use ffi_utils::test_utils::{call_1, call_2, call_vec_u8};
    use routing::XOR_NAME_LEN;
    use test_utils::{create_app, run_now};

    #[test]
    fn encrypt_decrypt() {
        let app1 = create_app();
        let app2 = create_app();

        let (app1_pk1_h, app1_sk1_h): (EncryptPubKeyHandle, EncryptSecKeyHandle) =
            unsafe { unwrap!(call_2(|ud, cb| enc_generate_key_pair(&app1, ud, cb))) };
        let (app2_pk2_h, app2_sk2_h): (EncryptPubKeyHandle, EncryptSecKeyHandle) =
            unsafe { unwrap!(call_2(|ud, cb| enc_generate_key_pair(&app2, ud, cb))) };

        // Copying app2 pubkey to app1 object cache
        // and app1 pubkey to app2 object cache
        let pk2_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_get(&app2, app2_pk2_h, ud, cb))) };
        let pk1_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_get(&app1, app1_pk1_h, ud, cb))) };

        let app1_pk2_h =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_new(&app1, &pk2_raw, ud, cb))) };
        let app2_pk1_h =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_new(&app2, &pk1_raw, ud, cb))) };

        // Trying to encrypt a message for app2 from app1
        let data = b"hi there";
        let encrypted = unsafe {
            unwrap!(call_vec_u8(|ud, cb| {
                encrypt(&app1,
                        data.as_ptr(),
                        data.len(),
                        app1_pk2_h,
                        app1_sk1_h,
                        ud,
                        cb)
            }))
        };

        // Trying to decrypt the message in app2
        let decrypted = unsafe {
            unwrap!(call_vec_u8(|ud, cb| {
                decrypt(&app2,
                        encrypted.as_ptr(),
                        encrypted.len(),
                        app2_pk1_h,
                        app2_sk2_h,
                        ud,
                        cb)
            }))
        };

        assert_eq!(&decrypted, data);
    }

    #[test]
    fn encrypt_decrypt_sealed() {
        let app1 = create_app();
        let app2 = create_app();

        let (app2_pk2_h, app2_sk2_h): (EncryptPubKeyHandle, EncryptSecKeyHandle) =
            unsafe { unwrap!(call_2(|ud, cb| enc_generate_key_pair(&app2, ud, cb))) };

        // Copying app2 pubkey to app1 object cache
        // and app1 pubkey to app2 object cache
        let pk2_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_get(&app2, app2_pk2_h, ud, cb))) };

        let app1_pk2_h =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_new(&app1, &pk2_raw, ud, cb))) };

        // Trying to encrypt a message for app2 from app1
        let data = b"sealed box message";
        let encrypted = unsafe {
            unwrap!(call_vec_u8(|ud, cb| {
                                    encrypt_sealed_box(&app1,
                                                       data.as_ptr(),
                                                       data.len(),
                                                       app1_pk2_h,
                                                       ud,
                                                       cb)
                                }))
        };

        // Trying to decrypt the message in app2
        let decrypted = unsafe {
            unwrap!(call_vec_u8(|ud, cb| {
                decrypt_sealed_box(&app2,
                                   encrypted.as_ptr(),
                                   encrypted.len(),
                                   app2_pk2_h,
                                   app2_sk2_h,
                                   ud,
                                   cb)
            }))
        };

        assert_eq!(&decrypted, data);
    }

    #[test]
    fn sign_key_basics() {
        let app = create_app();
        let app_sign_key1_h = unsafe { unwrap!(call_1(|ud, cb| app_pub_sign_key(&app, ud, cb))) };

        let app_sign_key1 = run_now(&app, move |client, context| {
            let app_sign_key1 = unwrap!(client.public_signing_key());
            let app_sign_key2 = unwrap!(context.object_cache().get_sign_key(app_sign_key1_h));
            assert_eq!(app_sign_key1, *app_sign_key2);

            app_sign_key1
        });

        let app_sign_key1_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| sign_key_get(&app, app_sign_key1_h, ud, cb))) };

        let app_sign_key2_h =
            unsafe { unwrap!(call_1(|ud, cb| sign_key_new(&app, &app_sign_key1_raw, ud, cb))) };

        let app_sign_key2 = run_now(&app, move |_, context| {
            *unwrap!(context.object_cache().get_sign_key(app_sign_key2_h))
        });

        assert_eq!(app_sign_key1, app_sign_key2);
    }

    #[test]
    fn enc_key_basics() {
        let app = create_app();
        let app_enc_key1_h = unsafe { unwrap!(call_1(|ud, cb| app_pub_enc_key(&app, ud, cb))) };

        let app_enc_key1 = run_now(&app, move |client, context| {
            let app_enc_key1 = unwrap!(client.public_encryption_key());
            let app_enc_key2 = unwrap!(context.object_cache().get_encrypt_key(app_enc_key1_h));
            assert_eq!(app_enc_key1, *app_enc_key2);

            app_enc_key1
        });

        let app_enc_key1_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_get(&app, app_enc_key1_h, ud, cb))) };

        let app_enc_key2_h =
            unsafe { unwrap!(call_1(|ud, cb| enc_pub_key_new(&app, &app_enc_key1_raw, ud, cb))) };

        let app_enc_key2 = run_now(&app, move |_, context| {
            *unwrap!(context.object_cache().get_encrypt_key(app_enc_key2_h))
        });

        assert_eq!(app_enc_key1, app_enc_key2);
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/helper.rs from [9fa305d069] to [1cde45235a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
41
42
43
44
45
46
47
48


49






50
51
52
53
54
55
56
..
68
69
70
71
72
73
74
75
76


77






78
79
80
81
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use App;
use AppContext;
use errors::AppError;
use ffi_utils::OpaqueCtx;
use ffi_utils::callback::{Callback, CallbackArgs};
use futures::Future;
use object_cache::MDataInfoHandle;
use safe_core::{Client, FutureExt, MDataInfo};
use std::fmt::Debug;
use std::os::raw::c_void;

................................................................................
    where C: Callback + Copy + Send + 'static,
          F: FnOnce(&Client, &AppContext) -> Result<C::Args, AppError> + Send + 'static
{
    let user_data = OpaqueCtx(user_data);

    (*app).send(move |client, context| {
        match f(client, context) {
            Ok(args) => o_cb.call(user_data.0, 0, args),


            Err(err) => o_cb.call(user_data.0, ffi_error_code!(err), C::Args::default()),






        }

        None
    })
}

// Helper to reduce boilerplate when sending asynchronous operations to the app
................................................................................
          AppError: From<E>
{
    let user_data = OpaqueCtx(user_data);

    (*app).send(move |client, context| {
        let info = try_cb!(context.object_cache().get_mdata_info(info_h), user_data, cb);
        f(client, context, &*info)
            .map(move |args| cb.call(user_data.0, 0, args))
            .map_err(AppError::from)


            .map_err(move |err| cb.call(user_data.0, ffi_error_code!(err), C::Args::default()))






            .into_box()
            .into()
    })
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|




|







 







|
>
>
|
>
>
>
>
>
>







 







|

>
>
|
>
>
>
>
>
>




1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use App;
use AppContext;
use errors::AppError;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx};
use ffi_utils::callback::{Callback, CallbackArgs};
use futures::Future;
use object_cache::MDataInfoHandle;
use safe_core::{Client, FutureExt, MDataInfo};
use std::fmt::Debug;
use std::os::raw::c_void;

................................................................................
    where C: Callback + Copy + Send + 'static,
          F: FnOnce(&Client, &AppContext) -> Result<C::Args, AppError> + Send + 'static
{
    let user_data = OpaqueCtx(user_data);

    (*app).send(move |client, context| {
        match f(client, context) {
            Ok(args) => o_cb.call(user_data.0, FFI_RESULT_OK, args),
            Err(err) => {
                let (error_code, description) = ffi_error!(err);
                o_cb.call(user_data.0,
                          FfiResult {
                              error_code,
                              description: description.as_ptr(),
                          },
                          C::Args::default())
            }
        }

        None
    })
}

// Helper to reduce boilerplate when sending asynchronous operations to the app
................................................................................
          AppError: From<E>
{
    let user_data = OpaqueCtx(user_data);

    (*app).send(move |client, context| {
        let info = try_cb!(context.object_cache().get_mdata_info(info_h), user_data, cb);
        f(client, context, &*info)
            .map(move |args| cb.call(user_data.0, FFI_RESULT_OK, args))
            .map_err(AppError::from)
            .map_err(move |err| {
                let (error_code, description) = ffi_error!(err);
                cb.call(user_data.0,
                        FfiResult {
                            error_code,
                            description: description.as_ptr(),
                        },
                        C::Args::default())
            })
            .into_box()
            .into()
    })
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/immutable_data.rs from [83f10a4371] to [e8b1a05ba2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59








60
61
62
63
64
65
66
..
67
68
69
70
71
72
73
74

75
76
77
78
79
80
81
82
83
84

85




86
87
88
89
90
91

92




93
94
95
96
97
98
99
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122

123
124
125
126
127
128
129
130
131
132
133
134

135
136
137
138

139
140
141
142
143
144
145


146






147
148
149
150
151
152
153
...
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
...
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190








191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211

212





213
214
215
216
217
218
219
...
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238

239






240
241
242
243
244


245
246




247
248
249
250
251
252
253
254
255









256
257
258
259
260
261
262
263
264
265
266
267
268

269
270
271
272
273

274




275
276
277
278
279
280
281
282
283
284
285

286
287
288
289
290

291




292
293
294
295
296
297
298
...
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337

338




339
340
341
342
343
344
345
346
...
353
354
355
356
357
358
359

360
361
362
363
364
365
366


367
368
369
370
371
372
373
374
375
376
377
378
379
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use super::cipher_opt::CipherOpt;
use App;
use errors::AppError;
use ffi_utils::{OpaqueCtx, catch_unwind_cb, vec_clone_from_raw_parts};
use futures::Future;
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::{CipherOptHandle, SelfEncryptorReaderHandle, SelfEncryptorWriterHandle};
use routing::{XOR_NAME_LEN, XorName};
use safe_core::{FutureExt, SelfEncryptionStorage, immutable_data};
use self_encryption::{SelfEncryptor, SequentialEncryptor};
use std::os::raw::c_void;
................................................................................
type XorNamePtr = *const [u8; XOR_NAME_LEN];

/// Get a Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_new_self_encryptor(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      i32,
                                                                      SEWriterHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |client, context| {
            let se_storage = SelfEncryptionStorage::new(client.clone());
            let context = context.clone();

            let fut = SequentialEncryptor::new(se_storage, None)
                .map_err(AppError::from)
                .map(move |se| {
                    let handle = context.object_cache().insert_se_writer(se);
                    o_cb(user_data.0, 0, handle);
                })
                .map_err(move |e| { o_cb(user_data.0, ffi_error_code!(e), 0); })








                .into_box();

            Some(fut)
        })
    });
}

................................................................................
/// Write to Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_write_to_self_encryptor(app: *const App,
                                                       se_h: SEWriterHandle,
                                                       data: *const u8,
                                                       size: usize,
                                                       user_data: *mut c_void,
                                                       o_cb: extern "C" fn(*mut c_void, i32)) {

    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        let data_slice = vec_clone_from_raw_parts(data, size);

        (*app).send(move |_, context| {
            let fut = {
                match context.object_cache().get_se_writer(se_h) {
                    Ok(writer) => writer.write(&data_slice),
                    Err(e) => {

                        o_cb(user_data.0, ffi_error_code!(e));




                        return None;
                    }
                }
            };
            let fut = fut.map_err(AppError::from)
                .then(move |res| {

                    o_cb(user_data.0, ffi_result_code!(res));




                    Ok(())
                })
                .into_box();
            Some(fut)
        })
    });
}
................................................................................
/// Close Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_close_self_encryptor(app: *const App,
                                                    se_h: SEWriterHandle,
                                                    cipher_opt_h: CipherOptHandle,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void,
                                                                        i32,
                                                                        XorNamePtr)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |client, context| {
            let client2 = client.clone();
            let client3 = client.clone();
            let context2 = context.clone();

            let se_writer = try_cb!(context.object_cache().remove_se_writer(se_h),
                                    user_data,
                                    o_cb);

            se_writer.close()

                .map_err(AppError::from)
                .and_then(move |(data_map, _)| {
                    let ser_data_map = serialise(&data_map)?;
                    let enc_data_map = {
                        let cipher_opt = context2.object_cache().get_cipher_opt(cipher_opt_h)?;
                        cipher_opt.encrypt(&ser_data_map, &context2)?
                    };

                    Ok(enc_data_map)
                })
                .and_then(move |enc_data_map| {
                    immutable_data::create(&client2, enc_data_map, None).map_err(AppError::from)

                })
                .and_then(move |data| {
                    let name = *data.name();


                    client3.put_idata(data)
                        .map_err(AppError::from)
                        .map(move |_| name)
                })
                .then(move |result| {
                    match result {
                        Ok(name) => o_cb(user_data.0, 0, &name.0),


                        Err(e) => o_cb(user_data.0, ffi_error_code!(e), ptr::null()),






                    }
                    Ok(())
                })
                .into_box()
                .into()
        })
    });
................................................................................

/// Fetch Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_fetch_self_encryptor(app: *const App,
                                                    name: XorNamePtr,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void,
                                                                        i32,
                                                                        SEReaderHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = XorName(*name);

        (*app).send(move |client, context| {
            let client2 = client.clone();
................................................................................
            let client3 = client.clone();
            let context2 = context.clone();
            let context3 = context.clone();

            immutable_data::get_value(client, &name, None)
                .map_err(AppError::from)
                .and_then(move |enc_data_map| {

                    let ser_data_map = CipherOpt::decrypt(&enc_data_map, &context2, &client2)?;
                    let data_map = deserialise(&ser_data_map)?;

                    Ok(data_map)
                })
                .and_then(move |data_map| {
                    let se_storage = SelfEncryptionStorage::new(client3);
                    SelfEncryptor::new(se_storage, data_map).map_err(AppError::from)
                })
                .map(move |se_reader| {
                    let handle = context3.object_cache().insert_se_reader(se_reader);
                    o_cb(user_data.0, 0, handle);
                })
                .map_err(move |e| { o_cb(user_data.0, ffi_error_code!(e), 0); })








                .into_box()
                .into()
        })
    });
}

/// Get data size from Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_size(app: *const App,
                                    se_h: SEReaderHandle,
                                    user_data: *mut c_void,
                                    o_cb: extern "C" fn(*mut c_void, i32, u64)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            match context.object_cache().get_se_reader(se_h) {
                Ok(se) => {
                    o_cb(user_data.0, 0, se.len());
                }
                Err(e) => {

                    o_cb(user_data.0, ffi_error_code!(e), 0);





                }
            };
            None
        })
    });
}

................................................................................
#[no_mangle]
pub unsafe extern "C" fn idata_read_from_self_encryptor(app: *const App,
                                                        se_h: SEReaderHandle,
                                                        from_pos: u64,
                                                        len: u64,
                                                        user_data: *mut c_void,
                                                        o_cb: extern "C" fn(*mut c_void,
                                                                            i32,
                                                                            *const u8,
                                                                            usize)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let se = match context.object_cache().get_se_reader(se_h) {
                Ok(r) => r,
                Err(e) => {

                    o_cb(user_data.0, ffi_error_code!(e), ptr::null(), 0);






                    return None;
                }
            };

            if from_pos + len > se.len() {


                o_cb(user_data.0,
                     ffi_error_code!(AppError::InvalidSelfEncryptorReadOffsets),




                     ptr::null_mut(),
                     0);
                return None;
            }

            let fut = se.read(from_pos, len)
                .map(move |data| { o_cb(user_data.0, 0, data.as_ptr(), data.len()); })
                .map_err(AppError::from)
                .map_err(move |e| { o_cb(user_data.0, ffi_error_code!(e), ptr::null(), 0); })









                .into_box();

            Some(fut)
        })
    });
}

/// Free Self Encryptor Writer handle
#[no_mangle]
pub unsafe extern "C" fn idata_self_encryptor_writer_free(app: *const App,
                                                          handle: SEWriterHandle,
                                                          user_data: *mut c_void,
                                                          o_cb: extern "C" fn(*mut c_void, i32)) {

    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_se_writer(handle);

            o_cb(user_data.0, ffi_result_code!(res));




            None
        })
    });
}

/// Free Self Encryptor Reader handle
#[no_mangle]
pub unsafe extern "C" fn idata_self_encryptor_reader_free(app: *const App,
                                                          handle: SEReaderHandle,
                                                          user_data: *mut c_void,
                                                          o_cb: extern "C" fn(*mut c_void, i32)) {

    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_se_reader(handle);

            o_cb(user_data.0, ffi_result_code!(res));




            None
        })
    })
}

#[cfg(test)]
mod tests {
................................................................................
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));

        unsafe {
            let cipher_opt_h = unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app, ud, cb)));
            let se_writer_h = unwrap!(call_1(|ud, cb| idata_new_self_encryptor(&app, ud, cb)));

            let res = call_0(|ud, cb| {
                idata_write_to_self_encryptor(&app,
                                              0,
                                              plain_text.as_ptr(),
                                              plain_text.len(),
                                              ud,
                                              cb)
            });
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            unwrap!(call_0(|ud, cb| {
                idata_write_to_self_encryptor(&app,
                                              se_writer_h,
                                              plain_text.as_ptr(),
                                              plain_text.len(),
                                              ud,
                                              cb)
            }));

            let name: [u8; XOR_NAME_LEN] = unwrap!(call_1(|ud, cb| {

                idata_close_self_encryptor(&app, se_writer_h, cipher_opt_h, ud, cb)




            }));

            // It should've been closed by immut_data_close_self_encryptor
            let res = call_0(|ud, cb| idata_self_encryptor_writer_free(&app, se_writer_h, ud, cb));
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            // Invalid Self encryptor reader.
            let res: Result<u64, _> = call_1(|ud, cb| idata_size(&app, 0, ud, cb));
................................................................................
            let se_reader_h = {
                unwrap!(call_1(|ud, cb| idata_fetch_self_encryptor(&app, &name, ud, cb)))
            };

            let size = unwrap!(call_1(|ud, cb| idata_size(&app, se_reader_h, ud, cb)));
            assert_eq!(size, plain_text.len() as u64);


            let res = call_vec_u8(|ud, cb| {
                idata_read_from_self_encryptor(&app, se_reader_h, 1, size, ud, cb)
            });
            assert_eq!(res,
                       Err(AppError::InvalidSelfEncryptorReadOffsets.error_code()));

            let received_plain_text = unwrap!(call_vec_u8(|ud, cb| {


                idata_read_from_self_encryptor(&app, se_reader_h, 0, size, ud, cb)
            }));
            assert_eq!(plain_text, received_plain_text);

            unwrap!(call_0(|ud, cb| idata_self_encryptor_reader_free(&app, se_reader_h, ud, cb)));

            let res = call_0(|ud, cb| idata_self_encryptor_reader_free(&app, se_reader_h, ud, cb));
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            unwrap!(call_0(|ud, cb| cipher_opt_free(&app, cipher_opt_h, ud, cb)));
        }
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|




|







 







|











|
|
|
|
>
>
>
>
>
>
>
>







 







|
>










>
|
>
>
>
>






>
|
>
>
>
>







 







|













|
>











|
>
|

|

>
|
|
|
|


|
>
>
|
>
>
>
>
>
>







 







|







 







>
|
|

|
|

|
|
|

|
|
|
|
>
>
>
>
>
>
>
>











|






|


>
|
>
>
>
>
>







 







|









>
|
>
>
>
>
>
>





>
>

<
>
>
>
>






|

|
>
>
>
>
>
>
>
>
>












|
>





>
|
>
>
>
>










|
>





>
|
>
>
>
>







 







|
|
|
|
|
|
|



|
|
|
|
|
|
|

|
>
|
>
>
>
>
|







 







>
|
|
|



|
>
>
|
|
|










1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
..
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295

296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
...
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
...
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use super::cipher_opt::CipherOpt;
use App;
use errors::AppError;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, catch_unwind_cb, vec_clone_from_raw_parts};
use futures::Future;
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::{CipherOptHandle, SelfEncryptorReaderHandle, SelfEncryptorWriterHandle};
use routing::{XOR_NAME_LEN, XorName};
use safe_core::{FutureExt, SelfEncryptionStorage, immutable_data};
use self_encryption::{SelfEncryptor, SequentialEncryptor};
use std::os::raw::c_void;
................................................................................
type XorNamePtr = *const [u8; XOR_NAME_LEN];

/// Get a Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_new_self_encryptor(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      FfiResult,
                                                                      SEWriterHandle)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |client, context| {
            let se_storage = SelfEncryptionStorage::new(client.clone());
            let context = context.clone();

            let fut = SequentialEncryptor::new(se_storage, None)
                .map_err(AppError::from)
                .map(move |se| {
                         let handle = context.object_cache().insert_se_writer(se);
                         o_cb(user_data.0, FFI_RESULT_OK, handle);
                     })
                .map_err(move |e| {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0);
                })
                .into_box();

            Some(fut)
        })
    });
}

................................................................................
/// Write to Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_write_to_self_encryptor(app: *const App,
                                                       se_h: SEWriterHandle,
                                                       data: *const u8,
                                                       size: usize,
                                                       user_data: *mut c_void,
                                                       o_cb: extern "C" fn(*mut c_void,
                                                                           FfiResult)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        let data_slice = vec_clone_from_raw_parts(data, size);

        (*app).send(move |_, context| {
            let fut = {
                match context.object_cache().get_se_writer(se_h) {
                    Ok(writer) => writer.write(&data_slice),
                    Err(e) => {
                        let (error_code, description) = ffi_error!(e);
                        o_cb(user_data.0,
                             FfiResult {
                                 error_code,
                                 description: description.as_ptr(),
                             });
                        return None;
                    }
                }
            };
            let fut = fut.map_err(AppError::from)
                .then(move |res| {
                    let (error_code, description) = ffi_result!(res);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box();
            Some(fut)
        })
    });
}
................................................................................
/// Close Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_close_self_encryptor(app: *const App,
                                                    se_h: SEWriterHandle,
                                                    cipher_opt_h: CipherOptHandle,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void,
                                                                        FfiResult,
                                                                        XorNamePtr)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |client, context| {
            let client2 = client.clone();
            let client3 = client.clone();
            let context2 = context.clone();

            let se_writer = try_cb!(context.object_cache().remove_se_writer(se_h),
                                    user_data,
                                    o_cb);

            se_writer
                .close()
                .map_err(AppError::from)
                .and_then(move |(data_map, _)| {
                    let ser_data_map = serialise(&data_map)?;
                    let enc_data_map = {
                        let cipher_opt = context2.object_cache().get_cipher_opt(cipher_opt_h)?;
                        cipher_opt.encrypt(&ser_data_map, &context2)?
                    };

                    Ok(enc_data_map)
                })
                .and_then(move |enc_data_map| {
                              immutable_data::create(&client2, &enc_data_map, None)
                                  .map_err(AppError::from)
                          })
                .and_then(move |data| {
                              let name = *data.name();

                              client3
                                  .put_idata(data)
                                  .map_err(AppError::from)
                                  .map(move |_| name)
                          })
                .then(move |result| {
                    match result {
                        Ok(name) => o_cb(user_data.0, FFI_RESULT_OK, &name.0),
                        Err(e) => {
                            let (error_code, description) = ffi_error!(e);
                            o_cb(user_data.0,
                                 FfiResult {
                                     error_code,
                                     description: description.as_ptr(),
                                 },
                                 ptr::null())
                        }
                    }
                    Ok(())
                })
                .into_box()
                .into()
        })
    });
................................................................................

/// Fetch Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_fetch_self_encryptor(app: *const App,
                                                    name: XorNamePtr,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void,
                                                                        FfiResult,
                                                                        SEReaderHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let name = XorName(*name);

        (*app).send(move |client, context| {
            let client2 = client.clone();
................................................................................
            let client3 = client.clone();
            let context2 = context.clone();
            let context3 = context.clone();

            immutable_data::get_value(client, &name, None)
                .map_err(AppError::from)
                .and_then(move |enc_data_map| {
                              let ser_data_map =
                                  CipherOpt::decrypt(&enc_data_map, &context2, &client2)?;
                              let data_map = deserialise(&ser_data_map)?;

                              Ok(data_map)
                          })
                .and_then(move |data_map| {
                              let se_storage = SelfEncryptionStorage::new(client3);
                              SelfEncryptor::new(se_storage, data_map).map_err(AppError::from)
                          })
                .map(move |se_reader| {
                         let handle = context3.object_cache().insert_se_reader(se_reader);
                         o_cb(user_data.0, FFI_RESULT_OK, handle);
                     })
                .map_err(move |e| {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0);
                })
                .into_box()
                .into()
        })
    });
}

/// Get data size from Self Encryptor
#[no_mangle]
pub unsafe extern "C" fn idata_size(app: *const App,
                                    se_h: SEReaderHandle,
                                    user_data: *mut c_void,
                                    o_cb: extern "C" fn(*mut c_void, FfiResult, u64)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            match context.object_cache().get_se_reader(se_h) {
                Ok(se) => {
                    o_cb(user_data.0, FFI_RESULT_OK, se.len());
                }
                Err(e) => {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0);
                }
            };
            None
        })
    });
}

................................................................................
#[no_mangle]
pub unsafe extern "C" fn idata_read_from_self_encryptor(app: *const App,
                                                        se_h: SEReaderHandle,
                                                        from_pos: u64,
                                                        len: u64,
                                                        user_data: *mut c_void,
                                                        o_cb: extern "C" fn(*mut c_void,
                                                                            FfiResult,
                                                                            *const u8,
                                                                            usize)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let se = match context.object_cache().get_se_reader(se_h) {
                Ok(r) => r,
                Err(e) => {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0);
                    return None;
                }
            };

            if from_pos + len > se.len() {
                let (error_code, description) =
                    ffi_error!(AppError::InvalidSelfEncryptorReadOffsets);
                o_cb(user_data.0,

                     FfiResult {
                         error_code,
                         description: description.as_ptr(),
                     },
                     ptr::null_mut(),
                     0);
                return None;
            }

            let fut = se.read(from_pos, len)
                .map(move |data| { o_cb(user_data.0, FFI_RESULT_OK, data.as_ptr(), data.len()); })
                .map_err(AppError::from)
                .map_err(move |e| {
                    let (error_code, description) = ffi_error!(e);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0);
                })
                .into_box();

            Some(fut)
        })
    });
}

/// Free Self Encryptor Writer handle
#[no_mangle]
pub unsafe extern "C" fn idata_self_encryptor_writer_free(app: *const App,
                                                          handle: SEWriterHandle,
                                                          user_data: *mut c_void,
                                                          o_cb: extern "C" fn(*mut c_void,
                                                                              FfiResult)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_se_writer(handle);
            let (error_code, description) = ffi_result!(res);
            o_cb(user_data.0,
                 FfiResult {
                     error_code,
                     description: description.as_ptr(),
                 });
            None
        })
    });
}

/// Free Self Encryptor Reader handle
#[no_mangle]
pub unsafe extern "C" fn idata_self_encryptor_reader_free(app: *const App,
                                                          handle: SEReaderHandle,
                                                          user_data: *mut c_void,
                                                          o_cb: extern "C" fn(*mut c_void,
                                                                              FfiResult)) {
    let user_data = OpaqueCtx(user_data);

    catch_unwind_cb(user_data, o_cb, || {
        (*app).send(move |_, context| {
            let res = context.object_cache().remove_se_reader(handle);
            let (error_code, description) = ffi_result!(res);
            o_cb(user_data.0,
                 FfiResult {
                     error_code,
                     description: description.as_ptr(),
                 });
            None
        })
    })
}

#[cfg(test)]
mod tests {
................................................................................
        let plain_text = unwrap!(utils::generate_random_vector::<u8>(10));

        unsafe {
            let cipher_opt_h = unwrap!(call_1(|ud, cb| cipher_opt_new_symmetric(&app, ud, cb)));
            let se_writer_h = unwrap!(call_1(|ud, cb| idata_new_self_encryptor(&app, ud, cb)));

            let res = call_0(|ud, cb| {
                                 idata_write_to_self_encryptor(&app,
                                                               0,
                                                               plain_text.as_ptr(),
                                                               plain_text.len(),
                                                               ud,
                                                               cb)
                             });
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            unwrap!(call_0(|ud, cb| {
                               idata_write_to_self_encryptor(&app,
                                                             se_writer_h,
                                                             plain_text.as_ptr(),
                                                             plain_text.len(),
                                                             ud,
                                                             cb)
                           }));

            let name: [u8; XOR_NAME_LEN];
            name = unwrap!(call_1(|ud, cb| {
                                      idata_close_self_encryptor(&app,
                                                                 se_writer_h,
                                                                 cipher_opt_h,
                                                                 ud,
                                                                 cb)
                                  }));

            // It should've been closed by immut_data_close_self_encryptor
            let res = call_0(|ud, cb| idata_self_encryptor_writer_free(&app, se_writer_h, ud, cb));
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            // Invalid Self encryptor reader.
            let res: Result<u64, _> = call_1(|ud, cb| idata_size(&app, 0, ud, cb));
................................................................................
            let se_reader_h = {
                unwrap!(call_1(|ud, cb| idata_fetch_self_encryptor(&app, &name, ud, cb)))
            };

            let size = unwrap!(call_1(|ud, cb| idata_size(&app, se_reader_h, ud, cb)));
            assert_eq!(size, plain_text.len() as u64);

            let res =
                call_vec_u8(|ud, cb| {
                                idata_read_from_self_encryptor(&app, se_reader_h, 1, size, ud, cb)
                            });
            assert_eq!(res,
                       Err(AppError::InvalidSelfEncryptorReadOffsets.error_code()));

            let received_plain_text;
            received_plain_text =
                call_vec_u8(|ud, cb| {
                                idata_read_from_self_encryptor(&app, se_reader_h, 0, size, ud, cb)
                            });
            assert_eq!(plain_text, unwrap!(received_plain_text));

            unwrap!(call_0(|ud, cb| idata_self_encryptor_reader_free(&app, se_reader_h, ud, cb)));

            let res = call_0(|ud, cb| idata_self_encryptor_reader_free(&app, se_reader_h, ud, cb));
            assert_eq!(res, Err(AppError::InvalidSelfEncryptorHandle.error_code()));

            unwrap!(call_0(|ud, cb| cipher_opt_free(&app, cipher_opt_h, ud, cb)));
        }
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/ipc.rs from [54aa15d45a] to [59d27e6ed2].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
..
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
87
88
89
90
91
92
93
94
95
96
97
98
99

100


101
102
103
104
105
106
107
108







109
110
111

112





113

114



115


116
117

118








119
120
121
122
123
124
125
...
159
160
161
162
163
164
165


166

167
168
169
170
171
172
173
...
188
189
190
191
192
193
194


195

196
197
198
199
200
201
202
...
259
260
261
262
263
264
265

266
267
268
269
270
271
272
273
...
328
329
330
331
332
333
334

335
336
337
338
339
340
341
342
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! App-related IPC utilities.

use errors::AppError;
use ffi_utils::{ReprC, catch_unwind_cb, from_c_str};
use safe_core::ipc::{self, AuthReq, ContainersReq, IpcError, IpcMsg, IpcReq, IpcResp};
use safe_core::ipc::req::ffi::AuthReq as FfiAuthReq;
use safe_core::ipc::req::ffi::ContainersReq as FfiContainersReq;
use safe_core::ipc::resp::ffi::AuthGranted as FfiAuthGranted;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};

/// Encode `AuthReq`.
#[no_mangle]
pub unsafe extern "C" fn encode_auth_req(req: *const FfiAuthReq,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             i32,
                                                             u32,
                                                             *const c_char)) {
    catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
        let req_id = ipc::gen_req_id();
        let req = AuthReq::clone_from_repr_c(req)?;

        let msg = IpcMsg::Req {
................................................................................
            req_id: req_id,
            req: IpcReq::Auth(req),
        };

        let encoded = ipc::encode_msg(&msg, "safe-auth")?;
        let encoded = CString::new(encoded)?;

        o_cb(user_data, 0, req_id, encoded.as_ptr());

        Ok(())
    })
}

/// Encode `ContainersReq`.
#[no_mangle]
pub unsafe extern "C" fn encode_containers_req(req: *const FfiContainersReq,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   i32,
                                                                   u32,
                                                                   *const c_char)) {
    catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
        let req_id = ipc::gen_req_id();
        let req = ContainersReq::clone_from_repr_c(req)?;

        let msg = IpcMsg::Req {
................................................................................
            req_id: req_id,
            req: IpcReq::Containers(req),
        };

        let encoded = ipc::encode_msg(&msg, "safe-auth")?;
        let encoded = CString::new(encoded)?;

        o_cb(user_data, 0, req_id, encoded.as_ptr());

        Ok(())
    })
}

/// Decode IPC message.
#[no_mangle]
................................................................................
pub unsafe extern "C" fn decode_ipc_msg(msg: *const c_char,
                                        user_data: *mut c_void,
                                        o_auth: extern "C" fn(*mut c_void,
                                                              u32,
                                                              *const FfiAuthGranted),
                                        o_containers: extern "C" fn(*mut c_void, u32),
                                        o_revoked: extern "C" fn(*mut c_void),
                                        o_err: extern "C" fn(*mut c_void, i32, u32)) {
    catch_unwind_cb(user_data, o_err, || -> Result<_, AppError> {
        let msg = from_c_str(msg)?;
        let msg = ipc::decode_msg(&msg)?;

        match msg {

            IpcMsg::Resp { resp: IpcResp::Auth(res), req_id } => {


                match res {
                    Ok(auth_granted) => {
                        match auth_granted.into_repr_c() {
                            Ok(auth_granted) => {
                                o_auth(user_data, req_id, &auth_granted);
                            }
                            Err(err) => {
                                o_err(user_data, ffi_error_code!(AppError::from(err)), req_id);







                            }
                        }
                    }

                    Err(err) => o_err(user_data, ffi_error_code!(AppError::from(err)), req_id),





                }

            }



            IpcMsg::Resp { resp: IpcResp::Containers(res), req_id } => {


                match res {
                    Ok(()) => o_containers(user_data, req_id),

                    Err(err) => o_err(user_data, ffi_error_code!(AppError::from(err)), req_id),








                }
            }
            IpcMsg::Revoked { .. } => o_revoked(user_data),
            _ => {
                return Err(IpcError::InvalidMsg.into());
            }
        }
................................................................................
            unsafe { unwrap!(call_2(|ud, cb| encode_auth_req(&req_c, ud, cb))) };

        // Decode it and verify it's the same we encoded.
        assert!(encoded.starts_with("safe-auth:"));
        let msg = unwrap!(ipc::decode_msg(&encoded));

        let (decoded_req_id, decoded_req) = match msg {


            IpcMsg::Req { req_id, req: IpcReq::Auth(req) } => (req_id, req),

            x => panic!("Unexpected {:?}", x),
        };

        assert_eq!(decoded_req_id, req_id);
        assert_eq!(decoded_req, req);
    }

................................................................................
            unsafe { unwrap!(call_2(|ud, cb| encode_containers_req(&req_c, ud, cb))) };

        // Decode it and verify it's the same we encoded.
        assert!(encoded.starts_with("safe-auth:"));
        let msg = unwrap!(ipc::decode_msg(&encoded));

        let (decoded_req_id, decoded_req) = match msg {


            IpcMsg::Req { req_id, req: IpcReq::Containers(req) } => (req_id, req),

            x => panic!("Unexpected {:?}", x),
        };

        assert_eq!(decoded_req_id, req_id);
        assert_eq!(decoded_req, req);
    }

................................................................................
            extern "C" fn revoked_cb(ctx: *mut c_void) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }


            extern "C" fn err_cb(ctx: *mut c_void, _error_code: i32, _req_id: u32) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            let context_ptr: *mut Context = &mut context;
................................................................................
            extern "C" fn revoked_cb(ctx: *mut c_void) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }


            extern "C" fn err_cb(ctx: *mut c_void, _error_code: i32, _req_id: u32) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            let context_ptr: *mut Context = &mut context;


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|




|












|







 







|










|







 







|







 







|





>
|
>
>







|
>
>
>
>
>
>
>



>
|
>
>
>
>
>
|
>
|
>
>
>
|
>
>


>
|
>
>
>
>
>
>
>
>







 







>
>
|
>







 







>
>
|
>







 







>
|







 







>
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
..
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
...
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
...
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
...
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! App-related IPC utilities.

use errors::AppError;
use ffi_utils::{FFI_RESULT_OK, FfiResult, ReprC, catch_unwind_cb, from_c_str};
use safe_core::ipc::{self, AuthReq, ContainersReq, IpcError, IpcMsg, IpcReq, IpcResp};
use safe_core::ipc::req::ffi::AuthReq as FfiAuthReq;
use safe_core::ipc::req::ffi::ContainersReq as FfiContainersReq;
use safe_core::ipc::resp::ffi::AuthGranted as FfiAuthGranted;
use std::ffi::CString;
use std::os::raw::{c_char, c_void};

/// Encode `AuthReq`.
#[no_mangle]
pub unsafe extern "C" fn encode_auth_req(req: *const FfiAuthReq,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             u32,
                                                             *const c_char)) {
    catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
        let req_id = ipc::gen_req_id();
        let req = AuthReq::clone_from_repr_c(req)?;

        let msg = IpcMsg::Req {
................................................................................
            req_id: req_id,
            req: IpcReq::Auth(req),
        };

        let encoded = ipc::encode_msg(&msg, "safe-auth")?;
        let encoded = CString::new(encoded)?;

        o_cb(user_data, FFI_RESULT_OK, req_id, encoded.as_ptr());

        Ok(())
    })
}

/// Encode `ContainersReq`.
#[no_mangle]
pub unsafe extern "C" fn encode_containers_req(req: *const FfiContainersReq,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   FfiResult,
                                                                   u32,
                                                                   *const c_char)) {
    catch_unwind_cb(user_data, o_cb, || -> Result<_, AppError> {
        let req_id = ipc::gen_req_id();
        let req = ContainersReq::clone_from_repr_c(req)?;

        let msg = IpcMsg::Req {
................................................................................
            req_id: req_id,
            req: IpcReq::Containers(req),
        };

        let encoded = ipc::encode_msg(&msg, "safe-auth")?;
        let encoded = CString::new(encoded)?;

        o_cb(user_data, FFI_RESULT_OK, req_id, encoded.as_ptr());

        Ok(())
    })
}

/// Decode IPC message.
#[no_mangle]
................................................................................
pub unsafe extern "C" fn decode_ipc_msg(msg: *const c_char,
                                        user_data: *mut c_void,
                                        o_auth: extern "C" fn(*mut c_void,
                                                              u32,
                                                              *const FfiAuthGranted),
                                        o_containers: extern "C" fn(*mut c_void, u32),
                                        o_revoked: extern "C" fn(*mut c_void),
                                        o_err: extern "C" fn(*mut c_void, FfiResult, u32)) {
    catch_unwind_cb(user_data, o_err, || -> Result<_, AppError> {
        let msg = from_c_str(msg)?;
        let msg = ipc::decode_msg(&msg)?;

        match msg {
            IpcMsg::Resp {
                resp: IpcResp::Auth(res),
                req_id,
            } => {
                match res {
                    Ok(auth_granted) => {
                        match auth_granted.into_repr_c() {
                            Ok(auth_granted) => {
                                o_auth(user_data, req_id, &auth_granted);
                            }
                            Err(err) => {
                                let e = AppError::from(err);
                                let (error_code, description) = ffi_error!(e);
                                o_err(user_data,
                                      FfiResult {
                                          error_code,
                                          description: description.as_ptr(),
                                      },
                                      req_id);
                            }
                        }
                    }
                    Err(err) => {
                        let e = AppError::from(err);
                        let (error_code, description) = ffi_error!(e);
                        o_err(user_data,
                              FfiResult {
                                  error_code,
                                  description: description.as_ptr(),
                              },
                              req_id);
                    }
                }
            }
            IpcMsg::Resp {
                resp: IpcResp::Containers(res),
                req_id,
            } => {
                match res {
                    Ok(()) => o_containers(user_data, req_id),
                    Err(err) => {
                        let e = AppError::from(err);
                        let (error_code, description) = ffi_error!(e);
                        o_err(user_data,
                              FfiResult {
                                  error_code,
                                  description: description.as_ptr(),
                              },
                              req_id);
                    }
                }
            }
            IpcMsg::Revoked { .. } => o_revoked(user_data),
            _ => {
                return Err(IpcError::InvalidMsg.into());
            }
        }
................................................................................
            unsafe { unwrap!(call_2(|ud, cb| encode_auth_req(&req_c, ud, cb))) };

        // Decode it and verify it's the same we encoded.
        assert!(encoded.starts_with("safe-auth:"));
        let msg = unwrap!(ipc::decode_msg(&encoded));

        let (decoded_req_id, decoded_req) = match msg {
            IpcMsg::Req {
                req_id,
                req: IpcReq::Auth(req),
            } => (req_id, req),
            x => panic!("Unexpected {:?}", x),
        };

        assert_eq!(decoded_req_id, req_id);
        assert_eq!(decoded_req, req);
    }

................................................................................
            unsafe { unwrap!(call_2(|ud, cb| encode_containers_req(&req_c, ud, cb))) };

        // Decode it and verify it's the same we encoded.
        assert!(encoded.starts_with("safe-auth:"));
        let msg = unwrap!(ipc::decode_msg(&encoded));

        let (decoded_req_id, decoded_req) = match msg {
            IpcMsg::Req {
                req_id,
                req: IpcReq::Containers(req),
            } => (req_id, req),
            x => panic!("Unexpected {:?}", x),
        };

        assert_eq!(decoded_req_id, req_id);
        assert_eq!(decoded_req, req);
    }

................................................................................
            extern "C" fn revoked_cb(ctx: *mut c_void) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            #[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
            extern "C" fn err_cb(ctx: *mut c_void, _res: FfiResult, _req_id: u32) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            let context_ptr: *mut Context = &mut context;
................................................................................
            extern "C" fn revoked_cb(ctx: *mut c_void) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            #[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
            extern "C" fn err_cb(ctx: *mut c_void, _res: FfiResult, _req_id: u32) {
                unsafe {
                    let ctx = ctx as *mut Context;
                    (*ctx).unexpected_cb = true;
                }
            }

            let context_ptr: *mut Context = &mut context;

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mdata_info.rs from [1d9bff3740] to [25ef94f01a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

26
27
28
29
30
31
32
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
..
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
..
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
...
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155






























156



157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
...
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
...
255
256
257
258
259
260
261

262
263
264
265
266
267
268
269
270
271
272
273
274
275
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use App;
use errors::AppError;
use ffi::helper::send_sync;
use ffi_utils::{OpaqueCtx, catch_unwind_cb};

use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::MDataInfoHandle;
use routing::{XOR_NAME_LEN, XorName};
use safe_core::MDataInfo;
use std::os::raw::c_void;
use std::slice;

................................................................................
/// Create non-encrypted mdata info with explicit data name.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_new_public(app: *const App,
                                               name: *const [u8; XOR_NAME_LEN],
                                               type_tag: u64,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   i32,
                                                                   MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let name = XorName(*name);

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::new_public(name, type_tag);
            Ok(context.object_cache().insert_mdata_info(info))
................................................................................
/// Create encrypted mdata info with explicit data name.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_new_private(app: *const App,
                                                name: *const [u8; XOR_NAME_LEN],
                                                type_tag: u64,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void,
                                                                    i32,
                                                                    MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let name = XorName(*name);

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::new_private(name, type_tag);
            Ok(context.object_cache().insert_mdata_info(info))
................................................................................

/// Create random, non-encrypted mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_random_public(app: *const App,
                                                  type_tag: u64,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      i32,
                                                                      MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::random_public(type_tag)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
................................................................................

/// Create random, encrypted mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_random_private(app: *const App,
                                                   type_tag: u64,
                                                   user_data: *mut c_void,
                                                   o_cb: extern "C" fn(*mut c_void,
                                                                       i32,
                                                                       MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::random_private(type_tag)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_info_encrypt_entry_key(app: *const App,
                                                      info_h: MDataInfoHandle,
                                                      input_ptr: *const u8,
                                                      input_len: usize,
                                                      user_data: *mut c_void,
                                                      o_cb: extern "C" fn(*mut c_void,
                                                                          i32,
                                                                          *const u8,
                                                                          usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let input = slice::from_raw_parts(input_ptr, input_len).to_vec();

        (*app).send(move |_, context| {
................................................................................
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let vec = try_cb!(info.enc_entry_key(&input).map_err(AppError::from),
                              user_data,
                              o_cb);

            o_cb(user_data.0, 0, vec.as_ptr(), vec.len());

            None
        })
    })
}

/// Encrypt mdata entry value using the corresponding mdata info.
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_info_encrypt_entry_value(app: *const App,
                                                        info_h: MDataInfoHandle,
                                                        input_ptr: *const u8,
                                                        input_len: usize,
                                                        user_data: *mut c_void,
                                                        o_cb: extern "C" fn(*mut c_void,
                                                                            i32,
                                                                            *const u8,
                                                                            usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let input = slice::from_raw_parts(input_ptr, input_len).to_vec();

        (*app).send(move |_, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let vec = try_cb!(info.enc_entry_value(&input).map_err(AppError::from),
                              user_data,
                              o_cb);































            o_cb(user_data.0, 0, vec.as_ptr(), vec.len());




            None
        })
    })
}

/// Extract name and type tag from the mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_extract_name_and_type_tag(app: *const App,
                                                              info_h: MDataInfoHandle,
                                                              user_data: *mut c_void,
                                                              o_cb: extern "C" fn(*mut c_void,
                                                                                  i32,
                                                                                  *const [u8;
                                                                                   XOR_NAME_LEN],
                                                                                  u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = context.object_cache().get_mdata_info(info_h)?;
            Ok((&info.name.0, info.type_tag))
        })
    })
}
................................................................................

/// Serialise `MDataInfo`.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_serialise(app: *const App,
                                              info_h: MDataInfoHandle,
                                              user_data: *mut c_void,
                                              o_cb: extern "C" fn(*mut c_void,
                                                                  i32,
                                                                  *const u8,
                                                                  usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |_, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let encoded = try_cb!(serialise(&*info).map_err(AppError::from), user_data, o_cb);

            o_cb(user_data.0, 0, encoded.as_ptr(), encoded.len());



            None
        })
    })
}

/// Deserialise `MDataInfo`.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_deserialise(app: *const App,
                                                ptr: *const u8,
                                                len: usize,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void,
                                                                    i32,
                                                                    MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let encoded = slice::from_raw_parts(ptr, len).to_vec();

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = deserialise(&encoded)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
}
................................................................................
                    move |_, context| context.object_cache().insert_mdata_info(info))
        };

        let encoded =
            unsafe { unwrap!(call_vec_u8(|ud, cb| mdata_info_serialise(&app, info1_h, ud, cb))) };

        let info2_h = unsafe {

            let res = call_1(|ud, cb| {
                mdata_info_deserialise(&app, encoded.as_ptr(), encoded.len(), ud, cb)
            });

            unwrap!(res)
        };

        let info2 = run_now(&app, move |_, context| {
            unwrap!(context.object_cache().remove_mdata_info(info2_h))
        });

        assert_eq!(info1, info2);
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|




|
>







 







|







 







|







 







|







 







|







 







|







 







|







 







|




|









>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|
>
>
>












|


|







 







|











|
>
>
>












|


|







 







>
|
|
|











1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
..
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
..
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
..
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
...
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
...
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use App;
use errors::AppError;
use ffi::helper::send_sync;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, SafePtr, catch_unwind_cb,
                vec_clone_from_raw_parts};
use maidsafe_utilities::serialisation::{deserialise, serialise};
use object_cache::MDataInfoHandle;
use routing::{XOR_NAME_LEN, XorName};
use safe_core::MDataInfo;
use std::os::raw::c_void;
use std::slice;

................................................................................
/// Create non-encrypted mdata info with explicit data name.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_new_public(app: *const App,
                                               name: *const [u8; XOR_NAME_LEN],
                                               type_tag: u64,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   FfiResult,
                                                                   MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let name = XorName(*name);

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::new_public(name, type_tag);
            Ok(context.object_cache().insert_mdata_info(info))
................................................................................
/// Create encrypted mdata info with explicit data name.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_new_private(app: *const App,
                                                name: *const [u8; XOR_NAME_LEN],
                                                type_tag: u64,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void,
                                                                    FfiResult,
                                                                    MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let name = XorName(*name);

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::new_private(name, type_tag);
            Ok(context.object_cache().insert_mdata_info(info))
................................................................................

/// Create random, non-encrypted mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_random_public(app: *const App,
                                                  type_tag: u64,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      FfiResult,
                                                                      MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::random_public(type_tag)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
................................................................................

/// Create random, encrypted mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_random_private(app: *const App,
                                                   type_tag: u64,
                                                   user_data: *mut c_void,
                                                   o_cb: extern "C" fn(*mut c_void,
                                                                       FfiResult,
                                                                       MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = MDataInfo::random_private(type_tag)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_info_encrypt_entry_key(app: *const App,
                                                      info_h: MDataInfoHandle,
                                                      input_ptr: *const u8,
                                                      input_len: usize,
                                                      user_data: *mut c_void,
                                                      o_cb: extern "C" fn(*mut c_void,
                                                                          FfiResult,
                                                                          *const u8,
                                                                          usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let input = slice::from_raw_parts(input_ptr, input_len).to_vec();

        (*app).send(move |_, context| {
................................................................................
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let vec = try_cb!(info.enc_entry_key(&input).map_err(AppError::from),
                              user_data,
                              o_cb);

            o_cb(user_data.0, FFI_RESULT_OK, vec.as_safe_ptr(), vec.len());

            None
        })
    })
}

/// Encrypt mdata entry value using the corresponding mdata info.
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_info_encrypt_entry_value(app: *const App,
                                                        info_h: MDataInfoHandle,
                                                        input_ptr: *const u8,
                                                        input_len: usize,
                                                        user_data: *mut c_void,
                                                        o_cb: extern "C" fn(*mut c_void,
                                                                            FfiResult,
                                                                            *const u8,
                                                                            usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let input = vec_clone_from_raw_parts(input_ptr, input_len);

        (*app).send(move |_, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let vec = try_cb!(info.enc_entry_value(&input).map_err(AppError::from),
                              user_data,
                              o_cb);

            o_cb(user_data.0, FFI_RESULT_OK, vec.as_safe_ptr(), vec.len());

            None
        })
    })
}

/// Decrypt mdata entry value or a key using the corresponding mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_decrypt(app: *const App,
                                            info_h: MDataInfoHandle,
                                            input_ptr: *const u8,
                                            input_len: usize,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                *const u8,
                                                                usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let encoded = vec_clone_from_raw_parts(input_ptr, input_len);

        (*app).send(move |_, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let decrypted = try_cb!(info.decrypt(&encoded).map_err(AppError::from),
                                    user_data,
                                    o_cb);

            o_cb(user_data.0,
                 FFI_RESULT_OK,
                 decrypted.as_safe_ptr(),
                 decrypted.len());

            None
        })
    })
}

/// Extract name and type tag from the mdata info.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_extract_name_and_type_tag(app: *const App,
                                                              info_h: MDataInfoHandle,
                                                              user_data: *mut c_void,
                                                              o_cb: extern "C" fn(*mut c_void,
                                                                                  FfiResult,
                                                                                  *const [u8;
                                                                                   XOR_NAME_LEN],
u64)){
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let info = context.object_cache().get_mdata_info(info_h)?;
            Ok((&info.name.0, info.type_tag))
        })
    })
}
................................................................................

/// Serialise `MDataInfo`.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_serialise(app: *const App,
                                              info_h: MDataInfoHandle,
                                              user_data: *mut c_void,
                                              o_cb: extern "C" fn(*mut c_void,
                                                                  FfiResult,
                                                                  *const u8,
                                                                  usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |_, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let encoded = try_cb!(serialise(&*info).map_err(AppError::from), user_data, o_cb);

            o_cb(user_data.0,
                 FFI_RESULT_OK,
                 encoded.as_safe_ptr(),
                 encoded.len());
            None
        })
    })
}

/// Deserialise `MDataInfo`.
#[no_mangle]
pub unsafe extern "C" fn mdata_info_deserialise(app: *const App,
                                                ptr: *const u8,
                                                len: usize,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void,
                                                                    FfiResult,
                                                                    MDataInfoHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let encoded = vec_clone_from_raw_parts(ptr, len);

        send_sync(app, user_data, o_cb, move |_, context| {
            let info = deserialise(&encoded)?;
            Ok(context.object_cache().insert_mdata_info(info))
        })
    })
}
................................................................................
                    move |_, context| context.object_cache().insert_mdata_info(info))
        };

        let encoded =
            unsafe { unwrap!(call_vec_u8(|ud, cb| mdata_info_serialise(&app, info1_h, ud, cb))) };

        let info2_h = unsafe {
            let res =
                call_1(|ud, cb| {
                           mdata_info_deserialise(&app, encoded.as_ptr(), encoded.len(), ud, cb)
                       });

            unwrap!(res)
        };

        let info2 = run_now(&app, move |_, context| {
            unwrap!(context.object_cache().remove_mdata_info(info2_h))
        });

        assert_eq!(info1, info2);
    }
}

Deleted wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/misc.rs version [a173552eff].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use App;
use ffi::helper::send_sync;
use ffi_utils::catch_unwind_cb;
use object_cache::{EncryptKeyHandle, SignKeyHandle};
use rust_sodium::crypto::{box_, sign};
use std::os::raw::c_void;

/// Get the public signing key of the app.
#[no_mangle]
pub unsafe extern "C" fn app_pub_sign_key(app: *const App,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void, i32, SignKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |client, context| {
            let key = client.public_signing_key()?;
            Ok(context.object_cache().insert_sign_key(key))
        })
    })
}

/// Create new public signing key from raw array.
#[no_mangle]
pub unsafe extern "C" fn sign_key_new(app: *const App,
                                      data: *const [u8; sign::PUBLICKEYBYTES],
                                      user_data: *mut c_void,
                                      o_cb: extern "C" fn(*mut c_void, i32, SignKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = sign::PublicKey(*data);
        send_sync(app,
                  user_data,
                  o_cb,
                  move |_, context| Ok(context.object_cache().insert_sign_key(key)))
    })
}

/// Retrieve the public signing key as raw array.
#[no_mangle]
pub unsafe extern "C" fn sign_key_get(app: *const App,
                                      handle: SignKeyHandle,
                                      user_data: *mut c_void,
                                      o_cb: extern "C" fn(*mut c_void,
                                                          i32,
                                                          *const [u8; sign::PUBLICKEYBYTES])) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let key = context.object_cache().get_sign_key(handle)?;
            Ok(&key.0)
        })
    })
}

/// Free signing key from memory
#[no_mangle]
pub unsafe extern "C" fn sign_key_free(app: *const App,
                                       handle: SignKeyHandle,
                                       user_data: *mut c_void,
                                       o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_sign_key(handle)?;
            Ok(())
        })
    })
}

/// Get the public encryption key of the app.
#[no_mangle]
pub unsafe extern "C" fn app_pub_enc_key(app: *const App,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32, EncryptKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |client, context| {
            let key = client.public_encryption_key()?;
            Ok(context.object_cache().insert_encrypt_key(key))
        })
    })
}

/// Create new public encryption key from raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_key_new(app: *const App,
                                     data: *const [u8; box_::PUBLICKEYBYTES],
                                     user_data: *mut c_void,
                                     o_cb: extern "C" fn(*mut c_void, i32, EncryptKeyHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = box_::PublicKey(*data);
        send_sync(app,
                  user_data,
                  o_cb,
                  move |_, context| Ok(context.object_cache().insert_encrypt_key(key)))
    })
}

/// Retrieve the public encryption key as raw array.
#[no_mangle]
pub unsafe extern "C" fn enc_key_get(app: *const App,
                                     handle: EncryptKeyHandle,
                                     user_data: *mut c_void,
                                     o_cb: extern "C" fn(*mut c_void,
                                                         i32,
                                                         *const [u8; box_::PUBLICKEYBYTES])) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let key = context.object_cache().get_encrypt_key(handle)?;
            Ok(&key.0)
        })
    })
}

/// Free encryption key from memory
#[no_mangle]
pub unsafe extern "C" fn enc_key_free(app: *const App,
                                      handle: EncryptKeyHandle,
                                      user_data: *mut c_void,
                                      o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_encrypt_key(handle)?;
            Ok(())
        })
    })
}

/*
/// Reset the object cache (drop all objects stored in it). This will invalidate
/// all currently held object handles.
#[no_mangle]
pub unsafe extern "C" fn misc_object_cache_reset(session: *const Session,
                                                 user_data: *mut c_void,
                                                 o_cb: unsafe extern "C" fn(*mut c_void, i32)) {
    let user_data = OpaqueCtx(user_data);

    helper::catch_unwind_cb(user_data, o_cb, || {
        (*session).send(move |_, obj_cache| {
            obj_cache.reset();
            o_cb(user_data.0, 0);
            None
        })
    })
}
*/

#[cfg(test)]
mod tests {
    use super::*;
    use ffi_utils::test_utils::call_1;
    use routing::XOR_NAME_LEN;
    use test_utils::{create_app, run_now};

    #[test]
    fn sign_key_basics() {
        let app = create_app();
        let app_sign_key1_h = unsafe { unwrap!(call_1(|ud, cb| app_pub_sign_key(&app, ud, cb))) };

        let app_sign_key1 = run_now(&app, move |client, context| {
            let app_sign_key1 = unwrap!(client.public_signing_key());
            let app_sign_key2 = unwrap!(context.object_cache().get_sign_key(app_sign_key1_h));
            assert_eq!(app_sign_key1, *app_sign_key2);

            app_sign_key1
        });

        let app_sign_key1_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| sign_key_get(&app, app_sign_key1_h, ud, cb))) };

        let app_sign_key2_h =
            unsafe { unwrap!(call_1(|ud, cb| sign_key_new(&app, &app_sign_key1_raw, ud, cb))) };

        let app_sign_key2 = run_now(&app, move |_, context| {
            *unwrap!(context.object_cache().get_sign_key(app_sign_key2_h))
        });

        assert_eq!(app_sign_key1, app_sign_key2);
    }

    #[test]
    fn enc_key_basics() {
        let app = create_app();
        let app_enc_key1_h = unsafe { unwrap!(call_1(|ud, cb| app_pub_enc_key(&app, ud, cb))) };

        let app_enc_key1 = run_now(&app, move |client, context| {
            let app_enc_key1 = unwrap!(client.public_encryption_key());
            let app_enc_key2 = unwrap!(context.object_cache().get_encrypt_key(app_enc_key1_h));
            assert_eq!(app_enc_key1, *app_enc_key2);

            app_enc_key1
        });

        let app_enc_key1_raw: [u8; XOR_NAME_LEN] =
            unsafe { unwrap!(call_1(|ud, cb| enc_key_get(&app, app_enc_key1_h, ud, cb))) };

        let app_enc_key2_h =
            unsafe { unwrap!(call_1(|ud, cb| enc_key_new(&app, &app_enc_key1_raw, ud, cb))) };

        let app_enc_key2 = run_now(&app, move |_, context| {
            *unwrap!(context.object_cache().get_encrypt_key(app_enc_key2_h))
        });

        assert_eq!(app_enc_key1, app_enc_key2);
    }
}
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<
<




























































































































































































































































































































































































































































Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mod.rs from [4375e81b19] to [f9fc0a4404].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
..
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
..
57
58
59
60
61
62
63

64
65
66
67
68
69
70
71
72
73
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI

#![allow(unsafe_code)]

use super::App;
use super::errors::AppError;
................................................................................
pub mod cipher_opt;
/// Low level manipulation of `ImmutableData`
pub mod immutable_data;
/// IPC utilities
pub mod ipc;
/// `MDataInfo` operations
pub mod mdata_info;
/// Miscellaneous routines
pub mod misc;
/// Low level manipulation of `MutableData`
pub mod mutable_data;
/// NFS API
pub mod nfs;

mod helper;

................................................................................
                                                                                    i32,
                                                                                    i32),
                                          o_app: *mut *mut App)
                                          -> i32 {
    catch_unwind_error_code(|| -> Result<_, AppError> {
        let user_data = OpaqueCtx(user_data);


        let app = App::unregistered(move |event| {
            call_network_observer(event, user_data.0, network_observer_cb)
        })?;

        *o_app = Box::into_raw(Box::new(app));

        Ok(())
    })
}



|
|
<
|

|
|
<
<
|

|
|
|
<

|
|







 







|
|







 







>
|
|
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
..
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
..
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI

#![allow(unsafe_code)]

use super::App;
use super::errors::AppError;
................................................................................
pub mod cipher_opt;
/// Low level manipulation of `ImmutableData`
pub mod immutable_data;
/// IPC utilities
pub mod ipc;
/// `MDataInfo` operations
pub mod mdata_info;
/// Crypto-related routines
pub mod crypto;
/// Low level manipulation of `MutableData`
pub mod mutable_data;
/// NFS API
pub mod nfs;

mod helper;

................................................................................
                                                                                    i32,
                                                                                    i32),
                                          o_app: *mut *mut App)
                                          -> i32 {
    catch_unwind_error_code(|| -> Result<_, AppError> {
        let user_data = OpaqueCtx(user_data);

        let app =
            App::unregistered(move |event| {
                                  call_network_observer(event, user_data.0, network_observer_cb)
                              })?;

        *o_app = Box::into_raw(Box::new(app));

        Ok(())
    })
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/entries.rs from [908f0b94f1] to [6d780284b3].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
..
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
..
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109

110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
...
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
...
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
...
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
...
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
...
365
366
367
368
369
370
371


372
373

374
375
376
377
378
379
380
381
382
383
384
...
429
430
431
432
433
434
435

436
437
438
439
440
441
442
443
444
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI for mutable data entries, keys and values.

use App;
use errors::AppError;
use ffi::helper::send_sync;

use ffi_utils::{OpaqueCtx, catch_unwind_cb, vec_clone_from_raw_parts};
use ffi_utils::callback::Callback;
use object_cache::{MDataEntriesHandle, MDataKeysHandle, MDataValuesHandle};
use routing::{ClientError, Value};
use safe_core::CoreError;
use std::collections::{BTreeMap, BTreeSet};
use std::os::raw::c_void;

/// Create new empty entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_new(app: *const App,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               i32,
                                                               MDataEntriesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app,
                  user_data,
                  o_cb,
                  |_, context| Ok(context.object_cache().insert_mdata_entries(Default::default())))

    })
}

/// Insert an entry to the entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_insert(app: *const App,
                                              entries_h: MDataEntriesHandle,
                                              key_ptr: *const u8,
                                              key_len: usize,
                                              value_ptr: *const u8,
                                              value_len: usize,
                                              user_data: *mut c_void,
                                              o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = vec_clone_from_raw_parts(key_ptr, key_len);
        let value = vec_clone_from_raw_parts(value_ptr, value_len);

        with_entries(app, entries_h, user_data, o_cb, |entries| {
            let _ = entries.insert(key,
                                   Value {
................................................................................
}

/// Returns the number of entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_len(app: *const App,
                                           entries_h: MDataEntriesHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, i32, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_entries(app, entries_h, user_data, o_cb, |entries| Ok(entries.len())))
}

/// Get the entry value at the given key.
/// The callbacks arguments are: user data, error code, pointer to value,
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_get(app: *const App,
                                           entries_h: MDataEntriesHandle,
                                           key_ptr: *const u8,
                                           key_len: usize,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               i32,
                                                               *const u8,
                                                               usize,
                                                               u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let key = vec_clone_from_raw_parts(key_ptr, key_len);

        (*app).send(move |_, context| {
            let entries = context.object_cache().get_mdata_entries(entries_h);
            let entries = try_cb!(entries, user_data, o_cb);

            let value = entries.get(&key)

                .ok_or(ClientError::NoSuchEntry)
                .map_err(CoreError::from)
                .map_err(AppError::from);
            let value = try_cb!(value, user_data, o_cb);

            o_cb(user_data.0,
                 0,
                 value.content.as_ptr(),
                 value.content.len(),
                 value.entry_version);

            None
        })
    })
}
................................................................................
                                                entry_cb: extern "C" fn(*mut c_void,
                                                                        *const u8,
                                                                        usize,
                                                                        *const u8,
                                                                        usize,
                                                                        u64),
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_entries(app, entries_h, user_data.0, o_cb, move |entries| {
            for (key, value) in entries {
                entry_cb(user_data.0,
                         key.as_ptr(),
                         key.len(),
                         value.content.as_ptr(),
                         value.content.len(),
                         value.entry_version);
            }

            Ok(())
        })
    })
................................................................................
}

/// Free the entries from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_free(app: *const App,
                                            entries_h: MDataEntriesHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_entries(entries_h)?;
            Ok(())
        })
    })
}

/// Returns the number of keys.
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_len(app: *const App,
                                        keys_h: MDataKeysHandle,
                                        user_data: *mut c_void,
                                        o_cb: extern "C" fn(*mut c_void, i32, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_keys(app, keys_h, user_data, o_cb, |keys| Ok(keys.len())))
}

/// Iterate over the keys.
///
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_for_each(app: *const App,
                                             keys_h: MDataKeysHandle,
                                             key_cb: unsafe extern "C" fn(*mut c_void,
                                                                          *const u8,
                                                                          usize),
                                             user_data: *mut c_void,
                                             o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_keys(app, keys_h, user_data.0, o_cb, move |keys| {
            for key in keys {
                key_cb(user_data.0, key.as_ptr(), key.len());
            }

            Ok(())
        })
    })
}

/// Free the keys from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_free(app: *const App,
                                         keys_h: MDataKeysHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_keys(keys_h)?;
            Ok(())
        })
    })
}

/// Returns the number of values.
#[no_mangle]
pub unsafe extern "C" fn mdata_values_len(app: *const App,
                                          values_h: MDataValuesHandle,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void, i32, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_values(app, values_h, user_data, o_cb, |values| Ok(values.len())))
}

/// Iterate over the values.
///
................................................................................
pub unsafe extern "C" fn mdata_values_for_each(app: *const App,
                                               values_h: MDataValuesHandle,
                                               value_cb: unsafe extern "C" fn(*mut c_void,
                                                                              *const u8,
                                                                              usize,
                                                                              u64),
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_values(app, values_h, user_data.0, o_cb, move |values| {
            for value in values {
                value_cb(user_data.0,
                         value.content.as_ptr(),
                         value.content.len(),
                         value.entry_version);
            }

            Ok(())
        })
    })
................................................................................
}

/// Free the values from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_values_free(app: *const App,
                                           values_h: MDataValuesHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_values(values_h)?;
            Ok(())
        })
    })
}
................................................................................
        });

        let len: usize =
            unsafe { unwrap!(call_1(|ud, cb| mdata_entries_len(&app, handle, ud, cb))) };
        assert_eq!(len, 2);

        let (tx, rx) = mpsc::channel::<Value>();


        extern "C" fn get_cb(user_data: *mut c_void,
                             error_code: i32,

                             ptr: *const u8,
                             len: usize,
                             version: u64) {
            assert_eq!(error_code, 0);

            unsafe {
                let value = vec_clone_from_raw_parts(ptr, len);
                let value = Value {
                    content: value,
                    entry_version: version,
                };
................................................................................
                };

                let user_data = user_data as *mut (Sender<()>, BTreeMap<_, _>);
                let _ = (*user_data).1.insert(key, value);
            }
        }


        extern "C" fn done_cb(user_data: *mut c_void, error_code: i32) {
            assert_eq!(error_code, 0);
            let user_data = user_data as *mut (Sender<_>, BTreeMap<Vec<u8>, Value>);

            unsafe {
                unwrap!((*user_data).0.send(()));
            }
        }



|
|
<
|

|
|
<
<
|

|
|
|
<

|
|






>
|












|


|
|
|
|
>












|







 







|







 







|











|
>






|
|







 







|






|

|







 







|













|







 







|





|












|













|







 







|






|







 







|







 







>
>

<
>



|







 







>
|
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
..
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
...
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
...
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
...
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
...
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
...
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
...
364
365
366
367
368
369
370
371
372
373

374
375
376
377
378
379
380
381
382
383
384
385
...
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI for mutable data entries, keys and values.

use App;
use errors::AppError;
use ffi::helper::send_sync;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, SafePtr, catch_unwind_cb,
                vec_clone_from_raw_parts};
use ffi_utils::callback::Callback;
use object_cache::{MDataEntriesHandle, MDataKeysHandle, MDataValuesHandle};
use routing::{ClientError, Value};
use safe_core::CoreError;
use std::collections::{BTreeMap, BTreeSet};
use std::os::raw::c_void;

/// Create new empty entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_new(app: *const App,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               FfiResult,
                                                               MDataEntriesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {
            Ok(context
                   .object_cache()
                   .insert_mdata_entries(Default::default()))
        })
    })
}

/// Insert an entry to the entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_insert(app: *const App,
                                              entries_h: MDataEntriesHandle,
                                              key_ptr: *const u8,
                                              key_len: usize,
                                              value_ptr: *const u8,
                                              value_len: usize,
                                              user_data: *mut c_void,
                                              o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let key = vec_clone_from_raw_parts(key_ptr, key_len);
        let value = vec_clone_from_raw_parts(value_ptr, value_len);

        with_entries(app, entries_h, user_data, o_cb, |entries| {
            let _ = entries.insert(key,
                                   Value {
................................................................................
}

/// Returns the number of entries.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_len(app: *const App,
                                           entries_h: MDataEntriesHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, FfiResult, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_entries(app, entries_h, user_data, o_cb, |entries| Ok(entries.len())))
}

/// Get the entry value at the given key.
/// The callbacks arguments are: user data, error code, pointer to value,
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_get(app: *const App,
                                           entries_h: MDataEntriesHandle,
                                           key_ptr: *const u8,
                                           key_len: usize,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               FfiResult,
                                                               *const u8,
                                                               usize,
                                                               u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let key = vec_clone_from_raw_parts(key_ptr, key_len);

        (*app).send(move |_, context| {
            let entries = context.object_cache().get_mdata_entries(entries_h);
            let entries = try_cb!(entries, user_data, o_cb);

            let value = entries
                .get(&key)
                .ok_or(ClientError::NoSuchEntry)
                .map_err(CoreError::from)
                .map_err(AppError::from);
            let value = try_cb!(value, user_data, o_cb);

            o_cb(user_data.0,
                 FFI_RESULT_OK,
                 value.content.as_safe_ptr(),
                 value.content.len(),
                 value.entry_version);

            None
        })
    })
}
................................................................................
                                                entry_cb: extern "C" fn(*mut c_void,
                                                                        *const u8,
                                                                        usize,
                                                                        *const u8,
                                                                        usize,
                                                                        u64),
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_entries(app, entries_h, user_data.0, o_cb, move |entries| {
            for (key, value) in entries {
                entry_cb(user_data.0,
                         key.as_safe_ptr(),
                         key.len(),
                         value.content.as_safe_ptr(),
                         value.content.len(),
                         value.entry_version);
            }

            Ok(())
        })
    })
................................................................................
}

/// Free the entries from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_entries_free(app: *const App,
                                            entries_h: MDataEntriesHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_entries(entries_h)?;
            Ok(())
        })
    })
}

/// Returns the number of keys.
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_len(app: *const App,
                                        keys_h: MDataKeysHandle,
                                        user_data: *mut c_void,
                                        o_cb: extern "C" fn(*mut c_void, FfiResult, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_keys(app, keys_h, user_data, o_cb, |keys| Ok(keys.len())))
}

/// Iterate over the keys.
///
................................................................................
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_for_each(app: *const App,
                                             keys_h: MDataKeysHandle,
                                             key_cb: unsafe extern "C" fn(*mut c_void,
                                                                          *const u8,
                                                                          usize),
                                             user_data: *mut c_void,
                                             o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_keys(app, keys_h, user_data.0, o_cb, move |keys| {
            for key in keys {
                key_cb(user_data.0, key.as_safe_ptr(), key.len());
            }

            Ok(())
        })
    })
}

/// Free the keys from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_keys_free(app: *const App,
                                         keys_h: MDataKeysHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_keys(keys_h)?;
            Ok(())
        })
    })
}

/// Returns the number of values.
#[no_mangle]
pub unsafe extern "C" fn mdata_values_len(app: *const App,
                                          values_h: MDataValuesHandle,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void, FfiResult, usize)) {
    catch_unwind_cb(user_data,
                    o_cb,
                    || with_values(app, values_h, user_data, o_cb, |values| Ok(values.len())))
}

/// Iterate over the values.
///
................................................................................
pub unsafe extern "C" fn mdata_values_for_each(app: *const App,
                                               values_h: MDataValuesHandle,
                                               value_cb: unsafe extern "C" fn(*mut c_void,
                                                                              *const u8,
                                                                              usize,
                                                                              u64),
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        with_values(app, values_h, user_data.0, o_cb, move |values| {
            for value in values {
                value_cb(user_data.0,
                         value.content.as_safe_ptr(),
                         value.content.len(),
                         value.entry_version);
            }

            Ok(())
        })
    })
................................................................................
}

/// Free the values from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_values_free(app: *const App,
                                           values_h: MDataValuesHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context.object_cache().remove_mdata_values(values_h)?;
            Ok(())
        })
    })
}
................................................................................
        });

        let len: usize =
            unsafe { unwrap!(call_1(|ud, cb| mdata_entries_len(&app, handle, ud, cb))) };
        assert_eq!(len, 2);

        let (tx, rx) = mpsc::channel::<Value>();

        #[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
        extern "C" fn get_cb(user_data: *mut c_void,

                             res: FfiResult,
                             ptr: *const u8,
                             len: usize,
                             version: u64) {
            assert_eq!(res.error_code, 0);

            unsafe {
                let value = vec_clone_from_raw_parts(ptr, len);
                let value = Value {
                    content: value,
                    entry_version: version,
                };
................................................................................
                };

                let user_data = user_data as *mut (Sender<()>, BTreeMap<_, _>);
                let _ = (*user_data).1.insert(key, value);
            }
        }

        #[cfg_attr(feature="cargo-clippy", allow(needless_pass_by_value))]
        extern "C" fn done_cb(user_data: *mut c_void, res: FfiResult) {
            assert_eq!(res.error_code, 0);
            let user_data = user_data as *mut (Sender<_>, BTreeMap<Vec<u8>, Value>);

            unsafe {
                unwrap!((*user_data).0.send(()));
            }
        }

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/entry_actions.rs from [4df9777bf6] to [6a40b864e6].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40


41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
..
99
100
101
102
103
104
105
106
107
108


109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130


131
132
133
134
135
136
137
138
...
200
201
202
203
204
205
206
207
208
209

210
211
212
213
214

215
216
217
218
219
220
221
222
223
224
225
226
227
228


229

230
231
232
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI for mutable data entry actions.

use App;
use ffi::helper::send_sync;
use ffi_utils::{catch_unwind_cb, vec_clone_from_raw_parts};
use object_cache::MDataEntryActionsHandle;
use routing::{EntryAction, Value};
use std::os::raw::c_void;

/// Create new entry actions.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_new(app: *const App,
                                                 user_data: *mut c_void,
                                                 o_cb: extern "C" fn(*mut c_void,
                                                                     i32,
                                                                     MDataEntryActionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {
            let actions = Default::default();


            Ok(context.object_cache().insert_mdata_entry_actions(actions))
        })
    })
}

/// Add action to insert new entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_insert(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    value_ptr: *const u8,
                                                    value_len: usize,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, i32)) {
    add_action(app, actions_h, key_ptr, key_len, user_data, o_cb, || {
        EntryAction::Ins(Value {
            content: vec_clone_from_raw_parts(value_ptr, value_len),
            entry_version: 0,
        })
    })
}

/// Add action to update existing entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_update(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    value_ptr: *const u8,
                                                    value_len: usize,
                                                    entry_version: u64,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, i32)) {
    add_action(app, actions_h, key_ptr, key_len, user_data, o_cb, || {
        EntryAction::Update(Value {
            content: vec_clone_from_raw_parts(value_ptr, value_len),
            entry_version: entry_version,
        })
    })
}

/// Add action to delete existing entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_delete(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    entry_version: u64,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, i32)) {
    add_action(app,
               actions_h,
               key_ptr,
               key_len,
               user_data,
               o_cb,
               || EntryAction::Del(entry_version))
................................................................................
}

/// Free the entry actions from memory
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_free(app: *const App,
                                                  actions_h: MDataEntryActionsHandle,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {


            let _ = context.object_cache().remove_mdata_entry_actions(actions_h)?;
            Ok(())
        })
    })
}

// Add new action to the entry actions stored in the object cache. The action
// to add is the result of the passed in lambda `f`.
unsafe fn add_action<F>(app: *const App,
                        actions_h: MDataEntryActionsHandle,
                        key_ptr: *const u8,
                        key_len: usize,
                        user_data: *mut c_void,
                        o_cb: extern "C" fn(*mut c_void, i32),
                        f: F)
    where F: FnOnce() -> EntryAction
{
    catch_unwind_cb(user_data, o_cb, || {
        let key = vec_clone_from_raw_parts(key_ptr, key_len);
        let action = f();

        send_sync(app, user_data, o_cb, move |_, context| {


            let mut actions = context.object_cache().get_mdata_entry_actions(actions_h)?;
            let _ = actions.insert(key, action);
            Ok(())
        })
    })
}

#[cfg(test)]
................................................................................
        }

        run_now(&app, move |_, context| {
            let actions = unwrap!(context.object_cache().get_mdata_entry_actions(handle));
            assert_eq!(actions.len(), 3);

            match *unwrap!(actions.get(&key0)) {
                EntryAction::Ins(Value { ref content, entry_version: 0 }) if *content == value0 => {
                    ()
                }

                _ => panic!("Unexpected action"),
            }

            match *unwrap!(actions.get(&key1)) {
                EntryAction::Update(Value { ref content, entry_version }) if *content == value1 &&

                                                                             entry_version ==
                                                                             version1 => (),
                _ => panic!("Unexpected action"),
            }

            match *unwrap!(actions.get(&key2)) {
                EntryAction::Del(version) if version == version2 => (),
                _ => panic!("Unexpected action"),
            }
        });

        unsafe { unwrap!(call_0(|ud, cb| mdata_entry_actions_free(&app, handle, ud, cb))) };

        run_now(&app, move |_, context| {


            assert!(context.object_cache().get_mdata_entry_actions(handle).is_err())

        });
    }
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|





|









|




>
>
|













|


|
|
|













|


|
|
|











|







 







|


>
>
|












|








>
>
|







 







|
|
|
>




|
>
|
|












>
>
|
>



1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
..
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
...
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI for mutable data entry actions.

use App;
use ffi::helper::send_sync;
use ffi_utils::{FfiResult, catch_unwind_cb, vec_clone_from_raw_parts};
use object_cache::MDataEntryActionsHandle;
use routing::{EntryAction, Value};
use std::os::raw::c_void;

/// Create new entry actions.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_new(app: *const App,
                                                 user_data: *mut c_void,
                                                 o_cb: extern "C" fn(*mut c_void,
                                                                     FfiResult,
                                                                     MDataEntryActionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {
            let actions = Default::default();
            Ok(context
                   .object_cache()
                   .insert_mdata_entry_actions(actions))
        })
    })
}

/// Add action to insert new entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_insert(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    value_ptr: *const u8,
                                                    value_len: usize,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    add_action(app, actions_h, key_ptr, key_len, user_data, o_cb, || {
        EntryAction::Ins(Value {
                             content: vec_clone_from_raw_parts(value_ptr, value_len),
                             entry_version: 0,
                         })
    })
}

/// Add action to update existing entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_update(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    value_ptr: *const u8,
                                                    value_len: usize,
                                                    entry_version: u64,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    add_action(app, actions_h, key_ptr, key_len, user_data, o_cb, || {
        EntryAction::Update(Value {
                                content: vec_clone_from_raw_parts(value_ptr, value_len),
                                entry_version: entry_version,
                            })
    })
}

/// Add action to delete existing entry.
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_delete(app: *const App,
                                                    actions_h: MDataEntryActionsHandle,
                                                    key_ptr: *const u8,
                                                    key_len: usize,
                                                    entry_version: u64,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    add_action(app,
               actions_h,
               key_ptr,
               key_len,
               user_data,
               o_cb,
               || EntryAction::Del(entry_version))
................................................................................
}

/// Free the entry actions from memory
#[no_mangle]
pub unsafe extern "C" fn mdata_entry_actions_free(app: *const App,
                                                  actions_h: MDataEntryActionsHandle,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context
                .object_cache()
                .remove_mdata_entry_actions(actions_h)?;
            Ok(())
        })
    })
}

// Add new action to the entry actions stored in the object cache. The action
// to add is the result of the passed in lambda `f`.
unsafe fn add_action<F>(app: *const App,
                        actions_h: MDataEntryActionsHandle,
                        key_ptr: *const u8,
                        key_len: usize,
                        user_data: *mut c_void,
                        o_cb: extern "C" fn(*mut c_void, FfiResult),
                        f: F)
    where F: FnOnce() -> EntryAction
{
    catch_unwind_cb(user_data, o_cb, || {
        let key = vec_clone_from_raw_parts(key_ptr, key_len);
        let action = f();

        send_sync(app, user_data, o_cb, move |_, context| {
            let mut actions = context
                .object_cache()
                .get_mdata_entry_actions(actions_h)?;
            let _ = actions.insert(key, action);
            Ok(())
        })
    })
}

#[cfg(test)]
................................................................................
        }

        run_now(&app, move |_, context| {
            let actions = unwrap!(context.object_cache().get_mdata_entry_actions(handle));
            assert_eq!(actions.len(), 3);

            match *unwrap!(actions.get(&key0)) {
                EntryAction::Ins(Value {
                                     ref content,
                                     entry_version: 0,
                                 }) if *content == value0 => (),
                _ => panic!("Unexpected action"),
            }

            match *unwrap!(actions.get(&key1)) {
                EntryAction::Update(Value {
                                        ref content,
                                        entry_version,
                                    }) if *content == value1 && entry_version == version1 => (),
                _ => panic!("Unexpected action"),
            }

            match *unwrap!(actions.get(&key2)) {
                EntryAction::Del(version) if version == version2 => (),
                _ => panic!("Unexpected action"),
            }
        });

        unsafe { unwrap!(call_0(|ud, cb| mdata_entry_actions_free(&app, handle, ud, cb))) };

        run_now(&app, move |_, context| {
            assert!(context
                        .object_cache()
                        .get_mdata_entry_actions(handle)
                        .is_err())
        });
    }
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/helper.rs from [378b17127c] to [9af77c5957].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

45
46
47
48
49
50
51
52
53
54
55
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use errors::AppError;

use object_cache::{MDataPermissionsHandle, ObjectCache, SignKeyHandle};
use routing::{PermissionSet, User};
use std::collections::BTreeMap;

// Retrieve the sign key corresponding to the handle from the object cache and wrap it
// in `User`. If the handle is 0, return `User::Anyone`.
pub fn get_user(object_cache: &ObjectCache, handle: SignKeyHandle) -> Result<User, AppError> {
    let user = if handle != 0 {
        let sign_key = object_cache.get_sign_key(handle)?;
        User::Key(*sign_key)
    } else {
        User::Anyone
    };

    Ok(user)
}

// Insert the permissions into the object cache.
pub fn insert_permissions(object_cache: &ObjectCache,
                          permissions: BTreeMap<User, PermissionSet>)
                          -> MDataPermissionsHandle {
    let permissions = permissions.into_iter()

        .map(|(user, permission_set)| {
            let permission_set_h = object_cache.insert_mdata_permission_set(permission_set);
            (user, permission_set_h)
        })
        .collect();

    object_cache.insert_mdata_permissions(permissions)
}

// Retrieve permissions from the object cache.
pub fn get_permissions(object_cache: &ObjectCache,


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|


>







|













|
>

|
|
|







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use errors::AppError;
use ffi::mutable_data::permissions::USER_ANYONE;
use object_cache::{MDataPermissionsHandle, ObjectCache, SignKeyHandle};
use routing::{PermissionSet, User};
use std::collections::BTreeMap;

// Retrieve the sign key corresponding to the handle from the object cache and wrap it
// in `User`. If the handle is 0, return `User::Anyone`.
pub fn get_user(object_cache: &ObjectCache, handle: SignKeyHandle) -> Result<User, AppError> {
    let user = if handle != USER_ANYONE {
        let sign_key = object_cache.get_sign_key(handle)?;
        User::Key(*sign_key)
    } else {
        User::Anyone
    };

    Ok(user)
}

// Insert the permissions into the object cache.
pub fn insert_permissions(object_cache: &ObjectCache,
                          permissions: BTreeMap<User, PermissionSet>)
                          -> MDataPermissionsHandle {
    let permissions = permissions
        .into_iter()
        .map(|(user, permission_set)| {
                 let permission_set_h = object_cache.insert_mdata_permission_set(permission_set);
                 (user, permission_set_h)
             })
        .collect();

    object_cache.insert_mdata_permissions(permissions)
}

// Retrieve permissions from the object cache.
pub fn get_permissions(object_cache: &ObjectCache,

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/mod.rs from [dc76686306] to [1d21161e8a].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

32
33
34
35
36
37
38
39
40








41
42
43
44
45

46

47
48
49
50
51
52
53
54
55
56
57
58
59
60
..
65
66
67
68
69
70
71
72
73
74
75
76
77
78

79
80
81
82
83
84
85
86
87
88
89
90
91
92

93
94
95

96




97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
...
120
121
122
123
124
125
126



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147

148
149
150
151
152
153
154




155
156
157










158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176

177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192


193
194
195
196
197

198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220

221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253

254
255
256

257




258
259
260
261
262
263
264
...
265
266
267
268
269
270
271
272
273
274
275
276

277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
...
300
301
302
303
304
305
306

307
308
309
310
311
312
313








314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341

342
343
344
345
346
347
348
349
350
351
352
353


354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382

383
384
385

386




387
388
389
390
391
392
393
...
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413

414
415
416

417




418
419
420
421
422
423
424
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

pub mod entry_actions;
pub mod entries;
pub mod permissions;
mod helper;
#[cfg(test)]
mod tests;

use App;
use errors::AppError;
use ffi::helper::send_with_mdata_info;

use ffi_utils::{OpaqueCtx, catch_unwind_cb, vec_clone_from_raw_parts};
use futures::Future;
use object_cache::{MDataEntriesHandle, MDataEntryActionsHandle, MDataInfoHandle, MDataKeysHandle,
                   MDataPermissionSetHandle, MDataPermissionsHandle, MDataValuesHandle,
                   SignKeyHandle};
use routing::MutableData;
use safe_core::{CoreError, FutureExt, mdata_info};
use std::os::raw::c_void;
use std::ptr;









/// Create new mutable data and put it on the network.
///
/// `permissions_h` is a handle to permissions to be set on the mutable data.
/// If 0, the permissions will be empty.

/// `entries_h` is a handle to entries for the mutable data. If 0, the entries will be empty.

#[no_mangle]
pub unsafe extern "C" fn mdata_put(app: *const App,
                                   info_h: MDataInfoHandle,
                                   permissions_h: MDataPermissionsHandle,
                                   entries_h: MDataEntriesHandle,
                                   user_data: *mut c_void,
                                   o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
................................................................................
                        user_data,
                        o_cb)
            } else {
                Default::default()
            };

            let entries = if entries_h != 0 {
                let entries = try_cb!(context.object_cache().get_mdata_entries(entries_h),
                                      user_data,
                                      o_cb);

                try_cb!(mdata_info::encrypt_entries(&info, &*entries).map_err(AppError::from),
                        user_data,
                        o_cb)

            } else {
                Default::default()
            };

            let data = try_cb!(MutableData::new(info.name,
                                                info.type_tag,
                                                permissions,
                                                entries,
                                                btree_set![owner_key])
                                   .map_err(CoreError::from)
                                   .map_err(AppError::from),
                               user_data,
                               o_cb);


            client.put_mdata(data)
                .map_err(AppError::from)
                .then(move |result| {

                    o_cb(user_data.0, ffi_result_code!(result));




                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

/// Get version of the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_get_version(app: *const App,
                                           info_h: MDataInfoHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, i32, u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app,
                             info_h,
                             user_data,
                             o_cb,
                             |client, _, info| client.get_mdata_version(info.name, info.type_tag))
    })
................................................................................
/// Get value at the given key from the mutable data.
/// The arguments to the callback are:
///     1. user data
///     2. error code
///     3. pointer to content
///     4. content length
///     5. entry version



#[no_mangle]
pub unsafe extern "C" fn mdata_get_value(app: *const App,
                                         info_h: MDataInfoHandle,
                                         key_ptr: *const u8,
                                         key_len: usize,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             i32,
                                                             *const u8,
                                                             usize,
                                                             u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let key = vec_clone_from_raw_parts(key_ptr, key_len);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let info = info.clone();


            client.get_mdata_value(info.name, info.type_tag, key)
                .and_then(move |value| {
                    let content = info.decrypt(&value.content)?;
                    Ok((content, value.entry_version))
                })
                .map(move |(content, version)| {
                    o_cb(user_data.0, 0, content.as_ptr(), content.len(), version);




                })
                .map_err(AppError::from)
                .map_err(move |err| o_cb(user_data.0, ffi_error_code!(err), ptr::null(), 0, 0))










                .into_box()
                .into()
        })
    })
}

/// Get complete list of entries in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_entries(app: *const App,
                                            info_h: MDataInfoHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                i32,
                                                                MDataEntriesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();


            client.list_mdata_entries(info.name, info.type_tag)
                .map_err(AppError::from)
                .and_then(move |entries| {
                    let entries = mdata_info::decrypt_entries(&info, &entries)?;
                    Ok(context.object_cache().insert_mdata_entries(entries))
                })
        })
    })
}

/// Get list of keys in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_keys(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32, MDataKeysHandle)) {


    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();


            client.list_mdata_keys(info.name, info.type_tag)
                .map_err(AppError::from)
                .and_then(move |keys| {
                    let keys = mdata_info::decrypt_keys(&info, &keys)?;
                    Ok(context.object_cache().insert_mdata_keys(keys))
                })
        })
    })
}

/// Get list of values in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_values(app: *const App,
                                           info_h: MDataInfoHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               i32,
                                                               MDataValuesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();


            client.list_mdata_values(info.name, info.type_tag)
                .map_err(AppError::from)
                .and_then(move |values| {
                    let values = mdata_info::decrypt_values(&info, &values)?;
                    Ok(context.object_cache().insert_mdata_values(values))
                })
        })
    })
}

/// Mutate entries of the mutable data.
#[no_mangle]
pub unsafe fn mdata_mutate_entries(app: *const App,
                                   info_h: MDataInfoHandle,
                                   actions_h: MDataEntryActionsHandle,
                                   user_data: *mut c_void,
                                   o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let actions = {
                let actions = try_cb!(context.object_cache().get_mdata_entry_actions(actions_h),
                                      user_data,
                                      o_cb);
                try_cb!(mdata_info::encrypt_entry_actions(&info, &*actions).map_err(AppError::from),
                        user_data,
                        o_cb)
            };


            client.mutate_mdata_entries(info.name, info.type_tag, actions)
                .map_err(AppError::from)
                .then(move |result| {

                    o_cb(user_data.0, ffi_result_code!(result));




                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}
................................................................................

/// Get list of all permissions set on the mutable data
#[no_mangle]
pub unsafe fn mdata_list_permissions(app: *const App,
                                     info_h: MDataInfoHandle,
                                     user_data: *mut c_void,
                                     o_cb: extern "C" fn(*mut c_void,
                                                         i32,
                                                         MDataPermissionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();

            client.list_mdata_permissions(info.name, info.type_tag)
                .map(move |perms| helper::insert_permissions(context.object_cache(), perms))
        })
    })
}

/// Get list of permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key, or 0 which means "anyone".
#[no_mangle]
pub unsafe fn mdata_list_user_permissions(app: *const App,
                                          info_h: MDataInfoHandle,
                                          user_h: SignKeyHandle,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void,
                                                              i32,
                                                              MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
................................................................................
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);

            let context = context.clone();


            client.list_mdata_user_permissions(info.name, info.type_tag, user)
                .map(move |set| {
                    let handle = context.object_cache().insert_mdata_permission_set(set);
                    o_cb(user_data.0, 0, handle);
                })
                .map_err(AppError::from)
                .map_err(move |err| o_cb(user_data.0, ffi_error_code!(err), 0))








                .into_box()
                .into()
        })
    })
}

/// Set permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key, or 0 which means "anyone".
#[no_mangle]
pub unsafe fn mdata_set_user_permissions(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_h: SignKeyHandle,
                                         permission_set_h: MDataPermissionSetHandle,
                                         version: u64,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);
            let permission_set = *try_cb!(context.object_cache()

                                              .get_mdata_permission_set(permission_set_h),
                                          user_data,
                                          o_cb);

            client.set_mdata_user_permissions(info.name,
                                              info.type_tag,
                                              user,
                                              permission_set,
                                              version)
                .map_err(AppError::from)
                .then(move |result| {
                    o_cb(user_data.0, ffi_result_code!(result));


                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

/// Delete permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key, or 0 which means "anyone".
#[no_mangle]
pub unsafe fn mdata_del_user_permissions(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_h: SignKeyHandle,
                                         version: u64,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);


            client.del_mdata_user_permissions(info.name, info.type_tag, user, version)
                .map_err(AppError::from)
                .then(move |result| {

                    o_cb(user_data.0, ffi_result_code!(result));




                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}
................................................................................
/// Change owner of the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_change_owner(app: *const App,
                                            info_h: MDataInfoHandle,
                                            new_owner_h: SignKeyHandle,
                                            version: u64,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let new_owner = *try_cb!(context.object_cache().get_sign_key(new_owner_h),
                                     user_data,
                                     o_cb);


            client.change_mdata_owner(info.name, info.type_tag, new_owner, version)
                .map_err(AppError::from)
                .then(move |result| {

                    o_cb(user_data.0, ffi_result_code!(result));




                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|











>
|





|


>
>
>
>
>
>
>
>




|
>
|
>






|







 







|
|
|
<
<
<
<
>









|
|



>
|


>
|
>
>
>
>













|







 







>
>
>







|













>
|
<
<
|
<

|
>
>
>
>
|

|
>
>
>
>
>
>
>
>
>
>












|






>
|

<
<
|
<









|
>
>





>
|

<
<
|
<










|






>
|

<
<
|
<










|







<
|
|
|
<
<
<
<
<
>
|


>
|
>
>
>
>







 







|




>
|







|






|







 







>
|

|
|
|

|
>
>
>
>
>
>
>
>








|







|










|
>




|
|
|
|
|
|
|
|
>
>










|






|











>
|


>
|
>
>
>
>







 







|











>
|


>
|
>
>
>
>







1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
..
72
73
74
75
76
77
78
79
80
81




82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
...
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162


163

164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204


205

206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225


226

227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246


247

248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265

266
267
268





269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
...
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
...
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

pub mod entry_actions;
pub mod entries;
pub mod permissions;
mod helper;
#[cfg(test)]
mod tests;

use App;
use errors::AppError;
use ffi::helper::send_with_mdata_info;
use ffi_utils::{FFI_RESULT_OK, FfiResult, OpaqueCtx, SafePtr, catch_unwind_cb,
                vec_clone_from_raw_parts};
use futures::Future;
use object_cache::{MDataEntriesHandle, MDataEntryActionsHandle, MDataInfoHandle, MDataKeysHandle,
                   MDataPermissionSetHandle, MDataPermissionsHandle, MDataValuesHandle,
                   SignKeyHandle};
use routing::MutableData;
use safe_core::{CoreError, FutureExt};
use std::os::raw::c_void;
use std::ptr;

/// Special value that represents an empty permission set.
#[no_mangle]
pub static PERMISSIONS_EMPTY: u64 = 0;

/// Special value that represents an empty entry set.
#[no_mangle]
pub static ENTRIES_EMPTY: u64 = 0;

/// Create new mutable data and put it on the network.
///
/// `permissions_h` is a handle to permissions to be set on the mutable data.
/// If `PERMISSIONS_EMPTY`, the permissions will be empty.
///
/// `entries_h` is a handle to entries for the mutable data.
/// If `ENTRIES_EMPTY`, the entries will be empty.
#[no_mangle]
pub unsafe extern "C" fn mdata_put(app: *const App,
                                   info_h: MDataInfoHandle,
                                   permissions_h: MDataPermissionsHandle,
                                   entries_h: MDataEntriesHandle,
                                   user_data: *mut c_void,
                                   o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
................................................................................
                        user_data,
                        o_cb)
            } else {
                Default::default()
            };

            let entries = if entries_h != 0 {
                try_cb!(context.object_cache().get_mdata_entries(entries_h),
                        user_data,
                        o_cb)




                        .clone()
            } else {
                Default::default()
            };

            let data = try_cb!(MutableData::new(info.name,
                                                info.type_tag,
                                                permissions,
                                                entries,
                                                btree_set![owner_key])
                                       .map_err(CoreError::from)
                                       .map_err(AppError::from),
                               user_data,
                               o_cb);

            client
                .put_mdata(data)
                .map_err(AppError::from)
                .then(move |result| {
                    let (error_code, description) = ffi_result!(result);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

/// Get version of the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_get_version(app: *const App,
                                           info_h: MDataInfoHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void, FfiResult, u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app,
                             info_h,
                             user_data,
                             o_cb,
                             |client, _, info| client.get_mdata_version(info.name, info.type_tag))
    })
................................................................................
/// Get value at the given key from the mutable data.
/// The arguments to the callback are:
///     1. user data
///     2. error code
///     3. pointer to content
///     4. content length
///     5. entry version
///
/// Please notice that if a value is fetched from a private `MutableData`,
/// it's not automatically decrypted.
#[no_mangle]
pub unsafe extern "C" fn mdata_get_value(app: *const App,
                                         info_h: MDataInfoHandle,
                                         key_ptr: *const u8,
                                         key_len: usize,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             *const u8,
                                                             usize,
                                                             u64)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);
        let key = vec_clone_from_raw_parts(key_ptr, key_len);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let info = info.clone();

            client
                .get_mdata_value(info.name, info.type_tag, key)


                .and_then(move |value| Ok((value.content, value.entry_version)))

                .map(move |(content, version)| {
                         o_cb(user_data.0,
                              FFI_RESULT_OK,
                              content.as_safe_ptr(),
                              content.len(),
                              version);
                     })
                .map_err(AppError::from)
                .map_err(move |err| {
                    let (error_code, description) = ffi_error!(err);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         ptr::null(),
                         0,
                         0)
                })
                .into_box()
                .into()
        })
    })
}

/// Get complete list of entries in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_entries(app: *const App,
                                            info_h: MDataInfoHandle,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void,
                                                                FfiResult,
                                                                MDataEntriesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();

            client
                .list_mdata_entries(info.name, info.type_tag)
                .map_err(AppError::from)


                .and_then(move |entries| Ok(context.object_cache().insert_mdata_entries(entries)))

        })
    })
}

/// Get list of keys in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_keys(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void,
                                                             FfiResult,
                                                             MDataKeysHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();

            client
                .list_mdata_keys(info.name, info.type_tag)
                .map_err(AppError::from)


                .and_then(move |keys| Ok(context.object_cache().insert_mdata_keys(keys)))

        })
    })
}

/// Get list of values in the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_list_values(app: *const App,
                                           info_h: MDataInfoHandle,
                                           user_data: *mut c_void,
                                           o_cb: extern "C" fn(*mut c_void,
                                                               FfiResult,
                                                               MDataValuesHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            let info = info.clone();

            client
                .list_mdata_values(info.name, info.type_tag)
                .map_err(AppError::from)


                .and_then(move |values| Ok(context.object_cache().insert_mdata_values(values)))

        })
    })
}

/// Mutate entries of the mutable data.
#[no_mangle]
pub unsafe fn mdata_mutate_entries(app: *const App,
                                   info_h: MDataInfoHandle,
                                   actions_h: MDataEntryActionsHandle,
                                   user_data: *mut c_void,
                                   o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);

            let actions = try_cb!(context.object_cache().get_mdata_entry_actions(actions_h),
                                  user_data,
                                  o_cb);





            client
                .mutate_mdata_entries(info.name, info.type_tag, actions.clone())
                .map_err(AppError::from)
                .then(move |result| {
                    let (error_code, description) = ffi_result!(result);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}
................................................................................

/// Get list of all permissions set on the mutable data
#[no_mangle]
pub unsafe fn mdata_list_permissions(app: *const App,
                                     info_h: MDataInfoHandle,
                                     user_data: *mut c_void,
                                     o_cb: extern "C" fn(*mut c_void,
                                                         FfiResult,
                                                         MDataPermissionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_with_mdata_info(app, info_h, user_data, o_cb, move |client, context, info| {
            let context = context.clone();
            client
                .list_mdata_permissions(info.name, info.type_tag)
                .map(move |perms| helper::insert_permissions(context.object_cache(), perms))
        })
    })
}

/// Get list of permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key or `USER_ANYONE`.
#[no_mangle]
pub unsafe fn mdata_list_user_permissions(app: *const App,
                                          info_h: MDataInfoHandle,
                                          user_h: SignKeyHandle,
                                          user_data: *mut c_void,
                                          o_cb: extern "C" fn(*mut c_void,
                                                              FfiResult,
                                                              MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
................................................................................
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);

            let context = context.clone();

            client
                .list_mdata_user_permissions(info.name, info.type_tag, user)
                .map(move |set| {
                         let handle = context.object_cache().insert_mdata_permission_set(set);
                         o_cb(user_data.0, FFI_RESULT_OK, handle);
                     })
                .map_err(AppError::from)
                .map_err(move |err| {
                    let (error_code, description) = ffi_error!(err);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         },
                         0)
                })
                .into_box()
                .into()
        })
    })
}

/// Set permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key or `USER_ANYONE`.
#[no_mangle]
pub unsafe fn mdata_set_user_permissions(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_h: SignKeyHandle,
                                         permission_set_h: MDataPermissionSetHandle,
                                         version: u64,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);
            let permission_set = *try_cb!(context
                                              .object_cache()
                                              .get_mdata_permission_set(permission_set_h),
                                          user_data,
                                          o_cb);

            client
                .set_mdata_user_permissions(info.name, info.type_tag, user, permission_set, version)
                .map_err(AppError::from)
                .then(move |result| {
                    let (error_code, description) = ffi_result!(result);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

/// Delete permissions set on the mutable data for the given user.
///
/// User is either handle to a signing key or `USER_ANYONE`.
#[no_mangle]
pub unsafe fn mdata_del_user_permissions(app: *const App,
                                         info_h: MDataInfoHandle,
                                         user_h: SignKeyHandle,
                                         version: u64,
                                         user_data: *mut c_void,
                                         o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let user = try_cb!(helper::get_user(context.object_cache(), user_h),
                               user_data,
                               o_cb);

            client
                .del_mdata_user_permissions(info.name, info.type_tag, user, version)
                .map_err(AppError::from)
                .then(move |result| {
                    let (error_code, description) = ffi_result!(result);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}
................................................................................
/// Change owner of the mutable data.
#[no_mangle]
pub unsafe extern "C" fn mdata_change_owner(app: *const App,
                                            info_h: MDataInfoHandle,
                                            new_owner_h: SignKeyHandle,
                                            version: u64,
                                            user_data: *mut c_void,
                                            o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        let user_data = OpaqueCtx(user_data);

        (*app).send(move |client, context| {
            let info = try_cb!(context.object_cache().get_mdata_info(info_h),
                               user_data,
                               o_cb);
            let new_owner = *try_cb!(context.object_cache().get_sign_key(new_owner_h),
                                     user_data,
                                     o_cb);

            client
                .change_mdata_owner(info.name, info.type_tag, new_owner, version)
                .map_err(AppError::from)
                .then(move |result| {
                    let (error_code, description) = ffi_result!(result);
                    o_cb(user_data.0,
                         FfiResult {
                             error_code,
                             description: description.as_ptr(),
                         });
                    Ok(())
                })
                .into_box()
                .into()
        })
    })
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/permissions.rs from [47bd6f61e4] to [ac1e64fdd9].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

27
28
29
30




31
32
33
34
35
36
37
..
54
55
56
57
58
59
60
61
62
63
64


65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
..
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
...
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
...
116
117
118
119
120
121
122
123
124
125


126
127
128
129
130
131
132
133
134
135
136
137
138
139
140


141
142
143
144
145
146
147
148
149
150
151
152
153


154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172

173

174
175
176
177
178
179
180
181
...
185
186
187
188
189
190
191
192
193
194
195
196


197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224


225
226
227
228
229
230
231
232
233
234
235
236
237
238
239


240
241
242
243
244
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

//! FFI for mutable data permissions and permission sets.

use App;
use errors::AppError;
use ffi::helper::send_sync;

use ffi_utils::{OpaqueCtx, catch_unwind_cb};
use object_cache::{MDataPermissionSetHandle, MDataPermissionsHandle, SignKeyHandle};
use routing::{Action, PermissionSet, User};
use std::os::raw::c_void;





/// Permission actions.
#[repr(C)]
pub enum MDataAction {
    /// Permission to insert new entries.
    Insert,
    /// Permission to update existing entries.
................................................................................
}

/// Create new permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permission_set_new(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      i32,
                                                                      MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {


            Ok(context.object_cache().insert_mdata_permission_set(PermissionSet::new()))
        })
    })
}

/// Allow the action in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_allow(app: *const App,
                                                     set_h: MDataPermissionSetHandle,
                                                     action: MDataAction,
                                                     user_data: *mut c_void,
                                                     o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.allow(action.into());
            Ok(())
        })
    })
................................................................................

/// Deny the action in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_deny(app: *const App,
                                                    set_h: MDataPermissionSetHandle,
                                                    action: MDataAction,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.deny(action.into());
            Ok(())
        })
    })
................................................................................

/// Clear the actions in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_clear(app: *const App,
                                                     set_h: MDataPermissionSetHandle,
                                                     action: MDataAction,
                                                     user_data: *mut c_void,
                                                     o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.clear(action.into());
            Ok(())
        })
    })
................................................................................
}

/// Free the permission set from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_free(app: *const App,
                                                    set_h: MDataPermissionSetHandle,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {


            let _ = context.object_cache().remove_mdata_permission_set(set_h)?;
            Ok(())
        })
    })
}

/// Create new permissions.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_new(app: *const App,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   i32,
                                                                   MDataPermissionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {


            Ok(context.object_cache().insert_mdata_permissions(Default::default()))
        })
    })
}

/// Get the number of entries in the permissions.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_len(app: *const App,
                                               permissions_h: MDataPermissionsHandle,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void, i32, usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {


            let permissions = context.object_cache().get_mdata_permissions(permissions_h)?;
            Ok(permissions.len())
        })
    })
}

/// Get the permission set corresponding to the given user (0 means anyone).

#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_get(app: *const App,
                                               permissions_h: MDataPermissionsHandle,
                                               user_h: SignKeyHandle,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   i32,
                                                                   MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let permissions = context.object_cache().get_mdata_permissions(permissions_h)?;
            let user_key = *context.object_cache().get_sign_key(user_h)?;

            let handle = *permissions.get(&User::Key(user_key))

                .ok_or(AppError::InvalidSignKeyHandle)?;

            Ok(handle)
        })
    })
}

/// Iterate over the permissions.
................................................................................
pub unsafe extern "C"
fn mdata_permissions_for_each(app: *const App,
                              permissions_h: MDataPermissionsHandle,
                              each_cb: extern "C" fn(*mut c_void,
                                                            SignKeyHandle,
                                                            MDataPermissionSetHandle),
                              user_data: *mut c_void,
                              done_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, done_cb, || {
        let user_data = OpaqueCtx(user_data);

        send_sync(app, user_data.0, done_cb, move |_, context| {


            let permissions = context.object_cache().get_mdata_permissions(permissions_h)?;
            for (user_key, permission_set_h) in &*permissions {
                let user_h = match *user_key {
                    User::Key(key) => context.object_cache().insert_sign_key(key),
                    User::Anyone => 0,
                };
                each_cb(user_data.0, user_h, *permission_set_h);
            }

            Ok(())
        })
    })
}

/// Insert permission set for the given user to the permissions.
///
/// To insert permissions for "Anyone", pass 0 as the user handle.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_insert(app: *const App,
                                                  permissions_h: MDataPermissionsHandle,
                                                  user_h: SignKeyHandle,
                                                  permission_set_h: MDataPermissionSetHandle,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut permissions = context.object_cache().get_mdata_permissions(permissions_h)?;
            let user_key = *context.object_cache().get_sign_key(user_h)?;


            let _ = permissions.insert(User::Key(user_key), permission_set_h);

            Ok(())
        })
    })
}

/// Free the permissions from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_free(app: *const App,
                                                permissions_h: MDataPermissionsHandle,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void, i32)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {


            let _ = context.object_cache().remove_mdata_permissions(permissions_h)?;
            Ok(())
        })
    })
}


|
|
<
|

|
|
<
<
|

|
|
|
<

|
|






>
|



>
>
>
>







 







|



>
>
|










|







 







|







 







|







 







|


>
>
|










|



>
>
|









|


>
>
|





|
>






|



|
|
>
|
>
|







 







|




>
>
|



|











|






|


|
|
>
>
|











|


>
>
|




1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
..
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
..
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
...
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
...
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
...
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

//! FFI for mutable data permissions and permission sets.

use App;
use errors::AppError;
use ffi::helper::send_sync;
use ffi::mutable_data::helper;
use ffi_utils::{FfiResult, OpaqueCtx, catch_unwind_cb};
use object_cache::{MDataPermissionSetHandle, MDataPermissionsHandle, SignKeyHandle};
use routing::{Action, PermissionSet, User};
use std::os::raw::c_void;

/// Special value that represents `User::Anyone` in permission sets.
#[no_mangle]
pub static USER_ANYONE: u64 = 0;

/// Permission actions.
#[repr(C)]
pub enum MDataAction {
    /// Permission to insert new entries.
    Insert,
    /// Permission to update existing entries.
................................................................................
}

/// Create new permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permission_set_new(app: *const App,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void,
                                                                      FfiResult,
                                                                      MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {
            Ok(context
                   .object_cache()
                   .insert_mdata_permission_set(PermissionSet::new()))
        })
    })
}

/// Allow the action in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_allow(app: *const App,
                                                     set_h: MDataPermissionSetHandle,
                                                     action: MDataAction,
                                                     user_data: *mut c_void,
                                                     o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.allow(action.into());
            Ok(())
        })
    })
................................................................................

/// Deny the action in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_deny(app: *const App,
                                                    set_h: MDataPermissionSetHandle,
                                                    action: MDataAction,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.deny(action.into());
            Ok(())
        })
    })
................................................................................

/// Clear the actions in the permission set.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_clear(app: *const App,
                                                     set_h: MDataPermissionSetHandle,
                                                     action: MDataAction,
                                                     user_data: *mut c_void,
                                                     o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut set = context.object_cache().get_mdata_permission_set(set_h)?;
            *set = set.clear(action.into());
            Ok(())
        })
    })
................................................................................
}

/// Free the permission set from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_set_free(app: *const App,
                                                    set_h: MDataPermissionSetHandle,
                                                    user_data: *mut c_void,
                                                    o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context
                .object_cache()
                .remove_mdata_permission_set(set_h)?;
            Ok(())
        })
    })
}

/// Create new permissions.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_new(app: *const App,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   FfiResult,
                                                                   MDataPermissionsHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, |_, context| {
            Ok(context
                   .object_cache()
                   .insert_mdata_permissions(Default::default()))
        })
    })
}

/// Get the number of entries in the permissions.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_len(app: *const App,
                                               permissions_h: MDataPermissionsHandle,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void, FfiResult, usize)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let permissions = context
                .object_cache()
                .get_mdata_permissions(permissions_h)?;
            Ok(permissions.len())
        })
    })
}

/// Get the permission set corresponding to the given user.
/// Use a constant `USER_ANYONE` for anyone.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_get(app: *const App,
                                               permissions_h: MDataPermissionsHandle,
                                               user_h: SignKeyHandle,
                                               user_data: *mut c_void,
                                               o_cb: extern "C" fn(*mut c_void,
                                                                   FfiResult,
                                                                   MDataPermissionSetHandle)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let permissions = context
                .object_cache()
                .get_mdata_permissions(permissions_h)?;
            let handle = *permissions
                              .get(&helper::get_user(context.object_cache(), user_h)?)
                              .ok_or(AppError::InvalidSignKeyHandle)?;

            Ok(handle)
        })
    })
}

/// Iterate over the permissions.
................................................................................
pub unsafe extern "C"
fn mdata_permissions_for_each(app: *const App,
                              permissions_h: MDataPermissionsHandle,
                              each_cb: extern "C" fn(*mut c_void,
                                                            SignKeyHandle,
                                                            MDataPermissionSetHandle),
                              user_data: *mut c_void,
done_cb: extern "C" fn(*mut c_void, FfiResult )){
    catch_unwind_cb(user_data, done_cb, || {
        let user_data = OpaqueCtx(user_data);

        send_sync(app, user_data.0, done_cb, move |_, context| {
            let permissions = context
                .object_cache()
                .get_mdata_permissions(permissions_h)?;
            for (user_key, permission_set_h) in &*permissions {
                let user_h = match *user_key {
                    User::Key(key) => context.object_cache().insert_sign_key(key),
                    User::Anyone => USER_ANYONE,
                };
                each_cb(user_data.0, user_h, *permission_set_h);
            }

            Ok(())
        })
    })
}

/// Insert permission set for the given user to the permissions.
///
/// To insert permissions for "Anyone", pass `USER_ANYONE` as the user handle.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_insert(app: *const App,
                                                  permissions_h: MDataPermissionsHandle,
                                                  user_h: SignKeyHandle,
                                                  permission_set_h: MDataPermissionSetHandle,
                                                  user_data: *mut c_void,
                                                  o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let mut permissions = context
                .object_cache()
                .get_mdata_permissions(permissions_h)?;
            let _ = permissions.insert(helper::get_user(context.object_cache(), user_h)?,
                                       permission_set_h);

            Ok(())
        })
    })
}

/// Free the permissions from memory.
#[no_mangle]
pub unsafe extern "C" fn mdata_permissions_free(app: *const App,
                                                permissions_h: MDataPermissionsHandle,
                                                user_data: *mut c_void,
                                                o_cb: extern "C" fn(*mut c_void, FfiResult)) {
    catch_unwind_cb(user_data, o_cb, || {
        send_sync(app, user_data, o_cb, move |_, context| {
            let _ = context
                .object_cache()
                .remove_mdata_permissions(permissions_h)?;
            Ok(())
        })
    })
}

Modified wiki_references/2017/software/MaidSafe_net/src_from_GitHub/the_repository_clones/beaker-plugin-safe-authenticator/native/safe_app/src/ffi/mutable_data/tests.rs from [b79d6d4de0] to [9b12746720].

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

31
32
33
34
35
36
37
..
38
39
40
41
42
43
44
45
46
47
48
49
50

51
52
53
54
55
56
57
58
..
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

98
99
100
101
102
103
104
105
106
107
108
109
...
112
113
114
115
116
117
118





119

120
121
122
123
124
125
126
127
128
129
130
...
148
149
150
151
152
153
154
155
156
157
158
159
160

161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
...
201
202
203
204
205
206
207
208
209
210
211
212
213





214

215

216
217
218
219
220
221
222
223
...
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
...
317
318
319
320
321
322
323

324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340





341

342

343
344
345
346
347
348
349
350
...
374
375
376
377
378
379
380
381
382
383
384
385
386
387

388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410

411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433

434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
...
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496

497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
...
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
...
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605

606
607
608
609


610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
...
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
...
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
...
741
742
743
744
745
746
747
748


749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
...
823
824
825
826
827
828
829
830
831
832
833
834
835

836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
...
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
...
914
915
916
917
918
919
920





























































































































































































































































































































// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net
// Commercial License, version 1.0 or later, or (2) The General Public License
// (GPL), version 3, depending on which licence you accepted on initial access
// to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project
// generally, you agree to be bound by the terms of the MaidSafe Contributor
// Agreement, version 1.0.
// This, along with the Licenses can be found in the root directory of this
// project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network
// Software distributed under the GPL Licence is distributed on an "AS IS"
// BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
// implied.
//
// Please review the Licences for the specific language governing permissions
// and limitations relating to use of the SAFE Network Software.

use futures::Future;
use maidsafe_utilities::thread;
use rand::{OsRng, Rng};
use routing::{Action, ClientError, EntryAction, MutableData, PermissionSet, User, Value, XorName};
use rust_sodium::crypto::sign;
use safe_core::{CoreError, DIR_TAG, FutureExt};
use safe_core::utils::test_utils::random_client;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::mpsc;

use test_utils::{create_app, run};

// MD created by App. App lists it's own sign_pk in owners field: Put should
// fail - Rejected by MaidManagers. Should pass when it lists the owner's
// sign_pk instead
#[test]
fn md_created_by_app_1() {
................................................................................
    let app = create_app();
    run(&app, |client, _app_context| {
        let mut rng = unwrap!(OsRng::new());

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.public_signing_key()));
        let name: XorName = rng.gen();
        let mdata = unwrap!(MutableData::new(name.clone(),
                                             DIR_TAG,
                                             BTreeMap::new(),
                                             BTreeMap::new(),
                                             owners));
        let cl2 = client.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                match res {
                    Ok(()) => panic!("Put should be rejected by MaidManagers"),
                    Err(CoreError::RoutingClientError(ClientError::InvalidOwners)) => (),
                    Err(x) => panic!("Expected ClientError::InvalidOwners. Got {:?}", x),
                }
                let mut owners = BTreeSet::new();
................................................................................
        let mut rng = unwrap!(OsRng::new());
        let sign_pk = unwrap!(client.public_signing_key());

        let mut permissions = BTreeMap::new();
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();
        let mdata =
            unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, BTreeMap::new(), owners));
        let name2 = name.clone();
        let cl2 = client.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                cl2.change_mdata_owner(name, DIR_TAG, sign_pk, 2)
            })
            .then(move |res| -> Result<_, ()> {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                }
                unwrap!(alt_client_tx.send((name2, sign_pk)));
................................................................................
            .into_box()
            .into()
    }));
    let _joiner = thread::named("Alt client", || {
        random_client(move |client| {
            let (name, sign_pk) = unwrap!(alt_client_rx.recv());
            let cl2 = client.clone();





            client.ins_auth_key(sign_pk, 1)

                .then(move |res| {
                    unwrap!(res);
                    cl2.change_mdata_owner(name, DIR_TAG, sign_pk, 2)
                })
                .then(move |res| -> Result<(), ()> {
                    match res {
                        Ok(()) => panic!("It should fail"),
                        Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                        Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                    }
                    unwrap!(tx.send(()));
................................................................................
    unwrap!(app.send(move |client, _app_context| {
        let sign_pk = unwrap!(client.public_signing_key());
        unwrap!(app_sign_pk_tx.send(sign_pk));
        let name: XorName = unwrap!(name_rx.recv());
        let mut actions = BTreeMap::new();
        let _ = actions.insert(vec![1, 2, 3, 4],
                               EntryAction::Ins(Value {
                                   content: vec![2, 3, 5],
                                   entry_version: 1,
                               }));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let name2 = name.clone();

        client.mutate_mdata_entries(name.clone(), DIR_TAG, actions)
            .then(move |res| {
                unwrap!(res);
                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![1, 2, 3, 4],
                                       EntryAction::Update(Value {
                                           content: vec![2, 8, 5],
                                           entry_version: 2,
                                       }));
                cl2.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
................................................................................
                                       PermissionSet::new().allow(Action::Insert));

            let mut owners = BTreeSet::new();
            owners.insert(unwrap!(client.owner_key()));

            let name: XorName = rng.gen();

            let mdata = unwrap!(MutableData::new(name.clone(),
                                                 DIR_TAG,
                                                 permissions,
                                                 BTreeMap::new(),
                                                 owners));
            let cl2 = client.clone();





            client.ins_auth_key(app_sign_pk, 1)

                .and_then(move |()| {

                    cl2.put_mdata(mdata)
                })
                .map(move |()| unwrap!(name_tx.send(name)))
                .map_err(|e| panic!("{:?}", e))
        });
    });
    unwrap!(rx.recv());
}
................................................................................
    unwrap!(app.send(move |client, _app_context| {
        let sign_pk = unwrap!(client.public_signing_key());
        unwrap!(app_sign_pk_tx.send(sign_pk));
        let name: XorName = unwrap!(name_rx.recv());
        let mut actions = BTreeMap::new();
        let _ = actions.insert(vec![1, 2, 3, 4],
                               EntryAction::Ins(Value {
                                   content: vec![2, 3, 5],
                                   entry_version: 1,
                               }));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let name2 = name.clone();
        let name3 = name.clone();
        let name4 = name.clone();
        let name5 = name.clone();
        client.mutate_mdata_entries(name.clone(), DIR_TAG, actions)
            .then(move |res| {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                }
                let mut actions = BTreeMap::new();
................................................................................
    }));
    let _joiner = thread::named("Alt client", || {
        random_client(move |client| {
            let app_sign_pk = unwrap!(app_sign_pk_rx.recv());
            let mut rng = unwrap!(OsRng::new());

            let mut permissions = BTreeMap::new();

            let _ = permissions.insert(User::Key(app_sign_pk),
                                       PermissionSet::new().allow(Action::ManagePermissions));

            let mut data = BTreeMap::new();
            let _ = data.insert(vec![1, 8, 3, 4],
                                Value {
                                    content: vec![1],
                                    entry_version: 1,
                                });

            let mut owners = BTreeSet::new();
            owners.insert(unwrap!(client.owner_key()));

            let name: XorName = rng.gen();

            let mdata = unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, data, owners));
            let cl2 = client.clone();





            client.ins_auth_key(app_sign_pk, 1)

                .and_then(move |()| {

                    cl2.put_mdata(mdata)
                })
                .map(move |()| unwrap!(name_tx.send(name)))
                .map_err(|e| panic!("{:?}", e))
        });
    });
    unwrap!(rx.recv());
}
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();
        let mdata =
            unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, BTreeMap::new(), owners));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let name2 = name.clone();
        let name3 = name.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                unwrap!(name_tx.send(name.clone()));
                let entry_key: Vec<u8> = unwrap!(entry_rx.recv());
                cl2.get_mdata_value(name, DIR_TAG, entry_key.clone())
                    .map(move |v| (v, entry_key))
            })
            .then(move |res| {
                let (value, entry_key) = unwrap!(res);
                assert_eq!(value,
                           Value {
                               content: vec![8],
                               entry_version: 1,
                           });
                cl3.del_mdata_user_permissions(name2, DIR_TAG, User::Anyone, 1)
                    .map(move |()| entry_key)
            })
            .then(move |res| {
                let entry_key = unwrap!(res);
                unwrap!(mutate_again_tx.send(()));
                unwrap!(final_check_rx.recv());
                cl4.list_mdata_keys(name3, DIR_TAG).map(move |x| (x, entry_key))

            })
            .then(move |res| -> Result<_, ()> {
                let (keys, entry_key) = unwrap!(res);
                assert_eq!(keys.len(), 1);
                assert!(keys.contains(&entry_key));
                unwrap!(tx.send(()));
                Ok(())
            })
            .into_box()
            .into()
    }));
    unwrap!(app2.send(move |client, _app_context| {
        let name = unwrap!(name_rx.recv());
        let entry_key = vec![1, 2, 3];

        let mut actions = BTreeMap::new();
        let _ = actions.insert(entry_key.clone(),
                               EntryAction::Ins(Value {
                                   content: vec![8],
                                   entry_version: 1,
                               }));

        let cl2 = client.clone();

        client.mutate_mdata_entries(name.clone(), DIR_TAG, actions)
            .then(move |res| {
                unwrap!(res);
                unwrap!(entry_tx.send(entry_key));
                unwrap!(mutate_again_rx.recv());

                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![2, 2, 2],
                                       EntryAction::Ins(Value {
                                           content: vec![21],
                                           entry_version: 1,
                                       }));

                cl2.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| -> Result<_, ()> {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();
        let mdata =
            unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, BTreeMap::new(), owners));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let cl7 = client.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                let permissions = PermissionSet::new().allow(Action::Update);
                cl2.set_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), permissions, 1)
            })
            .then(move |res| {
                unwrap!(res);
                cl3.del_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), 1)
            })
            .then(move |res| {
                match res {
                    Ok(()) => panic!("It should fail with invalid successor"),
                    Err(CoreError::RoutingClientError(ClientError::InvalidSuccessor)) => (),
                    Err(x) => panic!("Expected ClientError::InvalidSuccessor. Got {:?}", x),
                }
                cl4.list_mdata_permissions(name, DIR_TAG)
            })
            .then(move |res| {
                let permissions = unwrap!(res);
                assert_eq!(permissions.len(), 2);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Insert),
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
................................................................................
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(random_key)))
                               .is_allowed(Action::ManagePermissions),
                           None);
                cl5.get_mdata_version(name, DIR_TAG)
            })
            .then(move |res| {
                let v = unwrap!(res);
                assert_eq!(v, 1);
                cl6.del_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), v + 1)
            })
            .then(move |res| {
                unwrap!(res);
                cl7.list_mdata_permissions(name, DIR_TAG)
            })
            .map(move |permissions| {
                assert_eq!(permissions.len(), 1);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Insert),
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Update),
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();
        let mdata =
            unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, BTreeMap::new(), owners));

        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let cl7 = client.clone();
        let cl8 = client.clone();
        let cl9 = client.clone();
        let cl10 = client.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                let permissions = PermissionSet::new().allow(Action::Insert).allow(Action::Delete);


                cl2.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_a),
                                               permissions,
                                               1)
            })
            .then(move |res| {
                unwrap!(res);
                cl3.list_mdata_permissions(name, DIR_TAG)
            })
            .then(move |res| {
                {
                    let permissions = unwrap!(res);
                    assert_eq!(permissions.len(), 2);
                    assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                                   .is_allowed(Action::Insert),
                               None);
................................................................................
                cl4.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_b),
                                               permissions,
                                               2)
            })
            .then(move |res| {
                unwrap!(res);
                cl5.list_mdata_permissions(name, DIR_TAG)
            })
            .then(move |res| {
                {
                    let permissions = unwrap!(res);
                    assert_eq!(permissions.len(), 3);
                    assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                                   .is_allowed(Action::Insert),
                               None);
................................................................................
                cl6.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_b),
                                               permissions,
                                               3)
            })
            .then(move |res| {
                unwrap!(res);
                cl7.del_mdata_user_permissions(name, DIR_TAG, User::Key(random_key_a), 4)
            })
            .then(move |res| {
                unwrap!(res);
                cl8.list_mdata_permissions(name, DIR_TAG)
            })
            .then(move |res| {
                {
                    let permissions = unwrap!(res);
                    assert_eq!(permissions.len(), 2);
                    assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                                   .is_allowed(Action::Insert),
                               None);
................................................................................
                                   .is_allowed(Action::Delete),
                               None);
                    assert_eq!(unwrap!(permissions.get(&User::Key(random_key_b)))
                                   .is_allowed(Action::ManagePermissions),
                               None);
                }

                let permissions = PermissionSet::new().deny(Action::Insert).deny(Action::Delete);


                cl9.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_b),
                                               permissions,
                                               5)
            })
            .then(move |res| {
                unwrap!(res);
                cl10.list_mdata_permissions(name, DIR_TAG)
            })
            .then(move |res| -> Result<_, ()> {
                {
                    let permissions = unwrap!(res);
                    assert_eq!(permissions.len(), 2);
                    assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                                   .is_allowed(Action::Insert),
                               None);
................................................................................
                                entry_version: 1,
                            });

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();
        let mdata = unwrap!(MutableData::new(name.clone(), DIR_TAG, permissions, data, owners));

        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();

        client.put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![0, 1, 1],
                                       EntryAction::Ins(Value {
                                           content: vec![2, 3, 17],
                                           entry_version: 1,
                                       }));
                let _ = actions.insert(vec![0, 1, 0],
                                       EntryAction::Update(Value {
                                           content: vec![2, 8, 64],
                                           entry_version: 2,
                                       }));
                let _ = actions.insert(vec![0, 0, 1], EntryAction::Del(2));
                cl2.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| {
                unwrap!(res);
                cl3.list_mdata_entries(name, DIR_TAG)
            })
            .then(move |res| {
                let entries = unwrap!(res);
                assert_eq!(entries.len(), 3);
                assert_eq!(*unwrap!(entries.get(&vec![0, 0, 1])),
                           Value {
                               content: vec![],
                               entry_version: 2,
................................................................................
                           Value {
                               content: vec![2, 3, 17],
                               entry_version: 1,
                           });
                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![1, 0, 0],
                                       EntryAction::Ins(Value {
                                           content: vec![4, 4, 4, 4],
                                           entry_version: 1,
                                       }));
                let _ = actions.insert(vec![0, 1, 0],
                                       EntryAction::Update(Value {
                                           content: vec![64, 8, 1],
                                           entry_version: 3,
                                       }));
                let _ = actions.insert(vec![0, 1, 1], EntryAction::Del(2));
                cl4.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| {
                unwrap!(res);
                cl5.list_mdata_entries(name, DIR_TAG)
            })
            .then(|res| -> Result<_, ()> {
                let entries = unwrap!(res);
                assert_eq!(entries.len(), 4);
                assert_eq!(*unwrap!(entries.get(&vec![0, 0, 1])),
                           Value {
                               content: vec![],
                               entry_version: 2,
................................................................................
                               entry_version: 1,
                           });
                Ok(())
            })
            .map_err(|e| panic!("{:?}", e))
    });
}































































































































































































































































































































|
|
<
|

|
|
<
<
|

|
|
|
<

|
|










>







 







|
|
<
<
<

>
|







 







<
|


<
|
|

>
|

|
|
|







 







>
>
>
>
>
|
>

|
|
|







 







|
|
|


|
>
|





|
|
|







 







|
|
<
<
<

>
>
>
>
>
|
>
|
>
|







 







|
|
|





|
|
|
|
|







 







>
|
|













|

>
>
>
>
>
|
>
|
>
|







 







<
|



|
|
>
|

|
|
|
|
|
|











|
|
|
|
>
|

|
|
|
|
|
|










|
|
|


>
|








|
|
|







 







<
|






>
|






|
|
|

|
|
|
|
|
|
|







 







|
|
|
|

|
|
|







 







<
|










>
|


|
>
>







|
|
|







 







|
|
|







 







|
|
|

|
|
|







 







|
>
>







|
|
|







 







|





>
|





|
|
|


|
|
|




|
|
|







 







|
|
|


|
|
|




|
|
|







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
1
2
3
4

5
6
7
8


9
10
11
12
13

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
..
35
36
37
38
39
40
41
42
43



44
45
46
47
48
49
50
51
52
53
..
78
79
80
81
82
83
84

85
86
87

88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
...
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
...
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
...
202
203
204
205
206
207
208
209
210



211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
...
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
...
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
...
387
388
389
390
391
392
393

394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
...
497
498
499
500
501
502
503

504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
...
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
...
602
603
604
605
606
607
608

609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
...
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
...
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
...
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
...
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
...
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
...
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
// Copyright 2016 MaidSafe.net limited.
//
// This SAFE Network Software is licensed to you under (1) the MaidSafe.net Commercial License,
// version 1.0 or later, or (2) The General Public License (GPL), version 3, depending on which

// licence you accepted on initial access to the Software (the "Licences").
//
// By contributing code to the SAFE Network Software, or to this project generally, you agree to be
// bound by the terms of the MaidSafe Contributor Agreement.  This, along with the Licenses can be


// found in the root directory of this project at LICENSE, COPYING and CONTRIBUTOR.
//
// Unless required by applicable law or agreed to in writing, the SAFE Network Software distributed
// under the GPL Licence is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.

//
// Please review the Licences for the specific language governing permissions and limitations
// relating to use of the SAFE Network Software.

use futures::Future;
use maidsafe_utilities::thread;
use rand::{OsRng, Rng};
use routing::{Action, ClientError, EntryAction, MutableData, PermissionSet, User, Value, XorName};
use rust_sodium::crypto::sign;
use safe_core::{CoreError, DIR_TAG, FutureExt};
use safe_core::utils::test_utils::random_client;
use std::collections::{BTreeMap, BTreeSet};
use std::sync::mpsc;
use std::time::Duration;
use test_utils::{create_app, run};

// MD created by App. App lists it's own sign_pk in owners field: Put should
// fail - Rejected by MaidManagers. Should pass when it lists the owner's
// sign_pk instead
#[test]
fn md_created_by_app_1() {
................................................................................
    let app = create_app();
    run(&app, |client, _app_context| {
        let mut rng = unwrap!(OsRng::new());

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.public_signing_key()));
        let name: XorName = rng.gen();
        let mdata =
            unwrap!(MutableData::new(name, DIR_TAG, BTreeMap::new(), BTreeMap::new(), owners));



        let cl2 = client.clone();
        client
            .put_mdata(mdata)
            .then(move |res| {
                match res {
                    Ok(()) => panic!("Put should be rejected by MaidManagers"),
                    Err(CoreError::RoutingClientError(ClientError::InvalidOwners)) => (),
                    Err(x) => panic!("Expected ClientError::InvalidOwners. Got {:?}", x),
                }
                let mut owners = BTreeSet::new();
................................................................................
        let mut rng = unwrap!(OsRng::new());
        let sign_pk = unwrap!(client.public_signing_key());

        let mut permissions = BTreeMap::new();
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));


        let owners = btree_set![unwrap!(client.owner_key())];

        let name: XorName = rng.gen();

        let mdata = unwrap!(MutableData::new(name, DIR_TAG, permissions, BTreeMap::new(), owners));
        let name2 = name;
        let cl2 = client.clone();
        client
            .put_mdata(mdata)
            .then(move |res| {
                      unwrap!(res);
                      cl2.change_mdata_owner(name, DIR_TAG, sign_pk, 1)
                  })
            .then(move |res| -> Result<_, ()> {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                }
                unwrap!(alt_client_tx.send((name2, sign_pk)));
................................................................................
            .into_box()
            .into()
    }));
    let _joiner = thread::named("Alt client", || {
        random_client(move |client| {
            let (name, sign_pk) = unwrap!(alt_client_rx.recv());
            let cl2 = client.clone();
            let cl3 = client.clone();
            client
                .list_auth_keys_and_version()
                .then(move |res| {
                          let (_, version) = unwrap!(res);
                          cl2.ins_auth_key(sign_pk, version + 1)
                      })
                .then(move |res| {
                          unwrap!(res);
                          cl3.change_mdata_owner(name, DIR_TAG, sign_pk, 1)
                      })
                .then(move |res| -> Result<(), ()> {
                    match res {
                        Ok(()) => panic!("It should fail"),
                        Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                        Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                    }
                    unwrap!(tx.send(()));
................................................................................
    unwrap!(app.send(move |client, _app_context| {
        let sign_pk = unwrap!(client.public_signing_key());
        unwrap!(app_sign_pk_tx.send(sign_pk));
        let name: XorName = unwrap!(name_rx.recv());
        let mut actions = BTreeMap::new();
        let _ = actions.insert(vec![1, 2, 3, 4],
                               EntryAction::Ins(Value {
                                                    content: vec![2, 3, 5],
                                                    entry_version: 1,
                                                }));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let name2 = name;
        client
            .mutate_mdata_entries(name, DIR_TAG, actions)
            .then(move |res| {
                unwrap!(res);
                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![1, 2, 3, 4],
                                       EntryAction::Update(Value {
                                                               content: vec![2, 8, 5],
                                                               entry_version: 2,
                                                           }));
                cl2.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
................................................................................
                                       PermissionSet::new().allow(Action::Insert));

            let mut owners = BTreeSet::new();
            owners.insert(unwrap!(client.owner_key()));

            let name: XorName = rng.gen();

            let mdata =
                unwrap!(MutableData::new(name, DIR_TAG, permissions, BTreeMap::new(), owners));



            let cl2 = client.clone();
            let cl3 = client.clone();

            client.list_auth_keys_and_version()
                .then(move |res| {
                    let (_, version) = unwrap!(res);
                    cl2.ins_auth_key(app_sign_pk, version + 1)
                })
                .then(move |res| {
                    unwrap!(res);
                    cl3.put_mdata(mdata)
                })
                .map(move |()| unwrap!(name_tx.send(name)))
                .map_err(|e| panic!("{:?}", e))
        });
    });
    unwrap!(rx.recv());
}
................................................................................
    unwrap!(app.send(move |client, _app_context| {
        let sign_pk = unwrap!(client.public_signing_key());
        unwrap!(app_sign_pk_tx.send(sign_pk));
        let name: XorName = unwrap!(name_rx.recv());
        let mut actions = BTreeMap::new();
        let _ = actions.insert(vec![1, 2, 3, 4],
                               EntryAction::Ins(Value {
                                                    content: vec![2, 3, 5],
                                                    entry_version: 1,
                                                }));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let name2 = name;
        let name3 = name;
        let name4 = name;
        let name5 = name;
        client.mutate_mdata_entries(name, DIR_TAG, actions)
            .then(move |res| {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
                    Err(x) => panic!("Expected ClientError::AccessDenied. Got {:?}", x),
                }
                let mut actions = BTreeMap::new();
................................................................................
    }));
    let _joiner = thread::named("Alt client", || {
        random_client(move |client| {
            let app_sign_pk = unwrap!(app_sign_pk_rx.recv());
            let mut rng = unwrap!(OsRng::new());

            let mut permissions = BTreeMap::new();
            let _ =
                permissions.insert(User::Key(app_sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

            let mut data = BTreeMap::new();
            let _ = data.insert(vec![1, 8, 3, 4],
                                Value {
                                    content: vec![1],
                                    entry_version: 1,
                                });

            let mut owners = BTreeSet::new();
            owners.insert(unwrap!(client.owner_key()));

            let name: XorName = rng.gen();

            let mdata = unwrap!(MutableData::new(name, DIR_TAG, permissions, data, owners));
            let cl2 = client.clone();
            let cl3 = client.clone();

            client.list_auth_keys_and_version()
                .then(move |res| {
                    let (_, version) = unwrap!(res);
                    cl2.ins_auth_key(app_sign_pk, version + 1)
                })
                .then(move |res| {
                    unwrap!(res);
                    cl3.put_mdata(mdata)
                })
                .map(move |()| unwrap!(name_tx.send(name)))
                .map_err(|e| panic!("{:?}", e))
        });
    });
    unwrap!(rx.recv());
}
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();

        let mdata = unwrap!(MutableData::new(name, DIR_TAG, permissions, BTreeMap::new(), owners));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let name2 = name;
        let name3 = name;
        client
            .put_mdata(mdata)
            .then(move |res| {
                      unwrap!(res);
                      unwrap!(name_tx.send(name));
                      let entry_key: Vec<u8> = unwrap!(entry_rx.recv());
                      cl2.get_mdata_value(name, DIR_TAG, entry_key.clone())
                          .map(move |v| (v, entry_key))
                  })
            .then(move |res| {
                let (value, entry_key) = unwrap!(res);
                assert_eq!(value,
                           Value {
                               content: vec![8],
                               entry_version: 1,
                           });
                cl3.del_mdata_user_permissions(name2, DIR_TAG, User::Anyone, 1)
                    .map(move |()| entry_key)
            })
            .then(move |res| {
                      let entry_key = unwrap!(res);
                      unwrap!(mutate_again_tx.send(()));
                      unwrap!(final_check_rx.recv());
                      cl4.list_mdata_keys(name3, DIR_TAG)
                          .map(move |x| (x, entry_key))
                  })
            .then(move |res| -> Result<_, ()> {
                      let (keys, entry_key) = unwrap!(res);
                      assert_eq!(keys.len(), 1);
                      assert!(keys.contains(&entry_key));
                      unwrap!(tx.send(()));
                      Ok(())
                  })
            .into_box()
            .into()
    }));
    unwrap!(app2.send(move |client, _app_context| {
        let name = unwrap!(name_rx.recv());
        let entry_key = vec![1, 2, 3];

        let mut actions = BTreeMap::new();
        let _ = actions.insert(entry_key.clone(),
                               EntryAction::Ins(Value {
                                                    content: vec![8],
                                                    entry_version: 1,
                                                }));

        let cl2 = client.clone();
        client
            .mutate_mdata_entries(name, DIR_TAG, actions)
            .then(move |res| {
                unwrap!(res);
                unwrap!(entry_tx.send(entry_key));
                unwrap!(mutate_again_rx.recv());

                let mut actions = BTreeMap::new();
                let _ = actions.insert(vec![2, 2, 2],
                                       EntryAction::Ins(Value {
                                                            content: vec![21],
                                                            entry_version: 1,
                                                        }));

                cl2.mutate_mdata_entries(name, DIR_TAG, actions)
            })
            .then(move |res| -> Result<_, ()> {
                match res {
                    Ok(()) => panic!("It should fail"),
                    Err(CoreError::RoutingClientError(ClientError::AccessDenied)) => (),
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();

        let mdata = unwrap!(MutableData::new(name, DIR_TAG, permissions, BTreeMap::new(), owners));
        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let cl7 = client.clone();
        client
            .put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                let permissions = PermissionSet::new().allow(Action::Update);
                cl2.set_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), permissions, 1)
            })
            .then(move |res| {
                      unwrap!(res);
                      cl3.del_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), 1)
                  })
            .then(move |res| {
                      match res {
                          Ok(()) => panic!("It should fail with invalid successor"),
                          Err(CoreError::RoutingClientError(ClientError::InvalidSuccessor)) => (),
                          Err(x) => panic!("Expected ClientError::InvalidSuccessor. Got {:?}", x),
                      }
                      cl4.list_mdata_permissions(name, DIR_TAG)
                  })
            .then(move |res| {
                let permissions = unwrap!(res);
                assert_eq!(permissions.len(), 2);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Insert),
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
................................................................................
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(random_key)))
                               .is_allowed(Action::ManagePermissions),
                           None);
                cl5.get_mdata_version(name, DIR_TAG)
            })
            .then(move |res| {
                      let v = unwrap!(res);
                      assert_eq!(v, 1);
                      cl6.del_mdata_user_permissions(name, DIR_TAG, User::Key(random_key), v + 1)
                  })
            .then(move |res| {
                      unwrap!(res);
                      cl7.list_mdata_permissions(name, DIR_TAG)
                  })
            .map(move |permissions| {
                assert_eq!(permissions.len(), 1);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Insert),
                           None);
                assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                               .is_allowed(Action::Update),
................................................................................
        let _ = permissions.insert(User::Key(sign_pk),
                                   PermissionSet::new().allow(Action::ManagePermissions));

        let mut owners = BTreeSet::new();
        owners.insert(unwrap!(client.owner_key()));

        let name: XorName = rng.gen();

        let mdata = unwrap!(MutableData::new(name, DIR_TAG, permissions, BTreeMap::new(), owners));

        let cl2 = client.clone();
        let cl3 = client.clone();
        let cl4 = client.clone();
        let cl5 = client.clone();
        let cl6 = client.clone();
        let cl7 = client.clone();
        let cl8 = client.clone();
        let cl9 = client.clone();
        let cl10 = client.clone();
        client
            .put_mdata(mdata)
            .then(move |res| {
                unwrap!(res);
                let permissions = PermissionSet::new()
                    .allow(Action::Insert)
                    .allow(Action::Delete);
                cl2.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_a),
                                               permissions,
                                               1)
            })
            .then(move |res| {
                      unwrap!(res);
                      cl3.list_mdata_permissions(name, DIR_TAG)
                  })
            .then(move |res| {
                {
                    let permissions = unwrap!(res);
                    assert_eq!(permissions.len(), 2);
                    assert_eq!(unwrap!(permissions.get(&User::Key(sign_pk)))
                                   .is_allowed(Action::Insert),
                               None);
................................................................................
                cl4.set_mdata_user_permissions(name,
                                               DIR_TAG,
                                               User::Key(random_key_b),
                                               permissions,
                                               2)
            })
            .then(move |res| {
                      unwrap!(res);