Changeset 3ce68b7 in mainline for uspace/lib/http/headers.c


Ignore:
Timestamp:
2013-09-26T09:01:36Z (12 years ago)
Author:
Martin Sucha <sucha14@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
b623b68
Parents:
c17469e
Message:

libhttp: receive headers correctly

File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/lib/http/headers.c

    rc17469e r3ce68b7  
    4040
    4141#include "http.h"
     42#include "http-ctype.h"
    4243
    4344#define HTTP_HEADER_LINE "%s: %s\r\n"
    44 
    45 static char *cut_str(const char *start, const char *end)
    46 {
    47         size_t size = end - start;
    48         return str_ndup(start, size);
    49 }
    5045
    5146void http_header_init(http_header_t *header)
     
    9893}
    9994
    100 int http_header_parse(const char *line, http_header_t *header)
    101 {
    102         const char *pos = line;
    103         while (*pos != 0 && *pos != ':') pos++;
    104         if (*pos != ':')
     95int http_header_receive_name(receive_buffer_t *rb, char **out_name)
     96{
     97        receive_buffer_mark_t name_start;
     98        receive_buffer_mark_t name_end;
     99       
     100        recv_mark(rb, &name_start);
     101        recv_mark(rb, &name_end);
     102       
     103        char c = 0;
     104        do {
     105                recv_mark_update(rb, &name_end);
     106               
     107                int rc = recv_char(rb, &c, true);
     108                if (rc != EOK) {
     109                        recv_unmark(rb, &name_start);
     110                        recv_unmark(rb, &name_end);
     111                        return rc;
     112                }
     113        } while (is_token(c));
     114       
     115        if (c != ':') {
     116                recv_unmark(rb, &name_start);
     117                recv_unmark(rb, &name_end);
    105118                return EINVAL;
    106        
    107         char *name = cut_str(line, pos);
    108         if (name == NULL)
    109                 return ENOMEM;
    110        
    111         pos++;
    112        
    113         while (*pos == ' ') pos++;
    114        
    115         char *value = str_dup(pos);
    116         if (value == NULL) {
     119        }
     120       
     121        char *name = NULL;
     122        int rc = recv_cut_str(rb, &name_start, &name_end, &name);
     123        recv_unmark(rb, &name_start);
     124        recv_unmark(rb, &name_end);
     125        if (rc != EOK)
     126                return rc;
     127       
     128        *out_name = name;
     129        return EOK;
     130}
     131
     132int http_header_receive_value(receive_buffer_t *rb, char **out_value)
     133{
     134        int rc = EOK;
     135        char c = 0;
     136       
     137        receive_buffer_mark_t value_start;
     138        recv_mark(rb, &value_start);
     139       
     140        /* Ignore any inline LWS */
     141        while (true) {
     142                recv_mark_update(rb, &value_start);
     143                rc = recv_char(rb, &c, false);
     144                if (rc != EOK)
     145                        goto error;
     146               
     147                if (c != ' ' && c != '\t')
     148                        break;
     149               
     150                rc = recv_char(rb, &c, true);
     151                if (rc != EOK)
     152                        goto error;
     153        }
     154       
     155        receive_buffer_mark_t value_end;
     156        recv_mark(rb, &value_end);
     157       
     158        while (true) {
     159                recv_mark_update(rb, &value_end);
     160               
     161                rc = recv_char(rb, &c, true);
     162                if (rc != EOK)
     163                        goto error_end;
     164               
     165                if (c != '\r' && c != '\n')
     166                        continue;
     167               
     168                rc = recv_discard(rb, (c == '\r' ? '\n' : '\r'));
     169                if (rc < 0)
     170                        goto error_end;
     171               
     172                rc = recv_char(rb, &c, false);
     173                if (rc != EOK)
     174                        goto error_end;
     175               
     176                if (c != ' ' && c != '\t')
     177                        break;
     178               
     179                /* Ignore the char */
     180                rc = recv_char(rb, &c, true);
     181                if (rc != EOK)
     182                        goto error_end;
     183        }
     184       
     185        char *value = NULL;
     186        rc = recv_cut_str(rb, &value_start, &value_end, &value);
     187        recv_unmark(rb, &value_start);
     188        recv_unmark(rb, &value_end);
     189        if (rc != EOK)
     190                return rc;
     191       
     192        *out_value = value;
     193        return EOK;
     194error_end:
     195        recv_unmark(rb, &value_end);
     196error:
     197        recv_unmark(rb, &value_start);
     198        return rc;
     199}
     200
     201int http_header_receive(receive_buffer_t *rb, http_header_t *header)
     202{
     203        char *name = NULL;
     204        int rc = http_header_receive_name(rb, &name);
     205        if (rc != EOK) {
     206                printf("Failed receiving header name\n");
     207                return rc;
     208        }
     209       
     210        char *value = NULL;
     211        rc = http_header_receive_value(rb, &value);
     212        if (rc != EOK) {
    117213                free(name);
    118                 return ENOMEM;
     214                return rc;
    119215        }
    120216       
    121217        header->name = name;
    122218        header->value = value;
    123        
    124219        return EOK;
    125220}
    126221
     222/** Normalize HTTP header value
     223 *
     224 * @see RFC2616 section 4.2
     225 */
     226void http_header_normalize_value(char *value)
     227{
     228        size_t read_index = 0;
     229        size_t write_index = 0;
     230       
     231        while (is_lws(value[read_index])) read_index++;
     232       
     233        while (value[read_index] != 0) {
     234                if (is_lws(value[read_index])) {
     235                        while (is_lws(value[read_index])) read_index++;
     236                       
     237                        if (value[read_index] != 0)
     238                                value[write_index++] = ' ';
     239                       
     240                        continue;
     241                }
     242               
     243                value[write_index++] = value[read_index++];
     244        }
     245       
     246        value[write_index] = 0;
     247}
     248
    127249/** @}
    128250 */
Note: See TracChangeset for help on using the changeset viewer.