r8316: give full access to the popt command line parsing in ejs scripts, including
[kai/samba.git] / source4 / scripting / ejs / mprutil.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    utility functions for manipulating mpr variables in ejs calls
5
6    Copyright (C) Andrew Tridgell 2005
7    
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.
12    
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.
17    
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.
21 */
22
23 #include "includes.h"
24 #include "lib/ejs/ejs.h"
25 #include "lib/ldb/include/ldb.h"
26
27 /*
28   find a mpr component, allowing for sub objects, using the '.' convention
29 */
30  NTSTATUS mprGetVar(struct MprVar **v, const char *name)
31 {
32         const char *p = strchr(name, '.');
33         char *objname;
34         NTSTATUS status;
35         if (p == NULL) {
36                 *v = mprGetProperty(*v, name, NULL);
37                 if (*v == NULL) {
38                         DEBUG(1,("mprGetVar unable to find '%s'\n", name));
39                         return NT_STATUS_INVALID_PARAMETER;
40                 }
41                 return NT_STATUS_OK;
42         }
43         objname = talloc_strndup(mprMemCtx(), name, p-name);
44         NT_STATUS_HAVE_NO_MEMORY(objname);
45         *v = mprGetProperty(*v, objname, NULL);
46         NT_STATUS_HAVE_NO_MEMORY(*v);
47         status = mprGetVar(v, p+1);
48         talloc_free(objname);
49         return status;
50 }
51
52
53 /*
54   set a mpr component, allowing for sub objects, using the '.' convention
55   destroys 'val' after setting
56 */
57  NTSTATUS mprSetVar(struct MprVar *v, const char *name, struct MprVar val)
58 {
59         const char *p = strchr(name, '.');
60         char *objname;
61         struct MprVar *v2;
62         NTSTATUS status;
63         if (p == NULL) {
64                 v2 = mprSetProperty(v, name, &val);
65                 if (v2 == NULL) {
66                         DEBUG(1,("mprSetVar unable to set '%s'\n", name));
67                         return NT_STATUS_INVALID_PARAMETER_MIX;
68                 }
69                 mprDestroyVar(&val);
70                 return NT_STATUS_OK;
71         }
72         objname = talloc_strndup(mprMemCtx(), name, p-name);
73         if (objname == NULL) {
74                 return NT_STATUS_NO_MEMORY;
75         }
76         v2 = mprGetProperty(v, objname, NULL);
77         if (v2 == NULL) {
78                 mprSetVar(v, objname, mprCreateObjVar(objname, MPR_DEFAULT_HASH_SIZE));
79                 v2 = mprGetProperty(v, objname, NULL);
80         }
81         status = mprSetVar(v2, p+1, val);
82         talloc_free(objname);
83         return status;
84 }
85
86
87
88 /*
89   add an indexed array element to a property
90 */
91  void mprAddArray(struct MprVar *var, int i, struct MprVar v)
92 {
93         char idx[16];
94         mprItoa(i, idx, sizeof(idx));
95         mprSetVar(var, idx, v);
96         mprSetVar(var, "length", mprCreateIntegerVar(i+1));
97 }
98
99 /*
100   construct a MprVar from a list
101 */
102 struct MprVar mprList(const char *name, const char **list)
103 {
104         struct MprVar var;
105         int i;
106
107         var = mprCreateObjVar(name, MPR_DEFAULT_HASH_SIZE);
108         for (i=0;list && list[i];i++) {
109                 mprAddArray(&var, i, mprCreateStringVar(list[i], 1));
110         }
111         if (i==0) {
112                 mprSetVar(&var, "length", mprCreateIntegerVar(i));
113         }
114         return var;
115 }
116
117 /*
118   construct a string MprVar from a lump of data
119 */
120 struct MprVar mprData(const uint8_t *p, size_t length)
121 {
122         struct MprVar var;
123         char *s = talloc_strndup(mprMemCtx(), p, length);
124         if (s == NULL) {
125                 return mprCreateUndefinedVar();
126         }
127         var = mprCreateStringVar(s, 1);
128         talloc_free(s);
129         return var;
130 }
131
132 /*
133   turn a ldb_message into a ejs object variable
134 */
135 struct MprVar mprLdbMessage(struct ldb_message *msg)
136 {
137         struct MprVar var;
138         int i;
139         /* we force some attributes to always be an array in the
140            returned structure. This makes the scripting easier, as you don't 
141            need a special case for the single value case */
142         const char *multivalued[] = { "objectClass", "memberOf", "privilege", 
143                                             "member", NULL };
144
145         var = mprCreateObjVar(msg->dn, MPR_DEFAULT_HASH_SIZE);
146
147         for (i=0;i<msg->num_elements;i++) {
148                 struct ldb_message_element *el = &msg->elements[i];
149                 struct MprVar val;
150                 if (el->num_values == 1 &&
151                     !str_list_check_ci(multivalued, el->name)) {
152                         val = mprData(el->values[0].data, el->values[0].length);
153                 } else {
154                         int j;
155                         val = mprCreateObjVar(el->name, MPR_DEFAULT_HASH_SIZE);
156                         for (j=0;j<el->num_values;j++) {
157                                 mprAddArray(&val, j, 
158                                             mprData(el->values[j].data, 
159                                                     el->values[j].length));
160                         }
161                 }
162                 mprSetVar(&var, el->name, val);
163         }
164
165         /* add the dn if it is not already specified */
166         if (mprGetProperty(&var, "dn", 0) == 0) {
167                 mprSetVar(&var, "dn", mprCreateStringVar(msg->dn, 1));
168         }
169         
170         return var;             
171 }
172
173
174 /*
175   turn an array of ldb_messages into a ejs object variable
176 */
177 struct MprVar mprLdbArray(struct ldb_message **msg, int count, const char *name)
178 {
179         struct MprVar res;
180         int i;
181
182         res = mprCreateObjVar(name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE);
183         for (i=0;i<count;i++) {
184                 mprAddArray(&res, i, mprLdbMessage(msg[i]));
185         }
186         return res;
187 }
188
189
190 /*
191   turn a MprVar string variable into a const char *
192  */
193 const char *mprToString(const struct MprVar *v)
194 {
195         if (v->type != MPR_TYPE_STRING) return NULL;
196         return v->string;
197 }
198
199 /*
200   turn a MprVar integer variable into an int
201  */
202 int mprToInt(const struct MprVar *v)
203 {
204         if (v->type != MPR_TYPE_INT) return 0;
205         return v->integer;
206 }
207
208 /*
209   turn a MprVar object variable into a string list
210   this assumes the object variable consists only of strings
211 */
212 const char **mprToList(TALLOC_CTX *mem_ctx, struct MprVar *v)
213 {
214         const char **list = NULL;
215         struct MprVar *el;
216
217         if (v->type != MPR_TYPE_OBJECT ||
218             v->properties == NULL) {
219                 return NULL;
220         }
221         for (el=mprGetFirstProperty(v, MPR_ENUM_DATA);
222              el;
223              el=mprGetNextProperty(v, el, MPR_ENUM_DATA)) {
224                 const char *s = mprToString(el);
225                 if (s) {
226                         list = str_list_add(list, s);
227                 }
228         }
229         talloc_steal(mem_ctx, list);
230         return list;
231 }
232
233 /*
234   turn a NTSTATUS into a MprVar object with lots of funky properties
235 */
236 struct MprVar mprNTSTATUS(NTSTATUS status)
237 {
238         struct MprVar res;
239
240         res = mprCreateObjVar("ntstatus", MPR_DEFAULT_HASH_SIZE);
241
242         mprSetVar(&res, "errstr", mprCreateStringVar(nt_errstr(status), 1));
243         mprSetVar(&res, "v", mprCreateIntegerVar(NT_STATUS_V(status)));
244         mprSetVar(&res, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status)));
245         mprSetVar(&res, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status)));
246
247         return res;
248 }
249
250 /*
251   turn a WERROR into a MprVar object with lots of funky properties
252 */
253 struct MprVar mprWERROR(WERROR status)
254 {
255         struct MprVar res;
256
257         res = mprCreateObjVar("werror", MPR_DEFAULT_HASH_SIZE);
258
259         mprSetVar(&res, "errstr", mprCreateStringVar(win_errstr(status), 1));
260         mprSetVar(&res, "v", mprCreateIntegerVar(W_ERROR_V(status)));
261         mprSetVar(&res, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status)));
262         mprSetVar(&res, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status)));
263
264         return res;
265 }
266
267
268 /*
269   set a pointer in a existing MprVar
270 */
271 void mprSetPtr(struct MprVar *v, const char *propname, const void *p)
272 {
273         mprSetVar(v, propname, mprCreatePtrVar(discard_const(p), NULL));
274 }
275
276 /*
277   set a pointer in a existing MprVar, making it a child of the property
278 */
279 void mprSetPtrChild(struct MprVar *v, const char *propname, const void *p)
280 {
281         mprSetVar(v, propname, mprCreatePtrVar(discard_const(p), NULL));
282         talloc_steal(mprGetProperty(v, propname, NULL), p);
283 }
284
285 /*
286   get a pointer from a MprVar
287 */
288 void *mprGetPtr(struct MprVar *v, const char *propname)
289 {
290         struct MprVar *val;
291         val = mprGetProperty(v, propname, NULL);
292         if (val == NULL) {
293                 return NULL;
294         }
295         if (val->type != MPR_TYPE_PTR) {
296                 return NULL;
297         }
298         return val->ptr;
299 }
300
301 /*
302   set the return value then free the variable
303 */
304  void mpr_Return(int eid, struct MprVar v)
305
306         ejsSetReturnValue(eid, v);
307         mprDestroyVar(&v);
308 }
309
310 /*
311   set the return value then free the variable
312 */
313 void mpr_ReturnString(int eid, const char *s)
314
315         mpr_Return(eid, mprCreateStringVar(s, False));
316 }
317
318