• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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