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_encode_buffer.h"
17
18 #include "mms_decode_buffer.h"
19 #include "securec.h"
20 #include "telephony_log_wrapper.h"
21
22 namespace OHOS {
23 namespace Telephony {
24 using namespace std;
25 /**
26 * @brief DecodeInteger
27 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
28 * Uintvar-integer = 1*5 OCTET
29 * @param value
30 * @return true
31 * @return false
32 */
EncodeUintvar(uint32_t value)33 bool MmsEncodeBuffer::EncodeUintvar(uint32_t value)
34 {
35 const uint8_t setNotHighestBitZero = 0x80;
36 const uint8_t setHighestBitZero = 0x7f;
37 const uint8_t shiftUintBits = 7;
38 char reversed[8] = {0};
39 int len = 1;
40 reversed[0] = (char)value & setHighestBitZero;
41 value = value >> shiftUintBits;
42 while (value > 0) {
43 reversed[len] = setNotHighestBitZero | (value & setHighestBitZero);
44 len++;
45 value = value >> shiftUintBits;
46 }
47
48 int j = 0;
49 for (j = 0; j < len; j++) {
50 if (!WriteByte(reversed[len - j - 1])) {
51 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
52 return false;
53 }
54 }
55 return true;
56 }
57
WriteByte(uint8_t value)58 bool MmsEncodeBuffer::WriteByte(uint8_t value)
59 {
60 if (curPosition_ >= CODE_BUFFER_MAX_SIZE) {
61 TELEPHONY_LOGE("Encode buffer current position invalid.");
62 return false;
63 }
64 pduBuffer_[curPosition_++] = value;
65 return true;
66 }
67
WriteBuffer(MmsEncodeBuffer & buff)68 bool MmsEncodeBuffer::WriteBuffer(MmsEncodeBuffer &buff)
69 {
70 uint32_t len = buff.GetCurPosition();
71 if (curPosition_ + len >= CODE_BUFFER_MAX_SIZE) {
72 TELEPHONY_LOGE("Encode buffer current position invalid.");
73 return false;
74 }
75 if (memcpy_s(pduBuffer_.get() + curPosition_, len, buff.pduBuffer_.get(), len) != EOK) {
76 TELEPHONY_LOGE("Encode buffer memcpy_s fail.");
77 return false;
78 }
79 curPosition_ += buff.GetCurPosition();
80 return true;
81 }
82
WriteBuffer(std::unique_ptr<char[]> input,uint32_t length)83 bool MmsEncodeBuffer::WriteBuffer(std::unique_ptr<char[]> input, uint32_t length)
84 {
85 if (input == nullptr) {
86 TELEPHONY_LOGE("Encode buffer input is null.");
87 return false;
88 }
89
90 if (curPosition_ + length >= CODE_BUFFER_MAX_SIZE) {
91 TELEPHONY_LOGE("Encode buffer current position invalid.");
92 return false;
93 }
94 if (memcpy_s(pduBuffer_.get() + curPosition_, length, input.get(), length) != EOK) {
95 TELEPHONY_LOGE("Encode buffer memcpy_s fail.");
96 return false;
97 }
98 curPosition_ += length;
99 return true;
100 }
101
102 /**
103 * @brief EncodeShortLength
104 * wap-230-wsp-20010705-a.pdf section:8.4.2.2 Length
105 * Short-length = <Any octet 0-30>
106 * @param value
107 * @return true
108 * @return false
109 */
EncodeShortLength(uint8_t value)110 bool MmsEncodeBuffer::EncodeShortLength(uint8_t value)
111 {
112 const uint8_t minShortLength = 30;
113 if (value > minShortLength) {
114 TELEPHONY_LOGE("Encode buffer value invalid.");
115 return false;
116 }
117 if (!WriteByte(value)) {
118 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
119 return false;
120 }
121 return true;
122 }
123
124 /**
125 * @brief EncodeShortInteger
126 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
127 * Short-integer = OCTET
128 * Integers in range 0-127 shall be encoded as a one octet value with
129 * the most significant bit set to one (1xxx xxxx) and with the value
130 * in the remaining least significant bits
131 * @param value
132 * @return true
133 * @return false
134 */
EncodeShortInteger(uint8_t value)135 bool MmsEncodeBuffer::EncodeShortInteger(uint8_t value)
136 {
137 const uint8_t setHighestBitOne = 0x80;
138 if (!WriteByte(value | setHighestBitOne)) {
139 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
140 return false;
141 }
142 return true;
143 }
144
145 /**
146 * @brief EncodeOctet
147 * wap-230-wsp-20010705-a section:8.1.2 Variable Length Unsigned Integers
148 * octet 8 bits of opaque data
149 * @param value
150 * @return true
151 * @return false
152 */
EncodeOctet(uint8_t value)153 bool MmsEncodeBuffer::EncodeOctet(uint8_t value)
154 {
155 if (!WriteByte(value)) {
156 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
157 return false;
158 }
159 return true;
160 }
161
162 /**
163 * @brief EncodeValueLength
164 * wap-230-wsp-20010705-a section:8.4.2.2 Length
165 * value-length = short-length | (Length-quote Length)
166 * short-length = <Any octet 0-30>
167 * Length-quote = <Octet 31>
168 * (Length-quote Length) = Length-quote + Uintvar-length
169 * @param value
170 * @return true
171 * @return false
172 */
EncodeValueLength(uint32_t value)173 bool MmsEncodeBuffer::EncodeValueLength(uint32_t value)
174 {
175 const uint8_t lengthQuote = 0x1f;
176 const uint32_t maxShortLength = 30;
177
178 if (value <= maxShortLength) {
179 return EncodeShortLength(value);
180 }
181 if (!WriteByte(lengthQuote)) {
182 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
183 return false;
184 }
185 if (!EncodeUintvar(value)) {
186 TELEPHONY_LOGE("Encode buffer EncodeUintvar fail.");
187 return false;
188 }
189 return true;
190 }
191
EncodeInteger(uint32_t value)192 bool MmsEncodeBuffer::EncodeInteger(uint32_t value)
193 {
194 const uint32_t maxShortInteger = 127;
195 if (value <= maxShortInteger) {
196 return EncodeShortInteger(value);
197 } else {
198 return EncodeLongInteger(value);
199 }
200 return true;
201 }
202
203 /**
204 * @brief EncodeLongInteger
205 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
206 * Long-integer = [Short-length] [Multi-octet-integer]
207 * Short-length = 1 byte
208 * Multi-octet-integer = <Short-length> bytes
209 * @param value
210 * @return true
211 * @return false
212 */
EncodeLongInteger(uint64_t value)213 bool MmsEncodeBuffer::EncodeLongInteger(uint64_t value)
214 {
215 const uint64_t getLast8Bit = 0x000000FF;
216 const uint8_t rightMoveBits = 8;
217
218 uint64_t temp = value;
219 uint8_t count = 0;
220 uint8_t result[8] = {0};
221 while (temp > 0) {
222 result[count] = temp & getLast8Bit;
223 temp = temp >> rightMoveBits;
224 count++;
225 }
226
227 if (value == 0) {
228 count = 1;
229 }
230 if (!WriteByte(count)) {
231 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
232 return false;
233 }
234
235 for (int16_t i = static_cast<int16_t>(count) - 1; i >= 0; i--) {
236 if (!WriteByte(result[i])) {
237 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
238 return false;
239 }
240 }
241 return true;
242 }
243
244 /**
245 * @brief EncodeText
246 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
247 * Text-string = [Quote] *TEXT End-of-string
248 * Quote = <Octet 127>
249 * End-of-string = <Octet 0>
250 * @param value
251 * @return true
252 * @return false
253 */
EncodeText(std::string value)254 bool MmsEncodeBuffer::EncodeText(std::string value)
255 {
256 const uint8_t quoteText = 0x7f;
257 if (value.empty()) {
258 TELEPHONY_LOGI("Encode buffer value is empty string.");
259 return true;
260 }
261
262 if (value.at(0) > quoteText) {
263 if (!WriteByte(quoteText)) {
264 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
265 return false;
266 }
267 }
268 for (std::size_t i = 0; i < value.length(); i++) {
269 if (!WriteByte(value.at(i))) {
270 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
271 return false;
272 }
273 }
274 if (!WriteByte(0)) {
275 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
276 return false;
277 }
278 return true;
279 }
280
281 /**
282 * @brief EncodeQuotedText
283 * wap-230-wsp-20010705-a section:8.4.2.1 Basic rules
284 * Quoted-string = <Octet 34> *TEXT End-of-string
285 * The TEXT encodes an RFC2616 Quoted-string with the enclosing quotation-marks <"> removed
286 * @param value
287 * @return true
288 * @return false
289 */
EncodeQuotedText(std::string value)290 bool MmsEncodeBuffer::EncodeQuotedText(std::string value)
291 {
292 if (value.empty()) {
293 return true;
294 }
295 if (!WriteByte('\"')) {
296 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
297 return false;
298 }
299 for (std::size_t i = 0; i < value.length(); i++) {
300 if (!WriteByte(value.at(i))) {
301 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
302 return false;
303 }
304 }
305 if (!WriteByte(0)) {
306 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
307 return false;
308 }
309 return true;
310 }
311
312 /**
313 * @brief EncodeTokenText
314 * wap-230-wsp-20010705-a section:8.4.2.2 Length
315 * Token-text = Token End-of-string
316 * End-of-string = <Octet 0>
317 * @param value
318 * @return true
319 * @return false
320 */
EncodeTokenText(std::string value)321 bool MmsEncodeBuffer::EncodeTokenText(std::string value)
322 {
323 if (value.empty()) {
324 return true;
325 }
326 for (std::size_t i = 0; i < value.length(); i++) {
327 if (!MmsDecodeBuffer::CharIsToken(value.at(i))) {
328 TELEPHONY_LOGE("Encode buffer EncodeTokenText fail.");
329 return false;
330 }
331 }
332 for (std::size_t i = 0; i < value.length(); i++) {
333 if (!WriteByte(value.at(i))) {
334 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
335 return false;
336 }
337 }
338 if (!WriteByte(0)) {
339 TELEPHONY_LOGE("Encode buffer WriteByte fail.");
340 return false;
341 }
342 return true;
343 }
344 } // namespace Telephony
345 } // namespace OHOS
346