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