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