Move string manipulation functions from xlat.c to rlm_expr
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 20 Sep 2012 12:55:08 +0000 (13:55 +0100)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Thu, 20 Sep 2012 12:59:27 +0000 (13:59 +0100)
src/main/xlat.c
src/modules/rlm_expr/rlm_expr.c

index 3d45a07..90081e7 100644 (file)
@@ -26,7 +26,6 @@
 RCSID("$Id$")
 
 #include       <freeradius-devel/radiusd.h>
-#include       <freeradius-devel/md5.h>
 #include       <freeradius-devel/rad_assert.h>
 
 #include       <ctype.h>
@@ -591,99 +590,6 @@ static size_t xlat_debug(UNUSED void *instance, REQUEST *request,
        return strlen(out);
 }
 
-
-/*
- *     Calculate the MD5 hash of a string.
- */
-static size_t xlat_md5(UNUSED void *instance, REQUEST *request,
-                      char *fmt, char *out, size_t outlen,
-                      UNUSED RADIUS_ESCAPE_STRING func)
-{
-       int i;
-       uint8_t digest[16];
-       FR_MD5_CTX ctx;
-       char buffer[1024];
-
-       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
-               *out = '\0';
-               return 0;
-       }
-
-       fr_MD5Init(&ctx);
-       fr_MD5Update(&ctx, (void *) buffer, strlen(buffer));
-       fr_MD5Final(digest, &ctx);
-
-       if (outlen < 33) {
-               snprintf(out, outlen, "md5_overflow");
-               return strlen(out);
-       }
-
-       for (i = 0; i < 16; i++) {
-               snprintf(out + i * 2, 3, "%02x", digest[i]);
-       }
-
-       return strlen(out);
-}
-
-
-/*
- *     Convert a string to lowercase
- */
-static size_t xlat_lc(UNUSED void *instance, REQUEST *request,
-                      char *fmt, char *out, size_t outlen,
-                      UNUSED RADIUS_ESCAPE_STRING func)
-{
-       char *p, *q;
-       char buffer[1024];
-
-       if (outlen <= 1) return 0;
-
-       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
-               *out = '\0';
-               return 0;
-       }
-
-       for (p = buffer, q = out; *p != '\0'; p++, outlen--) {
-               if (outlen <= 1) break;
-
-               *(q++) = tolower((int) *p);
-       }
-
-       *q = '\0';
-
-       return strlen(out);
-}
-
-
-/*
- *     Convert a string to uppercase
- */
-static size_t xlat_uc(UNUSED void *instance, REQUEST *request,
-                      char *fmt, char *out, size_t outlen,
-                      UNUSED RADIUS_ESCAPE_STRING func)
-{
-       char *p, *q;
-       char buffer[1024];
-
-       if (outlen <= 1) return 0;
-
-       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
-               *out = '\0';
-               return 0;
-       }
-
-       for (p = buffer, q = out; *p != '\0'; p++, outlen--) {
-               if (outlen <= 1) break;
-
-               *(q++) = toupper((int) *p);
-       }
-
-       *q = '\0';
-
-       return strlen(out);
-}
-
-
 /*
  *     Compare two xlat_t structs, based ONLY on the module name.
  */
@@ -791,21 +697,6 @@ int xlat_register(const char *module, RAD_XLAT_FUNC func, void *instance)
                c = xlat_find("debug");
                rad_assert(c != NULL);
                c->internal = TRUE;
