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 "sms_common_utils.h" 17 18#include <ctime> 19#include "securec.h" 20#include "telephony_log_wrapper.h" 21 22namespace OHOS { 23namespace Telephony { 24static constexpr uint8_t SMS_ENCODE_GSM_BIT = 7; 25static constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160; 26static constexpr uint8_t SMS_BYTE_BIT = 8; 27static constexpr uint16_t SEC_PER_HOUR = 3600; 28static constexpr uint8_t BASE_GSM_YEAR = 100; 29static constexpr uint8_t MAX_ABS_TIME_LEN = 32; 30static constexpr uint8_t HEX_NUM_A = 0x0A; 31static constexpr uint8_t HEX_NUM_B = 0x0B; 32static constexpr uint8_t HEX_NUM_C = 0x0C; 33static constexpr uint8_t MIN_PRINTABLE_CHAR = 32; 34static constexpr uint8_t MAX_PRINTABLE_CHAR = 127; 35 36uint16_t SmsCommonUtils::Pack7bitChar( 37 const uint8_t *userData, uint16_t dataLen, uint8_t fillBits, uint8_t *packData, uint16_t packLen) 38{ 39 uint16_t dstIdx = 0; 40 if (userData == nullptr || packData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) { 41 TELEPHONY_LOGE("userData error."); 42 return dstIdx; 43 } 44 45 auto shift = fillBits; 46 if (shift > 0) { 47 dstIdx = 1; 48 } 49 uint16_t srcIdx = 0; 50 while (srcIdx < dataLen && dstIdx < packLen) { 51 if (shift == 0) { 52 packData[dstIdx] = userData[srcIdx]; 53 shift = SMS_ENCODE_GSM_BIT; 54 srcIdx++; 55 dstIdx++; 56 if (srcIdx >= dataLen) { 57 break; 58 } 59 } 60 if (shift > 1) { 61 packData[dstIdx - 1] |= userData[srcIdx] << shift; 62 packData[dstIdx] = userData[srcIdx] >> (SMS_BYTE_BIT - shift); 63 srcIdx++; 64 dstIdx++; 65 shift--; 66 } else if (shift == 1) { 67 packData[dstIdx - 1] |= userData[srcIdx] << shift; 68 shift--; 69 srcIdx++; 70 } 71 } 72 return dstIdx; 73} 74 75uint16_t SmsCommonUtils::Unpack7bitChar( 76 const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) 77{ 78 uint16_t srcIdx = 0; 79 uint16_t dstIdx = 0; 80 auto shift = fillBits; 81 if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { 82 TELEPHONY_LOGE("userData error."); 83 return dstIdx; 84 } 85 if (shift > 0) { 86 srcIdx = 1; 87 } 88 for (; srcIdx < dataLen && dstIdx < unpackDataLen; dstIdx++) { 89 if (shift == 0) { 90 unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; 91 shift = SMS_ENCODE_GSM_BIT; 92 srcIdx++; 93 dstIdx++; 94 if (dstIdx >= dataLen) { 95 dstIdx--; 96 break; 97 } 98 } 99 if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { 100 unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); 101 unpackData[dstIdx] &= 0x7F; 102 shift--; 103 if (shift > 0) { 104 srcIdx++; 105 } 106 } 107 } 108 return dstIdx; 109} 110 111uint16_t SmsCommonUtils::Unpack7bitCharForCBPdu( 112 const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen) 113{ 114 uint16_t srcIdx = 0; 115 uint16_t dstIdx = 0; 116 auto shift = fillBits; 117 if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) { 118 TELEPHONY_LOGE("userData error."); 119 return dstIdx; 120 } 121 if (shift > 0) { 122 srcIdx = 1; 123 } 124 for (; srcIdx < dataLen && dstIdx < unpackDataLen;) { 125 if (shift == 0) { 126 unpackData[dstIdx] = tpdu[srcIdx] & 0x7F; 127 shift = SMS_ENCODE_GSM_BIT; 128 srcIdx++; 129 dstIdx++; 130 } 131 if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) { 132 unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift)); 133 unpackData[dstIdx] &= 0x7F; 134 shift--; 135 if (shift > 0) { 136 srcIdx++; 137 } 138 dstIdx++; 139 } 140 } 141 if (dstIdx >= unpackDataLen) { 142 TELEPHONY_LOGE("dstIdx:%{public}d", dstIdx); 143 return 0; 144 } 145 uint8_t value = 0; 146 if (shift == 0) { 147 value = tpdu[srcIdx] >> shift; 148 } else if (srcIdx > 1) { 149 value = tpdu[srcIdx - 1] >> shift; 150 } 151 if (value >= MIN_PRINTABLE_CHAR && value <= MAX_PRINTABLE_CHAR) { 152 unpackData[dstIdx] = value; 153 dstIdx++; 154 } 155 TELEPHONY_LOGI("dstIdx:%{public}d", dstIdx); 156 return dstIdx; 157} 158 159uint8_t SmsCommonUtils::DigitToDtmfChar(const uint8_t c) 160{ 161 if (c == '0') { 162 return HEX_NUM_A; 163 } else if (c == '*') { 164 return HEX_NUM_B; 165 } else if (c == '#') { 166 return HEX_NUM_C; 167 } else { 168 return (c - '0'); 169 } 170} 171 172uint8_t SmsCommonUtils::DtmfCharToDigit(const uint8_t c) 173{ 174 switch (c) { 175 case HEX_NUM_B: 176 return '*'; 177 case HEX_NUM_C: 178 return '#'; 179 case HEX_NUM_A: 180 return '0'; 181 default: 182 return (c + '0'); 183 } 184} 185 186int64_t SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs) 187{ 188 time_t rawtime; 189 struct tm tmObj; 190 if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { 191 return time(nullptr); 192 } 193 tmObj.tm_year = (timeAbs.year + BASE_GSM_YEAR); 194 tmObj.tm_mon = (timeAbs.month - 0x01); 195 tmObj.tm_mday = timeAbs.day; 196 tmObj.tm_hour = timeAbs.hour; 197 tmObj.tm_min = timeAbs.minute; 198 tmObj.tm_sec = timeAbs.second; 199 tmObj.tm_isdst = 0; 200 rawtime = mktime(&tmObj); 201 GetDisplayTime(rawtime); 202 rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04)); 203 GetDisplayTime(rawtime); 204 /* timezone value is tiemzone + daylight. So should not add daylight */ 205 rawtime -= timezone; 206 GetDisplayTime(rawtime); 207 return rawtime; 208} 209 210void SmsCommonUtils::GetDisplayTime(const time_t &rawtime) 211{ 212 struct tm tmObj; 213 char displayTime[MAX_ABS_TIME_LEN]; 214 if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) { 215 TELEPHONY_LOGE("GetDisplayTime memset fail."); 216 return; 217 } 218 219 if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) { 220 TELEPHONY_LOGE("GetDisplayTime memset fail."); 221 return; 222 } 223 224 localtime_r(&rawtime, &tmObj); 225 if (strftime(displayTime, MAX_ABS_TIME_LEN, "%Y-%02m-%02d %T %z", &tmObj) <= 0) { 226 TELEPHONY_LOGE("strftime error."); 227 return; 228 } 229} 230} // namespace Telephony 231} // namespace OHOS 232