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