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 "mms_content_type.h"
16
17 #include "telephony_log_wrapper.h"
18 #include "mms_decode_buffer.h"
19 #include "mms_charset.h"
20
21 namespace OHOS {
22 namespace Telephony {
DumpMmsContentType()23 void MmsContentType::DumpMmsContentType()
24 {
25 TELEPHONY_LOGI("contentType : %{public}s", contentType_.c_str());
26 msgContentParm_.DumpContentParam();
27 }
28
MmsContentType(const MmsContentType & srcContentType)29 MmsContentType::MmsContentType(const MmsContentType &srcContentType)
30 {
31 contentType_ = srcContentType.contentType_;
32 msgContentParm_ = srcContentType.msgContentParm_;
33 }
34
operator =(const MmsContentType & srcContentType)35 MmsContentType &MmsContentType::operator=(const MmsContentType &srcContentType)
36 {
37 if (this != &srcContentType) {
38 contentType_ = srcContentType.contentType_;
39 msgContentParm_ = srcContentType.msgContentParm_;
40 }
41 return *this;
42 }
43
44 /**
45 * @brief DecodeMmsContentType
46 * wap-230-wsp-20010705-a section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
47 * Content-type-value = Constrained-media | Content-general-form
48 * Constrained-media = Constrained-encoding
49 * Constrained-encoding = Extension-Media | Short-integer
50 * Extension-media = *TEXT End-of-string
51 * Content-general-form = Value-length Media-type
52 * Media-type = (Well-known-media | Extension-Media) *(Parameter)
53 * Well-known-media = Integer-value
54 * Parameter = Typed-parameter | Untyped-parameter
55 * @param decodeBuffer
56 * @param contentLength
57 * @return true
58 * @return false
59 */
DecodeMmsContentType(MmsDecodeBuffer & decodeBuffer,int32_t & contentLength)60 bool MmsContentType::DecodeMmsContentType(MmsDecodeBuffer &decodeBuffer, int32_t &contentLength)
61 {
62 const uint8_t setHighestBitZero = 0x7f;
63 uint8_t oneByte = 0;
64 if (decodeBuffer.DecodeIsShortInt()) {
65 if (!decodeBuffer.GetOneByte(oneByte)) {
66 TELEPHONY_LOGE("Decode contentType GetOneByte fail.");
67 return false;
68 }
69 contentType_ = GetContentTypeFromInt(oneByte & setHighestBitZero);
70 contentLength = 1;
71 return true;
72 }
73
74 if (decodeBuffer.DecodeIsString()) {
75 std::string sType = "";
76 uint32_t len = 0;
77 decodeBuffer.DecodeText(sType, len);
78 contentLength = static_cast<int32_t>(len + 1);
79 contentType_ = sType;
80 return true; // 2
81 }
82
83 if (!DecodeMmsCTGeneralForm(decodeBuffer, contentLength)) {
84 TELEPHONY_LOGE("Decode contentType DecodeMmsCTGeneralForm fail.");
85 return false;
86 }
87 return true;
88 }
89
90 /**
91 * @brief DecodeMmsCTGeneralForm
92 * wap-230-wsp-20010705-a section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
93 * Content-type-value = Constrained-media | Content-general-form
94 * Constrained-media = Constrained-encoding
95 * Constrained-encoding = Extension-Media | Short-integer
96 * Extension-media = *TEXT End-of-string
97 * Content-general-form = Value-length Media-type
98 * Media-type = (Well-known-media | Extension-Media) *(Parameter)
99 * Well-known-media = Integer-value
100 * Parameter = Typed-parameter | Untyped-parameter
101 * @param decodeBuffer
102 * @param contentLength
103 * @return true
104 * @return false
105 */
DecodeMmsCTGeneralForm(MmsDecodeBuffer & decodeBuffer,int32_t & contentLength)106 bool MmsContentType::DecodeMmsCTGeneralForm(MmsDecodeBuffer &decodeBuffer, int32_t &contentLength)
107 {
108 const uint8_t setHighestBitZero = 0x7f;
109
110 /** false indicated no more data */
111 if (!decodeBuffer.DecodeIsValueLength()) {
112 TELEPHONY_LOGE("Decode contentType DecodeIsValueLength fail.");
113 return false;
114 }
115
116 uint32_t valueLength = 0;
117 uint32_t returnLength = 0;
118 if (!decodeBuffer.DecodeValueLengthReturnLen(valueLength, returnLength)) {
119 TELEPHONY_LOGE("Decode contentType DecodeValueLengthReturnLen fail.");
120 return false;
121 }
122 contentLength = static_cast<int32_t>(valueLength + returnLength);
123
124 uint8_t oneByte = 0;
125 if (!decodeBuffer.PeekOneByte(oneByte)) {
126 TELEPHONY_LOGE("Decode contentType PeekOneByte fail.");
127 return false;
128 }
129 if (decodeBuffer.DecodeIsShortInt()) {
130 contentType_ = GetContentTypeFromInt(oneByte & setHighestBitZero);
131 if (!decodeBuffer.IncreasePointer(1)) {
132 TELEPHONY_LOGE("Decode contentType IncreasePointer fail.");
133 return false;
134 }
135 if (valueLength == 0) {
136 TELEPHONY_LOGE("Decode contentType valueLength empty.");
137 return false;
138 }
139 valueLength--;
140 } else if (decodeBuffer.DecodeIsString()) {
141 std::string sType = "";
142 uint32_t len = 0;
143 decodeBuffer.DecodeText(sType, len);
144 valueLength -= len + 1;
145 contentType_ = sType;
146 } else {
147 TELEPHONY_LOGE("Decode contentType DecodeMmsContentType fail.");
148 return false;
149 }
150
151 if (!DecodeParameter(decodeBuffer, valueLength)) {
152 TELEPHONY_LOGE("Decode contentType DecodeParameter fail.");
153 return false;
154 }
155 return true;
156 }
157
GetContentTypeFromInt(uint8_t type)158 std::string MmsContentType::GetContentTypeFromInt(uint8_t type)
159 {
160 for (unsigned int i = 0; i < sizeof(mmsContentNames) / sizeof(mmsContentNames[0]); i++) {
161 if (type == static_cast<uint8_t>(mmsContentNames[i].key)) {
162 return mmsContentNames[i].value;
163 }
164 }
165 return "*/*";
166 }
167
GetContentTypeFromString(std::string str)168 int8_t MmsContentType::GetContentTypeFromString(std::string str)
169 {
170 for (unsigned int i = 0; i < sizeof(mmsContentNames) / sizeof(mmsContentNames[0]); i++) {
171 if (str == std::string(mmsContentNames[i].value)) {
172 return i;
173 }
174 }
175 return -1;
176 }
177
178 /**
179 * @brief DecodeParameter
180 * wap-230-wsp-20010705-a section:8.4.2.4 Parameter
181 * Parameter = Typed-parameter | Untyped-parameter
182 * Typed-parameter = Well-known-parameter-token Typed-value
183 * Well-known-parameter-token = Integer-value
184 * Typed-value = Compact-value | Text-value
185 * Compact-value = Integer-value |
186 * Date-value | Delta-seconds-value | Q-value | Version-value |
187 * Uri-value
188 * Untyped-parameter = Token-text Untyped-value
189 * Untyped-value = Integer-value | Text-value
190 * Delta-seconds-value = Long-integer
191 * Q-value = 1*2 OCTET
192 * @param decodeBuffer
193 * @param valueLength
194 * @return true
195 * @return false
196 */
DecodeParameter(MmsDecodeBuffer & decodeBuffer,int32_t valueLength)197 bool MmsContentType::DecodeParameter(MmsDecodeBuffer &decodeBuffer, int32_t valueLength)
198 {
199 uint8_t paramCode = 0;
200 while (valueLength > 0) {
201 if (!decodeBuffer.GetOneByte(paramCode)) {
202 TELEPHONY_LOGE("Decode contentType GetOneByte fail.");
203 return false;
204 }
205 valueLength--;
206 switch (static_cast<ContentParam>(paramCode)) {
207 case ContentParam::CT_P_CHARSET: {
208 /* charset */
209 if (!DecodeCharsetField(decodeBuffer, valueLength)) {
210 TELEPHONY_LOGE("Decode contentType DecodeCharsetField fail.");
211 return false;
212 }
213 break;
214 }
215 case ContentParam::CT_P_FILENAME:
216 case ContentParam::CT_P_FILENAME_VALUE:
217 case ContentParam::CT_P_START_VALUE:
218 case ContentParam::CT_P_START:
219 case ContentParam::CT_P_NAME:
220 case ContentParam::CT_P_NAME_VALUE:
221 case ContentParam::CT_P_START_INFO:
222 case ContentParam::CT_P_START_INFO_VALUE: {
223 if (!DecodeTextField(decodeBuffer, paramCode, valueLength)) {
224 TELEPHONY_LOGE("Decode contentType DecodeTextField fail.");
225 return false;
226 }
227 break;
228 }
229 case ContentParam::CT_P_TYPE:
230 case ContentParam::CT_P_TYPE_STRING: {
231 if (!DecodeTypeField(decodeBuffer, valueLength)) {
232 TELEPHONY_LOGE("Decode contentType DecodeTypeField fail.");
233 return false;
234 }
235 break;
236 }
237 default: {
238 if (!decodeBuffer.IncreasePointer(valueLength)) {
239 TELEPHONY_LOGE("Decode contentType IncreasePointer fail.");
240 return false;
241 }
242 valueLength = 0;
243 }
244 }
245 }
246 return true;
247 }
248
GetContentType(std::string & str)249 bool MmsContentType::GetContentType(std::string &str)
250 {
251 str = contentType_;
252 return true;
253 }
254
SetContentType(std::string str)255 bool MmsContentType::SetContentType(std::string str)
256 {
257 contentType_ = str;
258 return true;
259 }
260
SetContentParam(MmsContentParam & contentParam)261 bool MmsContentType::SetContentParam(MmsContentParam &contentParam)
262 {
263 msgContentParm_ = contentParam;
264 return true;
265 }
266
267 /**
268 * @brief DecodeTextField
269 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
270 * Text-string = [Quote] *TEXT End-of-string
271 * Quote = <Octet 127>
272 * End-of-string = <Octet 0>
273 * @param decodeBuffer
274 * @param field
275 * @param valueLength
276 * @return true
277 * @return false
278 */
DecodeTextField(MmsDecodeBuffer & decodeBuffer,uint8_t field,int32_t & valueLength)279 bool MmsContentType::DecodeTextField(MmsDecodeBuffer &decodeBuffer, uint8_t field, int32_t &valueLength)
280 {
281 std::string str = "";
282 uint32_t len = 0;
283 if (!decodeBuffer.DecodeText(str, len)) {
284 TELEPHONY_LOGE("Decode contentType DecodeText fail.");
285 return false;
286 }
287 msgContentParm_.GetParamMap().insert(std::make_pair(field, str));
288 valueLength -= static_cast<int32_t>(len);
289 valueLength -= 1;
290 return true;
291 }
292
293 /**
294 * @brief DecodeCharsetField
295 * wap-230-wsp-20010705-a section:8.4.2.8 Accept charset field
296 * Well-known-charset = Any-charset | Integer-value
297 * Any-charset = <Octet 128>
298 * @param decodeBuffer
299 * @param valueLength
300 * @return true
301 * @return false
302 */
DecodeCharsetField(MmsDecodeBuffer & decodeBuffer,int32_t & valueLength)303 bool MmsContentType::DecodeCharsetField(MmsDecodeBuffer &decodeBuffer, int32_t &valueLength)
304 {
305 int32_t charset = 0;
306 uint8_t oneByte = 0;
307 const uint8_t textMinValue = 32;
308 const uint8_t textMaxValue = 127;
309 if (decodeBuffer.PeekOneByte(oneByte) == false) {
310 TELEPHONY_LOGE("Decode contentType PeekOneByte fail.");
311 return false;
312 }
313 if (((oneByte > textMinValue) && (oneByte < textMaxValue)) || (oneByte == 0)) {
314 std::string sCharset = "";
315 uint32_t len = 0;
316 if (!decodeBuffer.DecodeText(sCharset, len)) {
317 TELEPHONY_LOGE("Decode contentType DecodeText fail.");
318 return false;
319 }
320 valueLength -= static_cast<int32_t>(len + 1);
321 uint32_t tmpCharSet = 0;
322 auto charSetInstance = DelayedSingleton<MmsCharSet>::GetInstance();
323 if (charSetInstance == nullptr || (!charSetInstance->GetCharSetIntFromString(tmpCharSet, sCharset))) {
324 TELEPHONY_LOGE("Decode contentType GetInstance or GetCharSetIntFromString fail.");
325 return false;
326 }
327 charset = static_cast<int32_t>(tmpCharSet);
328 } else {
329 uint32_t startPosition = decodeBuffer.GetCurPosition();
330 uint64_t tmp = 0;
331 if (!decodeBuffer.DecodeInteger(tmp)) {
332 TELEPHONY_LOGE("Decode contentType DecodeInteger fail.");
333 return false;
334 }
335 charset = (int32_t)tmp;
336 uint32_t endPosition = decodeBuffer.GetCurPosition();
337 if (endPosition >= startPosition) {
338 valueLength -= static_cast<int32_t>(endPosition - startPosition);
339 }
340 }
341 msgContentParm_.SetCharSet(charset);
342 return true;
343 }
344
345 /**
346 * @brief DecodeTypeField
347 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
348 * Constrained-encoding = Extension-Media | Short-integer
349 * Extension-media = *TEXT End-of-string
350 * @param decodeBuffer
351 * @param valueLength
352 * @return true
353 * @return false
354 */
DecodeTypeField(MmsDecodeBuffer & decodeBuffer,int32_t & valueLength)355 bool MmsContentType::DecodeTypeField(MmsDecodeBuffer &decodeBuffer, int32_t &valueLength)
356 {
357 uint8_t oneByte = 0;
358 if (decodeBuffer.GetOneByte(oneByte) == false) {
359 TELEPHONY_LOGE("Decode contentType GetOneByte fail.");
360 return false;
361 }
362
363 if (oneByte > 0x7f) {
364 msgContentParm_.SetType(GetContentTypeFromInt(oneByte & 0x7f));
365 valueLength -= 1;
366 } else {
367 if (!decodeBuffer.DecreasePointer(1)) {
368 TELEPHONY_LOGE("Decode contentType DecreasePointer fail.");
369 return false;
370 }
371
372 std::string sType = "";
373 uint32_t len = 0;
374 if (!decodeBuffer.DecodeText(sType, len)) {
375 TELEPHONY_LOGE("Decode contentType DecodeText fail.");
376 return false;
377 }
378 valueLength -= static_cast<int32_t>(len);
379 valueLength -= 1;
380 msgContentParm_.SetType(sType);
381 }
382 return true;
383 }
384
385 /**
386 * @brief EncodeTextField
387 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
388 * Text-string = [Quote] *TEXT End-of-string
389 * Quote = <Octet 127>
390 * End-of-string = <Octet 0>
391 * @param encodeBuffer
392 * @return true
393 * @return false
394 */
EncodeTextField(MmsEncodeBuffer & encodeBuffer)395 bool MmsContentType::EncodeTextField(MmsEncodeBuffer &encodeBuffer)
396 {
397 const uint8_t textParamLen = 8;
398 uint8_t fields[textParamLen] = {static_cast<uint8_t>(ContentParam::CT_P_FILENAME),
399 static_cast<uint8_t>(ContentParam::CT_P_FILENAME_VALUE),
400 static_cast<uint8_t>(ContentParam::CT_P_START_VALUE), static_cast<uint8_t>(ContentParam::CT_P_START),
401 static_cast<uint8_t>(ContentParam::CT_P_NAME), static_cast<uint8_t>(ContentParam::CT_P_NAME_VALUE),
402 static_cast<uint8_t>(ContentParam::CT_P_START_INFO),
403 static_cast<uint8_t>(ContentParam::CT_P_START_INFO_VALUE)};
404
405 for (size_t i = 0; i < sizeof(fields); i++) {
406 if (msgContentParm_.GetParamMap().find(fields[i]) != msgContentParm_.GetParamMap().end()) {
407 if (!encodeBuffer.WriteByte(fields[i])) {
408 TELEPHONY_LOGE("Encode contentType WriteByte fail.");
409 return false;
410 }
411 if (!encodeBuffer.EncodeText(msgContentParm_.GetParamMap()[fields[i]])) {
412 TELEPHONY_LOGE("Encode contentType EncodeText fail.");
413 return false;
414 }
415 }
416 }
417 return true;
418 }
419
420 /**
421 * @brief EncodeCharsetField
422 * wap-230-wsp-20010705-a section:8.4.2.8 Accept charset field
423 * Well-known-charset = Any-charset | Integer-value
424 * Any-charset = <Octet 128>
425 * @param encodeBuffer
426 * @return true
427 * @return false
428 */
EncodeCharsetField(MmsEncodeBuffer & encodeBuffer)429 bool MmsContentType::EncodeCharsetField(MmsEncodeBuffer &encodeBuffer)
430 {
431 if (msgContentParm_.GetCharSet() == 0) {
432 return true;
433 }
434 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(ContentParam::CT_P_CHARSET))) {
435 TELEPHONY_LOGE("Encode contentType WriteByte fail.");
436 return false;
437 }
438 if (!encodeBuffer.EncodeLongInteger(msgContentParm_.GetCharSet())) {
439 TELEPHONY_LOGE("Encode contentType EncodeLongInteger fail.");
440 return false;
441 }
442 return true;
443 }
444
445 /**
446 * @brief EncodeTypeField
447 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
448 * Constrained-encoding = Extension-Media | Short-integer
449 * Extension-media = *TEXT End-of-string
450 * @param encodeBuffer
451 * @return true
452 * @return false
453 */
EncodeTypeField(MmsEncodeBuffer & encodeBuffer)454 bool MmsContentType::EncodeTypeField(MmsEncodeBuffer &encodeBuffer)
455 {
456 if (msgContentParm_.GetType().empty()) {
457 return true;
458 }
459 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(ContentParam::CT_P_TYPE))) {
460 TELEPHONY_LOGE("Encode contentType WriteByte fail.");
461 return false;
462 }
463 if (!encodeBuffer.EncodeText(msgContentParm_.GetType())) {
464 TELEPHONY_LOGE("Encode contentType EncodeText fail.");
465 return false;
466 }
467 return true;
468 }
469
470 /**
471 * @brief EncodeMmsBodyPartContentParam
472 * wap-230-wsp-20010705-a section:8.4.2.4 Parameter
473 * Parameter = Typed-parameter | Untyped-parameter
474 * Typed-parameter = Well-known-parameter-token Typed-value
475 * Well-known-parameter-token = Integer-value
476 * Typed-value = Compact-value | Text-value
477 * Compact-value = Integer-value |
478 * Date-value | Delta-seconds-value | Q-value | Version-value |
479 * Uri-value
480 * Untyped-parameter = Token-text Untyped-value
481 * Untyped-value = Integer-value | Text-value
482 * @param encodeBuffer
483 * @return true
484 * @return false
485 */
EncodeMmsBodyPartContentParam(MmsEncodeBuffer & encodeBuffer)486 bool MmsContentType::EncodeMmsBodyPartContentParam(MmsEncodeBuffer &encodeBuffer)
487 {
488 if (!EncodeTextField(encodeBuffer)) {
489 TELEPHONY_LOGE("Encode contentType EncodeTextField fail.");
490 return false;
491 }
492 if (!EncodeCharsetField(encodeBuffer)) {
493 TELEPHONY_LOGE("Encode contentType EncodeCharsetField fail.");
494 return false;
495 }
496 if (!EncodeTypeField(encodeBuffer)) {
497 TELEPHONY_LOGE("Encode contentType EncodeTypeField fail.");
498 return false;
499 }
500 return true;
501 }
502
503 /**
504 * @brief EncodeMmsBodyPartContentType
505 * wap-230-wsp-20010705-a section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
506 * Content-type-value = Constrained-media | Content-general-form
507 * Constrained-media = Constrained-encoding
508 * Constrained-encoding = Extension-Media | Short-integer
509 * Extension-media = *TEXT End-of-string
510 * Content-general-form = Value-length Media-type
511 * Media-type = (Well-known-media | Extension-Media) *(Parameter)
512 * Well-known-media = Integer-value
513 * Parameter = Typed-parameter | Untyped-parameter
514 * @param encodeBuffer
515 * @return true
516 * @return false
517 */
EncodeMmsBodyPartContentType(MmsEncodeBuffer & encodeBuffer)518 bool MmsContentType::EncodeMmsBodyPartContentType(MmsEncodeBuffer &encodeBuffer)
519 {
520 MmsEncodeBuffer tmpEncodeBuffer;
521 int8_t u8ContentType = 0;
522 u8ContentType = GetContentTypeFromString(contentType_);
523 if (u8ContentType < 0) {
524 if (!tmpEncodeBuffer.EncodeText(contentType_)) {
525 TELEPHONY_LOGE("Encode contentType EncodeText fail.");
526 return false;
527 }
528 } else {
529 if (!tmpEncodeBuffer.WriteByte(static_cast<uint8_t>(u8ContentType) | 0x80)) {
530 TELEPHONY_LOGE("Encode contentType WriteByte fail.");
531 return false;
532 }
533 }
534 if (!EncodeMmsBodyPartContentParam(tmpEncodeBuffer)) {
535 TELEPHONY_LOGE("Encode contentType EncodeMmsBodyPartContentParam fail.");
536 return false;
537 }
538 if (!encodeBuffer.EncodeValueLength(tmpEncodeBuffer.GetCurPosition())) {
539 TELEPHONY_LOGE("Encode contentType EncodeValueLength fail.");
540 return false;
541 }
542 if (!encodeBuffer.WriteBuffer(tmpEncodeBuffer)) {
543 TELEPHONY_LOGE("Encode contentType WriteBuffer fail.");
544 return false;
545 }
546 return true;
547 }
548
GetContentParam()549 MmsContentParam& MmsContentType::GetContentParam()
550 {
551 return msgContentParm_;
552 }
553 } // namespace Telephony
554 } // namespace OHOS
555