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 uint8_t oneByte = 0;
195 uint8_t paramCode = 0;
196 while (valueLength > 0) {
197 if (!decodeBuffer.GetOneByte(oneByte)) {
198 TELEPHONY_LOGE("Wap push DecodeParameter GetOneByte fail.");
199 return false;
200 }
201 paramCode = oneByte;
202 valueLength--;
203 switch (static_cast<WapContentParam>(paramCode)) {
204 case WapContentParam::CT_P_CHARSET: {
205 if (!DecodeCharsetField(decodeBuffer, valueLength)) {
206 TELEPHONY_LOGE("Wap push DecodeParameter DecodeCharsetField fail.");
207 return false;
208 }
209 break;
210 }
211 case WapContentParam::CT_P_FILENAME:
212 case WapContentParam::CT_P_FILENAME_VALUE:
213 case WapContentParam::CT_P_START_VALUE:
214 case WapContentParam::CT_P_START:
215 case WapContentParam::CT_P_NAME:
216 case WapContentParam::CT_P_NAME_VALUE:
217 case WapContentParam::CT_P_START_INFO:
218 case WapContentParam::CT_P_START_INFO_VALUE: {
219 if (!DecodeTextField(decodeBuffer, paramCode, valueLength)) {
220 TELEPHONY_LOGE("Wap push DecodeParameter DecodeTextField fail.");
221 return false;
222 }
223 break;
224 }
225 case WapContentParam::CT_P_TYPE:
226 case WapContentParam::CT_P_TYPE_STRING: {
227 if (!DecodeTypeField(decodeBuffer, valueLength)) {
228 TELEPHONY_LOGE("Wap push DecodeParameter DecodeTypeField fail.");
229 return false;
230 }
231 break;
232 }
233 default: {
234 if (!decodeBuffer.IncreasePointer(valueLength)) {
235 TELEPHONY_LOGE("Wap push DecodeParameter IncreasePointer fail.");
236 return false;
237 }
238 valueLength = 0;
239 }
240 }
241 }
242 return true;
243 }
244
GetContentType()245 std::string SmsWapPushContentType::GetContentType()
246 {
247 return contentType_;
248 }
249
SetContentType(std::string str)250 bool SmsWapPushContentType::SetContentType(std::string str)
251 {
252 contentType_ = str;
253 return true;
254 }
255
256 /**
257 * @brief DecodeTextField
258 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
259 * Text-string = [Quote] *TEXT End-of-string
260 * Quote = <Octet 127>
261 * End-of-string = <Octet 0>
262 * @param decodeBuffer
263 * @param field
264 * @param valueLength
265 * @return true
266 * @return false
267 */
DecodeTextField(SmsWapPushBuffer & decodeBuffer,uint8_t field,int32_t & valueLength)268 bool SmsWapPushContentType::DecodeTextField(SmsWapPushBuffer &decodeBuffer, uint8_t field, int32_t &valueLength)
269 {
270 std::string str = "";
271 uint32_t len = 0;
272 if (!decodeBuffer.DecodeText(str, len)) {
273 TELEPHONY_LOGE("Wap push DecodeTextField DecodeText fail.");
274 return false;
275 }
276 textParameterMap_.insert(std::make_pair(field, str));
277 valueLength -= static_cast<int32_t>(len);
278 valueLength -= 1;
279 return true;
280 }
281
282 /**
283 * @brief DecodeCharsetField
284 * wap-230-wsp-20010705-a section:8.4.2.8 Accept charset field
285 * Well-known-charset = Any-charset | Integer-value
286 * Any-charset = <Octet 128>
287 * @param decodeBuffer
288 * @param valueLength
289 * @return true
290 * @return false
291 */
DecodeCharsetField(SmsWapPushBuffer & decodeBuffer,int32_t & valueLength)292 bool SmsWapPushContentType::DecodeCharsetField(SmsWapPushBuffer &decodeBuffer, int32_t &valueLength)
293 {
294 const uint8_t TEXT_MAX = 0x7F;
295 const uint8_t TEXT_MIN = 0x20;
296 int32_t charset = 0;
297 uint8_t oneByte = 0;
298 if (decodeBuffer.PeekOneByte(oneByte) == false) {
299 TELEPHONY_LOGE("Wap push DecodeCharsetField PeekOneByte fail.");
300 return false;
301 }
302 if (((oneByte > TEXT_MIN) && (oneByte < TEXT_MAX)) || (oneByte == 0)) {
303 std::string sCharset = "";
304 uint32_t len = 0;
305
306 if (!decodeBuffer.DecodeText(sCharset, len)) {
307 TELEPHONY_LOGE("Wap push DecodeCharsetField DecodeText fail.");
308 return false;
309 }
310 valueLength -= static_cast<int32_t>(len + 1);
311 uint32_t tmpCharSet = 0;
312 if (!GetCharSetIntFromString(tmpCharSet, sCharset)) {
313 TELEPHONY_LOGE("Wap push DecodeCharsetField GetCharSetIntFromString fail.");
314 return false;
315 }
316 charset = static_cast<int32_t>(tmpCharSet);
317 } else {
318 uint32_t startPosition = decodeBuffer.GetCurPosition();
319 uint64_t temp = 0;
320 if (!decodeBuffer.DecodeInteger(temp)) {
321 TELEPHONY_LOGE("Wap push DecodeCharsetField DecodeInteger fail.");
322 return false;
323 }
324 charset = static_cast<int32_t>(temp);
325 uint32_t endPosition = decodeBuffer.GetCurPosition();
326 valueLength -= static_cast<int32_t>(endPosition - startPosition);
327 }
328 charset_ = static_cast<uint32_t>(charset);
329 return true;
330 }
331
332 /**
333 * @brief DecodeTypeField
334 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
335 * Constrained-encoding = Extension-Media | Short-integer
336 * Extension-media = *TEXT End-of-string
337 * @param decodeBuffer
338 * @param valueLength
339 * @return true
340 * @return false
341 */
DecodeTypeField(SmsWapPushBuffer & decodeBuffer,int32_t & valueLength)342 bool SmsWapPushContentType::DecodeTypeField(SmsWapPushBuffer &decodeBuffer, int32_t &valueLength)
343 {
344 const uint8_t TEXT_MAX = 0x7F;
345 uint8_t oneByte = 0;
346 if (decodeBuffer.GetOneByte(oneByte) == false) {
347 TELEPHONY_LOGE("Wap push DecodeTypeField GetOneByte fail.");
348 return false;
349 }
350
351 if (oneByte > TEXT_MAX) {
352 type_ = GetContentTypeFromInt(oneByte & TEXT_MAX);
353 valueLength -= 1;
354 } else {
355 if (!decodeBuffer.DecreasePointer(1)) {
356 TELEPHONY_LOGE("Wap push DecodeTypeField DecreasePointer fail.");
357 return false;
358 }
359 std::string sType = "";
360 uint32_t len = 0;
361 if (!decodeBuffer.DecodeText(sType, len)) {
362 TELEPHONY_LOGE("Wap push DecodeTypeField DecodeText fail.");
363 return false;
364 }
365 valueLength -= static_cast<int32_t>(len);
366 valueLength -= 1;
367 type_ = sType;
368 }
369 return true;
370 }
371
GetCharSetIntFromString(uint32_t & charSet,const std::string & strCharSet)372 bool SmsWapPushContentType::GetCharSetIntFromString(uint32_t &charSet, const std::string &strCharSet)
373 {
374 auto iterMap = mapCharSet_.find(strCharSet);
375 if (iterMap != mapCharSet_.end()) {
376 charSet = iterMap->second;
377 return true;
378 }
379 return false;
380 }
381
GetContentTypeFromInt(uint8_t type)382 std::string SmsWapPushContentType::GetContentTypeFromInt(uint8_t type)
383 {
384 for (unsigned int i = 0; i < sizeof(wapContentNames) / sizeof(wapContentNames[0]); i++) {
385 if (type == static_cast<uint8_t>(wapContentNames[i].key)) {
386 return wapContentNames[i].value;
387 }
388 }
389 return "*/*";
390 }
391 } // namespace Telephony
392 } // namespace OHOS
393