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