• 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_body_part.h"
16 
17 #include <ctime>
18 
19 #include "securec.h"
20 #include "utils/mms_base64.h"
21 #include "utils/mms_quoted_printable.h"
22 #include "telephony_log_wrapper.h"
23 
24 namespace OHOS {
25 namespace Telephony {
26 using namespace std;
MmsBodyPart()27 MmsBodyPart::MmsBodyPart() : headerLen_(0), bodyLen_(0) {}
28 
MmsBodyPart(const MmsBodyPart & srcBodyPart)29 MmsBodyPart::MmsBodyPart(const MmsBodyPart &srcBodyPart) : headerLen_(0), bodyLen_(0)
30 {
31     *this = srcBodyPart;
32 }
33 
~MmsBodyPart()34 MmsBodyPart::~MmsBodyPart()
35 {
36     if (pbodyPartBuffer_ != nullptr) {
37         pbodyPartBuffer_.reset();
38     }
39 }
40 
DumpMmsBodyPart()41 void MmsBodyPart::DumpMmsBodyPart()
42 {
43     TELEPHONY_LOGI("============== Start BodyPart Info ==========");
44     std::string isSmil = isSmilFile_ ? "ture" : "false";
45     TELEPHONY_LOGI("isSmilFile : %{public}s", isSmil.c_str());
46     TELEPHONY_LOGI("strFileName : %{public}s", strFileName_.c_str());
47     TELEPHONY_LOGI("headerLen : %{public}u", headerLen_);
48     TELEPHONY_LOGI("bodyPartLen : %{public}u", bodyLen_);
49     bodyPartContentType_.DumpMmsContentType();
50     mmsBodyPartHeader_.DumpBodyPartHeader();
51     TELEPHONY_LOGI("============== End BodyPart Info ==========");
52 }
53 
operator =(const MmsBodyPart & srcBodyPart)54 MmsBodyPart &MmsBodyPart::operator=(const MmsBodyPart &srcBodyPart)
55 {
56     if (this == &srcBodyPart) {
57         return *this;
58     }
59 
60     bodyLen_ = srcBodyPart.bodyLen_;
61     pbodyPartBuffer_ = std::make_unique<char[]>(bodyLen_);
62     if (pbodyPartBuffer_ == nullptr || srcBodyPart.pbodyPartBuffer_ == nullptr) {
63         bodyLen_ = 0;
64         AssignBodyPart(srcBodyPart);
65         TELEPHONY_LOGE("Assignment Buffer Nullptr Error.");
66         return *this;
67     }
68 
69     if (memcpy_s(pbodyPartBuffer_.get(), bodyLen_, srcBodyPart.pbodyPartBuffer_.get(), bodyLen_) != EOK) {
70         bodyLen_ = 0;
71         TELEPHONY_LOGE("Copy BodyPart Buffer Memory Error.");
72     }
73     AssignBodyPart(srcBodyPart);
74     return *this;
75 }
76 
AssignBodyPart(const MmsBodyPart & obj)77 void MmsBodyPart::AssignBodyPart(const MmsBodyPart &obj)
78 {
79     headerLen_ = obj.headerLen_;
80     mmsBodyPartHeader_ = obj.mmsBodyPartHeader_;
81     strFileName_ = obj.strFileName_;
82     bodyPartContentType_ = obj.bodyPartContentType_;
83 }
84 
85 /**
86  * @brief DecodePart
87  * wap-230-wsp-20010705-a   section:8.5.3 Multipart Entry
88  * HeadersLen   Uintvar
89  * DataLen      Uintvar
90  * ContentType  Multiple octets
91  * Headers      (HeadersLen – length of ContentType) octets
92  * Data         DataLen octets
93  * @param decodeBuffer
94  * @return true
95  * @return false
96  */
DecodePart(MmsDecodeBuffer & decodeBuffer)97 bool MmsBodyPart::DecodePart(MmsDecodeBuffer &decodeBuffer)
98 {
99     uint32_t headerLength = 0;
100     uint32_t bodyLength = 0;
101     uint32_t length = 0;
102     if (!decodeBuffer.DecodeUintvar(headerLength, length)) {
103         TELEPHONY_LOGE("Decode Body Part Header Uintvar Error.");
104         return false;
105     }
106     if (!decodeBuffer.DecodeUintvar(bodyLength, length)) {
107         TELEPHONY_LOGE("Decode Body Part Body Lenght Uintvar Error.");
108         return false;
109     }
110     int32_t contentLength = 0;
111     if (!bodyPartContentType_.DecodeMmsContentType(decodeBuffer, contentLength)) {
112         TELEPHONY_LOGE("Decode Body Part ContentType Error.");
113         return false;
114     }
115 
116     headerLen_ = headerLength;
117     bodyLen_ = bodyLength;
118     if (headerLen_ < static_cast<uint32_t>(contentLength)) {
119         TELEPHONY_LOGE("Decode Body Part HeaderLen Less Than ContentLength Error.");
120         return false;
121     }
122     if (!DecodePartHeader(decodeBuffer, headerLen_ - contentLength)) {
123         TELEPHONY_LOGE("Decode Body Part Header Error.");
124         return false;
125     }
126     if (!DecodePartBody(decodeBuffer, bodyLen_)) {
127         TELEPHONY_LOGE("Decode Body Part Body Error.");
128         return false;
129     }
130     DecodeSetFileName();
131     return true;
132 }
133 
134 /**
135  * @brief DecodePartHeader
136  * wap-230-wsp-20010705-a   section:8.4.2.6 Header
137  * Message-header			  = Well-known-header | Application-header
138  * Application-header		  = Token-text Application-specific-value
139  * Well-known-field-name	  = Short-integer
140  * Application-specific-value = Text-string
141  * @param decodeBuffer
142  * @param headerLen
143  * @return true
144  * @return false
145  */
DecodePartHeader(MmsDecodeBuffer & decodeBuffer,uint32_t headerLen)146 bool MmsBodyPart::DecodePartHeader(MmsDecodeBuffer &decodeBuffer, uint32_t headerLen)
147 {
148     const uint8_t headerAccept = 0x80;
149     const uint8_t headerCacheControl = 0xC7;
150     const uint8_t textMin = 32;
151     const uint8_t textMax = 127;
152 
153     uint8_t oneByte = 0;
154     while (headerLen > 0) {
155         if (!decodeBuffer.PeekOneByte(oneByte)) {
156             TELEPHONY_LOGE("Decode Body Part PeekOneByte Error.");
157             return false;
158         }
159         if (headerAccept <= oneByte && headerCacheControl >= oneByte) {
160             if (!mmsBodyPartHeader_.DecodeWellKnownHeader(decodeBuffer, headerLen)) {
161                 TELEPHONY_LOGE("Decode Body Part DecodeWellKnownHeader Error.");
162                 return false;
163             }
164         } else if ((oneByte >= textMin) && (oneByte <= textMax)) {
165             if (!mmsBodyPartHeader_.DecodeApplicationHeader(decodeBuffer, headerLen)) {
166                 TELEPHONY_LOGE("Decode Body Part DecodeApplicationHeader Error.");
167                 return false;
168             }
169         } else {
170             TELEPHONY_LOGE("Header Field[%{pulbic}02X] is not support.", oneByte);
171             return false;
172         }
173     }
174     return true;
175 }
176 
DecodePartBody(MmsDecodeBuffer & decodeBuffer,uint32_t bodyLength)177 bool MmsBodyPart::DecodePartBody(MmsDecodeBuffer &decodeBuffer, uint32_t bodyLength)
178 {
179     uint32_t offset = decodeBuffer.GetCurPosition();
180     if (offset + bodyLength > decodeBuffer.GetSize()) {
181         TELEPHONY_LOGE("Decode Body Part buffer size err.");
182         return false;
183     }
184     if (bodyLength > MAX_MMS_MSG_PART_LEN) {
185         TELEPHONY_LOGE("Decode Body Part body length err.");
186         return false;
187     }
188 
189     std::unique_ptr<char[]> bodyPartBuffer = decodeBuffer.ReadDataBuffer(offset, bodyLength);
190     if (bodyPartBuffer == nullptr) {
191         TELEPHONY_LOGE("Decode Body Part buffer is null.");
192         return false;
193     }
194 
195     std::string transferEncoding;
196     if (!mmsBodyPartHeader_.GetContentTransferEncoding(transferEncoding)) {
197         TELEPHONY_LOGE("bodyPartHeader GetContentTransferEncoding Error");
198         return false;
199     }
200 
201     std::string encodebuffer = "";
202     std::string encodeString(bodyPartBuffer.get(), bodyLength);
203     if (transferEncoding == ENCODE_BASE64) {
204         encodebuffer = MmsBase64::Decode(encodeString);
205     } else if (transferEncoding == ENCODE_QUOTED_PRINTABLE) {
206         MmsQuotedPrintable::Decode(encodeString, encodebuffer);
207     }
208 
209     if (encodebuffer.length()) {
210         bodyLen_ = 0;
211         uint32_t tempLen = encodebuffer.length();
212         pbodyPartBuffer_ = std::make_unique<char[]>(tempLen);
213         if (pbodyPartBuffer_ == nullptr) {
214             TELEPHONY_LOGE("pbodyPartBuffer_ nullptr Error");
215             return false;
216         }
217         if (memcpy_s(pbodyPartBuffer_.get(), tempLen, encodebuffer.data(), tempLen) != EOK) {
218             TELEPHONY_LOGE("Memcpy_s pbodyPartBuffer_ Error");
219             return false;
220         }
221         bodyLen_ = tempLen;
222     } else {
223         pbodyPartBuffer_ = std::move(bodyPartBuffer);
224     }
225     if (!decodeBuffer.IncreasePointer(bodyLength)) {
226         TELEPHONY_LOGE("Decode Body Part IncreasePointer err.");
227         return false;
228     }
229     return true;
230 }
231 
SetAttachment(MmsAttachment & attachment)232 bool MmsBodyPart::SetAttachment(MmsAttachment &attachment)
233 {
234     std::string filePathName = attachment.GetAttachmentFilePath();
235     bool readFileRes = WriteBodyFromFile(filePathName);
236     if (readFileRes) {
237         std::string tempFileName = attachment.GetFileName();
238         if (tempFileName.empty()) {
239             std::size_t pos = filePathName.find_last_of('/');
240             if (pos != std::string::npos) {
241                 tempFileName = filePathName.substr(pos + 1);
242             }
243         }
244         SetFileName(tempFileName);
245     }
246 
247     /** If Read Attatemt Body Buffer From File Error Will Temp Read From Buffer **/
248     if (!readFileRes) {
249         if (!WriteBodyFromAttachmentBuffer(attachment)) {
250             TELEPHONY_LOGE("Attachment Not Any Body Data Error.");
251             return false;
252         }
253         SetFileName(attachment.GetFileName());
254     }
255 
256     if (strFileName_.empty()) {
257         TELEPHONY_LOGE("Get Attachment FileName Invalid error!");
258         return false;
259     }
260     if (!SetContentType(attachment.GetContentType())) {
261         TELEPHONY_LOGE("Mms BodyPart SetContentType is fail!");
262         return false;
263     }
264     if (!SetContentId(attachment.GetContentId())) {
265         TELEPHONY_LOGE("Mms BodyPart GetContentId is fail!");
266         return false;
267     }
268     if (!SetContentLocation(attachment.GetContentLocation())) {
269         TELEPHONY_LOGE("Mms BodyPart SetContentLocation is fail!");
270         return false;
271     }
272     if (!mmsBodyPartHeader_.SetContentTransferEncoding(attachment.GetContentTransferEncoding())) {
273         TELEPHONY_LOGE("Mms BodyPartHeader SetContentTransferEncoding is fail!");
274         return false;
275     }
276     SetSmilFile(attachment.IsSmilFile());
277     SetContentDisposition(attachment.GetContentDisposition());
278     GetContentType().GetContentParam().SetFileName(strFileName_);
279     GetContentType().GetContentParam().SetCharSet(attachment.GetCharSet());
280     return true;
281 }
282 
IsSmilFile()283 bool MmsBodyPart::IsSmilFile()
284 {
285     return isSmilFile_;
286 }
287 
SetSmilFile(bool isSmil)288 void MmsBodyPart::SetSmilFile(bool isSmil)
289 {
290     isSmilFile_ = isSmil;
291 }
292 
SetContentType(std::string strContentType)293 bool MmsBodyPart::SetContentType(std::string strContentType)
294 {
295     return bodyPartContentType_.SetContentType(strContentType);
296 }
297 
GetContentType(std::string & strContentType)298 bool MmsBodyPart::GetContentType(std::string &strContentType)
299 {
300     return bodyPartContentType_.GetContentType(strContentType);
301 }
302 
SetContentId(std::string contentId)303 bool MmsBodyPart::SetContentId(std::string contentId)
304 {
305     return mmsBodyPartHeader_.SetContentId(contentId);
306 }
307 
GetContentId(std::string & contentId)308 bool MmsBodyPart::GetContentId(std::string &contentId)
309 {
310     return mmsBodyPartHeader_.GetContentId(contentId);
311 }
312 
SetContentLocation(std::string contentLocation)313 bool MmsBodyPart::SetContentLocation(std::string contentLocation)
314 {
315     return mmsBodyPartHeader_.SetContentLocation(contentLocation);
316 }
317 
GetContentLocation(std::string & contentLocation)318 bool MmsBodyPart::GetContentLocation(std::string &contentLocation)
319 {
320     return mmsBodyPartHeader_.GetContentLocation(contentLocation);
321 }
322 
SetContentDisposition(std::string contentDisposition)323 bool MmsBodyPart::SetContentDisposition(std::string contentDisposition)
324 {
325     return mmsBodyPartHeader_.SetContentDisposition(contentDisposition);
326 }
327 
GetContentDisposition(std::string & contentDisposition)328 bool MmsBodyPart::GetContentDisposition(std::string &contentDisposition)
329 {
330     return mmsBodyPartHeader_.GetContentDisposition(contentDisposition);
331 }
332 
333 /**
334  * @brief EncodeMmsBodyPart
335  * wap-230-wsp-20010705-a   section:8.5.3 Multipart Entry
336  * HeadersLen   Uintvar
337  * DataLen      Uintvar
338  * ContentType  Multiple octets
339  * Headers      (HeadersLen – length of ContentType) octets
340  * Data         DataLen octets
341  * @param encodeBuffer
342  * @return true
343  * @return false
344  */
EncodeMmsBodyPart(MmsEncodeBuffer & encodeBuffer)345 bool MmsBodyPart::EncodeMmsBodyPart(MmsEncodeBuffer &encodeBuffer)
346 {
347     MmsEncodeBuffer tmpEncodeBuffer;
348     if (!bodyPartContentType_.EncodeMmsBodyPartContentType(tmpEncodeBuffer)) {
349         TELEPHONY_LOGE("Encode MmsBodyPart ContentType Error.");
350         return false;
351     }
352     if (!mmsBodyPartHeader_.EncodeMmsBodyPartHeader(tmpEncodeBuffer)) {
353         TELEPHONY_LOGE("Encode MmsBodyPart Header Error.");
354         return false;
355     }
356     if (!encodeBuffer.EncodeUintvar(tmpEncodeBuffer.GetCurPosition())) {
357         TELEPHONY_LOGE("Encode MmsBodyPart Body Uintvar Error.");
358         return false;
359     }
360     if (!encodeBuffer.EncodeUintvar(bodyLen_)) {
361         TELEPHONY_LOGE("Encode MmsBodyPart Body Len Uintvar Error.");
362         return false;
363     }
364     if (!encodeBuffer.WriteBuffer(tmpEncodeBuffer)) {
365         TELEPHONY_LOGE("Encode MmsBodyPart WriteBuffer Error.");
366         return false;
367     }
368     uint32_t bodyLen = 0;
369     std::unique_ptr<char[]> bodyBuff = ReadBodyPartBuffer(bodyLen);
370     if (!encodeBuffer.WriteBuffer(std::move(bodyBuff), bodyLen)) {
371         return false;
372     }
373     return true;
374 }
375 
DecodeSetFileName()376 void MmsBodyPart::DecodeSetFileName()
377 {
378     std::string fileName = "";
379     GetContentType().GetContentParam().GetFileName(fileName);
380     if (fileName.length() > 0) {
381         strFileName_ = fileName;
382         return;
383     }
384     std::string contentLocation = "";
385     GetPartHeader().GetContentLocation(contentLocation);
386     if (contentLocation.length() > 0) {
387         strFileName_ = contentLocation;
388         return;
389     }
390     std::string contentId = "";
391     GetPartHeader().GetContentId(contentId);
392     if (contentId.length() > 0) {
393         strFileName_ = contentId;
394         return;
395     }
396 
397     const unsigned char timeBufferLen = 64;
398     time_t currentTime = time(nullptr);
399     if (currentTime == -1) {
400         return;
401     }
402     char chCurrentTime[timeBufferLen] = {0};
403     tm *time = localtime(&currentTime);
404     if (currentTime == static_cast<time_t>(-1) || time == nullptr) {
405         TELEPHONY_LOGI("obtain current time Error.");
406     }
407     (void)strftime(chCurrentTime, sizeof(chCurrentTime), "%Y%m%d%H%M%S", time);
408     strFileName_ = chCurrentTime;
409     return;
410 }
411 
WriteBodyFromFile(std::string path)412 bool MmsBodyPart::WriteBodyFromFile(std::string path)
413 {
414     FILE *pFile = nullptr;
415     pFile = fopen(path.c_str(), "rb");
416     if (pFile == nullptr) {
417         TELEPHONY_LOGI("Write Body Part from File notFind, try to use buffer");
418         return false;
419     }
420     (void)fseek(pFile, 0, SEEK_END);
421     long fileLen = ftell(pFile);
422     if (fileLen <= 0 || fileLen > (long)MAX_MMS_MSG_PART_LEN) {
423         (void)fclose(pFile);
424         TELEPHONY_LOGE("fileLen is invalid [%{public}ld]", fileLen);
425         return false;
426     }
427     if (pbodyPartBuffer_) {
428         pbodyPartBuffer_.reset();
429     }
430     pbodyPartBuffer_ = std::make_unique<char[]>(fileLen);
431     if (!pbodyPartBuffer_) {
432         (void)fclose(pFile);
433         TELEPHONY_LOGE("Buffer initialize fail!");
434         return false;
435     }
436 
437     (void)fseek(pFile, 0, SEEK_SET);
438     bodyLen_ = fread(pbodyPartBuffer_.get(), 1, MAX_MMS_MSG_PART_LEN, pFile);
439     (void)fclose(pFile);
440     return true;
441 }
442 
WriteBodyFromAttachmentBuffer(MmsAttachment & attachment)443 bool MmsBodyPart::WriteBodyFromAttachmentBuffer(MmsAttachment &attachment)
444 {
445     if (attachment.GetFileName().empty()) {
446         TELEPHONY_LOGE("Attachment must set fileName, else error!");
447         return false;
448     }
449 
450     uint32_t dataLen = 0;
451     std::unique_ptr<char[]> tempBuffer = nullptr;
452     tempBuffer = attachment.GetDataBuffer(dataLen);
453     if (tempBuffer == nullptr) {
454         TELEPHONY_LOGE("Read Attachment Data Buffer nullptr error.");
455         return false;
456     }
457 
458     if (dataLen <= 0 || dataLen > (long)MAX_MMS_MSG_PART_LEN) {
459         TELEPHONY_LOGE("Attachment DataLen is invalid Error");
460         return false;
461     }
462 
463     if (pbodyPartBuffer_) {
464         pbodyPartBuffer_.reset();
465     }
466     pbodyPartBuffer_ = std::make_unique<char[]>(dataLen);
467     if (!pbodyPartBuffer_) {
468         TELEPHONY_LOGE("Buffer initialize fail!");
469         return false;
470     }
471 
472     if (memcpy_s(pbodyPartBuffer_.get(), dataLen, tempBuffer.get(), dataLen) != EOK) {
473         TELEPHONY_LOGE("Attachment Buffer MemCopy Error.");
474         bodyLen_ = 0;
475         return false;
476     }
477     bodyLen_ = dataLen;
478     return true;
479 }
480 
GetPartFileName()481 std::string MmsBodyPart::GetPartFileName()
482 {
483     return strFileName_;
484 }
485 
SetFileName(std::string fileName)486 void MmsBodyPart::SetFileName(std::string fileName)
487 {
488     strFileName_ = fileName;
489 }
490 
GetContentType()491 MmsContentType &MmsBodyPart::GetContentType()
492 {
493     return bodyPartContentType_;
494 }
495 
GetPartHeader()496 MmsBodyPartHeader &MmsBodyPart::GetPartHeader()
497 {
498     return mmsBodyPartHeader_;
499 }
500 
ReadBodyPartBuffer(uint32_t & len)501 std::unique_ptr<char[]> MmsBodyPart::ReadBodyPartBuffer(uint32_t &len)
502 {
503     len = bodyLen_;
504     std::unique_ptr<char[]> result = std::make_unique<char[]>(len);
505     if (result == nullptr) {
506         TELEPHONY_LOGE("Read BodyPart Buffer MakeUnique Error.");
507         return nullptr;
508     }
509     if (memcpy_s(result.get(), len, pbodyPartBuffer_.get(), len) != EOK) {
510         TELEPHONY_LOGE("Read BodyPart Buffer Memcpy_s Error.");
511         return nullptr;
512     }
513     return result;
514 }
515 } // namespace Telephony
516 } // namespace OHOS
517