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 "napi_mms_pdu.h"
17 
18 #include "ability.h"
19 #include "datashare_helper.h"
20 #include "datashare_predicates.h"
21 #include "telephony_log_wrapper.h"
22 
23 namespace OHOS {
24 namespace Telephony {
25 const std::string SMS_PROFILE_MMS_PDU_URI = "datashare:///com.ohos.smsmmsability/sms_mms/mms_pdu";
26 static constexpr const char *PDU_CONTENT = "pdu_content";
27 static constexpr const char *ID = "id";
28 static constexpr uint8_t SLIDE_STEP = 2;
29 static constexpr uint8_t HEX_VALUE_F0 = 0xF0;
30 static constexpr uint8_t HEX_VALUE_0F = 0x0F;
31 static constexpr uint32_t SPLIT_PDU_LENGTH = 195 * 1024;
32 
DeleteMmsPdu(NapiMmsPduHelper & pduHelper)33 void NAPIMmsPdu::DeleteMmsPdu(NapiMmsPduHelper &pduHelper)
34 {
35     if (GetMmsPdu(pduHelper).empty()) {
36         TELEPHONY_LOGE("mmsPdu_ is nullptr");
37         return;
38     }
39     std::shared_ptr<DataShare::DataShareHelper> datashareHelper = pduHelper.GetDataShareHelper();
40     if (datashareHelper == nullptr) {
41         TELEPHONY_LOGE("datashareHelper is nullptr");
42         return;
43     }
44 
45     Uri uri(SMS_PROFILE_MMS_PDU_URI);
46     DataShare::DataSharePredicates predicates;
47     std::vector<std::string> dbUrls = SplitUrl(pduHelper.GetDbUrl());
48     int32_t result = -1;
49     for (std::string url : dbUrls) {
50         predicates.EqualTo(ID, url);
51         result = datashareHelper->Delete(uri, predicates);
52         if (result < 0) {
53             TELEPHONY_LOGE("delete mms pdu fail");
54             mmsPdu_ = "";
55             return;
56         }
57     }
58     mmsPdu_ = "";
59     TELEPHONY_LOGI("result:%{public}d", result);
60 }
61 
InsertMmsPdu(NapiMmsPduHelper & pduHelper,const std::string & mmsPdu)62 bool NAPIMmsPdu::InsertMmsPdu(NapiMmsPduHelper &pduHelper, const std::string &mmsPdu)
63 {
64     std::shared_ptr<DataShare::DataShareHelper> datashareHelper = pduHelper.GetDataShareHelper();
65     if (datashareHelper == nullptr) {
66         TELEPHONY_LOGE("datashareHelper is nullptr");
67         return false;
68     }
69 
70     Uri uri(SMS_PROFILE_MMS_PDU_URI);
71 
72     std::vector<std::string> mmsPdus = SplitPdu(mmsPdu);
73 
74     std::string dbUrl;
75     for (std::string mmsPdu : mmsPdus) {
76         DataShare::DataShareValuesBucket bucket;
77         bucket.Put(PDU_CONTENT, mmsPdu);
78         int32_t result = datashareHelper->Insert(uri, bucket);
79         if (result < 0) {
80             TELEPHONY_LOGE("mms pdu insert fail");
81             return false;
82         }
83         dbUrl += std::to_string(result) + ',';
84     }
85 
86     TELEPHONY_LOGI("insert db, dbUrl:%{public}s", dbUrl.c_str());
87     pduHelper.SetDbUrl(dbUrl);
88     pduHelper.NotifyAll();
89     return dbUrl.empty() ? false : true;
90 }
91 
SplitPdu(const std::string & mmsPdu)92 std::vector<std::string> NAPIMmsPdu::SplitPdu(const std::string &mmsPdu)
93 {
94     std::vector<std::string> mmsPdus;
95     std::string targetMmsPdu;
96     for (size_t i = 0; i < mmsPdu.size(); i++) {
97         targetMmsPdu += static_cast<char>((mmsPdu[i] & HEX_VALUE_0F) | HEX_VALUE_F0);
98         targetMmsPdu += static_cast<char>((mmsPdu[i] & HEX_VALUE_F0) | HEX_VALUE_0F);
99     }
100     std::string mmsPduData;
101     for (uint32_t locate = 0; locate * SPLIT_PDU_LENGTH < targetMmsPdu.size(); locate++) {
102         if ((locate + 1) * SPLIT_PDU_LENGTH < targetMmsPdu.size()) {
103             mmsPduData = targetMmsPdu.substr(locate * SPLIT_PDU_LENGTH, SPLIT_PDU_LENGTH);
104             mmsPdus.push_back(mmsPduData);
105         } else {
106             mmsPduData = targetMmsPdu.substr(locate * SPLIT_PDU_LENGTH);
107             mmsPdus.push_back(mmsPduData);
108             break;
109         }
110     }
111     TELEPHONY_LOGI("pduLen:%{public}zu,targetPduLen:%{public}zu", mmsPdu.size(), targetMmsPdu.size());
112     return mmsPdus;
113 }
114 
GetMmsPdu(NapiMmsPduHelper & pduHelper)115 std::string NAPIMmsPdu::GetMmsPdu(NapiMmsPduHelper &pduHelper)
116 {
117     if (!QueryMmsPdu(pduHelper)) {
118         return "";
119     }
120     return mmsPdu_;
121 }
122 
SetMmsPdu(const std::string & mmsPdu)123 void NAPIMmsPdu::SetMmsPdu(const std::string &mmsPdu)
124 {
125     mmsPdu_ = mmsPdu;
126 }
127 
SplitUrl(std::string url)128 std::vector<std::string> NAPIMmsPdu::SplitUrl(std::string url)
129 {
130     std::vector<std::string> dbUrls;
131     while (url.size() > 0) {
132         size_t locate = url.find_first_of(',');
133         if (locate == 0 || locate == std::string::npos) {
134             break;
135         }
136         dbUrls.push_back(url.substr(0, locate));
137         url = url.substr(locate + 1);
138     }
139     return dbUrls;
140 }
141 
QueryMmsPdu(NapiMmsPduHelper & pduHelper)142 bool NAPIMmsPdu::QueryMmsPdu(NapiMmsPduHelper &pduHelper)
143 {
144     std::shared_ptr<DataShare::DataShareHelper> datashareHelper = pduHelper.GetDataShareHelper();
145     if (datashareHelper == nullptr) {
146         TELEPHONY_LOGE("datashareHelper is nullptr");
147         return false;
148     }
149     std::vector<std::string> dbUrls = SplitUrl(pduHelper.GetDbUrl());
150     std::string mmsPdu;
151     std::string urlData;
152     for (std::string url : dbUrls) {
153         urlData.append(url + ',');
154         Uri uri(SMS_PROFILE_MMS_PDU_URI);
155         std::vector<std::string> colume;
156         DataShare::DataSharePredicates predicates;
157         predicates.EqualTo(ID, url);
158         auto resultSet = datashareHelper->Query(uri, predicates, colume);
159         if (resultSet == nullptr) {
160             TELEPHONY_LOGE("resultSet is nullptr");
161             return false;
162         }
163         int count;
164         resultSet->GetRowCount(count);
165         if (count <= 0) {
166             TELEPHONY_LOGE("pdu count: %{public}d error", count);
167             resultSet->Close();
168             return false;
169         }
170         int columnIndex;
171         std::vector<uint8_t> blobValue;
172         for (int row = 0; row < count; row++) {
173             resultSet->GoToRow(row);
174             resultSet->GetColumnIndex(PDU_CONTENT, columnIndex);
175             resultSet->GetBlob(columnIndex, blobValue);
176         }
177         resultSet->Close();
178         blobValue.pop_back();
179         for (size_t i = 0; i + 1 < blobValue.size(); i = i + SLIDE_STEP) {
180             char pduChar = (blobValue[i] & HEX_VALUE_0F) | (blobValue[i + 1] & HEX_VALUE_F0);
181             mmsPdu += static_cast<char>(pduChar);
182         }
183     }
184     TELEPHONY_LOGI("mmsPdu size:%{public}zu, urlData:%{public}s", mmsPdu.size(), urlData.c_str());
185     SetMmsPdu(mmsPdu);
186     return true;
187 }
188 } // namespace Telephony
189 } // namespace OHOS