ad998701f6d7f9553a3946a1256670aa5f9fdad6
[jra/samba/.git] / source4 / scripting / ejs / smbcalls_string.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    provide access to string functions
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/ejs/ejs.h"
26 #include "system/passwd.h"
27
28 /*
29   usage:
30       var s = strlower("UPPER");
31 */
32 static int ejs_strlower(MprVarHandle eid, int argc, char **argv)
33 {
34         char *s;
35         if (argc != 1) {
36                 ejsSetErrorMsg(eid, "strlower invalid arguments");
37                 return -1;
38         }
39         s = strlower_talloc(mprMemCtx(), argv[0]);
40         mpr_Return(eid, mprString(s));
41         talloc_free(s);
42         return 0;
43 }
44
45 /*
46   usage:
47       var s = strupper("lower");
48 */
49 static int ejs_strupper(MprVarHandle eid, int argc, char **argv)
50 {
51         char *s;
52         if (argc != 1) {
53                 ejsSetErrorMsg(eid, "strupper invalid arguments");
54                 return -1;
55         }
56         s = strupper_talloc(mprMemCtx(), argv[0]);
57         mpr_Return(eid, mprString(s));
58         talloc_free(s);
59         return 0;
60 }
61
62 /*
63   usage:
64      list = split(".", "a.foo.bar");
65
66   NOTE: does not take a regular expression, unlink perl split()
67 */
68 static int ejs_split(MprVarHandle eid, int argc, char **argv)
69 {
70         const char *separator;
71         char *s, *p;
72         struct MprVar ret;
73         int count = 0;
74         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
75         if (argc != 2) {
76                 ejsSetErrorMsg(eid, "split invalid arguments");
77                 return -1;
78         }
79         separator = argv[0];
80         s = argv[1];
81
82         ret = mprObject("list");
83
84         while ((p = strstr(s, separator))) {
85                 char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s));
86                 mprAddArray(&ret, count++, mprString(s2));
87                 talloc_free(s2);
88                 s = p + strlen(separator);
89         }
90         if (*s) {
91                 mprAddArray(&ret, count++, mprString(s));
92         }
93         talloc_free(tmp_ctx);
94         mpr_Return(eid, ret);
95         return 0;
96 }
97
98
99 /*
100   usage:
101      str = join("DC=", list);
102 */
103 static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv)
104 {
105         int i;
106         const char *separator;
107         char *ret = NULL;
108         const char **list;
109         TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx());
110         if (argc != 2 ||
111             argv[0]->type != MPR_TYPE_STRING ||
112             argv[1]->type != MPR_TYPE_OBJECT) {
113                 ejsSetErrorMsg(eid, "join invalid arguments");
114                 return -1;
115         }
116
117         separator = mprToString(argv[0]);
118         list      = mprToArray(tmp_ctx, argv[1]);
119
120         if (list == NULL || list[0] == NULL) {
121                 talloc_free(tmp_ctx);
122                 mpr_Return(eid, mprString(NULL));
123                 return 0;
124         }
125         
126         ret = talloc_strdup(tmp_ctx, list[0]);
127         if (ret == NULL) {
128                 goto failed;
129         }
130         for (i=1;list[i];i++) {
131                 ret = talloc_asprintf_append(ret, "%s%s", separator, list[i]);
132                 if (ret == NULL) {
133                         goto failed;
134                 }
135         }
136         mpr_Return(eid, mprString(ret));
137         talloc_free(tmp_ctx);
138         return 0;
139 failed:
140         ejsSetErrorMsg(eid, "out of memory");
141         return -1;
142 }
143
144
145 /*
146   blergh, C certainly makes this hard!
147   usage:
148      str = sprintf("i=%d s=%7s", 7, "foo");
149 */
150 static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv)
151 {
152         const char *format;
153         const char *p;
154         char *ret;
155         int a = 1;
156         char *(*_asprintf_append)(char *, const char *, ...);
157         TALLOC_CTX *tmp_ctx;
158         if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) {
159                 ejsSetErrorMsg(eid, "sprintf invalid arguments");
160                 return -1;
161         }
162         format = mprToString(argv[0]);
163         tmp_ctx = talloc_new(mprMemCtx());
164         ret = talloc_strdup(tmp_ctx, "");
165
166         /* avoid all the format string warnings */
167         _asprintf_append = talloc_asprintf_append;
168
169         /*
170           hackity hack ...
171         */
172         while ((p = strchr(format, '%'))) {
173                 char *fmt2;
174                 int len, len_count=0;
175                 char *tstr;
176                 ret = talloc_asprintf_append(ret, "%*.*s", 
177                                              (int)(p-format), (int)(p-format), 
178                                              format);
179                 if (ret == NULL) goto failed;
180                 format += (int)(p-format);
181                 len = strcspn(p+1, "dxuiofgGpXeEFcs%") + 1;
182                 fmt2 = talloc_strndup(tmp_ctx, p, len+1);
183                 if (fmt2 == NULL) goto failed;
184                 len_count = count_chars(fmt2, '*');
185                 /* find the type string */
186                 tstr = &fmt2[len];
187                 while (tstr > fmt2 && isalpha(tstr[-1])) {
188                         tstr--;
189                 }
190                 if (strcmp(tstr, "%") == 0) {
191                         ret = talloc_asprintf_append(ret, "%%");
192                         if (ret == NULL) {
193                                 goto failed;
194                         }
195                         format += len+1;
196                         continue;
197                 }
198                 if (len_count > 2 || 
199                     argc < a + len_count + 1) {
200                         ejsSetErrorMsg(eid, "sprintf: not enough arguments for format");
201                         goto failed;
202                 }
203 #define FMT_ARG(fn, type) do { \
204                         switch (len_count) { \
205                         case 0: \
206                                 ret = _asprintf_append(ret, fmt2, \
207                                                              (type)fn(argv[a])); \
208                                 break; \
209                         case 1: \
210                                 ret = _asprintf_append(ret, fmt2, \
211                                                              (int)mprVarToNumber(argv[a]), \
212                                                              (type)fn(argv[a+1])); \
213                                 break; \
214                         case 2: \
215                                 ret = _asprintf_append(ret, fmt2, \
216                                                              (int)mprVarToNumber(argv[a]), \
217                                                              (int)mprVarToNumber(argv[a+1]), \
218                                                              (type)fn(argv[a+2])); \
219                                 break; \
220                         } \
221                         a += len_count + 1; \
222                         if (ret == NULL) { \
223                                 goto failed; \
224                         } \
225 } while (0)
226
227                 if (strcmp(tstr, "s")==0)        FMT_ARG(mprToString,    const char *);
228                 else if (strcmp(tstr, "c")==0)   FMT_ARG(*mprToString,   char);
229                 else if (strcmp(tstr, "d")==0)   FMT_ARG(mprVarToNumber, int);
230                 else if (strcmp(tstr, "ld")==0)  FMT_ARG(mprVarToNumber, long);
231                 else if (strcmp(tstr, "lld")==0) FMT_ARG(mprVarToNumber, long long);
232                 else if (strcmp(tstr, "x")==0)   FMT_ARG(mprVarToNumber, int);
233                 else if (strcmp(tstr, "lx")==0)  FMT_ARG(mprVarToNumber, long);
234                 else if (strcmp(tstr, "llx")==0) FMT_ARG(mprVarToNumber, long long);
235                 else if (strcmp(tstr, "X")==0)   FMT_ARG(mprVarToNumber, int);
236                 else if (strcmp(tstr, "lX")==0)  FMT_ARG(mprVarToNumber, long);
237                 else if (strcmp(tstr, "llX")==0) FMT_ARG(mprVarToNumber, long long);
238                 else if (strcmp(tstr, "u")==0)   FMT_ARG(mprVarToNumber, int);
239                 else if (strcmp(tstr, "lu")==0)  FMT_ARG(mprVarToNumber, long);
240                 else if (strcmp(tstr, "llu")==0) FMT_ARG(mprVarToNumber, long long);
241                 else if (strcmp(tstr, "i")==0)   FMT_ARG(mprVarToNumber, int);
242                 else if (strcmp(tstr, "li")==0)  FMT_ARG(mprVarToNumber, long);
243                 else if (strcmp(tstr, "lli")==0) FMT_ARG(mprVarToNumber, long long);
244                 else if (strcmp(tstr, "o")==0)   FMT_ARG(mprVarToNumber, int);
245                 else if (strcmp(tstr, "lo")==0)  FMT_ARG(mprVarToNumber, long);
246                 else if (strcmp(tstr, "llo")==0) FMT_ARG(mprVarToNumber, long long);
247                 else if (strcmp(tstr, "f")==0)   FMT_ARG(mprVarToFloat,  double);
248                 else if (strcmp(tstr, "lf")==0)  FMT_ARG(mprVarToFloat,  double);
249                 else if (strcmp(tstr, "g")==0)   FMT_ARG(mprVarToFloat,  double);
250                 else if (strcmp(tstr, "lg")==0)  FMT_ARG(mprVarToFloat,  double);
251                 else if (strcmp(tstr, "e")==0)   FMT_ARG(mprVarToFloat,  double);
252                 else if (strcmp(tstr, "le")==0)  FMT_ARG(mprVarToFloat,  double);
253                 else if (strcmp(tstr, "E")==0)   FMT_ARG(mprVarToFloat,  double);
254                 else if (strcmp(tstr, "lE")==0)  FMT_ARG(mprVarToFloat,  double);
255                 else if (strcmp(tstr, "F")==0)   FMT_ARG(mprVarToFloat,  double);
256                 else if (strcmp(tstr, "lF")==0)  FMT_ARG(mprVarToFloat,  double);
257                 else {
258                         ejsSetErrorMsg(eid, "sprintf: unknown format string '%s'", fmt2);
259                         goto failed;
260                 }
261                 format += len+1;
262         }
263
264         ret = talloc_asprintf_append(ret, "%s", format);
265         mpr_Return(eid, mprString(ret));
266         talloc_free(tmp_ctx);
267         return 0;          
268         
269 failed:
270         talloc_free(tmp_ctx);
271         return -1;
272 }
273
274 /*
275   used to build your own print function
276      str = vsprintf(args);
277 */
278 static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv)
279 {
280         struct MprVar **args, *len, *v;
281         int i, ret, length;
282         if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) {
283                 ejsSetErrorMsg(eid, "vsprintf invalid arguments");
284                 return -1;
285         }
286         v = argv[0];
287         len = mprGetProperty(v, "length", NULL);
288         if (len == NULL) {
289                 ejsSetErrorMsg(eid, "vsprintf takes an array");
290                 return -1;
291         }
292         length = mprToInt(len);
293         args = talloc_array(mprMemCtx(), struct MprVar *, length);
294         if (args == NULL) {
295                 return -1;
296         }
297
298         for (i=0;i<length;i++) {
299                 char idx[16];
300                 mprItoa(i, idx, sizeof(idx));
301                 args[i] = mprGetProperty(v, idx, NULL);
302         }
303         
304         ret = ejs_sprintf(eid, length, args);
305         talloc_free(args);
306         return ret;
307 }
308
309 /*
310   setup C functions that be called from ejs
311 */
312 void smb_setup_ejs_string(void)
313 {
314         ejsDefineStringCFunction(-1, "strlower", ejs_strlower, NULL, MPR_VAR_SCRIPT_HANDLE);
315         ejsDefineStringCFunction(-1, "strupper", ejs_strupper, NULL, MPR_VAR_SCRIPT_HANDLE);
316         ejsDefineStringCFunction(-1, "split", ejs_split, NULL, MPR_VAR_SCRIPT_HANDLE);
317         ejsDefineCFunction(-1, "join", ejs_join, NULL, MPR_VAR_SCRIPT_HANDLE);
318         ejsDefineCFunction(-1, "sprintf", ejs_sprintf, NULL, MPR_VAR_SCRIPT_HANDLE);
319         ejsDefineCFunction(-1, "vsprintf", ejs_vsprintf, NULL, MPR_VAR_SCRIPT_HANDLE);
320 }