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