r9756: One-way upgrade from Samba3->Samba4 basically works now
[sfrench/samba-autobuild/.git] / source4 / scripting / ejs / smbcalls_string.c
index 7a19ecdf2cabaae78dd9771a443277f1884bfd46..e127cdf8af8f7291212587b3c4a7122f2d50eb73 100644 (file)
@@ -4,6 +4,7 @@
    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
 
 #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,6 +73,22 @@ 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:
      list = split(".", "a.foo.bar");
@@ -95,6 +125,61 @@ 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]);
+       if (start_offset < 0) start_offset += strlen(orig);
+       if (start_offset < 0 || start_offset > strlen(orig)) {
+               ejsSetErrorMsg(eid, "substr arg 2 out of bounds");
+               return -1;
+       }
+
+       if (argc == 3) {
+               length = mprToInt(argv[1]);
+               if (length < 0) length += strlen(orig) - start_offset;
+               if (length < 0 || length+start_offset > strlen(orig)) {
+                       ejsSetErrorMsg(eid, "substr arg 3 out of bounds");
+                       return -1;
+               }
+       } else {
+               length = strlen(orig);
+       }
+
+       target = talloc_strndup(mprMemCtx(), orig+start_offset, length);
+       
+       mpr_Return(eid, mprString(target));
+
+       talloc_free(target);
+
+       return 0;
+}
 
 /*
   usage:
@@ -184,7 +269,7 @@ 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) {
@@ -271,14 +356,146 @@ 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_size(mprMemCtx(), 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_size(mprMemCtx(), 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, "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)
 {
-       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);
 }