Retry read() when getting EAGAIN
[platform/framework/web/download-provider.git] / agent / download-agent-http-msg-handler.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 #include <ctype.h>
20 #include <curl/curl.h>
21
22 #include "download-agent-http-msg-handler.h"
23 #include "download-agent-debug.h"
24 #include "download-agent-encoding.h"
25
26 // '.' and ';' are request from Vodafone
27 #define IS_TERMINATING_CHAR(c)                  (((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20))
28 #define IS_TERMINATING_CHAR_EX(c)               (((c) == '"') || ((c) == ';') || ((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20))
29 #define IS_URI_TERMINATING_CHAR(c)              (((c) == '\0') || ((c) == 0x0d) || ((c) == 0x0a) || ((c) == 0x20))
30
31 enum parsing_type {
32         WITH_PARSING_OPTION,
33         WITHOUT_PARSING_OPTION
34 };
35
36 static da_ret_t __http_header_add_field(http_header_t **head,
37                 const char *field, const char *value, enum parsing_type type);
38 static void __http_header_destroy_all_field(http_header_t **head);
39 static da_bool_t __get_http_header_for_field(
40                 http_msg_response_t *http_msg_response, const char *in_field,
41                 http_header_t **out_header);
42 static void __exchange_header_value(http_header_t *header,
43                 const char *in_raw_value);
44 static http_header_options_t *__create_http_header_option(const char *field,
45                 const char *value);
46 static void __http_header_destroy_all_option(http_header_options_t **head);
47 static da_bool_t __get_http_header_option_for_field(
48                 http_header_options_t *header_option, const char *in_field,
49                 char **out_value);
50 static http_header_options_t *__parsing_N_create_option_str(char *org_str);
51 static http_header_options_t *__parsing_options(char *org_str);
52 static void __parsing_raw_value(http_header_t *http_header);
53
54 da_ret_t http_msg_request_create(http_msg_request_t **http_msg_request)
55 {
56         http_msg_request_t *temp_http_msg_request = NULL;
57
58         //      DA_LOGV("");
59
60         temp_http_msg_request = (http_msg_request_t *)calloc(1,
61                         sizeof(http_msg_request_t));
62         if (!temp_http_msg_request) {
63                 *http_msg_request = NULL;
64                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
65                 return DA_ERR_FAIL_TO_MEMALLOC;
66         }
67
68         temp_http_msg_request->http_method = NULL;
69         temp_http_msg_request->url = NULL;
70         temp_http_msg_request->head = NULL;
71         temp_http_msg_request->http_body = NULL;
72
73         *http_msg_request = temp_http_msg_request;
74         DA_LOGV("http_msg_request: %x", (unsigned int)(*http_msg_request));
75
76         return DA_RESULT_OK;
77 }
78
79 void http_msg_request_destroy(http_msg_request_t **http_msg_request)
80 {
81         http_msg_request_t *temp_http_msg_request = *http_msg_request;
82
83         DA_LOGV("");
84
85         if (temp_http_msg_request) {
86                 if (temp_http_msg_request->http_method) {
87                         free(temp_http_msg_request->http_method);
88                         temp_http_msg_request->http_method = NULL;
89                 }
90                 if (temp_http_msg_request->url) {
91                         free(temp_http_msg_request->url);
92                         temp_http_msg_request->url = NULL;
93                 }
94                 if (temp_http_msg_request->http_body) {
95                         free(temp_http_msg_request->http_body);
96                         temp_http_msg_request->http_body = NULL;
97                 }
98                 __http_header_destroy_all_field(&(temp_http_msg_request->head));
99                 free(*http_msg_request);
100                 *http_msg_request = NULL;
101         }
102 }
103
104 da_ret_t http_msg_request_set_url(http_msg_request_t *http_msg_request,
105                 const char *url)
106 {
107         DA_LOGV("");
108
109         if (!http_msg_request) {
110                 DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
111                 return DA_ERR_INVALID_ARGUMENT;
112         }
113
114         if (!url) {
115                 DA_LOGE("url is NULL; DA_ERR_INVALID_ARGUMENT");
116                 return DA_ERR_INVALID_URL;
117         }
118
119         http_msg_request->url = strdup(url);
120         DA_SECURE_LOGI("http url[%s]", http_msg_request->url);
121         return DA_RESULT_OK;
122 }
123
124 da_ret_t http_msg_request_get_url(http_msg_request_t *http_msg_request,
125                 const char **url)
126 {
127         DA_LOGV("");
128
129         if (!http_msg_request) {
130                 DA_LOGE("http_msg_request is NULL; DA_ERR_INVALID_ARGUMENT");
131                 return DA_ERR_INVALID_ARGUMENT;
132         }
133
134         if (http_msg_request->url) {
135                 *url = http_msg_request->url;
136                 return DA_RESULT_OK;
137         } else {
138                 *url = DA_NULL;
139                 return DA_ERR_INVALID_ARGUMENT;
140         }
141 }
142
143 da_ret_t http_msg_request_add_field(http_msg_request_t *http_msg_request,
144                 const char *field, const char *value)
145 {
146         //      DA_LOGV("");
147
148         if (!http_msg_request) {
149                 DA_LOGE("Check NULL! : http_msg_request");
150                 return DA_ERR_INVALID_ARGUMENT;
151         }
152
153         return __http_header_add_field(&(http_msg_request->head), field, value, WITHOUT_PARSING_OPTION);
154 }
155
156 da_ret_t http_msg_response_create(http_msg_response_t **http_msg_response)
157 {
158         http_msg_response_t *temp_http_msg_response = NULL;
159
160         DA_LOGV("");
161
162         temp_http_msg_response = (http_msg_response_t *)calloc(1,
163                         sizeof(http_msg_response_t));
164         if (!temp_http_msg_response) {
165                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
166                 return DA_ERR_FAIL_TO_MEMALLOC;
167         } else {
168                 temp_http_msg_response->status_code = 0;
169                 temp_http_msg_response->head = NULL;
170                 *http_msg_response = temp_http_msg_response;
171                 return DA_RESULT_OK;
172         }
173 }
174
175 void http_msg_response_destroy(http_msg_response_t **http_msg_response)
176 {
177         http_msg_response_t *temp_http_msg_response = *http_msg_response;
178
179         DA_LOGV("");
180         if (temp_http_msg_response) {
181                 __http_header_destroy_all_field(&(temp_http_msg_response->head));
182                 free(*http_msg_response);
183                 *http_msg_response = DA_NULL;
184         }
185 }
186
187 da_ret_t http_msg_response_add_field(http_msg_response_t *http_msg_response,
188                 const char *field, const char *value)
189 {
190         DA_LOGV("");
191
192         if (!http_msg_response) {
193                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
194                 return DA_ERR_INVALID_ARGUMENT;
195         }
196         return __http_header_add_field(&(http_msg_response->head), field, value, WITH_PARSING_OPTION);
197 }
198
199 da_ret_t __http_header_add_field(http_header_t **head,
200                 const char *field, const char *value, enum parsing_type type)
201 {
202         http_header_t *pre = NULL;
203         http_header_t *cur = NULL;
204
205         //DA_SECURE_LOGD("[%s][%s]", field, value);
206
207         pre = cur = *head;
208         while (cur) {
209                 pre = cur;
210                 /* Replace default value with user wanted value
211                  * Remove the value which is stored before and add a new value.
212                  */
213                 if (cur->field && cur->raw_value &&
214                                 strncasecmp(cur->field, field, strlen(field)) == 0) {
215                         DA_SECURE_LOGD("Remove value for replacement [%s][%s]", cur->field, cur->raw_value);
216                         if (cur->field) {
217                                 free(cur->field);
218                                 cur->field = NULL;
219                         }
220                         if (cur->raw_value) {
221                                 free(cur->raw_value);
222                                 cur->raw_value = NULL;
223                         }
224                 }
225                 cur = cur->next;
226         }
227
228         cur = (http_header_t *)calloc(1, sizeof(http_header_t));
229         if (cur) {
230                 cur->field = strdup(field);
231                 cur->raw_value = strdup(value);
232                 cur->options = NULL;
233                 cur->next = NULL;
234
235                 if (type == WITHOUT_PARSING_OPTION) {
236                         cur->value = strdup(value);
237                         cur->options = NULL;
238                 } else {
239                         __parsing_raw_value(cur);
240                 }
241
242                 if (pre)
243                         pre->next = cur;
244                 else
245                         *head = cur;
246         } else {
247                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
248                 return DA_ERR_FAIL_TO_MEMALLOC;
249         }
250
251         return DA_RESULT_OK;
252 }
253
254 void __http_header_destroy_all_field(http_header_t **head)
255 {
256         http_header_t *pre = NULL;
257         http_header_t *cur = NULL;
258
259         cur = *head;
260
261         while (cur) {
262                 if (cur->field) {
263                         free(cur->field);
264                         cur->field = DA_NULL;
265                 }
266                 if (cur->value) {
267                         free(cur->value);
268                         cur->value = DA_NULL;
269                 }
270                 if (cur->raw_value) {
271                         free(cur->raw_value);
272                         cur->raw_value = DA_NULL;
273                 }
274                 __http_header_destroy_all_option(&(cur->options));
275                 free(cur->options);
276                 cur->options = DA_NULL;
277                 pre = cur;
278                 cur = cur->next;
279                 free(pre);
280         }
281         *head = DA_NULL;
282 }
283
284 http_header_options_t *__create_http_header_option(const char *field,
285                 const char *value)
286 {
287         http_header_options_t *option = NULL;
288
289         option = (http_header_options_t *)calloc(1,
290                         sizeof(http_header_options_t));
291         if (option) {
292                 if (field)
293                         option->field = strdup(field);
294                 if (value)
295                         option->value = strdup(value);
296                 option->next = NULL;
297         }
298         return option;
299 }
300
301 void __http_header_destroy_all_option(http_header_options_t **head)
302 {
303         http_header_options_t *pre = NULL;
304         http_header_options_t *cur = NULL;
305
306         //      DA_LOGV("");
307
308         cur = *head;
309
310         while (cur) {
311                 if (cur->field) {
312                         DA_SECURE_LOGD("field= %s", cur->field);
313                         free(cur->field);
314                         cur->field = DA_NULL;
315                 }
316                 if (cur->value) {
317                         free(cur->value);
318                         cur->value = DA_NULL;
319                 }
320                 pre = cur;
321                 cur = cur->next;
322                 free(pre);
323         }
324         *head = DA_NULL;
325 }
326
327 da_ret_t http_msg_request_get_iter(http_msg_request_t *http_msg_request,
328                 http_msg_iter_t *http_msg_iter)
329 {
330         DA_LOGV("");
331
332         if (!http_msg_request) {
333                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
334                 return DA_ERR_INVALID_ARGUMENT;
335         }
336
337         *http_msg_iter = http_msg_request->head;
338
339         return DA_RESULT_OK;
340 }
341
342 da_ret_t http_msg_response_get_iter(http_msg_response_t *http_msg_response,
343                 http_msg_iter_t *http_msg_iter)
344 {
345         if (!http_msg_response) {
346                 DA_LOGE("DA_ERR_INVALID_ARGUMENT");
347                 return DA_ERR_INVALID_ARGUMENT;
348         }
349
350         *http_msg_iter = http_msg_response->head;
351         return DA_RESULT_OK;
352 }
353
354 da_bool_t http_msg_get_field_with_iter(http_msg_iter_t *http_msg_iter,
355                 char **out_field, char **out_value)
356 {
357         http_header_t *cur = *http_msg_iter;
358
359         if (cur) {
360                 *out_field = cur->field;
361                 *out_value = cur->value;
362                 *http_msg_iter = cur->next;
363                 return DA_TRUE;
364         } else {
365                 return DA_FALSE;
366         }
367 }
368
369 da_bool_t http_msg_get_header_with_iter(http_msg_iter_t *http_msg_iter,
370                 char **out_field, http_header_t **out_header)
371 {
372         http_header_t *cur = *http_msg_iter;
373
374         if (cur) {
375                 *out_field = cur->field;
376                 *out_header = cur;
377                 *http_msg_iter = cur->next;
378                 return DA_TRUE;
379         } else {
380                 return DA_FALSE;
381         }
382 }
383
384 http_header_options_t *__parsing_N_create_option_str(char *org_str)
385 {
386         char *option_field = NULL;
387         char *option_value = NULL;
388         int option_field_len = 0;
389         int option_value_len = 0;
390         char *org_pos = NULL;
391         int org_str_len = 0;
392         char *working_str = NULL;
393         char *working_pos = NULL;
394         char *working_pos_field_start = NULL;
395         char *working_pos_value_start = NULL;
396         da_bool_t is_inside_quotation = DA_FALSE;
397         da_bool_t is_working_for_field = DA_TRUE;
398         int i = 0;
399         http_header_options_t *option = NULL;
400
401         //      DA_LOGV("");
402
403         if (!org_str)
404                 return NULL;
405
406         org_str_len = strlen(org_str);
407         if (org_str_len <= 0)
408                 return NULL;
409
410         working_str = (char *)calloc(1, org_str_len + 1);
411         if (!working_str)
412                 return NULL;
413
414         org_pos = org_str;
415         working_pos_field_start = working_pos = working_str;
416
417         for (i = 0; i < org_str_len; i++) {
418                 if (*org_pos == '"')
419                         is_inside_quotation = !is_inside_quotation;
420                 if (is_inside_quotation) {
421                         // Leave anything including blank if it is inside of double quotation mark.
422                         *working_pos = *org_pos;
423                         is_working_for_field ? option_field_len++
424                                 : option_value_len++;
425                         working_pos++;
426                         org_pos++;
427                 } else {
428                         if (*org_pos == ' ') {
429                                 org_pos++;
430                         } else if (*org_pos == '=') {
431                                 if (is_working_for_field) {
432                                         is_working_for_field = DA_FALSE;
433                                         working_pos_value_start = working_pos;
434                                 }
435                                 org_pos++;
436                         } else {
437                                 *working_pos = *org_pos;
438                                 is_working_for_field ? option_field_len++
439                                         : option_value_len++;
440                                 working_pos++;
441                                 org_pos++;
442                         }
443                 }
444         }
445
446         if (option_field_len > 0 && working_pos_field_start) {
447                 option_field = (char *)calloc(1, option_field_len + 1);
448                 if (option_field)
449                         strncpy(option_field, working_pos_field_start,
450                                         option_field_len);
451         }
452         if (option_value_len > 0 && working_pos_value_start) {
453                 option_value = (char *)calloc(1, option_value_len + 1);
454                 if (option_value)
455                         strncpy(option_value, working_pos_value_start,
456                                         option_value_len);
457         }
458         if (working_str) {
459                 free(working_str);
460                 working_pos = working_str = NULL;
461         }
462
463         DA_SECURE_LOGD("option_field = [%s], option_value = [%s]",
464                         option_field ? option_field : "",
465                         option_value ? option_value : "");
466
467         if (option_field || option_value) {
468                 option = __create_http_header_option(
469                                 option_field, option_value);
470                 if (option_field) {
471                         free(option_field);
472                         option_field = NULL;
473                 }
474                 if (option_value) {
475                         free(option_value);
476                         option_value = NULL;
477                 }
478         }
479         return option;
480 }
481
482 http_header_options_t *__parsing_options(char *org_str)
483 {
484         da_ret_t ret = DA_RESULT_OK;
485         http_header_options_t *head = NULL;
486         http_header_options_t *pre = NULL;
487         http_header_options_t *cur = NULL;
488
489         int wanted_str_len = 0;
490         char *wanted_str = NULL;
491         char *wanted_str_start = NULL;
492         char *wanted_str_end = NULL;
493         char *cur_pos = NULL;
494
495         DA_LOGV("");
496
497         if (!org_str)
498                 return NULL;
499
500         /* Do Not use strtok(). It's not thread safe. */
501         //      DA_SECURE_LOGD("org_str = %s", org_str);
502
503         cur_pos = org_str;
504
505         while (cur_pos) {
506                 wanted_str_start = cur_pos;
507                 wanted_str_end = strchr(cur_pos, ';');
508                 if (wanted_str_end) {
509                         cur_pos = wanted_str_end + 1;
510                 } else {
511                         wanted_str_end = org_str + strlen(org_str);
512                         cur_pos = NULL;
513                 }
514                 wanted_str_len = wanted_str_end - wanted_str_start;
515                 wanted_str = (char *)calloc(1, wanted_str_len + 1);
516                 if (!wanted_str) {
517                         DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
518                         ret = DA_ERR_FAIL_TO_MEMALLOC;
519                         goto ERR;
520                 }
521                 strncpy(wanted_str, wanted_str_start, wanted_str_len);
522
523                 //              DA_SECURE_LOGD("wanted_str = [%s]", wanted_str);
524                 cur = __parsing_N_create_option_str(wanted_str);
525                 if (pre) {
526                         pre->next = cur;
527                         pre = cur;
528                 } else {
529                         head = pre = cur;
530                 }
531
532                 free(wanted_str);
533                 wanted_str = NULL;
534         }
535
536 ERR:
537         if (ret != DA_RESULT_OK)
538                 __http_header_destroy_all_option(&head);
539         return head;
540 }
541
542 void __parsing_raw_value(http_header_t *http_header_field)
543 {
544         char *raw_value = NULL;
545         char *option_str_start = NULL;
546         char *trimed_value = NULL;
547         int trimed_value_len = 0;
548         char *trimed_value_start = NULL;
549         char *trimed_value_end = NULL;
550
551         raw_value = http_header_field->raw_value;
552         //      DA_SECURE_LOGD("raw_value = [%s]", raw_value);
553
554         if (!raw_value)
555                 return;
556
557         trimed_value_start = raw_value;
558         trimed_value_end = strchr(raw_value, ';');
559         if (!trimed_value_end) {
560                 // No options
561                 http_header_field->value = strdup(raw_value);
562                 http_header_field->options = NULL;
563
564                 return;
565         }
566
567         // for trimed value
568         trimed_value_len = trimed_value_end - trimed_value_start;
569         trimed_value = (char *)calloc(1, trimed_value_len + 1);
570         if (!trimed_value) {
571                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
572                 return;
573         }
574         strncpy(trimed_value, trimed_value_start, trimed_value_len);
575         http_header_field->value = trimed_value;
576
577         // for option parsing
578         option_str_start = trimed_value_end + 1;
579         http_header_field->options = __parsing_options(option_str_start);
580
581         /////////////// show
582         http_header_options_t *cur = NULL;
583         cur = http_header_field->options;
584         while (cur) {
585                 //              DA_SECURE_LOGD("field = [%s], value = [%s]", cur->field, cur->value);
586                 cur = cur->next;
587         }
588 }
589
590 da_bool_t __get_http_header_option_for_field(
591                 http_header_options_t *header_option, const char *in_field,
592                 char **out_value)
593 {
594         http_header_options_t *cur = NULL;
595
596         //      DA_LOGV("");
597
598         if (!header_option) {
599                 DA_LOGE("input header_option is NULL.");
600                 return DA_FALSE;
601         }
602
603         cur = header_option;
604         while (cur) {
605                 if (cur->field) {
606                         if (!strncasecmp(cur->field, in_field, strlen(cur->field)) &&
607                                         cur->value) {
608                                 DA_SECURE_LOGD("[%s][%s]", cur->field, cur->value);
609                                 *out_value = cur->value;
610                                 return DA_TRUE;
611                         }
612
613                 }
614                 cur = cur->next;
615         }
616         return DA_FALSE;
617 }
618
619 da_bool_t __get_http_header_for_field(http_msg_response_t *http_msg_response,
620                 const char *in_field, http_header_t **out_header)
621 {
622         http_msg_iter_t http_msg_iter = DA_NULL;
623         http_header_t *header = NULL;
624         char *field = NULL;
625
626         //DA_LOGV("");
627
628         http_msg_response_get_iter(http_msg_response, &http_msg_iter);
629         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
630                 if (field && header && !strncasecmp(field, in_field, strlen(field))) {
631                         //DA_SECURE_LOGD("[%s][%s]", field, header->value);
632                         *out_header = header;
633                         return DA_TRUE;
634                 }
635         }
636
637         return DA_FALSE;
638 }
639
640 da_bool_t __get_http_req_header_for_field(http_msg_request_t *http_msg_request,
641                 const char *in_field, http_header_t **out_header)
642 {
643         http_msg_iter_t http_msg_iter = DA_NULL;
644         http_header_t *header = NULL;
645         char *field = NULL;
646
647         //DA_LOGV("");
648
649         http_msg_request_get_iter(http_msg_request, &http_msg_iter);
650         while (http_msg_get_header_with_iter(&http_msg_iter, &field, &header)) {
651                 if (field && header && !strncasecmp(field, in_field, strlen(field))) {
652                         //DA_SECURE_LOGD("[%s][%s]", field, header->value);
653                         *out_header = header;
654                         return DA_TRUE;
655                 }
656         }
657
658         return DA_FALSE;
659 }
660
661 void __exchange_header_value(http_header_t *header, const char *in_raw_value)
662 {
663         DA_LOGV("");
664
665         if (!header || !in_raw_value)
666                 return;
667
668         __http_header_destroy_all_option(&(header->options));
669
670         if (header->value) {
671                 free(header->value);
672                 header->value = DA_NULL;
673         }
674         if (header->raw_value)
675                 free(header->raw_value);
676         header->raw_value = strdup(in_raw_value);
677
678         __parsing_raw_value(header);
679 }
680
681 da_bool_t http_msg_response_get_content_type(
682                 http_msg_response_t *http_msg_response, char **out_type)
683 {
684         da_bool_t b_ret = DA_FALSE;
685         http_header_t *header = NULL;
686
687         DA_LOGV("");
688
689         b_ret = __get_http_header_for_field(http_msg_response,
690                         HTTP_FIELD_CONTENT_TYPE, &header);
691         if (!b_ret) {
692                 DA_LOGV("no Content-Type");
693                 return DA_FALSE;
694         }
695         if (out_type)
696                 *out_type = strdup(header->value);
697
698         return DA_TRUE;
699 }
700
701 void http_msg_response_set_content_type(http_msg_response_t *http_msg_response,
702                 const char *in_type)
703 {
704         da_bool_t b_ret = DA_FALSE;
705         http_header_t *header = NULL;
706
707         DA_LOGV("");
708
709         if (!http_msg_response || !in_type)
710                 return;
711
712         b_ret = __get_http_header_for_field(http_msg_response,
713                         HTTP_FIELD_CONTENT_TYPE, &header);
714         if (b_ret) {
715                 if (header->raw_value && !strcmp(header->raw_value, in_type))
716                         return;
717
718                 DA_SECURE_LOGD("exchange Content-Type to [%s] from [%s]", in_type, header->value);
719                 __exchange_header_value(header, in_type);
720         } else {
721                 __http_header_add_field(&(http_msg_response->head),
722                                 HTTP_FIELD_CONTENT_TYPE, in_type, WITH_PARSING_OPTION);
723         }
724 }
725
726 da_bool_t http_msg_response_get_content_length(
727                 http_msg_response_t *http_msg_response, da_size_t *out_length)
728 {
729         da_bool_t b_ret = DA_FALSE;
730         http_header_t *header = NULL;
731
732         DA_LOGV("");
733
734         b_ret = __get_http_header_for_field(http_msg_response,
735                         HTTP_FIELD_CONTENT_LENGTH, &header);
736         if (!b_ret) {
737                 DA_LOGV("no Content-Length");
738                 return DA_FALSE;
739         }
740
741         if (out_length)
742                 *out_length = atoll(header->value);
743
744         return DA_TRUE;
745 }
746
747 da_bool_t http_msg_response_get_content_disposition(
748                 http_msg_response_t *http_msg_response, http_msg_t *http_msg, char **out_disposition,
749                 char **out_file_name)
750 {
751         da_bool_t b_ret = DA_FALSE;
752         http_header_t *header = NULL;
753         char *file_name = NULL;
754         char *wanted_str = NULL;
755         char *wanted_str_start = NULL;
756         char *wanted_str_end = NULL;
757         char *decoded_str = NULL;
758         int wanted_str_len = 0;
759
760         DA_LOGV("");
761
762         b_ret = __get_http_header_for_field(http_msg_response,
763                         HTTP_FIELD_CONTENT_DISPOSITION, &header);
764         if (!b_ret) {
765                 DA_LOGV("no Content-Disposition");
766                 return DA_FALSE;
767         }
768         if (out_disposition)
769                 *out_disposition = strdup(header->value);
770         if (!out_file_name)
771                 return DA_FALSE;
772
773         b_ret = __get_http_header_option_for_field(header->options, "filename",
774                         &file_name);
775         if (!b_ret) {
776                 DA_LOGV("no option");
777                 return DA_FALSE;
778         }
779
780         // eliminate double quotation mark if it exists on derived value
781         wanted_str_start = strchr(file_name, '"');
782         if (!wanted_str_start) {
783                 *out_file_name = strdup(file_name);
784                 return DA_TRUE;
785         } else {
786                 //              DA_SECURE_LOGD("wanted_str_start = [%s]", wanted_str_start);
787                 wanted_str_start++;
788                 wanted_str_end = strchr(wanted_str_start, '"');
789                 if (wanted_str_end) {
790                         wanted_str_len = wanted_str_end - wanted_str_start;
791                         wanted_str = (char*)calloc(1, wanted_str_len + 1);
792                         if (!wanted_str) {
793                                 DA_LOGE("DA_ERR_FAIL_TO_MEMALLOC");
794                                 return DA_FALSE;
795                         }
796                         strncpy(wanted_str, wanted_str_start, wanted_str_len);
797
798                         b_ret = is_base64_encoded_word(wanted_str);
799                         if (b_ret) {
800                                 DA_LOGV("It's base64 encoded-word string");
801                                 if (DA_RESULT_OK == decode_base64_encoded_str(
802                                                         wanted_str, &decoded_str)) {
803                                         DA_SECURE_LOGD("base64 decoded str = [%s]", decoded_str);
804                                         free(wanted_str);
805                                         wanted_str = decoded_str;
806                                         decoded_str = NULL;
807                                 } else {
808                                         DA_LOGV("Fail to base64 decode. Just use un-decoded string.");
809                                 }
810                         } else {
811                                 DA_LOGV("It's NOT base64 encoded-word string");
812                         }
813
814                         if (http_msg->curl) {
815                                 decoded_str = curl_easy_unescape(http_msg->curl, wanted_str, wanted_str_len, NULL);
816                         } else{
817                                 CURL* handle = curl_easy_init();
818                                 decoded_str = curl_easy_unescape(handle, wanted_str, wanted_str_len, NULL);
819                                 curl_easy_cleanup(handle);
820                         }
821
822                         /* If it is url encoded string */
823                         if (decoded_str) {
824                                 char* file_name;
825                                 DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str);
826                                 file_name = strdup(decoded_str);
827                                 NULL_CHECK_AND_FREE(wanted_str);
828                                 curl_free(decoded_str);
829                                 decoded_str = NULL;
830
831                                 *out_file_name = file_name;
832                                 return DA_TRUE;
833                         } else{
834                                 DA_LOGE("Fail to url decode.");
835                                 NULL_CHECK_AND_FREE(wanted_str);
836                                 *out_file_name = NULL;
837                                 return DA_FALSE;
838                         }
839                 } else {
840                         DA_LOGE("Not matched \" !");
841                         return DA_FALSE;
842                 }
843         }
844 }
845
846 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
847                 char **out_value)
848 {
849         da_bool_t b_ret = DA_FALSE;
850         http_header_t *header = NULL;
851
852         DA_LOGV("");
853
854         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG,
855                         &header);
856         if (!b_ret) {
857                 DA_LOGV("no ETag");
858                 return DA_FALSE;
859         }
860         if (out_value)
861                 *out_value = strdup(header->value);
862
863         return DA_TRUE;
864 }
865
866 #ifdef _RAF_SUPPORT
867 da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response,
868                 char **out_value)
869 {
870         da_bool_t b_ret = DA_FALSE;
871         http_header_t *header = NULL;
872
873         DA_LOGV("");
874
875         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE,
876                         &header);
877         if (!b_ret) {
878                 DA_LOGV("no RAF mode");
879                 return DA_FALSE;
880         }
881         if (out_value)
882                 *out_value = strdup(header->value);
883
884         return DA_TRUE;
885 }
886 #endif
887
888 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
889                 char **out_value)
890 {
891         da_bool_t b_ret = DA_FALSE;
892         http_header_t *header = NULL;
893
894         DA_LOGV("");
895
896         b_ret = __get_http_header_for_field(http_msg_response,
897                         HTTP_FIELD_DATA, &header);
898         if (!b_ret) {
899                 DA_LOGV("no Date");
900                 return DA_FALSE;
901         }
902         if (out_value)
903                 *out_value = strdup(header->value);
904
905         return DA_TRUE;
906 }
907
908 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
909                 char **out_value)
910 {
911         da_bool_t b_ret = DA_FALSE;
912         http_header_t *header = NULL;
913
914         DA_LOGV("");
915
916         b_ret = __get_http_header_for_field(http_msg_response,
917                         HTTP_FIELD_LOCATION, &header);
918         if (!b_ret) {
919                 DA_LOGV("no Location");
920                 return DA_FALSE;
921         }
922         if (out_value)
923                 *out_value = strdup(header->value);
924
925         return DA_TRUE;
926 }
927
928 da_bool_t http_msg_response_get_transfer_encoding(http_msg_response_t *http_msg_response,
929                 char **out_value)
930 {
931         da_bool_t b_ret = DA_FALSE;
932         http_header_t *header = NULL;
933
934         DA_LOGV("");
935
936         b_ret = __get_http_header_for_field(http_msg_response,
937                         HTTP_FIELD_TRANSFER_ENCODING, &header);
938         if (!b_ret) {
939                 DA_LOGE("no Transfer-Encoding");
940                 return DA_FALSE;
941         }
942         if (out_value)
943                 *out_value = strdup(header->value);
944
945         return DA_TRUE;
946 }
947
948 char *__stristr(const char *long_str, const char *find_str)
949 {
950         int i = 0;
951         int length_long = 0;
952         int length_find = 0;
953         char *ret_ptr = NULL;
954         char *org_ptr = NULL;
955         char *look_ptr = NULL;
956
957         if (long_str == NULL || find_str == NULL) {
958                 DA_LOGE("INVALID ARGUMENT");
959                 return NULL;
960         }
961
962         length_long = strlen(long_str);
963         length_find = strlen(find_str);
964
965         org_ptr = (char*)calloc(1, length_long + 1);
966
967         if (org_ptr == NULL) {
968                 DA_LOGE("INVALID ARGUMENT");
969                 return NULL;
970         }
971
972         look_ptr = (char*)calloc(1, length_find + 1);
973
974         if (look_ptr == NULL) {
975                 DA_LOGE("INVALID ARGUMENT");
976                 free(org_ptr);
977                 return NULL;
978         }
979
980         while (i < length_long) {
981                 if (isalpha(long_str[i]) != 0) {
982                         if (isupper(long_str[i]) != 0)
983                                 org_ptr[i] = long_str[i];
984                         else
985                                 org_ptr[i] = toupper(long_str[i]);
986                 } else {
987                         org_ptr[i] = long_str[i];
988                 }
989                 i++;
990         }
991
992         i = 0;
993
994         while (i < length_find) {
995                 if (isalpha(find_str[i]) != 0) {
996                         if (isupper(find_str[i]) != 0)
997                                 look_ptr[i] = find_str[i];
998                         else
999                                 look_ptr[i] = toupper(find_str[i]);
1000                 } else {
1001                         look_ptr[i] = find_str[i];
1002                 }
1003                 i++;
1004         }
1005
1006         ret_ptr = strstr(org_ptr, look_ptr);
1007
1008         if (ret_ptr == 0) {
1009                 free(org_ptr);
1010                 free(look_ptr);
1011                 return NULL;
1012         } else {
1013                 i = ret_ptr - org_ptr;
1014         }
1015
1016         free(org_ptr);
1017         free(look_ptr);
1018
1019         return (char*)(long_str + i);
1020 }
1021
1022 /* This is not used. But it can be needed if there is no http header parser at http library.*/
1023 da_bool_t extract_attribute_from_header(
1024                 char *szHeadStr,
1025                 const char *szFindStr,
1026                 char **ppRtnValue)
1027 {
1028         char *pValuePos = NULL;
1029         int index = 0;
1030         int startPos = 0;
1031         int strLen = 0;
1032         int need_to_end_quataion_mark = 0;
1033
1034         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1035                 DA_LOGE("INVALID ARGUMENT");
1036                 return DA_FALSE;
1037         }
1038         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1039                 DA_LOGE("INVALID ARGUMENT");;
1040
1041                 return DA_FALSE;
1042         }
1043         if (ppRtnValue == NULL)
1044                 return DA_FALSE;
1045
1046         pValuePos = __stristr(szHeadStr, (char*)szFindStr);
1047         if (pValuePos == NULL) {
1048                 *ppRtnValue = NULL;
1049                 goto ERR;
1050         }
1051
1052         index = strlen(szFindStr);
1053
1054         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1055                 index++;
1056
1057                 if (pValuePos[index] == '\0')
1058                         return DA_FALSE;
1059         }
1060
1061         index++;
1062
1063         /* jump space */
1064         while (pValuePos[index] == ' ')
1065                 index++;
1066
1067         /* jump quatation mark */
1068         while (pValuePos[index] == '"') {
1069                 need_to_end_quataion_mark = 1;
1070                 index++;
1071         }
1072
1073         startPos = index;
1074
1075         /* Find the end of data.
1076          * terminate character list does not contain ';' in case of URI
1077          */
1078         if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION, strlen(HTTP_FIELD_LOCATION))) {
1079                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index]))
1080                         index++;
1081         } else if (need_to_end_quataion_mark) {
1082                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index]))
1083                         index++;
1084         } else {
1085                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index]))
1086                         index++;
1087         }
1088
1089         strLen = index - startPos;
1090
1091         if (strLen < 1) {
1092                 DA_LOGE(" strLen is < 1");
1093                 goto ERR;
1094         }
1095
1096         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1097
1098         if (*ppRtnValue == NULL) {
1099                 DA_LOGE(" *ppRtnValue is NULL");
1100                 goto ERR;
1101         }
1102
1103         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1104         *(*ppRtnValue + strLen) = '\0';
1105
1106         return DA_TRUE;
1107 ERR:
1108         if (*ppRtnValue) {
1109                 free(*ppRtnValue);
1110                 *ppRtnValue = NULL;
1111         }
1112         return DA_FALSE;
1113 }
1114
1115 da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request,
1116                 char **out_value)
1117 {
1118         da_bool_t b_ret = DA_FALSE;
1119         http_header_t *header = NULL;
1120
1121         DA_LOGV("");
1122
1123         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE,
1124                         &header);
1125         if (!b_ret) {
1126                 DA_LOGV("no If Range");
1127                 return DA_FALSE;
1128         }
1129         if (out_value)
1130                 *out_value = strdup(header->value);
1131
1132         return DA_TRUE;
1133 }
1134
1135 da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request,
1136                 char **out_value)
1137 {
1138         da_bool_t b_ret = DA_FALSE;
1139         http_header_t *header = NULL;
1140
1141         DA_LOGV("");
1142
1143         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE,
1144                         &header);
1145         if (!b_ret) {
1146                 DA_LOGV("no Range");
1147                 return DA_FALSE;
1148         }
1149         if (out_value)
1150                 *out_value = strdup(header->value);
1151
1152         return DA_TRUE;
1153 }