Let winbind depend directly on libnet rather than through the ejs bindings.
[samba.git] / source4 / scripting / ejs / smbcalls_string.c
index 7a19ecdf2cabaae78dd9771a443277f1884bfd46..541303ff2d0ecf3d9b920b9f4f1eb68c1d4abe8c 100644 (file)
@@ -4,10 +4,11 @@
    provide access to string functions
 
    Copyright (C) Andrew Tridgell 2005
+   Copyright (C) Jelmer Vernooij 2005 (substr)
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "scripting/ejs/smbcalls.h"
-#include "lib/ejs/ejs.h"
-#include "system/passwd.h"
+#include "lib/appweb/ejs/ejs.h"
+
+/*
+  usage:
+      var len = strlen(str);
+*/
+static int ejs_strlen(MprVarHandle eid, int argc, char **argv)
+{
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "strlen invalid arguments");
+               return -1;
+       }
+       mpr_Return(eid, mprCreateIntegerVar(strlen_m(argv[0])));
+       return 0;
+}
 
 /*
   usage:
@@ -59,33 +72,76 @@ static int ejs_strupper(MprVarHandle eid, int argc, char **argv)
        return 0;
 }
 
+/*
+  usage:
+      var s = strstr(string, substring);
+*/
+static int ejs_strstr(MprVarHandle eid, int argc, char **argv)
+{
+       char *s;
+       if (argc != 2) {
+               ejsSetErrorMsg(eid, "strstr invalid arguments");
+               return -1;
+       }
+       s = strstr(argv[0], argv[1]);
+       mpr_Return(eid, mprString(s));
+       return 0;
+}
+
+/*
+  usage:
+      var s = strspn(string, legal_chars_string);
+*/
+static int ejs_strspn(MprVarHandle eid, int argc, char **argv)
+{
+        int len;
+       if (argc != 2) {
+               ejsSetErrorMsg(eid, "strspn invalid arguments");
+               return -1;
+       }
+       len = strspn(argv[0], argv[1]);
+       mpr_Return(eid, mprCreateIntegerVar(len));
+       return 0;
+}
+
 /*
   usage:
      list = split(".", "a.foo.bar");
+     list = split(".", "a.foo.bar", count);
 
-  NOTE: does not take a regular expression, unlink perl split()
+  count is an optional count of how many splits to make
+
+  NOTE: does not take a regular expression, unlike perl split()
 */
-static int ejs_split(MprVarHandle eid, int argc, char **argv)
+static int ejs_split(MprVarHandle eid, int argc, struct MprVar **argv)
 {
-       const char *separator;
-       char *s, *p;
+       const char *separator, *s;
+       char *p;
        struct MprVar ret;
-       int count = 0;
+       int count = 0, maxcount=0;
        TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
-       if (argc != 2) {
+       if (argc < 2 ||
+           argv[0]->type != MPR_TYPE_STRING ||
+           argv[1]->type != MPR_TYPE_STRING) {
                ejsSetErrorMsg(eid, "split invalid arguments");
                return -1;
        }
-       separator = argv[0];
-       s = argv[1];
+       separator = mprToString(argv[0]);
+       s         = mprToString(argv[1]);
+       if (argc == 3) {
+               maxcount = mprToInt(argv[2]);
+       }
 
-       ret = mprObject("list");
+       ret = mprArray("list");
 
        while ((p = strstr(s, separator))) {
                char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s));
                mprAddArray(&ret, count++, mprString(s2));
                talloc_free(s2);
                s = p + strlen(separator);
+               if (maxcount != 0 && count >= maxcount) {
+                       break;
+               }
        }
        if (*s) {
                mprAddArray(&ret, count++, mprString(s));
@@ -95,6 +151,60 @@ static int ejs_split(MprVarHandle eid, int argc, char **argv)
        return 0;
 }
 
