More code taken from apreq - this time more modified to fit with apr and
even with a test case!
Really out the door this time :-)
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. 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;
+ * @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("ed, 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;
+}
--
david
http://feathercast.org/