r8602: allow options in ldb connect calls
[bbaumbach/samba-autobuild/.git] / source4 / scripting / ejs / smbcalls_ldb.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    provide hooks into smbd C calls from ejs scripts
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 "scripting/ejs/smbcalls.h"
25 #include "lib/appweb/ejs/ejs.h"
26 #include "lib/ldb/include/ldb.h"
27
28 /*
29   get the connected db
30  */
31 static struct ldb_context *ejs_get_ldb_context(int eid)
32 {
33         struct ldb_context *ldb = mprGetThisPtr(eid, "db");
34         if (ldb == NULL) {
35                 ejsSetErrorMsg(eid, "invalid ldb connection");
36         }
37         return ldb;
38 }
39
40 /*
41   perform an ldb search, returning an array of results
42
43   syntax:
44      res = ldb.search("expression");
45      var attrs = new Array("attr1", "attr2", "attr3");
46      ldb.search("expression", attrs);
47      var basedn = "cn=this,dc=is,dc=a,dc=test";
48      ldb.search("expression", attrs, ldb.SCOPE_SUBTREE, basedn);
49 */
50 static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv)
51 {
52         const char **attrs = NULL;
53         const char *expression;
54         const char *basedn = NULL;
55         int scope = LDB_SCOPE_DEFAULT;
56         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
57         struct ldb_context *ldb;
58         int ret;
59         struct ldb_message **res;
60
61         /* validate arguments */
62         if (argc < 1 || argc > 4) {
63                 ejsSetErrorMsg(eid, "ldb.search invalid number of arguments");
64                 goto failed;
65         }
66         if (argc > 3 && argv[3]->type != MPR_TYPE_OBJECT) {
67                 ejsSetErrorMsg(eid, "ldb.search attributes must be an object");
68                 goto failed;
69         }
70
71         ldb = ejs_get_ldb_context(eid);
72         if (ldb == NULL) {
73                 return -1;
74         }
75         
76         expression = mprToString(argv[0]);
77         if (expression == NULL) {
78                 ejsSetErrorMsg(eid, "ldb.search invalid expression");
79                 goto failed;
80         }
81         if (argc > 1) {
82                 basedn = mprToString(argv[1]);
83                 /* a null basedn is valid */
84         }
85         if (argc > 2) {
86                 scope = mprToInt(argv[2]);
87                 switch (scope) {
88                         case LDB_SCOPE_DEFAULT:
89                         case LDB_SCOPE_BASE:
90                         case LDB_SCOPE_ONELEVEL:
91                         case LDB_SCOPE_SUBTREE:
92                                 break; /* ok */
93                         default:
94                                 ejsSetErrorMsg(eid, "ldb.search invalid scope");
95                                 goto failed;
96                 }
97         }
98         if (argc > 3) {
99                 attrs = mprToList(tmp_ctx, argv[3]);
100         }
101         ret = ldb_search(ldb, basedn, scope, expression, attrs, &res);
102         if (ret == -1) {
103                 ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb));
104                 mpr_Return(eid, mprCreateUndefinedVar());
105         } else {
106                 mpr_Return(eid, mprLdbArray(res, ret, "ldb_message"));
107         }
108
109         talloc_free(tmp_ctx);
110         return 0;
111
112 failed:
113         talloc_free(tmp_ctx);
114         return -1;
115 }
116
117
118 /*
119   perform an ldb add or modify
120 */
121 static int ejs_ldbAddModify(MprVarHandle eid, int argc, struct MprVar **argv,
122                             int fn(struct ldb_context *, const struct ldb_message *))
123 {
124         const char *ldifstring;
125         struct ldb_context *ldb;
126         struct ldb_ldif *ldif;
127         int ret;
128
129         if (argc != 1) {
130                 ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
131                 return -1;
132         }
133
134         ldifstring = mprToString(argv[0]);
135         if (ldifstring == NULL) {
136                 ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments");
137                 return -1;
138         }
139
140         ldb = ejs_get_ldb_context(eid);
141         if (ldb == NULL) {
142                 return -1;
143         }
144
145         while ((ldif = ldb_ldif_read_string(ldb, &ldifstring))) {
146                 ret = fn(ldb, ldif->msg);
147                 talloc_free(ldif);
148                 if (ret != 0) break;
149         }
150
151         mpr_Return(eid, mprCreateBoolVar(ret == 0));
152         return 0;
153 }
154
155
156 /*
157   perform an ldb delete
158   usage:
159    ok = ldb.delete(dn);
160 */
161 static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv)
162 {
163         const char *dn;
164         struct ldb_context *ldb;
165         int ret;
166
167         if (argc != 1) {
168                 ejsSetErrorMsg(eid, "ldb.delete invalid arguments");
169                 return -1;
170         }
171
172         dn = mprToString(argv[0]);
173
174         ldb = ejs_get_ldb_context(eid);
175         if (ldb == NULL) {
176                 return -1;
177         }
178         ret = ldb_delete(ldb, dn);
179
180         mpr_Return(eid, mprCreateBoolVar(ret == 0));
181         return 0;
182 }
183
184 /*
185   perform an ldb rename
186   usage:
187    ok = ldb.rename(dn1, dn2);
188 */
189 static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv)
190 {
191         const char *dn1, *dn2;
192         struct ldb_context *ldb;
193         int ret;
194
195         if (argc != 2) {
196                 ejsSetErrorMsg(eid, "ldb.rename invalid arguments");
197                 return -1;
198         }
199
200         dn1 = mprToString(argv[0]);
201         dn2 = mprToString(argv[1]);
202         if (dn1 == NULL || dn2 == NULL) {
203                 ejsSetErrorMsg(eid, "ldb.rename invalid arguments");
204                 return -1;
205         }
206
207         ldb = ejs_get_ldb_context(eid);
208         if (ldb == NULL) {
209                 return -1;
210         }
211
212         ret = ldb_rename(ldb, dn1, dn2);
213
214         mpr_Return(eid, mprCreateBoolVar(ret == 0));
215         return 0;
216 }
217
218 /*
219   get last error message
220   usage:
221    ok = ldb.errstring();
222 */
223 static int ejs_ldbErrstring(MprVarHandle eid, int argc, struct MprVar **argv)
224 {
225         struct ldb_context *ldb;
226
227         ldb = ejs_get_ldb_context(eid);
228         if (ldb == NULL) {
229                 return -1;
230         }
231
232         mpr_Return(eid, mprString(ldb_errstring(ldb)));
233         return 0;
234 }
235
236 /*
237   perform an ldb modify
238
239   syntax:
240     ok = ldb.modify(ldifstring);
241 */
242 static int ejs_ldbAdd(MprVarHandle eid, int argc, struct MprVar **argv)
243 {
244         return ejs_ldbAddModify(eid, argc, argv, ldb_add);
245 }
246
247 /*
248   perform an ldb add
249
250   syntax:
251     ok = ldb.add(ldifstring);
252 */
253 static int ejs_ldbModify(MprVarHandle eid, int argc, struct MprVar **argv)
254 {
255         return ejs_ldbAddModify(eid, argc, argv, ldb_modify);
256 }
257
258 /*
259   connect to a database
260   usage:
261    ok = ldb.connect(dbfile);
262    ok = ldb.connect(dbfile, "modules:modlist");
263 */
264 static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv)
265 {
266         struct ldb_context *ldb;
267         const char *dbfile;
268
269         if (argc < 1) {
270                 ejsSetErrorMsg(eid, "ldb.connect invalid arguments");
271                 return -1;
272         }
273
274         dbfile = argv[0];
275
276         ldb = ldb_wrap_connect(mprMemCtx(), dbfile, 0, argv+1);
277         if (ldb == NULL) {
278                 ejsSetErrorMsg(eid, "ldb.connect failed to open %s", dbfile);
279         }
280
281         mprSetThisPtr(eid, "db", ldb);
282         mpr_Return(eid, mprCreateBoolVar(ldb != NULL));
283         return 0;
284 }
285
286
287 /*
288   initialise ldb ejs subsystem
289 */
290 static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv)
291 {
292         struct MprVar *ldb;
293         mpr_Return(eid, mprObject("ldb"));
294
295         ldb  = ejsGetReturnValue(eid);
296
297         mprSetStringCFunction(ldb, "connect", ejs_ldbConnect);
298         mprSetCFunction(ldb, "search", ejs_ldbSearch);
299         mprSetCFunction(ldb, "add", ejs_ldbAdd);
300         mprSetCFunction(ldb, "modify", ejs_ldbModify);
301         mprSetCFunction(ldb, "del", ejs_ldbDelete);
302         mprSetCFunction(ldb, "rename", ejs_ldbRename);
303         mprSetCFunction(ldb, "errstring", ejs_ldbErrstring);
304         mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE));
305         mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL));
306         mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE));
307
308         return 0;
309 }
310
311
312 /*
313   setup C functions that be called from ejs
314 */
315 void smb_setup_ejs_ldb(void)
316 {
317         ejsDefineCFunction(-1, "ldb_init", ejs_ldb_init, NULL, MPR_VAR_SCRIPT_HANDLE);
318 }