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_cb_umts_codec.h" 17 18#include "cdma_sms_common.h" 19#include "gsm_pdu_hex_value.h" 20#include "securec.h" 21#include "sms_common_utils.h" 22#include "string_utils.h" 23#include "telephony_log_wrapper.h" 24#include "text_coder.h" 25 26namespace OHOS { 27namespace Telephony { 28static constexpr uint8_t SMS_BYTE_BIT = 8; 29static constexpr uint8_t GSM_CODE_BIT = 7; 30static constexpr uint8_t MAX_PAGE_PDU_LEN = 82; 31 32GsmCbUmtsCodec::GsmCbUmtsCodec(std::shared_ptr<GsmCbCodec::GsmCbMessageHeader> header, 33 std::shared_ptr<GsmCbPduDecodeBuffer> buffer, std::shared_ptr<GsmCbCodec> cbCodec) 34{ 35 cbHeader_ = header; 36 cbPduBuffer_ = buffer; 37 cbCodec_ = cbCodec; 38} 39 40GsmCbUmtsCodec::~GsmCbUmtsCodec() {} 41 42/** 43 * refer to 3GPP TS 23.041 V4.1.0 9.4.2.1 General Description 44 * refer to 3GPP TS 23.041 V4.1.0 9.4.2.2 Message Parameter 45 */ 46bool GsmCbUmtsCodec::Decode3gHeader() 47{ 48 if (cbPduBuffer_ == nullptr || cbHeader_ == nullptr || cbCodec_ == nullptr || cbPduBuffer_->GetSize() == 0) { 49 TELEPHONY_LOGE("CB pdu data error."); 50 return false; 51 } 52 53 cbPduBuffer_->IncreasePointer(1); 54 uint8_t oneByte = 0; 55 if (!cbPduBuffer_->GetOneByte(oneByte)) { 56 TELEPHONY_LOGE("get data error."); 57 return false; 58 } 59 uint8_t temp = oneByte; 60 if (!cbPduBuffer_->GetOneByte(oneByte)) { 61 TELEPHONY_LOGE("get data error."); 62 return false; 63 } 64 cbHeader_->msgId = (temp << HEX_VALUE_08) | oneByte; 65 bool isEtws; 66 cbCodec_->IsEtwsMessage(isEtws); 67 if (isEtws) { 68 cbHeader_->cbMsgType = GsmCbCodec::GSM_ETWS; 69 } 70 if (!cbPduBuffer_->GetOneByte(oneByte)) { 71 TELEPHONY_LOGE("get data error."); 72 return false; 73 } 74 temp = oneByte; 75 cbHeader_->serialNum.geoScope = (temp & HEX_VALUE_C0) >> HEX_VALUE_06; 76 cbHeader_->serialNum.msgCode = (temp & HEX_VALUE_3F) << HEX_VALUE_04; 77 78 if (!cbPduBuffer_->GetOneByte(oneByte)) { 79 TELEPHONY_LOGE("get data error."); 80 return false; 81 } 82 temp = oneByte; 83 cbHeader_->serialNum.msgCode |= (temp & HEX_VALUE_F0) >> HEX_VALUE_04; 84 cbHeader_->serialNum.updateNum = temp & HEX_VALUE_0F; 85 86 if (!cbPduBuffer_->GetOneByte(oneByte)) { 87 TELEPHONY_LOGE("get data error."); 88 return false; 89 } 90 uint8_t dcs = oneByte; 91 return Decode3gHeaderPartData(dcs); 92} 93 94bool GsmCbUmtsCodec::Decode3gHeaderPartData(uint8_t dcs) 95{ 96 if (cbCodec_ == nullptr) { 97 TELEPHONY_LOGE("CB pdu data error."); 98 return false; 99 } 100 uint8_t oneByte = 0; 101 if (!cbPduBuffer_->GetOneByte(oneByte)) { 102 TELEPHONY_LOGE("get data error."); 103 return false; 104 } 105 cbHeader_->totalPages = oneByte; 106 107 if (!cbPduBuffer_->GetOneByte(oneByte)) { 108 TELEPHONY_LOGE("get data error."); 109 return false; 110 } 111 unsigned short iosTemp = oneByte; 112 113 if (!cbPduBuffer_->GetOneByte(oneByte)) { 114 TELEPHONY_LOGE("get data error."); 115 return false; 116 } 117 iosTemp |= (oneByte << SMS_BYTE_BIT); 118 cbCodec_->DecodeCbMsgDCS(dcs, iosTemp, cbHeader_->dcs); 119 cbHeader_->langType = cbHeader_->dcs.langType; 120 cbHeader_->recvTime = static_cast<time_t>(cbCodec_->GetRecvTime()); 121 if (cbPduBuffer_->GetCurPosition() >= HEX_VALUE_02) { 122 cbPduBuffer_->SetPointer(cbPduBuffer_->GetCurPosition() - HEX_VALUE_02); 123 } 124 return true; 125} 126 127/** 128 * refer to 3GPP TS 23.041 V4.1.0 9.4.2.2.5 CB Data 129 */ 130bool GsmCbUmtsCodec::Decode3gCbMsg() 131{ 132 if (cbHeader_ == nullptr) { 133 TELEPHONY_LOGE("CB pdu data error."); 134 return false; 135 } 136 137 bool decodeResult = false; 138 switch (cbHeader_->dcs.codingScheme) { 139 case DATA_CODING_7BIT: { 140 decodeResult = Decode3g7Bit(); 141 break; 142 } 143 case DATA_CODING_8BIT: 144 case DATA_CODING_UCS2: { 145 decodeResult = Decode3gUCS2(); 146 break; 147 } 148 default: 149 break; 150 } 151 cbHeader_->totalPages = 1; 152 return decodeResult; 153} 154 155bool GsmCbUmtsCodec::Decode3g7Bit() 156{ 157 if (cbPduBuffer_ == nullptr || cbCodec_ == nullptr || cbPduBuffer_->GetSize() == 0) { 158 TELEPHONY_LOGE("CB pdu data error."); 159 return false; 160 } 161 162 std::vector<unsigned char> dataPdu; 163 cbCodec_->GetPduData(dataPdu); 164 if (dataPdu.size() == 0 || cbPduBuffer_->GetCurPosition() >= cbPduBuffer_->GetSize()) { 165 TELEPHONY_LOGE("dataPdu empty."); 166 return false; 167 } 168 uint16_t pduLen = cbPduBuffer_->GetSize() - cbPduBuffer_->GetCurPosition(); 169 170 const uint8_t *tpdu = dataPdu.data(); 171 for (uint8_t i = 0; i < cbHeader_->totalPages; ++i) { 172 uint16_t pageLenOffset = (i + 1) * MAX_PAGE_PDU_LEN + i; 173 if (pduLen <= pageLenOffset) { 174 TELEPHONY_LOGE("CB Msg Size err [%{public}d]", pduLen); 175 messageRaw_.clear(); 176 return false; 177 } 178 uint16_t dataLen = tpdu[pageLenOffset]; 179 uint16_t offset = (i * MAX_PAGE_PDU_LEN) + i; 180 if (dataLen > MAX_PAGE_PDU_LEN) { 181 TELEPHONY_LOGE("CB Msg Size is over MAX [%{public}d]", dataLen); 182 messageRaw_.clear(); 183 return false; 184 } 185 uint16_t unpackLen = 0; 186 uint8_t pageData[MAX_PAGE_PDU_LEN * SMS_BYTE_BIT / GSM_CODE_BIT] = { 0 }; 187 unpackLen = SmsCommonUtils::Unpack7bitChar( 188 &tpdu[offset], dataLen, 0x00, pageData, MAX_PAGE_PDU_LEN * SMS_BYTE_BIT / GSM_CODE_BIT); 189 for (uint16_t position = 0; position < unpackLen; position++) { 190 messageRaw_.push_back(pageData[position]); 191 } 192 } 193 cbCodec_->SetCbMessageRaw(messageRaw_); 194 return true; 195} 196 197bool GsmCbUmtsCodec::Decode3gUCS2() 198{ 199 if (cbPduBuffer_ == nullptr || cbCodec_ == nullptr || cbPduBuffer_->GetSize() == 0) { 200 TELEPHONY_LOGE("CB pdu data error."); 201 return false; 202 } 203 204 std::vector<unsigned char> dataPdu; 205 cbCodec_->GetPduData(dataPdu); 206 if (dataPdu.size() == 0 || cbPduBuffer_->GetCurPosition() >= cbPduBuffer_->GetSize()) { 207 TELEPHONY_LOGE("dataPdu empty."); 208 return false; 209 } 210 uint16_t pduLen = cbPduBuffer_->GetSize() - cbPduBuffer_->GetCurPosition(); 211 212 uint8_t *tpdu = dataPdu.data(); 213 uint16_t tpduLen = dataPdu.size(); 214 for (uint8_t i = 0; i < cbHeader_->totalPages; ++i) { 215 TELEPHONY_LOGI("cbHeader_->totalPages:%{public}d", cbHeader_->totalPages); 216 uint16_t pageLenOffset = static_cast<uint8_t>((i + 1) * MAX_PAGE_PDU_LEN + i); 217 if (pduLen <= pageLenOffset) { 218 TELEPHONY_LOGE("pageLenOffset invalid."); 219 messageRaw_.clear(); 220 return false; 221 } 222 uint16_t dataLen = 0; 223 uint16_t offset = 0; 224 if (cbHeader_->dcs.iso639Lang[0]) { 225 if (tpdu[pageLenOffset] >= HEX_VALUE_02) { 226 dataLen = tpdu[pageLenOffset] - HEX_VALUE_02; 227 } 228 offset = (i * MAX_PAGE_PDU_LEN) + i + HEX_VALUE_02; 229 } else { 230 dataLen = tpdu[pageLenOffset]; 231 offset = (i * MAX_PAGE_PDU_LEN) + i; 232 } 233 if (dataLen > 0 && dataLen <= MAX_PAGE_PDU_LEN && dataLen < tpduLen) { 234 for (uint8_t position = offset; position < offset + dataLen; position++) { 235 messageRaw_.push_back(static_cast<char>(tpdu[position])); 236 } 237 } 238 } 239 cbCodec_->SetCbMessageRaw(messageRaw_); 240 return true; 241} 242} // namespace Telephony 243} // namespace OHOS