a0b6233f9fa9eb4c1b000fd1b6655c7e72ced982
[platform/core/api/media-content.git] / src / media_util_private.c
1 /*
2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3 *
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
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
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.
15 */
16
17
18 #include <dirent.h>
19 #include <fcntl.h>
20 #include <media_info_private.h>
21 #include <storage.h>
22 #include <system_info.h>
23 #include <sys/stat.h>
24
25 #ifdef _USE_SENIOR_MODE
26 #include <media_util_private.h>
27 #endif
28
29 static int MEDIA_CONTENT_OTHER_SUPPORT = -1;
30
31 bool _media_util_check_support_media_type(const char *path)
32 {
33         int ret = SYSTEM_INFO_ERROR_NONE;
34         int media_type = -1;
35         bool is_supported = false;
36
37         content_retvm_if(!STRING_VALID(path), false, "path is empty");
38
39         if (MEDIA_CONTENT_OTHER_SUPPORT == -1) {
40                 ret = system_info_get_platform_bool("http://tizen.org/feature/content.scanning.others", &is_supported);
41                 if (ret != SYSTEM_INFO_ERROR_NONE) {
42                         content_debug("SYSTEM_INFO_ERROR: content.scanning.others [%d]", ret);
43                         return false;
44                 }
45
46                 MEDIA_CONTENT_OTHER_SUPPORT = is_supported;
47         }
48
49         /* If not, check media type */
50         if (!MEDIA_CONTENT_OTHER_SUPPORT) {
51                 ret = media_svc_get_media_type(path, &media_type);
52                 content_retvm_if(ret != MS_MEDIA_ERR_NONE, false, "Failed to get media type");
53
54                 if (media_type == MEDIA_CONTENT_TYPE_OTHERS)
55                         return false;
56         }
57
58         return true;
59 }
60
61 int _media_util_check_file_exist(const char *path)
62 {
63         int exist;
64
65         /* check the file exits actually */
66         exist = open(path, O_RDONLY);
67         if (exist < 0) {
68                 if (errno == EACCES || errno == EPERM) {
69                         content_stderror("open file fail");
70                         content_sec_debug("path [%s]", path);
71                         return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
72                 } else {
73                         content_stderror("open file fail");
74                         content_sec_debug("path [%s]", path);
75                         return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
76                 }
77         }
78
79         close(exist);
80
81         return MEDIA_CONTENT_ERROR_NONE;
82 }
83
84 void _media_util_trim_path(const char *input_path, char **output_path)
85 {
86         gchar **name_list = NULL;
87         gchar *tmp_path = NULL;
88
89         if (!STRING_VALID(input_path) || output_path == NULL)
90                 return;
91
92         /* Workflow example
93                 Input : /a/b//c/
94                 After g_strsplit() : {'','a','b','','c',''}
95                 After g_build_pathv() : a/b/c
96                 After g_strdup_printf() : /a/b/c
97         */
98         name_list = g_strsplit(input_path, "/", -1);
99         if (!name_list)
100                 return;
101
102         tmp_path = g_build_pathv(G_DIR_SEPARATOR_S, name_list);
103         g_strfreev(name_list);
104         if (!tmp_path)
105                 return;
106
107         /* g_build_pathv does not add root '/' */
108         *output_path = g_strdup_printf("/%s", tmp_path);
109         g_free(tmp_path);
110 }
111
112
113 int _media_util_get_file_time(const char *path)
114 {
115         struct stat statbuf;
116         int ret = 0;
117
118         memset(&statbuf, 0, sizeof(struct stat));
119         ret = stat(path, &statbuf);
120         if (ret == -1) {
121                 content_stderror("stat failed");
122                 return ret;
123         }
124
125         return statbuf.st_mtime;
126 }
127
128 bool _media_util_is_ignorable_file(const char *path)
129 {
130         content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid path");
131
132         char *tmp_path = NULL;
133         char *org_path = NULL;
134
135 #ifndef _USE_TVPD_MODE
136         char replace[MAX_PATH_LEN] = {0, };
137 #endif
138
139         /* Check is exist (It may be the path to the deleted file) */
140         if (!g_file_test(path, G_FILE_TEST_EXISTS)) {
141                 content_sec_debug("removed path[%s]", path);
142                 return false;
143         }
144
145         /* Check symbolic link file */
146         if (g_file_test(path, G_FILE_TEST_IS_SYMLINK)) {
147                 content_error("symbolic link(file)");
148                 content_sec_debug("path : %s", path);
149                 return true;
150         }
151
152         /* Check hidden path */
153         if (strstr(path, "/.") != NULL) {
154                 content_error("hidden path");
155                 content_sec_debug("path : %s", path);
156                 return true;
157         }
158
159         /* Check symbolic directory */
160         tmp_path = realpath(path, NULL);
161         /* Get trimmed path */
162         _media_util_trim_path(path, &org_path);
163
164 #ifdef _USE_TVPD_MODE
165         if (g_strcmp0(tmp_path, org_path) != 0) {
166                 content_error("symbolic link(directory)");
167                 content_sec_debug("path[%s] real[%s]", org_path, tmp_path);
168                 SAFE_FREE(tmp_path);
169                 g_free(org_path);
170                 return true;
171         }
172 #else
173         if (g_str_has_prefix(tmp_path, MEDIA_SHARE_PATH)) {
174                 /* If shared dirctory, it should be change path to TZ_USER_SHARE from realpath */
175                 snprintf(replace, MAX_PATH_LEN, "%s%s", tzplatform_getenv(TZ_USER_MEDIASHARED), tmp_path + strlen(MEDIA_SHARE_PATH));
176                 if (g_strcmp0(replace, org_path) != 0) {
177                         content_error("symbolic link(directory)");
178                         content_sec_debug("path[%s] real[%s]", org_path, tmp_path);
179                         SAFE_FREE(tmp_path);
180                         g_free(org_path);
181                         return true;
182                 }
183         } else {
184                 if (g_strcmp0(tmp_path, org_path) != 0) {
185                         content_error("symbolic link(directory)");
186                         content_sec_debug("path[%s] real[%s]", org_path, tmp_path);
187                         SAFE_FREE(tmp_path);
188                         g_free(org_path);
189                         return true;
190                 }
191         }
192 #endif
193         SAFE_FREE(tmp_path);
194         g_free(org_path);
195
196         return false;
197 }
198
199 static bool __is_scan_ignore_exist(const char *path)
200 {
201         const char *scan_ignore = ".scan_ignore";
202         char *ignore_path = NULL;
203         gboolean result = FALSE;
204
205         if (!STRING_VALID(path))
206                 return false;
207
208         ignore_path = g_build_path(G_DIR_SEPARATOR_S, path, scan_ignore, NULL);
209         result = g_file_test(ignore_path, G_FILE_TEST_EXISTS);
210
211         if (result)
212                 content_error("scan ignore file exist [%s]", ignore_path);
213
214         g_free(ignore_path);
215
216         return (bool)result;
217 }
218
219 bool _media_util_is_ignorable_dir(const char *dir_path)
220 {
221         int ret = MEDIA_CONTENT_ERROR_NONE;
222         ms_user_storage_type_e storage_type = MS_USER_STORAGE_INTERNAL;
223
224         content_retvm_if(!STRING_VALID(dir_path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "invalid dir_path");
225         content_sec_debug("dir_path : %s", dir_path);
226
227         /*1. Check Hidden Directory*/
228         if (strstr(dir_path, "/.") != NULL) {
229                 content_error("hidden path");
230                 return true;
231         }
232
233         /*2. Check Scan Ignore Directory*/
234         ret = ms_user_get_storage_type(_content_get_uid(), dir_path, &storage_type);
235         if (ret != MS_MEDIA_ERR_NONE) {
236                 content_error("ms_user_get_storage_type failed : %d", ret);
237                 return false;
238         }
239
240         char *leaf_path = NULL;
241         char search_path[MAX_PATH_LEN] = {0, };
242
243         SAFE_STRLCPY(search_path, dir_path, sizeof(search_path));
244
245         while (STRING_VALID(search_path)) {
246                 if (__is_scan_ignore_exist(search_path))
247                         return true;
248
249                 leaf_path = strrchr(search_path, '/');
250                 if (!leaf_path)
251                         break;
252
253                 search_path[leaf_path - search_path] = '\0';
254         }
255
256         return false;
257 }
258
259 int _media_content_check_dir(const char *path)
260 {
261         DIR *dp = NULL;
262         char *real = NULL;
263         char *origin = NULL;
264 #ifndef _USE_TVPD_MODE
265         char result_path[MAX_PATH_LEN] = {0, };
266 #endif
267         dp = opendir(path);
268         if (dp == NULL) {
269                 if (errno == EACCES || errno == EPERM) {
270                         content_stderror("open dir fail");
271                         content_sec_error("path [%s]", path);
272                         return MEDIA_CONTENT_ERROR_PERMISSION_DENIED;
273                 } else {
274                         content_stderror("open dir fail");
275                         content_sec_error("path [%s]", path);
276                         return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
277                 }
278         }
279
280         closedir(dp);
281
282         /* Check symbolic link directory */
283         real = realpath(path, NULL);
284         /* Get trimmed path */
285         _media_util_trim_path(path, &origin);
286
287 #ifdef _USE_TVPD_MODE
288         if (g_strcmp0(real, origin) != 0) {
289                 content_error("symbolic link(directory)");
290                 content_sec_debug("path[%s] real[%s]", origin, real);
291                 SAFE_FREE(real);
292                 g_free(origin);
293                 return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
294         }
295 #else
296         if (g_str_has_prefix(real, MEDIA_SHARE_PATH)) {
297                 /* If shared dirctory, it should be change path to TZ_USER_SHARE from realpath */
298                 snprintf(result_path, MAX_PATH_LEN, "%s%s", tzplatform_getenv(TZ_USER_MEDIASHARED), real + strlen(MEDIA_SHARE_PATH));
299                 if (g_strcmp0(result_path, origin) != 0) {
300                         content_error("symbolic link(directory)");
301                         content_sec_debug("path[%s] real[%s]", origin, real);
302                         SAFE_FREE(real);
303                         g_free(origin);
304                         return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
305                 }
306         } else {
307                 if (g_strcmp0(real, origin) != 0) {
308                         content_error("symbolic link(directory)");
309                         content_sec_debug("path[%s] real[%s]", origin, real);
310                         SAFE_FREE(real);
311                         g_free(origin);
312                         return MEDIA_CONTENT_ERROR_INVALID_PARAMETER;
313                 }
314         }
315 #endif
316
317         SAFE_FREE(real);
318         g_free(origin);
319
320         return MEDIA_CONTENT_ERROR_NONE;
321 }
322
323
324 /* FIXME : If there are no issue reports related to this, it will be deleted in tizen 6.5 or after. */
325 char * _media_content_replace_path_in_condition(const char *condition)
326 {
327         return g_strdup(condition);
328 #if 0
329         char **split_list = NULL;
330         char *result = NULL;
331
332         if (!STRING_VALID(MEDIA_ROOT_PATH_INTERNAL_OLD) || !STRING_VALID(MEDIA_ROOT_PATH_INTERNAL))
333                 return NULL;
334
335         content_sec_debug("Old condition[%s]", condition);
336
337         split_list = g_strsplit(condition, MEDIA_ROOT_PATH_INTERNAL_OLD, -1);
338         if (!split_list)
339                 return NULL;
340
341         result = g_strjoinv(MEDIA_ROOT_PATH_INTERNAL, split_list);
342         g_strfreev(split_list);
343
344         return result;
345 #endif
346 }
347
348 /* FIXME : If there are no issue reports related to this, it will be deleted in Tizen 6.5 or after. */
349 int _media_content_replace_path(const char *path, char *replace_path)
350 {
351         content_retvm_if(!STRING_VALID(path), MEDIA_CONTENT_ERROR_INVALID_PARAMETER, "Invalid path");
352
353         snprintf(replace_path, MAX_PATH_LEN, "%s", path);
354 #if 0
355         if (strncmp(path, MEDIA_ROOT_PATH_INTERNAL_OLD, strlen(MEDIA_ROOT_PATH_INTERNAL_OLD)) == 0) {
356                 content_sec_debug("Old path[%s]", path);
357                 snprintf(replace_path, MAX_PATH_LEN, "%s%s", MEDIA_ROOT_PATH_INTERNAL, path + strlen(MEDIA_ROOT_PATH_INTERNAL_OLD));
358         } else {
359                 snprintf(replace_path, MAX_PATH_LEN, "%s", path);
360         }
361 #endif
362
363         return MEDIA_CONTENT_ERROR_NONE;
364 }
365
366 #ifdef _USE_SENIOR_MODE
367 bool _media_content_is_support_senior_mode()
368 {
369         bool bSupportSeniorMode = false;
370
371         if (system_info_get_value_bool(SYSTEM_INFO_KEY_GET_SENIOR_MODE_SUPPORTED, &bSupportSeniorMode) != SYSTEM_INFO_ERROR_NONE) {
372                 content_debug("Get senior mode support failed");
373                 return false;
374         }
375         /* content_debug("Senior mode Support : [%d]", bSupportSeniorMode); */
376         return bSupportSeniorMode;
377 }
378 #endif
379