1 /*
2  * Copyright (C) 2023 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 "gsm_sms_tpdu_decode.h"
17 
18 #include "gsm_pdu_hex_value.h"
19 #include "gsm_user_data_pdu.h"
20 #include "securec.h"
21 #include "telephony_log_wrapper.h"
22 
23 namespace OHOS {
24 namespace Telephony {
25 using namespace std;
GsmSmsTpduDecode(std::shared_ptr<GsmUserDataPdu> dataCodec,std::shared_ptr<GsmSmsParamCodec> paramCodec,std::shared_ptr<GsmSmsTpduCodec> tpdu)26 GsmSmsTpduDecode::GsmSmsTpduDecode(std::shared_ptr<GsmUserDataPdu> dataCodec,
27     std::shared_ptr<GsmSmsParamCodec> paramCodec, std::shared_ptr<GsmSmsTpduCodec> tpdu)
28 {
29     uDataCodec_ = dataCodec;
30     paramCodec_ = paramCodec;
31     tpdu_ = tpdu;
32 }
33 
~GsmSmsTpduDecode()34 GsmSmsTpduDecode::~GsmSmsTpduDecode() {}
35 
DecodeSubmit(SmsReadBuffer & buffer,struct SmsSubmit * submit)36 bool GsmSmsTpduDecode::DecodeSubmit(SmsReadBuffer &buffer, struct SmsSubmit *submit)
37 {
38     if (submit == nullptr || tpdu_ == nullptr) {
39         TELEPHONY_LOGE("nullptr error.");
40         return false;
41     }
42 
43     tpdu_->DebugTpdu(buffer, PARSE_SUBMIT_TYPE);
44     // TP-RD
45     uint8_t oneByte = 0;
46     if (!buffer.PickOneByte(oneByte)) {
47         TELEPHONY_LOGE("get data error.");
48         return false;
49     }
50     if (oneByte & HEX_VALUE_04) {
51         submit->bRejectDup = false;
52     } else {
53         submit->bRejectDup = true;
54     }
55     // TP-VPF
56     if (!buffer.PickOneByte(oneByte)) {
57         TELEPHONY_LOGE("get data error.");
58         return false;
59     }
60     submit->vpf = static_cast<enum SmsVpf>(oneByte & HEX_VALUE_18);
61     // TP-SRR
62     if (!buffer.PickOneByte(oneByte)) {
63         TELEPHONY_LOGE("get data error.");
64         return false;
65     }
66     if (oneByte & HEX_VALUE_20) {
67         submit->bStatusReport = true;
68     } else {
69         submit->bStatusReport = false;
70     }
71     // TP-UDHI
72     if (!buffer.PickOneByte(oneByte)) {
73         TELEPHONY_LOGE("get data error.");
74         return false;
75     }
76     if (oneByte & HEX_VALUE_40) {
77         submit->bHeaderInd = true;
78     } else {
79         submit->bHeaderInd = false;
80     }
81     return DecodeSubmitPartData(buffer, submit);
82 }
83 
DecodeSubmitPartData(SmsReadBuffer & buffer,struct SmsSubmit * submit)84 bool GsmSmsTpduDecode::DecodeSubmitPartData(SmsReadBuffer &buffer, struct SmsSubmit *submit)
85 {
86     if (paramCodec_ == nullptr || uDataCodec_ == nullptr) {
87         TELEPHONY_LOGE("nullptr error.");
88         return false;
89     }
90     uint8_t oneByte = 0;
91     // TP-RP
92     if (!buffer.PickOneByte(oneByte)) {
93         TELEPHONY_LOGE("get data error.");
94         return false;
95     }
96     if (oneByte & HEX_VALUE_80) {
97         submit->bReplyPath = true;
98     } else {
99         submit->bReplyPath = false;
100     }
101     buffer.MoveForward(1);
102 
103     // TP-MR
104     if (!buffer.ReadByte(oneByte)) {
105         TELEPHONY_LOGE("get data error.");
106         return false;
107     }
108     submit->msgRef = oneByte;
109     // TP-DA
110     if (!paramCodec_->DecodeAddressPdu(buffer, &(submit->destAddress))) {
111         TELEPHONY_LOGE("DecodeAddressPdu Fail");
112         return false;
113     }
114     // TP-PID
115     if (!buffer.ReadByte(oneByte)) {
116         TELEPHONY_LOGE("get data error.");
117         return false;
118     }
119     submit->pid = tpdu_->ParsePid(oneByte);
120     // TP-DCS
121     if (!paramCodec_->DecodeDcsPdu(buffer, &(submit->dcs))) {
122         TELEPHONY_LOGE("DecodeDcsPdu Fail");
123         return false;
124     }
125     // TP-VP
126     if (submit->vpf != SMS_VPF_NOT_PRESENT) {
127         // Decode VP
128     }
129     // TP-UDL & TP-UD
130     bool result =
131         uDataCodec_->DecodeUserDataPdu(buffer, submit->bHeaderInd, submit->dcs.codingScheme, &(submit->userData));
132     TELEPHONY_LOGI("decode submit result : =%{public}d", result);
133     return result;
134 }
135 
DecodePartData(const uint8_t & pTpdu,struct SmsDeliver & deliver)136 void DecodePartData(const uint8_t &pTpdu, struct SmsDeliver &deliver)
137 {
138     /* TP-MMS */
139     if (pTpdu & HEX_VALUE_04) {
140         deliver.bMoreMsg = false;
141     } else {
142         deliver.bMoreMsg = true;
143     }
144     /* TP-SRI */
145     if (pTpdu & HEX_VALUE_20) {
146         deliver.bStatusReport = true;
147     } else {
148         deliver.bStatusReport = false;
149     }
150     /* TP-UDHI */
151     if (pTpdu & HEX_VALUE_40) {
152         deliver.bHeaderInd = true;
153     } else {
154         deliver.bHeaderInd = false;
155     }
156     /* TP-RP */
157     if (pTpdu & HEX_VALUE_80) {
158         deliver.bReplyPath = true;
159     } else {
160         deliver.bReplyPath = false;
161     }
162 }
163 
DecodeDeliver(SmsReadBuffer & buffer,struct SmsDeliver * deliver)164 bool GsmSmsTpduDecode::DecodeDeliver(SmsReadBuffer &buffer, struct SmsDeliver *deliver)
165 {
166     if (deliver == nullptr || tpdu_ == nullptr || paramCodec_ == nullptr) {
167         TELEPHONY_LOGE("nullptr error.");
168         return false;
169     }
170 
171     uint8_t oneByte = 0;
172     if (!buffer.ReadByte(oneByte)) {
173         TELEPHONY_LOGE("get data error.");
174         return false;
175     }
176     tpdu_->DebugTpdu(buffer, PARSE_DELIVER_TYPE);
177     DecodePartData(oneByte, *deliver);
178 
179     /* TP-OA */
180     if (!paramCodec_->DecodeAddressPdu(buffer, &(deliver->originAddress))) {
181         TELEPHONY_LOGE("DecodeAddressPdu fail");
182         return false;
183     }
184 
185     /* TP-PID */
186     if (!buffer.ReadByte(oneByte)) {
187         TELEPHONY_LOGE("get data error.");
188         return false;
189     }
190     deliver->pid = tpdu_->ParsePid(oneByte);
191     /* TP-DCS */
192     if (!paramCodec_->DecodeDcsPdu(buffer, &(deliver->dcs))) {
193         TELEPHONY_LOGE("decode dcs fail.");
194         return false;
195     }
196     /* Support KSC5601 :: Coding group bits == 0x84 */
197     if (!buffer.PickOneByteFromIndex(buffer.GetIndex() - 1, oneByte)) {
198         TELEPHONY_LOGE("get data error.");
199         return false;
200     }
201     if (oneByte == HEX_VALUE_84) {
202         deliver->dcs.codingScheme = DATA_CODING_EUCKR;
203     }
204     return DecodeDeliverPartData(buffer, deliver);
205 }
206 
DecodeDeliverPartData(SmsReadBuffer & buffer,struct SmsDeliver * deliver)207 bool GsmSmsTpduDecode::DecodeDeliverPartData(SmsReadBuffer &buffer, struct SmsDeliver *deliver)
208 {
209     if (uDataCodec_ == nullptr) {
210         TELEPHONY_LOGE("nullptr error.");
211         return false;
212     }
213 
214     if (deliver->pid == HEX_VALUE_20 && deliver->originAddress.ton == TYPE_ALPHA_NUMERIC) {
215         int32_t setType = -1;
216         int32_t indType = -1;
217         bool voicemail = paramCodec_->CheckVoicemail(buffer, &setType, &indType);
218         if (voicemail) {
219             deliver->dcs.bMWI = true;
220             if (setType == 0) {
221                 deliver->dcs.bIndActive = false;
222             } else {
223                 deliver->dcs.bIndActive = true;
224             }
225             if (indType == 0) {
226                 deliver->dcs.indType = SMS_VOICE_INDICATOR;
227             } else if (indType == 1) {
228                 deliver->dcs.indType = SMS_VOICE2_INDICATOR;
229             }
230         }
231     }
232 
233     /* TP-SCTS */
234     if (!paramCodec_->DecodeTimePdu(buffer, &(deliver->timeStamp))) {
235         TELEPHONY_LOGE("decode time fail.");
236         return false;
237     }
238     /* TP-UD */
239     bool result = uDataCodec_->DecodeUserDataPdu(
240         buffer, deliver->bHeaderInd, deliver->dcs.codingScheme, &(deliver->userData), &(deliver->udData));
241     if (!result) {
242         TELEPHONY_LOGE("decode delivery fail.");
243     }
244     return result;
245 }
246 
DecodeStatusReport(SmsReadBuffer & buffer,struct SmsStatusReport * statusRep)247 bool GsmSmsTpduDecode::DecodeStatusReport(SmsReadBuffer &buffer, struct SmsStatusReport *statusRep)
248 {
249     /* TP-MMS */
250     if (statusRep == nullptr || paramCodec_ == nullptr) {
251         TELEPHONY_LOGE("nullptr error.");
252         return false;
253     }
254 
255     uint8_t oneByte = 0;
256     if (!buffer.PickOneByte(oneByte)) {
257         TELEPHONY_LOGE("get data error.");
258         return false;
259     }
260     statusRep->bMoreMsg = (oneByte & HEX_VALUE_04) ? false : true;
261     /* TP-SRQ */
262 
263     if (!buffer.PickOneByte(oneByte)) {
264         TELEPHONY_LOGE("get data error.");
265         return false;
266     }
267     statusRep->bStatusReport = (oneByte & HEX_VALUE_20) ? true : false;
268     /* TP-UDHI */
269     if (!buffer.ReadByte(oneByte)) {
270         TELEPHONY_LOGE("get data error.");
271         return false;
272     }
273     statusRep->bHeaderInd = (oneByte & HEX_VALUE_40) ? true : false;
274     /* TP-MR */
275     if (!buffer.ReadByte(oneByte)) {
276         TELEPHONY_LOGE("get data error.");
277         return false;
278     }
279     statusRep->msgRef = oneByte;
280     /* TP-RA */
281 
282     if (!paramCodec_->DecodeAddressPdu(buffer, &(statusRep->recipAddress))) {
283         TELEPHONY_LOGE("decode addr fail.");
284         return false;
285     }
286 
287     /* TP-SCTS */
288     /* Decode timestamp */
289     if (!paramCodec_->DecodeTimePdu(buffer, &(statusRep->timeStamp))) {
290         TELEPHONY_LOGE("decode time fail.");
291         return false;
292     }
293     return DecodeStatusReportPartData(buffer, statusRep);
294 }
295 
DecodeStatusReportPartData(SmsReadBuffer & buffer,struct SmsStatusReport * statusRep)296 bool GsmSmsTpduDecode::DecodeStatusReportPartData(SmsReadBuffer &buffer, struct SmsStatusReport *statusRep)
297 {
298     /* TP-DT */
299     /* Decode timestamp */
300     if (!paramCodec_->DecodeTimePdu(buffer, &(statusRep->dischargeTime))) {
301         TELEPHONY_LOGE("decode time fail.");
302         return false;
303     }
304     /* TP-Status */
305     uint8_t oneByte = 0;
306     if (!buffer.ReadByte(oneByte)) {
307         TELEPHONY_LOGE("get data error.");
308         return false;
309     }
310     statusRep->status = oneByte;
311     /* TP-PI */
312     if (!buffer.ReadByte(oneByte)) {
313         TELEPHONY_LOGE("no pdu data remains.");
314         return true;
315     }
316     statusRep->paramInd = oneByte;
317     /* No Parameters */
318     if (statusRep->paramInd == 0) {
319         statusRep->pid = SMS_NORMAL_PID;
320         statusRep->dcs.bCompressed = false;
321         statusRep->dcs.bMWI = false;
322         statusRep->dcs.bIndActive = false;
323         statusRep->dcs.msgClass = SMS_CLASS_UNKNOWN;
324         statusRep->dcs.codingScheme = DATA_CODING_7BIT;
325         statusRep->dcs.codingGroup = CODING_GENERAL_GROUP;
326         statusRep->dcs.indType = SMS_OTHER_INDICATOR;
327         statusRep->userData.headerCnt = 0;
328         statusRep->userData.length = 0;
329         int ret = memset_s(statusRep->userData.data, sizeof(statusRep->userData.data), 0x00, MAX_USER_DATA_LEN + 1);
330         if (ret != EOK) {
331             TELEPHONY_LOGE("memset_s error.");
332             return false;
333         }
334     }
335     return DecodeStatusReportData(buffer, statusRep);
336 }
337 
DecodeStatusReportData(SmsReadBuffer & buffer,struct SmsStatusReport * statusRep)338 bool GsmSmsTpduDecode::DecodeStatusReportData(SmsReadBuffer &buffer, struct SmsStatusReport *statusRep)
339 {
340     if (tpdu_ == nullptr || uDataCodec_ == nullptr) {
341         TELEPHONY_LOGE("nullptr error.");
342         return false;
343     }
344 
345     /* TP-PID */
346     if (statusRep->paramInd & HEX_VALUE_01) {
347         uint8_t oneByte = 0;
348         if (!buffer.ReadByte(oneByte)) {
349             TELEPHONY_LOGE("get data error.");
350             return false;
351         }
352         statusRep->pid = tpdu_->ParsePid(oneByte);
353     }
354     /* TP-DCS */
355     if (statusRep->paramInd & HEX_VALUE_02) {
356         if (!paramCodec_->DecodeDcsPdu(buffer, &(statusRep->dcs))) {
357             TELEPHONY_LOGE("decode dcs fail.");
358             return false;
359         }
360     }
361     /* TP-UDL & TP-UD */
362     bool result = true;
363     if (statusRep->paramInd & HEX_VALUE_04) {
364         /* Decode User Data */
365         result = uDataCodec_->DecodeUserDataPdu(
366             buffer, statusRep->bHeaderInd, statusRep->dcs.codingScheme, &(statusRep->userData));
367     }
368     TELEPHONY_LOGI("decode status result : =%{public}d", result);
369     return result;
370 }
371 } // namespace Telephony
372 } // namespace OHOS