1e5d0e473Sopenharmony_ci/*
2e5d0e473Sopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
3e5d0e473Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
4e5d0e473Sopenharmony_ci * you may not use this file except in compliance with the License.
5e5d0e473Sopenharmony_ci * You may obtain a copy of the License at
6e5d0e473Sopenharmony_ci *
7e5d0e473Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
8e5d0e473Sopenharmony_ci *
9e5d0e473Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
10e5d0e473Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
11e5d0e473Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12e5d0e473Sopenharmony_ci * See the License for the specific language governing permissions and
13e5d0e473Sopenharmony_ci * limitations under the License.
14e5d0e473Sopenharmony_ci */
15e5d0e473Sopenharmony_ci
16e5d0e473Sopenharmony_ci#include "sms_common_utils.h"
17e5d0e473Sopenharmony_ci
18e5d0e473Sopenharmony_ci#include <ctime>
19e5d0e473Sopenharmony_ci#include "securec.h"
20e5d0e473Sopenharmony_ci#include "telephony_log_wrapper.h"
21e5d0e473Sopenharmony_ci
22e5d0e473Sopenharmony_cinamespace OHOS {
23e5d0e473Sopenharmony_cinamespace Telephony {
24e5d0e473Sopenharmony_cistatic constexpr uint8_t SMS_ENCODE_GSM_BIT = 7;
25e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_GSM_7BIT_DATA_LEN = 160;
26e5d0e473Sopenharmony_cistatic constexpr uint8_t SMS_BYTE_BIT = 8;
27e5d0e473Sopenharmony_cistatic constexpr uint16_t SEC_PER_HOUR = 3600;
28e5d0e473Sopenharmony_cistatic constexpr uint8_t BASE_GSM_YEAR = 100;
29e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_ABS_TIME_LEN = 32;
30e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_A = 0x0A;
31e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_B = 0x0B;
32e5d0e473Sopenharmony_cistatic constexpr uint8_t HEX_NUM_C = 0x0C;
33e5d0e473Sopenharmony_cistatic constexpr uint8_t MIN_PRINTABLE_CHAR = 32;
34e5d0e473Sopenharmony_cistatic constexpr uint8_t MAX_PRINTABLE_CHAR = 127;
35e5d0e473Sopenharmony_ci
36e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Pack7bitChar(
37e5d0e473Sopenharmony_ci    const uint8_t *userData, uint16_t dataLen, uint8_t fillBits, uint8_t *packData, uint16_t packLen)
38e5d0e473Sopenharmony_ci{
39e5d0e473Sopenharmony_ci    uint16_t dstIdx = 0;
40e5d0e473Sopenharmony_ci    if (userData == nullptr || packData == nullptr || dataLen > MAX_GSM_7BIT_DATA_LEN) {
41e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("userData error.");
42e5d0e473Sopenharmony_ci        return dstIdx;
43e5d0e473Sopenharmony_ci    }
44e5d0e473Sopenharmony_ci
45e5d0e473Sopenharmony_ci    auto shift = fillBits;
46e5d0e473Sopenharmony_ci    if (shift > 0) {
47e5d0e473Sopenharmony_ci        dstIdx = 1;
48e5d0e473Sopenharmony_ci    }
49e5d0e473Sopenharmony_ci    uint16_t srcIdx = 0;
50e5d0e473Sopenharmony_ci    while (srcIdx < dataLen && dstIdx < packLen) {
51e5d0e473Sopenharmony_ci        if (shift == 0) {
52e5d0e473Sopenharmony_ci            packData[dstIdx] = userData[srcIdx];
53e5d0e473Sopenharmony_ci            shift = SMS_ENCODE_GSM_BIT;
54e5d0e473Sopenharmony_ci            srcIdx++;
55e5d0e473Sopenharmony_ci            dstIdx++;
56e5d0e473Sopenharmony_ci            if (srcIdx >= dataLen) {
57e5d0e473Sopenharmony_ci                break;
58e5d0e473Sopenharmony_ci            }
59e5d0e473Sopenharmony_ci        }
60e5d0e473Sopenharmony_ci        if (shift > 1) {
61e5d0e473Sopenharmony_ci            packData[dstIdx - 1] |= userData[srcIdx] << shift;
62e5d0e473Sopenharmony_ci            packData[dstIdx] = userData[srcIdx] >> (SMS_BYTE_BIT - shift);
63e5d0e473Sopenharmony_ci            srcIdx++;
64e5d0e473Sopenharmony_ci            dstIdx++;
65e5d0e473Sopenharmony_ci            shift--;
66e5d0e473Sopenharmony_ci        } else if (shift == 1) {
67e5d0e473Sopenharmony_ci            packData[dstIdx - 1] |= userData[srcIdx] << shift;
68e5d0e473Sopenharmony_ci            shift--;
69e5d0e473Sopenharmony_ci            srcIdx++;
70e5d0e473Sopenharmony_ci        }
71e5d0e473Sopenharmony_ci    }
72e5d0e473Sopenharmony_ci    return dstIdx;
73e5d0e473Sopenharmony_ci}
74e5d0e473Sopenharmony_ci
75e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Unpack7bitChar(
76e5d0e473Sopenharmony_ci    const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen)
77e5d0e473Sopenharmony_ci{
78e5d0e473Sopenharmony_ci    uint16_t srcIdx = 0;
79e5d0e473Sopenharmony_ci    uint16_t dstIdx = 0;
80e5d0e473Sopenharmony_ci    auto shift = fillBits;
81e5d0e473Sopenharmony_ci    if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) {
82e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("userData error.");
83e5d0e473Sopenharmony_ci        return dstIdx;
84e5d0e473Sopenharmony_ci    }
85e5d0e473Sopenharmony_ci    if (shift > 0) {
86e5d0e473Sopenharmony_ci        srcIdx = 1;
87e5d0e473Sopenharmony_ci    }
88e5d0e473Sopenharmony_ci    for (; srcIdx < dataLen && dstIdx < unpackDataLen; dstIdx++) {
89e5d0e473Sopenharmony_ci        if (shift == 0) {
90e5d0e473Sopenharmony_ci            unpackData[dstIdx] = tpdu[srcIdx] & 0x7F;
91e5d0e473Sopenharmony_ci            shift = SMS_ENCODE_GSM_BIT;
92e5d0e473Sopenharmony_ci            srcIdx++;
93e5d0e473Sopenharmony_ci            dstIdx++;
94e5d0e473Sopenharmony_ci            if (dstIdx >= dataLen) {
95e5d0e473Sopenharmony_ci                dstIdx--;
96e5d0e473Sopenharmony_ci                break;
97e5d0e473Sopenharmony_ci            }
98e5d0e473Sopenharmony_ci        }
99e5d0e473Sopenharmony_ci        if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) {
100e5d0e473Sopenharmony_ci            unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift));
101e5d0e473Sopenharmony_ci            unpackData[dstIdx] &= 0x7F;
102e5d0e473Sopenharmony_ci            shift--;
103e5d0e473Sopenharmony_ci            if (shift > 0) {
104e5d0e473Sopenharmony_ci                srcIdx++;
105e5d0e473Sopenharmony_ci            }
106e5d0e473Sopenharmony_ci        }
107e5d0e473Sopenharmony_ci    }
108e5d0e473Sopenharmony_ci    return dstIdx;
109e5d0e473Sopenharmony_ci}
110e5d0e473Sopenharmony_ci
111e5d0e473Sopenharmony_ciuint16_t SmsCommonUtils::Unpack7bitCharForCBPdu(
112e5d0e473Sopenharmony_ci    const uint8_t *tpdu, uint16_t dataLen, uint8_t fillBits, uint8_t *unpackData, uint16_t unpackDataLen)
113e5d0e473Sopenharmony_ci{
114e5d0e473Sopenharmony_ci    uint16_t srcIdx = 0;
115e5d0e473Sopenharmony_ci    uint16_t dstIdx = 0;
116e5d0e473Sopenharmony_ci    auto shift = fillBits;
117e5d0e473Sopenharmony_ci    if (unpackData == nullptr || tpdu == nullptr || dataLen == 0 || unpackDataLen == 0 || dataLen > unpackDataLen) {
118e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("userData error.");
119e5d0e473Sopenharmony_ci        return dstIdx;
120e5d0e473Sopenharmony_ci    }
121e5d0e473Sopenharmony_ci    if (shift > 0) {
122e5d0e473Sopenharmony_ci        srcIdx = 1;
123e5d0e473Sopenharmony_ci    }
124e5d0e473Sopenharmony_ci    for (; srcIdx < dataLen && dstIdx < unpackDataLen;) {
125e5d0e473Sopenharmony_ci        if (shift == 0) {
126e5d0e473Sopenharmony_ci            unpackData[dstIdx] = tpdu[srcIdx] & 0x7F;
127e5d0e473Sopenharmony_ci            shift = SMS_ENCODE_GSM_BIT;
128e5d0e473Sopenharmony_ci            srcIdx++;
129e5d0e473Sopenharmony_ci            dstIdx++;
130e5d0e473Sopenharmony_ci        }
131e5d0e473Sopenharmony_ci        if (shift > 0 && srcIdx < dataLen && dstIdx < unpackDataLen) {
132e5d0e473Sopenharmony_ci            unpackData[dstIdx] = ((unsigned int)tpdu[srcIdx - 1] >> shift) + (tpdu[srcIdx] << (SMS_BYTE_BIT - shift));
133e5d0e473Sopenharmony_ci            unpackData[dstIdx] &= 0x7F;
134e5d0e473Sopenharmony_ci            shift--;
135e5d0e473Sopenharmony_ci            if (shift > 0) {
136e5d0e473Sopenharmony_ci                srcIdx++;
137e5d0e473Sopenharmony_ci            }
138e5d0e473Sopenharmony_ci            dstIdx++;
139e5d0e473Sopenharmony_ci        }
140e5d0e473Sopenharmony_ci    }
141e5d0e473Sopenharmony_ci    if (dstIdx >= unpackDataLen) {
142e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("dstIdx:%{public}d", dstIdx);
143e5d0e473Sopenharmony_ci        return 0;
144e5d0e473Sopenharmony_ci    }
145e5d0e473Sopenharmony_ci    uint8_t value = 0;
146e5d0e473Sopenharmony_ci    if (shift == 0) {
147e5d0e473Sopenharmony_ci        value = tpdu[srcIdx] >> shift;
148e5d0e473Sopenharmony_ci    } else if (srcIdx > 1) {
149e5d0e473Sopenharmony_ci        value = tpdu[srcIdx - 1] >> shift;
150e5d0e473Sopenharmony_ci    }
151e5d0e473Sopenharmony_ci    if (value >= MIN_PRINTABLE_CHAR && value <= MAX_PRINTABLE_CHAR) {
152e5d0e473Sopenharmony_ci        unpackData[dstIdx] = value;
153e5d0e473Sopenharmony_ci        dstIdx++;
154e5d0e473Sopenharmony_ci    }
155e5d0e473Sopenharmony_ci    TELEPHONY_LOGI("dstIdx:%{public}d", dstIdx);
156e5d0e473Sopenharmony_ci    return dstIdx;
157e5d0e473Sopenharmony_ci}
158e5d0e473Sopenharmony_ci
159e5d0e473Sopenharmony_ciuint8_t SmsCommonUtils::DigitToDtmfChar(const uint8_t c)
160e5d0e473Sopenharmony_ci{
161e5d0e473Sopenharmony_ci    if (c == '0') {
162e5d0e473Sopenharmony_ci        return HEX_NUM_A;
163e5d0e473Sopenharmony_ci    } else if (c == '*') {
164e5d0e473Sopenharmony_ci        return HEX_NUM_B;
165e5d0e473Sopenharmony_ci    } else if (c == '#') {
166e5d0e473Sopenharmony_ci        return HEX_NUM_C;
167e5d0e473Sopenharmony_ci    } else {
168e5d0e473Sopenharmony_ci        return (c - '0');
169e5d0e473Sopenharmony_ci    }
170e5d0e473Sopenharmony_ci}
171e5d0e473Sopenharmony_ci
172e5d0e473Sopenharmony_ciuint8_t SmsCommonUtils::DtmfCharToDigit(const uint8_t c)
173e5d0e473Sopenharmony_ci{
174e5d0e473Sopenharmony_ci    switch (c) {
175e5d0e473Sopenharmony_ci        case HEX_NUM_B:
176e5d0e473Sopenharmony_ci            return '*';
177e5d0e473Sopenharmony_ci        case HEX_NUM_C:
178e5d0e473Sopenharmony_ci            return '#';
179e5d0e473Sopenharmony_ci        case HEX_NUM_A:
180e5d0e473Sopenharmony_ci            return '0';
181e5d0e473Sopenharmony_ci        default:
182e5d0e473Sopenharmony_ci            return (c + '0');
183e5d0e473Sopenharmony_ci    }
184e5d0e473Sopenharmony_ci}
185e5d0e473Sopenharmony_ci
186e5d0e473Sopenharmony_ciint64_t SmsCommonUtils::ConvertTime(const struct SmsTimeAbs &timeAbs)
187e5d0e473Sopenharmony_ci{
188e5d0e473Sopenharmony_ci    time_t rawtime;
189e5d0e473Sopenharmony_ci    struct tm tmObj;
190e5d0e473Sopenharmony_ci    if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
191e5d0e473Sopenharmony_ci        return time(nullptr);
192e5d0e473Sopenharmony_ci    }
193e5d0e473Sopenharmony_ci    tmObj.tm_year = (timeAbs.year + BASE_GSM_YEAR);
194e5d0e473Sopenharmony_ci    tmObj.tm_mon = (timeAbs.month - 0x01);
195e5d0e473Sopenharmony_ci    tmObj.tm_mday = timeAbs.day;
196e5d0e473Sopenharmony_ci    tmObj.tm_hour = timeAbs.hour;
197e5d0e473Sopenharmony_ci    tmObj.tm_min = timeAbs.minute;
198e5d0e473Sopenharmony_ci    tmObj.tm_sec = timeAbs.second;
199e5d0e473Sopenharmony_ci    tmObj.tm_isdst = 0;
200e5d0e473Sopenharmony_ci    rawtime = mktime(&tmObj);
201e5d0e473Sopenharmony_ci    GetDisplayTime(rawtime);
202e5d0e473Sopenharmony_ci    rawtime -= (timeAbs.timeZone * (SEC_PER_HOUR / 0x04));
203e5d0e473Sopenharmony_ci    GetDisplayTime(rawtime);
204e5d0e473Sopenharmony_ci    /* timezone value is tiemzone + daylight. So should not add daylight */
205e5d0e473Sopenharmony_ci    rawtime -= timezone;
206e5d0e473Sopenharmony_ci    GetDisplayTime(rawtime);
207e5d0e473Sopenharmony_ci    return rawtime;
208e5d0e473Sopenharmony_ci}
209e5d0e473Sopenharmony_ci
210e5d0e473Sopenharmony_civoid SmsCommonUtils::GetDisplayTime(const time_t &rawtime)
211e5d0e473Sopenharmony_ci{
212e5d0e473Sopenharmony_ci    struct tm tmObj;
213e5d0e473Sopenharmony_ci    char displayTime[MAX_ABS_TIME_LEN];
214e5d0e473Sopenharmony_ci    if (memset_s(&tmObj, sizeof(struct tm), 0x00, sizeof(tm)) != EOK) {
215e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("GetDisplayTime memset fail.");
216e5d0e473Sopenharmony_ci        return;
217e5d0e473Sopenharmony_ci    }
218e5d0e473Sopenharmony_ci
219e5d0e473Sopenharmony_ci    if (memset_s(displayTime, sizeof(displayTime), 0x00, sizeof(displayTime)) != EOK) {
220e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("GetDisplayTime memset fail.");
221e5d0e473Sopenharmony_ci        return;
222e5d0e473Sopenharmony_ci    }
223e5d0e473Sopenharmony_ci
224e5d0e473Sopenharmony_ci    localtime_r(&rawtime, &tmObj);
225e5d0e473Sopenharmony_ci    if (strftime(displayTime, MAX_ABS_TIME_LEN, "%Y-%02m-%02d %T %z", &tmObj) <= 0) {
226e5d0e473Sopenharmony_ci        TELEPHONY_LOGE("strftime error.");
227e5d0e473Sopenharmony_ci        return;
228e5d0e473Sopenharmony_ci    }
229e5d0e473Sopenharmony_ci}
230e5d0e473Sopenharmony_ci} // namespace Telephony
231e5d0e473Sopenharmony_ci} // namespace OHOS
232