LCOV - code coverage report
Current view: top level - ext/http - php_http_info.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 60 73 82.2 %
Date: 2015-02-17 20:30:22 Functions: 3 4 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :     +--------------------------------------------------------------------+
       3             :     | PECL :: http                                                       |
       4             :     +--------------------------------------------------------------------+
       5             :     | Redistribution and use in source and binary forms, with or without |
       6             :     | modification, are permitted provided that the conditions mentioned |
       7             :     | in the accompanying LICENSE file are met.                          |
       8             :     +--------------------------------------------------------------------+
       9             :     | Copyright (c) 2004-2014, Michael Wallner <mike@php.net>            |
      10             :     +--------------------------------------------------------------------+
      11             : */
      12             : 
      13             : #include "php_http_api.h"
      14             : 
      15         136 : php_http_info_t *php_http_info_init(php_http_info_t *i TSRMLS_DC)
      16             : {
      17         136 :         if (!i) {
      18           0 :                 i = emalloc(sizeof(*i));
      19             :         }
      20             : 
      21         136 :         memset(i, 0, sizeof(*i));
      22             : 
      23         136 :         return i;
      24             : }
      25             : 
      26         280 : void php_http_info_dtor(php_http_info_t *i)
      27             : {
      28         280 :         switch (i->type) {
      29             :                 case PHP_HTTP_REQUEST:
      30          61 :                         PTR_SET(PHP_HTTP_INFO(i).request.method, NULL);
      31          61 :                         PTR_SET(PHP_HTTP_INFO(i).request.url, NULL);
      32          61 :                         break;
      33             :                 
      34             :                 case PHP_HTTP_RESPONSE:
      35         164 :                         PTR_SET(PHP_HTTP_INFO(i).response.status, NULL);
      36         164 :                         break;
      37             :                 
      38             :                 default:
      39          55 :                         break;
      40             :         }
      41         280 : }
      42             : 
      43           0 : void php_http_info_free(php_http_info_t **i)
      44             : {
      45           0 :         if (*i) {
      46           0 :                 php_http_info_dtor(*i);
      47           0 :                 efree(*i);
      48           0 :                 *i = NULL;
      49             :         }
      50           0 : }
      51             : 
      52         537 : php_http_info_t *php_http_info_parse(php_http_info_t *info, const char *pre_header TSRMLS_DC)
      53             : {
      54             :         const char *end, *http;
      55         537 :         zend_bool free_info = !info;
      56             :         
      57             :         /* sane parameter */
      58         537 :         if ((!pre_header) || (!*pre_header)) {
      59           0 :                 return NULL;
      60             :         }
      61             :         
      62             :         /* where's the end of the line */
      63         537 :         if (!(end = php_http_locate_eol(pre_header, NULL))) {
      64          37 :                 end = pre_header + strlen(pre_header);
      65             :         }
      66             :         
      67             :         /* there must be HTTP/1.x in the line */
      68         537 :         if (!(http = php_http_locate_str(pre_header, end - pre_header, "HTTP/", lenof("HTTP/")))) {
      69         401 :                 return NULL;
      70             :         }
      71             :         
      72         136 :         info = php_http_info_init(info TSRMLS_CC);
      73             : 
      74             :         /* and nothing than SPACE or NUL after HTTP/X.x */
      75         136 :         if (!php_http_version_parse(&info->http.version, http TSRMLS_CC)
      76         136 :         ||      (http[lenof("HTTP/X.x")] && (!PHP_HTTP_IS_CTYPE(space, http[lenof("HTTP/X.x")])))) {
      77           5 :                 if (free_info) {
      78           0 :                         php_http_info_free(&info);
      79             :                 }
      80           5 :                 return NULL;
      81             :         }
      82             : 
      83             : #if 0
      84             :         {
      85             :                 char *line = estrndup(pre_header, end - pre_header);
      86             :                 fprintf(stderr, "http_parse_info('%s')\n", line);
      87             :                 efree(line);
      88             :         }
      89             : #endif
      90             : 
      91             :         /* is response */
      92         131 :         if (pre_header == http) {
      93          88 :                 const char *status = NULL, *code = http + sizeof("HTTP/X.x");
      94             :                 
      95          88 :                 info->type = PHP_HTTP_RESPONSE;
      96          88 :                 while (' ' == *code) ++code;
      97          88 :                 if (code && end > code) {
      98             :                         /* rfc7230#3.1.2 The status-code element is a 3-digit integer code */
      99          87 :                         PHP_HTTP_INFO(info).response.code = 100*(*code++ - '0');
     100          87 :                         PHP_HTTP_INFO(info).response.code += 10*(*code++ - '0');
     101          87 :                         PHP_HTTP_INFO(info).response.code +=     *code++ - '0';
     102          87 :                         if (PHP_HTTP_INFO(info).response.code < 100 || PHP_HTTP_INFO(info).response.code > 599) {
     103           1 :                                 if (free_info) {
     104           0 :                                         php_http_info_free(&info);
     105             :                                 }
     106           1 :                                 return NULL;
     107             :                         }
     108          86 :                         status = code;
     109             :                 } else {
     110           1 :                         PHP_HTTP_INFO(info).response.code = 0;
     111             :                 }
     112          87 :                 if (status && end > status) {
     113          73 :                         while (' ' == *status) ++status;
     114          73 :                         PHP_HTTP_INFO(info).response.status = estrndup(status, end - status);
     115             :                 } else {
     116          14 :                         PHP_HTTP_INFO(info).response.status = NULL;
     117             :                 }
     118             :                 
     119          87 :                 return info;
     120             :         }
     121             :         
     122             :         /* is request */
     123          43 :         else if (*(http - 1) == ' ' && (!http[lenof("HTTP/X.x")] || http[lenof("HTTP/X.x")] == '\r' || http[lenof("HTTP/X.x")] == '\n')) {
     124          42 :                 const char *url = strchr(pre_header, ' ');
     125             :                 
     126          42 :                 info->type = PHP_HTTP_REQUEST;
     127          82 :                 if (url && http > url) {
     128          42 :                         size_t url_len = url - pre_header;
     129             : 
     130          42 :                         PHP_HTTP_INFO(info).request.method = estrndup(pre_header, url_len);
     131             : 
     132          42 :                         while (' ' == *url) ++url;
     133          42 :                         while (' ' == *(http-1)) --http;
     134             : 
     135          42 :                         if (http > url) {
     136             :                                 /* CONNECT presents an authority only */
     137          40 :                                 if (strcasecmp(PHP_HTTP_INFO(info).request.method, "CONNECT")) {
     138          39 :                                         PHP_HTTP_INFO(info).request.url = php_http_url_parse(url, http - url, ~0 TSRMLS_CC);
     139             :                                 } else {
     140           1 :                                         PHP_HTTP_INFO(info).request.url = php_http_url_parse_authority(url, http - url, ~0 TSRMLS_CC);
     141             :                                 }
     142             :                         } else {
     143           2 :                                 PTR_SET(PHP_HTTP_INFO(info).request.method, NULL);
     144           2 :                                 return NULL;
     145             :                         }
     146             :                 } else {
     147           0 :                         PHP_HTTP_INFO(info).request.method = NULL;
     148           0 :                         PHP_HTTP_INFO(info).request.url = NULL;
     149             :                 }
     150             :                 
     151          40 :                 return info;
     152             :         }
     153             : 
     154             :         /* some darn header containing HTTP/X.x */
     155             :         else {
     156           1 :                 if (free_info) {
     157           0 :                         php_http_info_free(&info);
     158             :                 }
     159           1 :                 return NULL;
     160             :         }
     161             : }
     162             : 
     163             : /*
     164             :  * Local variables:
     165             :  * tab-width: 4
     166             :  * c-basic-offset: 4
     167             :  * End:
     168             :  * vim600: noet sw=4 ts=4 fdm=marker
     169             :  * vim<600: noet sw=4 ts=4
     170             :  */
     171             : 

Generated by: LCOV version 1.11