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