1 /**
2 * @file sharenodekeys.cpp
3 * @brief cr element share/node map key generator
4 *
5 * (c) 2013-2014 by Mega Limited, Auckland, New Zealand
6 *
7 * This file is part of the MEGA SDK - Client Access Engine.
8 *
9 * Applications using the MEGA API must present a valid application key
10 * and comply with the the rules set forth in the Terms of Service.
11 *
12 * The MEGA SDK is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 *
16 * @copyright Simplified (2-clause) BSD License.
17 *
18 * You should have received a copy of the license along with this
19 * program.
20 */
21
22 #include "mega/sharenodekeys.h"
23 #include "mega/node.h"
24 #include "mega/base64.h"
25 #include "mega/megaclient.h"
26 #include "mega/command.h"
27
28 namespace mega {
29 // add share node and return its index
addshare(Node * sn)30 int ShareNodeKeys::addshare(Node* sn)
31 {
32 for (int i = static_cast<int>(shares.size()); i--;)
33 {
34 if (shares[i] == sn)
35 {
36 return i;
37 }
38 }
39
40 shares.push_back(sn);
41
42 return static_cast<int>(shares.size() - 1);
43 }
44
add(Node * n,Node * sn,int specific)45 void ShareNodeKeys::add(Node* n, Node* sn, int specific)
46 {
47 if (!sn)
48 {
49 sn = n;
50 }
51
52 add(n->nodekey(), n->nodehandle, sn, specific);
53 }
54
55 // add a nodecore (!sn: all relevant shares, otherwise starting from sn, fixed: only sn)
add(const string & nodekey,handle nodehandle,Node * sn,int specific,const byte * item,int itemlen)56 void ShareNodeKeys::add(const string& nodekey, handle nodehandle, Node* sn, int specific, const byte* item, int itemlen)
57 {
58 char buf[96];
59 char* ptr;
60 byte key[FILENODEKEYLENGTH];
61
62 int addnode = 0;
63
64 // emit all share nodekeys for known shares
65 do {
66 if (sn->sharekey)
67 {
68 sprintf(buf, ",%d,%d,\"", addshare(sn), (int)items.size());
69
70 sn->sharekey->ecb_encrypt((byte*)nodekey.data(), key, nodekey.size());
71
72 ptr = strchr(buf + 5, 0);
73 ptr += Base64::btoa(key, int(nodekey.size()), ptr);
74 *ptr++ = '"';
75
76 keys.append(buf, ptr - buf);
77 addnode = 1;
78 }
79 } while (!specific && (sn = sn->parent));
80
81 if (addnode)
82 {
83 items.resize(items.size() + 1);
84
85 if (item)
86 {
87 items[items.size() - 1].assign((const char*)item, itemlen);
88 }
89 else
90 {
91 items[items.size() - 1].assign((const char*)&nodehandle, MegaClient::NODEHANDLE);
92 }
93 }
94 }
95
get(Command * c,bool skiphandles)96 void ShareNodeKeys::get(Command* c, bool skiphandles)
97 {
98 if (keys.size())
99 {
100 c->beginarray("cr");
101
102 // emit share node handles
103 c->beginarray();
104 for (unsigned i = 0; i < shares.size(); i++)
105 {
106 c->element((const byte*)&shares[i]->nodehandle, MegaClient::NODEHANDLE);
107 }
108
109 c->endarray();
110
111 // emit item handles (can be node handles or upload tokens)
112 c->beginarray();
113
114 if (!skiphandles)
115 {
116 for (unsigned i = 0; i < items.size(); i++)
117 {
118 c->element((const byte*)items[i].c_str(), int(items[i].size()));
119 }
120 }
121
122 c->endarray();
123
124 // emit linkage/keys
125 c->beginarray();
126 c->appendraw(keys.c_str() + 1, int(keys.size() - 1));
127 c->endarray();
128
129 c->endarray();
130 }
131 }
132 } // namespace
133