2 * Copyright (c) 2019 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include <linux/xattr.h>
20 #include <sys/smack.h>
22 #include <glib/gstdio.h>
24 #include <tzplatform_config.h>
25 #include <security-manager.h>
33 #include "notification-ex/common.h"
34 #include "notification-ex/shared_file.h"
35 #include "notification-ex/group_item.h"
41 #define LOG_TAG "NOTIFICATION_EX"
42 #define CHECK_LABEL "::RO"
43 #define NOTI_PRIV_DATA_DIR "data/.notification_ex"
47 namespace notification {
49 SharedFile::SharedFile() = default;
50 SharedFile::~SharedFile() = default;
51 SharedFile::SharingData::SharingData() = default;
52 SharedFile::SharingData::~SharingData() = default;
53 SharedFile::SharingTarget::SharingTarget() = default;
54 SharedFile::SharingTarget::~SharingTarget() = default;
56 const char* SharedFile::GetLastIndex(const char* path, const char* search) {
61 if (path == nullptr || search == nullptr)
64 search_len = strlen(search);
65 index = path + strlen(path) - search_len;
67 while (index >= path) {
68 for (i = 0; i < search_len; i++) {
69 if (index[i] != search[i])
82 bool SharedFile::MakeDir(const char* path) {
83 if (access(path, R_OK) == 0)
86 auto noti_dir = unique_ptr<GFile, decltype(&g_object_unref)>(
87 g_file_new_for_path(path), g_object_unref);
88 if (noti_dir == nullptr)
91 GError* g_err = nullptr;
92 if (!g_file_make_directory(noti_dir.get(), nullptr, &g_err)) {
94 LOGE("Failed to make sharing dir[%s]", g_err->message);
103 string SharedFile::GetDir(string path) {
111 index = GetLastIndex(path.c_str(), "/");
112 if (index == nullptr) {
113 LOGE("Failed to find directory separator");
117 dir_len = index - path.c_str() + 1;
118 if (dir_len <= 0 || dir_len > PATH_MAX)
121 dir.reserve(PATH_MAX);
122 snprintf(&dir[0], dir_len, "%s", path.c_str());
127 int SharedFile::CopyFile(const char* source, const char* dest) {
128 GError* g_err = nullptr;
129 struct utimbuf ut = {0, };
131 if (source == nullptr || dest == nullptr) {
132 LOGE("Invalid parameter");
133 return ERROR_INVALID_PARAMETER;
136 auto dst = unique_ptr<GFile, decltype(&g_object_unref)>(
137 g_file_new_for_path(dest), g_object_unref);
138 if (dst == nullptr) {
139 LOGE("dest path is wrong [%s]", dest);
140 return ERROR_IO_ERROR;
143 if (g_file_query_exists(dst.get(), nullptr)) {
144 LOGD("dst path already existed [%s]", dest);
145 return ERROR_ALREADY_EXIST_ID;
148 auto src = unique_ptr<GFile, decltype(&g_object_unref)>(
149 g_file_new_for_path(source), g_object_unref);
150 if (src == nullptr) {
151 LOGE("src path is wrong [%s]", source);
152 return ERROR_IO_ERROR;
155 if (!g_file_copy(src.get(), dst.get(), G_FILE_COPY_NOFOLLOW_SYMLINKS, nullptr,
156 nullptr, nullptr, &g_err)) {
158 LOGE("Copying file from [%s] to [%s] is failed [%s]", source, dest,
162 return ERROR_IO_ERROR;
165 ut.modtime = time(nullptr);
166 if (g_utime(dest, &ut) != 0)
167 LOGD("Failed to set g_utime %d ", errno);
172 vector<char*> SharedFile::ConvertListToArray(const list<string>& data) {
178 for (const auto& i : data)
179 v.push_back(const_cast<char*>(i.c_str()));
184 bool SharedFile::IsPrivatePath(string path) const {
185 char* smack_label = nullptr;
189 LOGE("Invalid parameter");
193 if (smack_new_label_from_path(path.c_str(), XATTR_NAME_SMACK, 1, &smack_label)
195 LOGE("smack_new_label_from_path failed");
199 if (GetLastIndex(smack_label, CHECK_LABEL) != nullptr)
206 string SharedFile::GetDataPath(string app_id, string path) const {
210 if (app_id.empty() || path.empty()) {
211 LOGE("Invalid parameter");
215 tzplatform_set_user(getuid());
216 user_app = tzplatform_getenv(TZ_USER_APP);
217 tzplatform_reset_user();
219 dir = user_app + "/" + app_id + "/" + NOTI_PRIV_DATA_DIR + "/";
220 dir += string(GetLastIndex(path.c_str(), "/") + 1);
225 int SharedFile::SetSharingData(SharingData sharing_data,
226 list<string> new_shared_file_list, list<string> new_receiver_group_list,
227 multimap<string, string> receiver_group_map) {
228 private_sharing_req* handle = nullptr;
229 vector<char*> path_array;
230 vector<char*> target_array;
231 const char* appid = nullptr;
234 if (new_shared_file_list.empty() || new_receiver_group_list.empty()) {
235 LOGE("Invalid parameter");
236 return ERROR_INVALID_PARAMETER;
239 ret = security_manager_private_sharing_req_new(&handle);
240 if (ret != SECURITY_MANAGER_SUCCESS) {
241 LOGE("Failed to create private sharing request handle[%d]", ret);
242 return ERROR_IO_ERROR;
245 auto req = unique_ptr<private_sharing_req,
246 decltype(&security_manager_private_sharing_req_free)>(
247 handle, security_manager_private_sharing_req_free);
249 return ERROR_IO_ERROR;
251 appid = strdup(sharing_data.app_id.c_str());
252 if (appid == nullptr) {
253 LOGE("Failed to get Sender appid");
254 return ERROR_OUT_OF_MEMORY;
257 ret = security_manager_private_sharing_req_set_owner_appid(req.get(), appid);
258 if (ret != SECURITY_MANAGER_SUCCESS) {
259 LOGE("Failed to set owner appid[%s][%d]", appid, ret);
260 return ERROR_IO_ERROR;
263 path_array = ConvertListToArray(new_shared_file_list);
264 if (path_array.empty()) {
265 LOGE("path_array is null");
266 return ERROR_IO_ERROR;
269 ret = security_manager_private_sharing_req_add_paths(req.get(),
270 const_cast<const char**>(path_array.data()), path_array.size());
271 if (ret != SECURITY_MANAGER_SUCCESS) {
272 LOGE("Failed to add paths [%d]", ret);
273 return ERROR_IO_ERROR;
276 target_array = ConvertListToArray(new_receiver_group_list);
277 if (target_array.empty()) {
278 LOGE("target_array is null");
279 return ERROR_IO_ERROR;
282 for (int i = 0; i < static_cast<int>(target_array.size()); i++) {
283 multimap<string, string>::iterator it;
284 for (it = receiver_group_map.begin(); it != receiver_group_map.end(); it++) {
285 if (it->first.compare(target_array[i]) == 0) {
286 ret = security_manager_private_sharing_req_set_target_appid(req.get(),
288 if (ret != SECURITY_MANAGER_SUCCESS) {
289 LOGE("Failed to set target appid [%s]", appid);
290 return ERROR_IO_ERROR;
293 ret = security_manager_private_sharing_apply(req.get());
294 if (ret != SECURITY_MANAGER_SUCCESS) {
295 LOGE("Failed to apply private sharing [%d]", ret);
296 return ERROR_IO_ERROR;
305 int SharedFile::UnsetSharingData(SharingData sharing_data,
306 multimap<string, string> receiver_group_map) {
307 private_sharing_req* handle = nullptr;
308 vector<char*> path_array;
309 vector<char*> target_array;
310 const char* appid = nullptr;
313 if (receiver_group_map.empty()) {
314 LOGE("Invalid parameter");
315 return ERROR_INVALID_PARAMETER;
318 ret = security_manager_private_sharing_req_new(&handle);
319 if (ret != SECURITY_MANAGER_SUCCESS) {
320 LOGE("Failed to create private sharing request handle[%d]", ret);
321 return ERROR_IO_ERROR;
324 auto req = unique_ptr<private_sharing_req,
325 decltype(&security_manager_private_sharing_req_free)>(
326 handle, security_manager_private_sharing_req_free);
328 return ERROR_IO_ERROR;
330 appid = strdup(sharing_data.app_id.c_str());
331 if (appid == nullptr) {
332 LOGE("Failed to get Sender appid");
333 return ERROR_OUT_OF_MEMORY;
336 ret = security_manager_private_sharing_req_set_owner_appid(req.get(), appid);
337 if (ret != SECURITY_MANAGER_SUCCESS) {
338 LOGE("Failed to set owner appid[%s][%d]", appid, ret);
339 return ERROR_IO_ERROR;
342 path_array = ConvertListToArray(sharing_data.shared_file_list);
343 if (path_array.empty()) {
344 LOGE("path_array is null");
345 return ERROR_IO_ERROR;
348 ret = security_manager_private_sharing_req_add_paths(req.get(),
349 const_cast<const char**>(path_array.data()), path_array.size());
350 if (ret != SECURITY_MANAGER_SUCCESS) {
351 LOGE("Failed to add paths [%d]", ret);
352 return ERROR_IO_ERROR;
355 target_array = ConvertListToArray(sharing_data.receiver_group_list);
356 if (target_array.empty()) {
357 LOGE("target_array is null");
358 return ERROR_IO_ERROR;
361 for (int i = 0; i < static_cast<int>(target_array.size()); i++) {
362 multimap<string, string>::iterator it;
363 for (it = receiver_group_map.begin(); it != receiver_group_map.end(); it++) {
364 if (it->first.compare(target_array[i]) == 0) {
365 ret = security_manager_private_sharing_req_set_target_appid(req.get(),
367 if (ret != SECURITY_MANAGER_SUCCESS) {
368 LOGE("Failed to set target appid [%s]", appid);
369 return ERROR_IO_ERROR;
372 ret = security_manager_private_sharing_drop(req.get());
373 if (ret != SECURITY_MANAGER_SUCCESS) {
374 LOGE("Failed to drop private sharing [%d]", ret);
375 return ERROR_IO_ERROR;
384 SharedFile::SharingData SharedFile::FindSharingData(string appid) {
385 if (sharing_data_list_.size() == 0 || appid.empty())
388 for (auto sharing_data : sharing_data_list_) {
389 if (sharing_data.app_id.compare(appid) == 0)
396 int SharedFile::SetPrivateSharing(list<shared_ptr<AbstractItem>> notiList,
397 multimap<string, string> receiver_group_map) {
398 if (notiList.empty() || receiver_group_map.empty()) {
399 LOGE("Invalid parameter");
400 return ERROR_INVALID_PARAMETER;
403 for (auto& i : notiList) {
404 SharingData sharing_data;
405 list<string> new_shared_file_list;
406 list<string> new_receiver_group_list;
408 list<string> shared_path_list = i->GetSharedPath();
409 if (shared_path_list.empty())
412 string appid = i->GetSenderAppId();
416 sharing_data = FindSharingData(appid);
417 if (!sharing_data.app_id.empty()) {
418 string noti_id = i->GetId();
419 list<string>::iterator it;
420 it = find_if(sharing_data.noti_id_list.begin(),
421 sharing_data.noti_id_list.end(),
422 [¬i_id](std::string id){
423 return id.compare(noti_id) == 0;
425 if (it == sharing_data.noti_id_list.end())
426 sharing_data.noti_id_list.push_back(noti_id);
428 for (auto& shared_path : shared_path_list) {
429 list<string>::iterator it;
430 it = find_if(sharing_data.shared_file_list.begin(),
431 sharing_data.shared_file_list.end(),
432 [&shared_path](std::string shared_file){
433 return shared_file.compare(shared_path) == 0;
435 if (it == sharing_data.shared_file_list.end()) {
436 sharing_data.shared_file_list.push_back(shared_path);
437 new_shared_file_list.push_back(shared_path);
441 list<string> receiver_list = i->GetReceiverList();
442 for (auto& receiver : receiver_list) {
443 list<string>::iterator it;
444 it = find_if(sharing_data.receiver_group_list.begin(),
445 sharing_data.receiver_group_list.end(),
446 [&receiver](std::string receiver_group){
447 return receiver_group.compare(receiver) == 0;
449 if (it == sharing_data.receiver_group_list.end()) {
450 sharing_data.receiver_group_list.push_back(receiver);
451 new_receiver_group_list.push_back(receiver);
455 sharing_data.app_id = appid;
456 sharing_data.dir = GetDir(*(shared_path_list.begin()));
457 sharing_data.noti_id_list.emplace_back(i->GetId());
458 sharing_data.shared_file_list = shared_path_list;
459 sharing_data.receiver_group_list = i->GetReceiverList();
460 sharing_data_list_.emplace_back(sharing_data);
462 new_shared_file_list = shared_path_list;
463 new_receiver_group_list = i->GetReceiverList();
466 if (SetSharingData(sharing_data, new_shared_file_list,
467 new_receiver_group_list, receiver_group_map) == ERROR_NONE)
471 LOGD("SetPrivateSharing");
475 int SharedFile::UpdatePrivateSharing(list<shared_ptr<AbstractItem>> notiList,
476 multimap<string, string> receiver_group_map) {
477 if (notiList.empty() || receiver_group_map.empty()) {
478 LOGE("Invalid parameter");
479 return ERROR_INVALID_PARAMETER;
482 for (auto& i : notiList) {
483 list<string> new_shared_file_list;
484 list<string> new_receiver_group_list;
485 list<string> shared_path_list = i->GetSharedPath();
486 if (shared_path_list.empty())
489 string appid = i->GetSenderAppId();
490 SharingData sharing_data = FindSharingData(appid);
491 if (appid.empty() || sharing_data.app_id.empty())
494 for (auto& shared_path : shared_path_list) {
495 std::list<std::string>::iterator it;
496 it = std::find_if(sharing_data.shared_file_list.begin(),
497 sharing_data.shared_file_list.end(),
498 [&shared_path](std::string shared_file){
499 return shared_file.compare(shared_path) == 0;
501 if (it == sharing_data.shared_file_list.end()) {
502 sharing_data.shared_file_list.push_back(shared_path);
503 new_shared_file_list.push_back(shared_path);
507 new_receiver_group_list = i->GetReceiverList();
508 if (SetSharingData(sharing_data, new_shared_file_list,
509 new_receiver_group_list, receiver_group_map) == ERROR_NONE)
513 LOGD("UpdatePrivateSharing");
517 int SharedFile::RemovePrivateSharing(list<shared_ptr<AbstractItem>> notiList,
518 multimap<string, string> receiver_group_map) {
519 if (notiList.empty() || receiver_group_map.empty()) {
520 LOGE("Invalid parameter");
521 return ERROR_INVALID_PARAMETER;
524 for (auto& i : notiList) {
525 string appid = i->GetSenderAppId();
529 SharingData sharing_data = FindSharingData(appid);
530 if (sharing_data.app_id.empty())
533 sharing_data.noti_id_list.remove(i->GetId());
534 if (sharing_data.noti_id_list.size() == 0) {
535 UnsetSharingData(sharing_data, receiver_group_map);
537 vector<char*> path_array = ConvertListToArray(sharing_data.shared_file_list);
538 if (!path_array.empty()) {
539 for (int i = 0; i < static_cast<int>(path_array.size()); i++) {
540 if (g_remove(path_array[i]) == -1)
541 LOGE("Failed to remove shared_file(%s)", path_array[i]);
544 g_rmdir(sharing_data.dir.c_str());
548 LOGD("RemovePrivateSharing");
552 int SharedFile::CopyPrivateFile(shared_ptr<item::AbstractItem> item) {
553 if (item == nullptr) {
554 LOGE("Invalid paramenter");
555 return ERROR_INVALID_PARAMETER;
558 list<map<string, string>> path_map_list = item->GetPathMapList();
559 if (path_map_list.empty())
562 if (!MakeDir(GetDir((*(path_map_list.begin())).begin()->second).c_str()))
563 return ERROR_IO_ERROR;
565 list<map<string, string>>::iterator list_it;
566 for (list_it = path_map_list.begin(); list_it != path_map_list.end(); ++list_it) {
567 map<string, string>::iterator map_it;
568 for (map_it = (*list_it).begin(); map_it != (*list_it).end(); map_it++) {
569 CopyFile((map_it->first).c_str(), (map_it->second).c_str());
577 } // namespace notification