[DF180327-00886] Add *.xml to the extension translation table
[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 extention length refer to https://en.wikipedia.org/wiki/List_of_filename_extensions */
218                         if (strlen(buff) > MAX_EXT_NAME_LEN)
219                                 return ret;
220
221                         /* check to exist "?" after extension name */
222                         q = strrchr(buff, '?');
223                         if (q)
224                                 buf_len = strlen(buff) - strlen(q);
225                         else
226                                 buf_len = strlen(buff);
227                         *ext = (char*) calloc(1, buf_len + 1) ;
228
229                         if (DA_NULL == *ext) {
230                                 ret = DA_FALSE;
231                                 DA_LOGE("Memory Fail");
232                                 goto ERR;
233                         }
234                         strncpy(*ext, buff, buf_len);
235                         DA_SECURE_LOGD("extention name[%s]", *ext);
236                         return ret;
237                 }
238         }
239 ERR:
240         if (*ext) {
241                 free(*ext);
242                 *ext = DA_NULL;
243         }
244         return ret;
245 }
246
247 /* FIXME move this function to another file */
248 da_bool_t da_get_file_name_from_url(char *url, char **name)
249 {
250         da_bool_t ret = DA_TRUE;
251         char *buff = DA_NULL;
252         char *Start = NULL;
253         char *End = NULL;
254         char c = 0;
255         int i = 0;
256         int j = 0;
257         int len_name = 0;
258         char name_buff[DA_MAX_FILE_NAME_LEN + 1] = {0,};
259
260         DA_LOGV("");
261
262         if (DA_NULL == url || DA_NULL == name) {
263                 ret = DA_FALSE;
264                 DA_LOGE("Invalid Argument");
265                 goto ERR;
266         }
267
268         if (!strstr(url, "http") && !strstr(url, "https")) {
269                 ret = DA_FALSE;
270                 DA_LOGE("Invalid Argument");
271                 goto ERR;
272         }
273
274         buff = (char*) calloc(1, strlen(url) +1);
275         if (DA_NULL == buff) {
276                 ret = DA_FALSE;
277                 DA_LOGE("Memory Fail");
278                 goto ERR;
279         }
280
281         while ((c = url[i++]) != 0) {
282                 if (c == '%') {
283                         char buffer[3] = {0,};
284                         buffer[0] = url[i++];
285                         buffer[1] = url[i++];
286                         buff[j++] = (char)strtol(buffer, NULL, 16);
287                 } else {
288                         buff[j++] = c;
289                 }
290         }
291         End = strstr(buff, "?");
292         if (DA_NULL != End) {
293                 Start = End -1;
294                 while (*(Start) != '/')
295                         Start--;
296
297                 if ((*(Start) == '/') && ((len_name = (End - Start)) > 1)) {
298                         Start++;
299                         if (DA_MAX_FILE_NAME_LEN <= len_name)   {
300                                 strncpy(name_buff, Start, DA_MAX_FILE_NAME_LEN);
301                                 name_buff[DA_MAX_FILE_NAME_LEN] = '\0';
302                         } else {
303                                 strncpy(name_buff, Start, len_name);
304                                 name_buff[len_name] = '\0';
305                         }
306                 } else {
307                         ret = DA_FALSE;
308                         goto ERR ; /*Name not found*/
309                 }
310         } else {
311                 int urlLen = strlen(buff);
312                 int Start_pos = 0;
313                 Start_pos = urlLen - 1;
314
315                 while (Start_pos > 0) {
316                         if (buff[Start_pos] == '/')
317                                 break;
318                         Start_pos--;
319                 }
320                 Start_pos++;
321                 if (Start_pos == 0 || urlLen - Start_pos <= 0) {
322                         ret = DA_FALSE;
323                         goto ERR;
324                 }
325                 while (Start_pos < urlLen) {
326                         name_buff[len_name++] = buff[Start_pos++];
327                         if (DA_MAX_FILE_NAME_LEN <= len_name) {
328                                 name_buff[DA_MAX_FILE_NAME_LEN] = '\0';
329                                 break;
330                         }
331                 }
332         }
333
334         if (len_name) {
335                 End = strrchr(name_buff, '.');
336                 if (End != NULL)
337                         *End = '\0';
338                 //              DA_SECURE_LOGD("file name BEFORE removing prohibited character = %s", name_buff);
339                 delete_prohibited_char(name_buff, strlen(name_buff));
340                 len_name = strlen(name_buff);
341                 *name = (char*) calloc(1, len_name + 1);
342                 if (*name)
343                         strncpy(*name, name_buff, len_name);
344         }
345         //      DA_SECURE_LOGD("Extracted file name : %s", *name);
346 ERR:
347         if (buff) {
348                 free(buff);
349                 buff = DA_NULL;
350         }
351         return ret;
352 }
353
354 void delete_prohibited_char(char *szTarget, int str_len)
355 {
356         char *chk_str = NULL;
357         int i = 0;
358         int j = 0;
359         int tar_len = 0;
360         DA_LOGD("");
361         if (szTarget == NULL || str_len <= 0 || strlen(szTarget) != str_len) {
362                 DA_LOGE("Invaild Parameter\n");
363                 return;
364         }
365
366         chk_str = (char *)calloc(1, str_len + 1);
367         if (chk_str == NULL)
368                 return;
369
370         while (szTarget[j] != '\0') {
371                 if (IS_PROHIBITED_CHAR(szTarget[j]) == DA_FALSE &&
372                                 IS_SPACE_CHARACTER(szTarget[j]) == DA_FALSE) {
373                         chk_str[i] = szTarget[j];
374                         i++;
375                 }
376                 j++;
377         }
378
379         chk_str[i] = '\0';
380         tar_len = strlen(chk_str);
381
382         if (tar_len <= 0)
383                 szTarget[0] = '\0';
384         else {
385                 for (i = 0; i < tar_len; i++)
386                         szTarget[i] = chk_str[i];
387                 szTarget[i] = '\0';
388         }
389
390         if (chk_str != NULL)
391                 free(chk_str);
392
393         return;
394 }
395
396 #ifdef _ENABLE_OMA_DRM
397 da_bool_t is_content_drm_dcf(char *content_type)
398 {
399         if (content_type == DA_NULL)
400                 return DA_FALSE;
401
402         if (0 == strcmp(content_type, DRM_MIME_CONTENT_STR)) {
403                 DA_LOGV("DRM_DM content");
404                 return DA_TRUE;
405         } else {
406                 return DA_FALSE;
407         }
408 }
409
410 da_bool_t is_content_drm_dm(char *content_type)
411 {
412         if (content_type == DA_NULL)
413                 return DA_FALSE;
414
415         if (0 == strcmp(content_type, DRM_MIME_MSG_STR)) {
416                 DA_LOGV("DRM_DM content");
417                 return DA_TRUE;
418         } else {
419                 return DA_FALSE;
420         }
421 }
422 #endif
423
424 da_ret_t get_extension_from_mime_type(char *mime_type, char **extension)
425 {
426         da_ret_t ret = DA_RESULT_OK;
427         char *ext = DA_NULL;
428
429         DA_LOGV("");
430         if (DA_NULL == mime_type || DA_NULL == extension) {
431                 DA_LOGE("received mime_type is null");
432                 ret = DA_ERR_INVALID_ARGUMENT;
433                 goto ERR;
434         }
435         //      DA_SECURE_LOGD("input mime type = %s", mime_type);
436         if (DA_RESULT_OK != (ret = da_mime_get_ext_name(mime_type, &ext))) {
437                 DA_LOGE("can't find proper extension!");
438                 goto ERR;
439         }
440         *extension = ext;
441         //      DA_SECURE_LOGD("found extension = %s", *extension);
442
443 ERR:
444         return ret;
445 }
446