apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From david reid <da...@jetnet.co.uk>
Subject apr_uri_string_encode/decode
Date Wed, 02 Aug 2006 10:58:35 GMT
First pass at importing some apreq functions. Not yet had time to wirte
a test! Rushing out of door, so just a quick mail :-)

More integration with apr_uri structure is planned, but not yet had time
to finish that bit :-)



-- Index: include/apr_uri.h
===================================================================
--- include/apr_uri.h   (revision 427948)
+++ include/apr_uri.h   (working copy)
@@ -170,6 +170,31 @@
                                                  const char *hostinfo,
                                                  apr_uri_t *uptr);

+/**
+ * @fn apr_size_t apr_uri_query_string_encode(char *dest, const char *src,
+                                              const apr_size_t slen)
+ * @brief URI encode a query string
+ * @param dest the destination pointer
+ * @param src the source pointer
+ * @param slen length of source string
+ */
+APU_DECLARE(apr_size_t) apr_uri_query_string_encode(char *, const char *,
+                                                    const apr_size_t);
+
+/**
+ * @fn apr_status_t apr_uri_query_string_decode(char *d, apr_size_t *dlen,
+                                                const char *s,
+                                                apr_size_t slen)
+ * @brief URI Decode a query string
+ * @param d destination pointer
+ * @param dlen length of created string
+ * @param s source pointer
+ * @param slen length of source string
+ */
+APU_DECLARE(apr_status_t) apr_uri_query_string_decode(char *, apr_size_t *,
+                                                      const char *,
+                                                      apr_size_t);
+
 /** @} */
 #ifdef __cplusplus
 }
Index: build.conf
===================================================================
--- build.conf  (revision 427948)
+++ build.conf  (working copy)
@@ -15,7 +15,7 @@
   ldap/*.c
   misc/*.c
   memcache/*.c
-  uri/apr_uri.c
+  uri/*.c
   xml/*.c
   strmatch/*.c
   xlate/*.c



/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
 * applicable.
 *
 * Licensed 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.
 */

/*
 * apr_uri_coding.c: URI related utility things
 *
 */

#include "apr_strings.h"
#include "apr_lib.h"

#include "apu.h"

static const char c2x_table[] = "0123456789ABCDEF";
static APR_INLINE unsigned char hex2_to_char(const char *what)
{
    register unsigned 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);
}

static APR_INLINE apr_uint16_t hex4_to_bmp(const char *what)
{
    register apr_uint16_t digit = 0;

#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'));
    digit *= 16;
    digit += (what[2] >= 'A' ? ((what[2] & 0xDF)-'A') + 10 : (what[2]-'0'));
    digit *= 16;
    digit += (what[3] >= 'A' ? ((what[3] & 0xDF)-'A') + 10 : (what[3]-'0'));

#else /*APR_CHARSET_EBCDIC*/
    char xstr[7];
    xstr[0]='0';
    xstr[1]='x';
    xstr[2]=what[0];
    xstr[3]=what[1];
    xstr[4]=what[2];
    xstr[5]=what[3];
    xstr[6]='\0';
    digit = apr_xlate_conv_byte(ap_hdrs_from_ascii, 0xFFFF &
strtol(xstr, NULL, 16));
#endif /*APR_CHARSET_EBCDIC*/
    return (digit);
}

static apr_status_t url_decode(char *dest, apr_size_t *dlen,
                               const char *src, apr_size_t *slen)
{
    register const char *s = src;
    unsigned char *start = (unsigned char *)dest;
    register unsigned char *d = (unsigned char *)dest;
    const char *end = src + *slen;

    for (; s < end; ++d, ++s) {
        switch (*s) {

        case '+':
            *d = ' ';
            break;

        case '%':
	    if (s + 2 < end && apr_isxdigit(s[1]) && apr_isxdigit(s[2]))
            {
                *d = hex2_to_char(s + 1);
                s += 2;
	    }
            else if (s + 5 < end && (s[1] == 'u' || s[1] == 'U') &&
                     apr_isxdigit(s[2]) && apr_isxdigit(s[3]) &&
                     apr_isxdigit(s[4]) && apr_isxdigit(s[5]))
            {
                apr_uint16_t c = hex4_to_bmp(s+2);

                if (c < 0x80) {
                    *d = c;
                }
                else if (c < 0x800) {
                    *d++ = 0xC0 | (c >> 6);
                    *d   = 0x80 | (c & 0x3F);
                }
                else {
                    *d++ = 0xE0 | (c >> 12);
                    *d++ = 0x80 | ((c >> 6) & 0x3F);
                    *d   = 0x80 | (c & 0x3F);
                }
                s += 5;
            }
	    else {
                *dlen = d - start;
                *slen = s - src;
                if (s + 5 < end
                    || (s + 2 < end && !apr_isxdigit(s[2]))
                    || (s + 1 < end && !apr_isxdigit(s[1])
                        && s[1] != 'u' && s[1] != 'U'))
                {
                    *d = 0;
                    return 1;
                }

                memmove(d, s, end - s);
                d[end - s] = 0;
                return 2;
	    }
            break;

        default:
            if (*s > 0) {
                *d = *s;
            }
            else {
                *d = 0;
                *dlen = d - start;
                *slen = s - src;
                return 1;
            }
        }
    }

    *d = 0;
    *dlen = d - start;
    *slen = s - src;
    return APR_SUCCESS;
}

APU_DECLARE(apr_size_t) apr_uri_query_string_encode(char *dest, const
char *src,
                                                    const apr_size_t slen)
{
    char *d = dest;
    const unsigned char *s = (const unsigned char *)src;
    unsigned char c;

    for ( ; s < (const unsigned char *)src + slen; ++s) {
        c = *s;
        if ( c < 0x80 && (apr_isalnum(c)
                          || c == '-' || c == '.'
                          || c == '_' || c == '~') )
            *d++ = c;

        else if ( c == ' ' )
            *d++ = '+';

        else {
#if APR_CHARSET_EBCDIC
            c = apr_xlate_conv_byte(ap_hdrs_to_ascii, (unsigned char)c);
#endif
            *d++ = '%';
            *d++ = c2x_table[c >> 4];
            *d++ = c2x_table[c & 0xf];
        }
    }
    *d = 0;

    return d - dest;
}


APU_DECLARE(apr_status_t) apr_uri_query_string_decode(char *d,
apr_size_t *dlen,
                                                      const char *s,
                                                      apr_size_t slen)
{
    apr_size_t len = 0;
    const char *end = s + slen;

    if (s == (const char *)d) {     /* optimize for src = dest case */
        for ( ; d < end; ++d) {
            if (*d == '%' || *d == '+')
                break;
            else if (*d == 0) {
                *dlen = (const char *)d - s;
                return -1;
            }
        }
        len = (const char *)d - s;
        s = (const char *)d;
        slen -= len;
    }

    return url_decode(d, dlen, s, &slen);
}



david

http://feathercast.org/

Mime
View raw message