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