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
16 #include "mms_body_part_header.h"
17
18 #include "telephony_log_wrapper.h"
19
20 namespace OHOS {
21 namespace Telephony {
operator =(const MmsBodyPartHeader & srcHeader)22 MmsBodyPartHeader &MmsBodyPartHeader::operator=(const MmsBodyPartHeader &srcHeader)
23 {
24 if (this != &srcHeader) {
25 strContentTransferEncoding_ = srcHeader.strContentTransferEncoding_;
26 strFileName_ = srcHeader.strFileName_;
27 strContentLocation_ = srcHeader.strContentLocation_;
28 strContentID_ = srcHeader.strContentID_;
29 strDisposition_ = srcHeader.strDisposition_;
30 textMap_ = srcHeader.textMap_;
31 }
32 return *this;
33 }
34
MmsBodyPartHeader(const MmsBodyPartHeader & obj)35 MmsBodyPartHeader::MmsBodyPartHeader(const MmsBodyPartHeader &obj)
36 {
37 *this = obj;
38 }
39
DumpBodyPartHeader()40 void MmsBodyPartHeader::DumpBodyPartHeader() {}
41
42 /**
43 * @brief DecodeContentLocation
44 * OMA-TS-MMS_ENC-V1_3-20110913-A section:7.3.10 X-Mms-Content-Location Field
45 * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
46 * Content-location-value = Uri-value
47 * When used in the M-Mbox-Delete.conf and M-Delete.conf PDU:
48 * Content-location-Del-value = Value-length Status-count-value Content-location-value
49 * Status-count-value = Integer-value
50 * Uri-value = Text-string
51 * @param decodeBuffer
52 * @param Len
53 * @return true
54 * @return false
55 */
DecodeContentLocation(MmsDecodeBuffer & decodeBuffer,uint32_t & Len)56 bool MmsBodyPartHeader::DecodeContentLocation(MmsDecodeBuffer &decodeBuffer, uint32_t &Len)
57 {
58 std::string sTmp = "";
59 Len = 0;
60 if (!decodeBuffer.DecodeText(sTmp, Len)) {
61 TELEPHONY_LOGE("Body part header decode text fail.");
62 return false;
63 }
64 strContentLocation_ = sTmp;
65 return true;
66 }
67
68 /**
69 * @brief DecodeContentId
70 * wap-230-wsp-20010705-a section:8.4.2.67 Content-ID field
71 * Content-ID-value = Quoted-string
72 * @param decodeBuffer
73 * @param Len
74 * @return true
75 * @return false
76 */
DecodeContentId(MmsDecodeBuffer & decodeBuffer,uint32_t & Len)77 bool MmsBodyPartHeader::DecodeContentId(MmsDecodeBuffer &decodeBuffer, uint32_t &Len)
78 {
79 std::string sTmp = "";
80 Len = 0;
81 if (!decodeBuffer.DecodeQuotedText(sTmp, Len)) {
82 TELEPHONY_LOGE("Body part header decode quoted text fail.");
83 return false;
84 }
85 strContentID_ = sTmp;
86 return true;
87 }
88
89 /**
90 * @brief DecodeContentDisposition
91 * wap-230-wsp-20010705-a section:8.4.2.53 Content-disposition field
92 * Content-disposition-value = Value-length Disposition *(Parameter)
93 * Disposition = Form-data | Attachment | Inline | Token-text
94 * Form-data = <Octet 128>
95 * Attachment = <Octet 129>
96 * Inline = <Octet 130>
97 * @param decodeBuffer
98 * @param Len
99 * @return true
100 * @return false
101 */
DecodeContentDisposition(MmsDecodeBuffer & decodeBuffer,uint32_t & Len)102 bool MmsBodyPartHeader::DecodeContentDisposition(MmsDecodeBuffer &decodeBuffer, uint32_t &Len)
103 {
104 uint32_t dispositionLength = 0;
105 uint32_t count = 0;
106 if (!decodeBuffer.DecodeUintvar(dispositionLength, count)) {
107 TELEPHONY_LOGE("Body part header decode uintvar fail.");
108 return false;
109 }
110
111 uint32_t beginPostion = decodeBuffer.GetCurPosition();
112 uint8_t oneByte = 0;
113 if (!decodeBuffer.GetOneByte(oneByte)) {
114 TELEPHONY_LOGE("Body part header decode get one byte fail.");
115 return false;
116 }
117
118 switch (static_cast<MmsDispositonParam>(oneByte)) {
119 case MmsDispositonParam::P_DISPOSITION_FROM_DATA: {
120 strDisposition_ = DISPOSITION_FROM_DATA;
121 break;
122 }
123 case MmsDispositonParam::P_DISPOSITION_ATTACHMENT: {
124 strDisposition_ = DISPOSITION_ATTACHMENT;
125 break;
126 }
127 case MmsDispositonParam::P_DISPOSITION_INLINE: {
128 strDisposition_ = DISPOSITION_INLINE;
129 break;
130 }
131 default: {
132 if (!decodeBuffer.DecreasePointer(1)) {
133 TELEPHONY_LOGE("Body part header move pointer fail.");
134 return false;
135 }
136 std::string strTmp = "";
137 uint32_t tmpLen = 0;
138 if (!decodeBuffer.DecodeText(strTmp, tmpLen)) {
139 TELEPHONY_LOGE("Body part header decode text fail.");
140 return false;
141 }
142 strDisposition_ = strTmp;
143 break;
144 }
145 }
146 TELEPHONY_LOGI("strDisposition_ == %{public}s", strDisposition_.c_str());
147 if (!DecodeDispositionParameter(decodeBuffer, dispositionLength, beginPostion)) {
148 TELEPHONY_LOGE("Decode Disposition Parameter error.");
149 return false;
150 }
151 Len = dispositionLength + count + 1;
152 return true;
153 }
154
155 /**
156 * @brief DecodeContentDispositionParameter
157 * wap-230-wsp-20010705-a section:8.4.2.53 Content-disposition field
158 * Content-disposition-value = Value-length Disposition *(Parameter)
159 * Disposition = Form-data | Attachment | Inline | Token-text
160 * Form-data = <Octet 128>
161 * Attachment = <Octet 129>
162 * Inline = <Octet 130>
163 * @param decodeBuffer
164 * @param dispLen
165 * @param beginPos
166 * @return true
167 * @return false
168 */
DecodeDispositionParameter(MmsDecodeBuffer & decodeBuffer,uint32_t & dispLen,uint32_t beginPos)169 bool MmsBodyPartHeader::DecodeDispositionParameter(
170 MmsDecodeBuffer &decodeBuffer, uint32_t &dispLen, uint32_t beginPos)
171 {
172 const uint8_t pFileNameValue = 0x98;
173 uint32_t endPostion = decodeBuffer.GetCurPosition();
174 uint8_t oneByte = 0;
175 if (endPostion < beginPos) {
176 TELEPHONY_LOGI("Body part header data case 1.");
177 return true;
178 } else if ((dispLen <= (endPostion - beginPos)) && dispLen >= 1) {
179 dispLen = endPostion - beginPos - 1;
180 TELEPHONY_LOGI("Body part header data case 2.");
181 return true;
182 }
183
184 if (!decodeBuffer.GetOneByte(oneByte)) {
185 TELEPHONY_LOGE("Body part header decode get one byte fail.");
186 return false;
187 }
188 if (oneByte == pFileNameValue) {
189 std::string strTmp = "";
190 uint32_t tmpLen = 0;
191 if (!decodeBuffer.DecodeText(strTmp, tmpLen)) {
192 TELEPHONY_LOGE("Body part header decode text fail.");
193 return false;
194 }
195 strFileName_ = strTmp;
196 }
197 endPostion = decodeBuffer.GetCurPosition();
198 if ((endPostion < beginPos) || dispLen < (endPostion - beginPos)) {
199 TELEPHONY_LOGE("Body part header data error.");
200 return false;
201 }
202 if (!decodeBuffer.IncreasePointer(dispLen - (endPostion - beginPos))) {
203 TELEPHONY_LOGE("Body part header decode content disposition move pointer err.");
204 return false;
205 }
206 return true;
207 }
208
209 /**
210 * @brief DecodeWellKnownHeader
211 * wap-230-wsp-20010705-a section:8.4.2.6 Header
212 * Well-known-header = Well-known-field-name Wap-value
213 * Well-known-field-name = Short-integer
214 * Wap-value = Accept-value | Accept-charset-value |...
215 * @param decodeBuffer
216 * @param headerLen
217 * @return true
218 * @return false
219 */
DecodeWellKnownHeader(MmsDecodeBuffer & decodeBuffer,uint32_t & headerLen)220 bool MmsBodyPartHeader::DecodeWellKnownHeader(MmsDecodeBuffer &decodeBuffer, uint32_t &headerLen)
221 {
222 const uint8_t endStringZeroLen = 1;
223 uint8_t fieldCode = 0xff;
224 uint8_t oneByte = 0;
225 if (!decodeBuffer.GetOneByte(oneByte)) {
226 TELEPHONY_LOGE("Body part header decode get one byte fail.");
227 return false;
228 }
229 headerLen--;
230 uint32_t len = 0;
231 fieldCode = oneByte & 0x7f;
232 switch (static_cast<MmsHeaderParam>(fieldCode)) {
233 case MmsHeaderParam::P_CONTENT_LOCATION_V1: /* Content-Location */
234 case MmsHeaderParam::P_CONTENT_LOCATION_V2: { /* Content-Location */
235 if (!DecodeContentLocation(decodeBuffer, len)) {
236 TELEPHONY_LOGE("Body part header decode content location fail.");
237 return false;
238 }
239 break;
240 }
241 case MmsHeaderParam::P_CONTENT_ID: { /* Content-ID */
242 if (!DecodeContentId(decodeBuffer, len)) {
243 TELEPHONY_LOGE("Body part header decode contentId fail.");
244 return false;
245 }
246 break;
247 }
248 case MmsHeaderParam::P_CONTENT_DISPOSITION_V1: /* Content-Disposition */
249 case MmsHeaderParam::P_CONTENT_DISPOSITION_V2: {
250 if (!DecodeContentDisposition(decodeBuffer, len)) {
251 TELEPHONY_LOGE("Body part header decode content disposition fail.");
252 return false;
253 }
254 break;
255 }
256 default: {
257 std::string sTmp = "";
258 decodeBuffer.DecodeQuotedText(sTmp, len);
259 break;
260 }
261 }
262 if (headerLen > len + endStringZeroLen) {
263 headerLen -= len + endStringZeroLen;
264 } else {
265 headerLen = 0;
266 }
267 return true;
268 }
269
270 /**
271 * @brief DecodeApplicationHeader
272 * wap-230-wsp-20010705-a section:8.4.2.6 Header
273 * Application-header = Token-text Application-specific-value
274 * Application-specific-value = Text-string
275 * @param decodeBuffer
276 * @param headerLen
277 * @return true
278 * @return false
279 */
DecodeApplicationHeader(MmsDecodeBuffer & decodeBuffer,uint32_t & headerLen)280 bool MmsBodyPartHeader::DecodeApplicationHeader(MmsDecodeBuffer &decodeBuffer, uint32_t &headerLen)
281 {
282 const uint32_t endStringZeroLen = 2;
283 headerLen = 0;
284 std::string sField = "";
285 uint32_t fieldLen = 0;
286 if (!decodeBuffer.DecodeTokenText(sField, fieldLen)) {
287 TELEPHONY_LOGE("Body part header decode token text fail.");
288 return false;
289 }
290
291 std::string sValue = "";
292 uint32_t valueLen = 0;
293 if (!decodeBuffer.DecodeText(sValue, valueLen)) {
294 TELEPHONY_LOGE("Body part header decode text fail.");
295 return false;
296 }
297 if (sField == "Content-Transfer-Encoding") {
298 strContentTransferEncoding_ = sValue;
299 }
300 if (headerLen > fieldLen + valueLen + endStringZeroLen) {
301 headerLen -= fieldLen + valueLen + endStringZeroLen;
302 } else {
303 headerLen = 0;
304 }
305 return true;
306 }
307
GetContentId(std::string & contentId)308 bool MmsBodyPartHeader::GetContentId(std::string &contentId)
309 {
310 contentId.clear();
311 contentId = strContentID_;
312 return true;
313 }
314
SetContentId(std::string contentId)315 bool MmsBodyPartHeader::SetContentId(std::string contentId)
316 {
317 strContentID_ = contentId;
318 return true;
319 }
320
GetContentTransferEncoding(std::string & contentTransferEncoding)321 bool MmsBodyPartHeader::GetContentTransferEncoding(std::string &contentTransferEncoding)
322 {
323 contentTransferEncoding.clear();
324 contentTransferEncoding = strContentTransferEncoding_;
325 return true;
326 }
327
SetContentTransferEncoding(std::string contentTransferEncoding)328 bool MmsBodyPartHeader::SetContentTransferEncoding(std::string contentTransferEncoding)
329 {
330 strContentTransferEncoding_ = contentTransferEncoding;
331 return true;
332 }
333
GetContentLocation(std::string & contentLocation)334 bool MmsBodyPartHeader::GetContentLocation(std::string &contentLocation)
335 {
336 contentLocation.clear();
337 contentLocation.assign(strContentLocation_);
338 return true;
339 }
340
SetContentLocation(std::string contentLocation)341 bool MmsBodyPartHeader::SetContentLocation(std::string contentLocation)
342 {
343 strContentLocation_ = contentLocation;
344 return true;
345 }
346
GetContentDisposition(std::string & contentDisposition)347 bool MmsBodyPartHeader::GetContentDisposition(std::string &contentDisposition)
348 {
349 contentDisposition.clear();
350 contentDisposition.assign(strDisposition_);
351 return true;
352 }
353
SetContentDisposition(std::string contentDisposition)354 bool MmsBodyPartHeader::SetContentDisposition(std::string contentDisposition)
355 {
356 strDisposition_ = contentDisposition;
357 return true;
358 }
359
360 /**
361 * @brief EncodeContentLocation
362 * OMA-TS-MMS_ENC-V1_3-20110913-A section:7.3.10 X-Mms-Content-Location Field
363 * When used in a PDU other than M-Mbox-Delete.conf and M-Delete.conf:
364 * Content-location-value = Uri-value
365 * When used in the M-Mbox-Delete.conf and M-Delete.conf PDU:
366 * Content-location-Del-value = Value-length Status-count-value Content-location-value
367 * Status-count-value = Integer-value
368 * Uri-value = Text-string
369 * @param encodeBuffer
370 * @return true
371 * @return false
372 */
EncodeContentLocation(MmsEncodeBuffer & encodeBuffer)373 bool MmsBodyPartHeader::EncodeContentLocation(MmsEncodeBuffer &encodeBuffer)
374 {
375 const uint8_t setHighestBitOne = 0x80;
376 if (strContentLocation_.empty()) {
377 TELEPHONY_LOGI("Body part header encode content location is empty.");
378 return true;
379 }
380
381 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsHeaderParam::P_CONTENT_LOCATION_V2) | setHighestBitOne)) {
382 TELEPHONY_LOGE("Body part header encode content location write byte fail.");
383 return false;
384 }
385 if (!encodeBuffer.EncodeText(strContentLocation_)) {
386 TELEPHONY_LOGE("Body part header encode content location fail.");
387 return false;
388 }
389 return true;
390 }
391
392 /**
393 * @brief EncodeContentId
394 * wap-230-wsp-20010705-a section:8.4.2.67 Content-ID field
395 * Content-ID-value = Quoted-string
396 * @param encodeBuffer
397 * @return true
398 * @return false
399 */
EncodeContentId(MmsEncodeBuffer & encodeBuffer)400 bool MmsBodyPartHeader::EncodeContentId(MmsEncodeBuffer &encodeBuffer)
401 {
402 const uint8_t setHighestBitOne = 0x80;
403 if (strContentID_.empty()) {
404 TELEPHONY_LOGI("Body part header encode content ID is empty.");
405 return true;
406 }
407
408 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsHeaderParam::P_CONTENT_ID) | setHighestBitOne)) {
409 TELEPHONY_LOGE("Body part header encode content ID write byte fail.");
410 return false;
411 }
412 if (!encodeBuffer.EncodeQuotedText(strContentID_)) {
413 TELEPHONY_LOGE("Body part header encode content ID fail.");
414 return false;
415 }
416 return true;
417 }
418
419 /**
420 * @brief EncodeContentDisposition
421 * wap-230-wsp-20010705-a section:8.4.2.53 Content-disposition field
422 * Content-disposition-value = Value-length Disposition *(Parameter)
423 * Disposition = Form-data | Attachment | Inline | Token-text
424 * Form-data = <Octet 128>
425 * Attachment = <Octet 129>
426 * Inline = <Octet 130>
427 * @param encodeBuffer
428 * @return true
429 * @return false
430 */
EncodeContentDisposition(MmsEncodeBuffer & encodeBuffer)431 bool MmsBodyPartHeader::EncodeContentDisposition(MmsEncodeBuffer &encodeBuffer)
432 {
433 const uint8_t setHighestBitOne = 0x80;
434 std::vector<std::string> dispVec {DISPOSITION_FROM_DATA, DISPOSITION_ATTACHMENT, DISPOSITION_INLINE};
435 auto it = std::find(dispVec.begin(), dispVec.end(), strDisposition_);
436 if (it == dispVec.end()) {
437 return true;
438 }
439
440 TELEPHONY_LOGI("strDisposition = %{public}s", strDisposition_.c_str());
441 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsHeaderParam::P_CONTENT_DISPOSITION_V1) | setHighestBitOne)) {
442 TELEPHONY_LOGE("Body part header encode content disposition write byte fail.");
443 return false;
444 }
445 if (!encodeBuffer.EncodeUintvar(0x01)) {
446 TELEPHONY_LOGE("EncodeContentDisposition EncodeUintvar Error.");
447 return false;
448 }
449 if (strDisposition_ == DISPOSITION_FROM_DATA) {
450 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsDispositonParam::P_DISPOSITION_FROM_DATA))) {
451 TELEPHONY_LOGE("Body part header encode content disposition write byte fail.");
452 return false;
453 }
454 return true;
455 }
456 if (strDisposition_ == DISPOSITION_ATTACHMENT) {
457 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsDispositonParam::P_DISPOSITION_ATTACHMENT))) {
458 TELEPHONY_LOGE("Body part header encode content disposition write byte fail.");
459 return false;
460 }
461 return true;
462 }
463 if (strDisposition_ == DISPOSITION_INLINE) {
464 if (!encodeBuffer.WriteByte(static_cast<uint8_t>(MmsDispositonParam::P_DISPOSITION_INLINE))) {
465 TELEPHONY_LOGE("Body part header encode content disposition write byte fail.");
466 return false;
467 }
468 return true;
469 }
470 return true;
471 }
472
473 /**
474 * @brief EncodeContentDisposition
475 * wap-230-wsp-20010705-a section:8.4.2.46 Transfer encoding field
476 * Transfer-encoding-values = Chunked | Token-text
477 * Chunked = <Octet 128>
478 * @param encodeBuffer
479 * @return true
480 * @return false
481 */
EncodeContentTransferEncoding(MmsEncodeBuffer & encodeBuffer)482 bool MmsBodyPartHeader::EncodeContentTransferEncoding(MmsEncodeBuffer &encodeBuffer)
483 {
484 if (strContentTransferEncoding_.empty()) {
485 TELEPHONY_LOGI("Body part header encode content transfer encoding is empty.");
486 return true;
487 }
488
489 if (!encodeBuffer.EncodeText("Content-Transfer-Encoding")) {
490 TELEPHONY_LOGE("Body part header encode content transfer encoding encode text fail.");
491 return false;
492 }
493 if (!encodeBuffer.EncodeText(strContentTransferEncoding_)) {
494 TELEPHONY_LOGE("Body part header encode content transfer encoding encode text fail.");
495 return false;
496 }
497 return true;
498 }
499
500 /**
501 * @brief EncodeMmsBodyPartHeader
502 * wap-230-wsp-20010705-a section:8.4.2.6 Header
503 * Well-known-header = Well-known-field-name Wap-value
504 * Well-known-field-name = Short-integer
505 * Wap-value = Accept-value | Accept-charset-value |...
506 * @param encodeBuffer
507 * @return true
508 * @return false
509 */
EncodeMmsBodyPartHeader(MmsEncodeBuffer & encodeBuffer)510 bool MmsBodyPartHeader::EncodeMmsBodyPartHeader(MmsEncodeBuffer &encodeBuffer)
511 {
512 if (!EncodeContentId(encodeBuffer)) {
513 TELEPHONY_LOGE("Body part header encode ContentId fail.");
514 return false;
515 }
516 if (!EncodeContentLocation(encodeBuffer)) {
517 TELEPHONY_LOGE("Body part header encode ContentLocation fail.");
518 return false;
519 }
520 if (!EncodeContentDisposition(encodeBuffer)) {
521 TELEPHONY_LOGE("Body part header encode ContentDisposition fail.");
522 return false;
523 }
524 if (!EncodeContentTransferEncoding(encodeBuffer)) {
525 TELEPHONY_LOGE("Body part header encode ContentTransferEncoding fail.");
526 return false;
527 }
528 return true;
529 }
530 } // namespace Telephony
531 } // namespace OHOS
532