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