New functions (patch included): str_uri_escape and unescape

From: Date: Sat, 17 Mar 2001 02:07:37 +0000
Subject: New functions (patch included): str_uri_escape and unescape
Groups: php.dev 
Request: Send a blank email to php-dev+get-49184@lists.php.net to get a copy of this message
Hello! I couldn't find any pointers on where to send contributions, I hope this is the right place. Anyway, I was stumped when I couldn't find an easy way to escape strings for use when printing URLs. So I added two new functions: str_uri_escape and the coresponding str_uri_unescape to the collection of string functions. Manual: string str_uri_escape (string str) Returns a string escaped according to RFC 2396 for use in URLs and URIs. All reserved characters are encoded as %xx where xx is the hexadecimal representation of of the coresponding octet. string str_uri_unescape (string str) Decodes an escaped string. See str_uri_escape. More info an be found at http://www.faqs.org/rfcs/rfc2396.html Since this is a pretty fundamental operation for webapplications I wouldn't be suprised if similar code already exists somewhere in the PHP source, but I didn't find anything. Please CC any comments directly to me, I'm not subscribed to the list due to the huge amount of mails from the bugtracking system. Regards, Fredrik -- Do fish get thirsty? Fredrik Öhrn Chalmers University of Technology ohrn@chl.chalmers.se Sweden *** basic_functions.c.orig Sat Mar 17 00:51:25 2001 --- basic_functions.c Sat Mar 17 00:53:16 2001 *************** *** 140,145 **** --- 140,147 ---- PHP_FE(php_sapi_name, NULL) PHP_FE(php_uname, NULL) + PHP_FE(str_uri_escape, NULL) + PHP_FE(str_uri_unescape, NULL) PHP_FE(strnatcmp, NULL) PHP_FE(strnatcasecmp, NULL) PHP_FE(substr_count, NULL) *** php_string.h.orig Sat Mar 17 00:51:48 2001 --- php_string.h Sat Mar 17 01:51:10 2001 *************** *** 78,83 **** --- 78,85 ---- PHP_FUNCTION(substr_count); PHP_FUNCTION(str_pad); PHP_FUNCTION(sscanf); + PHP_FUNCTION(str_uri_escape); + PHP_FUNCTION(str_uri_unescape); #define strnatcmp(a, b) \ strnatcmp_ex(a, strlen(a), b, strlen(b), 0) *************** *** 126,131 **** --- 128,136 ---- PHPAPI char *php_strerror(int errnum); #define strerror php_strerror #endif + + PHPAPI char *php_str_uri_escape(char *str, int length, int *new_length, int should_free); + PHPAPI void php_uri_unescape(char *str, int *len); void register_string_constants(INIT_FUNC_ARGS); *** quot_print.h.orig Sat Mar 17 02:13:31 2001 --- quot_print.h Sat Mar 17 02:02:04 2001 *************** *** 23,26 **** --- 23,28 ---- PHP_FUNCTION(quoted_printable_decode); + PHPAPI char php_hex2int(int c); + #endif /* QUOT_PRINT_H */ *** quot_print.c.orig Sat Mar 17 01:45:54 2001 --- quot_print.c Sat Mar 17 02:02:14 2001 *************** *** 34,40 **** /* * Converting HEX char to INT value */ ! static char php_hex2int(int c) { if ( isdigit(c) ) { --- 34,40 ---- /* * Converting HEX char to INT value */ ! PHPAPI char php_hex2int(int c) { if ( isdigit(c) ) { *************** *** 43,48 **** --- 43,52 ---- else if ( c >= 'A' && c <= 'F' ) { return c - 'A' + 10; + } + else if ( c >= 'a' && c <= 'f' ) + { + return c - 'a' + 10; } else { *** string.c.orig Sat Mar 17 00:52:04 2001 --- string.c Sat Mar 17 02:02:37 2001 *************** *** 36,41 **** --- 36,42 ---- #include "php_globals.h" #include "basic_functions.h" #include "php_smart_str.h" + #include "quot_print.h" #define STR_PAD_LEFT 0 #define STR_PAD_RIGHT 1 *************** *** 2973,2978 **** --- 2974,3083 ---- } /* }}} */ + /* {{{ proto string str_uri_escape(string str) + Escape a string according to RFC 2396 (i.e. %xx style). */ + PHP_FUNCTION(str_uri_escape) + { + zval **str; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(str); + + if(Z_STRLEN_PP(str) == 0) { + RETURN_EMPTY_STRING(); + } + + return_value->value.str.val = php_str_uri_escape((*str)->value.str.val,(*str)->value.str.len,&return_value->value.str.len,0); + return_value->type = IS_STRING; + } + /* }}} */ + + PHPAPI char *php_str_uri_escape(char *str, int length, int *new_length, int should_free) + { + /* Encodes valid characters: A-Z a-z 0-9 -_.!~*'() */ + static char ok [96] = { + 0,1,0,0,0,0,0,1,1,1,1,0,0,1,1,0, + 1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0, + 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1, + 0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, + 1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0 + }; + + char *new_str; + char *source,*target; + unsigned char c; + int count = 0; + PLS_FETCH(); + + if (!str) { + *new_length = 0; + return str; + } + + for (source = str; *source; source++) + if (*source<32 || !ok[*source-32]) + count ++; + + *new_length = length + count + count; + + new_str = (char *) emalloc(*new_length); + + for (source=str,target=new_str; *source; source++) { + if (*source>31 && ok[*source-32]) + *target++ = *source; + else + { + c = *source; + *target++ = '%'; + *target++ = hexconvtab [c >> 4]; + *target++ = hexconvtab [c & 15]; + } + } + + *target = 0; + if (should_free) { + STR_FREE(str); + } + return new_str; + } + + /* {{{ proto string str_uri_unescape(string str) + Unescape a string according to RFC 2396 (i.e. %xx style). */ + PHP_FUNCTION(str_uri_unescape) + { + zval **str; + + if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) { + WRONG_PARAM_COUNT; + } + convert_to_string_ex(str); + + *return_value = **str; + zval_copy_ctor(return_value); + php_uri_unescape(return_value->value.str.val,&return_value->value.str.len); + } + /* }}} */ + + /* be careful, this edits the string in-place */ + PHPAPI void php_uri_unescape(char *str, int *len) + { + char *s = str, *t = str; + PLS_FETCH(); + + while (*s) { + if (*s == '%') { + s++; /* skip the % */ + if (*s) *t = php_hex2int (*s++) << 4; + if (*s) *t++ += php_hex2int (*s++); + } else { + *t++ = *s++; + } + } + *t = '\0'; + } /* * Local variables:

« previous php.dev (#49184) next »