• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2020 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 #include "want_utils.h"
17 #include "element_name_utils.h"
18 
19 #include <securec.h>
20 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
21 #include <string>
22 #include <liteipc_adapter.h>
23 #endif
24 
25 #include "log.h"
26 #include "utils.h"
27 
28 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
29 using UriKeyType = enum {
30     BEGIN,
31     DEVICE,
32     BUNDLE,
33     ABILITY,
34     END,
35 };
36 
37 using UriProperties = struct {
38     const char *key;    /* key of uri property */
39     uint8_t keyLen;     /* key length of uri property */
40     UriKeyType type;    /* key type of uri property */
41 };
42 
43 const static UriProperties URI_PROPERTIES[] = {
44     { "#Want",    5, BEGIN   },
45     { "device=",  7, DEVICE  },
46     { "bundle=",  7, BUNDLE  },
47     { "ability=", 8, ABILITY },
48     { "end",      3, END     },
49 };
50 
51 constexpr static char URI_SEPARATOR = ';';
52 constexpr static int VALUE_NULL = 0;
53 constexpr static int VALUE_OBJECT = 1;
54 constexpr static int DATA_LENGTH = 2048;
55 #endif
56 
57 constexpr uint8_t INT_VALUE_TYPE = 6;
58 constexpr uint8_t STRING_VALUE_TYPE = 13;
59 constexpr uint8_t KEY_VALUE_PAIR_TYPE = 97;
60 
ClearWant(Want * want)61 void ClearWant(Want *want)
62 {
63     if (want == nullptr) {
64         return;
65     }
66 
67     ClearElement(want->element);
68     AdapterFree(want->element);
69 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
70     AdapterFree(want->sid);
71 #endif
72     AdapterFree(want->data);
73 }
74 
SetWantElement(Want * want,ElementName element)75 bool SetWantElement(Want *want, ElementName element)
76 {
77     if (want == nullptr) {
78         return false;
79     }
80 
81     ClearElement(want->element);
82     AdapterFree(want->element);
83     want->element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
84     if (want->element == nullptr) {
85         return false;
86     }
87     want->element->deviceId = OHOS::Utils::Strdup(element.deviceId);
88     want->element->bundleName = OHOS::Utils::Strdup(element.bundleName);
89     want->element->abilityName = OHOS::Utils::Strdup(element.abilityName);
90     return true;
91 }
92 
EncapTlv(uint8_t type,uint8_t length,const void * value,uint8_t valueLen)93 Tlv *EncapTlv(uint8_t type, uint8_t length, const void *value, uint8_t valueLen)
94 {
95     void *entity = nullptr;
96 
97     // Tlv header can only has 2 bytes.
98     uint8_t totalLen = valueLen + 2;
99     entity = calloc(1, totalLen);
100     if (entity == nullptr) {
101         return nullptr;
102     }
103 
104     if (memcpy_s((unsigned char *)entity, 1, &type, 1) != 0 ||
105         memcpy_s((unsigned char *)entity + 1, 1, &length, 1) != 0 ||
106         memcpy_s((unsigned char *)entity + 2, valueLen, value, valueLen) != 0) {
107         AdapterFree(entity);
108         return nullptr;
109     }
110 
111     Tlv *newTlv = new Tlv();
112     newTlv->type = type;
113     newTlv->entity = entity;
114     newTlv->totalLen = totalLen;
115     return newTlv;
116 }
117 
FreeTlvStruct(Tlv * tlv)118 void FreeTlvStruct(Tlv *tlv)
119 {
120     AdapterFree(tlv->entity);
121     AdapterFree(tlv);
122 }
123 
CombineKeyValueTlv(Tlv * keyTlv,Tlv * valueTlv)124 Tlv *CombineKeyValueTlv(Tlv *keyTlv, Tlv *valueTlv)
125 {
126     uint8_t newTlvValueLen = keyTlv->totalLen + valueTlv->totalLen;
127     void *newTlvValue = calloc(1, newTlvValueLen);
128     if (newTlvValue == nullptr) {
129         return nullptr;
130     }
131     if (memcpy_s((unsigned char *)newTlvValue, keyTlv->totalLen, keyTlv->entity, keyTlv->totalLen) != 0 ||
132         memcpy_s((unsigned char *)newTlvValue + keyTlv->totalLen, valueTlv->totalLen,
133         valueTlv->entity, valueTlv->totalLen) != 0) {
134         AdapterFree(newTlvValue);
135         return nullptr;
136     }
137 
138     Tlv *newTlv = EncapTlv(KEY_VALUE_PAIR_TYPE, newTlvValueLen, newTlvValue, newTlvValueLen);
139     AdapterFree(newTlvValue);
140     return newTlv;
141 }
142 
UpdateWantData(Want * want,Tlv * tlv)143 bool UpdateWantData(Want *want, Tlv *tlv)
144 {
145     bool result = false;
146     if (want->data != nullptr) {
147         void *newWantData = calloc(1, tlv->totalLen + want->dataLength);
148         if (newWantData == nullptr) {
149             return result;
150         }
151         if (memcpy_s(newWantData, want->dataLength, want->data, want->dataLength) != 0 ||
152             memcpy_s((unsigned char*)newWantData + want->dataLength, tlv->totalLen, tlv->entity, tlv->totalLen) != 0) {
153             AdapterFree(newWantData);
154             return result;
155         }
156         SetWantData(want, newWantData, tlv->totalLen + want->dataLength);
157         AdapterFree(newWantData);
158         result = true;
159     } else {
160         SetWantData(want, tlv->entity, tlv->totalLen);
161         result = true;
162     }
163     return result;
164 }
165 
SetIntParam(Want * want,const char * key,uint8_t keyLen,int32_t value)166 bool SetIntParam(Want *want, const char *key, uint8_t keyLen, int32_t value)
167 {
168     bool result = false;
169     if (keyLen <= 0) {
170         return result;
171     }
172 
173     Tlv *keyTlv = EncapTlv(STRING_VALUE_TYPE, keyLen, (void *)key, keyLen);
174     if (keyTlv == nullptr) {
175         return result;
176     }
177     if (value < 0) {
178         HILOG_ERROR(HILOG_MODULE_APP, "SetIntParam value should be positive");
179         FreeTlvStruct(keyTlv);
180         return result;
181     }
182     int intBufferbNumber = 4;
183     unsigned char intBuffer[4] = {0};
184     for (int i = 0; i < intBufferbNumber; i++) {
185         intBuffer[i] = value >> (8 * (3- i));
186     }
187     Tlv *valueTlv = EncapTlv(INT_VALUE_TYPE, sizeof(int), (void *)intBuffer, sizeof(int));
188     if (valueTlv == nullptr) {
189         FreeTlvStruct(keyTlv);
190         return result;
191     }
192     Tlv *newTlv = CombineKeyValueTlv(keyTlv, valueTlv);
193     FreeTlvStruct(keyTlv);
194     FreeTlvStruct(valueTlv);
195     if (newTlv == nullptr) {
196         return result;
197     }
198     if (UpdateWantData(want, newTlv)) {
199         AdapterFree(newTlv);
200         result = true;
201     }
202     AdapterFree(newTlv);
203     return result;
204 }
205 
SetStrParam(Want * want,const char * key,uint8_t keyLen,const char * value,uint8_t valueLen)206 bool SetStrParam(Want *want, const char *key, uint8_t keyLen, const char *value, uint8_t valueLen)
207 {
208     bool result = false;
209     if (keyLen <= 0 || valueLen <= 0) {
210         return result;
211     }
212 
213     Tlv *keyTlv = EncapTlv(STRING_VALUE_TYPE, keyLen, (void *)key, keyLen);
214     if (keyTlv == nullptr) {
215         return result;
216     }
217 
218     Tlv *valueTlv = EncapTlv(STRING_VALUE_TYPE, valueLen, (void *)value, valueLen);
219     if (valueTlv == nullptr) {
220         FreeTlvStruct(keyTlv);
221         return result;
222     }
223     Tlv *newTlv = CombineKeyValueTlv(keyTlv, valueTlv);
224     FreeTlvStruct(keyTlv);
225     FreeTlvStruct(valueTlv);
226     if (newTlv == nullptr) {
227         return result;
228     }
229     if (UpdateWantData(want, newTlv)) {
230         AdapterFree(newTlv);
231         result = true;
232     }
233     AdapterFree(newTlv);
234     return result;
235 }
236 
237 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
SetWantSvcIdentity(Want * want,SvcIdentity sid)238 bool SetWantSvcIdentity(Want *want, SvcIdentity sid)
239 {
240     if (want == nullptr) {
241         return false;
242     }
243 
244     AdapterFree(want->sid);
245     want->sid = reinterpret_cast<SvcIdentity *>(AdapterMalloc(sizeof(SvcIdentity)));
246     if (want->sid == nullptr) {
247         return false;
248     }
249     if (memcpy_s(want->sid, sizeof(SvcIdentity), &sid, sizeof(SvcIdentity)) != EOK) {
250         AdapterFree(want->sid);
251         return false;
252     }
253 
254     return true;
255 }
256 #endif
257 
SetWantData(Want * want,const void * data,uint16_t dataLength)258 bool SetWantData(Want *want, const void *data, uint16_t dataLength)
259 {
260     if (want == nullptr) {
261         return false;
262     }
263 
264     AdapterFree(want->data);
265     want->data = OHOS::Utils::Memdup(data, dataLength);
266     if (want->data == nullptr) {
267         want->dataLength = 0;
268         return false;
269     }
270 
271     want->dataLength = dataLength;
272     return true;
273 }
274 
275 #ifdef OHOS_APPEXECFWK_BMS_BUNDLEMANAGER
SerializeWant(IpcIo * io,const Want * want)276 bool SerializeWant(IpcIo *io, const Want *want)
277 {
278     if ((io == nullptr) || (want == nullptr) || (want->dataLength > DATA_LENGTH)) {
279         return false;
280     }
281 
282     if (want->element == nullptr) {
283         IpcIoPushInt32(io, VALUE_NULL);
284     } else {
285         IpcIoPushInt32(io, VALUE_OBJECT);
286         if (!SerializeElement(io, want->element)) {
287             return false;
288         }
289     }
290     IpcIoPushInt32(io, want->dataLength);
291     if (want->dataLength > 0) {
292 #ifdef __LINUX__
293         IpcIoPushFlatObj(io, want->data, want->dataLength);
294 #else
295         const BuffPtr buff = {
296             want->dataLength,
297             want->data,
298         };
299         IpcIoPushDataBuff(io, &buff);
300 #endif
301     }
302     if (want->sid == nullptr) {
303         IpcIoPushInt32(io, VALUE_NULL);
304     } else {
305         IpcIoPushInt32(io, VALUE_OBJECT);
306         IpcIoPushSvc(io, want->sid);
307     }
308 
309     return true;
310 }
311 
DeserializeWant(Want * want,IpcIo * io)312 bool DeserializeWant(Want *want, IpcIo *io)
313 {
314     if ((want == nullptr) || (io == nullptr)) {
315         return false;
316     }
317 
318     if (IpcIoPopInt32(io) == VALUE_OBJECT) {
319         want->element = reinterpret_cast<ElementName *>(AdapterMalloc(sizeof(ElementName)));
320         if (want->element == nullptr ||
321             memset_s(want->element, sizeof(ElementName), 0, sizeof(ElementName)) != EOK ||
322             !DeserializeElement(want->element, io)) {
323             AdapterFree(want->element);
324             return false;
325         }
326     }
327     if (IpcIoPopInt32(io) > 0) {
328 #ifdef __LINUX__
329         uint32_t size = 0;
330         void *data = IpcIoPopFlatObj(io, &size);
331         if (!SetWantData(want, data, size)) {
332             ClearWant(want);
333             return false;
334         }
335 #else
336         BuffPtr *buff = IpcIoPopDataBuff(io);
337         if (buff == nullptr) {
338             ClearWant(want);
339             return false;
340         }
341         if (!SetWantData(want, buff->buff, buff->buffSz)) {
342             FreeBuffer(nullptr, buff->buff);
343             ClearWant(want);
344             return false;
345         }
346         FreeBuffer(nullptr, buff->buff);
347 #endif
348     }
349     if (IpcIoPopInt32(io) == VALUE_OBJECT) {
350         auto sid = IpcIoPopSvc(io);
351         if ((sid == nullptr) || !SetWantSvcIdentity(want, *sid)) {
352 #ifdef __LINUX__
353             AdapterFree(sid);
354             sid = nullptr;
355 #endif
356             ClearWant(want);
357             return false;
358         }
359 #ifdef __LINUX__
360         AdapterFree(sid);
361         sid = nullptr;
362 #endif
363     }
364 
365     return true;
366 }
367 
WantParseUri(const char * uri)368 Want *WantParseUri(const char *uri)
369 {
370     if (uri == nullptr) {
371         return nullptr;
372     }
373     char *parseUri = OHOS::Utils::Strdup(uri);
374     if (parseUri == nullptr) {
375         return nullptr;
376     }
377     ElementName element = { nullptr, nullptr, nullptr };
378     char *beginIndex = parseUri;
379     for (auto property : URI_PROPERTIES) {
380         if (strstr(beginIndex, property.key) != beginIndex) {
381             AdapterFree(parseUri);
382             return nullptr;
383         }
384         if (property.type == END) {
385             break;
386         }
387         char *endIndex = strchr(beginIndex, URI_SEPARATOR);
388         if ((endIndex == nullptr) || (endIndex <= beginIndex)) {
389             AdapterFree(parseUri);
390             return nullptr;
391         }
392         *endIndex = '\0';
393         beginIndex += property.keyLen;
394         switch (property.type) {
395             case DEVICE: {
396                 SetElementDeviceID(&element, beginIndex);
397                 break;
398             }
399             case BUNDLE: {
400                 SetElementBundleName(&element, beginIndex);
401                 break;
402             }
403             case ABILITY: {
404                 SetElementAbilityName(&element, beginIndex);
405                 break;
406             }
407             default: {
408                 break;
409             }
410         }
411         beginIndex = endIndex + 1;
412     }
413     AdapterFree(parseUri);
414     Want *want = new Want();
415     if ((memset_s(want, sizeof(Want), 0, sizeof(Want)) != EOK) || !SetWantElement(want, element)) {
416         ClearElement(&element);
417         delete want;
418         return nullptr;
419     }
420     ClearElement(&element);
421     return want;
422 }
423 
WantToUri(Want want)424 const char *WantToUri(Want want)
425 {
426     std::string uriString;
427 
428     for (auto property : URI_PROPERTIES) {
429         uriString += property.key;
430         switch (property.type) {
431             case BEGIN: {
432                 uriString += URI_SEPARATOR;
433                 break;
434             }
435             case DEVICE: {
436                 if ((want.element != nullptr) && (want.element->deviceId != nullptr)) {
437                     uriString += want.element->deviceId;
438                 }
439                 uriString += URI_SEPARATOR;
440                 break;
441             }
442             case BUNDLE: {
443                 if ((want.element != nullptr) && (want.element->bundleName != nullptr)) {
444                     uriString += want.element->bundleName;
445                 }
446                 uriString += URI_SEPARATOR;
447                 break;
448             }
449             case ABILITY: {
450                 if ((want.element != nullptr) && (want.element->abilityName != nullptr)) {
451                     uriString += want.element->abilityName;
452                 }
453                 uriString += URI_SEPARATOR;
454                 break;
455             }
456             default: {
457                 break;
458             }
459         }
460     }
461 
462     uint16_t len = uriString.size();
463     char *uri = reinterpret_cast<char *>(AdapterMalloc(len + 1));
464     if (uri == nullptr) {
465         return nullptr;
466     }
467     if (strncpy_s(uri, len + 1, uriString.c_str(), len) < 0) {
468         AdapterFree(uri);
469         return nullptr;
470     }
471 
472     return uri;
473 }
474 #endif
475