r8280: - added irpc_connect() for connecting to a irpc server by name
[kai/samba.git] / source / 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 static 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 }
97
98 /*
99   construct a MprVar from a list
100 */
101 struct MprVar mprList(const char *name, const char **list)
102 {
103         struct MprVar var;
104         int i;
105
106         var = mprCreateObjVar(name, MPR_DEFAULT_HASH_SIZE);
107         for (i=0;list && list[i];i++) {
108                 mprAddArray(&var, i, mprCreateStringVar(list[i], 1));
109         }
110         return var;
111 }
112
113 /*
114   construct a string MprVar from a lump of data
115 */
116 struct MprVar mprData(const uint8_t *p, size_t length)
117 {
118         struct MprVar var;
119         char *s = talloc_strndup(mprMemCtx(), p, length);
120         if (s == NULL) {
121                 return mprCreateUndefinedVar();
122         }
123         var = mprCreateStringVar(s, 1);
124         talloc_free(s);
125         return var;
126 }
127
128 /*
129   turn a ldb_message into a ejs object variable
130 */
131 struct MprVar mprLdbMessage(struct ldb_message *msg)
132 {
133         struct MprVar var;
134         int i;
135         /* we force some attributes to always be an array in the
136            returned structure. This makes the scripting easier, as you don't 
137            need a special case for the single value case */
138         const char *multivalued[] = { "objectClass", "memberOf", "privilege", 
139                                             "member", NULL };
140
141         var = mprCreateObjVar(msg->dn, MPR_DEFAULT_HASH_SIZE);
142
143         for (i=0;i<msg->num_elements;i++) {
144                 struct ldb_message_element *el = &msg->elements[i];
145                 struct MprVar val;
146                 if (el->num_values == 1 &&
147                     !str_list_check_ci(multivalued, el->name)) {
148                         val = mprData(el->values[0].data, el->values[0].length);
149                 } else {
150                         int j;
151                         val = mprCreateObjVar(el->name, MPR_DEFAULT_HASH_SIZE);
152                         for (j=0;j<el->num_values;j++) {
153                                 mprAddArray(&val, j, 
154                                             mprData(el->values[j].data, 
155                                                     el->values[j].length));
156                         }
157                 }
158                 mprSetVar(&var, el->name, val);
159         }
160
161         /* add the dn if it is not already specified */
162         if (mprGetProperty(&var, "dn", 0) == 0) {
163                 mprSetVar(&var, "dn", mprCreateStringVar(msg->dn, 1));
164         }
165         
166         return var;             
167 }
168
169
170 /*
171   turn an array of ldb_messages into a ejs object variable
172 */
173 struct MprVar mprLdbArray(struct ldb_message **msg, int count, const char *name)
174 {
175         struct MprVar res;
176         int i;
177
178         res = mprCreateObjVar(name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE);
179         for (i=0;i<count;i++) {
180                 mprAddArray(&res, i, mprLdbMessage(msg[i]));
181         }
182         mprSetPropertyValue(&res, "length", mprCreateIntegerVar(i));
183         return res;     
184 }
185
186
187 /*
188   turn a MprVar string variable into a const char *
189  */
190 const char *mprToString(const struct MprVar *v)
191 {
192         if (v->type != MPR_TYPE_STRING) return NULL;
193         return v->string;
194 }
195
196 /*
197   turn a MprVar integer variable into an int
198  */
199 int mprToInt(const struct MprVar *v)
200 {
201         if (v->type != MPR_TYPE_INT) return 0;
202         return v->integer;
203 }
204
205 /*
206   turn a MprVar object variable into a string list
207   this assumes the object variable consists only of strings
208 */
209 const char **mprToList(TALLOC_CTX *mem_ctx, struct MprVar *v)
210 {
211         const char **list = NULL;
212         struct MprVar *el;
213
214         if (v->type != MPR_TYPE_OBJECT ||
215             v->properties == NULL) {
216                 return NULL;
217         }
218         for (el=mprGetFirstProperty(v, MPR_ENUM_DATA);
219              el;
220              el=mprGetNextProperty(v, el, MPR_ENUM_DATA)) {
221                 const char *s = mprToString(el);
222                 if (s) {
223                         list = str_list_add(list, s);
224                 }
225         }
226         talloc_steal(mem_ctx, list);
227         return list;
228 }
229
230 /*
231   turn a NTSTATUS into a MprVar object with lots of funky properties
232 */
233 struct MprVar mprNTSTATUS(NTSTATUS status)
234 {
235         struct MprVar res;
236
237         res = mprCreateObjVar("ntstatus", MPR_DEFAULT_HASH_SIZE);
238
239         mprSetVar(&res, "errstr", mprCreateStringVar(nt_errstr(status), 1));
240         mprSetVar(&res, "v", mprCreateIntegerVar(NT_STATUS_V(status)));
241         mprSetVar(&res, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status)));
242         mprSetVar(&res, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status)));
243
244         return res;
245 }
246
247 /*
248   turn a WERROR into a MprVar object with lots of funky properties
249 */
250 struct MprVar mprWERROR(WERROR status)
251 {
252         struct MprVar res;
253
254         res = mprCreateObjVar("werror", MPR_DEFAULT_HASH_SIZE);
255
256         mprSetVar(&res, "errstr", mprCreateStringVar(win_errstr(status), 1));
257         mprSetVar(&res, "v", mprCreateIntegerVar(W_ERROR_V(status)));
258         mprSetVar(&res, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status)));
259         mprSetVar(&res, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status)));
260
261         return res;
262 }
263
264
265 /*
266   set a pointer in a existing MprVar
267 */
268 void mprSetPtr(struct MprVar *v, const char *propname, const void *p)
269 {
270         mprSetVar(v, propname, mprCreatePtrVar(discard_const(p), NULL));
271 }
272
273 /*
274   set a pointer in a existing MprVar, making it a child of the property
275 */
276 void mprSetPtrChild(struct MprVar *v, const char *propname, const void *p)
277 {
278         mprSetVar(v, propname, mprCreatePtrVar(discard_const(p), NULL));
279         talloc_steal(mprGetProperty(v, propname, NULL), p);
280 }
281
282 /*
283   get a pointer from a MprVar
284 */
285 void *mprGetPtr(struct MprVar *v, const char *propname)
286 {
287         struct MprVar *val;
288         val = mprGetProperty(v, propname, NULL);
289         if (val == NULL) {
290                 return NULL;
291         }
292         if (val->type != MPR_TYPE_PTR) {
293                 return NULL;
294         }
295         return val->ptr;
296 }
297
298 /*
299   set the return value then free the variable
300 */
301  void mpr_Return(int eid, struct MprVar v)
302
303         ejsSetReturnValue(eid, v);
304         mprDestroyVar(&v);
305 }
306
307 /*
308   set the return value then free the variable
309 */
310 void mpr_ReturnString(int eid, const char *s)
311
312         mpr_Return(eid, mprCreateStringVar(s, False));
313 }
314
315