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