• 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_ - static_cast<uint32_t>(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     struct tm tmInfo;
404     if (memset_s(&tmInfo, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
405         TELEPHONY_LOGE("DisplayTime memset fail.");
406         return;
407     }
408 
409     tm *timeptr = localtime_r(&currentTime, &tmInfo);
410     if (currentTime == static_cast<time_t>(-1) || timeptr == nullptr) {
411         TELEPHONY_LOGI("obtain current time Error.");
412     }
413     if (timeptr != nullptr) {
414         (void)strftime(chCurrentTime, sizeof(chCurrentTime), "%Y%m%d%H%M%S", timeptr);
415     }
416     strFileName_ = chCurrentTime;
417     return;
418 }
419 
WriteBodyFromFile(std::string path)420 bool MmsBodyPart::WriteBodyFromFile(std::string path)
421 {
422     FILE *pFile = nullptr;
423     char realPath[PATH_MAX] = {0};
424     if (path.empty() || realpath(path.c_str(), realPath) == NULL) {
425         TELEPHONY_LOGE("path or realPath is NULL");
426         return false;
427     }
428     pFile = fopen(realPath, "rb");
429     if (pFile == nullptr) {
430         TELEPHONY_LOGI("Write Body Part from File notFind, try to use buffer");
431         return false;
432     }
433     (void)fseek(pFile, 0, SEEK_END);
434     long fileLen = ftell(pFile);
435     if (fileLen <= 0 || fileLen > (long)MAX_MMS_MSG_PART_LEN) {
436         (void)fclose(pFile);
437         TELEPHONY_LOGE("fileLen is invalid [%{public}ld]", fileLen);
438         return false;
439     }
440     if (pbodyPartBuffer_) {
441         pbodyPartBuffer_.reset();
442     }
443     pbodyPartBuffer_ = std::make_unique<char[]>(fileLen);
444     if (!pbodyPartBuffer_) {
445         (void)fclose(pFile);
446         TELEPHONY_LOGE("Buffer initialize fail!");
447         return false;
448     }
449 
450     (void)fseek(pFile, 0, SEEK_SET);
451     bodyLen_ = fread(pbodyPartBuffer_.get(), 1, MAX_MMS_MSG_PART_LEN, pFile);
452     (void)fclose(pFile);
453     return true;
454 }
455 
WriteBodyFromAttachmentBuffer(MmsAttachment & attachment)456 bool MmsBodyPart::WriteBodyFromAttachmentBuffer(MmsAttachment &attachment)
457 {
458     if (attachment.GetFileName().empty()) {
459         TELEPHONY_LOGE("Attachment must set fileName, else error!");
460         return false;
461     }
462 
463     uint32_t dataLen = 0;
464     std::unique_ptr<char[]> tempBuffer = nullptr;
465     tempBuffer = attachment.GetDataBuffer(dataLen);
466     if (tempBuffer == nullptr) {
467         TELEPHONY_LOGE("Read Attachment Data Buffer nullptr error.");
468         return false;
469     }
470 
471     if (dataLen == 0 || dataLen > MAX_MMS_MSG_PART_LEN) {
472         TELEPHONY_LOGE("Attachment DataLen is invalid Error");
473         return false;
474     }
475 
476     if (pbodyPartBuffer_) {
477         pbodyPartBuffer_.reset();
478     }
479     pbodyPartBuffer_ = std::make_unique<char[]>(dataLen);
480     if (!pbodyPartBuffer_) {
481         TELEPHONY_LOGE("Buffer initialize fail!");
482         return false;
483     }
484 
485     if (memcpy_s(pbodyPartBuffer_.get(), dataLen, tempBuffer.get(), dataLen) != EOK) {
486         TELEPHONY_LOGE("Attachment Buffer MemCopy Error.");
487         bodyLen_ = 0;
488         return false;
489     }
490     bodyLen_ = dataLen;
491     return true;
492 }
493 
GetPartFileName()494 std::string MmsBodyPart::GetPartFileName()
495 {
496     return strFileName_;
497 }
498 
SetFileName(std::string fileName)499 void MmsBodyPart::SetFileName(std::string fileName)
500 {
501     strFileName_ = fileName;
502 }
503 
GetContentType()504 MmsContentType &MmsBodyPart::GetContentType()
505 {
506     return bodyPartContentType_;
507 }
508 
GetPartHeader()509 MmsBodyPartHeader &MmsBodyPart::GetPartHeader()
510 {
511     return mmsBodyPartHeader_;
512 }
513 
ReadBodyPartBuffer(uint32_t & len)514 std::unique_ptr<char[]> MmsBodyPart::ReadBodyPartBuffer(uint32_t &len)
515 {
516     len = bodyLen_;
517     std::unique_ptr<char[]> result = std::make_unique<char[]>(len);
518     if (result == nullptr) {
519         TELEPHONY_LOGE("Read BodyPart Buffer MakeUnique Error.");
520         return nullptr;
521     }
522     if (memcpy_s(result.get(), len, pbodyPartBuffer_.get(), len) != EOK) {
523         TELEPHONY_LOGE("Read BodyPart Buffer Memcpy_s Error.");
524         return nullptr;
525     }
526     return result;
527 }
528 } // namespace Telephony
529 } // namespace OHOS
530