r9339: treat arrays of uint8 values as a special DATA_BLOB type in the ejs
[ira/wip.git] / source / scripting / ejs / mprutil.c
index 3c28cb4bf1865cddd86ec0ad30f752f394b04dfb..700185f07e6867382f8b51d4c39de50e6b42bd97 100644 (file)
 */
 
 #include "includes.h"
-#include "lib/ejs/ejs.h"
+#include "lib/appweb/ejs/ejs.h"
 #include "lib/ldb/include/ldb.h"
 
+/*
+  return a default mpr object
+*/
+struct MprVar mprObject(const char *name)
+{
+       return ejsCreateObj(name && *name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE);
+}
+
 /*
   find a mpr component, allowing for sub objects, using the '.' convention
 */
@@ -75,7 +83,7 @@
        }
        v2 = mprGetProperty(v, objname, NULL);
        if (v2 == NULL) {
-               mprSetVar(v, objname, mprCreateObjVar(objname, MPR_DEFAULT_HASH_SIZE));
+               mprSetVar(v, objname, mprObject(objname));
                v2 = mprGetProperty(v, objname, NULL);
        }
        status = mprSetVar(v2, p+1, val);
 /*
   add an indexed array element to a property
 */
-static void mprAddArray(struct MprVar *var, int i, struct MprVar v)
+ void mprAddArray(struct MprVar *var, int i, struct MprVar v)
 {
        char idx[16];
        mprItoa(i, idx, sizeof(idx));
        mprSetVar(var, idx, v);
+       mprSetVar(var, "length", mprCreateIntegerVar(i+1));
 }
 
 /*
@@ -103,13 +112,27 @@ struct MprVar mprList(const char *name, const char **list)
        struct MprVar var;
        int i;
 
-       var = mprCreateObjVar(name, MPR_DEFAULT_HASH_SIZE);
+       var = mprObject(name);
        for (i=0;list && list[i];i++) {
-               mprAddArray(&var, i, mprCreateStringVar(list[i], 1));
+               mprAddArray(&var, i, mprString(list[i]));
+       }
+       if (i==0) {
+               mprSetVar(&var, "length", mprCreateIntegerVar(i));
        }
        return var;
 }
 
+/*
+  construct a MprVar from a string, using NULL if needed
+*/
+struct MprVar mprString(const char *s)
+{
+       if (s == NULL) {
+               return mprCreatePtrVar(NULL);
+       }
+       return mprCreateStringVar(s, True);
+}
+
 /*
   construct a string MprVar from a lump of data
 */
@@ -120,7 +143,7 @@ struct MprVar mprData(const uint8_t *p, size_t length)
        if (s == NULL) {
                return mprCreateUndefinedVar();
        }
-       var = mprCreateStringVar(s, 1);
+       var = mprString(s);
        talloc_free(s);
        return var;
 }
@@ -128,7 +151,7 @@ struct MprVar mprData(const uint8_t *p, size_t length)
 /*
   turn a ldb_message into a ejs object variable
 */
