1 /*
2  * Copyright (C) 2024 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 <fstream>
17 #include <vector>
18 
19 #include "dualfwk_conf_loader.h"
20 #include "ringtone_errno.h"
21 #include "ringtone_file_utils.h"
22 #include "ringtone_restore_db_utils.h"
23 #include "directory_ex.h"
24 
25 namespace OHOS {
26 namespace Media {
27 
28 static const std::string SETTINGS_DATA_URI_BASE =
29     "datashare:///com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_";
30 static const std::string SETTINGS_DATA_FIELD_KEY = "KEYWORD";
31 static const std::string SETTINGS_DATA_FIELD_VAL = "VALUE";
32 static std::vector<std::string> SETTINGS_COLUMNS = {SETTINGS_DATA_FIELD_VAL};
33 static const int DEFAULT_USERID = 100;
34 
DualFwkConfLoader()35 DualFwkConfLoader::DualFwkConfLoader() {}
36 
Init()37 int32_t DualFwkConfLoader::Init()
38 {
39     DataShare::CreateOptions options;
40 
41     int userId = 0;
42     if (!RingtoneRestoreDbUtils::GetUserID(userId)) {
43         RINGTONE_DEBUG_LOG("Failed to get userId, using DEFAULT_USERID=%{public}d", DEFAULT_USERID);
44         userId = DEFAULT_USERID;
45     }
46     settingsDataUri_ = SETTINGS_DATA_URI_BASE + std::to_string(userId);
47     RINGTONE_DEBUG_LOG("Getting data share helper with SETTINGS_DATA_URI = %{public}s", settingsDataUri_.c_str());
48 
49     dataShareHelper_ = DataShare::DataShareHelper::Creator(settingsDataUri_, options);
50     if (dataShareHelper_ == nullptr) {
51         RINGTONE_WARN_LOG("dataShareHelper_ is null, failed to get data share helper");
52         return E_ERR;
53     }
54 
55     RINGTONE_INFO_LOG("Successfully initialized.");
56     return E_OK;
57 }
58 
GetSound(const std::string & line)59 static std::string GetSound(const std::string &line)
60 {
61     std::string tag = "sound=\"";
62     auto lenTag = tag.size();
63     auto positionOfTag = line.find(tag);
64     if (positionOfTag == std::string::npos) {
65         return "";
66     }
67     auto positionOfQuote = line.substr(positionOfTag + lenTag).find("\"");
68     if (positionOfQuote == std::string::npos) {
69         return "";
70     }
71     return line.substr(positionOfTag + lenTag, positionOfQuote);
72 }
73 
ParseBackupFile(const std::string & backupFile,const std::vector<std::string> & keys,std::map<std::string,std::string> & results)74 static int32_t ParseBackupFile(const std::string &backupFile, const std::vector<std::string> &keys,
75     std::map<std::string, std::string> &results)
76 {
77     RINGTONE_INFO_LOG("parse backupfile %{public}s uid=%{public}d", backupFile.c_str(), getuid());
78     std::string realPath;
79     if (!PathToRealPath(backupFile, realPath)) {
80         RINGTONE_ERR_LOG("the file not exists path: %{private}s", backupFile.c_str());
81         return E_INVALID_PATH;
82     }
83 
84     std::ifstream fs(realPath);
85     if (!fs.good()) {
86         RINGTONE_ERR_LOG("failed to open file %{private}s", realPath.c_str());
87         return E_ERR;
88     }
89 
90     std::string line;
91     while (std::getline(fs, line)) {
92         for (const auto &key : keys) {
93             auto pos = line.find(key);
94             if (pos == std::string::npos) {
95                 continue;
96             }
97             std::string value = GetSound(line);
98             if (value.size() > 0) {
99                 results.emplace(key, value);
100             }
101         }
102     }
103     return E_SUCCESS;
104 }
105 
Load(DualFwkConf & conf,const RestoreSceneType & type,const std::string & backupFile)106 int32_t DualFwkConfLoader::Load(DualFwkConf &conf, const RestoreSceneType &type, const std::string &backupFile)
107 {
108     if (dataShareHelper_ == nullptr) {
109         RINGTONE_ERR_LOG("DualFwkConfLoader is not initialized successfully");
110         return E_ERR;
111     }
112     std::map<std::string, std::string> backupConfigs;
113     if (ParseBackupFile(backupFile, {"mms_sim1_channel", "mms_sim2_channel"}, backupConfigs) != E_SUCCESS) {
114         RINGTONE_WARN_LOG("Failed to parse backup file %{public}s", backupFile.c_str());
115     }
116 
117     if (type == RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE) {
118         RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_CLONE");
119         conf.notificationSoundPath = GetConf("notification_sound");
120         conf.ringtonePath = GetConf("ringtone_path");
121         conf.ringtone2Path = GetConf("ringtone2_path");
122         conf.alarmAlertPath = GetConf("alarm_alert");
123         conf.messagePath = GetConf("message_path");
124         conf.messageSub1 = GetConf("message_sub1");
125         conf.messagePath = backupConfigs["mms_sim1_channel"];
126         conf.messageSub1 = backupConfigs["mms_sim2_channel"];
127     } else {
128         RINGTONE_INFO_LOG("Load configurations for RestoreSceneType::RESTORE_SCENE_TYPE_DUAL_UPGRADE");
129         conf.notificationSoundPath = GetConf("notification_sound_path");
130         conf.ringtonePath = GetConf("ringtone_path");
131         conf.ringtone2Path = GetConf("ringtone2_path");
132         conf.alarmAlertPath = GetConf("alarm_alert_path");
133         conf.messagePath = GetConf("message_path");
134         conf.messageSub1 = GetConf("message_sub1");
135     }
136 
137     return E_OK;
138 }
139 
ShowConf(const DualFwkConf & conf)140 void DualFwkConfLoader::ShowConf(const DualFwkConf &conf)
141 {
142     RINGTONE_DEBUG_LOG("===================================================");
143     RINGTONE_DEBUG_LOG("conf.notificationSoundPath  = %{public}s", conf.notificationSoundPath.c_str());
144     RINGTONE_DEBUG_LOG("conf.ringtonePath = %{public}s", conf.ringtonePath.c_str());
145     RINGTONE_DEBUG_LOG("conf.ringtone2Path = %{public}s", conf.ringtone2Path.c_str());
146     RINGTONE_DEBUG_LOG("conf.alarmAlertPath = %{public}s", conf.alarmAlertPath.c_str());
147     RINGTONE_DEBUG_LOG("conf.messagePath = %{public}s", conf.messagePath.c_str());
148     RINGTONE_DEBUG_LOG("conf.messageSub1 = %{public}s", conf.messageSub1.c_str());
149     RINGTONE_DEBUG_LOG("===================================================");
150 }
151 
GetConf(const std::string & key)152 std::string DualFwkConfLoader::GetConf(const std::string &key)
153 {
154     DataShare::DataSharePredicates dataSharePredicates;
155     dataSharePredicates.EqualTo(SETTINGS_DATA_FIELD_KEY, key);
156     Uri uri(settingsDataUri_);
157     auto resultSet = dataShareHelper_->Query(uri, dataSharePredicates, SETTINGS_COLUMNS);
158     if (resultSet == nullptr) {
159         RINGTONE_DEBUG_LOG("resultSet is null, failed to get value of key = %{public}s", key.c_str());
160         return "";
161     }
162 
163     int32_t numRows = 0;
164     resultSet->GetRowCount(numRows);
165     RINGTONE_INFO_LOG("%{public}d records found with key = %{public}s", numRows, key.c_str());
166     if (numRows == 0) {
167         RINGTONE_DEBUG_LOG("no record at key = %{public}s, returning an empty string.", key.c_str());
168         return "";
169     }
170     int32_t columnIndex = 0;
171     int32_t rowNumber = 0;
172     resultSet->GoToRow(rowNumber);
173     std::string valueResult = "";
174     int32_t ret = resultSet->GetString(columnIndex, valueResult);
175     if (ret != 0) {
176         RINGTONE_DEBUG_LOG("failed to get string, returning an empty string.");
177     } else {
178         RINGTONE_DEBUG_LOG("valueResult = %{public}s", valueResult.c_str());
179     }
180     return valueResult;
181 }
182 } // namespace Media
183 } // namespace OHOS