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