You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@apr.apache.org by mi...@apache.org on 2013/10/09 23:24:04 UTC
svn commit: r1530799 - in /apr/apr/branches/1.5.x: ./ encoding/ include/
include/private/ test/ tools/
Author: minfrin
Date: Wed Oct 9 21:24:03 2013
New Revision: 1530799
URL: http://svn.apache.org/r1530799
Log:
Backport the apr_escape() interface to apr v1.5.
Added:
apr/apr/branches/1.5.x/encoding/ (with props)
apr/apr/branches/1.5.x/encoding/apr_escape.c
apr/apr/branches/1.5.x/include/apr_escape.h
- copied, changed from r1489517, apr/apr/trunk/include/apr_escape.h
apr/apr/branches/1.5.x/include/private/
apr/apr/branches/1.5.x/include/private/apr_escape_test_char.h
apr/apr/branches/1.5.x/test/testescape.c
- copied, changed from r1489517, apr/apr/trunk/test/testescape.c
apr/apr/branches/1.5.x/tools/ (props changed)
- copied from r1489517, apr/apr/trunk/tools/
Modified:
apr/apr/branches/1.5.x/ (props changed)
apr/apr/branches/1.5.x/CHANGES
apr/apr/branches/1.5.x/Makefile.in
apr/apr/branches/1.5.x/build.conf
apr/apr/branches/1.5.x/test/Makefile.in
apr/apr/branches/1.5.x/test/abts_tests.h
apr/apr/branches/1.5.x/test/testutil.h
Propchange: apr/apr/branches/1.5.x/
------------------------------------------------------------------------------
Merged /apr/apr/trunk:r1484271,1489517,1530786
Modified: apr/apr/branches/1.5.x/CHANGES
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/CHANGES?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/CHANGES [utf-8] (original)
+++ apr/apr/branches/1.5.x/CHANGES [utf-8] Wed Oct 9 21:24:03 2013
@@ -1,6 +1,8 @@
-*- coding: utf-8 -*-
Changes for APR 1.5.0
+ *) Add the apr_escape interface. [Graham Leggett]
+
*) Cygwin build fixes. PRs 51016 and 55586. [Carlo Bramini
<carlo.bramix libero.it>]
Modified: apr/apr/branches/1.5.x/Makefile.in
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/Makefile.in?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/Makefile.in (original)
+++ apr/apr/branches/1.5.x/Makefile.in Wed Oct 9 21:24:03 2013
@@ -18,7 +18,7 @@ APR_MAJOR_VERSION=@APR_MAJOR_VERSION@
INCDIR=./include
OSDIR=$(top_srcdir)/include/arch/@OSDIR@
DEFOSDIR=$(INCDIR)/arch/@DEFAULT_OSDIR@
-INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) -I$(top_srcdir)/include/arch/@DEFAULT_OSDIR@ -I$(top_srcdir)/include
+INCLUDES=-I$(INCDIR) -I$(OSDIR) -I$(DEFOSDIR) -I$(top_srcdir)/include/arch/@DEFAULT_OSDIR@ -I$(top_srcdir)/include -I$(top_srcdir)/include/private
#
# Macros for target determination
@@ -36,7 +36,7 @@ INSTALL_DATA = @INSTALL_DATA@
# Rules for building specific targets, starting with 'all' for
# building the entire package.
#
-TARGETS = $(TARGET_LIB) apr.exp apr-config.out build/apr_rules.out
+TARGETS = $(TARGET_LIB) include/private/apr_escape_test_char.h apr.exp apr-config.out build/apr_rules.out
LT_VERSION = @LT_VERSION@
@@ -45,7 +45,7 @@ LT_VERSION = @LT_VERSION@
@INCLUDE_OUTPUTS@
CLEAN_TARGETS = apr-config.out apr.exp exports.c export_vars.c .make.dirs \
- build/apr_rules.out
+ build/apr_rules.out tools/gen_test_char
DISTCLEAN_TARGETS = config.cache config.log config.status \
include/apr.h include/arch/unix/apr_private.h \
libtool $(APR_CONFIG) build/apr_rules.mk apr.pc \
@@ -125,5 +125,15 @@ check: $(TARGET_LIB)
etags:
etags `find . -name '*.[ch]'`
+OBJECTS_gen_test_char = tools/gen_test_char.lo $(LOCAL_LIBS)
+tools/gen_test_char@EXEEXT@: $(OBJECTS_gen_test_char)
+ $(LINK_PROG) $(OBJECTS_gen_test_char) $(ALL_LIBS)
+
+include/private/apr_escape_test_char.h: tools/gen_test_char
+ tools/gen_test_char > include/private/apr_escape_test_char.h
+
+LINK_PROG = $(LIBTOOL) $(LTFLAGS) --mode=link $(COMPILE) $(LT_LDFLAGS) \
+ @LT_NO_INSTALL@ $(ALL_LDFLAGS) -o $@
+
# DO NOT REMOVE
docs: $(INCDIR)/*.h
Modified: apr/apr/branches/1.5.x/build.conf
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/build.conf?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/build.conf (original)
+++ apr/apr/branches/1.5.x/build.conf Wed Oct 9 21:24:03 2013
@@ -6,6 +6,7 @@
# paths to platform-independent .c files to build
paths =
+ encoding/*.c
passwd/*.c
strings/*.c
tables/*.c
Propchange: apr/apr/branches/1.5.x/encoding/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Oct 9 21:24:03 2013
@@ -0,0 +1,4 @@
+*.lo
+*.la
+.libs
+
Added: apr/apr/branches/1.5.x/encoding/apr_escape.c
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/encoding/apr_escape.c?rev=1530799&view=auto
==============================================================================
--- apr/apr/branches/1.5.x/encoding/apr_escape.c (added)
+++ apr/apr/branches/1.5.x/encoding/apr_escape.c Wed Oct 9 21:24:03 2013
@@ -0,0 +1,1150 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* escape/unescape functions.
+ *
+ * These functions perform various escaping operations, and are provided in
+ * pairs, a function to query the length of and escape existing buffers, as
+ * well as companion functions to perform the same process to memory
+ * allocated from a pool.
+ *
+ * The API is designed to have the smallest possible RAM footprint, and so
+ * will only allocate the exact amount of RAM needed for each conversion.
+ */
+
+#include "apr_escape.h"
+#include "apr_escape_test_char.h"
+#include "apr_lib.h"
+#include "apr_strings.h"
+
+/* helper for Latin1 <-> entity encoding */
+#if APR_CHARSET_EBCDIC
+#include "apr_xlate.h"
+#define RAW_ASCII_CHAR(ch) apr_xlate_conv_byte(ap_hdrs_from_ascii, \
+ (unsigned char)ch)
+#else /* APR_CHARSET_EBCDIC */
+#define RAW_ASCII_CHAR(ch) (ch)
+#endif /* !APR_CHARSET_EBCDIC */
+
+/* we assume the folks using this ensure 0 <= c < 256... which means
+ * you need a cast to (unsigned char) first, you can't just plug a
+ * char in here and get it to work, because if char is signed then it
+ * will first be sign extended.
+ */
+#define TEST_CHAR(c, f) (test_char_table[(unsigned)(c)] & (f))
+
+APR_DECLARE(apr_status_t) apr_escape_shell(char *escaped, const char *str,
+ apr_ssize_t slen, apr_size_t *len)
+{
+ unsigned char *d;
+ const unsigned char *s;
+ apr_size_t size = 1;
+ int found = 0;
+
+ d = (unsigned char *) escaped;
+ s = (const unsigned char *) str;
+
+ if (s) {
+ if (d) {
+ for (; *s && slen; ++s, slen--) {
+#if defined(OS2) || defined(WIN32)
+ /*
+ * Newlines to Win32/OS2 CreateProcess() are ill advised.
+ * Convert them to spaces since they are effectively white
+ * space to most applications
+ */
+ if (*s == '\r' || *s == '\n') {
+ if (d) {
+ *d++ = ' ';
+ found = 1;
+ }
+ continue;
+ }
+#endif
+ if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+ *d++ = '\\';
+ size++;
+ found = 1;
+ }
+ *d++ = *s;
+ size++;
+ }
+ *d = '\0';
+ }
+ else {
+ for (; *s && slen; ++s, slen--) {
+ if (TEST_CHAR(*s, T_ESCAPE_SHELL_CMD)) {
+ size++;
+ found = 1;
+ }
+ size++;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_shell(apr_pool_t *p, const char *str)
+{
+ apr_size_t len;
+
+ switch (apr_escape_shell(NULL, str, APR_ESCAPE_STRING, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_escape_shell(cmd, str, APR_ESCAPE_STRING, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+static char x2c(const char *what)
+{
+ register char digit;
+
+#if !APR_CHARSET_EBCDIC
+ digit =
+ ((what[0] >= 'A') ? ((what[0] & 0xdf) - 'A') + 10 : (what[0] - '0'));
+ digit *= 16;
+ digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A') + 10 : (what[1] - '0'));
+#else /*APR_CHARSET_EBCDIC*/
+ char xstr[5];
+ xstr[0]='0';
+ xstr[1]='x';
+ xstr[2]=what[0];
+ xstr[3]=what[1];
+ xstr[4]='\0';
+ digit = apr_xlate_conv_byte(ap_hdrs_from_ascii,
+ 0xFF & strtol(xstr, NULL, 16));
+#endif /*APR_CHARSET_EBCDIC*/
+ return (digit);
+}
+
+APR_DECLARE(apr_status_t) apr_unescape_url(char *escaped, const char *url,
+ apr_ssize_t slen, const char *forbid, const char *reserved, int plus,
+ apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const char *s = (const char *) url;
+ char *d = (char *) escaped;
+ register int badesc, badpath;
+
+ if (!url) {
+ return APR_NOTFOUND;
+ }
+
+ badesc = 0;
+ badpath = 0;
+ if (s) {
+ if (d) {
+ for (; *s && slen; ++s, d++, slen--) {
+ if (plus && *s == '+') {
+ *d = ' ';
+ found = 1;
+ }
+ else if (*s != '%') {
+ *d = *s;
+ }
+ else {
+ if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
+ badesc = 1;
+ *d = '%';
+ }
+ else {
+ char decoded;
+ decoded = x2c(s + 1);
+ if ((decoded == '\0')
+ || (forbid && strchr(forbid, decoded))) {
+ badpath = 1;
+ *d = decoded;
+ s += 2;
+ slen -= 2;
+ }
+ else if (reserved && strchr(reserved, decoded)) {
+ *d++ = *s++;
+ *d++ = *s++;
+ *d = *s;
+ size += 2;
+ }
+ else {
+ *d = decoded;
+ s += 2;
+ slen -= 2;
+ found = 1;
+ }
+ }
+ }
+ size++;
+ }
+ *d = '\0';
+ }
+ else {
+ for (; *s && slen; ++s, slen--) {
+ if (plus && *s == '+') {
+ found = 1;
+ }
+ else if (*s != '%') {
+ /* character unchanged */
+ }
+ else {
+ if (!apr_isxdigit(*(s + 1)) || !apr_isxdigit(*(s + 2))) {
+ badesc = 1;
+ }
+ else {
+ char decoded;
+ decoded = x2c(s + 1);
+ if ((decoded == '\0')
+ || (forbid && strchr(forbid, decoded))) {
+ badpath = 1;
+ s += 2;
+ slen -= 2;
+ }
+ else if (reserved && strchr(reserved, decoded)) {
+ s += 2;
+ slen -= 2;
+ size += 2;
+ }
+ else {
+ s += 2;
+ slen -= 2;
+ found = 1;
+ }
+ }
+ }
+ size++;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (badesc) {
+ return APR_EINVAL;
+ }
+ else if (badpath) {
+ return APR_BADCH;
+ }
+ else if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_punescape_url(apr_pool_t *p, const char *url,
+ const char *forbid, const char *reserved, int plus)
+{
+ apr_size_t len;
+
+ switch (apr_unescape_url(NULL, url, APR_ESCAPE_STRING, forbid, reserved,
+ plus, &len)) {
+ case APR_SUCCESS: {
+ char *buf = apr_palloc(p, len);
+ apr_unescape_url(buf, url, APR_ESCAPE_STRING, forbid, reserved, plus,
+ NULL);
+ return buf;
+ }
+ case APR_EINVAL:
+ case APR_BADCH: {
+ return NULL;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return url;
+}
+
+/* c2x takes an unsigned, and expects the caller has guaranteed that
+ * 0 <= what < 256... which usually means that you have to cast to
+ * unsigned char first, because (unsigned)(char)(x) first goes through
+ * signed extension to an int before the unsigned cast.
+ *
+ * The reason for this assumption is to assist gcc code generation --
+ * the unsigned char -> unsigned extension is already done earlier in
+ * both uses of this code, so there's no need to waste time doing it
+ * again.
+ */
+static const char c2x_table[] = "0123456789abcdef";
+
+static APR_INLINE unsigned char *c2x(unsigned what, unsigned char prefix,
+ unsigned char *where)
+{
+#if APR_CHARSET_EBCDIC
+ what = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)what);
+#endif /*APR_CHARSET_EBCDIC*/
+ *where++ = prefix;
+ *where++ = c2x_table[what >> 4];
+ *where++ = c2x_table[what & 0xf];
+ return where;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_path_segment(char *escaped,
+ const char *str, apr_ssize_t slen, apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const unsigned char *s = (const unsigned char *) str;
+ unsigned char *d = (unsigned char *) escaped;
+ unsigned c;
+
+ if (s) {
+ if (d) {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
+ d = c2x(c, '%', d);
+ size += 2;
+ found = 1;
+ }
+ else {
+ *d++ = c;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ *d = '\0';
+ }
+ else {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_PATH_SEGMENT)) {
+ size += 2;
+ found = 1;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_path_segment(apr_pool_t *p,
+ const char *str)
+{
+ apr_size_t len;
+
+ switch (apr_escape_path_segment(NULL, str, APR_ESCAPE_STRING, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_escape_path_segment(cmd, str, APR_ESCAPE_STRING, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_path(char *escaped, const char *path,
+ apr_ssize_t slen, int partial, apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const unsigned char *s = (const unsigned char *) path;
+ unsigned char *d = (unsigned char *) escaped;
+ unsigned c;
+
+ if (!path) {
+ return APR_NOTFOUND;
+ }
+
+ if (!partial) {
+ const char *colon = strchr(path, ':');
+ const char *slash = strchr(path, '/');
+
+ if (colon && (!slash || colon < slash)) {
+ if (d) {
+ *d++ = '.';
+ *d++ = '/';
+ }
+ size += 2;
+ found = 1;
+ }
+ }
+ if (d) {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
+ d = c2x(c, '%', d);
+ }
+ else {
+ *d++ = c;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ *d = '\0';
+ }
+ else {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_OS_ESCAPE_PATH)) {
+ size += 2;
+ found = 1;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_path(apr_pool_t *p, const char *str,
+ int partial)
+{
+ apr_size_t len;
+
+ switch (apr_escape_path(NULL, str, APR_ESCAPE_STRING, partial, &len)) {
+ case APR_SUCCESS: {
+ char *path = apr_palloc(p, len);
+ apr_escape_path(path, str, APR_ESCAPE_STRING, partial, NULL);
+ return path;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_urlencoded(char *escaped, const char *str,
+ apr_ssize_t slen, apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const unsigned char *s = (const unsigned char *) str;
+ unsigned char *d = (unsigned char *) escaped;
+ unsigned c;
+
+ if (s) {
+ if (d) {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
+ d = c2x(c, '%', d);
+ size += 2;
+ found = 1;
+ }
+ else if (c == ' ') {
+ *d++ = '+';
+ found = 1;
+ }
+ else {
+ *d++ = c;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ *d = '\0';
+ }
+ else {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_URLENCODED)) {
+ size += 2;
+ found = 1;
+ }
+ else if (c == ' ') {
+ found = 1;
+ }
+ ++s;
+ size++;
+ slen--;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_urlencoded(apr_pool_t *p, const char *str)
+{
+ apr_size_t len;
+
+ switch (apr_escape_urlencoded(NULL, str, APR_ESCAPE_STRING, &len)) {
+ case APR_SUCCESS: {
+ char *encoded = apr_palloc(p, len);
+ apr_escape_urlencoded(encoded, str, APR_ESCAPE_STRING, NULL);
+ return encoded;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_entity(char *escaped, const char *str,
+ apr_ssize_t slen, int toasc, apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const unsigned char *s = (const unsigned char *) str;
+ unsigned char *d = (unsigned char *) escaped;
+ unsigned c;
+
+ if (s) {
+ if (d) {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_XML)) {
+ switch (c) {
+ case '>': {
+ memcpy(d, ">", 4);
+ size += 4;
+ d += 4;
+ break;
+ }
+ case '<': {
+ memcpy(d, "<", 4);
+ size += 4;
+ d += 4;
+ break;
+ }
+ case '&': {
+ memcpy(d, "&", 5);
+ size += 5;
+ d += 5;
+ break;
+ }
+ case '\"': {
+ memcpy(d, """, 6);
+ size += 6;
+ d += 6;
+ break;
+ }
+ case '\'': {
+ memcpy(d, "'", 6);
+ size += 6;
+ d += 6;
+ break;
+ }
+ }
+ found = 1;
+ }
+ else if (toasc && !apr_isascii(c)) {
+ int offset = apr_snprintf((char *) d, 6, "&#%3.3d;", c);
+ size += offset;
+ d += offset;
+ found = 1;
+ }
+ else {
+ *d++ = c;
+ size++;
+ }
+ ++s;
+ slen--;
+ }
+ *d = '\0';
+ }
+ else {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_XML)) {
+ switch (c) {
+ case '>': {
+ size += 4;
+ break;
+ }
+ case '<': {
+ size += 4;
+ break;
+ }
+ case '&': {
+ size += 5;
+ break;
+ }
+ case '\"': {
+ size += 6;
+ break;
+ }
+ case '\'': {
+ size += 6;
+ break;
+ }
+ }
+ found = 1;
+ }
+ else if (toasc && !apr_isascii(c)) {
+ char buf[8];
+ size += apr_snprintf(buf, 6, "&#%3.3d;", c);
+ found = 1;
+ }
+ else {
+ size++;
+ }
+ ++s;
+ slen--;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_entity(apr_pool_t *p, const char *str,
+ int toasc)
+{
+ apr_size_t len;
+
+ switch (apr_escape_entity(NULL, str, APR_ESCAPE_STRING, toasc, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_escape_entity(cmd, str, APR_ESCAPE_STRING, toasc, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+/* maximum length of any ISO-LATIN-1 HTML entity name. */
+#define MAXENTLEN (6)
+
+APR_DECLARE(apr_status_t) apr_unescape_entity(char *unescaped, const char *str,
+ apr_ssize_t slen, apr_size_t *len)
+{
+ int found = 0;
+ apr_size_t size = 1;
+ int val, i, j;
+ char *d = unescaped;
+ const char *s = str;
+ const char *ents;
+ static const char * const entlist[MAXENTLEN + 1] =
+ {
+ NULL, /* 0 */
+ NULL, /* 1 */
+ "lt\074gt\076", /* 2 */
+ "amp\046ETH\320eth\360", /* 3 */
+ "quot\042Auml\304Euml\313Iuml\317Ouml\326Uuml\334auml\344euml"
+ "\353iuml\357ouml\366uuml\374yuml\377", /* 4 */
+ "Acirc\302Aring\305AElig\306Ecirc\312Icirc\316Ocirc\324Ucirc"
+ "\333THORN\336szlig\337acirc\342aring\345aelig\346ecirc\352"
+ "icirc\356ocirc\364ucirc\373thorn\376", /* 5 */
+ "Agrave\300Aacute\301Atilde\303Ccedil\307Egrave\310Eacute\311"
+ "Igrave\314Iacute\315Ntilde\321Ograve\322Oacute\323Otilde"
+ "\325Oslash\330Ugrave\331Uacute\332Yacute\335agrave\340"
+ "aacute\341atilde\343ccedil\347egrave\350eacute\351igrave"
+ "\354iacute\355ntilde\361ograve\362oacute\363otilde\365"
+ "oslash\370ugrave\371uacute\372yacute\375" /* 6 */
+ };
+
+ if (s) {
+ if (d) {
+ for (; *s != '\0' && slen; s++, d++, size++, slen--) {
+ if (*s != '&') {
+ *d = *s;
+ continue;
+ }
+ /* find end of entity */
+ for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
+ i++) {
+ continue;
+ }
+
+ if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
+ *d = *s;
+ continue;
+ }
+
+ /* is it numeric ? */
+ if (s[1] == '#') {
+ for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
+ val = val * 10 + s[j] - '0';
+ }
+ s += i;
+ if (j < i || val <= 8 || (val >= 11 && val <= 31)
+ || (val >= 127 && val <= 160) || val >= 256) {
+ d--; /* no data to output */
+ size--;
+ }
+ else {
+ *d = RAW_ASCII_CHAR(val);
+ found = 1;
+ }
+ }
+ else {
+ j = i - 1;
+ if (j > MAXENTLEN || entlist[j] == NULL) {
+ /* wrong length */
+ *d = '&';
+ continue; /* skip it */
+ }
+ for (ents = entlist[j]; *ents != '\0'; ents += i) {
+ if (strncmp(s + 1, ents, j) == 0) {
+ break;
+ }
+ }
+
+ if (*ents == '\0') {
+ *d = '&'; /* unknown */
+ }
+ else {
+ *d = RAW_ASCII_CHAR(((const unsigned char *) ents)[j]);
+ s += i;
+ slen -= i;
+ found = 1;
+ }
+ }
+ }
+ *d = '\0';
+ }
+ else {
+ for (; *s != '\0' && slen; s++, size++, slen--) {
+ if (*s != '&') {
+ continue;
+ }
+ /* find end of entity */
+ for (i = 1; s[i] != ';' && s[i] != '\0' && (slen - i) != 0;
+ i++) {
+ continue;
+ }
+
+ if (s[i] == '\0' || (slen - i) == 0) { /* treat as normal data */
+ continue;
+ }
+
+ /* is it numeric ? */
+ if (s[1] == '#') {
+ for (j = 2, val = 0; j < i && apr_isdigit(s[j]); j++) {
+ val = val * 10 + s[j] - '0';
+ }
+ s += i;
+ if (j < i || val <= 8 || (val >= 11 && val <= 31)
+ || (val >= 127 && val <= 160) || val >= 256) {
+ /* no data to output */
+ size--;
+ }
+ else {
+ found = 1;
+ }
+ }
+ else {
+ j = i - 1;
+ if (j > MAXENTLEN || entlist[j] == NULL) {
+ /* wrong length */
+ continue; /* skip it */
+ }
+ for (ents = entlist[j]; *ents != '\0'; ents += i) {
+ if (strncmp(s + 1, ents, j) == 0) {
+ break;
+ }
+ }
+
+ if (*ents == '\0') {
+ /* unknown */
+ }
+ else {
+ s += i;
+ slen -= i;
+ found = 1;
+ }
+ }
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_punescape_entity(apr_pool_t *p, const char *str)
+{
+ apr_size_t len;
+
+ switch (apr_unescape_entity(NULL, str, APR_ESCAPE_STRING, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_unescape_entity(cmd, str, APR_ESCAPE_STRING, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_echo(char *escaped, const char *str,
+ apr_ssize_t slen, int quote, apr_size_t *len)
+{
+ apr_size_t size = 1;
+ int found = 0;
+ const unsigned char *s = (const unsigned char *) str;
+ unsigned char *d = (unsigned char *) escaped;
+ unsigned c;
+
+ if (s) {
+ if (d) {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
+ *d++ = '\\';
+ size++;
+ switch (c) {
+ case '\a':
+ *d++ = 'a';
+ size++;
+ found = 1;
+ break;
+ case '\b':
+ *d++ = 'b';
+ size++;
+ found = 1;
+ break;
+ case '\f':
+ *d++ = 'f';
+ size++;
+ found = 1;
+ break;
+ case '\n':
+ *d++ = 'n';
+ size++;
+ found = 1;
+ break;
+ case '\r':
+ *d++ = 'r';
+ size++;
+ found = 1;
+ break;
+ case '\t':
+ *d++ = 't';
+ size++;
+ found = 1;
+ break;
+ case '\v':
+ *d++ = 'v';
+ size++;
+ found = 1;
+ break;
+ case '\\':
+ *d++ = '\\';
+ size++;
+ found = 1;
+ break;
+ case '"':
+ if (quote) {
+ *d++ = c;
+ size++;
+ found = 1;
+ }
+ else {
+ d[-1] = c;
+ }
+ break;
+ default:
+ c2x(c, 'x', d);
+ d += 3;
+ size += 3;
+ found = 1;
+ break;
+ }
+ }
+ else {
+ *d++ = c;
+ size++;
+ }
+ ++s;
+ slen--;
+ }
+ *d = '\0';
+ }
+ else {
+ while ((c = *s) && slen) {
+ if (TEST_CHAR(c, T_ESCAPE_ECHO)) {
+ size++;
+ switch (c) {
+ case '\a':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ case '\v':
+ case '\\':
+ size++;
+ found = 1;
+ break;
+ case '"':
+ if (quote) {
+ size++;
+ found = 1;
+ }
+ break;
+ default:
+ size += 3;
+ found = 1;
+ break;
+ }
+ }
+ else {
+ size++;
+ }
+ ++s;
+ slen--;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!found) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_echo(apr_pool_t *p, const char *str,
+ int quote)
+{
+ apr_size_t len;
+
+ switch (apr_escape_echo(NULL, str, APR_ESCAPE_STRING, quote, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_escape_echo(cmd, str, APR_ESCAPE_STRING, quote, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return str;
+}
+
+APR_DECLARE(apr_status_t) apr_escape_hex(char *dest, const void *src,
+ apr_size_t srclen, int colon, apr_size_t *len)
+{
+ const unsigned char *in = src;
+ apr_size_t size;
+
+ if (!src) {
+ return APR_NOTFOUND;
+ }
+
+ if (dest) {
+ for (size = 0; size < srclen; size++) {
+ if (colon && size) {
+ *dest++ = ':';
+ }
+ *dest++ = c2x_table[in[size] >> 4];
+ *dest++ = c2x_table[in[size] & 0xf];
+ }
+ *dest = '\0';
+ }
+
+ if (len) {
+ if (colon && srclen) {
+ *len = srclen * 3;
+ }
+ else {
+ *len = srclen * 2 + 1;
+ }
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const char *) apr_pescape_hex(apr_pool_t *p, const void *src,
+ apr_size_t srclen, int colon)
+{
+ apr_size_t len;
+
+ switch (apr_escape_hex(NULL, src, srclen, colon, &len)) {
+ case APR_SUCCESS: {
+ char *cmd = apr_palloc(p, len);
+ apr_escape_hex(cmd, src, srclen, colon, NULL);
+ return cmd;
+ }
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return src;
+}
+
+APR_DECLARE(apr_status_t) apr_unescape_hex(void *dest, const char *str,
+ apr_ssize_t slen, int colon, apr_size_t *len)
+{
+ apr_size_t size = 0;
+ int flip = 0;
+ const unsigned char *s = (const unsigned char *) str;
+ unsigned char *d = (unsigned char *) dest;
+ unsigned c;
+ unsigned char u = 0;
+
+ if (s) {
+ if (d) {
+ while ((c = *s) && slen) {
+
+ if (!flip) {
+ u = 0;
+ }
+
+ if (colon && c == ':' && !flip) {
+ ++s;
+ slen--;
+ continue;
+ }
+ else if (apr_isdigit(c)) {
+ u |= c - '0';
+ }
+ else if (apr_isupper(c) && c <= 'F') {
+ u |= c - ('A' - 10);
+ }
+ else if (apr_islower(c) && c <= 'f') {
+ u |= c - ('a' - 10);
+ }
+ else {
+ return APR_BADCH;
+ }
+
+ if (flip) {
+ *d++ = u;
+ size++;
+ }
+ else {
+ u <<= 4;
+ *d = u;
+ }
+ flip = !flip;
+
+ ++s;
+ slen--;
+ }
+ }
+ else {
+ while ((c = *s) && slen) {
+
+ if (colon && c == ':' && !flip) {
+ ++s;
+ slen--;
+ continue;
+ }
+ else if (apr_isdigit(c)) {
+ /* valid */
+ }
+ else if (apr_isupper(c) && c <= 'F') {
+ /* valid */
+ }
+ else if (apr_islower(c) && c <= 'f') {
+ /* valid */
+ }
+ else {
+ return APR_BADCH;
+ }
+
+ if (flip) {
+ size++;
+ }
+ flip = !flip;
+
+ ++s;
+ slen--;
+ }
+ }
+ }
+
+ if (len) {
+ *len = size;
+ }
+ if (!s) {
+ return APR_NOTFOUND;
+ }
+
+ return APR_SUCCESS;
+}
+
+APR_DECLARE(const void *) apr_punescape_hex(apr_pool_t *p, const char *str,
+ int colon, apr_size_t *len)
+{
+ apr_size_t size;
+
+ switch (apr_unescape_hex(NULL, str, APR_ESCAPE_STRING, colon, &size)) {
+ case APR_SUCCESS: {
+ void *cmd = apr_palloc(p, size);
+ apr_unescape_hex(cmd, str, APR_ESCAPE_STRING, colon, len);
+ return cmd;
+ }
+ case APR_BADCH:
+ case APR_NOTFOUND: {
+ break;
+ }
+ }
+
+ return NULL;
+}
Copied: apr/apr/branches/1.5.x/include/apr_escape.h (from r1489517, apr/apr/trunk/include/apr_escape.h)
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/include/apr_escape.h?p2=apr/apr/branches/1.5.x/include/apr_escape.h&p1=apr/apr/trunk/include/apr_escape.h&r1=1489517&r2=1530799&rev=1530799&view=diff
==============================================================================
--- apr/apr/trunk/include/apr_escape.h (original)
+++ apr/apr/branches/1.5.x/include/apr_escape.h Wed Oct 9 21:24:03 2013
@@ -19,7 +19,7 @@
*/
#ifndef APR_ESCAPE_H
#define APR_ESCAPE_H
-#include "apu.h"
+#include "apr.h"
#include "apr_general.h"
#ifdef __cplusplus
extern "C" {
@@ -275,9 +275,8 @@ APR_DECLARE(const char *) apr_punescape_
/**
* Escape control characters in a string, as performed by the shell's
* 'echo' command. Characters are replaced as follows:
- * \a alert (bell), \b backspace, \e an escape character, \f form feed,
- * \n new line, \r carriage return, \t horizontal tab, \v vertical tab,
- * \\ backslash.
+ * \a alert (bell), \b backspace, \f form feed, \n new line, \r carriage
+ * return, \t horizontal tab, \v vertical tab, \\ backslash.
*
* Any non ascii character will be encoded as '\xHH', where HH is the hex
* code of the character.
Added: apr/apr/branches/1.5.x/include/private/apr_escape_test_char.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/include/private/apr_escape_test_char.h?rev=1530799&view=auto
==============================================================================
--- apr/apr/branches/1.5.x/include/private/apr_escape_test_char.h (added)
+++ apr/apr/branches/1.5.x/include/private/apr_escape_test_char.h Wed Oct 9 21:24:03 2013
@@ -0,0 +1,23 @@
+/* this file is automatically generated by gen_test_char, do not edit. "make include/private/apr_escape_test_char.h" to regenerate. */
+#define T_ESCAPE_SHELL_CMD (1)
+#define T_ESCAPE_PATH_SEGMENT (2)
+#define T_OS_ESCAPE_PATH (4)
+#define T_ESCAPE_ECHO (8)
+#define T_ESCAPE_URLENCODED (16)
+#define T_ESCAPE_XML (32)
+
+static const unsigned char test_char_table[256] = {
+ 32,30,30,30,30,30,30,30,30,30,31,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,6,16,63,22,17,22,49,17,
+ 17,17,1,16,16,0,0,18,0,0,0,0,0,0,0,0,0,0,16,23,
+ 55,16,55,23,16,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,23,31,23,23,0,23,0,0,0,
+ 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+ 0,0,0,23,23,23,17,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,
+ 30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30
+};
Modified: apr/apr/branches/1.5.x/test/Makefile.in
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/Makefile.in?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/test/Makefile.in (original)
+++ apr/apr/branches/1.5.x/test/Makefile.in Wed Oct 9 21:24:03 2013
@@ -28,7 +28,7 @@ TESTS = testtime.lo teststr.lo testvsn.l
testhash.lo testargs.lo testnames.lo testuser.lo testpath.lo \
testenv.lo testprocmutex.lo testfnmatch.lo testatomic.lo testflock.lo \
testsock.lo testglobalmutex.lo teststrnatcmp.lo testfilecopy.lo \
- testtemp.lo testlfs.lo testcond.lo
+ testtemp.lo testlfs.lo testcond.lo testescape.lo
OTHER_PROGRAMS = \
sendfile@EXEEXT@ \
Modified: apr/apr/branches/1.5.x/test/abts_tests.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/abts_tests.h?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/test/abts_tests.h (original)
+++ apr/apr/branches/1.5.x/test/abts_tests.h Wed Oct 9 21:24:03 2013
@@ -28,6 +28,7 @@ const struct testlist {
{testdso},
{testdup},
{testenv},
+ {testescape},
{testfile},
{testfilecopy},
{testfileinfo},
Copied: apr/apr/branches/1.5.x/test/testescape.c (from r1489517, apr/apr/trunk/test/testescape.c)
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/testescape.c?p2=apr/apr/branches/1.5.x/test/testescape.c&p1=apr/apr/trunk/test/testescape.c&r1=1489517&r2=1530799&rev=1530799&view=diff
==============================================================================
--- apr/apr/trunk/test/testescape.c (original)
+++ apr/apr/branches/1.5.x/test/testescape.c Wed Oct 9 21:24:03 2013
@@ -34,15 +34,33 @@ static void test_escape(abts_case *tc, v
apr_pool_create(&pool, NULL);
+ src = "Hello World &;`'\"|*?~<>^()[]{}$\\";
+ target = "Hello World \\&\\;\\`\\'\\\"\\|\\*\\?\\~\\<\\>\\^\\(\\)\\[\\]\\{\\}\\$\\\\";
+ dest = apr_pescape_shell(pool, src);
+ ABTS_ASSERT(tc,
+ apr_psprintf(pool, "shell escaped (%s) does not match expected output (%s)",
+ dest, target),
+ (strcmp(dest, target) == 0));
+ apr_escape_shell(NULL, src, APR_ESCAPE_STRING, &len);
+ ABTS_ASSERT(tc,
+ apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
+ (len == strlen(dest) + 1));
+
+#if !(defined(OS2) || defined(WIN32))
+ /* Now try with newline, which is converted to a space on OS/2 and Windows.
+ */
src = "Hello World &;`'\"|*?~<>^()[]{}$\\\n";
target = "Hello World \\&\\;\\`\\'\\\"\\|\\*\\?\\~\\<\\>\\^\\(\\)\\[\\]\\{\\}\\$\\\\\\\n";
dest = apr_pescape_shell(pool, src);
- ABTS_ASSERT(tc, "shell escaped matches expected output",
+ ABTS_ASSERT(tc,
+ apr_psprintf(pool, "shell escaped (%s) does not match expected output (%s)",
+ dest, target),
(strcmp(dest, target) == 0));
apr_escape_shell(NULL, src, APR_ESCAPE_STRING, &len);
ABTS_ASSERT(tc,
apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
(len == strlen(dest) + 1));
+#endif
src = "Hello";
dest = apr_punescape_url(pool, src, NULL, NULL, 0);
@@ -196,8 +214,8 @@ static void test_escape(abts_case *tc, v
dest = apr_pescape_echo(pool, src, 0);
ABTS_PTR_EQUAL(tc, src, dest);
- src = "\a\b\e\f\\n\r\t\v\"Hello World\"";
- target = "\\a\\b\\e\\f\\\\n\\r\\t\\v\"Hello World\"";
+ src = "\a\b\f\\n\r\t\v\"Hello World\"";
+ target = "\\a\\b\\f\\\\n\\r\\t\\v\"Hello World\"";
dest = apr_pescape_echo(pool, src, 0);
ABTS_STR_EQUAL(tc, target, dest);
apr_escape_echo(NULL, src, APR_ESCAPE_STRING, 0, &len);
@@ -205,8 +223,8 @@ static void test_escape(abts_case *tc, v
apr_psprintf(pool, "size mismatch (%" APR_SIZE_T_FMT "!=%" APR_SIZE_T_FMT ")", len, strlen(dest) + 1),
(len == strlen(dest) + 1));
- src = "\a\b\e\f\\n\r\t\v\"Hello World\"";
- target = "\\a\\b\\e\\f\\\\n\\r\\t\\v\\\"Hello World\\\"";
+ src = "\a\b\f\\n\r\t\v\"Hello World\"";
+ target = "\\a\\b\\f\\\\n\\r\\t\\v\\\"Hello World\\\"";
dest = apr_pescape_echo(pool, src, 1);
ABTS_STR_EQUAL(tc, target, dest);
apr_escape_echo(NULL, src, APR_ESCAPE_STRING, 1, &len);
Modified: apr/apr/branches/1.5.x/test/testutil.h
URL: http://svn.apache.org/viewvc/apr/apr/branches/1.5.x/test/testutil.h?rev=1530799&r1=1530798&r2=1530799&view=diff
==============================================================================
--- apr/apr/branches/1.5.x/test/testutil.h (original)
+++ apr/apr/branches/1.5.x/test/testutil.h Wed Oct 9 21:24:03 2013
@@ -64,6 +64,7 @@ abts_suite *testatomic(abts_suite *suite
abts_suite *testdir(abts_suite *suite);
abts_suite *testdso(abts_suite *suite);
abts_suite *testdup(abts_suite *suite);
+abts_suite *testescape(abts_suite *suite);
abts_suite *testenv(abts_suite *suite);
abts_suite *testfile(abts_suite *suite);
abts_suite *testfilecopy(abts_suite *suite);
Propchange: apr/apr/branches/1.5.x/tools/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Wed Oct 9 21:24:03 2013
@@ -0,0 +1,6 @@
+Makefile
+*.lo
+*.la
+.libs
+gen_test_char
+gen_test_char.exe
Re: svn commit: r1530799 - in /apr/apr/branches/1.5.x: ./ encoding/
include/ include/private/ test/ tools/
Posted by Eric Covener <co...@gmail.com>.
On Sat, Dec 14, 2013 at 7:32 PM, Eric Covener <co...@gmail.com> wrote:
> On Wed, Oct 9, 2013 at 5:24 PM, <mi...@apache.org> wrote:
>> +/* helper for Latin1 <-> entity encoding */
>> +#if APR_CHARSET_EBCDIC
>> +#include "apr_xlate.h"
>
> I didn't notice it at the time -- this is an APR dependency on APU,
> which works in trunk but not in 1.5.x.
Seems like that's just the start for the EBCDIC path. Even in trunk,
it uses e.g. ap_hdrs_to_ascii.
Re: svn commit: r1530799 - in /apr/apr/branches/1.5.x: ./ encoding/
include/ include/private/ test/ tools/
Posted by Eric Covener <co...@gmail.com>.
On Wed, Oct 9, 2013 at 5:24 PM, <mi...@apache.org> wrote:
> +/* helper for Latin1 <-> entity encoding */
> +#if APR_CHARSET_EBCDIC
> +#include "apr_xlate.h"
I didn't notice it at the time -- this is an APR dependency on APU,
which works in trunk but not in 1.5.x.