-struct MprVar mprLdbMessage(struct ldb_message *msg)
+static struct MprVar mprLdbMessage(struct ldb_context *ldb, struct ldb_message *msg)
 {
        struct MprVar var;
        int i;
@@ -138,21 +161,34 @@ struct MprVar mprLdbMessage(struct ldb_message *msg)
        const char *multivalued[] = { "objectClass", "memberOf", "privilege", 
                                            "member", NULL };
 
-       var = mprCreateObjVar(msg->dn, MPR_DEFAULT_HASH_SIZE);
+       var = mprObject(msg->dn);
 
        for (i=0;i<msg->num_elements;i++) {
                struct ldb_message_element *el = &msg->elements[i];
                struct MprVar val;
+               const struct ldb_attrib_handler *attr;
+               struct ldb_val v;
+
+               attr = ldb_attrib_handler(ldb, el->name);
+               if (attr == NULL) {
+                       goto failed;
+               }
+
                if (el->num_values == 1 &&
                    !str_list_check_ci(multivalued, el->name)) {
-                       val = mprData(el->values[0].data, el->values[0].length);
+                       if (attr->ldif_write_fn(ldb, msg, &el->values[0], &v) != 0) {
+                               goto failed;
+                       }
+                       val = mprData(v.data, v.length);
                } else {
                        int j;
-                       val = mprCreateObjVar(el->name, MPR_DEFAULT_HASH_SIZE);
+                       val = mprObject(el->name);
                        for (j=0;j<el->num_values;j++) {
-                               mprAddArray(&val, j, 
-                                           mprData(el->values[j].data, 
-                                                   el->values[j].length));
+                               if (attr->ldif_write_fn(ldb, msg, 
+                                                       &el->values[j], &v) != 0) {
+                                       goto failed;
+                               }
+                               mprAddArray(&val, j, mprData(v.data, v.length));
                        }
                }
                mprSetVar(&var, el->name, val);
@@ -160,27 +196,32 @@ struct MprVar mprLdbMessage(struct ldb_message *msg)
 
        /* add the dn if it is not already specified */
        if (mprGetProperty(&var, "dn", 0) == 0) {
-               mprSetVar(&var, "dn", mprCreateStringVar(msg->dn, 1));
+               mprSetVar(&var, "dn", mprString(msg->dn));
        }
        
        return var;             
+failed:
+       return mprCreateUndefinedVar();
 }
 
 
 /*
   turn an array of ldb_messages into a ejs object variable
 */
-struct MprVar mprLdbArray(struct ldb_message **msg, int count, const char *name)
+struct MprVar mprLdbArray(struct ldb_context *ldb, 
+                         struct ldb_message **msg, int count, const char *name)
 {
        struct MprVar res;
        int i;
 
-       res = mprCreateObjVar(name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE);
+       res = mprObject(name);
        for (i=0;i<count;i++) {
-               mprAddArray(&res, i, mprLdbMessage(msg[i]));
+               mprAddArray(&res, i, mprLdbMessage(ldb, msg[i]));
+       }
+       if (i==0) {
+               mprSetVar(&res, "length", mprCreateIntegerVar(0));
        }
-       mprSetPropertyValue(&res, "length", mprCreateIntegerVar(i));
-       return res;     
+       return res;
 }
 
 
@@ -189,7 +230,7 @@ struct MprVar mprLdbArray(struct ldb_message **msg, int count, const char *name)
  */
 const char *mprToString(const struct MprVar *v)
 {
-       if (v->type != MPR_TYPE_STRING) return NULL;
+       if (!mprVarIsString(v->type)) return NULL;
        return v->string;
 }
 
@@ -198,8 +239,8 @@ const char *mprToString(const struct MprVar *v)
  */
 int mprToInt(const struct MprVar *v)
 {
-       if (v->type != MPR_TYPE_INT) return 0;
-       return v->integer;
+       if (!mprVarIsNumber(v->type)) return 0;
+       return mprVarToNumber(v);
 }
 
 /*
@@ -227,6 +268,38 @@ const char **mprToList(TALLOC_CTX *mem_ctx, struct MprVar *v)
        return list;
 }
 
+
+/*
+  turn a MprVar object variable into a string list
+  this assumes the object variable is an array of strings
+*/
+const char **mprToArray(TALLOC_CTX *mem_ctx, struct MprVar *v)
+{
+       const char **list = NULL;
+       struct MprVar *len;
+       int length, i;
+
+       len = mprGetProperty(v, "length", NULL);
+       if (len == NULL) {
+               return NULL;
+       }
+       length = mprToInt(len);
+
+       for (i=0;i<length;i++) {
+               char idx[16];
+               struct MprVar *vs;
+               mprItoa(i, idx, sizeof(idx));           
+               vs = mprGetProperty(v, idx, NULL);
+               if (vs == NULL || vs->type != MPR_TYPE_STRING) {
+                       talloc_free(list);
+                       return NULL;
+               }
+               list = str_list_add(list, mprToString(vs));
+       }
+       talloc_steal(mem_ctx, list);
+       return list;
+}
+
 /*
   turn a NTSTATUS into a MprVar object with lots of funky properties
 */
@@ -234,9 +307,9 @@ struct MprVar mprNTSTATUS(NTSTATUS status)
 {
        struct MprVar res;
 
-       res = mprCreateObjVar("ntstatus", MPR_DEFAULT_HASH_SIZE);
+       res = mprObject("ntstatus");
 
-       mprSetVar(&res, "errstr", mprCreateStringVar(nt_errstr(status), 1));
+       mprSetVar(&res, "errstr", mprString(nt_errstr(status)));
        mprSetVar(&res, "v", mprCreateIntegerVar(NT_STATUS_V(status)));
        mprSetVar(&res, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status)));
        mprSetVar(&res, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status)));