-
-               xlat_register("md5", xlat_md5, &xlat_inst[0]);
-               c = xlat_find("md5");
-               rad_assert(c != NULL);
-               c->internal = TRUE;
-
-               xlat_register("tolower", xlat_lc, &xlat_inst[0]);
-               c = xlat_find("tolower");
-               rad_assert(c != NULL);
-               c->internal = TRUE;
-
-               xlat_register("toupper", xlat_uc, &xlat_inst[0]);
-               c = xlat_find("toupper");
-               rad_assert(c != NULL);
-               c->internal = TRUE;
        }
 
        /*
index 2e57110..10411d0 100644 (file)
 RCSID("$Id$")
 
 #include <freeradius-devel/radiusd.h>
+#include <freeradius-devel/md5.h>
 #include <freeradius-devel/modules.h>
+
+#include <ctype.h>
+
 #include "rlm_expr.h"
 
 /*
@@ -407,6 +411,159 @@ static size_t randstr_xlat(UNUSED void *instance, REQUEST *request,
        return outlen - freespace;
 }
 
+/**
+ * @brief URLencode special characters 
+ *
+ * Example: "%{urlquote:http://example.org/}" == "http%3A%47%47example.org%47"
+ */
+static size_t urlquote_xlat(UNUSED void *instance, REQUEST *request,
+                           const char *fmt, char *out, size_t outlen,
+                           UNUSED RADIUS_ESCAPE_STRING func)
+{
+       char    *p;
+       char    buffer[1024];
+       size_t  freespace = outlen;
+       size_t  len;
+       
+       if (outlen <= 1) return 0;
+
+       len = radius_xlat(buffer, sizeof(buffer), fmt, request, func);
+       if (!len) {
+               radlog(L_ERR, "rlm_expr: xlat failed.");
+               *out = '\0';
+               return 0;
+       }
+
+       p = buffer;
+       while ((len-- > 0) && (--freespace > 0)) {
+               if (isalnum(*p)) {
+                       *out++ = *p++;
+                       continue;
+               }
+
+               switch (*p) {
+                       case '-':
+                       case '_':
+                       case '.':
+                       case '~':
+                               *out++ = *p++;
+                               break;
+                       default:
+                               if (freespace < 3)
+                                       break;
+                               
+                               snprintf(out, 4, "%%%02x", *p++); /* %xx */
+                               
+                               /* Already decremented */
+                               freespace -= 2;
+                               out += 3;
+               }
+       }
+
+       *out = '\0';
+
+       return outlen - freespace;
+}
+
+/**
+ * @brief Convert a string to lowercase
+ *
+ * Example "%{lc:Bar}" == "bar"
+ *
+ * Probably only works for ASCII
+ */
+static size_t lc_xlat(UNUSED void *instance, REQUEST *request,
+                     const char *fmt, char *out, size_t outlen,
+                     UNUSED RADIUS_ESCAPE_STRING func)
+{
+       char *p, *q;
+       char buffer[1024];
+
+       if (outlen <= 1) return 0;
+
+       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
+               *out = '\0';
+               return 0;
+       }
+
+       for (p = buffer, q = out; *p != '\0'; p++, outlen--) {
+               if (outlen <= 1) break;
+
+               *(q++) = tolower((int) *p);
+       }
+
+       *q = '\0';
+
+       return strlen(out);
+}
+
+/**
+ * @brief Convert a string to uppercase
+ *
+ * Example: "%{uc:Foo}" == "FOO"
+ *
+ * Probably only works for ASCII
+ */
+static size_t uc_xlat(UNUSED void *instance, REQUEST *request,
+                     const char *fmt, char *out, size_t outlen,
+                     UNUSED RADIUS_ESCAPE_STRING func)
+{
+       char *p, *q;
+       char buffer[1024];
+
+       if (outlen <= 1) return 0;
+
+       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
+               *out = '\0';
+               return 0;
+       }
+
+       for (p = buffer, q = out; *p != '\0'; p++, outlen--) {
+               if (outlen <= 1) break;
+
+               *(q++) = toupper((int) *p);
+       }
+
+       *q = '\0';
+
+       return strlen(out);
+}
+
+/**
+ * @brief Calculate the MD5 hash of a string.
+ *
+ * Example: "%{md5:foo}" == "acbd18db4cc2f85cedef654fccc4a4d8"
+ */
+static size_t md5_xlat(UNUSED void *instance, REQUEST *request,
+                      const char *fmt, char *out, size_t outlen,
+                      UNUSED RADIUS_ESCAPE_STRING func)
+{
+       char buffer[1024];
+       uint8_t digest[16];
+       int i;
+       FR_MD5_CTX ctx;
+
+       if (!radius_xlat(buffer, sizeof(buffer), fmt, request, func)) {
+               *out = '\0';
+               return 0;
+       }
+
+       fr_MD5Init(&ctx);
+       fr_MD5Update(&ctx, (void *) buffer, strlen(buffer));
+       fr_MD5Final(digest, &ctx);
+
+       if (outlen < 33) {
+               snprintf(out, outlen, "md5_overflow");
+               return strlen(out);
+       }
+
+       for (i = 0; i < 16; i++) {
+               snprintf(out + i * 2, 3, "%02x", digest[i]);
+       }
+
+       return strlen(out);
+}
+
 /*
  *     Do any per-module initialization that is separate to each
  *     configured instance of the module.  e.g. set up connections
@@ -441,6 +598,10 @@ static int expr_instantiate(CONF_SECTION *conf, void **instance)
 
        xlat_register("rand", rand_xlat, inst);
        xlat_register("randstr", randstr_xlat, inst);
+       xlat_register("urlquote", urlquote_xlat, inst);
+       xlat_register("tolower", lc_xlat, inst);
+       xlat_register("toupper", uc_xlat, inst);
+       xlat_register("md5", md5_xlat, inst);
 
        /*
         * Initialize various paircompare functions