1 /*
2  * Copyright (C) 2021 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 #include "sms_wap_push_content_type.h"
16 
17 #include "telephony_log_wrapper.h"
18 #include "sms_wap_push_buffer.h"
19 
20 namespace OHOS {
21 namespace Telephony {
22 /**
23  * @brief Construct a new Sms Wap Push Content Type:: Sms Wap Push Content Type
24  * wap-230-wsp-20010705-a
25  * Table 42. Character Set Assignment Examples
26  */
SmsWapPushContentType()27 SmsWapPushContentType::SmsWapPushContentType()
28 {
29     mapCharSet_.emplace("US-ASCII", 0x03);
30     mapCharSet_.emplace("UTF-16", 0x03F7);
31     mapCharSet_.emplace("CSUNICODE", 0x03E8);
32     mapCharSet_.emplace("UTF-8", 0x6A);
33     mapCharSet_.emplace("ISO-2022-KR", 0x25);
34     mapCharSet_.emplace("KS_C_5601-1987", 0x24);
35     mapCharSet_.emplace("EUC-KR", 0x26);
36     mapCharSet_.emplace("ISO-2022-JP", 0x27);
37     mapCharSet_.emplace("ISO-2022-JP-2", 0x28);
38     mapCharSet_.emplace("ISO_8859-1", 0x04);
39     mapCharSet_.emplace("ISO_8859-2", 0x05);
40     mapCharSet_.emplace("ISO-8859-3", 0x06);
41     mapCharSet_.emplace("ISO-8859-4", 0x07);
42     mapCharSet_.emplace("ISO-8859-5", 0x08);
43     mapCharSet_.emplace("ISO-8859-6", 0x09);
44     mapCharSet_.emplace("ISO-8859-7", 0x0A);
45     mapCharSet_.emplace("ISO-8859-8", 0x0B);
46     mapCharSet_.emplace("ISO-8859-9", 0x0C);
47     mapCharSet_.emplace("ISO-8859-10", 0x0D);
48     mapCharSet_.emplace("ISO-8859-15", 0x6F);
49     mapCharSet_.emplace("SHIFT_JIS", 0x11);
50     mapCharSet_.emplace("EUC-JP", 0x13);
51     mapCharSet_.emplace("GB2312", 0x07E9);
52     mapCharSet_.emplace("BIG5", 0x0d);
53     mapCharSet_.emplace("WINDOWS-1251", 0x08CB);
54     mapCharSet_.emplace("KOI8-R", 0x0824);
55     mapCharSet_.emplace("KOI8-U", 0x0828);
56 }
57 
58 /**
59  * @brief DecodeContentType
60  * wap-230-wsp-20010705-a   section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
61  * Content-type-value = Constrained-media | Content-general-form
62  * Constrained-media = Constrained-encoding
63  * Constrained-encoding = Extension-Media | Short-integer
64  * Extension-media = *TEXT End-of-string
65  * Content-general-form = Value-length Media-type
66  * Media-type = (Well-known-media | Extension-Media) *(Parameter)
67  * Well-known-media = Integer-value
68  * Parameter = Typed-parameter | Untyped-parameter
69  * @param decodeBuffer
70  * @param contentLength
71  * @return true
72  * @return false
73  */
DecodeContentType(SmsWapPushBuffer & decodeBuffer,int32_t & contentLength)74 bool SmsWapPushContentType::DecodeContentType(SmsWapPushBuffer &decodeBuffer, int32_t &contentLength)
75 {
76     const uint8_t setHighestBitZero = 0x7f;
77 
78     if (decodeBuffer.DecodeIsShortInt()) {
79         uint8_t oneByte = 0;
80         if (!decodeBuffer.GetOneByte(oneByte)) {
81             TELEPHONY_LOGE("Wap push decode contentType GetOneByte fail.");
82             return false;
83         }
84         contentType_ = GetContentTypeFromInt(oneByte & setHighestBitZero);
85         contentLength = 1;
86         return true;
87     }
88 
89     if (decodeBuffer.DecodeIsString()) {
90         std::string sType = "";
91         uint32_t len = 0;
92         decodeBuffer.DecodeText(sType, len);
93         contentLength = static_cast<int32_t>(len + 1);
94         contentType_ = sType;
95         return true; // 2
96     }
97 
98     if (!DecodeCTGeneralForm(decodeBuffer, contentLength)) {
99         TELEPHONY_LOGE("Decode contentType DecodeMmsCTGeneralForm fail.");
100         return false;
101     }
102     return true;
103 }
104 
105 /**
106  * @brief DecodeCTGeneralForm
107  * wap-230-wsp-20010705-a   section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
108  * Content-type-value = Constrained-media | Content-general-form
109  * Constrained-media = Constrained-encoding
110  * Constrained-encoding = Extension-Media | Short-integer
111  * Extension-media = *TEXT End-of-string
112  * Content-general-form = Value-length Media-type
113  * Media-type = (Well-known-media | Extension-Media) *(Parameter)
114  * Well-known-media = Integer-value
115  * Parameter = Typed-parameter | Untyped-parameter
116  * @param decodeBuffer
117  * @param contentLength
118  * @return true
119  * @return false
120  */
DecodeCTGeneralForm(SmsWapPushBuffer & decodeBuffer,int32_t & contentLength)121 bool SmsWapPushContentType::DecodeCTGeneralForm(SmsWapPushBuffer &decodeBuffer, int32_t &contentLength)
122 {
123     const uint8_t setHighestBitZero = 0x7f;
124 
125     /** false indicated no more data */
126     if (!decodeBuffer.DecodeIsValueLength()) {
127         TELEPHONY_LOGE("Wap push decode contentType DecodeIsValueLength fail.");
128         return false;
129     }
130 
131     uint32_t valueLength = 0;
132     uint32_t returnLength = 0;
133     if (!decodeBuffer.DecodeValueLengthReturnLen(valueLength, returnLength)) {
134         TELEPHONY_LOGE("Wap push decode contentType DecodeValueLengthReturnLen fail.");
135         return false;
136     }
137     contentLength = static_cast<int32_t>(valueLength + returnLength);
138 
139     uint8_t oneByte = 0;
140     if (!decodeBuffer.PeekOneByte(oneByte)) {
141         TELEPHONY_LOGE("Wap push decode contentType PeekOneByte fail.");
142         return false;
143     }
144     if (decodeBuffer.DecodeIsShortInt()) {
145         contentType_ = GetContentTypeFromInt(oneByte & setHighestBitZero);
146         if (!decodeBuffer.IncreasePointer(1)) {
147             TELEPHONY_LOGE("Wap push decode contentType IncreasePointer fail.");
148             return false;
149         }
150         if (valueLength == 0) {
151             TELEPHONY_LOGI("Wap push decode contentType empty.");
152             return false;
153         }
154         valueLength--;
155     } else if (decodeBuffer.DecodeIsString()) {
156         std::string sType = "";
157         uint32_t len = 0;
158         decodeBuffer.DecodeText(sType, len);
159         valueLength -= len + 1;
160         contentType_ = sType;
161     } else {
162         TELEPHONY_LOGI("Wap push decode contentType empty.");
163         return false;
164     }
165 
166     if (!DecodeParameter(decodeBuffer, valueLength)) {
167         TELEPHONY_LOGE("Wap push decode contentType DecodeParameter fail.");
168         return false;
169     }
170     return true;
171 }
172 
173 /**
174  * @brief DecodeParameter
175  * wap-230-wsp-20010705-a   section:8.4.2.4 Parameter
176  * Parameter = Typed-parameter | Untyped-parameter
177  * Typed-parameter = Well-known-parameter-token Typed-value
178  * Well-known-parameter-token = Integer-value
179  * Typed-value = Compact-value | Text-value
180  * Compact-value = Integer-value |
181  *                 Date-value | Delta-seconds-value | Q-value | Version-value |
182  *                 Uri-value
183  * Untyped-parameter = Token-text Untyped-value
184  * Untyped-value = Integer-value | Text-value
185  * Delta-seconds-value = Long-integer
186  * Q-value = 1*2 OCTET
187  * @param decodeBuffer
188  * @param valueLength
189  * @return true
190  * @return false
191  */
DecodeParameter(SmsWapPushBuffer & decodeBuffer,int32_t valueLength)192 bool SmsWapPushContentType::DecodeParameter(SmsWapPushBuffer &decodeBuffer, int32_t valueLength)
193 {
194     while (valueLength > 0) {
195         uint8_t oneByte = 0;
196         if (!decodeBuffer.GetOneByte(oneByte)) {
197             TELEPHONY_LOGE("Wap push DecodeParameter GetOneByte fail.");
198             return false;
199         }
200         uint8_t paramCode = oneByte;
201         valueLength--;
202         switch (static_cast<WapContentParam>(paramCode)) {
203             case WapContentParam::CT_P_CHARSET: {
204                 if (!DecodeCharsetField(decodeBuffer, valueLength)) {
205                     TELEPHONY_LOGE("Wap push DecodeParameter DecodeCharsetField fail.");
206                     return false;
207                 }
208                 break;
209             }
210             case WapContentParam::CT_P_FILENAME:
211             case WapContentParam::CT_P_FILENAME_VALUE:
212             case WapContentParam::CT_P_START_VALUE:
213             case WapContentParam::CT_P_START:
214             case WapContentParam::CT_P_NAME:
215             case WapContentParam::CT_P_NAME_VALUE:
216             case WapContentParam::CT_P_START_INFO:
217             case WapContentParam::CT_P_START_INFO_VALUE: {
218                 if (!DecodeTextField(decodeBuffer, paramCode, valueLength)) {
219                     TELEPHONY_LOGE("Wap push DecodeParameter DecodeTextField fail.");
220                     return false;
221                 }
222                 break;
223             }
224             case WapContentParam::CT_P_TYPE:
225             case WapContentParam::CT_P_TYPE_STRING: {
226                 if (!DecodeTypeField(decodeBuffer, valueLength)) {
227                     TELEPHONY_LOGE("Wap push DecodeParameter DecodeTypeField fail.");
228                     return false;
229                 }
230                 break;
231             }
232             default: {
233                 if (!decodeBuffer.IncreasePointer(valueLength)) {
234                     TELEPHONY_LOGE("Wap push DecodeParameter IncreasePointer fail.");
235                     return false;
236                 }
237                 valueLength = 0;
238             }
239         }
240     }
241     return true;
242 }
243 
GetContentType()244 std::string SmsWapPushContentType::GetContentType()
245 {
246     return contentType_;
247 }
248 
SetContentType(std::string str)249 bool SmsWapPushContentType::SetContentType(std::string str)
250 {
251     contentType_ = str;
252     return true;
253 }
254 
255 /**
256  * @brief DecodeTextField
257  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
258  * Text-string = [Quote] *TEXT End-of-string
259  * Quote = <Octet 127>
260  * End-of-string = <Octet 0>
261  * @param decodeBuffer
262  * @param field
263  * @param valueLength
264  * @return true
265  * @return false
266  */
DecodeTextField(SmsWapPushBuffer & decodeBuffer,uint8_t field,int32_t & valueLength)267 bool SmsWapPushContentType::DecodeTextField(SmsWapPushBuffer &decodeBuffer, uint8_t field, int32_t &valueLength)
268 {
269     std::string str = "";
270     uint32_t len = 0;
271     if (!decodeBuffer.DecodeText(str, len)) {
272         TELEPHONY_LOGE("Wap push DecodeTextField DecodeText fail.");
273         return false;
274     }
275     textParameterMap_.insert(std::make_pair(field, str));
276     valueLength -= static_cast<int32_t>(len);
277     valueLength -= 1;
278     return true;
279 }
280 
281 /**
282  * @brief DecodeCharsetField
283  * wap-230-wsp-20010705-a   section:8.4.2.8 Accept charset field
284  * Well-known-charset = Any-charset | Integer-value
285  * Any-charset = <Octet 128>
286  * @param decodeBuffer
287  * @param valueLength
288  * @return true
289  * @return false
290  */
DecodeCharsetField(SmsWapPushBuffer & decodeBuffer,int32_t & valueLength)291 bool SmsWapPushContentType::DecodeCharsetField(SmsWapPushBuffer &decodeBuffer, int32_t &valueLength)
292 {
293     const uint8_t TEXT_MAX = 0x7F;
294     const uint8_t TEXT_MIN = 0x20;
295     int32_t charset = 0;
296     uint8_t oneByte = 0;
297     if (decodeBuffer.PeekOneByte(oneByte) == false) {
298         TELEPHONY_LOGE("Wap push DecodeCharsetField PeekOneByte fail.");
299         return false;
300     }
301     if (((oneByte > TEXT_MIN) && (oneByte < TEXT_MAX)) || (oneByte == 0)) {
302         std::string sCharset = "";
303         uint32_t len = 0;
304 
305         if (!decodeBuffer.DecodeText(sCharset, len)) {
306             TELEPHONY_LOGE("Wap push DecodeCharsetField DecodeText fail.");
307             return false;
308         }
309         valueLength -= static_cast<int32_t>(len + 1);
310         uint32_t tmpCharSet = 0;
311         if (!GetCharSetIntFromString(tmpCharSet, sCharset)) {
312             TELEPHONY_LOGE("Wap push DecodeCharsetField GetCharSetIntFromString fail.");
313             return false;
314         }
315         charset = static_cast<int32_t>(tmpCharSet);
316     } else {
317         uint32_t startPosition = decodeBuffer.GetCurPosition();
318         uint64_t temp = 0;
319         if (!decodeBuffer.DecodeInteger(temp)) {
320             TELEPHONY_LOGE("Wap push DecodeCharsetField DecodeInteger fail.");
321             return false;
322         }
323         charset = static_cast<int32_t>(temp);
324         uint32_t endPosition = decodeBuffer.GetCurPosition();
325         if (endPosition >= startPosition) {
326             valueLength -= static_cast<int32_t>(endPosition - startPosition);
327         }
328     }
329     charset_ = static_cast<uint32_t>(charset);
330     return true;
331 }
332 
333 /**
334  * @brief DecodeTypeField
335  * wap-230-wsp-20010705-a   section:8.4.2.1 Basic rules
336  * Constrained-encoding = Extension-Media | Short-integer
337  * Extension-media = *TEXT End-of-string
338  * @param decodeBuffer
339  * @param valueLength
340  * @return true
341  * @return false
342  */
DecodeTypeField(SmsWapPushBuffer & decodeBuffer,int32_t & valueLength)343 bool SmsWapPushContentType::DecodeTypeField(SmsWapPushBuffer &decodeBuffer, int32_t &valueLength)
344 {
345     const uint8_t TEXT_MAX = 0x7F;
346     uint8_t oneByte = 0;
347     if (decodeBuffer.GetOneByte(oneByte) == false) {
348         TELEPHONY_LOGE("Wap push DecodeTypeField GetOneByte fail.");
349         return false;
350     }
351 
352     if (oneByte > TEXT_MAX) {
353         type_ = GetContentTypeFromInt(oneByte & TEXT_MAX);
354         valueLength -= 1;
355     } else {
356         if (!decodeBuffer.DecreasePointer(1)) {
357             TELEPHONY_LOGE("Wap push DecodeTypeField DecreasePointer fail.");
358             return false;
359         }
360         std::string sType = "";
361         uint32_t len = 0;
362         if (!decodeBuffer.DecodeText(sType, len)) {
363             TELEPHONY_LOGE("Wap push DecodeTypeField DecodeText fail.");
364             return false;
365         }
366         valueLength -= static_cast<int32_t>(len);
367         valueLength -= 1;
368         type_ = sType;
369     }
370     return true;
371 }
372 
GetCharSetIntFromString(uint32_t & charSet,const std::string & strCharSet)373 bool SmsWapPushContentType::GetCharSetIntFromString(uint32_t &charSet, const std::string &strCharSet)
374 {
375     auto iterMap = mapCharSet_.find(strCharSet);
376     if (iterMap != mapCharSet_.end()) {
377         charSet = iterMap->second;
378         return true;
379     }
380     return false;
381 }
382 
GetContentTypeFromInt(uint8_t type)383 std::string SmsWapPushContentType::GetContentTypeFromInt(uint8_t type)
384 {
385     for (unsigned int i = 0; i < sizeof(wapContentNames) / sizeof(wapContentNames[0]); i++) {
386         if (type == static_cast<uint8_t>(wapContentNames[i].key)) {
387             return wapContentNames[i].value;
388         }
389     }
390     return "*/*";
391 }
392 } // namespace Telephony
393 } // namespace OHOS
394