apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Max Bowsher <ma...@ukf.net>
Subject Re: apr_quote
Date Wed, 02 Aug 2006 18:05:00 GMT
david reid wrote:
> Index: include/apr_strings.h
> ===================================================================
> --- include/apr_strings.h       (revision 416632)
> +++ include/apr_strings.h       (working copy)
> @@ -348,6 +348,35 @@
>   */
>  APR_DECLARE(char *) apr_strfsize(apr_off_t size, char *buf);
> 
> +/**
> + * @fn apr_status_t apr_quote_once(char **dest, const char *src,
> +                                    const apr_size_t slen,
> +                                    apr_pool_t *pool)
> + * @brief Quote the supplied string.

The biggest problem here is: What does "quote" mean? It is a
sufficiently generic term that it doesn't really explain at all.

If it is 'quote for command line usage', then presumably it needs to be
implemented differently on Unix and Windows.

> This fucntion will check to see if
> + *        the string is already quoted before applying changes. It will
> + *        always return a copy of the string in *dest;

Why does it always copy? I think it should return the input pointer if
it knows it is doing nothing.

Also, is it possible to reliably tell whether something is quoted or
not? I think the existence of quoting implies you could be quoting
something that looks quoted to preserve the first quotes from
interpretation as quotes.

If necessary, describe in the docstring that the function does a best
guess based on some heuristic, rather than making an accurate determination.

> + * @param dest pointer to the pointer to the returned string
> + * @param src string to be quoted
> + * @param slen length of string to be quoted
> + * @param pool the pool to use for memory allocation
> + */
> +APR_DECLARE(apr_status_t) apr_quote_once(char **, const char *,
> +                                         const apr_size_t, apr_pool_t *);
> +
> +
> +/**
> + * @fn apr_status_t apr_quote(char **dest, const char *src,
> +                                    const apr_size_t slen,
> +                                    apr_pool_t *pool)
> + * @brief Quote the supplied string.
> + * @param dest pointer to the pointer to the returned string
> + * @param src string to be quoted
> + * @param slen length of string to be quoted
> + * @param pool the pool to use for memory allocation
> + */
> +APR_DECLARE(apr_status_t) apr_quote(char **, const char *,
> +                                    const apr_size_t, apr_pool_t *);
> +
>  /** @} */
> 
> Index: test/teststr.c
> ===================================================================
> --- test/teststr.c      (revision 416903)
> +++ test/teststr.c      (working copy)
> @@ -363,6 +363,25 @@
>      ABTS_TRUE(tc, ret[1] == 'Z');
>  }
> 
> +static void string_quote(abts_case *tc, void *data)
> +{
> +    char *plain = "hello \"world\"";
> +    char *quoted = NULL, *qquoted = NULL;
> +    int rv;
> +    char *res = "\"\\\"hello \\\\\\\"world\\\\\\\"\\\"\"";
> +
> +    rv = apr_quote(&quoted, plain, 13, p);
> +    ABTS_INT_EQUAL(tc, rv, APR_SUCCESS);
> +    ABTS_STR_EQUAL(tc, "\"hello \\\"world\\\"\"", quoted);
> +    rv = apr_quote_once(&qquoted, quoted, 17, p);
> +    ABTS_INT_EQUAL(tc, rv, APR_SUCCESS);
> +    ABTS_STR_EQUAL(tc, "\"hello \\\"world\\\"\"", qquoted);
> +    rv = apr_quote(&qquoted, quoted, 17, p);
> +    ABTS_INT_EQUAL(tc, rv, APR_SUCCESS);
> +    ABTS_STR_EQUAL(tc, res, qquoted);
> +
> +}
> +
>  abts_suite *teststr(abts_suite *suite)
>  {
>      suite = ADD_SUITE(suite)
> @@ -379,6 +398,7 @@
>      abts_run_test(suite, overflow_strfsize, NULL);
>      abts_run_test(suite, string_strfsize, NULL);
>      abts_run_test(suite, string_cpystrn, NULL);
> +    abts_run_test(suite, string_quote, NULL);
> 
>      return suite;
>  }
> 
> --- strings/apr_quote.c (revision 0)
> +++ strings/apr_quote.c (revision 0)
> @@ -0,0 +1,106 @@
> +/* Copyright 2006 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.
> + */
> +
> +#include "apr.h"
> +#include "apr_strings.h"
> +#include "apr_private.h"
> +#include "apr_lib.h"
> +
> +#if APR_HAVE_SYS_TYPES_H
> +#include <sys/types.h>
> +#endif
> +#if APR_HAVE_STRING_H
> +#include <string.h>
> +#endif
> +#if APR_HAVE_CTYPE_H
> +#include <ctype.h>
> +#endif
> +
> +static int is_quoted(const char *p, const apr_size_t len)
> +{
> +    if (len > 1 && p[0] == '"' && p[len-1] == '"') {
> +        apr_size_t i;
> +        int backslash = 0;
> +
> +        for (i = 1; i < len - 1; i++) {
> +            if (p[i] == '\\')
> +                backslash = !backslash;
> +            else if (p[i] == 0 || (p[i] == '"' && !backslash))
> +                return 0;
> +            else
> +                backslash = 0;
> +        }
> +
> +        return !backslash;
> +    }
> +
> +    return 0;
> +}
> +
> +APR_DECLARE(apr_status_t) apr_quote_once(char **dest,
> +                                         const char *src,
> +                                         const apr_size_t slen,
> +                                         apr_pool_t *pool)
> +{
> +    if (is_quoted(src, slen)) {
> +        *dest = apr_pstrndup(pool, src, slen);
> +        return APR_SUCCESS;
> +    }
> +    return apr_quote(dest, src, slen, pool);
> +}
> +
> +APR_DECLARE(apr_status_t) apr_quote(char **dest, const char *src,
> +                                    const apr_size_t slen,
> +                                    apr_pool_t *pool)
> +{
> +    char *d = *dest;
> +    const char *s = src;
> +    const char *const last = src + slen - 1;
> +    int needed = 0;
> +
> +    *dest = NULL;
> +    if (slen == 0)
> +        return APR_EINVAL;
> +
> +    /* 2 pass - messy - better ways? */
> +    while (s <= last) {
> +        if (*s == '\\' || *s == '"' || *s == 0)
> +            needed++;
> +        s++;
> +    }
> +
> +    *dest = (char *)apr_pcalloc(pool, slen + needed + 3);
> +    d = *dest;
> +    s = src;
> +    *d++ = '"';
> +    while (s <= last) {
> +        switch (*s) {
> +            case 0:
> +                *d++ = '\\';
> +                *d++ = '0';
> +                s++;
> +                break;
> +            case '\\':
> +            case '"':
> +                *d++ = '\\';
> +            default:
> +                *d++ = *s++;
> +        }
> +    }
> +    *d++ = '"';
> +
> +    return APR_SUCCESS;
> +}
> 
> 



Mime
View raw message