LTP GCOV extension - code coverage report
Current view: directory - ext/http - http_url_api.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 227
Code covered: 81.1 % Executed lines: 184
Legend: not executed executed

       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-2007, Michael Wallner <mike@php.net>            |
      10                 :     +--------------------------------------------------------------------+
      11                 : */
      12                 : 
      13                 : /* $Id: http_url_api.c,v 1.52 2007/02/07 11:50:27 mike Exp $ */
      14                 : 
      15                 : #define HTTP_WANT_SAPI
      16                 : #define HTTP_WANT_NETDB
      17                 : #include "php_http.h"
      18                 : 
      19                 : #include "zend_ini.h"
      20                 : #include "php_output.h"
      21                 : #include "ext/standard/php_string.h"
      22                 : 
      23                 : #include "php_http_api.h"
      24                 : #include "php_http_querystring_api.h"
      25                 : #include "php_http_url_api.h"
      26                 : 
      27                 : static inline char *localhostname(void)
      28               2 : {
      29               2 :         char hostname[1024] = {0};
      30                 :         
      31                 : #ifdef PHP_WIN32
      32                 :         if (SUCCESS == gethostname(hostname, lenof(hostname))) {
      33                 :                 return estrdup(hostname);
      34                 :         }
      35                 : #elif defined(HAVE_GETHOSTNAME)
      36               2 :         if (SUCCESS == gethostname(hostname, lenof(hostname))) {
      37                 : #       if defined(HAVE_GETDOMAINNAME)
      38               2 :                 size_t hlen = strlen(hostname);
      39               2 :                 if (hlen <= lenof(hostname) - lenof("(none)")) {
      40               2 :                         hostname[hlen++] = '.';
      41               2 :                         if (SUCCESS == getdomainname(&hostname[hlen], lenof(hostname) - hlen)) {
      42               2 :                                 if (!strcmp(&hostname[hlen], "(none)")) {
      43               2 :                                         hostname[hlen - 1] = '\0';
      44                 :                                 }
      45               2 :                                 return estrdup(hostname);
      46                 :                         }
      47                 :                 }
      48                 : #       endif
      49               0 :                 if (strcmp(hostname, "(none)")) {
      50               0 :                         return estrdup(hostname);
      51                 :                 }
      52                 :         }
      53                 : #endif
      54               0 :         return estrdup("localhost");
      55                 : }
      56                 : 
      57                 : PHP_MINIT_FUNCTION(http_url)
      58             220 : {
      59             220 :         HTTP_LONG_CONSTANT("HTTP_URL_REPLACE", HTTP_URL_REPLACE);
      60             220 :         HTTP_LONG_CONSTANT("HTTP_URL_JOIN_PATH", HTTP_URL_JOIN_PATH);
      61             220 :         HTTP_LONG_CONSTANT("HTTP_URL_JOIN_QUERY", HTTP_URL_JOIN_QUERY);
      62             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_USER", HTTP_URL_STRIP_USER);
      63             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PASS", HTTP_URL_STRIP_PASS);
      64             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_AUTH", HTTP_URL_STRIP_AUTH);
      65             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PORT", HTTP_URL_STRIP_PORT);
      66             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_PATH", HTTP_URL_STRIP_PATH);
      67             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_QUERY", HTTP_URL_STRIP_QUERY);
      68             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_FRAGMENT", HTTP_URL_STRIP_FRAGMENT);
      69             220 :         HTTP_LONG_CONSTANT("HTTP_URL_STRIP_ALL", HTTP_URL_STRIP_ALL);
      70             220 :         return SUCCESS;
      71                 : }
      72                 : 
      73                 : PHP_HTTP_API char *_http_absolute_url(const char *url TSRMLS_DC)
      74              94 : {
      75              94 :         char *abs = NULL;
      76              94 :         php_url *purl = NULL;
      77                 :         
      78              94 :         if (url) {
      79              94 :                 purl = php_url_parse(abs = estrdup(url));
      80              94 :                 STR_SET(abs, NULL);
      81              94 :                 if (!purl) {
      82               0 :                         http_error_ex(HE_WARNING, HTTP_E_URL, "Could not parse URL (%s)", url);
      83               0 :                         return NULL;
      84                 :                 }
      85                 :         }
      86                 :         
      87              94 :         http_build_url(0, purl, NULL, NULL, &abs, NULL);
      88                 :         
      89              94 :         if (purl) {
      90              94 :                 php_url_free(purl);
      91                 :         }
      92                 :         
      93              94 :         return abs;
      94                 : }
      95                 : 
      96                 : /* {{{ void http_build_url(int flags, const php_url *, const php_url *, php_url **, char **, size_t *) */
      97                 : PHP_HTTP_API void _http_build_url(int flags, const php_url *old_url, const php_url *new_url, php_url **url_ptr, char **url_str, size_t *url_len TSRMLS_DC)
      98             106 : {
      99                 : #if defined(HAVE_GETSERVBYPORT) || defined(HAVE_GETSERVBYNAME)
     100                 :         struct servent *se;
     101                 : #endif
     102             106 :         php_url *url = ecalloc(1, sizeof(php_url));
     103                 : 
     104                 : #define __URLSET(u,n) \
     105                 :         ((u)&&(u)->n)
     106                 : #define __URLCPY(n) \
     107                 :         url->n = __URLSET(new_url,n) ? estrdup(new_url->n) : (__URLSET(old_url,n) ? estrdup(old_url->n) : NULL)
     108                 :         
     109             106 :         if (!(flags & HTTP_URL_STRIP_PORT)) {
     110             105 :                 url->port = (new_url&&new_url->port) ? new_url->port : ((old_url) ? old_url->port : 0);
     111                 :         }
     112             106 :         if (!(flags & HTTP_URL_STRIP_USER)) {
     113             104 :                 __URLCPY(user);
     114                 :         }
     115             106 :         if (!(flags & HTTP_URL_STRIP_PASS)) {
     116             104 :                 __URLCPY(pass);
     117                 :         }
     118                 :         
     119             106 :         __URLCPY(scheme);
     120             106 :         __URLCPY(host);
     121                 :         
     122             106 :         if (!(flags & HTTP_URL_STRIP_PATH)) {
     123             108 :                 if ((flags & HTTP_URL_JOIN_PATH) && __URLSET(old_url, path) && __URLSET(new_url, path) && *new_url->path != '/') {
     124               3 :                         size_t old_path_len = strlen(old_url->path), new_path_len = strlen(new_url->path);
     125                 :                         
     126               3 :                         url->path = ecalloc(1, old_path_len + new_path_len + 1 + 1);
     127                 :                         
     128               3 :                         strcat(url->path, old_url->path);
     129               3 :                         if (url->path[old_path_len - 1] != '/') {
     130               1 :                                 php_dirname(url->path, old_path_len);
     131               1 :                                 strcat(url->path, "/");
     132                 :                         }
     133               3 :                         strcat(url->path, new_url->path);
     134                 :                 } else {
     135             102 :                         __URLCPY(path);
     136                 :                 }
     137                 :         }
     138             106 :         if (!(flags & HTTP_URL_STRIP_QUERY)) {
     139             107 :                 if ((flags & HTTP_URL_JOIN_QUERY) && __URLSET(new_url, query) && __URLSET(old_url, query)) {
     140                 :                         zval qarr, qstr;
     141                 :                         
     142               1 :                         INIT_PZVAL(&qstr);
     143               1 :                         INIT_PZVAL(&qarr);
     144               1 :                         array_init(&qarr);
     145                 :                         
     146               1 :                         ZVAL_STRING(&qstr, old_url->query, 0);
     147               1 :                         http_querystring_modify(&qarr, &qstr);
     148               1 :                         ZVAL_STRING(&qstr, new_url->query, 0);
     149               1 :                         http_querystring_modify(&qarr, &qstr);
     150                 :                         
     151               1 :                         ZVAL_NULL(&qstr);
     152               1 :                         http_querystring_update(&qarr, &qstr);
     153               1 :                         url->query = Z_STRVAL(qstr);
     154               1 :                         zval_dtor(&qarr);
     155                 :                 } else {
     156             105 :                         __URLCPY(query);
     157                 :                 }
     158                 :         }
     159             106 :         if (!(flags & HTTP_URL_STRIP_FRAGMENT)) {
     160             105 :                 __URLCPY(fragment);
     161                 :         }
     162                 :         
     163             106 :         if (!url->scheme) {
     164               6 :                 zval *https = http_get_server_var("HTTPS", 1);
     165               6 :                 if (https && !strcasecmp(Z_STRVAL_P(https), "ON")) {
     166               0 :                         url->scheme = estrndup("https", lenof("https"));
     167               6 :                 } else switch (url->port) {
     168                 :                         case 443:
     169               0 :                                 url->scheme = estrndup("https", lenof("https"));
     170               0 :                                 break;
     171                 : 
     172                 : #ifndef HAVE_GETSERVBYPORT
     173                 :                         default:
     174                 : #endif
     175                 :                         case 80:
     176               0 :                                 url->scheme = estrndup("http", lenof("http"));
     177               0 :                                 break;
     178                 :                         
     179                 : #ifdef HAVE_GETSERVBYPORT
     180                 :                         default:
     181               6 :                                 if ((se = getservbyport(htons(url->port), "tcp")) && se->s_name) {
     182               0 :                                         url->scheme = estrdup(se->s_name);
     183                 :                                 } else {
     184               6 :                                         url->scheme = estrndup("http", lenof("http"));
     185                 :                                 }
     186                 :                                 break;
     187                 : #endif
     188                 :                 }
     189                 :         }
     190                 : 
     191             106 :         if (!url->host) {
     192                 :                 zval *zhost;
     193                 :                 
     194              12 :                 if ((((zhost = http_get_server_var("HTTP_HOST", 1)) || 
     195                 :                                 (zhost = http_get_server_var("SERVER_NAME", 1)))) && Z_STRLEN_P(zhost)) {
     196               5 :                         url->host = estrndup(Z_STRVAL_P(zhost), Z_STRLEN_P(zhost));
     197                 :                 } else {
     198               2 :                         url->host = localhostname();
     199                 :                 }
     200                 :         }
     201                 :         
     202             106 :         if (!url->path) {
     203              59 :                 if (SG(request_info).request_uri && SG(request_info).request_uri[0]) {
     204               0 :                         const char *q = strchr(SG(request_info).request_uri, '?');
     205                 :                         
     206               0 :                         if (q) {
     207               0 :                                 url->path = estrndup(SG(request_info).request_uri, q - SG(request_info).request_uri);
     208                 :                         } else {
     209               0 :                                 url->path = estrdup(SG(request_info).request_uri);
     210                 :                         }
     211                 :                 } else {
     212              59 :                         url->path = estrndup("/", 1);
     213                 :                 }
     214              47 :         } else if (url->path[0] != '/') {
     215               5 :                 if (SG(request_info).request_uri && SG(request_info).request_uri[0]) {
     216               0 :                         size_t ulen = strlen(SG(request_info).request_uri);
     217               0 :                         size_t plen = strlen(url->path);
     218                 :                         char *path;
     219                 :                         
     220               0 :                         if (SG(request_info).request_uri[ulen-1] != '/') {
     221               0 :                                 for (--ulen; ulen && SG(request_info).request_uri[ulen - 1] != '/'; --ulen);
     222                 :                         }
     223                 :                         
     224               0 :                         path = emalloc(ulen + plen + 1);
     225               0 :                         memcpy(path, SG(request_info).request_uri, ulen);
     226               0 :                         memcpy(path + ulen, url->path, plen);
     227               0 :                         path[ulen + plen] = '\0';
     228               0 :                         STR_SET(url->path, path);
     229                 :                 } else {
     230               5 :                         size_t plen = strlen(url->path);
     231               5 :                         char *path = emalloc(plen + 1 + 1);
     232                 :                         
     233               5 :                         path[0] = '/';
     234               5 :                         memcpy(&path[1], url->path, plen + 1);
     235               5 :                         STR_SET(url->path, path);
     236                 :                 }
     237                 :         }
     238                 :         /* replace directory references if path is not a single slash */
     239             106 :         if (url->path[0] && (url->path[0] != '/' || url->path[1])) {
     240              34 :                 char *ptr, *end = url->path + strlen(url->path) + 1;
     241                 :                         
     242              55 :                 for (ptr = strstr(url->path, "/."); ptr; ptr = strstr(ptr, "/.")) {
     243              21 :                         switch (ptr[2]) {
     244                 :                                 case '\0':
     245               0 :                                         ptr[1] = '\0';
     246               0 :                                         break;
     247                 :                                 
     248                 :                                 case '/':
     249               2 :                                         memmove(&ptr[1], &ptr[3], end - &ptr[3]);
     250               2 :                                         break;
     251                 :                                         
     252                 :                                 case '.':
     253               2 :                                         if (ptr[3] == '/') {
     254               2 :                                                 char *pos = &ptr[4];
     255              10 :                                                 while (ptr != url->path) {
     256               8 :                                                         if (*--ptr == '/') {
     257               2 :                                                                 break;
     258                 :                                                         }
     259                 :                                                 }
     260               2 :                                                 memmove(&ptr[1], pos, end - pos);
     261               2 :                                                 break;
     262               0 :                                         } else if (!ptr[3]) {
     263                 :                                                 /* .. at the end */
     264               0 :                                                 ptr[1] = '\0';
     265                 :                                         }
     266                 :                                         /* fallthrough */
     267                 :                                 
     268                 :                                 default:
     269                 :                                         /* something else */
     270              17 :                                         ++ptr;
     271                 :                                         break;
     272                 :                         }
     273                 :                 }
     274                 :         }
     275                 :         
     276             106 :         if (url->port) {
     277               3 :                 if (    ((url->port == 80) && !strcmp(url->scheme, "http"))
     278                 :                         ||      ((url->port ==443) && !strcmp(url->scheme, "https"))
     279                 : #ifdef HAVE_GETSERVBYNAME
     280                 :                         ||      ((se = getservbyname(url->scheme, "tcp")) && se->s_port && 
     281                 :                                         (url->port == ntohs(se->s_port)))
     282                 : #endif
     283                 :                 ) {
     284               1 :                         url->port = 0;
     285                 :                 }
     286                 :         }
     287                 :         
     288             106 :         if (url_str) {
     289                 :                 size_t len;
     290                 :                 
     291             106 :                 *url_str = emalloc(HTTP_URL_MAXLEN + 1);
     292                 :                 
     293             106 :                 **url_str = '\0';
     294             106 :                 strlcat(*url_str, url->scheme, HTTP_URL_MAXLEN);
     295             106 :                 strlcat(*url_str, "://", HTTP_URL_MAXLEN);
     296                 :                 
     297             106 :                 if (url->user && *url->user) {
     298               1 :                         strlcat(*url_str, url->user, HTTP_URL_MAXLEN);
     299               1 :                         if (url->pass && *url->pass) {
     300               0 :                                 strlcat(*url_str, ":", HTTP_URL_MAXLEN);
     301               0 :                                 strlcat(*url_str, url->pass, HTTP_URL_MAXLEN);
     302                 :                         }
     303               1 :                         strlcat(*url_str, "@", HTTP_URL_MAXLEN);
     304                 :                 }
     305                 :                 
     306             106 :                 strlcat(*url_str, url->host, HTTP_URL_MAXLEN);
     307                 :                 
     308             106 :                 if (url->port) {
     309                 :                         char port_str[8];
     310                 :                         
     311               2 :                         snprintf(port_str, sizeof(port_str), "%d", (int) url->port);
     312               2 :                         strlcat(*url_str, ":", HTTP_URL_MAXLEN);
     313               2 :                         strlcat(*url_str, port_str, HTTP_URL_MAXLEN);
     314                 :                 }
     315                 :                 
     316             106 :                 strlcat(*url_str, url->path, HTTP_URL_MAXLEN);
     317                 :                 
     318             106 :                 if (url->query && *url->query) {
     319               8 :                         strlcat(*url_str, "?", HTTP_URL_MAXLEN);
     320               8 :                         strlcat(*url_str, url->query, HTTP_URL_MAXLEN);
     321                 :                 }
     322                 :                 
     323             106 :                 if (url->fragment && *url->fragment) {
     324               6 :                         strlcat(*url_str, "#", HTTP_URL_MAXLEN);
     325               6 :                         strlcat(*url_str, url->fragment, HTTP_URL_MAXLEN);
     326                 :                 }
     327                 :                 
     328             106 :                 if (HTTP_URL_MAXLEN == (len = strlen(*url_str))) {
     329               0 :                         http_error(HE_NOTICE, HTTP_E_URL, "Length of URL exceeds HTTP_URL_MAXLEN");
     330                 :                 }
     331             106 :                 if (url_len) {
     332              12 :                         *url_len = len;
     333                 :                 }
     334                 :         }
     335                 :         
     336             106 :         if (url_ptr) {
     337               1 :                 *url_ptr = url;
     338                 :         } else {
     339             105 :                 php_url_free(url);
     340                 :         }
     341             106 : }
     342                 : /* }}} */
     343                 : 
     344                 : /* {{{ STATUS http_urlencode_hash_ex(HashTable *, zend_bool, char *, size_t, char **, size_t *) */
     345                 : PHP_HTTP_API STATUS _http_urlencode_hash_ex(HashTable *hash, zend_bool override_argsep,
     346                 :         char *pre_encoded_data, size_t pre_encoded_len,
     347                 :         char **encoded_data, size_t *encoded_len TSRMLS_DC)
     348              24 : {
     349                 :         char *arg_sep;
     350                 :         size_t arg_sep_len;
     351              24 :         phpstr *qstr = phpstr_new();
     352                 : 
     353              24 :         if (override_argsep || !(arg_sep_len = strlen(arg_sep = INI_STR("arg_separator.output")))) {
     354               5 :                 arg_sep = HTTP_URL_ARGSEP;
     355               5 :                 arg_sep_len = lenof(HTTP_URL_ARGSEP);
     356                 :         }
     357                 : 
     358              24 :         if (pre_encoded_len && pre_encoded_data) {
     359               0 :                 phpstr_append(qstr, pre_encoded_data, pre_encoded_len);
     360                 :         }
     361                 : 
     362              24 :         if (SUCCESS != http_urlencode_hash_recursive(hash, qstr, arg_sep, arg_sep_len, NULL, 0)) {
     363               0 :                 phpstr_free(&qstr);
     364               0 :                 return FAILURE;
     365                 :         }
     366                 : 
     367              24 :         phpstr_data(qstr, encoded_data, encoded_len);
     368              24 :         phpstr_free(&qstr);
     369                 : 
     370              24 :         return SUCCESS;
     371                 : }
     372                 : /* }}} */
     373                 : 
     374                 : /* {{{ http_urlencode_hash_recursive */
     375                 : PHP_HTTP_API STATUS _http_urlencode_hash_recursive(HashTable *ht, phpstr *str, const char *arg_sep, size_t arg_sep_len, const char *prefix, size_t prefix_len TSRMLS_DC)
     376              64 : {
     377              64 :         HashKey key = initHashKey(0);
     378              64 :         zval **data = NULL;
     379                 :         HashPosition pos;
     380                 : 
     381              64 :         if (!ht || !str) {
     382               0 :                 http_error(HE_WARNING, HTTP_E_INVALID_PARAM, "Invalid parameters");
     383               0 :                 return FAILURE;
     384                 :         }
     385              64 :         if (ht->nApplyCount > 0) {
     386               0 :                 return SUCCESS;
     387                 :         }
     388                 :         
     389             192 :         FOREACH_HASH_KEYVAL(pos, ht, key, data) {
     390                 :                 char *encoded_key;
     391                 :                 int encoded_len;
     392                 :                 phpstr new_prefix;
     393                 :                 
     394             128 :                 if (!data || !*data) {
     395               0 :                         phpstr_dtor(str);
     396               0 :                         return FAILURE;
     397                 :                 }
     398                 :                 
     399             128 :                 if (key.type == HASH_KEY_IS_STRING) {
     400              76 :                         if (!*key.str) {
     401                 :                                 /* only public properties */
     402               0 :                                 continue;
     403                 :                         }
     404              76 :                         if (key.len && key.str[key.len - 1] == '\0') {
     405              76 :                                 --key.len;
     406                 :                         }
     407              76 :                         encoded_key = php_url_encode(key.str, key.len, &encoded_len);
     408                 :                 } else {
     409              52 :                         encoded_len = spprintf(&encoded_key, 0, "%ld", key.num);
     410                 :                 }
     411                 :                 
     412                 :                 {
     413             128 :                         phpstr_init(&new_prefix);
     414             128 :                         if (prefix && prefix_len) {
     415              62 :                                 phpstr_append(&new_prefix, prefix, prefix_len);
     416              62 :                                 phpstr_appends(&new_prefix, "%5B");
     417                 :                         }
     418                 :                         
     419             128 :                         phpstr_append(&new_prefix, encoded_key, encoded_len);
     420             128 :                         efree(encoded_key);
     421                 :                         
     422             128 :                         if (prefix && prefix_len) {
     423              62 :                                 phpstr_appends(&new_prefix, "%5D");
     424                 :                         }
     425             128 :                         phpstr_fix(&new_prefix);
     426                 :                 }
     427                 :                 
     428             162 :                 if (Z_TYPE_PP(data) == IS_ARRAY || Z_TYPE_PP(data) == IS_OBJECT) {
     429                 :                         STATUS status;
     430              34 :                         ++ht->nApplyCount;
     431              34 :                         status = http_urlencode_hash_recursive(HASH_OF(*data), str, arg_sep, arg_sep_len, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
     432              34 :                         --ht->nApplyCount;
     433              34 :                         if (SUCCESS != status) {
     434               0 :                                 phpstr_dtor(&new_prefix);
     435               0 :                                 phpstr_dtor(str);
     436               0 :                                 return FAILURE;
     437                 :                         }
     438                 :                 } else {
     439              94 :                         zval *val = zval_copy(IS_STRING, *data);
     440                 :                         
     441              94 :                         if (PHPSTR_LEN(str)) {
     442              64 :                                 phpstr_append(str, arg_sep, arg_sep_len);
     443                 :                         }
     444              94 :                         phpstr_append(str, PHPSTR_VAL(&new_prefix), PHPSTR_LEN(&new_prefix));
     445              94 :                         phpstr_appends(str, "=");
     446                 :                         
     447              94 :                         if (Z_STRLEN_P(val) && Z_STRVAL_P(val)) {
     448                 :                                 char *encoded_val;
     449                 :                                 int encoded_len;
     450                 :                                 
     451              91 :                                 encoded_val = php_url_encode(Z_STRVAL_P(val), Z_STRLEN_P(val), &encoded_len);
     452              91 :                                 phpstr_append(str, encoded_val, encoded_len);
     453              91 :                                 efree(encoded_val);
     454                 :                         }
     455                 :                         
     456              94 :                         zval_free(&val);
     457                 :                 }
     458             128 :                 phpstr_dtor(&new_prefix);
     459                 :         }
     460              64 :         return SUCCESS;
     461                 : }
     462                 : /* }}} */
     463                 : 
     464                 : /*
     465                 :  * Local variables:
     466                 :  * tab-width: 4
     467                 :  * c-basic-offset: 4
     468                 :  * End:
     469                 :  * vim600: noet sw=4 ts=4 fdm=marker
     470                 :  * vim<600: noet sw=4 ts=4
     471                 :  */
     472                 : 

Generated by: LTP GCOV extension version 1.5