2 Unix SMB/CIFS implementation.
4 utility functions for manipulating mpr variables in ejs calls
6 Copyright (C) Andrew Tridgell 2005
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "lib/appweb/ejs/ejs.h"
25 #include "lib/ldb/include/ldb.h"
26 #include "scripting/ejs/smbcalls.h"
29 return a default mpr object
31 struct MprVar
mprObject(const char *name
)
33 return ejsCreateObj(name
&& *name
?name
:"(NULL)", MPR_DEFAULT_HASH_SIZE
);
37 return a empty mpr array
39 struct MprVar
mprArray(const char *name
)
41 return ejsCreateArray(name
&& *name
?name
:"(NULL)", 0);
45 find a mpr component, allowing for sub objects, using the '.' convention
47 NTSTATUS
mprGetVar(struct MprVar
**v
, const char *name
)
49 const char *p
= strchr(name
, '.');
53 *v
= mprGetProperty(*v
, name
, NULL
);
55 DEBUG(1,("mprGetVar unable to find '%s'\n", name
));
56 return NT_STATUS_INVALID_PARAMETER
;
60 objname
= talloc_strndup(mprMemCtx(), name
, p
-name
);
61 NT_STATUS_HAVE_NO_MEMORY(objname
);
62 *v
= mprGetProperty(*v
, objname
, NULL
);
63 NT_STATUS_HAVE_NO_MEMORY(*v
);
64 status
= mprGetVar(v
, p
+1);
71 set a mpr component, allowing for sub objects, using the '.' convention
72 destroys 'val' after setting
74 NTSTATUS
mprSetVar(struct MprVar
*v
, const char *name
, struct MprVar val
)
76 const char *p
= strchr(name
, '.');
81 v2
= mprSetProperty(v
, name
, &val
);
83 DEBUG(1,("mprSetVar unable to set '%s'\n", name
));
84 return NT_STATUS_INVALID_PARAMETER_MIX
;
89 objname
= talloc_strndup(mprMemCtx(), name
, p
-name
);
90 if (objname
== NULL
) {
91 return NT_STATUS_NO_MEMORY
;
93 v2
= mprGetProperty(v
, objname
, NULL
);
95 mprSetVar(v
, objname
, mprObject(objname
));
96 v2
= mprGetProperty(v
, objname
, NULL
);
98 status
= mprSetVar(v2
, p
+1, val
);
106 add an indexed array element to a property
108 void mprAddArray(struct MprVar
*var
, int i
, struct MprVar v
)
111 mprItoa(i
, idx
, sizeof(idx
));
112 mprSetVar(var
, idx
, v
);
116 construct a MprVar from a list
118 struct MprVar
mprList(const char *name
, const char **list
)
123 var
= mprArray(name
);
124 for (i
=0;list
&& list
[i
];i
++) {
125 mprAddArray(&var
, i
, mprString(list
[i
]));
131 construct a MprVar from a string, using NULL if needed
133 struct MprVar
mprString(const char *s
)
136 return mprCreatePtrVar(NULL
);
138 return mprCreateStringVar(s
, True
);
142 construct a string MprVar from a lump of data
144 struct MprVar
mprData(const uint8_t *p
, size_t length
)
147 char *s
= talloc_strndup(mprMemCtx(), (const char *)p
, length
);
149 return mprCreateUndefinedVar();
157 turn a ldb_message into a ejs object variable
159 static struct MprVar
mprLdbMessage(struct ldb_context
*ldb
, struct ldb_message
*msg
)
163 /* we force some attributes to always be an array in the
164 returned structure. This makes the scripting easier, as you don't
165 need a special case for the single value case */
166 const char *multivalued
[] = { "objectClass", "memberOf", "privilege",
169 var
= mprObject(ldb_dn_alloc_linearized(msg
, msg
->dn
));
171 for (i
=0;i
<msg
->num_elements
;i
++) {
172 struct ldb_message_element
*el
= &msg
->elements
[i
];
174 const struct ldb_schema_attribute
*a
;
177 a
= ldb_schema_attribute_by_name(ldb
, el
->name
);
182 if (el
->num_values
== 1 &&
183 !str_list_check_ci(multivalued
, el
->name
)) {
184 if (a
->syntax
->ldif_write_fn(ldb
, msg
, &el
->values
[0], &v
) != 0) {
187 /* FIXME: nasty hack, remove me when ejs will support
188 * arbitrary string and does not truncate on \0 */
189 if (strlen((char *)v
.data
) != v
.length
) {
190 val
= mprDataBlob(v
);
192 val
= mprData(v
.data
, v
.length
);
196 val
= mprArray(el
->name
);
197 for (j
=0;j
<el
->num_values
;j
++) {
198 if (a
->syntax
->ldif_write_fn(ldb
, msg
,
199 &el
->values
[j
], &v
) != 0) {
202 /* FIXME: nasty hack, remove me when ejs will support
203 * arbitrary string and does not truncate on \0 */
204 if (strlen((char *)v
.data
) != v
.length
) {
205 mprAddArray(&val
, j
, mprDataBlob(v
));
207 mprAddArray(&val
, j
, mprData(v
.data
, v
.length
));
211 mprSetVar(&var
, el
->name
, val
);
214 /* add the dn if it is not already specified */
215 if (mprGetProperty(&var
, "dn", 0) == 0) {
216 mprSetVar(&var
, "dn", mprString(ldb_dn_alloc_linearized(msg
, msg
->dn
)));
221 return mprCreateUndefinedVar();
226 turn an array of ldb_messages into a ejs object variable
228 struct MprVar
mprLdbArray(struct ldb_context
*ldb
,
229 struct ldb_message
**msg
, int count
, const char *name
)
234 res
= mprArray(name
);
235 for (i
=0;i
<count
;i
++) {
236 mprAddArray(&res
, i
, mprLdbMessage(ldb
, msg
[i
]));
243 turn a MprVar string variable into a const char *
245 const char *mprToString(struct MprVar
*v
)
248 mprReadProperty(v
, 0);
250 if (!mprVarIsString(v
->type
)) return NULL
;
255 turn a MprVar integer variable into an int
257 int mprToInt(struct MprVar
*v
)
260 mprReadProperty(v
, 0);
262 if (!mprVarIsNumber(v
->type
)) return 0;
263 return mprVarToNumber(v
);
267 turn a MprVar object variable into a string list
268 this assumes the object variable consists only of strings
270 const char **mprToList(TALLOC_CTX
*mem_ctx
, struct MprVar
*v
)
272 const char **list
= NULL
;
275 if (v
->type
!= MPR_TYPE_OBJECT
||
276 v
->properties
== NULL
) {
279 for (el
=mprGetFirstProperty(v
, MPR_ENUM_DATA
);
281 el
=mprGetNextProperty(v
, el
, MPR_ENUM_DATA
)) {
282 const char *s
= mprToString(el
);
284 list
= str_list_add(list
, s
);
287 talloc_steal(mem_ctx
, list
);
293 turn a MprVar object variable into a string list
294 this assumes the object variable is an array of strings
296 const char **mprToArray(TALLOC_CTX
*mem_ctx
, struct MprVar
*v
)
298 const char **list
= NULL
;
302 len
= mprGetProperty(v
, "length", NULL
);
306 length
= mprToInt(len
);
308 for (i
=0;i
<length
;i
++) {
311 mprItoa(i
, idx
, sizeof(idx
));
312 vs
= mprGetProperty(v
, idx
, NULL
);
313 if (vs
== NULL
|| vs
->type
!= MPR_TYPE_STRING
) {
317 list
= str_list_add(list
, mprToString(vs
));
319 talloc_steal(mem_ctx
, list
);
324 turn a NTSTATUS into a MprVar object with lots of funky properties
326 struct MprVar
mprNTSTATUS(NTSTATUS status
)
330 res
= mprObject("ntstatus");
332 mprSetVar(&res
, "errstr", mprString(nt_errstr(status
)));
333 mprSetVar(&res
, "v", mprCreateIntegerVar(NT_STATUS_V(status
)));
334 mprSetVar(&res
, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status
)));
335 mprSetVar(&res
, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status
)));
341 create a data-blob in a mpr variable
343 struct MprVar
mprDataBlob(DATA_BLOB blob
)
346 struct datablob
*pblob
= talloc(mprMemCtx(), struct datablob
);
347 *pblob
= data_blob_talloc(pblob
, blob
.data
, blob
.length
);
349 res
= mprObject("DATA_BLOB");
351 mprSetVar(&res
, "size", mprCreateIntegerVar(blob
.length
));
352 mprSetPtrChild(&res
, "blob", pblob
);
358 return a data blob from a mpr var created using mprDataBlob
360 struct datablob
*mprToDataBlob(struct MprVar
*v
)
362 return talloc_get_type(mprGetPtr(v
, "blob"), struct datablob
);
366 turn a WERROR into a MprVar object with lots of funky properties
368 struct MprVar
mprWERROR(WERROR status
)
372 res
= mprObject("werror");
374 mprSetVar(&res
, "errstr", mprString(win_errstr(status
)));
375 mprSetVar(&res
, "v", mprCreateIntegerVar(W_ERROR_V(status
)));
376 mprSetVar(&res
, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status
)));
377 mprSetVar(&res
, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status
)));
384 set a pointer in a existing MprVar
386 void mprSetPtr(struct MprVar
*v
, const char *propname
, const void *p
)
388 mprSetVar(v
, propname
, mprCreatePtrVar(discard_const(p
)));
392 set a pointer in a existing MprVar, freeing it when the property goes away
394 void mprSetPtrChild(struct MprVar
*v
, const char *propname
, const void *p
)
396 mprSetVar(v
, propname
, mprCreatePtrVar(discard_const(p
)));
397 v
= mprGetProperty(v
, propname
, NULL
);
398 v
->allocatedData
= 1;
399 talloc_steal(mprMemCtx(), p
);
403 get a pointer from a MprVar
405 void *mprGetPtr(struct MprVar
*v
, const char *propname
)
408 val
= mprGetProperty(v
, propname
, NULL
);
412 if (val
->type
!= MPR_TYPE_PTR
) {
419 set the return value then free the variable
421 void mpr_Return(int eid
, struct MprVar v
)
423 ejsSetReturnValue(eid
, v
);
428 set the return value then free the variable
430 void mpr_ReturnString(int eid
, const char *s
)
432 mpr_Return(eid
, mprString(s
));
437 set a C function in a variable
439 void mprSetCFunction(struct MprVar
*obj
, const char *name
, MprCFunction fn
)
441 mprSetVar(obj
, name
, mprCreateCFunctionVar(fn
, obj
, MPR_VAR_SCRIPT_HANDLE
));
445 set a string C function in a variable
447 void mprSetStringCFunction(struct MprVar
*obj
, const char *name
, MprStringCFunction fn
)
449 mprSetVar(obj
, name
, mprCreateStringCFunctionVar(fn
, obj
, MPR_VAR_SCRIPT_HANDLE
));
453 get a pointer in the current object
455 void *mprGetThisPtr(int eid
, const char *name
)
457 struct MprVar
*this = mprGetProperty(ejsGetLocalObject(eid
), "this", 0);
458 return mprGetPtr(this, name
);
462 set a pointer as a child of the local object
464 void mprSetThisPtr(int eid
, const char *name
, void *ptr
)
466 struct MprVar
*this = mprGetProperty(ejsGetLocalObject(eid
), "this", 0);
467 mprSetPtrChild(this, name
, ptr
);
471 used by object xxx_init() routines to allow for the caller
472 to supply a pre-existing object to add properties to,
473 or create a new object. This makes inheritance easy
475 struct MprVar
*mprInitObject(int eid
, const char *name
, int argc
, struct MprVar
**argv
)
477 if (argc
> 0 && mprVarIsObject(argv
[0]->type
)) {
480 mpr_Return(eid
, mprObject(name
));
481 return ejsGetReturnValue(eid
);