1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #define LOG_TAG "ExtensionCloudServerImpl"
17 #include "cloud_server_impl.h"
18 #include "accesstoken_kit.h"
19 #include "asset_loader_impl.h"
20 #include "cloud_extension.h"
21 #include "cloud_ext_types.h"
22 #include "cloud/subscription.h"
23 #include "error.h"
24 #include "error/general_error.h"
25 #include "extension_util.h"
26 #include "log_print.h"
27 #include "metadata/meta_data_manager.h"
28 #include "utils/anonymous.h"
29 
30 namespace OHOS::CloudData {
31 __attribute__((used)) static bool g_isInit =
32     DistributedData::CloudServer::RegisterCloudInstance(new (std::nothrow) CloudServerImpl());
33 using namespace Security::AccessToken;
34 using DBMetaMgr = DistributedData::MetaDataManager;
35 using Anonymous = DistributedData::Anonymous;
GetServerInfo(int32_t userId,bool needSpaceInfo)36 DBCloudInfo CloudServerImpl::GetServerInfo(int32_t userId, bool needSpaceInfo)
37 {
38     DBCloudInfo result;
39     OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
40     if (server == nullptr) {
41         return result;
42     }
43     auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
44         OhCloudExtCloudSyncFree(server);
45     });
46     OhCloudExtCloudInfo *info = nullptr;
47     auto status = OhCloudExtCloudSyncGetServiceInfo(pServer.get(), &info);
48     if (status != ERRNO_SUCCESS || info == nullptr) {
49         return result;
50     }
51     auto pInfo = std::shared_ptr<OhCloudExtCloudInfo>(info, [](auto *info) { OhCloudExtCloudInfoFree(info); });
52     status = OhCloudExtCloudInfoGetUser(pInfo.get(), &result.user);
53     if (status != ERRNO_SUCCESS || result.user != userId) {
54         ZLOGE("[IN]user: %{public}d, [OUT]user: %{public}d", userId, result.user);
55         return result;
56     }
57     unsigned char *id = nullptr;
58     size_t idLen = 0;
59     status = OhCloudExtCloudInfoGetId(pInfo.get(), &id, reinterpret_cast<unsigned int *>(&idLen));
60     if (status != ERRNO_SUCCESS || id == nullptr) {
61         return result;
62     }
63     result.id = std::string(reinterpret_cast<char *>(id), idLen);
64     if (needSpaceInfo) {
65         unsigned long long totalSpace = 0;
66         OhCloudExtCloudInfoGetTotalSpace(pInfo.get(), &totalSpace);
67         result.totalSpace = totalSpace;
68         unsigned long long remainSpace = 0;
69         OhCloudExtCloudInfoGetRemainSpace(pInfo.get(), &remainSpace);
70         result.remainSpace = remainSpace;
71     }
72     OhCloudExtCloudInfoEnabled(pInfo.get(), &result.enableCloud);
73     OhCloudExtHashMap *briefInfo = nullptr;
74     status = OhCloudExtCloudInfoGetAppInfo(pInfo.get(), &briefInfo);
75     if (status != ERRNO_SUCCESS || briefInfo == nullptr) {
76         return result;
77     }
78     auto pBriefInfo = std::shared_ptr<OhCloudExtHashMap>(briefInfo, [](auto *briefInfo) {
79         OhCloudExtHashMapFree(briefInfo);
80     });
81     GetAppInfo(pBriefInfo, result);
82     return result;
83 }
84 
GetAppInfo(std::shared_ptr<OhCloudExtHashMap> briefInfo,DBCloudInfo & cloudInfo)85 void CloudServerImpl::GetAppInfo(std::shared_ptr<OhCloudExtHashMap> briefInfo, DBCloudInfo &cloudInfo)
86 {
87     OhCloudExtVector *keys = nullptr;
88     OhCloudExtVector *values = nullptr;
89     auto status = OhCloudExtHashMapIterGetKeyValuePair(briefInfo.get(), &keys, &values);
90     if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
91         return;
92     }
93     auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
94     auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
95     size_t keysLen = 0;
96     OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
97     size_t valuesLen = 0;
98     OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
99     if (keysLen == 0 || keysLen != valuesLen) {
100         return;
101     }
102     for (size_t i = 0; i < keysLen; i++) {
103         void *key = nullptr;
104         size_t keyLen = 0;
105         status = OhCloudExtVectorGet(pKeys.get(), i, &key, reinterpret_cast<unsigned int *>(&keyLen));
106         if (status != ERRNO_SUCCESS || key == nullptr) {
107             return;
108         }
109         void *value = nullptr;
110         size_t valueLen = 0;
111         status = OhCloudExtVectorGet(pValues.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
112         if (status != ERRNO_SUCCESS || value == nullptr) {
113             return;
114         }
115         std::string bundle(reinterpret_cast<char *>(key), keyLen);
116         OhCloudExtAppInfo *appInfo = reinterpret_cast<OhCloudExtAppInfo *>(value);
117         cloudInfo.apps[bundle] = ExtensionUtil::ConvertAppInfo(appInfo);
118         OhCloudExtAppInfoFree(appInfo);
119     }
120 }
121 
GetAppSchema(int32_t userId,const std::string & bundleName)122 std::pair<int32_t, DBSchemaMeta> CloudServerImpl::GetAppSchema(int32_t userId, const std::string &bundleName)
123 {
124     DBSchemaMeta dbSchema;
125     dbSchema.bundleName = bundleName;
126     OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
127     if (server == nullptr) {
128         return { DBErr::E_ERROR, dbSchema };
129     }
130     auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
131         OhCloudExtCloudSyncFree(server);
132     });
133     OhCloudExtSchemaMeta *schema = nullptr;
134     auto status = OhCloudExtCloudSyncGetAppSchema(pServer.get(),
135         reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), &schema);
136     if (status == ERRNO_UNSUPPORTED) {
137         return { DBErr::E_NOT_SUPPORT, dbSchema };
138     }
139     if (status != ERRNO_SUCCESS || schema == nullptr) {
140         return { DBErr::E_ERROR, dbSchema };
141     }
142     auto pSchema = std::shared_ptr<OhCloudExtSchemaMeta>(schema, [](auto *schema) {
143         OhCloudExtSchemaMetaFree(schema);
144     });
145     OhCloudExtSchemaMetaGetVersion(pSchema.get(), &dbSchema.version);
146     OhCloudExtVector *databases = nullptr;
147     status = OhCloudExtSchemaMetaGetDatabases(pSchema.get(), &databases);
148     if (status != ERRNO_SUCCESS || databases == nullptr) {
149         return { DBErr::E_ERROR, dbSchema };
150     }
151     auto pDatabases = std::shared_ptr<OhCloudExtVector>(databases, [](auto *databases) {
152         OhCloudExtVectorFree(databases);
153     });
154     GetDatabases(pDatabases, dbSchema);
155     return { DBErr::E_OK, dbSchema };
156 }
157 
GetDatabases(std::shared_ptr<OhCloudExtVector> databases,DBSchemaMeta & dbSchema)158 void CloudServerImpl::GetDatabases(std::shared_ptr<OhCloudExtVector> databases, DBSchemaMeta &dbSchema)
159 {
160     size_t dbsLen = 0;
161     auto status = OhCloudExtVectorGetLength(databases.get(), reinterpret_cast<unsigned int *>(&dbsLen));
162     if (status != ERRNO_SUCCESS || dbsLen == 0) {
163         return;
164     }
165     dbSchema.databases.reserve(dbsLen);
166     for (size_t i = 0; i < dbsLen; i++) {
167         void *database = nullptr;
168         size_t dbLen = 0;
169         status = OhCloudExtVectorGet(databases.get(), i, &database, reinterpret_cast<unsigned int *>(&dbLen));
170         if (status != ERRNO_SUCCESS || database == nullptr) {
171             return;
172         }
173         OhCloudExtDatabase *db = reinterpret_cast<OhCloudExtDatabase *>(database);
174         auto pDb = std::shared_ptr<OhCloudExtDatabase>(db, [](auto *db) { OhCloudExtDatabaseFree(db); });
175         DBMeta dbMeta;
176         unsigned char *name = nullptr;
177         size_t nameLen = 0;
178         OhCloudExtDatabaseGetName(pDb.get(), &name, reinterpret_cast<unsigned int *>(&nameLen));
179         if (name == nullptr) {
180             return;
181         }
182         dbMeta.name = std::string(reinterpret_cast<char *>(name), nameLen);
183         unsigned char *alias = nullptr;
184         size_t aliasLen = 0;
185         OhCloudExtDatabaseGetAlias(pDb.get(), &alias, reinterpret_cast<unsigned int *>(&aliasLen));
186         if (alias == nullptr) {
187             return;
188         }
189         dbMeta.alias = std::string(reinterpret_cast<char *>(alias), aliasLen);
190         OhCloudExtHashMap *tables = nullptr;
191         OhCloudExtDatabaseGetTable(pDb.get(), &tables);
192         if (tables == nullptr) {
193             return;
194         }
195         auto pTables = std::shared_ptr<OhCloudExtHashMap>(tables, [](auto *tables) {
196             OhCloudExtHashMapFree(tables);
197         });
198         GetTables(pTables, dbMeta);
199         dbSchema.databases.emplace_back(std::move(dbMeta));
200     }
201 }
202 
GetTables(std::shared_ptr<OhCloudExtHashMap> tables,DBMeta & dbMeta)203 void CloudServerImpl::GetTables(std::shared_ptr<OhCloudExtHashMap> tables, DBMeta &dbMeta)
204 {
205     OhCloudExtVector *keys = nullptr;
206     OhCloudExtVector *values = nullptr;
207     auto status = OhCloudExtHashMapIterGetKeyValuePair(tables.get(), &keys, &values);
208     if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
209         return;
210     }
211     auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
212     auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
213     size_t keysLen = 0;
214     OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
215     size_t valuesLen = 0;
216     OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
217     if (keysLen == 0 || keysLen != valuesLen) {
218         return;
219     }
220     for (size_t i = 0; i < valuesLen; i++) {
221         void *value = nullptr;
222         size_t valueLen = 0;
223         status = OhCloudExtVectorGet(pValues.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
224         if (status != ERRNO_SUCCESS || value == nullptr) {
225             return;
226         }
227         DBTable dbTable;
228         OhCloudExtTable *table = reinterpret_cast<OhCloudExtTable *>(value);
229         auto pTable = std::shared_ptr<OhCloudExtTable>(table, [](auto *table) { OhCloudExtTableFree(table); });
230         GetTableInfo(pTable, dbTable);
231         OhCloudExtVector *fields = nullptr;
232         status = OhCloudExtTableGetFields(pTable.get(), &fields);
233         if (status != ERRNO_SUCCESS || fields == nullptr) {
234             return;
235         }
236         auto pFields = std::shared_ptr<OhCloudExtVector>(fields, [](auto *fields) {
237             OhCloudExtVectorFree(fields);
238         });
239         GetFields(pFields, dbTable);
240         dbMeta.tables.emplace_back(std::move(dbTable));
241     }
242 }
243 
GetTableInfo(std::shared_ptr<OhCloudExtTable> pTable,DBTable & dbTable)244 void CloudServerImpl::GetTableInfo(std::shared_ptr<OhCloudExtTable> pTable, DBTable &dbTable)
245 {
246     unsigned char *tbName = nullptr;
247     size_t tbNameLen = 0;
248     OhCloudExtTableGetName(pTable.get(), &tbName, reinterpret_cast<unsigned int *>(&tbNameLen));
249     if (tbName == nullptr) {
250         return;
251     }
252     dbTable.name = std::string(reinterpret_cast<char *>(tbName), tbNameLen);
253     unsigned char *tbAlias = nullptr;
254     size_t tbAliasLen = 0;
255     OhCloudExtTableGetAlias(pTable.get(), &tbAlias, reinterpret_cast<unsigned int *>(&tbAliasLen));
256     if (tbAlias == nullptr) {
257         return;
258     }
259     dbTable.alias = std::string(reinterpret_cast<char *>(tbAlias), tbAliasLen);
260 }
261 
GetFields(std::shared_ptr<OhCloudExtVector> fields,DBTable & dbTable)262 void CloudServerImpl::GetFields(std::shared_ptr<OhCloudExtVector> fields, DBTable &dbTable)
263 {
264     size_t fieldsLen = 0;
265     auto status = OhCloudExtVectorGetLength(fields.get(), reinterpret_cast<unsigned int *>(&fieldsLen));
266     if (status != ERRNO_SUCCESS || fieldsLen == 0) {
267         return;
268     }
269     dbTable.fields.reserve(fieldsLen);
270     for (size_t i = 0; i < fieldsLen; i++) {
271         void *value = nullptr;
272         size_t valueLen = 0;
273         status = OhCloudExtVectorGet(fields.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
274         if (status != ERRNO_SUCCESS || value == nullptr) {
275             return;
276         }
277         OhCloudExtField *field = reinterpret_cast<OhCloudExtField *>(value);
278         auto pField = std::shared_ptr<OhCloudExtField>(field, [](auto *field) { OhCloudExtFieldFree(field); });
279         DBField dbField;
280         unsigned char *colName = nullptr;
281         size_t colLen = 0;
282         OhCloudExtFieldGetColName(pField.get(), &colName, reinterpret_cast<unsigned int *>(&colLen));
283         if (colName == nullptr) {
284             return;
285         }
286         dbField.colName = std::string(reinterpret_cast<char *>(colName), colLen);
287         unsigned char *fdAlias = nullptr;
288         size_t fdAliasLen = 0;
289         OhCloudExtFieldGetAlias(pField.get(), &fdAlias, reinterpret_cast<unsigned int *>(&fdAliasLen));
290         if (fdAlias == nullptr) {
291             return;
292         }
293         dbField.alias = std::string(reinterpret_cast<char *>(fdAlias), fdAliasLen);
294         uint32_t fdtype;
295         OhCloudExtFieldGetTyp(pField.get(), &fdtype);
296         dbField.type = static_cast<int32_t>(fdtype);
297         bool primary = false;
298         OhCloudExtFieldGetPrimary(pField.get(), &primary);
299         dbField.primary = primary;
300         bool nullable = true;
301         OhCloudExtFieldGetNullable(pField.get(), &nullable);
302         dbField.nullable = nullable;
303         dbTable.fields.emplace_back(std::move(dbField));
304     }
305 }
306 
Subscribe(int32_t userId,const std::map<std::string,std::vector<DBMeta>> & dbs)307 int32_t CloudServerImpl::Subscribe(int32_t userId, const std::map<std::string, std::vector<DBMeta>> &dbs)
308 {
309     OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
310     if (server == nullptr) {
311         return DBErr::E_ERROR;
312     }
313     auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) {
314         OhCloudExtCloudSyncFree(server);
315     });
316     OhCloudExtHashMap *databases = OhCloudExtHashMapNew(OhCloudExtRustType::VALUETYPE_VEC_DATABASE);
317     if (databases == nullptr) {
318         return DBErr::E_ERROR;
319     }
320     auto pDatabases = std::shared_ptr<OhCloudExtHashMap>(databases, [](auto *databases) {
321         OhCloudExtHashMapFree(databases);
322     });
323     for (auto &[bundle, db] : dbs) {
324         OhCloudExtVector *database = OhCloudExtVectorNew(OhCloudExtRustType::VALUETYPE_DATABASE);
325         if (database == nullptr) {
326             return DBErr::E_ERROR;
327         }
328         size_t databaseLen = 0;
329         for (auto &item : db) {
330             auto data = ExtensionUtil::Convert(item);
331             if (data.first == nullptr) {
332                 return DBErr::E_ERROR;
333             }
334             auto status = OhCloudExtVectorPush(database, data.first, data.second);
335             if (status != ERRNO_SUCCESS) {
336                 return DBErr::E_ERROR;
337             }
338             databaseLen += 1;
339         }
340         auto status = OhCloudExtHashMapInsert(pDatabases.get(),
341             const_cast<void *>(reinterpret_cast<const void *>(bundle.c_str())), bundle.size(), database, databaseLen);
342         if (status != ERRNO_SUCCESS) {
343             return DBErr::E_ERROR;
344         }
345     }
346     return DoSubscribe(userId, pServer, pDatabases);
347 }
348 
DoSubscribe(int32_t userId,std::shared_ptr<OhCloudExtCloudSync> server,std::shared_ptr<OhCloudExtHashMap> databases)349 int32_t CloudServerImpl::DoSubscribe(int32_t userId, std::shared_ptr<OhCloudExtCloudSync> server,
350     std::shared_ptr<OhCloudExtHashMap> databases)
351 {
352     auto expire = std::chrono::duration_cast<std::chrono::milliseconds>
353         ((std::chrono::system_clock::now() + std::chrono::hours(INTERVAL)).time_since_epoch()).count();
354     OhCloudExtHashMap *relations = nullptr;
355     OhCloudExtVector *errs = nullptr;
356     auto status = OhCloudExtCloudSyncSubscribe(server.get(), databases.get(), expire, &relations, &errs);
357     if (status != ERRNO_SUCCESS || relations == nullptr) {
358         return DBErr::E_ERROR;
359     }
360     auto pRelations = std::shared_ptr<OhCloudExtHashMap>(relations, [](auto *relations) {
361         OhCloudExtHashMapFree(relations);
362     });
363     if (errs != nullptr) {
364         auto pErrs = std::shared_ptr<OhCloudExtVector>(errs, [](auto *errs) { OhCloudExtVectorFree(errs); });
365         size_t errsLen = 0;
366         status = OhCloudExtVectorGetLength(pErrs.get(), reinterpret_cast<unsigned int *>(&errsLen));
367         if (status != ERRNO_SUCCESS || errsLen == 0) {
368             return DBErr::E_ERROR;
369         }
370         for (size_t i = 0; i < errsLen; i++) {
371             void *value = nullptr;
372             size_t valueLen = 0;
373             status = OhCloudExtVectorGet(pErrs.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
374             if (status != ERRNO_SUCCESS || value == nullptr) {
375                 return DBErr::E_ERROR;
376             }
377             auto err = *reinterpret_cast<int *>(value);
378             if (err != ERRNO_SUCCESS) {
379                 ZLOGE("sub fail, err:%{oublic}d", err);
380                 return DBErr::E_ERROR;
381             }
382         }
383     }
384     return SaveSubscription(userId, pRelations, server);
385 }
386 
SaveSubscription(int32_t userId,std::shared_ptr<OhCloudExtHashMap> relations,std::shared_ptr<OhCloudExtCloudSync> server)387 int32_t CloudServerImpl::SaveSubscription(int32_t userId, std::shared_ptr<OhCloudExtHashMap> relations,
388     std::shared_ptr<OhCloudExtCloudSync> server)
389 {
390     OhCloudExtCloudInfo *info = nullptr;
391     auto status = OhCloudExtCloudSyncGetServiceInfo(server.get(), &info);
392     if (status != ERRNO_SUCCESS || info == nullptr) {
393         return DBErr::E_ERROR;
394     }
395     auto pInfo = std::shared_ptr<OhCloudExtCloudInfo>(info, [](auto *info) { OhCloudExtCloudInfoFree(info); });
396     unsigned char *id = nullptr;
397     size_t idLen = 0;
398     status = OhCloudExtCloudInfoGetId(pInfo.get(), &id, reinterpret_cast<unsigned int *>(&idLen));
399     if (status != ERRNO_SUCCESS || id == nullptr) {
400         return DBErr::E_ERROR;
401     }
402     std::string accountId(reinterpret_cast<char *>(id), idLen);
403     DBSub sub;
404     sub.userId = userId;
405     DBMetaMgr::GetInstance().LoadMeta(sub.GetKey(), sub, true);
406     if (!sub.id.empty() && sub.id != accountId) {
407         ZLOGE("diff id, [meta]id:%{public}s, [server]id:%{public}s", Anonymous::Change(sub.id).c_str(),
408               Anonymous::Change(accountId).c_str());
409         return DBErr::E_OK;
410     }
411     sub.id = accountId;
412     OhCloudExtVector *keys = nullptr;
413     OhCloudExtVector *values = nullptr;
414     status = OhCloudExtHashMapIterGetKeyValuePair(relations.get(), &keys, &values);
415     if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
416         return DBErr::E_ERROR;
417     }
418     auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
419     auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
420     if (SaveRelation(pKeys, pValues, sub) != DBErr::E_OK) {
421         return DBErr::E_ERROR;
422     }
423     DBMetaMgr::GetInstance().SaveMeta(sub.GetKey(), sub, true);
424     return DBErr::E_OK;
425 }
426 
SaveRelation(std::shared_ptr<OhCloudExtVector> keys,std::shared_ptr<OhCloudExtVector> values,DBSub & sub)427 int32_t CloudServerImpl::SaveRelation(std::shared_ptr<OhCloudExtVector> keys,
428     std::shared_ptr<OhCloudExtVector> values, DBSub &sub)
429 {
430     size_t valuesLen = 0;
431     auto status = OhCloudExtVectorGetLength(values.get(), reinterpret_cast<unsigned int *>(&valuesLen));
432     if (status != ERRNO_SUCCESS || valuesLen == 0) {
433         return DBErr::E_ERROR;
434     }
435     for (size_t i = 0; i < valuesLen; i++) {
436         void *value = nullptr;
437         size_t valueLen = 0;
438         OhCloudExtVectorGet(values.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
439         if (value == nullptr) {
440             return DBErr::E_ERROR;
441         }
442         OhCloudExtRelationSet *relationSet = reinterpret_cast<OhCloudExtRelationSet *>(value);
443         auto pRelationSet = std::shared_ptr<OhCloudExtRelationSet>(relationSet, [](auto *relationSet) {
444             OhCloudExtRelationSetFree(relationSet);
445         });
446         unsigned char *bundle = nullptr;
447         size_t bundleLen = 0;
448         OhCloudExtRelationSetGetBundleName(pRelationSet.get(), &bundle, reinterpret_cast<unsigned int *>(&bundleLen));
449         if (bundle == nullptr) {
450             return DBErr::E_ERROR;
451         }
452         unsigned long long expire = 0;
453         status = OhCloudExtRelationSetGetExpireTime(pRelationSet.get(), &expire);
454         if (status != ERRNO_SUCCESS || expire == 0) {
455             return DBErr::E_ERROR;
456         }
457         std::string bundleName(reinterpret_cast<char *>(bundle), bundleLen);
458         sub.expiresTime[bundleName] = static_cast<uint64_t>(expire);
459         OhCloudExtHashMap *relations = nullptr;
460         status = OhCloudExtRelationSetGetRelations(pRelationSet.get(), &relations);
461         if (status != ERRNO_SUCCESS || relations == nullptr) {
462             return DBErr::E_ERROR;
463         }
464         auto pRelations = std::shared_ptr<OhCloudExtHashMap>(relations, [](auto *relations) {
465             OhCloudExtHashMapFree(relations);
466         });
467         DBRelation dbRelation;
468         dbRelation.id = sub.id;
469         dbRelation.bundleName = bundleName;
470         if (GetRelation(pRelations, dbRelation) != DBErr::E_OK) {
471             return DBErr::E_ERROR;
472         }
473         DBMetaMgr::GetInstance().SaveMeta(sub.GetRelationKey(bundleName), dbRelation, true);
474     }
475     return DBErr::E_OK;
476 }
477 
GetRelation(std::shared_ptr<OhCloudExtHashMap> relations,DBRelation & dbRelation)478 int32_t CloudServerImpl::GetRelation(std::shared_ptr<OhCloudExtHashMap> relations, DBRelation &dbRelation)
479 {
480     OhCloudExtVector *keys = nullptr;
481     OhCloudExtVector *values = nullptr;
482     auto status = OhCloudExtHashMapIterGetKeyValuePair(relations.get(), &keys, &values);
483     if (status != ERRNO_SUCCESS || keys == nullptr || values == nullptr) {
484         return DBErr::E_ERROR;
485     }
486     auto pKeys = std::shared_ptr<OhCloudExtVector>(keys, [](auto *keys) { OhCloudExtVectorFree(keys); });
487     auto pValues = std::shared_ptr<OhCloudExtVector>(values, [](auto *values) { OhCloudExtVectorFree(values); });
488     size_t keysLen = 0;
489     OhCloudExtVectorGetLength(pKeys.get(), reinterpret_cast<unsigned int *>(&keysLen));
490     size_t valuesLen = 0;
491     OhCloudExtVectorGetLength(pValues.get(), reinterpret_cast<unsigned int *>(&valuesLen));
492     if (keysLen == 0 || keysLen != valuesLen) {
493         return DBErr::E_ERROR;
494     }
495     for (size_t i = 0; i < keysLen; i++) {
496         void *dbName = nullptr;
497         size_t dbNameLen = 0;
498         status = OhCloudExtVectorGet(pKeys.get(), i, &dbName, reinterpret_cast<unsigned int *>(&dbNameLen));
499         if (status != ERRNO_SUCCESS || dbName == nullptr) {
500             return DBErr::E_ERROR;
501         }
502         std::string databaseName(reinterpret_cast<char *>(dbName), dbNameLen);
503         void *subId = nullptr;
504         size_t subIdLen = 0;
505         status = OhCloudExtVectorGet(pValues.get(), i, &subId, reinterpret_cast<unsigned int *>(&subIdLen));
506         if (status != ERRNO_SUCCESS || subId == nullptr) {
507             return DBErr::E_ERROR;
508         }
509         uint64_t subscribeId = *reinterpret_cast<uint64_t *>(subId);
510         dbRelation.relations[std::move(databaseName)] = std::to_string(subscribeId);
511     }
512     return DBErr::E_OK;
513 }
514 
Unsubscribe(int32_t userId,const std::map<std::string,std::vector<DBMeta>> & dbs)515 int32_t CloudServerImpl::Unsubscribe(int32_t userId, const std::map<std::string, std::vector<DBMeta>> &dbs)
516 {
517     DBSub sub;
518     sub.userId = userId;
519     DBMetaMgr::GetInstance().LoadMeta(sub.GetKey(), sub, true);
520     if (sub.id.empty()) {
521         return DBErr::E_OK;
522     }
523     OhCloudExtCloudSync *server = OhCloudExtCloudSyncNew(userId);
524     if (server == nullptr) {
525         return DBErr::E_ERROR;
526     }
527     auto pServer = std::shared_ptr<OhCloudExtCloudSync>(server, [](auto *server) { OhCloudExtCloudSyncFree(server); });
528     std::vector<std::string> bundles;
529     OhCloudExtHashMap *subs = OhCloudExtHashMapNew(OhCloudExtRustType::VALUETYPE_VEC_STRING);
530     if (subs == nullptr) {
531         return DBErr::E_ERROR;
532     }
533     auto pSubs = std::shared_ptr<OhCloudExtHashMap>(subs, [](auto *subs) { OhCloudExtHashMapFree(subs); });
534     for (auto &[bundle, databases] : dbs) {
535         DBRelation dbRelation;
536         DBMetaMgr::GetInstance().LoadMeta(DBSub::GetRelationKey(userId, bundle), dbRelation, true);
537         OhCloudExtVector *relation = OhCloudExtVectorNew(OhCloudExtRustType::VALUETYPE_U32);
538         if (relation == nullptr) {
539             return DBErr::E_ERROR;
540         }
541         size_t relationLen = 0;
542         for (auto &database : databases) {
543             auto it = dbRelation.relations.find(database.name);
544             if (it == dbRelation.relations.end()) {
545                 continue;
546             }
547             uint32_t subId = std::stoul(it->second);
548             if (OhCloudExtVectorPush(relation, &subId, sizeof(uint32_t)) != ERRNO_SUCCESS) {
549                 return DBErr::E_ERROR;
550             }
551             relationLen += 1;
552         }
553         auto status = OhCloudExtHashMapInsert(pSubs.get(),
554             const_cast<void *>(reinterpret_cast<const void *>(bundle.c_str())), bundle.size(), relation, relationLen);
555         if (status != ERRNO_SUCCESS) {
556             return DBErr::E_ERROR;
557         }
558         bundles.emplace_back(bundle);
559     }
560     if (DoUnsubscribe(pServer, pSubs, bundles, sub) != DBErr::E_OK) {
561         return DBErr::E_ERROR;
562     }
563     DBMetaMgr::GetInstance().SaveMeta(sub.GetKey(), sub, true);
564     return DBErr::E_OK;
565 }
566 
DoUnsubscribe(std::shared_ptr<OhCloudExtCloudSync> server,std::shared_ptr<OhCloudExtHashMap> relations,const std::vector<std::string> & bundles,DBSub & sub)567 int32_t CloudServerImpl::DoUnsubscribe(std::shared_ptr<OhCloudExtCloudSync> server,
568     std::shared_ptr<OhCloudExtHashMap> relations, const std::vector<std::string> &bundles, DBSub &sub)
569 {
570     OhCloudExtVector *errs = nullptr;
571     auto status =  OhCloudExtCloudSyncUnsubscribe(server.get(), relations.get(), &errs);
572     if (status != ERRNO_SUCCESS) {
573         return DBErr::E_ERROR;
574     }
575     if (errs != nullptr) {
576         auto pErrs = std::shared_ptr<OhCloudExtVector>(errs, [](auto *errs) { OhCloudExtVectorFree(errs); });
577         size_t errsLen = 0;
578         OhCloudExtVectorGetLength(pErrs.get(), reinterpret_cast<unsigned int *>(&errsLen));
579         if (errsLen != bundles.size()) {
580             return DBErr::E_ERROR;
581         }
582         for (size_t i = 0; i < errsLen; i++) {
583             void *value = nullptr;
584             size_t valueLen = 0;
585             status = OhCloudExtVectorGet(pErrs.get(), i, &value, reinterpret_cast<unsigned int *>(&valueLen));
586             if (status != ERRNO_SUCCESS || value == nullptr) {
587                 return DBErr::E_ERROR;
588             }
589             int err = *reinterpret_cast<int *>(value);
590             if (err != ERRNO_SUCCESS) {
591                 continue;
592             }
593             sub.expiresTime.erase(bundles[i]);
594             DBMetaMgr::GetInstance().DelMeta(sub.GetRelationKey(bundles[i]), true);
595         }
596     } else {
597         for (size_t i = 0; i < bundles.size(); i++) {
598             sub.expiresTime.erase(bundles[i]);
599             DBMetaMgr::GetInstance().DelMeta(sub.GetRelationKey(bundles[i]), true);
600         }
601     }
602     return DBErr::E_OK;
603 }
604 
ConnectAssetLoader(uint32_t tokenId,const DBMeta & dbMeta)605 std::shared_ptr<DBAssetLoader> CloudServerImpl::ConnectAssetLoader(uint32_t tokenId, const DBMeta &dbMeta)
606 {
607     if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
608         return nullptr;
609     }
610     HapTokenInfo hapInfo;
611     if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != RET_SUCCESS) {
612         return nullptr;
613     }
614     auto data = ExtensionUtil::Convert(dbMeta);
615     if (data.first == nullptr) {
616         return nullptr;
617     }
618     OhCloudExtCloudAssetLoader *loader = OhCloudExtCloudAssetLoaderNew(hapInfo.userID,
619         reinterpret_cast<const unsigned char *>(hapInfo.bundleName.c_str()),
620         hapInfo.bundleName.size(), data.first);
621     return loader != nullptr ? std::make_shared<AssetLoaderImpl>(loader) : nullptr;
622 }
623 
ConnectAssetLoader(const std::string & bundleName,int user,const DBMeta & dbMeta)624 std::shared_ptr<DBAssetLoader> CloudServerImpl::ConnectAssetLoader(
625     const std::string &bundleName, int user, const DBMeta &dbMeta)
626 {
627     auto data = ExtensionUtil::Convert(dbMeta);
628     if (data.first == nullptr) {
629         return nullptr;
630     }
631     OhCloudExtCloudAssetLoader *loader = OhCloudExtCloudAssetLoaderNew(
632         user, reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), data.first);
633     return loader != nullptr ? std::make_shared<AssetLoaderImpl>(loader) : nullptr;
634 }
635 
ConnectCloudDB(uint32_t tokenId,const DBMeta & dbMeta)636 std::shared_ptr<DBCloudDB> CloudServerImpl::ConnectCloudDB(uint32_t tokenId, const DBMeta &dbMeta)
637 {
638     if (AccessTokenKit::GetTokenTypeFlag(tokenId) != TOKEN_HAP) {
639         return nullptr;
640     }
641     HapTokenInfo hapInfo;
642     if (AccessTokenKit::GetHapTokenInfo(tokenId, hapInfo) != RET_SUCCESS) {
643         return nullptr;
644     }
645     auto data = ExtensionUtil::Convert(dbMeta);
646     if (data.first == nullptr) {
647         return nullptr;
648     }
649     OhCloudExtCloudDatabase *cloudDb = OhCloudExtCloudDbNew(hapInfo.userID,
650         reinterpret_cast<const unsigned char *>(hapInfo.bundleName.c_str()),
651         hapInfo.bundleName.size(), data.first);
652     return cloudDb != nullptr ? std::make_shared<CloudDbImpl>(cloudDb) : nullptr;
653 }
654 
ConnectCloudDB(const std::string & bundleName,int user,const DBMeta & dbMeta)655 std::shared_ptr<DBCloudDB> CloudServerImpl::ConnectCloudDB(
656     const std::string &bundleName, int user, const DBMeta &dbMeta)
657 {
658     auto data = ExtensionUtil::Convert(dbMeta);
659     if (data.first == nullptr) {
660         return nullptr;
661     }
662     OhCloudExtCloudDatabase *cloudDb = OhCloudExtCloudDbNew(
663         user, reinterpret_cast<const unsigned char *>(bundleName.c_str()), bundleName.size(), data.first);
664     return cloudDb != nullptr ? std::make_shared<CloudDbImpl>(cloudDb) : nullptr;
665 }
666 } // namespace OHOS::CloudData