@@ -244,6 +317,31 @@ struct MprVar mprNTSTATUS(NTSTATUS status)
        return res;
 }
 
+/*
+  create a data-blob in a mpr variable
+*/
+struct MprVar mprDataBlob(DATA_BLOB blob)
+{
+       struct MprVar res;
+       struct data_blob *pblob = talloc(mprMemCtx(), struct data_blob);
+       *pblob = data_blob_talloc(pblob, blob.data, blob.length);
+
+       res = mprObject("DATA_BLOB");
+
+       mprSetVar(&res, "size", mprCreateIntegerVar(blob.length));
+       mprSetPtrChild(&res, "blob", pblob);
+
+       return res;
+}
+
+/*
+  return a data blob from a mpr var created using mprDataBlob
+*/
+struct data_blob *mprToDataBlob(struct MprVar *v)
+{
+       return talloc_get_type(mprGetPtr(v, "blob"), struct data_blob);
+}
+
 /*
   turn a WERROR into a MprVar object with lots of funky properties
 */
@@ -251,9 +349,9 @@ struct MprVar mprWERROR(WERROR status)
 {
        struct MprVar res;
 
-       res = mprCreateObjVar("werror", MPR_DEFAULT_HASH_SIZE);
+       res = mprObject("werror");
 
-       mprSetVar(&res, "errstr", mprCreateStringVar(win_errstr(status), 1));
+       mprSetVar(&res, "errstr", mprString(win_errstr(status)));
        mprSetVar(&res, "v", mprCreateIntegerVar(W_ERROR_V(status)));
        mprSetVar(&res, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status)));
        mprSetVar(&res, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status)));
@@ -267,7 +365,16 @@ struct MprVar mprWERROR(WERROR status)
 */
 void mprSetPtr(struct MprVar *v, const char *propname, const void *p)
 {
-       mprSetVar(v, propname, mprCreatePtrVar(discard_const(p), NULL));
+       mprSetVar(v, propname, mprCreatePtrVar(discard_const(p)));
+}
+
+/*
+  set a pointer in a existing MprVar, making it a child of the property
+*/
+void mprSetPtrChild(struct MprVar *v, const char *propname, const void *p)
+{
+       mprSetVar(v, propname, mprCreatePtrVar(discard_const(p)));
+       talloc_steal(mprGetProperty(v, propname, NULL), p);
 }
 
 /*
@@ -300,7 +407,54 @@ void *mprGetPtr(struct MprVar *v, const char *propname)
 */
 void mpr_ReturnString(int eid, const char *s)
 { 
-       mpr_Return(eid, mprCreateStringVar(s, False));
+       mpr_Return(eid, mprString(s));
 }
 
 
+/*
+  set a C function in a variable
+*/
+ void mprSetCFunction(struct MprVar *obj, const char *name, MprCFunction fn)
+{
+       mprSetVar(obj, name, mprCreateCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE));
+}
+
+/*
+  set a string C function in a variable
+*/
+ void mprSetStringCFunction(struct MprVar *obj, const char *name, MprStringCFunction fn)
+{
+       mprSetVar(obj, name, mprCreateStringCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE));
+}
+
+/*
+  get a pointer in the current object
+*/
+void *mprGetThisPtr(int eid, const char *name)
+{
+       struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
+       return mprGetPtr(this, name);
+}
+
+/*
+  set a pointer as a child of the local object
+*/
+void mprSetThisPtr(int eid, const char *name, void *ptr)
+{
+       struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0);
+       mprSetPtrChild(this, name, ptr);
+}
+
+/*
+  used by object xxx_init() routines to allow for the caller
+  to supply a pre-existing object to add properties to,
+  or create a new object. This makes inheritance easy
+*/
+struct MprVar *mprInitObject(int eid, const char *name, int argc, struct MprVar **argv)
+{
+       if (argc > 0 && mprVarIsObject(argv[0]->type)) {
+               return argv[0];
+       }
+       mpr_Return(eid, mprObject(name));
+       return ejsGetReturnValue(eid);
+}