Merge "[DF180327-00886] Add *.xml to the extension translation table" into tizen
[platform/framework/web/download-provider.git] / agent / download-agent-mime-util.c
1 /*
2  * Copyright (c) 2012 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 #include <string.h>
18 #include <stdlib.h>
19
20 #include <xdgmime.h>
21
22 #include "download-agent-debug.h"
23 #include "download-agent-mime-util.h"
24 #include "download-agent-pthread.h"
25
26 #define IS_PROHIBITED_CHAR(c)   ((c) == '/' || (c) == '\\' || (c) == '?' || (c) == '%' || (c) == '*' || (c) == ':' || (c) == '|' || (c) == '"' || (c) == '<' || (c) == '>')
27 #define IS_SPACE_CHARACTER(c)   ((c) == '\t')
28
29 #define MAX_EXT_NAME_LEN 12
30 #define MAX_EXT_TABLE_INDEX 18
31 Ext_translation_table ext_trans_table[MAX_EXT_TABLE_INDEX] = {
32         {"*.xla",                       "*.xls"},
33         {"*.pot",                       "*.ppt"},
34         {"*.xsl",                       "*.xml"},
35         {"*.spl",                       "*.swf"},
36         {"*.oga",                       "*.ogg"},
37         {"*.jpe",                       "*.jpg"},//5
38         {"*.CSSL",                      "*.css"},
39         {"*.htm",                       "*.html"},
40         {"*.hxx",                       "*.hpp"},
41         {"*.c++",                       "*.cpp"},
42         {"CMakeLists.txt",      "*.cmake"},//10
43         {"*.ime",                       "*.imy"},
44         {"Makefile",            "makefile"},
45         {"*.3g2",                       "*.3gp"},
46         {"*.mp2",                       "*.mpg"},
47         {"*.divx",                      "*.avi"},//15
48         {"*.jsm",                       "*.js"},
49         {"*.xsd",                       "*.xml"},
50 };
51 /* This is samsung mime policy
52  * 1. if the mime is audio/m4a, the extension name is defined as "m4a" for launching music player
53  */
54 #ifdef _SAMSUNG_MIME_POLICY
55 #define MAX_SEC_MIME_TABLE_INDEX 1
56 struct sec_mime_table_t {
57         char *mime;
58         char *ext;
59 };
60 struct sec_mime_table_t sec_mime_table[MAX_SEC_MIME_TABLE_INDEX] = {
61         {"audio/m4a",           "m4a"},
62 };
63 #endif
64
65 const char *ambiguous_MIME_Type_list[] = {
66         "text/plain",
67         "application/octet-stream"
68 };
69
70 /* Because xdgmime is not thread safety, this mutex is necessary */
71 pthread_mutex_t mutex_for_xdgmime = PTHREAD_MUTEX_INITIALIZER;
72
73 da_bool_t is_ambiguous_MIME_Type(const char *in_mime_type)
74 {
75         if (!in_mime_type)
76                 return DA_FALSE;
77
78         int index = 0;
79         int list_size = sizeof(ambiguous_MIME_Type_list) / sizeof(const char *);
80         for (index = 0 ; index < list_size ; index++) {
81                 if (0 == strncmp(in_mime_type, ambiguous_MIME_Type_list[index],
82                                         strlen(ambiguous_MIME_Type_list[index]))) {
83                         //DA_SECURE_LOGD("It is ambiguous! [%s]", ambiguous_MIME_Type_list[index]);
84                         return DA_TRUE;
85                 }
86         }
87
88         return DA_FALSE;
89 }
90
91 da_ret_t da_mime_get_ext_name(char *mime, char **ext)
92 {
93         da_ret_t ret = DA_RESULT_OK;
94         const char **extlist = DA_NULL;
95         const char *unaliased_mimetype = DA_NULL;
96         char ext_temp[DA_MAX_STR_LEN] = {0,};
97         char *temp = NULL;
98
99         DA_LOGV("");
100
101         if (DA_NULL == mime || DA_NULL == ext) {
102                 ret = DA_ERR_INVALID_ARGUMENT;
103                 DA_LOGE("Invalid mime type");
104                 goto ERR;
105         }
106         //      DA_SECURE_LOGD("mime str[%s]ptr[%p]len[%d]",mime,mime,strlen(mime));
107         /* unaliased_mimetype means representative mime among similar types */
108         DA_MUTEX_LOCK(&mutex_for_xdgmime);
109         unaliased_mimetype = xdg_mime_unalias_mime_type(mime);
110
111         if (unaliased_mimetype == DA_NULL) {
112                 ret = DA_ERR_INVALID_MIME_TYPE;
113                 DA_LOGI("Invalid mime type : No unsaliased mime type");
114                 DA_MUTEX_UNLOCK(&mutex_for_xdgmime);
115                 goto ERR;
116         }
117         DA_SECURE_LOGD("unaliased_mimetype[%s]\n", unaliased_mimetype);
118
119         /* Get extension name from shared-mime-info */
120         extlist = xdg_mime_get_file_names_from_mime_type(unaliased_mimetype);
121         DA_MUTEX_UNLOCK(&mutex_for_xdgmime);
122         if (extlist == DA_NULL || *extlist == DA_NULL) {
123                 int i = 0;
124                 ret = DA_ERR_INVALID_MIME_TYPE;
125                 DA_LOGV("No extension list");
126 #ifdef _SAMSUNG_MIME_POLICY
127                 for (i = 0; i < MAX_SEC_MIME_TABLE_INDEX; i++) {
128                         if (strncmp(sec_mime_table[i].mime, mime, strlen(mime)) == 0) {
129                                 strncpy(ext_temp, sec_mime_table[i].ext, DA_MAX_STR_LEN-1);
130                                 ret = DA_RESULT_OK;
131                                 break;
132                         }
133                 }
134 #endif
135         } else { /* For drm case, this else statement is needed */
136                 strncpy(ext_temp, *extlist, DA_MAX_STR_LEN - 1);
137                 /* If only one extension name is existed, don't enter here */
138                 while (*extlist != NULL) {
139                         int i = 0;
140                         /* If there are existed many extension names,
141                          *  try to search common extension name from table
142                          *  with first mime type at extension list*/
143                         for (i = 0; i < MAX_EXT_TABLE_INDEX; i++) {
144                                 if (strncmp(ext_trans_table[i].standard, *extlist,
145                                                         strlen(*extlist)) == 0) {
146                                         memset(ext_temp, 0x00, DA_MAX_STR_LEN);
147                                         strncpy(ext_temp, ext_trans_table[i].normal, DA_MAX_STR_LEN-1);
148                                         break;
149                                 }
150                         }
151                         DA_LOGV("index[%d]\n", i);
152                         /* If there is a mime at extension transform table */
153                         if (i < MAX_EXT_TABLE_INDEX)
154                                 break;
155                         extlist++;
156                 }
157         }
158
159         if (strlen(ext_temp) < 1) {
160                 /* If there is no mime string for OMA descriptor mime type */
161                 if (strncmp(DD_MIME_STR, mime, strlen(DD_MIME_STR)) == 0) {
162                         strncpy(ext_temp, DD_EXT_STR, DA_MAX_STR_LEN - 1);
163                         ret = DA_RESULT_OK;
164                         /* If there is no extension name for "applicaion/vnd.oma.drm.messeages"
165                          *  at shared-mime-info*/
166                 } else if (strncmp(DRM_MIME_MSG_STR, mime, strlen(DRM_MIME_MSG_STR)) ==
167                                 0) {
168                         strncpy(ext_temp, DRM_EXT_STR, DA_MAX_STR_LEN - 1);
169                         /* If there is extension name at extlist, the return value can have an error.*/
170                         ret = DA_RESULT_OK;
171                 } else {
172                         ret = DA_ERR_INVALID_MIME_TYPE;
173                         DA_LOGI("Invalid mime type : no extension name at list");
174                 }
175         }
176         if (ret != DA_RESULT_OK)
177                 goto ERR;
178
179         temp = strchr(ext_temp, '.');
180         if (temp == NULL)
181                 temp = ext_temp;
182         else
183                 temp++;
184
185         DA_SECURE_LOGD("final extension name:[%s]", temp);
186         *ext = (char*)calloc(1, strlen(temp) + 1);
187         if (*ext != DA_NULL) {
188                 strncpy(*ext, temp, strlen(temp));
189         } else  {
190                 ret = DA_ERR_FAIL_TO_MEMALLOC ;
191                 goto ERR ;
192         }
193 ERR:
194         return ret;
195 }
196
197 da_bool_t da_get_extension_name_from_url(char *url, char **ext)
198 {
199         da_bool_t ret = DA_TRUE;
200         char *buff = DA_NULL;
201         char *temp_str = DA_NULL;
202         int buf_len = 0;
203
204         DA_LOGV("");
205
206         if (DA_NULL == url || DA_NULL == ext) {
207                 ret = DA_FALSE;
208                 DA_LOGE("Invalid Argument");
209                 return ret;
210         }
211
212         if ((temp_str = strrchr(url, '/'))) {
213                 if ((buff = strrchr(temp_str, '.'))) {
214                         char *q = DA_NULL;
215                         buff++;
216
217                         /* check to exist "?" after extension name */
218                         q = strrchr(buff, '?');
219                         if (q)
220                                 buf_len = strlen(buff) - strlen(q);
221                         else
222                                 buf_len = strlen(buff);
223
224                         /* check extention length refer to https://en.wikipedia.org/wiki/List_of_filename_extensions */
225                         if (buf_len > MAX_EXT_NAME_LEN)
226                                 return ret;
227
228                         *ext = (char*) calloc(1, buf_len + 1) ;
229
230                         if (DA_NULL == *ext) {
231                                 ret = DA_FALSE;
232                                 DA_LOGE("Memory Fail");
233                                 goto ERR;
234                         }
235                         strncpy(*ext, buff, buf_len);
236                         DA_SECURE_LOGD("extention name[%s]", *ext);
237                         return ret;
238                 }
239         }
240 ERR:
241         if (*ext) {
242                 free(*ext);
243                 *ext = DA_NULL;
244         }
245         return ret;
246 }
247
248 /* FIXME move this function to another file */
249 da_bool_t da_get_file_name_from_url(char *url, char **name)
250 {
251         da_bool_t ret = DA_TRUE;
252         char *buff = DA_NULL;
253         char *Start = NULL;
254         char *End = NULL;
255         char c = 0;
256         int i = 0;
257         int j = 0;
258         int len_name = 0;
259         char name_buff[DA_MAX_FILE_NAME_LEN + 1] = {0,};
260
261         DA_LOGV("");
262
263         if (DA_NULL == url || DA_NULL == name) {
264                 ret = DA_FALSE;
265                 DA_LOGE("Invalid Argument");
266                 goto ERR;
267         }
268
269         if (!strstr(url, "http") && !strstr(url, "https")) {
270                 ret = DA_FALSE;
271                 DA_LOGE("Invalid Argument");
272                 goto ERR;
273         }
274
275         buff = (char*) calloc(1, strlen(url) +1);
276         if (DA_NULL == buff) {
277                 ret = DA_FALSE;
278                 DA_LOGE("Memory Fail");
279                 goto ERR;
280         }
281
282         while ((c = url[i++]) != 0) {
283                 if (c == '%') {
284                         char buffer[3] = {0,};
285                         buffer[0] = url[i++];
286                         buffer[1] = url[i++];
287                         buff[j++] = (char)strtol(buffer, NULL, 16);
288                 } else {
289                         buff[j++] = c;
290                 }
291         }
292         End = strstr(buff, "?");
293         if (DA_NULL != End) {
294                 Start = End -1;
295                 while (*(Start) != '/')
296                         Start--;
297
298                 if ((*(Start) == '/') && ((len_name = (End - Start)) > 1)) {
299                         Start++;
300                         if (DA_MAX_FILE_NAME_LEN <= len_name)   {
301                                 strncpy(name_buff, Start, DA_MAX_FILE_NAME_LEN);
302                                 name_buff[DA_MAX_FILE_NAME_LEN] = '\0';
303                         } else {
304                                 strncpy(name_buff, Start, len_name);
305                                 name_buff[len_name] = '\0';
306                         }
307                 } else {
308                         ret = DA_FALSE;
309                         goto ERR ; /*Name not found*/
310                 }
311         } else {
312                 int urlLen = strlen(buff);
313                 int Start_pos = 0;
314                 Start_pos = urlLen - 1;
315
316                 while (Start_pos > 0) {
317                         if (buff[Start_pos] == '/')
318                                 break;
319                         Start_pos--;
320                 }
321                 Start_pos++;
322                 if (Start_pos == 0 || urlLen - Start_pos <= 0) {
323                         ret = DA_FALSE;
324                         goto ERR;
325                 }
326                 while (Start_pos < urlLen) {
327                         name_buff[len_name++] = buff[Start_pos++];
328                         if (DA_MAX_FILE_NAME_LEN <= len_name) {
329                                 name_buff[DA_MAX_FILE_NAME_LEN] = '\0';
330                                 break;
331                         }
332                 }
333         }
334
335         if (len_name) {
336                 End = strrchr(name_buff, '.');
337                 if (End != NULL)
338                         *End = '\0';
339                 //              DA_SECURE_LOGD("file name BEFORE removing prohibited character = %s", name_buff);
340                 delete_prohibited_char(name_buff, strlen(name_buff));
341                 len_name = strlen(name_buff);
342                 *name = (char*) calloc(1, len_name + 1);
343                 if (*name)
344                         strncpy(*name, name_buff, len_name);
345         }
346         //      DA_SECURE_LOGD("Extracted file name : %s", *name);
347 ERR:
348         if (buff) {
349                 free(buff);
350                 buff = DA_NULL;
351         }
352         return ret;
353 }
354
355 void delete_prohibited_char(char *szTarget, int str_len)
356 {
357         char *chk_str = NULL;
358         int i = 0;
359         int j = 0;
360         int tar_len = 0;
361         DA_LOGD("");
362         if (szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) {
363                 DA_LOGE("Invaild Parameter\n");
364                 return;
365         }
366
367         chk_str = (char *)calloc(1, str_len + 1);
368         if (chk_str == NULL)
369                 return;
370
371         while (szTarget[j] != '\0') {
372                 if (IS_PROHIBITED_CHAR(szTarget[j]) == DA_FALSE &&
373                                 IS_SPACE_CHARACTER(szTarget[j]) == DA_FALSE) {
374                         chk_str[i] = szTarget[j];
375                         i++;
376                 }
377                 j++;
378         }
379
380         chk_str[i] = '\0';
381         tar_len = strlen(chk_str);
382
383         if (tar_len <= 0)
384                 szTarget[0] = '\0';
385         else {
386                 for (i = 0; i < tar_len; i++)
387                         szTarget[i] = chk_str[i];
388                 szTarget[i] = '\0';
389         }
390
391         if (chk_str != NULL)
392                 free(chk_str);
393
394         return;
395 }
396
397 #ifdef _ENABLE_OMA_DRM
398 da_bool_t is_content_drm_dcf(char *content_type)
399 {
400         if (content_type == DA_NULL)
401                 return DA_FALSE;
402
403         if (0 == strcmp(content_type, DRM_MIME_CONTENT_STR)) {
404                 DA_LOGV("DRM_DM content");
405                 return DA_TRUE;
406         } else {
407                 return DA_FALSE;
408         }
409 }
410
411 da_bool_t is_content_drm_dm(char *content_type)
412 {
413         if (content_type == DA_NULL)
414                 return DA_FALSE;
415
416         if (0 == strcmp(content_type, DRM_MIME_MSG_STR)) {
417                 DA_LOGV("DRM_DM content");
418                 return DA_TRUE;
419         } else {
420                 return DA_FALSE;
421         }
422 }
423 #endif
424
425 da_ret_t get_extension_from_mime_type(char *mime_type, char **extension)
426 {
427         da_ret_t ret = DA_RESULT_OK;
428         char *ext = DA_NULL;
429
430         DA_LOGV("");
431         if (DA_NULL == mime_type || DA_NULL == extension) {
432                 DA_LOGE("received mime_type is null");
433                 ret = DA_ERR_INVALID_ARGUMENT;
434                 goto ERR;
435         }
436         //      DA_SECURE_LOGD("input mime type = %s", mime_type);
437         if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) {
438                 DA_LOGE("can't find proper extension!");
439                 goto ERR;
440         }
441         *extension = ext;
442         //      DA_SECURE_LOGD("found extension = %s", *extension);
443
444 ERR:
445         return ret;
446 }
447