Sync with tizen_2.4, latest
[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, 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                         decode_url_encoded_str(wanted_str, &decoded_str);
813                         /* If it is url encoded string */
814                         if (decoded_str) {
815                                 DA_SECURE_LOGD("Url decoded str = [%s]", decoded_str);
816                                 free(wanted_str);
817                                 wanted_str = decoded_str;
818                                 decoded_str = NULL;
819                         }
820                         *out_file_name = wanted_str;
821                         DA_SECURE_LOGI("out_file_name = [%s]", *out_file_name);
822                         return DA_TRUE;
823                 } else {
824                         DA_LOGE("Not matched \" !");
825                         return DA_FALSE;
826                 }
827         }
828 }
829
830 da_bool_t http_msg_response_get_ETag(http_msg_response_t *http_msg_response,
831         char **out_value)
832 {
833         da_bool_t b_ret = DA_FALSE;
834         http_header_t *header = NULL;
835
836         DA_LOGV("");
837
838         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_ETAG,
839                         &header);
840         if (!b_ret) {
841                 DA_LOGV( "no ETag");
842                 return DA_FALSE;
843         }
844         if (out_value)
845                 *out_value = strdup(header->value);
846
847         return DA_TRUE;
848 }
849
850 #ifdef _RAF_SUPPORT
851 da_bool_t http_msg_response_get_RAF_mode(http_msg_response_t *http_msg_response,
852         char **out_value)
853 {
854         da_bool_t b_ret = DA_FALSE;
855         http_header_t *header = NULL;
856
857         DA_LOGV("");
858
859         b_ret = __get_http_header_for_field(http_msg_response, HTTP_FIELD_RAF_MODE,
860                         &header);
861         if (!b_ret) {
862                 DA_LOGV( "no RAF mode");
863                 return DA_FALSE;
864         }
865         if (out_value)
866                 *out_value = strdup(header->value);
867
868         return DA_TRUE;
869 }
870 #endif
871
872 da_bool_t http_msg_response_get_date(http_msg_response_t *http_msg_response,
873         char **out_value)
874 {
875         da_bool_t b_ret = DA_FALSE;
876         http_header_t *header = NULL;
877
878         DA_LOGV("");
879
880         b_ret = __get_http_header_for_field(http_msg_response,
881                         HTTP_FIELD_DATA, &header);
882         if (!b_ret) {
883                 DA_LOGV( "no Date");
884                 return DA_FALSE;
885         }
886         if (out_value)
887                 *out_value = strdup(header->value);
888
889         return DA_TRUE;
890 }
891
892 da_bool_t http_msg_response_get_location(http_msg_response_t *http_msg_response,
893         char **out_value)
894 {
895         da_bool_t b_ret = DA_FALSE;
896         http_header_t *header = NULL;
897
898         DA_LOGV("");
899
900         b_ret = __get_http_header_for_field(http_msg_response,
901                         HTTP_FIELD_LOCATION, &header);
902         if (!b_ret) {
903                 DA_LOGV( "no Location");
904                 return DA_FALSE;
905         }
906         if (out_value)
907                 *out_value = strdup(header->value);
908
909         return DA_TRUE;
910 }
911
912 char *__stristr(const char *long_str, const char *find_str)
913 {
914         int i = 0;
915         int length_long = 0;
916         int length_find = 0;
917         char *ret_ptr = NULL;
918         char *org_ptr = NULL;
919         char *look_ptr = NULL;
920
921         if (long_str == NULL || find_str == NULL) {
922                 DA_LOGE("INVALID ARGUMENT");
923                 return NULL;
924         }
925
926         length_long = strlen(long_str);
927         length_find = strlen(find_str);
928
929         org_ptr = (char*)calloc(1, length_long + 1);
930
931         if (org_ptr == NULL) {
932                 DA_LOGE("INVALID ARGUMENT");
933                 return NULL;
934         }
935
936         look_ptr = (char*)calloc(1, length_find + 1);
937
938         if (look_ptr == NULL) {
939                 DA_LOGE("INVALID ARGUMENT");
940                 free(org_ptr);
941                 return NULL;
942         }
943
944         while (i < length_long) {
945                 if (isalpha(long_str[i]) != 0) {
946                         if (isupper(long_str[i]) != 0) {
947                                 org_ptr[i] = long_str[i];
948                         } else {
949                                 org_ptr[i] = toupper(long_str[i]);
950                         }
951                 } else {
952                         org_ptr[i] = long_str[i];
953                 }
954                 i++;
955         }
956
957         i = 0;
958
959         while (i < length_find) {
960                 if (isalpha(find_str[i]) != 0) {
961                         if (isupper(find_str[i]) != 0) {
962                                 look_ptr[i] = find_str[i];
963                         } else {
964                                 look_ptr[i] = toupper(find_str[i]);
965                         }
966                 } else {
967                         look_ptr[i] = find_str[i];
968                 }
969                 i++;
970         }
971
972         ret_ptr = strstr(org_ptr, look_ptr);
973
974         if (ret_ptr == 0) {
975                 free(org_ptr);
976                 free(look_ptr);
977                 return NULL;
978         } else {
979                 i = ret_ptr - org_ptr;
980         }
981
982         free(org_ptr);
983         free(look_ptr);
984
985         return (char*)(long_str + i);
986 }
987
988 /* This is not used. But it can be needed if there is no http header parser at http library.*/
989 da_bool_t extract_attribute_from_header(
990         char *szHeadStr,
991         const char *szFindStr,
992         char **ppRtnValue)
993 {
994         char *pValuePos = NULL;
995         int index = 0;
996         int startPos = 0;
997         int strLen = 0;
998         int need_to_end_quataion_mark = 0;
999
1000         if (szHeadStr == DA_NULL || szFindStr == DA_NULL) {
1001                 DA_LOGE("INVALID ARGUMENT");
1002                 return DA_FALSE;
1003         }
1004         if (strlen(szHeadStr) <= 0 || strlen(szFindStr) <= 0) {
1005                 DA_LOGE("INVALID ARGUMENT");;
1006
1007                 return DA_FALSE;
1008         }
1009         if (ppRtnValue == NULL) {
1010                 return DA_FALSE;
1011         }
1012
1013         pValuePos = __stristr(szHeadStr, (char*)szFindStr);
1014         if (pValuePos == NULL) {
1015                 *ppRtnValue = NULL;
1016                 goto ERR;
1017         }
1018
1019         index = strlen(szFindStr);
1020
1021         while (pValuePos[index] != ':' && pValuePos[index] != '=') {
1022                 index++;
1023
1024                 if (pValuePos[index] == '\0') {
1025                         return DA_FALSE;
1026                 }
1027         }
1028
1029         index++;
1030
1031         /* jump space */
1032         while (pValuePos[index] == ' ') {
1033                 index++;
1034         }
1035
1036         /* jump quatation mark */
1037         while (pValuePos[index] == '"') {
1038                 need_to_end_quataion_mark = 1;
1039                 index++;
1040         }
1041
1042         startPos = index;
1043
1044         /* Find the end of data. */
1045         if (0 == strncasecmp(szFindStr, HTTP_FIELD_LOCATION,
1046                         strlen(HTTP_FIELD_LOCATION)))//terminate character list does not contain ';' in case of URI
1047         {
1048                 while (DA_FALSE == IS_URI_TERMINATING_CHAR(pValuePos[index])) {
1049                         index++;
1050                 }
1051         } else if (need_to_end_quataion_mark) {
1052                 while (DA_FALSE == IS_TERMINATING_CHAR_EX(pValuePos[index])) {
1053                         index++;
1054                 }
1055         } else {
1056                 while (DA_FALSE == IS_TERMINATING_CHAR(pValuePos[index])) {
1057                         index++;
1058                 }
1059         }
1060
1061         strLen = index - startPos;
1062
1063         if (strLen < 1) {
1064                 DA_LOGE(" strLen is < 1");
1065                 goto ERR;
1066         }
1067
1068         *ppRtnValue = (char*)calloc(1, sizeof(char) * (strLen + 1));
1069
1070         if (*ppRtnValue == NULL) {
1071                 DA_LOGE(" *ppRtnValue is NULL");
1072                 goto ERR;
1073         }
1074
1075         strncpy(*ppRtnValue, pValuePos + startPos, strLen);
1076         *(*ppRtnValue + strLen) = '\0';
1077
1078         return DA_TRUE;
1079 ERR:
1080         if (*ppRtnValue) {
1081                 free(*ppRtnValue);
1082                 *ppRtnValue = NULL;
1083         }
1084         return DA_FALSE;
1085 }
1086
1087 da_bool_t http_msg_request_get_if_range(http_msg_request_t *http_msg_request,
1088         char **out_value)
1089 {
1090         da_bool_t b_ret = DA_FALSE;
1091         http_header_t *header = NULL;
1092
1093         DA_LOGV("");
1094
1095         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_IF_RANGE,
1096                         &header);
1097         if (!b_ret) {
1098                 DA_LOGV( "no If Range");
1099                 return DA_FALSE;
1100         }
1101         if (out_value)
1102                 *out_value = strdup(header->value);
1103
1104         return DA_TRUE;
1105 }
1106
1107 da_bool_t http_msg_request_get_range(http_msg_request_t *http_msg_request,
1108         char **out_value)
1109 {
1110         da_bool_t b_ret = DA_FALSE;
1111         http_header_t *header = NULL;
1112
1113         DA_LOGV("");
1114
1115         b_ret = __get_http_req_header_for_field(http_msg_request, HTTP_FIELD_RANGE,
1116                         &header);
1117         if (!b_ret) {
1118                 DA_LOGV( "no Range");
1119                 return DA_FALSE;
1120         }
1121         if (out_value)
1122                 *out_value = strdup(header->value);
1123
1124         return DA_TRUE;
1125 }