+/*
+  usage:
+    str = substr(orig[, start_offset[, length]]);
+
+       special cases:
+               if start_offset < 0 then start_offset+=strlen(orig)
+               if length < 0 then length+=strlen(orig)-start_offset
+
+       (as found in many other languages)
+*/
+static int ejs_substr(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+       int start_offset = 0;
+       int length = 0;
+       const char *orig;
+       char *target;
+       
+       if (argc < 1 || argc > 3 ||
+           argv[0]->type != MPR_TYPE_STRING) {
+               ejsSetErrorMsg(eid, "substr invalid arguments");
+               return -1;
+       }
+
+       if (argc == 1) {
+               mpr_Return(eid, *argv[0]);
+               return 0;
+       }
+
+       orig = mprToString(argv[0]);
+       start_offset = mprToInt(argv[1]);
+       length = strlen(orig);
+       if (start_offset < 0) start_offset += strlen(orig);
+       if (start_offset < 0 || start_offset > strlen(orig)) {
+               ejsSetErrorMsg(eid, "substr arg 2 out of bounds ([%s], %d)", orig, start_offset);
+               return -1;
+       }
+
+       if (argc == 3) {
+               length = mprToInt(argv[2]);
+               if (length < 0) length += strlen(orig) - start_offset;
+               if (length < 0 || length+start_offset > strlen(orig)) {
+                       ejsSetErrorMsg(eid, "substr arg 3 out of bounds ([%s], %d, %d)", orig, start_offset, length);
+                       return -1;
+               }
+       }
+
+       target = talloc_strndup(mprMemCtx(), orig+start_offset, length);
+       
+       mpr_Return(eid, mprString(target));
+
+       talloc_free(target);
+
+       return 0;
+}
 
 /*
   usage:
@@ -128,7 +238,7 @@ static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv)
                goto failed;
        }
        for (i=1;list[i];i++) {
-               ret = talloc_asprintf_append(ret, "%s%s", separator, list[i]);
+               ret = talloc_asprintf_append_buffer(ret, "%s%s", separator, list[i]);
                if (ret == NULL) {
                        goto failed;
                }
@@ -147,13 +257,14 @@ failed:
   usage:
      str = sprintf("i=%d s=%7s", 7, "foo");
 */
