LTP GCOV extension - code coverage report
Current view: directory - ext/standard - url.c
Test: PHP Code Coverage
Date: 2007-04-10 Instrumented lines: 343
Code covered: 47.2 % Executed lines: 162
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 5                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2007 The PHP Group                                |
       6                 :    +----------------------------------------------------------------------+
       7                 :    | This source file is subject to version 3.01 of the PHP license,      |
       8                 :    | that is bundled with this package in the file LICENSE, and is        |
       9                 :    | available through the world-wide-web at the following url:           |
      10                 :    | http://www.php.net/license/3_01.txt                                  |
      11                 :    | If you did not receive a copy of the PHP license and are unable to   |
      12                 :    | obtain it through the world-wide-web, please send a note to          |
      13                 :    | license@php.net so we can mail you a copy immediately.               |
      14                 :    +----------------------------------------------------------------------+
      15                 :    | Author: Jim Winstead <jimw@php.net>                                  |
      16                 :    +----------------------------------------------------------------------+
      17                 :  */
      18                 : /* $Id: url.c,v 1.86.2.5.2.7 2007/01/01 09:36:09 sebastian Exp $ */
      19                 : 
      20                 : #include <stdlib.h>
      21                 : #include <string.h>
      22                 : #include <ctype.h>
      23                 : #include <sys/types.h>
      24                 : 
      25                 : #include "php.h"
      26                 : 
      27                 : #include "url.h"
      28                 : #include "file.h"
      29                 : #ifdef _OSD_POSIX
      30                 : #ifndef APACHE
      31                 : #error On this EBCDIC platform, PHP is only supported as an Apache module.
      32                 : #else /*APACHE*/
      33                 : #ifndef CHARSET_EBCDIC
      34                 : #define CHARSET_EBCDIC /* this machine uses EBCDIC, not ASCII! */
      35                 : #endif
      36                 : #include "ebcdic.h"
      37                 : #endif /*APACHE*/
      38                 : #endif /*_OSD_POSIX*/
      39                 : 
      40                 : /* {{{ free_url
      41                 :  */
      42                 : PHPAPI void php_url_free(php_url *theurl)
      43             223 : {
      44             223 :         if (theurl->scheme)
      45             210 :                 efree(theurl->scheme);
      46             223 :         if (theurl->user)
      47               4 :                 efree(theurl->user);
      48             223 :         if (theurl->pass)
      49               1 :                 efree(theurl->pass);
      50             223 :         if (theurl->host)
      51             209 :                 efree(theurl->host);
      52             223 :         if (theurl->path)
      53             161 :                 efree(theurl->path);
      54             223 :         if (theurl->query)
      55              18 :                 efree(theurl->query);
      56             223 :         if (theurl->fragment)
      57              17 :                 efree(theurl->fragment);
      58             223 :         efree(theurl);
      59             223 : }
      60                 : /* }}} */
      61                 : 
      62                 : /* {{{ php_replace_controlchars
      63                 :  */
      64                 : PHPAPI char *php_replace_controlchars_ex(char *str, int len)
      65             273 : {
      66             273 :         unsigned char *s = (unsigned char *)str;
      67             273 :         unsigned char *e = (unsigned char *)str + len;
      68                 :         
      69             273 :         if (!str) {
      70               0 :                 return (NULL);
      71                 :         }
      72                 :         
      73            2807 :         while (s < e) {
      74                 :             
      75            2261 :                 if (iscntrl(*s)) {
      76               0 :                         *s='_';
      77                 :                 }       
      78            2261 :                 s++;
      79                 :         }
      80                 :         
      81             273 :         return (str);
      82                 : } 
      83                 : /* }}} */
      84                 : 
      85                 : PHPAPI char *php_replace_controlchars(char *str)
      86               0 : {
      87               0 :         return php_replace_controlchars_ex(str, strlen(str));
      88                 : } 
      89                 : 
      90                 : PHPAPI php_url *php_url_parse(char const *str)
      91              94 : {
      92              94 :         return php_url_parse_ex(str, strlen(str));
      93                 : }
      94                 : 
      95                 : /* {{{ php_url_parse
      96                 :  */
      97                 : PHPAPI php_url *php_url_parse_ex(char const *str, int length)
      98             112 : {
      99                 :         char port_buf[6];
     100             112 :         php_url *ret = ecalloc(1, sizeof(php_url));
     101                 :         char const *s, *e, *p, *pp, *ue;
     102                 :                 
     103             112 :         s = str;
     104             112 :         ue = s + length;
     105                 : 
     106                 :         /* parse scheme */
     107             211 :         if ((e = memchr(s, ':', length)) && (e - s)) {
     108                 :                 /* validate scheme */
     109              99 :                 p = s;
     110             598 :                 while (p < e) {
     111                 :                         /* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */
     112             400 :                         if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') {
     113               0 :                                 if (e + 1 < ue) {
     114               0 :                                         goto parse_port;
     115                 :                                 } else {
     116               0 :                                         goto just_path;
     117                 :                                 }
     118                 :                         }
     119             400 :                         p++;
     120                 :                 }
     121                 :         
     122              99 :                 if (*(e + 1) == '\0') { /* only scheme is available */
     123               0 :                         ret->scheme = estrndup(s, (e - s));
     124               0 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     125               0 :                         goto end;
     126                 :                 }
     127                 : 
     128                 :                 /* 
     129                 :                  * certain schemas like mailto: and zlib: may not have any / after them
     130                 :                  * this check ensures we support those.
     131                 :                  */
     132              99 :                 if (*(e+1) != '/') {
     133                 :                         /* check if the data we get is a port this allows us to 
     134                 :                          * correctly parse things like a.com:80
     135                 :                          */
     136               0 :                         p = e + 1;
     137               0 :                         while (isdigit(*p)) {
     138               0 :                                 p++;
     139                 :                         }
     140                 :                         
     141               0 :                         if ((*p == '\0' || *p == '/') && (p - e) < 7) {
     142               0 :                                 goto parse_port;
     143                 :                         }
     144                 :                         
     145               0 :                         ret->scheme = estrndup(s, (e-s));
     146               0 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     147                 :                         
     148               0 :                         length -= ++e - s;
     149               0 :                         s = e;
     150               0 :                         goto just_path;
     151                 :                 } else {
     152              99 :                         ret->scheme = estrndup(s, (e-s));
     153              99 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     154                 :                 
     155              99 :                         if (*(e+2) == '/') {
     156              99 :                                 s = e + 3;
     157              99 :                                 if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
     158               0 :                                         if (*(e + 3) == '/') {
     159                 :                                                 /* support windows drive letters as in:
     160                 :                                                    file:///c:/somedir/file.txt
     161                 :                                                 */
     162               0 :                                                 if (*(e + 5) == ':') {
     163               0 :                                                         s = e + 4;
     164                 :                                                 }
     165               0 :                                                 goto nohost;
     166                 :                                         }
     167                 :                                 }
     168                 :                         } else {
     169               0 :                                 if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
     170               0 :                                         s = e + 1;
     171               0 :                                         goto nohost;
     172                 :                                 } else {
     173               0 :                                         length -= ++e - s;
     174               0 :                                         s = e;
     175               0 :                                         goto just_path;
     176                 :                                 }       
     177                 :                         }
     178                 :                 }       
     179              13 :         } else if (e) { /* no scheme, look for port */
     180               0 :                 parse_port:
     181               0 :                 p = e + 1;
     182               0 :                 pp = p;
     183                 :                 
     184               0 :                 while (pp-p < 6 && isdigit(*pp)) {
     185               0 :                         pp++;
     186                 :                 }
     187                 :                 
     188               0 :                 if (pp-p < 6 && (*pp == '/' || *pp == '\0')) {
     189               0 :                         memcpy(port_buf, p, (pp-p));
     190               0 :                         port_buf[pp-p] = '\0';
     191               0 :                         ret->port = atoi(port_buf);
     192                 :                 } else {
     193                 :                         goto just_path;
     194                 :                 }
     195                 :         } else {
     196              13 :                 just_path:
     197              13 :                 ue = s + length;
     198              13 :                 goto nohost;
     199                 :         }
     200                 :         
     201              99 :         e = ue;
     202                 :         
     203              99 :         if (!(p = memchr(s, '/', (ue - s)))) {
     204              58 :                 if ((p = memchr(s, '?', (ue - s)))) {
     205               0 :                         e = p;
     206              58 :                 } else if ((p = memchr(s, '#', (ue - s)))) {
     207               0 :                         e = p;
     208                 :                 }
     209                 :         } else {
     210              41 :                 e = p;
     211                 :         }       
     212                 :                 
     213                 :         /* check for login and password */
     214              99 :         if ((p = zend_memrchr(s, '@', (e-s)))) {
     215               3 :                 if ((pp = memchr(s, ':', (p-s)))) {
     216               1 :                         if ((pp-s) > 0) {
     217               1 :                                 ret->user = estrndup(s, (pp-s));
     218               1 :                                 php_replace_controlchars_ex(ret->user, (pp - s));
     219                 :                         }       
     220                 :                 
     221               1 :                         pp++;
     222               1 :                         if (p-pp > 0) {
     223               1 :                                 ret->pass = estrndup(pp, (p-pp));
     224               1 :                                 php_replace_controlchars_ex(ret->pass, (p-pp));
     225                 :                         }       
     226                 :                 } else {
     227               2 :                         ret->user = estrndup(s, (p-s));
     228               2 :                         php_replace_controlchars_ex(ret->user, (p-s));
     229                 :                 }
     230                 :                 
     231               3 :                 s = p + 1;
     232                 :         }
     233                 : 
     234                 :         /* check for port */
     235              99 :         if (*s == '[' && *(e-1) == ']') {
     236                 :                 /* Short circuit portscan, 
     237                 :                    we're dealing with an 
     238                 :                    IPv6 embedded address */
     239               0 :                 p = s;
     240                 :         } else {
     241                 :                 /* memrchr is a GNU specific extension
     242                 :                    Emulate for wide compatability */
     243              99 :                 for(p = e; *p != ':' && p >= s; p--);
     244                 :         }
     245                 : 
     246             102 :         if (p >= s && *p == ':') {
     247               3 :                 if (!ret->port) {
     248               3 :                         p++;
     249               3 :                         if (e-p > 5) { /* port cannot be longer then 5 characters */
     250               0 :                                 STR_FREE(ret->scheme);
     251               0 :                                 STR_FREE(ret->user);
     252               0 :                                 STR_FREE(ret->pass);
     253               0 :                                 efree(ret);
     254               0 :                                 return NULL;
     255               3 :                         } else if (e - p > 0) {
     256               3 :                                 memcpy(port_buf, p, (e-p));
     257               3 :                                 port_buf[e-p] = '\0';
     258               3 :                                 ret->port = atoi(port_buf);
     259                 :                         }
     260               3 :                         p--;
     261                 :                 }       
     262                 :         } else {
     263              96 :                 p = e;
     264                 :         }
     265                 :         
     266                 :         /* check if we have a valid host, if we don't reject the string as url */
     267              99 :         if ((p-s) < 1) {
     268               0 :                 STR_FREE(ret->scheme);
     269               0 :                 STR_FREE(ret->user);
     270               0 :                 STR_FREE(ret->pass);
     271               0 :                 efree(ret);
     272               0 :                 return NULL;
     273                 :         }
     274                 : 
     275              99 :         ret->host = estrndup(s, (p-s));
     276              99 :         php_replace_controlchars_ex(ret->host, (p - s));
     277                 :         
     278              99 :         if (e == ue) {
     279              58 :                 return ret;
     280                 :         }
     281                 :         
     282              41 :         s = e;
     283                 :         
     284              54 :         nohost:
     285                 :         
     286              54 :         if ((p = memchr(s, '?', (ue - s)))) {
     287               9 :                 pp = strchr(s, '#');
     288                 :                 
     289               9 :                 if (pp && pp < p) {
     290               0 :                         p = pp;
     291               0 :                         pp = strchr(pp+2, '#');
     292                 :                 }
     293                 :         
     294               9 :                 if (p - s) {
     295               8 :                         ret->path = estrndup(s, (p-s));
     296               8 :                         php_replace_controlchars_ex(ret->path, (p - s));
     297                 :                 }       
     298                 :         
     299               9 :                 if (pp) {
     300               7 :                         if (pp - ++p) { 
     301               7 :                                 ret->query = estrndup(p, (pp-p));
     302               7 :                                 php_replace_controlchars_ex(ret->query, (pp - p));
     303                 :                         }
     304               7 :                         p = pp;
     305               7 :                         goto label_parse;
     306               2 :                 } else if (++p - ue) {
     307               2 :                         ret->query = estrndup(p, (ue-p));
     308               2 :                         php_replace_controlchars_ex(ret->query, (ue - p));
     309                 :                 }
     310              45 :         } else if ((p = memchr(s, '#', (ue - s)))) {
     311               2 :                 if (p - s) {
     312               2 :                         ret->path = estrndup(s, (p-s));
     313               2 :                         php_replace_controlchars_ex(ret->path, (p - s));
     314                 :                 }       
     315                 :                 
     316               9 :                 label_parse:
     317               9 :                 p++;
     318                 :                 
     319               9 :                 if (ue - p) {
     320               9 :                         ret->fragment = estrndup(p, (ue-p));
     321               9 :                         php_replace_controlchars_ex(ret->fragment, (ue - p));
     322                 :                 }       
     323                 :         } else {
     324              43 :                 ret->path = estrndup(s, (ue-s));
     325              43 :                 php_replace_controlchars_ex(ret->path, (ue - s));
     326                 :         }
     327              54 : end:
     328              54 :         return ret;
     329                 : }
     330                 : /* }}} */
     331                 : 
     332                 : /* {{{ proto mixed parse_url(string url, [int url_component])
     333                 :    Parse a URL and return its components */
     334                 : PHP_FUNCTION(parse_url)
     335               2 : {
     336                 :         char *str;
     337                 :         int str_len;
     338                 :         php_url *resource;
     339               2 :         long key = -1;
     340                 : 
     341               2 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &str, &str_len, &key) == FAILURE) {
     342               0 :                 return;
     343                 :         }
     344                 : 
     345               2 :         resource = php_url_parse_ex(str, str_len);
     346               2 :         if (resource == NULL) {
     347               0 :                 php_error_docref1(NULL TSRMLS_CC, str, E_WARNING, "Unable to parse URL");
     348               0 :                 RETURN_FALSE;
     349                 :         }
     350                 : 
     351               2 :         if (key > -1) {
     352               0 :                 switch (key) {
     353                 :                         case PHP_URL_SCHEME:
     354               0 :                                 if (resource->scheme != NULL) RETVAL_STRING(resource->scheme, 1);
     355               0 :                                 break;
     356                 :                         case PHP_URL_HOST:
     357               0 :                                 if (resource->host != NULL) RETVAL_STRING(resource->host, 1);
     358               0 :                                 break;
     359                 :                         case PHP_URL_PORT:
     360               0 :                                 if (resource->port != 0) RETVAL_LONG(resource->port);
     361               0 :                                 break;
     362                 :                         case PHP_URL_USER:
     363               0 :                                 if (resource->user != NULL) RETVAL_STRING(resource->user, 1);
     364               0 :                                 break;
     365                 :                         case PHP_URL_PASS:
     366               0 :                                 if (resource->pass != NULL) RETVAL_STRING(resource->pass, 1);
     367               0 :                                 break;
     368                 :                         case PHP_URL_PATH:
     369               0 :                                 if (resource->path != NULL) RETVAL_STRING(resource->path, 1);
     370               0 :                                 break;
     371                 :                         case PHP_URL_QUERY:
     372               0 :                                 if (resource->query != NULL) RETVAL_STRING(resource->query, 1);
     373               0 :                                 break;
     374                 :                         case PHP_URL_FRAGMENT:
     375               0 :                                 if (resource->fragment != NULL) RETVAL_STRING(resource->fragment, 1);
     376               0 :                                 break;
     377                 :                         default:
     378               0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL component identifier %ld.", key);
     379               0 :                                 RETVAL_FALSE;
     380                 :                 }
     381               0 :                 goto done;
     382                 :         }
     383                 : 
     384                 :         /* allocate an array for return */
     385               2 :         array_init(return_value);
     386                 : 
     387                 :     /* add the various elements to the array */
     388               2 :         if (resource->scheme != NULL)
     389               2 :                 add_assoc_string(return_value, "scheme", resource->scheme, 1);
     390               2 :         if (resource->host != NULL)
     391               2 :                 add_assoc_string(return_value, "host", resource->host, 1);
     392               2 :         if (resource->port != 0)
     393               1 :                 add_assoc_long(return_value, "port", resource->port);
     394               2 :         if (resource->user != NULL)
     395               0 :                 add_assoc_string(return_value, "user", resource->user, 1);
     396               2 :         if (resource->pass != NULL)
     397               0 :                 add_assoc_string(return_value, "pass", resource->pass, 1);
     398               2 :         if (resource->path != NULL)
     399               2 :                 add_assoc_string(return_value, "path", resource->path, 1);
     400               2 :         if (resource->query != NULL)
     401               1 :                 add_assoc_string(return_value, "query", resource->query, 1);
     402               2 :         if (resource->fragment != NULL)
     403               2 :                 add_assoc_string(return_value, "fragment", resource->fragment, 1);
     404               2 : done:   
     405               2 :         php_url_free(resource);
     406                 : }
     407                 : /* }}} */
     408                 : 
     409                 : /* {{{ php_htoi
     410                 :  */
     411                 : static int php_htoi(char *s)
     412               0 : {
     413                 :         int value;
     414                 :         int c;
     415                 : 
     416               0 :         c = ((unsigned char *)s)[0];
     417               0 :         if (isupper(c))
     418               0 :                 c = tolower(c);
     419               0 :         value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
     420                 : 
     421               0 :         c = ((unsigned char *)s)[1];
     422               0 :         if (isupper(c))
     423               0 :                 c = tolower(c);
     424               0 :         value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
     425                 : 
     426               0 :         return (value);
     427                 : }
     428                 : /* }}} */
     429                 : 
     430                 : /* rfc1738:
     431                 : 
     432                 :    ...The characters ";",
     433                 :    "/", "?", ":", "@", "=" and "&" are the characters which may be
     434                 :    reserved for special meaning within a scheme...
     435                 : 
     436                 :    ...Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
     437                 :    reserved characters used for their reserved purposes may be used
     438                 :    unencoded within a URL...
     439                 : 
     440                 :    For added safety, we only leave -_. unencoded.
     441                 :  */
     442                 : 
     443                 : static unsigned char hexchars[] = "0123456789ABCDEF";
     444                 : 
     445                 : /* {{{ php_url_encode
     446                 :  */
     447                 : PHPAPI char *php_url_encode(char const *s, int len, int *new_length)
     448             167 : {
     449                 :         register unsigned char c;
     450                 :         unsigned char *to, *start;
     451                 :         unsigned char const *from, *end;
     452                 :         
     453             167 :         from = s;
     454             167 :         end = s + len;
     455             167 :         start = to = (unsigned char *) safe_emalloc(3, len, 1);
     456                 : 
     457             690 :         while (from < end) {
     458             356 :                 c = *from++;
     459                 : 
     460             356 :                 if (c == ' ') {
     461               0 :                         *to++ = '+';
     462                 : #ifndef CHARSET_EBCDIC
     463             373 :                 } else if ((c < '0' && c != '-' && c != '.') ||
     464                 :                                    (c < 'A' && c > '9') ||
     465                 :                                    (c > 'Z' && c < 'a' && c != '_') ||
     466                 :                                    (c > 'z')) {
     467              17 :                         to[0] = '%';
     468              17 :                         to[1] = hexchars[c >> 4];
     469              17 :                         to[2] = hexchars[c & 15];
     470              17 :                         to += 3;
     471                 : #else /*CHARSET_EBCDIC*/
     472                 :                 } else if (!isalnum(c) && strchr("_-.", c) == NULL) {
     473                 :                         /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */
     474                 :                         to[0] = '%';
     475                 :                         to[1] = hexchars[os_toascii[c] >> 4];
     476                 :                         to[2] = hexchars[os_toascii[c] & 15];
     477                 :                         to += 3;
     478                 : #endif /*CHARSET_EBCDIC*/
     479                 :                 } else {
     480             339 :                         *to++ = c;
     481                 :                 }
     482                 :         }
     483             167 :         *to = 0;
     484             167 :         if (new_length) {
     485             167 :                 *new_length = to - start;
     486                 :         }
     487             167 :         return (char *) start;
     488                 : }
     489                 : /* }}} */
     490                 : 
     491                 : /* {{{ proto string urlencode(string str)
     492                 :    URL-encodes string */
     493                 : PHP_FUNCTION(urlencode)
     494               0 : {
     495                 :         char *in_str, *out_str;
     496                 :         int in_str_len, out_str_len;
     497                 : 
     498               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
     499                 :                                                           &in_str_len) == FAILURE) {
     500               0 :                 return;
     501                 :         }
     502                 : 
     503               0 :         out_str = php_url_encode(in_str, in_str_len, &out_str_len);
     504               0 :         RETURN_STRINGL(out_str, out_str_len, 0);
     505                 : }
     506                 : /* }}} */
     507                 : 
     508                 : /* {{{ proto string urldecode(string str)
     509                 :    Decodes URL-encoded string */
     510                 : PHP_FUNCTION(urldecode)
     511               0 : {
     512                 :         char *in_str, *out_str;
     513                 :         int in_str_len, out_str_len;
     514                 : 
     515               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
     516                 :                                                           &in_str_len) == FAILURE) {
     517               0 :                 return;
     518                 :         }
     519                 : 
     520               0 :         out_str = estrndup(in_str, in_str_len);
     521               0 :         out_str_len = php_url_decode(out_str, in_str_len);
     522                 : 
     523               0 :     RETURN_STRINGL(out_str, out_str_len, 0);
     524                 : }
     525                 : /* }}} */
     526                 : 
     527                 : /* {{{ php_url_decode
     528                 :  */
     529                 : PHPAPI int php_url_decode(char *str, int len)
     530              66 : {
     531              66 :         char *dest = str;
     532              66 :         char *data = str;
     533                 : 
     534             490 :         while (len--) {
     535             358 :                 if (*data == '+') {
     536               0 :                         *dest = ' ';
     537                 :                 }
     538             358 :                 else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) 
     539                 :                                  && isxdigit((int) *(data + 2))) {
     540                 : #ifndef CHARSET_EBCDIC
     541               0 :                         *dest = (char) php_htoi(data + 1);
     542                 : #else
     543                 :                         *dest = os_toebcdic[(char) php_htoi(data + 1)];
     544                 : #endif
     545               0 :                         data += 2;
     546               0 :                         len -= 2;
     547                 :                 } else {
     548             358 :                         *dest = *data;
     549                 :                 }
     550             358 :                 data++;
     551             358 :                 dest++;
     552                 :         }
     553              66 :         *dest = '\0';
     554              66 :         return dest - str;
     555                 : }
     556                 : /* }}} */
     557                 : 
     558                 : /* {{{ php_raw_url_encode
     559                 :  */
     560                 : PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length)
     561               0 : {
     562                 :         register int x, y;
     563                 :         unsigned char *str;
     564                 : 
     565               0 :         str = (unsigned char *) safe_emalloc(3, len, 1);
     566               0 :         for (x = 0, y = 0; len--; x++, y++) {
     567               0 :                 str[y] = (unsigned char) s[x];
     568                 : #ifndef CHARSET_EBCDIC
     569               0 :                 if ((str[y] < '0' && str[y] != '-' && str[y] != '.') ||
     570                 :                         (str[y] < 'A' && str[y] > '9') ||
     571                 :                         (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
     572                 :                         (str[y] > 'z')) {
     573               0 :                         str[y++] = '%';
     574               0 :                         str[y++] = hexchars[(unsigned char) s[x] >> 4];
     575               0 :                         str[y] = hexchars[(unsigned char) s[x] & 15];
     576                 : #else /*CHARSET_EBCDIC*/
     577                 :                 if (!isalnum(str[y]) && strchr("_-.", str[y]) != NULL) {
     578                 :                         str[y++] = '%';
     579                 :                         str[y++] = hexchars[os_toascii[(unsigned char) s[x]] >> 4];
     580                 :                         str[y] = hexchars[os_toascii[(unsigned char) s[x]] & 15];
     581                 : #endif /*CHARSET_EBCDIC*/
     582                 :                 }
     583                 :         }
     584               0 :         str[y] = '\0';
     585               0 :         if (new_length) {
     586               0 :                 *new_length = y;
     587                 :         }
     588               0 :         return ((char *) str);
     589                 : }
     590                 : /* }}} */
     591                 : 
     592                 : /* {{{ proto string rawurlencode(string str)
     593                 :    URL-encodes string */
     594                 : PHP_FUNCTION(rawurlencode)
     595               0 : {
     596                 :         char *in_str, *out_str;
     597                 :         int in_str_len, out_str_len;
     598                 : 
     599               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
     600                 :                                                           &in_str_len) == FAILURE) {
     601               0 :                 return;
     602                 :         }
     603                 : 
     604               0 :         out_str = php_raw_url_encode(in_str, in_str_len, &out_str_len);
     605               0 :         RETURN_STRINGL(out_str, out_str_len, 0);
     606                 : }
     607                 : /* }}} */
     608                 : 
     609                 : /* {{{ proto string rawurldecode(string str)
     610                 :    Decodes URL-encodes string */
     611                 : PHP_FUNCTION(rawurldecode)
     612               0 : {
     613                 :         char *in_str, *out_str;
     614                 :         int in_str_len, out_str_len;
     615                 : 
     616               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &in_str,
     617                 :                                                           &in_str_len) == FAILURE) {
     618               0 :                 return;
     619                 :         }
     620                 : 
     621               0 :         out_str = estrndup(in_str, in_str_len);
     622               0 :         out_str_len = php_raw_url_decode(out_str, in_str_len);
     623                 : 
     624               0 :     RETURN_STRINGL(out_str, out_str_len, 0);
     625                 : }
     626                 : /* }}} */
     627                 : 
     628                 : /* {{{ php_raw_url_decode
     629                 :  */
     630                 : PHPAPI int php_raw_url_decode(char *str, int len)
     631               0 : {
     632               0 :         char *dest = str;
     633               0 :         char *data = str;
     634                 : 
     635               0 :         while (len--) {
     636               0 :                 if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) 
     637                 :                         && isxdigit((int) *(data + 2))) {
     638                 : #ifndef CHARSET_EBCDIC
     639               0 :                         *dest = (char) php_htoi(data + 1);
     640                 : #else
     641                 :                         *dest = os_toebcdic[(char) php_htoi(data + 1)];
     642                 : #endif
     643               0 :                         data += 2;
     644               0 :                         len -= 2;
     645                 :                 } else {
     646               0 :                         *dest = *data;
     647                 :                 }
     648               0 :                 data++;
     649               0 :                 dest++;
     650                 :         }
     651               0 :         *dest = '\0';
     652               0 :         return dest - str;
     653                 : }
     654                 : /* }}} */
     655                 : 
     656                 : /* {{{ proto array get_headers(string url[, int format])
     657                 :    fetches all the headers sent by the server in response to a HTTP request */
     658                 : PHP_FUNCTION(get_headers)
     659               0 : {
     660                 :         char *url;
     661                 :         int url_len;
     662                 :         php_stream_context *context;
     663                 :         php_stream *stream;
     664               0 :         zval **prev_val, **hdr = NULL, **h;
     665                 :         HashPosition pos;
     666                 :         HashTable *hashT;
     667               0 :         long format = 0;
     668                 :                 
     669               0 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &url, &url_len, &format) == FAILURE) {
     670               0 :                 return;
     671                 :         }
     672               0 :         context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc());
     673                 : 
     674               0 :         if (!(stream = php_stream_open_wrapper_ex(url, "r", REPORT_ERRORS | STREAM_USE_URL | STREAM_ONLY_GET_HEADERS, NULL, context))) {
     675               0 :                 RETURN_FALSE;
     676                 :         }
     677                 : 
     678               0 :         if (!stream->wrapperdata || Z_TYPE_P(stream->wrapperdata) != IS_ARRAY) {
     679               0 :                 php_stream_close(stream);
     680               0 :                 RETURN_FALSE;
     681                 :         }
     682                 : 
     683               0 :         array_init(return_value);
     684                 : 
     685                 :         /* check for curl-wrappers that provide headers via a special "headers" element */
     686               0 :         if (zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h) != FAILURE && Z_TYPE_PP(h) == IS_ARRAY) {
     687                 :                 /* curl-wrappers don't load data until the 1st read */ 
     688               0 :                 if (!Z_ARRVAL_PP(h)->nNumOfElements) {
     689               0 :                         php_stream_getc(stream);
     690                 :                 }
     691               0 :                 zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h);
     692               0 :                 hashT = Z_ARRVAL_PP(h); 
     693                 :         } else {
     694               0 :                 hashT = HASH_OF(stream->wrapperdata);
     695                 :         }
     696                 : 
     697               0 :         zend_hash_internal_pointer_reset_ex(hashT, &pos);
     698               0 :         while (zend_hash_get_current_data_ex(hashT, (void**)&hdr, &pos) != FAILURE) {
     699               0 :                 if (!hdr || Z_TYPE_PP(hdr) != IS_STRING) {
     700               0 :                         zend_hash_move_forward_ex(hashT, &pos);
     701               0 :                         continue;
     702                 :                 }
     703               0 :                 if (!format) {
     704               0 : no_name_header:
     705               0 :                         add_next_index_stringl(return_value, Z_STRVAL_PP(hdr), Z_STRLEN_PP(hdr), 1);
     706                 :                 } else {
     707                 :                         char c;
     708                 :                         char *s, *p;
     709                 : 
     710               0 :                         if ((p = strchr(Z_STRVAL_PP(hdr), ':'))) {
     711               0 :                                 c = *p;
     712               0 :                                 *p = '\0';
     713               0 :                                 s = p + 1;
     714               0 :                                 while (isspace((int)*(unsigned char *)s)) {
     715               0 :                                         s++;
     716                 :                                 }
     717                 : 
     718               0 :                                 if (zend_hash_find(HASH_OF(return_value), Z_STRVAL_PP(hdr), (p - Z_STRVAL_PP(hdr) + 1), (void **) &prev_val) == FAILURE) {
     719               0 :                                         add_assoc_stringl_ex(return_value, Z_STRVAL_PP(hdr), (p - Z_STRVAL_PP(hdr) + 1), s, (Z_STRLEN_PP(hdr) - (s - Z_STRVAL_PP(hdr))), 1);
     720                 :                                 } else { /* some headers may occur more then once, therefor we need to remake the string into an array */
     721               0 :                                         convert_to_array(*prev_val);
     722               0 :                                         add_next_index_stringl(*prev_val, s, (Z_STRLEN_PP(hdr) - (s - Z_STRVAL_PP(hdr))), 1);
     723                 :                                 }
     724                 : 
     725               0 :                                 *p = c;
     726                 :                         } else {
     727               0 :                                 goto no_name_header;
     728                 :                         }
     729                 :                 }
     730               0 :                 zend_hash_move_forward_ex(hashT, &pos);
     731                 :         }
     732                 : 
     733               0 :         php_stream_close(stream);
     734                 : }
     735                 : /* }}} */
     736                 : 
     737                 : /*
     738                 :  * Local variables:
     739                 :  * tab-width: 4
     740                 :  * c-basic-offset: 4
     741                 :  * End:
     742                 :  * vim600: sw=4 ts=4 fdm=marker
     743                 :  * vim<600: sw=4 ts=4
     744                 :  */

Generated by: LTP GCOV extension version 1.5