PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LTP GCOV extension - code coverage report
Current view: directory - standard - url.c
Test: PHP Code Coverage
Date: 2009-11-23 Instrumented lines: 382
Code covered: 85.6 % Executed lines: 327
Legend: not executed executed

       1                 : /*
       2                 :    +----------------------------------------------------------------------+
       3                 :    | PHP Version 6                                                        |
       4                 :    +----------------------------------------------------------------------+
       5                 :    | Copyright (c) 1997-2009 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 290199 2009-11-04 13:44:10Z iliaa $ */
      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                 : 
      41                 : /*
      42                 :  * These macros are similar to ZVAL_U_STRING*() but they select between
      43                 :  * Unicode/binary based on explicitly specified type, rather than the
      44                 :  * UG(unicode) global. They may be useful for other functions, but implementing
      45                 :  * them would probably require updating all of the corresponding add_*_assoc_*()
      46                 :  * macros, so let's keep them here for now and revisit the issue if someone else
      47                 :  * needs them in the future.
      48                 :  */
      49                 : #define ZVAL_UT_STRING(conv, type, z, s, flags) { \
      50                 :                 if (type == IS_UNICODE) { \
      51                 :                         UErrorCode status = U_ZERO_ERROR; \
      52                 :                         char *__s = (s); \
      53                 :                         int __s_len = strlen(__s); \
      54                 :                         UChar *u_str; \
      55                 :                         int u_len; \
      56                 :                         zend_string_to_unicode_ex(conv, &u_str, &u_len, __s, __s_len, &status); \
      57                 :                         if ((flags) & ZSTR_AUTOFREE) { \
      58                 :                                 efree(__s); \
      59                 :                         } \
      60                 :                         ZVAL_UNICODEL(z, u_str, u_len, 0); \
      61                 :                 } else { \
      62                 :                         char *__s=(s);                                  \
      63                 :                         Z_STRLEN_P(z) = strlen(__s);    \
      64                 :                         Z_STRVAL_P(z) = (((flags) & ZSTR_DUPLICATE) ? estrndup(__s, Z_STRLEN_P(z)) : __s);  \
      65                 :                         Z_TYPE_P(z) = IS_STRING;        \
      66                 :                 } \
      67                 :         }
      68                 : 
      69                 : #define ZVAL_UT_STRINGL(conv, type, z, s, l, flags) { \
      70                 :                 if (type == IS_UNICODE) { \
      71                 :                         UErrorCode status = U_ZERO_ERROR; \
      72                 :                         char *__s = (s); \
      73                 :                         int __s_len = (l); \
      74                 :                         UChar *u_str; \
      75                 :                         int u_len; \
      76                 :                         zend_string_to_unicode_ex(conv, &u_str, &u_len, __s, __s_len, &status); \
      77                 :                         if ((flags) & ZSTR_AUTOFREE) { \
      78                 :                                 efree(__s); \
      79                 :                         } \
      80                 :                         ZVAL_UNICODEL(z, u_str, u_len, 0); \
      81                 :                 } else { \
      82                 :                         char *__s=(s); int __l=l;       \
      83                 :                         Z_STRLEN_P(z) = __l;        \
      84                 :                         Z_STRVAL_P(z) = (((flags) & ZSTR_DUPLICATE) ? estrndup(__s, __l) : __s);    \
      85                 :                         Z_TYPE_P(z) = IS_STRING;    \
      86                 :                 }\
      87                 :         }
      88                 : 
      89                 : #define RETVAL_UT_STRING(conv, type, s, flags)          ZVAL_UT_STRING(conv, type, return_value, s, flags)
      90                 : #define RETVAL_UT_STRINGL(conv, type, s, l, flags)      ZVAL_UT_STRINGL(conv, type, return_value, s, l, flags)
      91                 : #define RETURN_UT_STRING(conv, type, t, flags)          { RETVAL_UT_STRING(conv, type, t, flags); return; }
      92                 : #define RETURN_UT_STRINGL(conv, type, t, l, flags)      { RETVAL_UT_STRINGL(conv, type, t, l, flags); return; }
      93                 : 
      94                 : /* {{{ free_url
      95                 :  */
      96                 : PHPAPI void php_url_free(php_url *theurl)
      97            2624 : {
      98            2624 :         if (theurl->scheme)
      99            2266 :                 efree(theurl->scheme);
     100            2624 :         if (theurl->user)
     101             122 :                 efree(theurl->user);
     102            2624 :         if (theurl->pass)
     103              73 :                 efree(theurl->pass);
     104            2624 :         if (theurl->host)
     105            2237 :                 efree(theurl->host);
     106            2624 :         if (theurl->path)
     107            2389 :                 efree(theurl->path);
     108            2624 :         if (theurl->query)
     109             235 :                 efree(theurl->query);
     110            2624 :         if (theurl->fragment)
     111             123 :                 efree(theurl->fragment);
     112            2624 :         efree(theurl);
     113            2624 : }
     114                 : /* }}} */
     115                 : 
     116                 : /* {{{ php_replace_controlchars
     117                 :  */
     118                 : PHPAPI char *php_replace_controlchars_ex(char *str, int len)
     119            3343 : {
     120            3343 :         unsigned char *s = (unsigned char *)str;
     121            3343 :         unsigned char *e = (unsigned char *)str + len;
     122                 :         
     123            3343 :         if (!str) {
     124               0 :                 return (NULL);
     125                 :         }
     126                 :         
     127         1058769 :         while (s < e) {
     128                 :             
     129         1052083 :                 if (iscntrl(*s)) {
     130               0 :                         *s='_';
     131                 :                 }       
     132         1052083 :                 s++;
     133                 :         }
     134                 :         
     135            3343 :         return (str);
     136                 : } 
     137                 : /* }}} */
     138                 : 
     139                 : PHPAPI char *php_replace_controlchars(char *str) /* {{{ */
     140               0 : {
     141               0 :         return php_replace_controlchars_ex(str, strlen(str));
     142                 : } 
     143                 : /* }}} */
     144                 : 
     145                 : PHPAPI php_url *php_url_parse(char const *str) /* {{{ */
     146             320 : {
     147             320 :         return php_url_parse_ex(str, strlen(str));
     148                 : }
     149                 : /* }}} */
     150                 : 
     151                 : /* {{{ php_url_parse
     152                 :  */
     153                 : PHPAPI php_url *php_url_parse_ex(char const *str, int length)
     154            1489 : {
     155                 :         char port_buf[6];
     156            1489 :         php_url *ret = ecalloc(1, sizeof(php_url));
     157                 :         char const *s, *e, *p, *pp, *ue;
     158                 :                 
     159            1489 :         s = str;
     160            1489 :         ue = s + length;
     161                 : 
     162                 :         /* parse scheme */
     163            2459 :         if ((e = memchr(s, ':', length)) && (e - s)) {
     164                 :                 /* validate scheme */
     165            1269 :                 p = s;
     166         1032234 :                 while (p < e) {
     167                 :                         /* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */
     168         1029704 :                         if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') {
     169               8 :                                 if (e + 1 < ue) {
     170               8 :                                         goto parse_port;
     171                 :                                 } else {
     172               0 :                                         goto just_path;
     173                 :                                 }
     174                 :                         }
     175         1029696 :                         p++;
     176                 :                 }
     177                 :         
     178            1261 :                 if (*(e + 1) == '\0') { /* only scheme is available */
     179              11 :                         ret->scheme = estrndup(s, (e - s));
     180              11 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     181              11 :                         goto end;
     182                 :                 }
     183                 : 
     184                 :                 /* 
     185                 :                  * certain schemas like mailto: and zlib: may not have any / after them
     186                 :                  * this check ensures we support those.
     187                 :                  */
     188            1250 :                 if (*(e+1) != '/') {
     189                 :                         /* check if the data we get is a port this allows us to 
     190                 :                          * correctly parse things like a.com:80
     191                 :                          */
     192             184 :                         p = e + 1;
     193             961 :                         while (isdigit(*p)) {
     194             593 :                                 p++;
     195                 :                         }
     196                 :                         
     197             184 :                         if ((*p == '\0' || *p == '/') && (p - e) < 7) {
     198             130 :                                 goto parse_port;
     199                 :                         }
     200                 :                         
     201              54 :                         ret->scheme = estrndup(s, (e-s));
     202              54 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     203                 :                         
     204              54 :                         length -= ++e - s;
     205              54 :                         s = e;
     206              54 :                         goto just_path;
     207                 :                 } else {
     208            1066 :                         ret->scheme = estrndup(s, (e-s));
     209            1066 :                         php_replace_controlchars_ex(ret->scheme, (e - s));
     210                 :                 
     211            1066 :                         if (*(e+2) == '/') {
     212            1035 :                                 s = e + 3;
     213            1035 :                                 if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
     214              76 :                                         if (*(e + 3) == '/') {
     215                 :                                                 /* support windows drive letters as in:
     216                 :                                                    file:///c:/somedir/file.txt
     217                 :                                                 */
     218              65 :                                                 if (*(e + 5) == ':') {
     219              27 :                                                         s = e + 4;
     220                 :                                                 }
     221              65 :                                                 goto nohost;
     222                 :                                         }
     223                 :                                 }
     224                 :                         } else {
     225              31 :                                 if (!strncasecmp("file", ret->scheme, sizeof("file"))) {
     226              10 :                                         s = e + 1;
     227              10 :                                         goto nohost;
     228                 :                                 } else {
     229              21 :                                         length -= ++e - s;
     230              21 :                                         s = e;
     231              21 :                                         goto just_path;
     232                 :                                 }       
     233                 :                         }
     234                 :                 }       
     235             220 :         } else if (e) { /* no scheme, look for port */
     236             138 :                 parse_port:
     237             138 :                 p = e + 1;
     238             138 :                 pp = p;
     239                 :                 
     240             807 :                 while (pp-p < 6 && isdigit(*pp)) {
     241             531 :                         pp++;
     242                 :                 }
     243                 :                 
     244             138 :                 if (pp-p < 6 && (*pp == '/' || *pp == '\0')) {
     245             132 :                         memcpy(port_buf, p, (pp-p));
     246             132 :                         port_buf[pp-p] = '\0';
     247             132 :                         ret->port = atoi(port_buf);
     248                 :                 } else {
     249                 :                         goto just_path;
     250                 :                 }
     251                 :         } else {
     252             301 :                 just_path:
     253             301 :                 ue = s + length;
     254             301 :                 goto nohost;
     255                 :         }
     256                 :         
     257            1102 :         e = ue;
     258                 :         
     259            1102 :         if (!(p = memchr(s, '/', (ue - s)))) {
     260                 :                 char *query, *fragment;
     261                 : 
     262             558 :                 query = memchr(s, '?', (ue - s));
     263             558 :                 fragment = memchr(s, '#', (ue - s));
     264                 : 
     265             558 :                 if (query && fragment) {
     266               0 :                         if (query > fragment) {
     267               0 :                                 p = e = fragment;
     268                 :                         } else {
     269               0 :                                 p = e = query;
     270                 :                         }
     271             558 :                 } else if (query) {
     272              55 :                         p = e = query;
     273             503 :                 } else if (fragment) {
     274              10 :                         p = e = fragment;
     275                 :                 }
     276                 :         } else {
     277             544 :                 e = p;
     278                 :         }       
     279                 :                 
     280                 :         /* check for login and password */
     281            1102 :         if ((p = zend_memrchr(s, '@', (e-s)))) {
     282             168 :                 if ((pp = memchr(s, ':', (p-s)))) {
     283              92 :                         if ((pp-s) > 0) {
     284              82 :                                 ret->user = estrndup(s, (pp-s));
     285              82 :                                 php_replace_controlchars_ex(ret->user, (pp - s));
     286                 :                         }       
     287                 :                 
     288              92 :                         pp++;
     289              92 :                         if (p-pp > 0) {
     290              82 :                                 ret->pass = estrndup(pp, (p-pp));
     291              82 :                                 php_replace_controlchars_ex(ret->pass, (p-pp));
     292                 :                         }       
     293                 :                 } else {
     294              76 :                         ret->user = estrndup(s, (p-s));
     295              76 :                         php_replace_controlchars_ex(ret->user, (p-s));
     296                 :                 }
     297                 :                 
     298             168 :                 s = p + 1;
     299                 :         }
     300                 : 
     301                 :         /* check for port */
     302            1111 :         if (*s == '[' && *(e-1) == ']') {
     303                 :                 /* Short circuit portscan, 
     304                 :                    we're dealing with an 
     305                 :                    IPv6 embedded address */
     306               9 :                 p = s;
     307                 :         } else {
     308                 :                 /* memrchr is a GNU specific extension
     309                 :                    Emulate for wide compatability */
     310            1093 :                 for(p = e; *p != ':' && p >= s; p--);
     311                 :         }
     312                 : 
     313            1649 :         if (p >= s && *p == ':') {
     314             565 :                 if (!ret->port) {
     315             433 :                         p++;
     316             433 :                         if (e-p > 5) { /* port cannot be longer then 5 characters */
     317              18 :                                 STR_FREE(ret->scheme);
     318              18 :                                 STR_FREE(ret->user);
     319              18 :                                 STR_FREE(ret->pass);
     320              18 :                                 efree(ret);
     321              18 :                                 return NULL;
     322             415 :                         } else if (e - p > 0) {
     323             333 :                                 memcpy(port_buf, p, (e-p));
     324             333 :                                 port_buf[e-p] = '\0';
     325             333 :                                 ret->port = atoi(port_buf);
     326                 :                         }
     327             415 :                         p--;
     328                 :                 }       
     329                 :         } else {
     330             537 :                 p = e;
     331                 :         }
     332                 :         
     333                 :         /* check if we have a valid host, if we don't reject the string as url */
     334            1084 :         if ((p-s) < 1) {
     335             353 :                 STR_FREE(ret->scheme);
     336             353 :                 STR_FREE(ret->user);
     337             353 :                 STR_FREE(ret->pass);
     338             353 :                 efree(ret);
     339             353 :                 return NULL;
     340                 :         }
     341                 : 
     342             731 :         ret->host = estrndup(s, (p-s));
     343             731 :         php_replace_controlchars_ex(ret->host, (p - s));
     344                 :         
     345             731 :         if (e == ue) {
     346             185 :                 return ret;
     347                 :         }
     348                 :         
     349             546 :         s = e;
     350                 :         
     351             922 :         nohost:
     352                 :         
     353             922 :         if ((p = memchr(s, '?', (ue - s)))) {
     354             322 :                 pp = strchr(s, '#');
     355                 : 
     356             322 :                 if (pp && pp < p) {
     357               0 :                         p = pp;
     358               0 :                         goto label_parse;
     359                 :                 }
     360                 :         
     361             322 :                 if (p - s) {
     362             293 :                         ret->path = estrndup(s, (p-s));
     363             293 :                         php_replace_controlchars_ex(ret->path, (p - s));
     364                 :                 }       
     365                 :         
     366             322 :                 if (pp) {
     367             113 :                         if (pp - ++p) { 
     368             103 :                                 ret->query = estrndup(p, (pp-p));
     369             103 :                                 php_replace_controlchars_ex(ret->query, (pp - p));
     370                 :                         }
     371             113 :                         p = pp;
     372             113 :                         goto label_parse;
     373             209 :                 } else if (++p - ue) {
     374             132 :                         ret->query = estrndup(p, (ue-p));
     375             132 :                         php_replace_controlchars_ex(ret->query, (ue - p));
     376                 :                 }
     377             600 :         } else if ((p = memchr(s, '#', (ue - s)))) {
     378              20 :                 if (p - s) {
     379              10 :                         ret->path = estrndup(s, (p-s));
     380              10 :                         php_replace_controlchars_ex(ret->path, (p - s));
     381                 :                 }       
     382                 :                 
     383             133 :                 label_parse:
     384             133 :                 p++;
     385                 :                 
     386             133 :                 if (ue - p) {
     387             123 :                         ret->fragment = estrndup(p, (ue-p));
     388             123 :                         php_replace_controlchars_ex(ret->fragment, (ue - p));
     389                 :                 }       
     390                 :         } else {
     391             580 :                 ret->path = estrndup(s, (ue-s));
     392             580 :                 php_replace_controlchars_ex(ret->path, (ue - s));
     393                 :         }
     394             933 : end:
     395             933 :         return ret;
     396                 : }
     397                 : /* }}} */
     398                 : 
     399                 : #define add_ascii_assoc_u_ascii_string(arg, key, str, type, duplicate) do { \
     400                 :                 zval *___tmp; \
     401                 :                 MAKE_STD_ZVAL(___tmp); \
     402                 :                 ZVAL_UT_STRING(UG(ascii_conv), type, ___tmp, str, duplicate); \
     403                 :                 add_ascii_assoc_zval(arg, key, ___tmp); \
     404                 :     } while (0)
     405                 : 
     406                 : 
     407                 : /* {{{ proto mixed parse_url(string url, [int url_component]) U
     408                 :    Parse a URL and return its components */
     409                 : PHP_FUNCTION(parse_url)
     410            1043 : {
     411                 :         zstr str;
     412                 :         int str_len;
     413                 :         zend_uchar type;
     414                 :         php_url *resource;
     415            1043 :         long key = -1;
     416                 : 
     417            1043 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t|l", &str, &str_len, &type, &key) == FAILURE) {
     418              18 :                 return;
     419                 :         }
     420                 : 
     421            1025 :         if (type == IS_UNICODE) {
     422                 :                 char *temp;
     423                 : 
     424            1011 :                 if ((temp = zend_unicode_to_ascii(str.u, str_len TSRMLS_CC)) == NULL) {
     425               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert URL parameter to ASCII");
     426               0 :                         return;
     427                 :                 }
     428            1011 :                 str.s = temp;
     429                 :         }
     430                 : 
     431            1025 :         resource = php_url_parse_ex(str.s, str_len);
     432            1025 :         if (resource == NULL) {
     433             117 :                 php_error_docref1(NULL TSRMLS_CC, str.s, E_WARNING, "Unable to parse URL");
     434             117 :                 if (type == IS_UNICODE) {
     435             117 :                         efree(str.s);
     436                 :                 }
     437             117 :                 RETURN_FALSE;
     438                 :         }
     439                 : 
     440             908 :         if (key > -1) {
     441             716 :                 switch (key) {
     442                 :                         case PHP_URL_SCHEME:
     443              96 :                                 if (resource->scheme != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->scheme, 1);
     444              96 :                                 break;
     445                 :                         case PHP_URL_HOST:
     446              90 :                                 if (resource->host != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->host, 1);
     447              90 :                                 break;
     448                 :                         case PHP_URL_PORT:
     449              88 :                                 if (resource->port != 0) RETVAL_LONG(resource->port);
     450              88 :                                 break;
     451                 :                         case PHP_URL_USER:
     452              88 :                                 if (resource->user != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->user, 1);
     453              88 :                                 break;
     454                 :                         case PHP_URL_PASS:
     455              88 :                                 if (resource->pass != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->pass, 1);
     456              88 :                                 break;
     457                 :                         case PHP_URL_PATH:
     458              88 :                                 if (resource->path != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->path, 1);
     459              88 :                                 break;
     460                 :                         case PHP_URL_QUERY:
     461              88 :                                 if (resource->query != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->query, 1);
     462              88 :                                 break;
     463                 :                         case PHP_URL_FRAGMENT:
     464              88 :                                 if (resource->fragment != NULL) RETVAL_UT_STRING(UG(ascii_conv), type, resource->fragment, 1);
     465              88 :                                 break;
     466                 :                         default:
     467               2 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid URL component identifier %ld", key);
     468               2 :                                 RETVAL_FALSE;
     469                 :                 }
     470             716 :                 goto done;
     471                 :         }
     472                 : 
     473                 :         /* allocate an array for return */
     474             192 :         array_init(return_value);
     475                 : 
     476                 :     /* add the various elements to the array */
     477             192 :         if (resource->scheme != NULL)
     478             143 :                 add_ascii_assoc_u_ascii_string(return_value, "scheme", resource->scheme, type, 1);
     479             192 :         if (resource->host != NULL)
     480             127 :                 add_ascii_assoc_u_ascii_string(return_value, "host", resource->host, type, 1);
     481             192 :         if (resource->port != 0)
     482              64 :                 add_ascii_assoc_long(return_value, "port", resource->port);
     483             192 :         if (resource->user != NULL)
     484              22 :                 add_ascii_assoc_u_ascii_string(return_value, "user", resource->user, type, 1);
     485             192 :         if (resource->pass != NULL)
     486              13 :                 add_ascii_assoc_u_ascii_string(return_value, "pass", resource->pass, type, 1);
     487             192 :         if (resource->path != NULL)
     488             165 :                 add_ascii_assoc_u_ascii_string(return_value, "path", resource->path, type, 1);
     489             192 :         if (resource->query != NULL)
     490              45 :                 add_ascii_assoc_u_ascii_string(return_value, "query", resource->query, type, 1);
     491             192 :         if (resource->fragment != NULL)
     492              23 :                 add_ascii_assoc_u_ascii_string(return_value, "fragment", resource->fragment, type, 1);
     493             908 : done:   
     494             908 :         php_url_free(resource);
     495             908 :         if (type == IS_UNICODE) {
     496             894 :                 efree(str.s);
     497                 :         }
     498                 : }
     499                 : /* }}} */
     500                 : 
     501                 : /* {{{ php_htoi
     502                 :  */
     503                 : static int php_htoi(char *s)
     504             118 : {
     505                 :         int value;
     506                 :         int c;
     507                 : 
     508             118 :         c = ((unsigned char *)s)[0];
     509             118 :         if (isupper(c))
     510               1 :                 c = tolower(c);
     511             118 :         value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
     512                 : 
     513             118 :         c = ((unsigned char *)s)[1];
     514             118 :         if (isupper(c))
     515              47 :                 c = tolower(c);
     516             118 :         value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
     517                 : 
     518             118 :         return (value);
     519                 : }
     520                 : /* }}} */
     521                 : 
     522                 : /* rfc1738:
     523                 : 
     524                 :    ...The characters ";",
     525                 :    "/", "?", ":", "@", "=" and "&" are the characters which may be
     526                 :    reserved for special meaning within a scheme...
     527                 : 
     528                 :    ...Thus, only alphanumerics, the special characters "$-_.+!*'(),", and
     529                 :    reserved characters used for their reserved purposes may be used
     530                 :    unencoded within a URL...
     531                 : 
     532                 :    For added safety, we only leave -_. unencoded.
     533                 :  */
     534                 : 
     535                 : static unsigned char hexchars[] = "0123456789ABCDEF";
     536                 : 
     537                 : /* {{{ php_url_encode
     538                 :  */
     539                 : PHPAPI char *php_url_encode(char const *s, int len, int *new_length)
     540             529 : {
     541                 :         register unsigned char c;
     542                 :         unsigned char *to, *start;
     543                 :         unsigned char const *from, *end;
     544                 :         
     545             529 :         from = (unsigned char*)s;
     546             529 :         end = from + len;
     547             529 :         start = to = (unsigned char *) safe_emalloc(3, len, 1);
     548                 : 
     549            9905 :         while (from < end) {
     550            8847 :                 c = *from++;
     551                 : 
     552            8847 :                 if (c == ' ') {
     553              10 :                         *to++ = '+';
     554                 : #ifndef CHARSET_EBCDIC
     555            8962 :                 } else if ((c < '0' && c != '-' && c != '.') ||
     556                 :                                    (c < 'A' && c > '9') ||
     557                 :                                    (c > 'Z' && c < 'a' && c != '_') ||
     558                 :                                    (c > 'z')) {
     559             125 :                         to[0] = '%';
     560             125 :                         to[1] = hexchars[c >> 4];
     561             125 :                         to[2] = hexchars[c & 15];
     562             125 :                         to += 3;
     563                 : #else /*CHARSET_EBCDIC*/
     564                 :                 } else if (!isalnum(c) && strchr("_-.", c) == NULL) {
     565                 :                         /* Allow only alphanumeric chars and '_', '-', '.'; escape the rest */
     566                 :                         to[0] = '%';
     567                 :                         to[1] = hexchars[os_toascii[c] >> 4];
     568                 :                         to[2] = hexchars[os_toascii[c] & 15];
     569                 :                         to += 3;
     570                 : #endif /*CHARSET_EBCDIC*/
     571                 :                 } else {
     572            8712 :                         *to++ = c;
     573                 :                 }
     574                 :         }
     575             529 :         *to = 0;
     576             529 :         if (new_length) {
     577             121 :                 *new_length = to - start;
     578                 :         }
     579             529 :         return (char *) start;
     580                 : }
     581                 : /* }}} */
     582                 : 
     583                 : /* {{{ proto string urlencode(binary str) U
     584                 :    URL-encodes string */
     585                 : PHP_FUNCTION(urlencode)
     586              91 : {
     587                 :         zstr in_str;
     588                 :         char *out_str;
     589                 :         int in_str_len, out_str_len;
     590                 :         zend_uchar in_str_type;
     591                 : 
     592              91 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &in_str,
     593                 :                                                           &in_str_len, &in_str_type) == FAILURE) {
     594               8 :                 return;
     595                 :         }
     596                 : 
     597              83 :         if (in_str_type == IS_UNICODE) {
     598              21 :                 char *utf8_str = NULL;
     599                 :                 int utf8_str_len;
     600              21 :                 UErrorCode status = U_ZERO_ERROR;
     601                 : 
     602              21 :                 zend_unicode_to_string_ex(UG(utf8_conv), &utf8_str, &utf8_str_len, in_str.u, in_str_len, &status);
     603              21 :                 if (U_FAILURE(status)) {
     604               0 :                         if (utf8_str) {
     605               0 :                                 efree(utf8_str);
     606                 :                         }
     607               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert argument to UTF-8");
     608               0 :                         RETURN_FALSE;
     609                 :                 }
     610                 : 
     611              21 :                 out_str = php_url_encode(utf8_str, utf8_str_len, &out_str_len);
     612              21 :                 efree(utf8_str);
     613              21 :                 php_error_docref(NULL TSRMLS_CC, E_STRICT, "expecting binary parameter, received Unicode parameter was converted to UTF-8");
     614                 :         } else {
     615              62 :                 out_str = php_url_encode(in_str.s, in_str_len, &out_str_len);
     616                 :         }
     617              83 :         RETURN_STRINGL(out_str, out_str_len, 0);
     618                 : }
     619                 : /* }}} */
     620                 : 
     621                 : /* {{{ proto binary urldecode(binary str) U
     622                 :    Decodes URL-encoded string */
     623                 : PHP_FUNCTION(urldecode)
     624              38 : {
     625                 :         char *in_str, *out_str;
     626                 :         int in_str_len, out_str_len;
     627                 : 
     628              38 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &in_str,
     629                 :                                                           &in_str_len) == FAILURE) {
     630              14 :                 return;
     631                 :         }
     632                 : 
     633              24 :         out_str = estrndup(in_str, in_str_len);
     634              24 :         out_str_len = php_url_decode(out_str, in_str_len);
     635                 : 
     636              24 :     RETURN_STRINGL(out_str, out_str_len, 0);
     637                 : }
     638                 : /* }}} */
     639                 : 
     640                 : /* {{{ php_url_decode
     641                 :  */
     642                 : PHPAPI int php_url_decode(char *str, int len)
     643             514 : {
     644             514 :         char *dest = str;
     645             514 :         char *data = str;
     646                 : 
     647            3966 :         while (len--) {
     648            2938 :                 if (*data == '+') {
     649              26 :                         *dest = ' ';
     650                 :                 }
     651            3000 :                 else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) 
     652                 :                                  && isxdigit((int) *(data + 2))) {
     653                 : #ifndef CHARSET_EBCDIC
     654              88 :                         *dest = (char) php_htoi(data + 1);
     655                 : #else
     656                 :                         *dest = os_toebcdic[(char) php_htoi(data + 1)];
     657                 : #endif
     658              88 :                         data += 2;
     659              88 :                         len -= 2;
     660                 :                 } else {
     661            2824 :                         *dest = *data;
     662                 :                 }
     663            2938 :                 data++;
     664            2938 :                 dest++;
     665                 :         }
     666             514 :         *dest = '\0';
     667             514 :         return dest - str;
     668                 : }
     669                 : /* }}} */
     670                 : 
     671                 : /* {{{ php_raw_url_encode
     672                 :  */
     673                 : PHPAPI char *php_raw_url_encode(char const *s, int len, int *new_length)
     674              21 : {
     675                 :         register int x, y;
     676                 :         unsigned char *str;
     677                 : 
     678              21 :         str = (unsigned char *) safe_emalloc(3, len, 1);
     679             210 :         for (x = 0, y = 0; len--; x++, y++) {
     680             189 :                 str[y] = (unsigned char) s[x];
     681                 : #ifndef CHARSET_EBCDIC
     682             189 :                 if ((str[y] < '0' && str[y] != '-' && str[y] != '.') ||
     683                 :                         (str[y] < 'A' && str[y] > '9') ||
     684                 :                         (str[y] > 'Z' && str[y] < 'a' && str[y] != '_') ||
     685                 :                         (str[y] > 'z' && str[y] != '~')) {
     686              36 :                         str[y++] = '%';
     687              36 :                         str[y++] = hexchars[(unsigned char) s[x] >> 4];
     688              36 :                         str[y] = hexchars[(unsigned char) s[x] & 15];
     689                 : #else /*CHARSET_EBCDIC*/
     690                 :                 if (!isalnum(str[y]) && strchr("_-.", str[y]) != NULL) {
     691                 :                         str[y++] = '%';
     692                 :                         str[y++] = hexchars[os_toascii[(unsigned char) s[x]] >> 4];
     693                 :                         str[y] = hexchars[os_toascii[(unsigned char) s[x]] & 15];
     694                 : #endif /*CHARSET_EBCDIC*/
     695                 :                 }
     696                 :         }
     697              21 :         str[y] = '\0';
     698              21 :         if (new_length) {
     699              21 :                 *new_length = y;
     700                 :         }
     701              21 :         return ((char *) str);
     702                 : }
     703                 : /* }}} */
     704                 : 
     705                 : /* {{{ proto binary rawurlencode(binary str) U
     706                 :    URL-encodes string */
     707                 : PHP_FUNCTION(rawurlencode)
     708              29 : {
     709                 :         zstr in_str;
     710                 :         char *out_str;
     711                 :         int in_str_len, out_str_len;
     712                 :         zend_uchar in_str_type;
     713                 : 
     714              29 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "t", &in_str,
     715                 :                                                           &in_str_len, &in_str_type) == FAILURE) {
     716               8 :                 return;
     717                 :         }
     718                 : 
     719              21 :         if (in_str_type == IS_UNICODE) {
     720              19 :                 char *utf8_str = NULL;
     721                 :                 int utf8_str_len;
     722              19 :                 UErrorCode status = U_ZERO_ERROR;
     723                 : 
     724              19 :                 zend_unicode_to_string_ex(UG(utf8_conv), &utf8_str, &utf8_str_len, in_str.u, in_str_len, &status);
     725              19 :                 if (U_FAILURE(status)) {
     726               0 :                         if (utf8_str) {
     727               0 :                                 efree(utf8_str);
     728                 :                         }
     729               0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "could not convert argument to UTF-8");
     730               0 :                         RETURN_FALSE;
     731                 :                 }
     732                 : 
     733              19 :                 out_str = php_raw_url_encode(utf8_str, utf8_str_len, &out_str_len);
     734              19 :                 efree(utf8_str);
     735              19 :                 php_error_docref(NULL TSRMLS_CC, E_STRICT, "expecting binary parameter, received Unicode parameter was converted to UTF-8");
     736                 :         } else {
     737               2 :                 out_str = php_raw_url_encode(in_str.s, in_str_len, &out_str_len);
     738                 :         }
     739              21 :         RETURN_STRINGL(out_str, out_str_len, 0);
     740                 : }
     741                 : /* }}} */
     742                 : 
     743                 : /* {{{ proto binary rawurldecode(binary str) U
     744                 :    Decodes URL-encodes string */
     745                 : PHP_FUNCTION(rawurldecode)
     746              28 : {
     747                 :         char *in_str, *out_str;
     748                 :         int in_str_len, out_str_len;
     749                 : 
     750              28 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "S", &in_str,
     751                 :                                                           &in_str_len) == FAILURE) {
     752              10 :                 return;
     753                 :         }
     754                 : 
     755              18 :         out_str = estrndup(in_str, in_str_len);
     756              18 :         out_str_len = php_raw_url_decode(out_str, in_str_len);
     757                 : 
     758              18 :     RETURN_STRINGL(out_str, out_str_len, 0);
     759                 : }
     760                 : /* }}} */
     761                 : 
     762                 : /* {{{ php_raw_url_decode
     763                 :  */
     764                 : PHPAPI int php_raw_url_decode(char *str, int len)
     765              18 : {
     766              18 :         char *dest = str;
     767              18 :         char *data = str;
     768                 : 
     769             183 :         while (len--) {
     770             177 :                 if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) 
     771                 :                         && isxdigit((int) *(data + 2))) {
     772                 : #ifndef CHARSET_EBCDIC
     773              30 :                         *dest = (char) php_htoi(data + 1);
     774                 : #else
     775                 :                         *dest = os_toebcdic[(char) php_htoi(data + 1)];
     776                 : #endif
     777              30 :                         data += 2;
     778              30 :                         len -= 2;
     779                 :                 } else {
     780             117 :                         *dest = *data;
     781                 :                 }
     782             147 :                 data++;
     783             147 :                 dest++;
     784                 :         }
     785              18 :         *dest = '\0';
     786              18 :         return dest - str;
     787                 : }
     788                 : /* }}} */
     789                 : 
     790                 : /* {{{ proto array get_headers(string url[, int format]) U
     791                 :    fetches all the headers sent by the server in response to a HTTP request */
     792                 : PHP_FUNCTION(get_headers)
     793               5 : {
     794                 :         char *url;
     795                 :         int url_len;
     796                 :         php_stream_context *context;
     797                 :         php_stream *stream;
     798               5 :         zval **prev_val, **hdr = NULL, **h;
     799                 :         HashPosition pos;
     800                 :         HashTable *hashT;
     801               5 :         long format = 0;
     802                 :                 
     803               5 :         if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|l", &url, &url_len, &format) == FAILURE) {
     804               5 :                 return;
     805                 :         }
     806               0 :         context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc());
     807                 : 
     808               0 :         if (!(stream = php_stream_open_wrapper_ex(url, "r", REPORT_ERRORS | STREAM_USE_URL | STREAM_ONLY_GET_HEADERS, NULL, context))) {
     809               0 :                 RETURN_FALSE;
     810                 :         }
     811                 : 
     812               0 :         if (!stream->wrapperdata || Z_TYPE_P(stream->wrapperdata) != IS_ARRAY) {
     813               0 :                 php_stream_close(stream);
     814               0 :                 RETURN_FALSE;
     815                 :         }
     816                 : 
     817               0 :         array_init(return_value);
     818                 : 
     819                 :         /* check for curl-wrappers that provide headers via a special "headers" element */
     820               0 :         if (zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h) != FAILURE && Z_TYPE_PP(h) == IS_ARRAY) {
     821                 :                 /* curl-wrappers don't load data until the 1st read */ 
     822               0 :                 if (!Z_ARRVAL_PP(h)->nNumOfElements) {
     823               0 :                         php_stream_getc(stream);
     824                 :                 }
     825               0 :                 zend_hash_find(HASH_OF(stream->wrapperdata), "headers", sizeof("headers"), (void **)&h);
     826               0 :                 hashT = Z_ARRVAL_PP(h); 
     827                 :         } else {
     828               0 :                 hashT = HASH_OF(stream->wrapperdata);
     829                 :         }
     830                 : 
     831               0 :         zend_hash_internal_pointer_reset_ex(hashT, &pos);
     832               0 :         while (zend_hash_get_current_data_ex(hashT, (void**)&hdr, &pos) != FAILURE) {
     833               0 :                 if (!hdr || Z_TYPE_PP(hdr) != IS_STRING) {
     834               0 :                         zend_hash_move_forward_ex(hashT, &pos);
     835               0 :                         continue;
     836                 :                 }
     837                 : 
     838               0 :                 if (!format) {
     839               0 : no_name_header:
     840               0 :                         add_next_index_stringl(return_value, Z_STRVAL_PP(hdr), Z_STRLEN_PP(hdr), 1);
     841                 :                 } else {
     842                 :                         char c;
     843                 :                         char *s, *p;
     844                 : 
     845               0 :                         if ((p = strchr(Z_STRVAL_PP(hdr), ':'))) {
     846               0 :                                 c = *p;
     847               0 :                                 *p = '\0';
     848               0 :                                 s = p + 1;
     849               0 :                                 while (isspace((int)*(unsigned char *)s)) {
     850               0 :                                         s++;
     851                 :                                 }
     852                 : 
     853               0 :                                 if (zend_hash_find(HASH_OF(return_value), Z_STRVAL_PP(hdr), (p - Z_STRVAL_PP(hdr) + 1), (void **) &prev_val) == FAILURE) {
     854               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);
     855                 :                                 } else { /* some headers may occur more then once, therefor we need to remake the string into an array */
     856               0 :                                         convert_to_array(*prev_val);
     857               0 :                                         add_next_index_stringl(*prev_val, s, (Z_STRLEN_PP(hdr) - (s - Z_STRVAL_PP(hdr))), 1);
     858                 :                                 }
     859                 : 
     860               0 :                                 *p = c;
     861                 :                         } else {
     862               0 :                                 goto no_name_header;
     863                 :                         }
     864                 :                 }
     865               0 :                 zend_hash_move_forward_ex(hashT, &pos);
     866                 :         }
     867                 : 
     868               0 :         php_stream_close(stream);
     869                 : }
     870                 : /* }}} */
     871                 : 
     872                 : /*
     873                 :  * Local variables:
     874                 :  * tab-width: 4
     875                 :  * c-basic-offset: 4
     876                 :  * End:
     877                 :  * vim600: sw=4 ts=4 fdm=marker
     878                 :  * vim<600: sw=4 ts=4
     879                 :  */

Generated by: LTP GCOV extension version 1.5

Generated at Mon, 23 Nov 2009 17:39:40 +0000 (33 hours ago)

Copyright © 2005-2009 The PHP Group
All rights reserved.