+typedef char *(*_asprintf_append_t)(char *, const char *, ...);
 static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
 {
        const char *format;
        const char *p;
        char *ret;
        int a = 1;
-       char *(*_asprintf_append)(char *, const char *, ...);
+       _asprintf_append_t _asprintf_append;
        TALLOC_CTX *tmp_ctx;
        if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) {
                ejsSetErrorMsg(eid, "sprintf invalid arguments");
@@ -164,7 +275,7 @@ static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
        ret = talloc_strdup(tmp_ctx, "");
 
        /* avoid all the format string warnings */
-       _asprintf_append = talloc_asprintf_append;
+       _asprintf_append = (_asprintf_append_t)talloc_asprintf_append_buffer;
 
        /*
          hackity hack ...
@@ -173,7 +284,7 @@ static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
                char *fmt2;
                int len, len_count=0;
                char *tstr;
-               ret = talloc_asprintf_append(ret, "%*.*s", 
+               ret = talloc_asprintf_append_buffer(ret, "%*.*s", 
                                             (int)(p-format), (int)(p-format), 
                                             format);
                if (ret == NULL) goto failed;
@@ -184,11 +295,11 @@ static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
                len_count = count_chars(fmt2, '*');
                /* find the type string */
                tstr = &fmt2[len];
-               while (tstr > fmt2 && isalpha(tstr[-1])) {
+               while (tstr > fmt2 && isalpha((unsigned char)tstr[-1])) {
                        tstr--;
                }
                if (strcmp(tstr, "%") == 0) {
-                       ret = talloc_asprintf_append(ret, "%%");
+                       ret = talloc_asprintf_append_buffer(ret, "%%");
                        if (ret == NULL) {
                                goto failed;
                        }
@@ -261,7 +372,7 @@ static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
                format += len+1;
        }
 
-       ret = talloc_asprintf_append(ret, "%s", format);
+       ret = talloc_asprintf_append_buffer(ret, "%s", format);
        mpr_Return(eid, mprString(ret));
        talloc_free(tmp_ctx);
        return 0;          
@@ -271,14 +382,148 @@ failed:
        return -1;
 }
 
+/*
+  used to build your own print function
+     str = vsprintf(args);
+*/
+static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+       struct MprVar **args, *len, *v;
+       int i, ret, length;
+       if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
+               ejsSetErrorMsg(eid, "vsprintf invalid arguments");
+               return -1;
+       }
+       v = argv[0];
+       len = mprGetProperty(v, "length", NULL);
+       if (len == NULL) {
+               ejsSetErrorMsg(eid, "vsprintf takes an array");
+               return -1;
+       }
+       length = mprToInt(len);
+       args = talloc_array(mprMemCtx(), struct MprVar *, length);
+       if (args == NULL) {
+               return -1;
+       }
+
+       for (i=0;i<length;i++) {
+               char idx[16];
+               mprItoa(i, idx, sizeof(idx));
+               args[i] = mprGetProperty(v, idx, NULL);
+       }
+       
+       ret = ejs_sprintf(eid, length, args);
+       talloc_free(args);
+       return ret;
+}
+
+
+/*
+  encode a string, replacing all non-alpha with %02x form
+*/
+static int ejs_encodeURIComponent(MprVarHandle eid, int argc, char **argv)
+{
+       int i, j, count=0;
+       const char *s;
+       char *ret;
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "encodeURIComponent invalid arguments");
+               return -1;
+       }
+       
+       s = argv[0];
+
+       for (i=0;s[i];i++) {
+               if (!isalnum(s[i])) count++;
+       }
+       
+       ret = talloc_array(mprMemCtx(), char, i + count*2 + 1);
+       if (ret == NULL) {
+               return -1;
+       }
+       for (i=j=0;s[i];i++,j++) {
+               if (!isalnum(s[i])) {
+                       snprintf(ret+j, 4, "%%%02X", (unsigned)s[i]);
+                       j += 2;
+               } else {
+                       ret[j] = s[i];
+               }
+       }
+       ret[j] = 0;
+       mpr_Return(eid, mprString(ret));
+       talloc_free(ret);
+       return 0;
+}
+
+/*
+  encode a string, replacing all non-alpha of %02x form
+*/
+static int ejs_decodeURIComponent(MprVarHandle eid, int argc, char **argv)
+{
+       int i, j, count=0;
+       const char *s;
+       char *ret;
+       if (argc != 1) {
+               ejsSetErrorMsg(eid, "decodeURIComponent invalid arguments");
+               return -1;
+       }
+       
+       s = argv[0];
+
+       ret = talloc_array(mprMemCtx(), char, strlen(s) + 1);
+       if (ret == NULL) {
+               return -1;
+       }
+
+       for (i=j=0;s[i];i++,j++) {
+               if (s[i] == '%') {
+                       unsigned c;
+                       if (sscanf(s+i+1, "%02X", &c) != 1) {
+                               ejsSetErrorMsg(eid, "decodeURIComponent bad format");
+                               return -1;
+                       }
+                       ret[j] = c;
+                       i += 2;
+               } else {
+                       ret[j] = s[i];
+               }
+               if (!isalnum(s[i])) count++;
+       }
+       
+       ret[j] = 0;
+       mpr_Return(eid, mprString(ret));
+       talloc_free(ret);
+       return 0;
+}
+
+/*
+  initialise string ejs subsystem
+*/
+static int ejs_string_init(MprVarHandle eid, int argc, struct MprVar **argv)
+{
+       struct MprVar *obj = mprInitObject(eid, "string", argc, argv);
+
+       mprSetCFunction(obj, "substr", ejs_substr);
+       mprSetStringCFunction(obj, "strlen", ejs_strlen);
+       mprSetStringCFunction(obj, "strlower", ejs_strlower);
+       mprSetStringCFunction(obj, "strupper", ejs_strupper);
+       mprSetStringCFunction(obj, "strstr", ejs_strstr);
+       mprSetStringCFunction(obj, "strspn", ejs_strspn);
+       mprSetCFunction(obj, "split", ejs_split);
+       mprSetCFunction(obj, "join", ejs_join);
+       mprSetCFunction(obj, "sprintf", ejs_sprintf);
+       mprSetCFunction(obj, "vsprintf", ejs_vsprintf);
+       mprSetStringCFunction(obj, "encodeURIComponent", ejs_encodeURIComponent);
+       mprSetStringCFunction(obj, "decodeURIComponent", ejs_decodeURIComponent);
+
+       return 0;
+}
+
 /*
   setup C functions that be called from ejs
 */
-void smb_setup_ejs_string(void)
+NTSTATUS smb_setup_ejs_string(void)
 {
-       ejsDefineStringCFunction(-1, "strlower", ejs_strlower, NULL, MPR_VAR_SCRIPT_HANDLE);
-       ejsDefineStringCFunction(-1, "strupper", ejs_strupper, NULL, MPR_VAR_SCRIPT_HANDLE);
-       ejsDefineStringCFunction(-1, "split", ejs_split, NULL, MPR_VAR_SCRIPT_HANDLE);
-       ejsDefineCFunction(-1, "join", ejs_join, NULL, MPR_VAR_SCRIPT_HANDLE);
-       ejsDefineCFunction(-1, "sprintf", ejs_sprintf, NULL, MPR_VAR_SCRIPT_HANDLE);
+       ejsDefineCFunction(-1, "string_init", ejs_string_init, NULL, MPR_VAR_SCRIPT_HANDLE);
+       return NT_STATUS_OK;
 }