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.h"
16
17 #include "mms_decode_buffer.h"
18 #include "telephony_log_wrapper.h"
19
20 namespace OHOS {
21 namespace Telephony {
22 using namespace std;
MmsBody()23 MmsBody::MmsBody() : bodyEntrys_(0) {}
24
DumpMmsBody()25 void MmsBody::DumpMmsBody()
26 {
27 for (auto bodyPart : mmsBodyParts_) {
28 bodyPart.DumpMmsBodyPart();
29 }
30 }
31
32 /**
33 * @brief DecodeMultipart
34 * wap-230-wsp-20010705-a.pdf section:8.5 Multipart Data
35 * The application/vnd.wap.multipart content type consists of a header followed by 0 or more entries.
36 * @param decodeBuffer
37 * @return true
38 * @return false
39 */
DecodeMultipart(MmsDecodeBuffer & decodeBuffer)40 bool MmsBody::DecodeMultipart(MmsDecodeBuffer &decodeBuffer)
41 {
42 uint32_t nEntries = 0;
43 uint32_t length = 0;
44 if (!decodeBuffer.DecodeUintvar(nEntries, length)) {
45 TELEPHONY_LOGE("Body decode multipart uintvar fail.");
46 return false;
47 }
48 bodyEntrys_ = nEntries;
49 TELEPHONY_LOGE("attachment number: %{public}u", nEntries);
50 while (nEntries) {
51 MmsBodyPart bodyPart;
52 if (!bodyPart.DecodePart(decodeBuffer, nEntries)) {
53 TELEPHONY_LOGE("Body decode multipart DecodePart fail.");
54 return false;
55 }
56 mmsBodyParts_.push_back(bodyPart);
57 nEntries--;
58 }
59 return true;
60 }
61
DecodeMmsBody(MmsDecodeBuffer & decodeBuffer,MmsHeader & header)62 bool MmsBody::DecodeMmsBody(MmsDecodeBuffer &decodeBuffer, MmsHeader &header)
63 {
64 unsigned char msgType = 0;
65 if (!header.GetOctetValue(MMS_MESSAGE_TYPE, msgType)) {
66 TELEPHONY_LOGE("Body decode GetOctetValue fail.");
67 return false;
68 }
69
70 if (msgType != MMS_MSGTYPE_SEND_REQ && msgType != MMS_MSGTYPE_RETRIEVE_CONF) {
71 // no body
72 TELEPHONY_LOGI("this mms message type no body");
73 return true;
74 }
75 std::string contentType = "";
76 header.GetHeaderContentType().GetContentType(contentType);
77 switch (static_cast<ContentTypes>(MmsContentType::GetContentTypeFromString(contentType))) {
78 case ContentTypes::APPLICATION_VND_WAP_MULTIPART_MIXED:
79 case ContentTypes::APPLICATION_VND_WAP_MULTIPART_RELATED:
80 case ContentTypes::APPLICATION_VND_WAP_MULTIPART_ALTERNATIVE:
81 case ContentTypes::MULTIPART_MIXED:
82 case ContentTypes::MULTIPART_ALTERNATIVE:
83 case ContentTypes::APPLICATION_VND_OMA_DRM_MESSAGE:
84 case ContentTypes::APPLICATION_VND_OMA_DRM_CONTENT:
85 return DecodeMultipart(decodeBuffer);
86 default:
87 break;
88 }
89 return true;
90 }
91
EncodeMmsBody(MmsEncodeBuffer & encodeBuffer)92 bool MmsBody::EncodeMmsBody(MmsEncodeBuffer &encodeBuffer)
93 {
94 uint32_t partsNum = GetBodyPartCount();
95 if (!encodeBuffer.EncodeUintvar(partsNum)) {
96 TELEPHONY_LOGE("Body encode uintvar fail.");
97 return false;
98 }
99 for (uint32_t i = 0; i < partsNum; i++) {
100 if (!mmsBodyParts_.at(i).EncodeMmsBodyPart(encodeBuffer)) {
101 TELEPHONY_LOGE("Body encode EncodeMmsBodyPart fail.");
102 return false;
103 }
104 }
105 return true;
106 }
107
108 /**
109 * @brief EncodeMmsHeaderContentType
110 * wap-230-wsp-20010705-a section:8.4.2.24 Content type field section:8.4.2.1 Basic rules
111 * Content-type-value = Constrained-media | Content-general-form
112 * Constrained-media = Constrained-encoding
113 * Constrained-encoding = Extension-Media | Short-integer
114 * Extension-media = *TEXT End-of-string
115 * Content-general-form = Value-length Media-type
116 * Media-type = (Well-known-media | Extension-Media) *(Parameter)
117 * Well-known-media = Integer-value
118 * Parameter = Typed-parameter | Untyped-parameter
119 * @param mmsHeader
120 * @param encodeBuffer
121 * @return true
122 * @return false
123 */
EncodeMmsHeaderContentType(MmsHeader & mmsHeader,MmsEncodeBuffer & encodeBuffer)124 bool MmsBody::EncodeMmsHeaderContentType(MmsHeader &mmsHeader, MmsEncodeBuffer &encodeBuffer)
125 {
126 if (!encodeBuffer.WriteByte((int8_t)(MMS_CONTENT_TYPE))) {
127 TELEPHONY_LOGE("Body encode WriteByte fail.");
128 return false;
129 }
130 std::string strContentType = "";
131 mmsHeader.GetHeaderContentType().GetContentType(strContentType);
132 if (!strContentType.length()) {
133 TELEPHONY_LOGE("Body encode ContentType length is zero.");
134 return false;
135 }
136 if (!mmsHeader.IsHaveBody() || GetBodyPartCount() == 0) {
137 if (!encodeBuffer.EncodeText(strContentType)) {
138 TELEPHONY_LOGE("Body encode ContentType EncodeText fail.");
139 return false;
140 }
141 return true;
142 }
143
144 MmsEncodeBuffer tmpEncodeBuffer;
145 if (!tmpEncodeBuffer.EncodeText(strContentType)) {
146 TELEPHONY_LOGE("Body encode ContentType EncodeText fail.");
147 return false;
148 }
149 // parameter
150 mmsHeader.GetHeaderContentType().EncodeTextField(tmpEncodeBuffer);
151 mmsHeader.GetHeaderContentType().EncodeTypeField(tmpEncodeBuffer);
152 mmsHeader.GetHeaderContentType().EncodeCharsetField(tmpEncodeBuffer);
153
154 if (!encodeBuffer.EncodeValueLength(tmpEncodeBuffer.GetCurPosition())) {
155 TELEPHONY_LOGE("Body encode ContentType EncodeValueLength fail.");
156 return false;
157 }
158 if (!encodeBuffer.WriteBuffer(tmpEncodeBuffer)) {
159 TELEPHONY_LOGE("Body encode ContentType WriteBuffer fail.");
160 return false;
161 }
162 return true;
163 }
164
GetBodyPartCount()165 uint32_t MmsBody::GetBodyPartCount()
166 {
167 return mmsBodyParts_.size();
168 }
169
IsContentLocationPartExist(std::string contentLocation)170 bool MmsBody::IsContentLocationPartExist(std::string contentLocation)
171 {
172 for (auto item : mmsBodyParts_) {
173 std::string strlocation = "";
174 item.GetPartHeader().GetContentLocation(strlocation);
175 if (contentLocation == strlocation) {
176 return true;
177 }
178 }
179 return false;
180 }
181
IsContentIdPartExist(std::string contentId)182 bool MmsBody::IsContentIdPartExist(std::string contentId)
183 {
184 for (auto item : mmsBodyParts_) {
185 std::string strId = "";
186 item.GetPartHeader().GetContentId(strId);
187 if (contentId == strId) {
188 return true;
189 }
190 }
191 return false;
192 }
193
IsBodyPartExist(MmsBodyPart & bodyPart)194 bool MmsBody::IsBodyPartExist(MmsBodyPart &bodyPart)
195 {
196 std::string contentId;
197 bodyPart.GetContentId(contentId);
198 if (IsContentIdPartExist(contentId)) {
199 return true;
200 }
201
202 std::string contentLocation;
203 bodyPart.GetContentLocation(contentLocation);
204 if (IsContentLocationPartExist(contentLocation)) {
205 return true;
206 }
207 return false;
208 }
209
GetMmsBodyPart(std::vector<MmsBodyPart> & parts)210 void MmsBody::GetMmsBodyPart(std::vector<MmsBodyPart> &parts)
211 {
212 parts.clear();
213 parts.assign(mmsBodyParts_.begin(), mmsBodyParts_.end());
214 }
215
AddMmsBodyPart(MmsBodyPart & bodyPart)216 bool MmsBody::AddMmsBodyPart(MmsBodyPart &bodyPart)
217 {
218 if (bodyPart.IsSmilFile() && bHaveSmilPart_) {
219 TELEPHONY_LOGE("Not allowed to add more than two SmilPart File error.");
220 return false;
221 }
222
223 if (bodyPart.IsSmilFile()) {
224 mmsBodyParts_.insert(mmsBodyParts_.begin(), bodyPart);
225 bHaveSmilPart_ = true;
226 } else {
227 mmsBodyParts_.push_back(bodyPart);
228 }
229 return true;
230 }
231 } // namespace Telephony
232 } // namespace OHOS
233