diff options
275 files changed, 6214 insertions, 54129 deletions
diff --git a/lib/replace/Makefile.in b/lib/replace/Makefile.in index c889a0e457..65f8125efd 100644 --- a/lib/replace/Makefile.in +++ b/lib/replace/Makefile.in @@ -47,7 +47,7 @@ test: all installcheck: install test -TEST_OBJS = test/testsuite.o test/os2_delete.o test/strptime.o test/getifaddrs.o +TEST_OBJS = test/main.o test/testsuite.o test/os2_delete.o test/strptime.o test/getifaddrs.o testsuite: libreplace.a $(TEST_OBJS) $(CC) -o testsuite $(TEST_OBJS) -L. -lreplace $(LDFLAGS) $(LIBS) diff --git a/lib/replace/test/main.c b/lib/replace/test/main.c new file mode 100644 index 0000000000..9bd12840a5 --- /dev/null +++ b/lib/replace/test/main.c @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + + libreplace tests + + Copyright (C) Jelmer Vernooij 2006 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" + +struct torture_context; +bool torture_local_replace(struct torture_context *ctx); + +int main(void) +{ + bool ret = torture_local_replace(NULL); + if (ret) + return 0; + return -1; +} diff --git a/lib/replace/test/testsuite.c b/lib/replace/test/testsuite.c index dcb05fbbf4..7929f11add 100644 --- a/lib/replace/test/testsuite.c +++ b/lib/replace/test/testsuite.c @@ -1068,14 +1068,3 @@ bool torture_local_replace(struct torture_context *ctx) return ret; } - -#if _SAMBA_BUILD_>3 -#else -int main(void) -{ - bool ret = torture_local_replace(NULL); - if (ret) - return 0; - return -1; -} -#endif diff --git a/lib/talloc/talloc.mk b/lib/talloc/talloc.mk index 23331b6365..f183cd57ef 100644 --- a/lib/talloc/talloc.mk +++ b/lib/talloc/talloc.mk @@ -5,8 +5,8 @@ TALLOC_SONAME = libtalloc.$(SHLIBEXT).1 all:: libtalloc.a $(TALLOC_SOLIB) testsuite -testsuite:: $(LIBOBJ) testsuite.o - $(CC) $(CFLAGS) -o testsuite testsuite.o $(LIBOBJ) $(LIBS) +testsuite:: $(LIBOBJ) testsuite.o testsuite_main.o + $(CC) $(CFLAGS) -o testsuite testsuite.o testsuite_main.o $(LIBOBJ) $(LIBS) libtalloc.a: $(LIBOBJ) ar -rv $@ $(LIBOBJ) @@ -28,7 +28,7 @@ install:: all doc:: talloc.3 talloc.3.html clean:: - rm -f *~ $(LIBOBJ) $(TALLOC_SOLIB) libtalloc.a testsuite testsuite.o *.gc?? talloc.3 talloc.3.html + rm -f *~ $(LIBOBJ) $(TALLOC_SOLIB) libtalloc.a testsuite testsuite.o testsuite_main.o *.gc?? talloc.3 talloc.3.html test:: testsuite ./testsuite diff --git a/lib/talloc/testsuite.c b/lib/talloc/testsuite.c index 3f06eee566..3d490ddf49 100644 --- a/lib/talloc/testsuite.c +++ b/lib/talloc/testsuite.c @@ -1140,13 +1140,3 @@ bool torture_local_talloc(struct torture_context *tctx) return ret; } - -#if _SAMBA_BUILD_ < 4 -int main(void) -{ - bool ret = torture_local_talloc(NULL); - if (!ret) - return -1; - return 0; -} -#endif diff --git a/lib/talloc/testsuite_main.c b/lib/talloc/testsuite_main.c new file mode 100644 index 0000000000..1b51333278 --- /dev/null +++ b/lib/talloc/testsuite_main.c @@ -0,0 +1,37 @@ +/* + Unix SMB/CIFS implementation. + + local testing of talloc routines. + + Copyright (C) Andrew Tridgell 2004 + + ** NOTE! The following LGPL license applies to the talloc + ** library. This does NOT imply that all of Samba is released + ** under the LGPL + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 3 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, see <http://www.gnu.org/licenses/>. +*/ + +#include "replace.h" + +struct torture_context; +bool torture_local_talloc(struct torture_context *tctx); + +int main(void) +{ + bool ret = torture_local_talloc(NULL); + if (!ret) + return -1; + return 0; +} diff --git a/source3/libcli/nbt/libnbt.h b/libcli/nbt/libnbt.h index d37a17c192..4ef4e9d60d 100644 --- a/source3/libcli/nbt/libnbt.h +++ b/libcli/nbt/libnbt.h @@ -83,7 +83,7 @@ struct nbt_name_request { /* information on what to do on completion */ struct { void (*fn)(struct nbt_name_request *); - void *_private; + void *private_data; } async; }; @@ -95,9 +95,8 @@ struct nbt_name_request { struct nbt_name_socket { struct socket_context *sock; struct event_context *event_ctx; -/* struct smb_iconv_convenience *iconv_convenience; -*/ + /* a queue of requests pending to be sent */ struct nbt_name_request *send_queue; @@ -114,14 +113,14 @@ struct nbt_name_socket { struct { void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, struct socket_address *); - void *_private; + void *private_data; } incoming; /* what to do with unexpected replies */ struct { void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, struct socket_address *); - void *_private; + void *private_data; } unexpected; }; @@ -276,9 +275,8 @@ struct nbt_name_release { }; struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx); - /*, - struct smb_iconv_convenience *iconv_convenience);*/ + struct event_context *event_ctx, + struct smb_iconv_convenience *iconv_convenience); struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock, struct nbt_name_query *io); NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, @@ -293,7 +291,7 @@ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_status *io); NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname); -NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name); +NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, DATA_BLOB *blob, struct nbt_name *name); NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name); void nbt_choose_called_name(TALLOC_CTX *mem_ctx, struct nbt_name *n, const char *name, int type); char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name); @@ -325,7 +323,7 @@ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, struct socket_address *), - void *_private); + void *private_data); NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, struct socket_address *dest, struct nbt_name_packet *request); diff --git a/source4/libcli/nbt/namequery.c b/libcli/nbt/namequery.c index 2e1bcd818b..ed3d8a2492 100644 --- a/source4/libcli/nbt/namequery.c +++ b/libcli/nbt/namequery.c @@ -1,27 +1,27 @@ -/* +/* Unix SMB/CIFS implementation. make nbt name query requests Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" +#include "../libcli/nbt/libnbt.h" +#include "../libcli/nbt/nbt_proto.h" #include "lib/socket/socket.h" #include "param/param.h" @@ -66,13 +66,13 @@ _PUBLIC_ struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nb failed: talloc_free(packet); - return NULL; + return NULL; } /** wait for a name query reply */ -_PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, +_PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, TALLOC_CTX *mem_ctx, struct nbt_name_query *io) { NTSTATUS status; @@ -85,7 +85,7 @@ _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, talloc_free(req); return status; } - + packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); @@ -109,16 +109,16 @@ _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, talloc_free(req); return NT_STATUS_NO_MEMORY; } - + for (i=0;i<io->out.num_addrs;i++) { - io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs, + io->out.reply_addrs[i] = talloc_steal(io->out.reply_addrs, packet->answers[0].rdata.netbios.addresses[i].ipaddr); } io->out.reply_addrs[i] = NULL; talloc_steal(mem_ctx, io->out.name.name); talloc_steal(mem_ctx, io->out.name.scope); - + talloc_free(req); return NT_STATUS_OK; @@ -127,7 +127,7 @@ _PUBLIC_ NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, /** wait for a name query reply */ -_PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_query *io) { struct nbt_name_request *req = nbt_name_query_send(nbtsock, io); @@ -170,13 +170,13 @@ _PUBLIC_ struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *n failed: talloc_free(packet); - return NULL; + return NULL; } /** wait for a name status reply */ -_PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, +_PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, TALLOC_CTX *mem_ctx, struct nbt_name_status *io) { NTSTATUS status; @@ -189,7 +189,7 @@ _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, talloc_free(req); return status; } - + packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); @@ -216,7 +216,7 @@ _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, talloc_steal(io->out.status.names, io->out.status.names[i].name); } - + talloc_free(req); return NT_STATUS_OK; @@ -225,7 +225,7 @@ _PUBLIC_ NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, /** wait for a name status reply */ -_PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_status *io) { struct nbt_name_request *req = nbt_name_status_send(nbtsock, io); diff --git a/source4/libcli/nbt/namerefresh.c b/libcli/nbt/namerefresh.c index b372e4a3f3..37bf0fc8f1 100644 --- a/source4/libcli/nbt/namerefresh.c +++ b/libcli/nbt/namerefresh.c @@ -1,27 +1,27 @@ -/* +/* Unix SMB/CIFS implementation. send out a name refresh request Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" +#include "../libcli/nbt/libnbt.h" +#include "../libcli/nbt/nbt_proto.h" #include "libcli/composite/composite.h" #include "lib/socket/socket.h" #include "param/param.h" @@ -65,11 +65,11 @@ struct nbt_name_request *nbt_name_refresh_send(struct nbt_name_socket *nbtsock, struct nbt_rdata_address, 1); if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed; packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags; - packet->additional[0].rdata.netbios.addresses[0].ipaddr = + packet->additional[0].rdata.netbios.addresses[0].ipaddr = talloc_strdup(packet->additional, io->in.address); - dest = socket_address_from_strings(nbtsock, - nbtsock->sock->backend_name, + dest = socket_address_from_strings(nbtsock, + nbtsock->sock->backend_name, io->in.dest_addr, io->in.dest_port); if (dest == NULL) goto failed; req = nbt_name_request_send(nbtsock, dest, packet, @@ -81,13 +81,13 @@ struct nbt_name_request *nbt_name_refresh_send(struct nbt_name_socket *nbtsock, failed: talloc_free(packet); - return NULL; + return NULL; } /* wait for a refresh reply */ -_PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, +_PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io) { NTSTATUS status; @@ -99,7 +99,7 @@ _PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, talloc_free(req); return status; } - + packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); @@ -116,7 +116,7 @@ _PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, talloc_free(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } - io->out.reply_addr = talloc_steal(mem_ctx, + io->out.reply_addr = talloc_steal(mem_ctx, packet->answers[0].rdata.netbios.addresses[0].ipaddr); talloc_steal(mem_ctx, io->out.name.name); talloc_steal(mem_ctx, io->out.name.scope); @@ -129,7 +129,7 @@ _PUBLIC_ NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, /* synchronous name refresh request */ -_PUBLIC_ NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io) { struct nbt_name_request *req = nbt_name_refresh_send(nbtsock, io); @@ -159,9 +159,9 @@ struct refresh_wins_state { */ static void name_refresh_wins_handler(struct nbt_name_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); - struct refresh_wins_state *state = talloc_get_type(c->private_data, + struct refresh_wins_state *state = talloc_get_type(c->private_data, struct refresh_wins_state); NTSTATUS status; @@ -184,7 +184,7 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_refresh_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; } } else if (!NT_STATUS_IS_OK(status)) { c->state = COMPOSITE_STATE_ERROR; @@ -200,7 +200,7 @@ static void name_refresh_wins_handler(struct nbt_name_request *req) c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_refresh_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; } } else { c->state = COMPOSITE_STATE_DONE; @@ -235,11 +235,11 @@ _PUBLIC_ struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_so state->wins_port = io->in.wins_port; state->wins_servers = str_list_copy(state, io->in.wins_servers); - if (state->wins_servers == NULL || + if (state->wins_servers == NULL || state->wins_servers[0] == NULL) goto failed; state->addresses = str_list_copy(state, io->in.addresses); - if (state->addresses == NULL || + if (state->addresses == NULL || state->addresses[0] == NULL) goto failed; state->io->in.name = io->in.name; @@ -259,7 +259,7 @@ _PUBLIC_ struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_so if (state->req == NULL) goto failed; state->req->async.fn = name_refresh_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; c->private_data = state; c->state = COMPOSITE_STATE_IN_PROGRESS; @@ -281,7 +281,7 @@ _PUBLIC_ NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC NTSTATUS status; status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct refresh_wins_state *state = + struct refresh_wins_state *state = talloc_get_type(c->private_data, struct refresh_wins_state); io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); io->out.rcode = state->io->out.rcode; diff --git a/source4/libcli/nbt/nameregister.c b/libcli/nbt/nameregister.c index 9c5ae43d40..d4728a8e02 100644 --- a/source4/libcli/nbt/nameregister.c +++ b/libcli/nbt/nameregister.c @@ -1,27 +1,27 @@ -/* +/* Unix SMB/CIFS implementation. send out a name registration request Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" +#include "../libcli/nbt/libnbt.h" +#include "../libcli/nbt/nbt_proto.h" #include "libcli/composite/composite.h" #include "lib/socket/socket.h" #include "librpc/gen_ndr/ndr_nbt.h" @@ -73,11 +73,11 @@ struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock, struct nbt_rdata_address, 1); if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed; packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags; - packet->additional[0].rdata.netbios.addresses[0].ipaddr = + packet->additional[0].rdata.netbios.addresses[0].ipaddr = talloc_strdup(packet->additional, io->in.address); if (packet->additional[0].rdata.netbios.addresses[0].ipaddr == NULL) goto failed; - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, + dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, io->in.dest_addr, io->in.dest_port); if (dest == NULL) goto failed; req = nbt_name_request_send(nbtsock, dest, packet, @@ -89,13 +89,13 @@ struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock, failed: talloc_free(packet); - return NULL; + return NULL; } /* wait for a registration reply */ -_PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, +_PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, TALLOC_CTX *mem_ctx, struct nbt_name_register *io) { NTSTATUS status; @@ -107,7 +107,7 @@ _PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, talloc_free(req); return status; } - + packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); @@ -124,11 +124,11 @@ _PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, talloc_free(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } - io->out.reply_addr = talloc_steal(mem_ctx, + io->out.reply_addr = talloc_steal(mem_ctx, packet->answers[0].rdata.netbios.addresses[0].ipaddr); talloc_steal(mem_ctx, io->out.name.name); talloc_steal(mem_ctx, io->out.name.scope); - + talloc_free(req); return NT_STATUS_OK; @@ -137,7 +137,7 @@ _PUBLIC_ NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, /* synchronous name registration request */ -_PUBLIC_ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_register *io) { struct nbt_name_request *req = nbt_name_register_send(nbtsock, io); @@ -161,7 +161,7 @@ struct register_bcast_state { */ static void name_register_bcast_handler(struct nbt_name_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, struct composite_context); + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct register_bcast_state *state = talloc_get_type(c->private_data, struct register_bcast_state); NTSTATUS status; @@ -183,7 +183,7 @@ static void name_register_bcast_handler(struct nbt_name_request *req) c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_bcast_handler; - state->req->async.private = c; + state->req->async.private_data = c; } } else if (!NT_STATUS_IS_OK(status)) { c->state = COMPOSITE_STATE_ERROR; @@ -192,7 +192,7 @@ static void name_register_bcast_handler(struct nbt_name_request *req) c->state = COMPOSITE_STATE_ERROR; c->status = NT_STATUS_CONFLICTING_ADDRESSES; DEBUG(3,("Name registration conflict from %s for %s with ip %s - rcode %d\n", - state->io->out.reply_from, + state->io->out.reply_from, nbt_name_string(state, &state->io->out.name), state->io->out.reply_addr, state->io->out.rcode)); @@ -241,7 +241,7 @@ _PUBLIC_ struct composite_context *nbt_name_register_bcast_send(struct nbt_name_ if (state->req == NULL) goto failed; state->req->async.fn = name_register_bcast_handler; - state->req->async.private = c; + state->req->async.private_data = c; c->private_data = state; c->state = COMPOSITE_STATE_IN_PROGRESS; @@ -297,9 +297,9 @@ struct register_wins_state { */ static void name_register_wins_handler(struct nbt_name_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); - struct register_wins_state *state = talloc_get_type(c->private_data, + struct register_wins_state *state = talloc_get_type(c->private_data, struct register_wins_state); NTSTATUS status; @@ -322,7 +322,7 @@ static void name_register_wins_handler(struct nbt_name_request *req) c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; } } else if (!NT_STATUS_IS_OK(status)) { c->state = COMPOSITE_STATE_ERROR; @@ -338,7 +338,7 @@ static void name_register_wins_handler(struct nbt_name_request *req) c->status = NT_STATUS_NO_MEMORY; } else { state->req->async.fn = name_register_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; } } else { c->state = COMPOSITE_STATE_DONE; @@ -373,11 +373,11 @@ _PUBLIC_ struct composite_context *nbt_name_register_wins_send(struct nbt_name_s state->wins_port = io->in.wins_port; state->wins_servers = str_list_copy(state, io->in.wins_servers); - if (state->wins_servers == NULL || + if (state->wins_servers == NULL || state->wins_servers[0] == NULL) goto failed; state->addresses = str_list_copy(state, io->in.addresses); - if (state->addresses == NULL || + if (state->addresses == NULL || state->addresses[0] == NULL) goto failed; state->io->in.name = io->in.name; @@ -399,7 +399,7 @@ _PUBLIC_ struct composite_context *nbt_name_register_wins_send(struct nbt_name_s if (state->req == NULL) goto failed; state->req->async.fn = name_register_wins_handler; - state->req->async.private = c; + state->req->async.private_data = c; c->private_data = state; c->state = COMPOSITE_STATE_IN_PROGRESS; @@ -421,7 +421,7 @@ _PUBLIC_ NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLO NTSTATUS status; status = composite_wait(c); if (NT_STATUS_IS_OK(status)) { - struct register_wins_state *state = + struct register_wins_state *state = talloc_get_type(c->private_data, struct register_wins_state); io->out.wins_server = talloc_steal(mem_ctx, state->wins_servers[0]); io->out.rcode = state->io->out.rcode; diff --git a/source4/libcli/nbt/namerelease.c b/libcli/nbt/namerelease.c index ba3af41752..e57a2f396e 100644 --- a/source4/libcli/nbt/namerelease.c +++ b/libcli/nbt/namerelease.c @@ -1,27 +1,27 @@ -/* +/* Unix SMB/CIFS implementation. send out a name release request Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "includes.h" -#include "libcli/nbt/libnbt.h" -#include "libcli/nbt/nbt_proto.h" +#include "../libcli/nbt/libnbt.h" +#include "../libcli/nbt/nbt_proto.h" #include "lib/socket/socket.h" #include "param/param.h" @@ -64,10 +64,10 @@ _PUBLIC_ struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket * struct nbt_rdata_address, 1); if (packet->additional[0].rdata.netbios.addresses == NULL) goto failed; packet->additional[0].rdata.netbios.addresses[0].nb_flags = io->in.nb_flags; - packet->additional[0].rdata.netbios.addresses[0].ipaddr = + packet->additional[0].rdata.netbios.addresses[0].ipaddr = talloc_strdup(packet->additional, io->in.address); - dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, + dest = socket_address_from_strings(packet, nbtsock->sock->backend_name, io->in.dest_addr, io->in.dest_port); if (dest == NULL) goto failed; req = nbt_name_request_send(nbtsock, dest, packet, @@ -79,13 +79,13 @@ _PUBLIC_ struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket * failed: talloc_free(packet); - return NULL; + return NULL; } /* wait for a release reply */ -_PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, +_PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, TALLOC_CTX *mem_ctx, struct nbt_name_release *io) { NTSTATUS status; @@ -97,7 +97,7 @@ _PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, talloc_free(req); return status; } - + packet = req->replies[0].packet; io->out.reply_from = talloc_steal(mem_ctx, req->replies[0].dest->addr); @@ -114,7 +114,7 @@ _PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, talloc_free(req); return NT_STATUS_INVALID_NETWORK_RESPONSE; } - io->out.reply_addr = talloc_steal(mem_ctx, + io->out.reply_addr = talloc_steal(mem_ctx, packet->answers[0].rdata.netbios.addresses[0].ipaddr); talloc_steal(mem_ctx, io->out.name.name); talloc_steal(mem_ctx, io->out.name.scope); @@ -127,7 +127,7 @@ _PUBLIC_ NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, /* synchronous name release request */ -_PUBLIC_ NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, TALLOC_CTX *mem_ctx, struct nbt_name_release *io) { struct nbt_name_request *req = nbt_name_release_send(nbtsock, io); diff --git a/source4/libcli/nbt/nbtname.c b/libcli/nbt/nbtname.c index 97ae2e9d72..338cb21089 100644 --- a/source4/libcli/nbt/nbtname.c +++ b/libcli/nbt/nbtname.c @@ -1,20 +1,20 @@ -/* +/* Unix SMB/CIFS implementation. manipulate nbt name structures Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -27,7 +27,6 @@ #include "librpc/gen_ndr/ndr_nbt.h" #include "librpc/gen_ndr/ndr_misc.h" #include "system/locale.h" -#include "param/param.h" /* don't allow an unlimited number of name components */ #define MAX_COMPONENTS 10 @@ -112,7 +111,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_fla /* break up name into a list of components */ for (num_components=0;num_components<MAX_COMPONENTS;num_components++) { - uint8_t *component; + uint8_t *component = NULL; NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset)); if (component == NULL) break; if (name) { @@ -158,7 +157,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_fla ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false); if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { uint8_t b[2]; - + if (offset > 0x3FFF) { return ndr_push_error(ndr, NDR_ERR_STRING, "offset for nbt string label pointer %u[%08X] > 0x00003FFF", @@ -219,7 +218,7 @@ static bool decompress_name(char *name, enum nbt_name_type *type) c2 < 'A' || c2 > 'P') { return false; } - name[i] = ((c1-'A')<<4) | (c2-'A'); + name[i] = ((c1-'A')<<4) | (c2-'A'); } name[i] = 0; if (i == 16) { @@ -234,7 +233,7 @@ static bool decompress_name(char *name, enum nbt_name_type *type) for (;i>0 && name[i-1]==' ';i--) { name[i-1] = 0; } - + return true; } @@ -242,7 +241,7 @@ static bool decompress_name(char *name, enum nbt_name_type *type) /* compress a name component */ -static uint8_t *compress_name(TALLOC_CTX *mem_ctx, +static uint8_t *compress_name(TALLOC_CTX *mem_ctx, const uint8_t *name, enum nbt_name_type type) { uint8_t *cname; @@ -356,7 +355,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags } else { fullname = cname; } - + ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname); return ndr_err; @@ -422,7 +421,7 @@ _PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx, n->scope = NULL; n->type = type; - if (is_ipaddress(name) || name == NULL) { + if ((name == NULL) || is_ipaddress(name)) { n->name = "*SMBSERVER"; return; } @@ -434,11 +433,11 @@ _PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx, return; } s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name)); - n->name = strupper_talloc(mem_ctx, s); + n->name = talloc_strdup_upper(mem_ctx, s); return; } - n->name = strupper_talloc(mem_ctx, name); + n->name = talloc_strdup_upper(mem_ctx, name); } @@ -483,14 +482,14 @@ _PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name) { TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); char *ret; - if (name->scope) { + if (name->scope) { ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s", nbt_hex_encode(tmp_ctx, name->name), - name->type, + name->type, nbt_hex_encode(tmp_ctx, name->scope)); } else { - ret = talloc_asprintf(mem_ctx, "%s<%02x>", - nbt_hex_encode(tmp_ctx, name->name), + ret = talloc_asprintf(mem_ctx, "%s<%02x>", + nbt_hex_encode(tmp_ctx, name->name), name->type); } talloc_free(tmp_ctx); @@ -518,7 +517,7 @@ _PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len); NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); - NDR_PULL_ALLOC(ndr, r); + NDR_PULL_ALLOC(ndr, r); /* oh wow, what a nasty bug in windows ... */ if (namebuf[0] == 0x1b && namebuf_len >= 16) { @@ -565,7 +564,7 @@ _PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr { uint8_t *namebuf; uint32_t namebuf_len; - uint32_t name_len; + uint32_t _name_len; uint32_t scope_len = 0; if (r == NULL) { @@ -577,8 +576,8 @@ _PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr return NDR_ERR_SUCCESS; } - name_len = strlen(r->name); - if (name_len > 15) { + _name_len = strlen(r->name); + if (_name_len > 15) { return ndr_push_error(ndr, NDR_ERR_STRING, "wrepl_nbt_name longer as 15 chars: %s", r->name); diff --git a/source4/libcli/nbt/nbtsocket.c b/libcli/nbt/nbtsocket.c index 5d4611e2d9..57531d2e7b 100644 --- a/source4/libcli/nbt/nbtsocket.c +++ b/libcli/nbt/nbtsocket.c @@ -1,20 +1,20 @@ -/* +/* Unix SMB/CIFS implementation. low level socket handling for nbt requests Copyright (C) Andrew Tridgell 2005 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -22,7 +22,7 @@ #include "includes.h" #include "lib/events/events.h" #include "lib/util/dlinklist.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "lib/socket/socket.h" #include "librpc/gen_ndr/ndr_nbt.h" #include "param/param.h" @@ -33,7 +33,7 @@ destroy a pending request */ static int nbt_name_request_destructor(struct nbt_name_request *req) -{ +{ if (req->state == NBT_REQUEST_SEND) { DLIST_REMOVE(req->nbtsock->send_queue, req); } @@ -51,7 +51,7 @@ static int nbt_name_request_destructor(struct nbt_name_request *req) if (req->nbtsock->send_queue == NULL) { EVENT_FD_NOT_WRITEABLE(req->nbtsock->fde); } - if (req->nbtsock->num_pending == 0 && + if (req->nbtsock->num_pending == 0 && req->nbtsock->incoming.handler == NULL) { EVENT_FD_NOT_READABLE(req->nbtsock->fde); } @@ -70,11 +70,11 @@ static void nbt_name_socket_send(struct nbt_name_socket *nbtsock) while ((req = nbtsock->send_queue)) { size_t len; - + len = req->encoded.length; - status = socket_sendto(nbtsock->sock, &req->encoded, &len, + status = socket_sendto(nbtsock->sock, &req->encoded, &len, req->dest); - if (NT_STATUS_IS_ERR(status)) goto failed; + if (NT_STATUS_IS_ERR(status)) goto failed; if (!NT_STATUS_IS_OK(status)) { talloc_free(tmp_ctx); @@ -116,17 +116,17 @@ failed: static void nbt_name_socket_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *private) { - struct nbt_name_request *req = talloc_get_type(private, + struct nbt_name_request *req = talloc_get_type(private, struct nbt_name_request); if (req->num_retries != 0) { req->num_retries--; - req->te = event_add_timed(req->nbtsock->event_ctx, req, + req->te = event_add_timed(req->nbtsock->event_ctx, req, timeval_add(&t, req->timeout, 0), nbt_name_socket_timeout, req); if (req->state != NBT_REQUEST_SEND) { req->state = NBT_REQUEST_SEND; - DLIST_ADD_END(req->nbtsock->send_queue, req, + DLIST_ADD_END(req->nbtsock->send_queue, req, struct nbt_name_request *); } EVENT_FD_WRITEABLE(req->nbtsock->fde); @@ -201,7 +201,7 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) } if (DEBUGLVL(10)) { - DEBUG(10,("Received nbt packet of length %d from %s:%d\n", + DEBUG(10,("Received nbt packet of length %d from %s:%d\n", (int)blob.length, src->addr, src->port)); NDR_PRINT_DEBUG(nbt_name_packet, packet); } @@ -217,7 +217,7 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) } /* find the matching request */ - req = (struct nbt_name_request *)idr_find(nbtsock->idr, + req = (struct nbt_name_request *)idr_find(nbtsock->idr, packet->name_trn_id); if (req == NULL) { if (nbtsock->unexpected.handler) { @@ -245,15 +245,15 @@ static void nbt_name_socket_recv(struct nbt_name_socket *nbtsock) req->num_retries = 0; req->received_wack = true; /* although there can be a timeout in the packet, w2k3 screws it up, - so better to set it ourselves */ + so better to set it ourselves */ req->timeout = lp_parm_int(global_loadparm, NULL, "nbt", "wack_timeout", 30); - req->te = event_add_timed(req->nbtsock->event_ctx, req, + req->te = event_add_timed(req->nbtsock->event_ctx, req, timeval_current_ofs(req->timeout, 0), nbt_name_socket_timeout, req); talloc_free(tmp_ctx); return; } - + req->replies = talloc_realloc(req, req->replies, struct nbt_name_reply, req->num_replies+1); if (req->replies == NULL) { @@ -293,11 +293,11 @@ done: static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *fde, uint16_t flags, void *private) { - struct nbt_name_socket *nbtsock = talloc_get_type(private, + struct nbt_name_socket *nbtsock = talloc_get_type(private, struct nbt_name_socket); if (flags & EVENT_FD_WRITE) { nbt_name_socket_send(nbtsock); - } + } if (flags & EVENT_FD_READ) { nbt_name_socket_recv(nbtsock); } @@ -308,7 +308,7 @@ static void nbt_name_socket_handler(struct event_context *ev, struct fd_event *f initialise a nbt_name_socket. The event_ctx is optional, if provided then operations will use that event context */ -_PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, +_PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, struct event_context *event_ctx, struct smb_iconv_convenience *iconv_convenience) { @@ -337,10 +337,10 @@ _PUBLIC_ struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, nbtsock->unexpected.handler = NULL; nbtsock->iconv_convenience = iconv_convenience; - nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock, + nbtsock->fde = event_add_fd(nbtsock->event_ctx, nbtsock, socket_get_fd(nbtsock->sock), 0, nbt_name_socket_handler, nbtsock); - + return nbtsock; failed: @@ -351,7 +351,7 @@ failed: /* send off a nbt name request */ -struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, +struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, struct socket_address *dest, struct nbt_name_packet *request, int timeout, int retries, @@ -378,7 +378,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, id = idr_get_new_random(req->nbtsock->idr, req, UINT16_MAX); } else { if (idr_find(req->nbtsock->idr, request->name_trn_id)) goto failed; - id = idr_get_new_above(req->nbtsock->idr, req, request->name_trn_id, + id = idr_get_new_above(req->nbtsock->idr, req, request->name_trn_id, UINT16_MAX); } if (id == -1) goto failed; @@ -386,13 +386,13 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, request->name_trn_id = id; req->name_trn_id = id; - req->te = event_add_timed(nbtsock->event_ctx, req, + req->te = event_add_timed(nbtsock->event_ctx, req, timeval_current_ofs(req->timeout, 0), nbt_name_socket_timeout, req); - - talloc_set_destructor(req, nbt_name_request_destructor); - ndr_err = ndr_push_struct_blob(&req->encoded, req, + talloc_set_destructor(req, nbt_name_request_destructor); + + ndr_err = ndr_push_struct_blob(&req->encoded, req, req->nbtsock->iconv_convenience, request, (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); @@ -401,7 +401,7 @@ struct nbt_name_request *nbt_name_request_send(struct nbt_name_socket *nbtsock, DLIST_ADD_END(nbtsock->send_queue, req, struct nbt_name_request *); if (DEBUGLVL(10)) { - DEBUG(10,("Queueing nbt packet to %s:%d\n", + DEBUG(10,("Queueing nbt packet to %s:%d\n", req->dest->addr, req->dest->port)); NDR_PRINT_DEBUG(nbt_name_packet, request); } @@ -419,7 +419,7 @@ failed: /* send off a nbt name reply */ -_PUBLIC_ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, +_PUBLIC_ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, struct socket_address *dest, struct nbt_name_packet *request) { @@ -435,13 +435,13 @@ _PUBLIC_ NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, req->state = NBT_REQUEST_SEND; req->is_reply = true; - talloc_set_destructor(req, nbt_name_request_destructor); + talloc_set_destructor(req, nbt_name_request_destructor); if (DEBUGLVL(10)) { - NDR_PRINT_DEBUG(nbt_name_packet, request); + NDR_PRINT_DEBUG(nbt_name_packet, request); } - ndr_err = ndr_push_struct_blob(&req->encoded, req, + ndr_err = ndr_push_struct_blob(&req->encoded, req, req->nbtsock->iconv_convenience, request, (ndr_push_flags_fn_t)ndr_push_nbt_name_packet); @@ -483,12 +483,12 @@ NTSTATUS nbt_name_request_recv(struct nbt_name_request *req) setup a handler for incoming requests */ _PUBLIC_ NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, + void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, struct socket_address *), void *private) { nbtsock->incoming.handler = handler; - nbtsock->incoming.private = private; + nbtsock->incoming.private_data = private; EVENT_FD_READABLE(nbtsock->fde); return NT_STATUS_OK; } diff --git a/source4/libcli/nbt/pynbt.c b/libcli/nbt/pynbt.c index e91096630a..e49c1776a3 100644 --- a/source4/libcli/nbt/pynbt.c +++ b/libcli/nbt/pynbt.c @@ -1,18 +1,18 @@ -/* +/* Unix SMB/CIFS implementation. Samba utility functions Copyright © Jelmer Vernooij <jelmer@samba.org> 2008 - + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. - + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. */ @@ -20,7 +20,7 @@ #include "includes.h" #include <Python.h> #include "libcli/util/pyerrors.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "lib/events/events.h" #include "param/param.h" @@ -48,7 +48,7 @@ static PyObject *py_nbt_node_init(PyTypeObject *self, PyObject *args, PyObject * return NULL; ev = s4_event_context_init(ret->mem_ctx); - ret->socket = nbt_name_socket_init(ret->mem_ctx, ev, lp_iconv_convenience(global_loadparm)); + ret->socket = nbt_name_socket_init(ret->mem_ctx, ev, lp_iconv_convenience(global_loadparm)); return (PyObject *)ret; } @@ -58,14 +58,14 @@ static bool PyObject_AsDestinationTuple(PyObject *obj, const char **dest_addr, u *dest_addr = PyString_AsString(obj); *dest_port = NBT_NAME_SERVICE_PORT; return true; - } + } if (PyTuple_Check(obj)) { if (PyTuple_Size(obj) < 1) { PyErr_SetString(PyExc_TypeError, "Destination tuple size invalid"); return false; } - + if (!PyString_Check(PyTuple_GetItem(obj, 0))) { PyErr_SetString(PyExc_TypeError, "Destination tuple first element not string"); return false; @@ -120,7 +120,7 @@ static bool PyObject_AsNBTName(PyObject *obj, struct nbt_name_socket *socket, st return false; } -static PyObject *PyObject_FromNBTName(struct nbt_name_socket *socket, struct smb_iconv_convenience *ic, +static PyObject *PyObject_FromNBTName(struct nbt_name_socket *socket, struct smb_iconv_convenience *ic, struct nbt_name *name) { if (name->scope) { @@ -145,10 +145,10 @@ static PyObject *py_nbt_name_query(PyObject *self, PyObject *args, PyObject *kwa io.in.timeout = 0; io.in.retries = 3; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bbii:query_name", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|bbii:query_name", discard_const_p(char *, kwnames), - &py_name, &py_dest, - &io.in.broadcast, &io.in.wins_lookup, + &py_name, &py_dest, + &io.in.broadcast, &io.in.wins_lookup, &io.in.timeout, &io.in.retries)) { return NULL; } @@ -182,7 +182,7 @@ static PyObject *py_nbt_name_query(PyObject *self, PyObject *args, PyObject *kwa Py_DECREF(ret); return NULL; } - + for (i = 0; i < io.out.num_addrs; i++) { PyList_SetItem(reply_addrs, i, PyString_FromString(io.out.reply_addrs[i])); } @@ -204,9 +204,9 @@ static PyObject *py_nbt_name_status(PyObject *self, PyObject *args, PyObject *kw io.in.timeout = 0; io.in.retries = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ii:name_status", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OO|ii:name_status", discard_const_p(char *, kwnames), - &py_name, &py_dest, + &py_name, &py_dest, &io.in.timeout, &io.in.retries)) { return NULL; } @@ -238,9 +238,9 @@ static PyObject *py_nbt_name_status(PyObject *self, PyObject *args, PyObject *kw py_names = PyList_New(io.out.status.num_names); for (i = 0; i < io.out.status.num_names; i++) { - PyList_SetItem(py_names, i, Py_BuildValue("(sii)", + PyList_SetItem(py_names, i, Py_BuildValue("(sii)", io.out.status.names[i].name, - io.out.status.names[i].nb_flags, + io.out.status.names[i].nb_flags, io.out.status.names[i].type)); } @@ -256,7 +256,7 @@ static PyObject *py_nbt_name_register(PyObject *self, PyObject *args, PyObject * struct nbt_name_register io; NTSTATUS status; - const char *kwnames[] = { "name", "address", "dest", "register_demand", "broadcast", + const char *kwnames[] = { "name", "address", "dest", "register_demand", "broadcast", "multi_homed", "ttl", "timeout", "retries", NULL }; io.in.broadcast = true; @@ -265,11 +265,11 @@ static PyObject *py_nbt_name_register(PyObject *self, PyObject *args, PyObject * io.in.timeout = 0; io.in.retries = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|bbbiii:query_name", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|bbbiii:query_name", discard_const_p(char *, kwnames), - &py_name, &io.in.address, &py_dest, - &io.in.register_demand, - &io.in.broadcast, &io.in.multi_homed, + &py_name, &io.in.address, &py_dest, + &io.in.register_demand, + &io.in.broadcast, &io.in.multi_homed, &io.in.ttl, &io.in.timeout, &io.in.retries)) { return NULL; } @@ -312,7 +312,7 @@ static PyObject *py_nbt_name_refresh(PyObject *self, PyObject *args, PyObject *k struct nbt_name_refresh io; NTSTATUS status; - const char *kwnames[] = { "name", "address", "dest", "nb_flags", "broadcast", + const char *kwnames[] = { "name", "address", "dest", "nb_flags", "broadcast", "ttl", "timeout", "retries", NULL }; io.in.broadcast = true; @@ -320,11 +320,11 @@ static PyObject *py_nbt_name_refresh(PyObject *self, PyObject *args, PyObject *k io.in.timeout = 0; io.in.retries = 0; - if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|ibiii:query_name", + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OsO|ibiii:query_name", discard_const_p(char *, kwnames), - &py_name, &io.in.address, &py_dest, - &io.in.nb_flags, - &io.in.broadcast, + &py_name, &io.in.address, &py_dest, + &io.in.nb_flags, + &io.in.broadcast, &io.in.ttl, &io.in.timeout, &io.in.retries)) { return NULL; } @@ -366,7 +366,7 @@ static PyObject *py_nbt_name_release(PyObject *self, PyObject *args, PyObject *k } static PyMethodDef py_nbt_methods[] = { - { "query_name", (PyCFunction)py_nbt_name_query, METH_VARARGS|METH_KEYWORDS, + { "query_name", (PyCFunction)py_nbt_name_query, METH_VARARGS|METH_KEYWORDS, "S.query_name(name, dest, broadcast=True, wins=False, timeout=0, retries=3) -> (reply_from, name, reply_addr)\n" "Query for a NetBIOS name" }, { "register_name", (PyCFunction)py_nbt_name_register, METH_VARARGS|METH_KEYWORDS, @@ -17,7 +17,7 @@ pidl - An IDL compiler written in Perl pidl --help -pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--ejs[=OUTPUT]] [--python[=OUTPUT]] [--swig[=OUTPUT]] [--ndr-parser[=OUTPUT]] [--client] [--server] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [--typelib=[OUTPUT]] [<idlfile>.idl]... +pidl [--outputdir[=OUTNAME]] [--includedir DIR...] [--parse-idl-tree] [--dump-idl-tree] [--dump-ndr-tree] [--header[=OUTPUT]] [--python[=OUTPUT]] [--swig[=OUTPUT]] [--ndr-parser[=OUTPUT]] [--client] [--server] [--warn-compat] [--quiet] [--verbose] [--template] [--ws-parser[=OUTPUT]] [--diff] [--dump-idl] [--tdr-parser[=OUTPUT]] [--samba3-ndr-client[=OUTPUT]] [--samba3-ndr-server[=OUTPUT]] [--typelib=[OUTPUT]] [<idlfile>.idl]... =head1 DESCRIPTION @@ -478,7 +478,6 @@ my($opt_ndr_parser); my($opt_tdr_parser); my($opt_ws_parser); my($opt_swig); -my($opt_ejs); my($opt_python); my($opt_quiet) = 0; my($opt_outputdir) = '.'; @@ -521,7 +520,6 @@ Samba 4 output: --ndr-parser[=OUTFILE] create a C NDR parser [ndr_BASENAME.c] --client[=OUTFILE] create a C NDR client [ndr_BASENAME_c.c] --tdr-parser[=OUTFILE] create a C TDR parser [tdr_BASENAME.c] - --ejs[=OUTFILE] create ejs wrapper file [BASENAME_ejs.c] --python[=OUTFILE] create python wrapper file [py_BASENAME.c] --swig[=OUTFILE] create swig wrapper file [BASENAME.i] --server[=OUTFILE] create server boilerplate [ndr_BASENAME_s.c] @@ -567,7 +565,6 @@ my $result = GetOptions ( 'ndr-parser:s' => \$opt_ndr_parser, 'client:s' => \$opt_client, 'ws-parser:s' => \$opt_ws_parser, - 'ejs' => \$opt_ejs, 'python' => \$opt_python, 'diff' => \$opt_diff, 'swig:s' => \$opt_swig, @@ -664,7 +661,6 @@ sub process_file($) defined($opt_server) or defined($opt_header) or defined($opt_ndr_parser) or - defined($opt_ejs) or defined($opt_python) or defined($opt_dump_ndr_tree) or defined($opt_samba3_header) or @@ -709,14 +705,6 @@ sub process_file($) FileSave($filename, $code); } - if (defined($opt_ejs)) { - require Parse::Pidl::Samba4::EJS; - my $generator = new Parse::Pidl::Samba4::EJS(); - my ($hdr,$prsr) = $generator->Parse($ndr, $h_filename); - FileSave("$outputdir/ndr_$basename\_ejs.c", $prsr); - FileSave("$outputdir/ndr_$basename\_ejs.h", $hdr); - } - if (defined($opt_python)) { require Parse::Pidl::Samba4::Python; my $generator = new Parse::Pidl::Samba4::Python(); diff --git a/release-scripts/create-tarball b/release-scripts/create-tarball index 3463f012a5..04728d835d 100755 --- a/release-scripts/create-tarball +++ b/release-scripts/create-tarball @@ -7,7 +7,7 @@ OPT_TAG="" OPT_KEYID="" TOPDIR="`dirname $0`/.." -VER_H="${TOPDIR}/source/include/version.h" +VER_H="${TOPDIR}/source3/include/version.h" function exitOnError { @@ -38,7 +38,7 @@ function printUsage } ## -## Parse the command line options +## Parse the command line options ## function parseOptions @@ -115,7 +115,7 @@ function buildDocs rsync -av "${OPT_DOCSDIR}"/ docs/ exitOnError $? "Failed top copy docs from ${OPT_DOCSDIR}" - + return 0 fi @@ -163,23 +163,23 @@ function createReleaseTag ## ## Main driver ## -function main +function main { parseOptions "$@" exitOnError $? "Failed to parse options" - + cd $TOPDIR git-checkout ${OPT_BRANCH} exitOnError $? "Invalid branch name \"${OPT_BRANCH}\"" - (cd source && ./script/mkversion.sh) + (cd source3 && ./script/mkversion.sh) if [ ! -f $VER_H ]; then exitOnError 1 "Failed to find ${VER_H}!" fi - version=`grep SAMBA_VERSION_OFFICIAL_STRING $VER_H | awk '{print $3}'` - vendor_version=`grep SAMBA_VERSION_VENDOR_SUFFIX $VER_H | awk '{print $3}'` + version=`grep "define SAMBA_VERSION_OFFICIAL_STRING" $VER_H | awk '{print $3}'` + vendor_version=`grep "define SAMBA_VERSION_VENDOR_SUFFIX" $VER_H | awk '{print $3}'` if [ -n "$vendor_version" ]; then version="$version-$vendor_version" fi @@ -198,7 +198,7 @@ function main buildDocs exitOnError $? "Failed to build documentation" - ( cd source && ./autogen.sh ) + ( cd source3 && ./autogen.sh ) cd .. tar cf samba-${version}.tar --exclude=.git* --exclude=CVS --exclude=.svn samba-${version} diff --git a/source3/Makefile.in b/source3/Makefile.in index 2300e4a20c..94d8d50da8 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -376,7 +376,7 @@ LIBADS_SERVER_OBJ = libads/kerberos_verify.o libads/authdata.o \ SECRETS_OBJ = passdb/secrets.o passdb/machine_sid.o -LIBNBT_OBJ = libcli/nbt/nbtname.o \ +LIBNBT_OBJ = ../libcli/nbt/nbtname.o \ librpc/gen_ndr/ndr_nbt.o \ librpc/gen_ndr/ndr_svcctl.o @@ -946,13 +946,14 @@ SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ $(LIBSAMBA_OBJ) \ $(POPT_LIB_OBJ) -TALLOCTORT_OBJ = @tallocdir@/testsuite.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ - $(LIBSAMBA_OBJ) +TALLOCTORT_OBJ = @tallocdir@/testsuite.o @tallocdir@/testsuite_main.o \ + $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSAMBA_OBJ) REPLACETORT_OBJ = @libreplacedir@/test/testsuite.o \ @libreplacedir@/test/getifaddrs.o \ @libreplacedir@/test/os2_delete.o \ @libreplacedir@/test/strptime.o \ + @libreplacedir@/test/main.o \ $(LIBREPLACE_OBJ) NDRDUMP_OBJ = librpc/tools/ndrdump.o \ @@ -984,6 +985,14 @@ IDMAP_HASH_OBJ = \ winbindd/idmap_hash/idmap_hash.o \ winbindd/idmap_hash/mapfile.o +IDMAP_ADEX_OBJ = \ + winbindd/idmap_adex/idmap_adex.o \ + winbindd/idmap_adex/cell_util.o \ + winbindd/idmap_adex/likewise_cell.o \ + winbindd/idmap_adex/provider_unified.o \ + winbindd/idmap_adex/gc_util.o \ + winbindd/idmap_adex/domain_util.o + WINBINDD_OBJ1 = \ winbindd/winbindd.o \ winbindd/winbindd_user.o \ @@ -2217,6 +2226,10 @@ bin/hash.@SHLIBEXT@: $(BINARY_PREREQS) $(IDMAP_HASH_OBJ) @echo "Building plugin $@" @$(SHLD_MODULE) $(IDMAP_HASH_OBJ) +bin/adex.@SHLIBEXT@: $(BINARY_PREREQS) $(IDMAP_ADEX_OBJ) + @echo "Building plugin $@" + @$(SHLD_MODULE) $(IDMAP_ADEX_OBJ) + bin/tdb2.@SHLIBEXT@: $(BINARY_PREREQS) winbindd/idmap_tdb2.o @echo "Building plugin $@" @$(SHLD_MODULE) winbindd/idmap_tdb2.o diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index 3b56e5f861..b7a76c6102 100644 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -56,6 +56,10 @@ #endif /* _SAMBA_BUILD_ */ #endif /* MOUNT_CIFS_VENDOR_SUFFIX */ +#ifdef _SAMBA_BUILD_ +#include "include/config.h" +#endif + #ifndef MS_MOVE #define MS_MOVE 8192 #endif @@ -94,6 +98,8 @@ char * prefixpath = NULL; /* like strncpy but does not 0 fill the buffer and always null * terminates. bufsize is the size of the destination buffer */ + +#ifndef HAVE_STRLCPY static size_t strlcpy(char *d, const char *s, size_t bufsize) { size_t len = strlen(s); @@ -104,10 +110,13 @@ static size_t strlcpy(char *d, const char *s, size_t bufsize) d[len] = 0; return ret; } +#endif /* like strncat but does not 0 fill the buffer and always null * terminates. bufsize is the length of the buffer, which should * be one more than the maximum resulting string length */ + +#ifndef HAVE_STRLCAT static size_t strlcat(char *d, const char *s, size_t bufsize) { size_t len1 = strlen(d); @@ -126,6 +135,7 @@ static size_t strlcat(char *d, const char *s, size_t bufsize) } return ret; } +#endif /* BB finish BB diff --git a/source3/configure.in b/source3/configure.in index 640afc47fb..f23f6b55be 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -6058,6 +6058,7 @@ SMB_MODULE(idmap_nss, winbindd/idmap_nss.o, "bin/nss.$SHLIBEXT", IDMAP) SMB_MODULE(idmap_rid, winbindd/idmap_rid.o, "bin/rid.$SHLIBEXT", IDMAP) SMB_MODULE(idmap_ad, winbindd/idmap_ad.o, "bin/ad.$SHLIBEXT", IDMAP) SMB_MODULE(idmap_hash, \$(IDMAP_HASH_OBJ), "bin/hash.$SHLIBEXT", IDMAP) +SMB_MODULE(idmap_adex, \$(IDMAP_ADEX_OBJ), "bin/adex.$SHLIBEXT", IDMAP) SMB_SUBSYSTEM(IDMAP, winbindd/idmap.o) SMB_MODULE(nss_info_template, winbindd/nss_info_template.o, "bin/template.$SHLIBEXT", NSS_INFO) @@ -6271,8 +6272,10 @@ fi SMBD_LIBS="$samba_dmapi_libs" AC_SUBST(SMBD_LIBS) +CFLAGS="${CFLAGS} \$(FLAGS)" + if test x$MERGED_BUILD != x1; then - CFLAGS="${CFLAGS} \$(FLAGS) -D_SAMBA_BUILD_=3" + CFLAGS="${CFLAGS} -D_SAMBA_BUILD_=3" fi AC_OUTPUT(Makefile diff --git a/source3/include/charset.h b/source3/include/charset.h index 4d04b5a1a6..1c2a5fb5f0 100644 --- a/source3/include/charset.h +++ b/source3/include/charset.h @@ -18,6 +18,8 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ +struct smb_iconv_convenience; + /* this defines the charset types used in samba */ typedef enum {CH_UTF16LE=0, CH_UTF16=0, CH_UNIX=1, CH_DISPLAY=2, CH_DOS=3, CH_UTF8=4, CH_UTF16BE=5} charset_t; diff --git a/source3/include/proto.h b/source3/include/proto.h index 2901911c70..a2772384c5 100644 --- a/source3/include/proto.h +++ b/source3/include/proto.h @@ -2204,23 +2204,6 @@ ADS_STATUS ads_change_trust_account_password(ADS_STRUCT *ads, char *host_princip ADS_STATUS ads_guess_service_principal(ADS_STRUCT *ads, char **returned_principal); -/* The following definitions come from libcli/nbt/nbtname.c */ - -_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s); -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s); -_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s); -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r); -_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r); -_PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname); -_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name); -_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name); -_PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx, - struct nbt_name *n, const char *name, int type); -_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name); -_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r); -_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r); -_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r); - /* The following definitions come from libgpo/gpext/gpext.c */ struct gp_extension *get_gp_extension_list(void); @@ -3960,16 +3943,14 @@ _PUBLIC_ enum ndr_err_code ndr_print_set_switch_value(struct ndr_print *ndr, con _PUBLIC_ uint32_t ndr_push_get_switch_value(struct ndr_push *ndr, const void *p); _PUBLIC_ uint32_t ndr_pull_get_switch_value(struct ndr_pull *ndr, const void *p); _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void *p); -_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, - ndr_pull_flags_fn_t fn); +_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, void *p, ndr_pull_flags_fn_t fn); _PUBLIC_ enum ndr_err_code ndr_pull_struct_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, ndr_pull_flags_fn_t fn); _PUBLIC_ enum ndr_err_code ndr_pull_union_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn); _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_pull_flags_fn_t fn); -_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, - ndr_push_flags_fn_t fn); +_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, const void *p, ndr_push_flags_fn_t fn); _PUBLIC_ enum ndr_err_code ndr_push_union_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, uint32_t level, ndr_push_flags_fn_t fn); _PUBLIC_ size_t ndr_size_struct(const void *p, int flags, ndr_push_flags_fn_t push); @@ -7049,6 +7030,12 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, DATA_BLOB lm_response, DATA_BLOB nt_response, struct netr_SamInfo3 **info3); +NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const unsigned char orig_trust_passwd_hash[16], + const char *new_trust_pwd_cleartext, + const unsigned char new_trust_passwd_hash[16], + uint32_t sec_channel_type); /* The following definitions come from rpc_client/cli_pipe.c */ @@ -7427,6 +7414,9 @@ void init_netr_PasswordInfo(struct netr_PasswordInfo *r, const char *workstation, struct samr_Password lmpassword, struct samr_Password ntpassword); +void init_netr_CryptPassword(const char *pwd, + unsigned char session_key[16], + struct netr_CryptPassword *pwd_buf); /* The following definitions come from rpc_client/init_samr.c */ diff --git a/source3/lib/messages_local.c b/source3/lib/messages_local.c index f436afc2ff..9f7f88f783 100644 --- a/source3/lib/messages_local.c +++ b/source3/lib/messages_local.c @@ -160,7 +160,7 @@ static NTSTATUS messaging_tdb_fetch(TDB_CONTEXT *msg_tdb, blob = data_blob_const(data.dptr, data.dsize); ndr_err = ndr_pull_struct_blob( - &blob, result, result, + &blob, result, NULL, result, (ndr_pull_flags_fn_t)ndr_pull_messaging_array); SAFE_FREE(data.dptr); @@ -203,7 +203,7 @@ static NTSTATUS messaging_tdb_store(TDB_CONTEXT *msg_tdb, } ndr_err = ndr_push_struct_blob( - &blob, mem_ctx, array, + &blob, mem_ctx, NULL, array, (ndr_push_flags_fn_t)ndr_push_messaging_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { diff --git a/source3/lib/netapi/examples/user/user_modalsset.c b/source3/lib/netapi/examples/user/user_modalsset.c index 57e1ef70ea..c6958a9012 100644 --- a/source3/lib/netapi/examples/user/user_modalsset.c +++ b/source3/lib/netapi/examples/user/user_modalsset.c @@ -95,6 +95,7 @@ int main(int argc, const char **argv) case 1: case 2: case 3: + break; case 1001: u1001.usrmod1001_min_passwd_len = 0; buffer = (uint8_t *)&u1001; diff --git a/source3/lib/netapi/tests/Makefile.in b/source3/lib/netapi/tests/Makefile.in index 0145753212..659f82c9d8 100644 --- a/source3/lib/netapi/tests/Makefile.in +++ b/source3/lib/netapi/tests/Makefile.in @@ -44,7 +44,7 @@ bin/.dummy: CMDLINE_OBJ = common.o NETAPIBUFFER_OBJ = netapibuffer.o -NETAPITEST_OBJ = netapitest.o netlocalgroup.o netuser.o netgroup.o netdisplay.o netshare.o $(CMDLINE_OBJ) +NETAPITEST_OBJ = netapitest.o netlocalgroup.o netuser.o netgroup.o netdisplay.o netshare.o netfile.o $(CMDLINE_OBJ) bin/netapitest@EXEEXT@: $(BINARY_PREREQS) $(NETAPITEST_OBJ) @echo Linking $@ diff --git a/source3/lib/netapi/tests/common.h b/source3/lib/netapi/tests/common.h index 5a320321ba..9320840909 100644 --- a/source3/lib/netapi/tests/common.h +++ b/source3/lib/netapi/tests/common.h @@ -41,6 +41,8 @@ NET_API_STATUS netapitest_display(struct libnetapi_ctx *ctx, const char *hostname); NET_API_STATUS netapitest_share(struct libnetapi_ctx *ctx, const char *hostname); +NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx, + const char *hostname); #ifndef ARRAY_SIZE #define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/source3/lib/netapi/tests/netapitest.c b/source3/lib/netapi/tests/netapitest.c index 87144020f5..4a38f721d8 100644 --- a/source3/lib/netapi/tests/netapitest.c +++ b/source3/lib/netapi/tests/netapitest.c @@ -84,6 +84,11 @@ int main(int argc, const char **argv) goto out; } + status = netapitest_file(ctx, hostname); + if (status) { + goto out; + } + out: if (status != 0) { printf("testsuite failed with: %s\n", diff --git a/source3/lib/netapi/tests/netfile.c b/source3/lib/netapi/tests/netfile.c new file mode 100644 index 0000000000..36ee8288ee --- /dev/null +++ b/source3/lib/netapi/tests/netfile.c @@ -0,0 +1,143 @@ +/* + * Unix SMB/CIFS implementation. + * NetFile testsuite + * Copyright (C) Guenther Deschner 2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <sys/types.h> +#include <inttypes.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <netapi.h> + +#include "common.h" + +static NET_API_STATUS test_netfileenum(const char *hostname, + uint32_t level) +{ + NET_API_STATUS status; + uint32_t entries_read = 0; + uint32_t total_entries = 0; + uint32_t resume_handle = 0; + uint8_t *buffer = NULL; + int i; + + struct FILE_INFO_2 *i2; + struct FILE_INFO_3 *i3; + + printf("testing NetFileEnum level %d\n", level); + + do { + status = NetFileEnum(hostname, + NULL, + NULL, + level, + &buffer, + (uint32_t)-1, + &entries_read, + &total_entries, + &resume_handle); + if (status == 0 || status == ERROR_MORE_DATA) { + switch (level) { + case 2: + i2 = (struct FILE_INFO_2 *)buffer; + break; + case 3: + i3 = (struct FILE_INFO_3 *)buffer; + break; + default: + return -1; + } + + for (i=0; i<entries_read; i++) { + + switch (level) { + case 2: + case 3: + break; + default: + break; + } + + switch (level) { + case 2: + i2++; + break; + case 3: + i3++; + break; + } + } + NetApiBufferFree(buffer); + } + } while (status == ERROR_MORE_DATA); + + if (status) { + return status; + } + + return 0; +} + +NET_API_STATUS netapitest_file(struct libnetapi_ctx *ctx, + const char *hostname) +{ + NET_API_STATUS status = 0; + uint8_t *buffer = NULL; + uint32_t levels[] = { 2, 3 }; + uint32_t enum_levels[] = { 2, 3 }; + int i; + + printf("NetFile tests\n"); + + /* test enum */ + + for (i=0; i<ARRAY_SIZE(enum_levels); i++) { + + status = test_netfileenum(hostname, enum_levels[i]); + if (status) { + NETAPI_STATUS(ctx, status, "NetFileEnum"); + goto out; + } + } + + /* basic queries */ +#if 0 + for (i=0; i<ARRAY_SIZE(levels); i++) { + + printf("testing NetFileGetInfo level %d\n", levels[i]); + + status = NetFileGetInfo(hostname, fid, levels[i], &buffer); + if (status && status != 124) { + NETAPI_STATUS(ctx, status, "NetFileGetInfo"); + goto out; + } + } +#endif + + status = 0; + + printf("NetFile tests succeeded\n"); + out: + if (status != 0) { + printf("NetFile testsuite failed with: %s\n", + libnetapi_get_error_string(ctx, status)); + } + + return status; +} diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c index 44ae23271e..4965200bc1 100644 --- a/source3/lib/secdesc.c +++ b/source3/lib/secdesc.c @@ -249,7 +249,7 @@ NTSTATUS marshall_sec_desc(TALLOC_CTX *mem_ctx, enum ndr_err_code ndr_err; ndr_err = ndr_push_struct_blob( - &blob, mem_ctx, secdesc, + &blob, mem_ctx, NULL, secdesc, (ndr_push_flags_fn_t)ndr_push_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -285,7 +285,7 @@ NTSTATUS unmarshall_sec_desc(TALLOC_CTX *mem_ctx, uint8 *data, size_t len, blob = data_blob_const(data, len); ndr_err = ndr_pull_struct_blob( - &blob, result, result, + &blob, result, NULL, result, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 0bde3e6984..40f051c851 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -108,7 +108,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, } ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data, - pac_data, + NULL, pac_data, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -124,7 +124,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, } ndr_err = ndr_pull_struct_blob(pac_data_blob, pac_data_raw, - pac_data_raw, + NULL, pac_data_raw, (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -205,7 +205,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, /* We find the data blobs above, now we parse them to get at the exact portion we should zero */ ndr_err = ndr_pull_struct_blob(kdc_sig_blob, kdc_sig_wipe, - kdc_sig_wipe, + NULL, kdc_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -215,7 +215,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, } ndr_err = ndr_pull_struct_blob(srv_sig_blob, srv_sig_wipe, - srv_sig_wipe, + NULL, srv_sig_wipe, (ndr_pull_flags_fn_t)ndr_pull_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -230,7 +230,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, /* and reencode, back into the same place it came from */ ndr_err = ndr_push_struct_blob(kdc_sig_blob, pac_data_raw, - kdc_sig_wipe, + NULL, kdc_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -239,7 +239,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, return status; } ndr_err = ndr_push_struct_blob(srv_sig_blob, pac_data_raw, - srv_sig_wipe, + NULL, srv_sig_wipe, (ndr_push_flags_fn_t)ndr_push_PAC_SIGNATURE_DATA); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -250,7 +250,7 @@ static krb5_error_code check_pac_checksum(TALLOC_CTX *mem_ctx, /* push out the whole structure, but now with zero'ed signatures */ ndr_err = ndr_push_struct_blob(&modified_pac_blob, pac_data_raw, - pac_data_raw, + NULL, pac_data_raw, (ndr_push_flags_fn_t)ndr_push_PAC_DATA_RAW); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); diff --git a/source3/libads/cldap.c b/source3/libads/cldap.c index 11565065af..73b28b523a 100644 --- a/source3/libads/cldap.c +++ b/source3/libads/cldap.c @@ -294,7 +294,7 @@ bool pull_mailslot_cldap_reply(TALLOC_CTX *mem_ctx, uint32_t nt_version_query = ((*nt_version) & 0x0000001f); uint16_t command = 0; - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, &command, + ndr_err = ndr_pull_struct_blob(blob, mem_ctx, NULL, &command, (ndr_pull_flags_fn_t)ndr_pull_uint16); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; diff --git a/source3/libcli/nbt/nbtname.c b/source3/libcli/nbt/nbtname.c deleted file mode 100644 index fbb9550655..0000000000 --- a/source3/libcli/nbt/nbtname.c +++ /dev/null @@ -1,626 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - manipulate nbt name structures - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -/* - see rfc1002 for the detailed format of compressed names -*/ - -#include "includes.h" -#include "librpc/gen_ndr/ndr_nbt.h" -#include "librpc/gen_ndr/ndr_misc.h" - -/* don't allow an unlimited number of name components */ -#define MAX_COMPONENTS 10 - -/** - print a nbt string -*/ -_PUBLIC_ void ndr_print_nbt_string(struct ndr_print *ndr, const char *name, const char *s) -{ - ndr_print_string(ndr, name, s); -} - -/* - pull one component of a nbt_string -*/ -static enum ndr_err_code ndr_pull_component(struct ndr_pull *ndr, - uint8_t **component, - uint32_t *offset, - uint32_t *max_offset) -{ - uint8_t len; - uint_t loops = 0; - while (loops < 5) { - if (*offset >= ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - len = ndr->data[*offset]; - if (len == 0) { - *offset += 1; - *max_offset = MAX(*max_offset, *offset); - *component = NULL; - return NDR_ERR_SUCCESS; - } - if ((len & 0xC0) == 0xC0) { - /* its a label pointer */ - if (1 + *offset >= ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - *max_offset = MAX(*max_offset, *offset + 2); - *offset = ((len&0x3F)<<8) | ndr->data[1 + *offset]; - *max_offset = MAX(*max_offset, *offset); - loops++; - continue; - } - if ((len & 0xC0) != 0) { - /* its a reserved length field */ - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - if (*offset + len + 2 > ndr->data_size) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME component"); - } - *component = (uint8_t*)talloc_strndup(ndr, (const char *)&ndr->data[1 + *offset], len); - NDR_ERR_HAVE_NO_MEMORY(*component); - *offset += len + 1; - *max_offset = MAX(*max_offset, *offset); - return NDR_ERR_SUCCESS; - } - - /* too many pointers */ - return ndr_pull_error(ndr, NDR_ERR_STRING, "BAD NBT NAME component"); -} - -/** - pull a nbt_string from the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_string(struct ndr_pull *ndr, int ndr_flags, const char **s) -{ - uint32_t offset = ndr->offset; - uint32_t max_offset = offset; - unsigned num_components; - char *name; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - name = NULL; - - /* break up name into a list of components */ - for (num_components=0;num_components<MAX_COMPONENTS;num_components++) { - uint8_t *component = NULL; - NDR_CHECK(ndr_pull_component(ndr, &component, &offset, &max_offset)); - if (component == NULL) break; - if (name) { - name = talloc_asprintf_append_buffer(name, ".%s", component); - NDR_ERR_HAVE_NO_MEMORY(name); - } else { - name = (char *)component; - } - } - if (num_components == MAX_COMPONENTS) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "BAD NBT NAME too many components"); - } - if (num_components == 0) { - name = talloc_strdup(ndr, ""); - NDR_ERR_HAVE_NO_MEMORY(name); - } - - (*s) = name; - ndr->offset = max_offset; - - return NDR_ERR_SUCCESS; -} - -/** - push a nbt string to the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_push_nbt_string(struct ndr_push *ndr, int ndr_flags, const char *s) -{ - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - while (s && *s) { - enum ndr_err_code ndr_err; - char *compname; - size_t complen; - uint32_t offset; - - /* see if we have pushed the remaing string allready, - * if so we use a label pointer to this string - */ - ndr_err = ndr_token_retrieve_cmp_fn(&ndr->nbt_string_list, s, &offset, (comparison_fn_t)strcmp, false); - if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - uint8_t b[2]; - - if (offset > 0x3FFF) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "offset for nbt string label pointer %u[%08X] > 0x00003FFF", - offset, offset); - } - - b[0] = 0xC0 | (offset>>8); - b[1] = (offset & 0xFF); - - return ndr_push_bytes(ndr, b, 2); - } - - complen = strcspn(s, "."); - - /* we need to make sure the length fits into 6 bytes */ - if (complen >= 0x3F) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "component length %u[%08X] > 0x00003F", - (unsigned)complen, (unsigned)complen); - } - - compname = talloc_asprintf(ndr, "%c%*.*s", - (unsigned char)complen, - (unsigned char)complen, - (unsigned char)complen, s); - NDR_ERR_HAVE_NO_MEMORY(compname); - - /* remember the current componemt + the rest of the string - * so it can be reused later - */ - NDR_CHECK(ndr_token_store(ndr, &ndr->nbt_string_list, s, ndr->offset)); - - /* push just this component into the blob */ - NDR_CHECK(ndr_push_bytes(ndr, (const uint8_t *)compname, complen+1)); - talloc_free(compname); - - s += complen; - if (*s == '.') s++; - } - - /* if we reach the end of the string and have pushed the last component - * without using a label pointer, we need to terminate the string - */ - return ndr_push_bytes(ndr, (const uint8_t *)"", 1); -} - - -/* - decompress a 'compressed' name component - */ -static bool decompress_name(char *name, enum nbt_name_type *type) -{ - int i; - for (i=0;name[2*i];i++) { - uint8_t c1 = name[2*i]; - uint8_t c2 = name[1+(2*i)]; - if (c1 < 'A' || c1 > 'P' || - c2 < 'A' || c2 > 'P') { - return false; - } - name[i] = ((c1-'A')<<4) | (c2-'A'); - } - name[i] = 0; - if (i == 16) { - *type = (enum nbt_name_type)(name[15]); - name[15] = 0; - i--; - } else { - *type = NBT_NAME_CLIENT; - } - - /* trim trailing spaces */ - for (;i>0 && name[i-1]==' ';i--) { - name[i-1] = 0; - } - - return true; -} - - -/* - compress a name component - */ -static uint8_t *compress_name(TALLOC_CTX *mem_ctx, - const uint8_t *name, enum nbt_name_type type) -{ - uint8_t *cname; - int i; - uint8_t pad_char; - - if (strlen((const char *)name) > 15) { - return NULL; - } - - cname = talloc_array(mem_ctx, uint8_t, 33); - if (cname == NULL) return NULL; - - for (i=0;name[i];i++) { - cname[2*i] = 'A' + (name[i]>>4); - cname[1+2*i] = 'A' + (name[i]&0xF); - } - if (strcmp((const char *)name, "*") == 0) { - pad_char = 0; - } else { - pad_char = ' '; - } - for (;i<15;i++) { - cname[2*i] = 'A' + (pad_char>>4); - cname[1+2*i] = 'A' + (pad_char&0xF); - } - - pad_char = type; - cname[2*i] = 'A' + (pad_char>>4); - cname[1+2*i] = 'A' + (pad_char&0xF); - - cname[32] = 0; - return cname; -} - - -/** - pull a nbt name from the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r) -{ - uint8_t *scope; - char *cname; - const char *s; - bool ok; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - NDR_CHECK(ndr_pull_nbt_string(ndr, ndr_flags, &s)); - - scope = (uint8_t *)strchr(s, '.'); - if (scope) { - *scope = 0; - r->scope = talloc_strdup(ndr->current_mem_ctx, (const char *)&scope[1]); - NDR_ERR_HAVE_NO_MEMORY(r->scope); - } else { - r->scope = NULL; - } - - cname = discard_const_p(char, s); - - /* the first component is limited to 16 bytes in the DOS charset, - which is 32 in the 'compressed' form */ - if (strlen(cname) > 32) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "NBT NAME cname > 32"); - } - - /* decompress the first component */ - ok = decompress_name(cname, &r->type); - if (!ok) { - return ndr_pull_error(ndr, NDR_ERR_STRING, - "NBT NAME failed to decompress"); - } - - r->name = talloc_strdup(ndr->current_mem_ctx, cname); - NDR_ERR_HAVE_NO_MEMORY(r->name); - - talloc_free(cname); - - return NDR_ERR_SUCCESS; -} - -/** - push a nbt name to the wire -*/ -_PUBLIC_ enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r) -{ - uint8_t *cname, *fullname; - enum ndr_err_code ndr_err; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - if (strlen(r->name) > 15) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "nbt_name longer as 15 chars: %s", - r->name); - } - - cname = compress_name(ndr, (const uint8_t *)r->name, r->type); - NDR_ERR_HAVE_NO_MEMORY(cname); - - if (r->scope) { - fullname = (uint8_t *)talloc_asprintf(ndr, "%s.%s", cname, r->scope); - NDR_ERR_HAVE_NO_MEMORY(fullname); - talloc_free(cname); - } else { - fullname = cname; - } - - ndr_err = ndr_push_nbt_string(ndr, ndr_flags, (const char *)fullname); - - return ndr_err; -} - - -/** - copy a nbt name structure -*/ -_PUBLIC_ NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname) -{ - *newname = *name; - newname->name = talloc_strdup(mem_ctx, newname->name); - NT_STATUS_HAVE_NO_MEMORY(newname->name); - newname->scope = talloc_strdup(mem_ctx, newname->scope); - if (name->scope) { - NT_STATUS_HAVE_NO_MEMORY(newname->scope); - } - return NT_STATUS_OK; -} - -/** - push a nbt name into a blob -*/ -_PUBLIC_ NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct nbt_name *name) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_push_struct_blob(blob, mem_ctx, name, (ndr_push_flags_fn_t)ndr_push_nbt_name); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - return NT_STATUS_OK; -} - -/** - pull a nbt name from a blob -*/ -_PUBLIC_ NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name) -{ - enum ndr_err_code ndr_err; - - ndr_err = ndr_pull_struct_blob(blob, mem_ctx, name, - (ndr_pull_flags_fn_t)ndr_pull_nbt_name); - if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { - return ndr_map_error2ntstatus(ndr_err); - } - - return NT_STATUS_OK; -} - - -/** - choose a name to use when calling a server in a NBT session request. - we use heuristics to see if the name we have been given is a IP - address, or a too-long name. If it is then use *SMBSERVER, or a - truncated name -*/ -_PUBLIC_ void nbt_choose_called_name(TALLOC_CTX *mem_ctx, - struct nbt_name *n, const char *name, int type) -{ - n->scope = NULL; - n->type = type; - - if ((name == NULL) || is_ipaddress(name)) { - n->name = "*SMBSERVER"; - return; - } - if (strlen(name) > 15) { - const char *p = strchr(name, '.'); - char *s; - if (p - name > 15) { - n->name = "*SMBSERVER"; - return; - } - s = talloc_strndup(mem_ctx, name, PTR_DIFF(p, name)); - n->name = talloc_strdup_upper(mem_ctx, s); - return; - } - - n->name = talloc_strdup_upper(mem_ctx, name); -} - - -/* - escape a string into a form containing only a small set of characters, - the rest is hex encoded. This is similar to URL encoding -*/ -static const char *nbt_hex_encode(TALLOC_CTX *mem_ctx, const char *s) -{ - int i, len; - char *ret; - const char *valid_chars = "_-.$@ "; -#define NBT_CHAR_ALLOW(c) (isalnum((unsigned char)c) || strchr(valid_chars, c)) - - for (len=i=0;s[i];i++,len++) { - if (!NBT_CHAR_ALLOW(s[i])) { - len += 2; - } - } - - ret = talloc_array(mem_ctx, char, len+1); - if (ret == NULL) return NULL; - - for (len=i=0;s[i];i++) { - if (NBT_CHAR_ALLOW(s[i])) { - ret[len++] = s[i]; - } else { - snprintf(&ret[len], 4, "%%%02x", (unsigned char)s[i]); - len += 3; - } - } - ret[len] = 0; - - return ret; -} - - -/** - form a string for a NBT name -*/ -_PUBLIC_ char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name) -{ - TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx); - char *ret; - if (name->scope) { - ret = talloc_asprintf(mem_ctx, "%s<%02x>-%s", - nbt_hex_encode(tmp_ctx, name->name), - name->type, - nbt_hex_encode(tmp_ctx, name->scope)); - } else { - ret = talloc_asprintf(mem_ctx, "%s<%02x>", - nbt_hex_encode(tmp_ctx, name->name), - name->type); - } - talloc_free(tmp_ctx); - return ret; -} - -/** - pull a nbt name, WINS Replication uses another on wire format for nbt name -*/ -_PUBLIC_ enum ndr_err_code ndr_pull_wrepl_nbt_name(struct ndr_pull *ndr, int ndr_flags, const struct nbt_name **_r) -{ - struct nbt_name *r; - uint8_t *namebuf; - uint32_t namebuf_len; - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - NDR_CHECK(ndr_pull_align(ndr, 4)); - NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &namebuf_len)); - if (namebuf_len < 1 || namebuf_len > 255) { - return ndr_pull_error(ndr, NDR_ERR_ALLOC, "value out of range"); - } - NDR_PULL_ALLOC_N(ndr, namebuf, namebuf_len); - NDR_CHECK(ndr_pull_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); - - NDR_PULL_ALLOC(ndr, r); - - /* oh wow, what a nasty bug in windows ... */ - if (namebuf[0] == 0x1b && namebuf_len >= 16) { - namebuf[0] = namebuf[15]; - namebuf[15] = 0x1b; - } - - if (namebuf_len < 17) { - r->type = 0x00; - - r->name = talloc_strndup(r, (char *)namebuf, namebuf_len); - if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - r->scope= NULL; - - talloc_free(namebuf); - *_r = r; - return NDR_ERR_SUCCESS; - } - - r->type = namebuf[15]; - - namebuf[15] = '\0'; - trim_string((char *)namebuf, NULL, " "); - r->name = talloc_strdup(r, (char *)namebuf); - if (!r->name) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - if (namebuf_len > 18) { - r->scope = talloc_strndup(r, (char *)(namebuf+17), namebuf_len-17); - if (!r->scope) return ndr_pull_error(ndr, NDR_ERR_ALLOC, "out of memory"); - } else { - r->scope = NULL; - } - - talloc_free(namebuf); - *_r = r; - return NDR_ERR_SUCCESS; -} - -/** - push a nbt name, WINS Replication uses another on wire format for nbt name -*/ -_PUBLIC_ enum ndr_err_code ndr_push_wrepl_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r) -{ - uint8_t *namebuf; - uint32_t namebuf_len; - uint32_t _name_len; - uint32_t scope_len = 0; - - if (r == NULL) { - return ndr_push_error(ndr, NDR_ERR_INVALID_POINTER, - "wrepl_nbt_name NULL pointer"); - } - - if (!(ndr_flags & NDR_SCALARS)) { - return NDR_ERR_SUCCESS; - } - - _name_len = strlen(r->name); - if (_name_len > 15) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "wrepl_nbt_name longer as 15 chars: %s", - r->name); - } - - if (r->scope) { - scope_len = strlen(r->scope); - } - if (scope_len > 238) { - return ndr_push_error(ndr, NDR_ERR_STRING, - "wrepl_nbt_name scope longer as 238 chars: %s", - r->scope); - } - - namebuf = (uint8_t *)talloc_asprintf(ndr, "%-15s%c%s", - r->name, 'X', - (r->scope?r->scope:"")); - if (!namebuf) return ndr_push_error(ndr, NDR_ERR_ALLOC, "out of memory"); - - namebuf_len = strlen((char *)namebuf) + 1; - - /* - * we need to set the type here, and use a place-holder in the talloc_asprintf() - * as the type can be 0x00, and then the namebuf_len = strlen(namebuf); would give wrong results - */ - namebuf[15] = r->type; - - /* oh wow, what a nasty bug in windows ... */ - if (r->type == 0x1b) { - namebuf[15] = namebuf[0]; - namebuf[0] = 0x1b; - } - - NDR_CHECK(ndr_push_align(ndr, 4)); - NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, namebuf_len)); - NDR_CHECK(ndr_push_array_uint8(ndr, NDR_SCALARS, namebuf, namebuf_len)); - - talloc_free(namebuf); - return NDR_ERR_SUCCESS; -} - -_PUBLIC_ void ndr_print_wrepl_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r) -{ - char *s = nbt_name_string(ndr, r); - ndr_print_string(ndr, name, s); - talloc_free(s); -} diff --git a/source3/libnet/libnet_dssync_keytab.c b/source3/libnet/libnet_dssync_keytab.c index 6ba2c3aa41..e762ecbe49 100644 --- a/source3/libnet/libnet_dssync_keytab.c +++ b/source3/libnet/libnet_dssync_keytab.c @@ -86,7 +86,7 @@ static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, old_utdv = talloc(mem_ctx, struct replUpToDateVectorBlob); ndr_err = ndr_pull_struct_blob(&entry->password, old_utdv, - old_utdv, + NULL, old_utdv, (ndr_pull_flags_fn_t)ndr_pull_replUpToDateVectorBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { NTSTATUS status = ndr_map_error2ntstatus(ndr_err); @@ -124,7 +124,7 @@ static NTSTATUS keytab_finish(struct dssync_context *ctx, TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUG(replUpToDateVectorBlob, new_utdv); } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, new_utdv, + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, new_utdv, (ndr_push_flags_fn_t)ndr_push_replUpToDateVectorBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -236,7 +236,7 @@ static NTSTATUS parse_supplemental_credentials(TALLOC_CTX *mem_ctx, status = NT_STATUS_NO_MEMORY; goto done; } - ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, pkb, + ndr_err = ndr_pull_struct_blob(&scpk_blob, mem_ctx, NULL, pkb, (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); diff --git a/source3/libnet/libnet_samsync.c b/source3/libnet/libnet_samsync.c index daf27ffb51..64dcf6de51 100644 --- a/source3/libnet/libnet_samsync.c +++ b/source3/libnet/libnet_samsync.c @@ -65,7 +65,7 @@ static NTSTATUS fix_user(TALLOC_CTX *mem_ctx, user->user_private_info.SensitiveData = data.data; user->user_private_info.DataLength = data.length; - ndr_err = ndr_pull_struct_blob(&data, mem_ctx, &keys, + ndr_err = ndr_pull_struct_blob(&data, mem_ctx, NULL, &keys, (ndr_pull_flags_fn_t)ndr_pull_netr_USER_KEYS); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { dump_data(10, data.data, data.length); @@ -397,7 +397,7 @@ NTSTATUS pull_netr_AcctLockStr(TALLOC_CTX *mem_ctx, blob = data_blob_const(r->array, r->length); - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, str, + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, str, (ndr_pull_flags_fn_t)ndr_pull_netr_AcctLockStr); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { diff --git a/source3/librpc/gen_ndr/libnetapi.h b/source3/librpc/gen_ndr/libnetapi.h index 98da9e12ea..ae7acbf572 100644 --- a/source3/librpc/gen_ndr/libnetapi.h +++ b/source3/librpc/gen_ndr/libnetapi.h @@ -413,7 +413,9 @@ struct USER_INFO_X { uint32_t usriX_code_page; const char * usriX_profile; const char * usriX_home_dir_drive; + uint32_t usriX_user_id; uint32_t usriX_primary_group_id; + uint32_t usriX_password_expired; }; struct GROUP_USERS_INFO_0 { diff --git a/source3/librpc/gen_ndr/nbt.h b/source3/librpc/gen_ndr/nbt.h index 62ad524a91..0943ee1a4d 100644 --- a/source3/librpc/gen_ndr/nbt.h +++ b/source3/librpc/gen_ndr/nbt.h @@ -221,7 +221,7 @@ union nbt_rdata { struct nbt_rdata_netbios netbios;/* [case(NBT_QTYPE_NETBIOS)] */ struct nbt_rdata_status status;/* [case(NBT_QTYPE_STATUS)] */ struct nbt_rdata_data data;/* [default] */ -}/* [nodiscriminant] */; +}/* [nodiscriminant,public] */; struct nbt_res_rec { struct nbt_name name; diff --git a/source3/librpc/gen_ndr/ndr_libnetapi.c b/source3/librpc/gen_ndr/ndr_libnetapi.c index a5266827b6..d7bf63e62f 100644 --- a/source3/librpc/gen_ndr/ndr_libnetapi.c +++ b/source3/librpc/gen_ndr/ndr_libnetapi.c @@ -1895,7 +1895,9 @@ _PUBLIC_ enum ndr_err_code ndr_push_USER_INFO_X(struct ndr_push *ndr, int ndr_fl NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_code_page)); NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_profile)); NDR_CHECK(ndr_push_string(ndr, NDR_SCALARS, r->usriX_home_dir_drive)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_user_id)); NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_primary_group_id)); + NDR_CHECK(ndr_push_uint32(ndr, NDR_SCALARS, r->usriX_password_expired)); } if (ndr_flags & NDR_BUFFERS) { if (r->usriX_logon_hours) { @@ -1942,7 +1944,9 @@ _PUBLIC_ enum ndr_err_code ndr_pull_USER_INFO_X(struct ndr_pull *ndr, int ndr_fl NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_code_page)); NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_profile)); NDR_CHECK(ndr_pull_string(ndr, NDR_SCALARS, &r->usriX_home_dir_drive)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_user_id)); NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_primary_group_id)); + NDR_CHECK(ndr_pull_uint32(ndr, NDR_SCALARS, &r->usriX_password_expired)); } if (ndr_flags & NDR_BUFFERS) { if (r->usriX_logon_hours) { @@ -1990,7 +1994,9 @@ _PUBLIC_ void ndr_print_USER_INFO_X(struct ndr_print *ndr, const char *name, con ndr_print_uint32(ndr, "usriX_code_page", r->usriX_code_page); ndr_print_string(ndr, "usriX_profile", r->usriX_profile); ndr_print_string(ndr, "usriX_home_dir_drive", r->usriX_home_dir_drive); + ndr_print_uint32(ndr, "usriX_user_id", r->usriX_user_id); ndr_print_uint32(ndr, "usriX_primary_group_id", r->usriX_primary_group_id); + ndr_print_uint32(ndr, "usriX_password_expired", r->usriX_password_expired); ndr->depth--; } diff --git a/source3/librpc/gen_ndr/ndr_nbt.c b/source3/librpc/gen_ndr/ndr_nbt.c index 75667183a8..01cccd6742 100644 --- a/source3/librpc/gen_ndr/ndr_nbt.c +++ b/source3/librpc/gen_ndr/ndr_nbt.c @@ -77,13 +77,13 @@ _PUBLIC_ void ndr_print_nbt_name(struct ndr_print *ndr, const char *name, const ndr->depth--; } -static enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r) +_PUBLIC_ enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r) { NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r)); return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r) +_PUBLIC_ enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r) { uint16_t v; NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v)); @@ -101,13 +101,13 @@ _PUBLIC_ void ndr_print_nbt_qclass(struct ndr_print *ndr, const char *name, enum ndr_print_enum(ndr, name, "ENUM", val, r); } -static enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r) +_PUBLIC_ enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r) { NDR_CHECK(ndr_push_uint16(ndr, NDR_SCALARS, r)); return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r) +_PUBLIC_ enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r) { uint16_t v; NDR_CHECK(ndr_pull_uint16(ndr, NDR_SCALARS, &v)); @@ -496,7 +496,7 @@ _PUBLIC_ void ndr_print_nbt_rdata_data(struct ndr_print *ndr, const char *name, ndr->depth--; } -static enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r) +_PUBLIC_ enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r) { if (ndr_flags & NDR_SCALARS) { int level = ndr_push_get_switch_value(ndr, r); @@ -532,7 +532,7 @@ static enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, return NDR_ERR_SUCCESS; } -static enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r) +_PUBLIC_ enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r) { int level; level = ndr_pull_get_switch_value(ndr, r); diff --git a/source3/librpc/gen_ndr/ndr_nbt.h b/source3/librpc/gen_ndr/ndr_nbt.h index 6e9702d5d5..f70d1ba8df 100644 --- a/source3/librpc/gen_ndr/ndr_nbt.h +++ b/source3/librpc/gen_ndr/ndr_nbt.h @@ -6,14 +6,18 @@ #ifndef _HEADER_NDR_nbt #define _HEADER_NDR_nbt -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #define NDR_NBT_CALL_COUNT (0) void ndr_print_nbt_operation(struct ndr_print *ndr, const char *name, uint16_t r); void ndr_print_nbt_name_type(struct ndr_print *ndr, const char *name, enum nbt_name_type r); enum ndr_err_code ndr_push_nbt_name(struct ndr_push *ndr, int ndr_flags, const struct nbt_name *r); enum ndr_err_code ndr_pull_nbt_name(struct ndr_pull *ndr, int ndr_flags, struct nbt_name *r); void ndr_print_nbt_name(struct ndr_print *ndr, const char *name, const struct nbt_name *r); +enum ndr_err_code ndr_push_nbt_qclass(struct ndr_push *ndr, int ndr_flags, enum nbt_qclass r); +enum ndr_err_code ndr_pull_nbt_qclass(struct ndr_pull *ndr, int ndr_flags, enum nbt_qclass *r); void ndr_print_nbt_qclass(struct ndr_print *ndr, const char *name, enum nbt_qclass r); +enum ndr_err_code ndr_push_nbt_qtype(struct ndr_push *ndr, int ndr_flags, enum nbt_qtype r); +enum ndr_err_code ndr_pull_nbt_qtype(struct ndr_pull *ndr, int ndr_flags, enum nbt_qtype *r); void ndr_print_nbt_qtype(struct ndr_print *ndr, const char *name, enum nbt_qtype r); void ndr_print_nbt_name_question(struct ndr_print *ndr, const char *name, const struct nbt_name_question *r); void ndr_print_nb_flags(struct ndr_print *ndr, const char *name, uint16_t r); @@ -23,6 +27,8 @@ void ndr_print_nbt_statistics(struct ndr_print *ndr, const char *name, const str void ndr_print_nbt_status_name(struct ndr_print *ndr, const char *name, const struct nbt_status_name *r); void ndr_print_nbt_rdata_status(struct ndr_print *ndr, const char *name, const struct nbt_rdata_status *r); void ndr_print_nbt_rdata_data(struct ndr_print *ndr, const char *name, const struct nbt_rdata_data *r); +enum ndr_err_code ndr_push_nbt_rdata(struct ndr_push *ndr, int ndr_flags, const union nbt_rdata *r); +enum ndr_err_code ndr_pull_nbt_rdata(struct ndr_pull *ndr, int ndr_flags, union nbt_rdata *r); void ndr_print_nbt_rdata(struct ndr_print *ndr, const char *name, const union nbt_rdata *r); void ndr_print_nbt_res_rec(struct ndr_print *ndr, const char *name, const struct nbt_res_rec *r); enum ndr_err_code ndr_push_nbt_name_packet(struct ndr_push *ndr, int ndr_flags, const struct nbt_name_packet *r); diff --git a/source3/librpc/idl/libnetapi.idl b/source3/librpc/idl/libnetapi.idl index 039dcf4152..f2f4a16c12 100644 --- a/source3/librpc/idl/libnetapi.idl +++ b/source3/librpc/idl/libnetapi.idl @@ -517,7 +517,9 @@ interface libnetapi uint32 usriX_code_page; string usriX_profile; string usriX_home_dir_drive; + uint32 usriX_user_id; uint32 usriX_primary_group_id; + uint32 usriX_password_expired; } USER_INFO_X; [nopush,nopull] NET_API_STATUS NetUserAdd( diff --git a/source3/librpc/idl/nbt.idl b/source3/librpc/idl/nbt.idl index 654f53c52f..da1eb2ef3f 100644 --- a/source3/librpc/idl/nbt.idl +++ b/source3/librpc/idl/nbt.idl @@ -10,7 +10,7 @@ import "misc.idl", "security.idl", "svcctl.idl", "samr.idl"; [ -helper("libcli/nbt/libnbt.h") +helper("../libcli/nbt/libnbt.h") ] interface nbt { @@ -73,11 +73,11 @@ interface nbt nbt_name_type type; } nbt_name; - typedef [enum16bit] enum { + typedef [public,enum16bit] enum { NBT_QCLASS_IP = 0x01 } nbt_qclass; - typedef [enum16bit] enum { + typedef [public,enum16bit] enum { NBT_QTYPE_ADDRESS = 0x0001, NBT_QTYPE_NAMESERVICE = 0x0002, NBT_QTYPE_NULL = 0x000A, @@ -160,7 +160,7 @@ interface nbt uint8 data[length]; } nbt_rdata_data; - typedef [nodiscriminant] union { + typedef [nodiscriminant,public] union { [case(NBT_QTYPE_NETBIOS)] nbt_rdata_netbios netbios; [case(NBT_QTYPE_STATUS)] nbt_rdata_status status; [default] nbt_rdata_data data; diff --git a/source3/librpc/ndr/ndr.c b/source3/librpc/ndr/ndr.c index d94d12e146..624024c94d 100644 --- a/source3/librpc/ndr/ndr.c +++ b/source3/librpc/ndr/ndr.c @@ -803,8 +803,11 @@ _PUBLIC_ uint32_t ndr_print_get_switch_value(struct ndr_print *ndr, const void * /* pull a struct from a blob using NDR */ -_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, TALLOC_CTX *mem_ctx, void *p, - ndr_pull_flags_fn_t fn) +_PUBLIC_ enum ndr_err_code ndr_pull_struct_blob(const DATA_BLOB *blob, + TALLOC_CTX *mem_ctx, + struct smb_iconv_convenience *iconv_convenience, + void *p, + ndr_pull_flags_fn_t fn) { struct ndr_pull *ndr; ndr = ndr_pull_init_blob(blob, mem_ctx); @@ -868,8 +871,11 @@ _PUBLIC_ enum ndr_err_code ndr_pull_union_blob_all(const DATA_BLOB *blob, TALLOC /* push a struct to a blob using NDR */ -_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, TALLOC_CTX *mem_ctx, const void *p, - ndr_push_flags_fn_t fn) +_PUBLIC_ enum ndr_err_code ndr_push_struct_blob(DATA_BLOB *blob, + TALLOC_CTX *mem_ctx, + struct smb_iconv_convenience *iconv_convenience, + const void *p, + ndr_push_flags_fn_t fn) { struct ndr_push *ndr; ndr = ndr_push_init_ctx(mem_ctx); diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c index 8b35a69def..8ee3507a04 100644 --- a/source3/libsmb/clidgram.c +++ b/source3/libsmb/clidgram.c @@ -181,7 +181,7 @@ bool send_getdc_request(TALLOC_CTX *mem_ctx, NDR_PRINT_DEBUG(nbt_ntlogon_packet, &packet); } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &packet, + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &packet, (ndr_push_flags_fn_t)ndr_push_nbt_ntlogon_packet); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return false; diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index 9d65fb4e94..8a5aedfde5 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -464,13 +464,11 @@ struct cli_state *cli_initialise(void) return NULL; } - cli = talloc(NULL, struct cli_state); + cli = TALLOC_ZERO_P(NULL, struct cli_state); if (!cli) { return NULL; } - ZERO_STRUCTP(cli); - cli->port = 0; cli->fd = -1; cli->cnum = -1; diff --git a/source3/libsmb/dsgetdcname.c b/source3/libsmb/dsgetdcname.c index 2a445cbd5a..e822635546 100644 --- a/source3/libsmb/dsgetdcname.c +++ b/source3/libsmb/dsgetdcname.c @@ -331,7 +331,7 @@ static NTSTATUS store_cldap_reply(TALLOC_CTX *mem_ctx, return status; } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &logon29, + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &logon29, (ndr_push_flags_fn_t)ndr_push_nbt_cldap_netlogon_29); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { return ndr_map_error2ntstatus(ndr_err); @@ -508,7 +508,7 @@ static NTSTATUS dsgetdcname_cache_fetch(TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r, (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon_29); data_blob_free(&blob); diff --git a/source3/libsmb/samlogon_cache.c b/source3/libsmb/samlogon_cache.c index 4abe5bb6de..af4986fa9d 100644 --- a/source3/libsmb/samlogon_cache.c +++ b/source3/libsmb/samlogon_cache.c @@ -141,7 +141,7 @@ bool netsamlogon_cache_store(const char *username, struct netr_SamInfo3 *info3) NDR_PRINT_DEBUG(netsamlogoncache_entry, &r); } - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, &r, + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, &r, (ndr_push_flags_fn_t)ndr_push_netsamlogoncache_entry); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("netsamlogon_cache_store: failed to push entry to cache\n")); @@ -197,7 +197,7 @@ struct netr_SamInfo3 *netsamlogon_cache_get(TALLOC_CTX *mem_ctx, const DOM_SID * blob = data_blob_const(data.dptr, data.dsize); - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &r, + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &r, (ndr_pull_flags_fn_t)ndr_pull_netsamlogoncache_entry); if (DEBUGLEVEL >= 10) { diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index 08a49930b4..2f336f14e6 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -22,104 +22,6 @@ /********************************************************* Change the domain password on the PDC. - - Just changes the password betwen the two values specified. - - Caller must have the cli connected to the netlogon pipe - already. -**********************************************************/ - -static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - const unsigned char orig_trust_passwd_hash[16], - const char *new_trust_pwd_cleartext, - const unsigned char new_trust_passwd_hash[16], - uint32 sec_channel_type) -{ - NTSTATUS result; - uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; - - result = rpccli_netlogon_setup_creds(cli, - cli->desthost, /* server name */ - lp_workgroup(), /* domain */ - global_myname(), /* client name */ - global_myname(), /* machine account name */ - orig_trust_passwd_hash, - sec_channel_type, - &neg_flags); - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n", - nt_errstr(result))); - return result; - } - - if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) { - - struct netr_Authenticator clnt_creds, srv_cred; - struct netr_CryptPassword new_password; - struct samr_CryptPassword password_buf; - - netlogon_creds_client_step(cli->dc, &clnt_creds); - - encode_pw_buffer(password_buf.data, new_trust_pwd_cleartext, STR_UNICODE); - - SamOEMhash(password_buf.data, cli->dc->sess_key, 516); - memcpy(new_password.data, password_buf.data, 512); - new_password.length = IVAL(password_buf.data, 512); - - result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx, - cli->dc->remote_machine, - cli->dc->mach_acct, - sec_channel_type, - global_myname(), - &clnt_creds, - &srv_cred, - &new_password); - - /* Always check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { - DEBUG(0,("rpccli_netr_ServerPasswordSet2: " - "credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - - } else { - - struct netr_Authenticator clnt_creds, srv_cred; - struct samr_Password new_password; - - netlogon_creds_client_step(cli->dc, &clnt_creds); - - cred_hash3(new_password.hash, - new_trust_passwd_hash, - cli->dc->sess_key, 1); - - result = rpccli_netr_ServerPasswordSet(cli, mem_ctx, - cli->dc->remote_machine, - cli->dc->mach_acct, - sec_channel_type, - global_myname(), - &clnt_creds, - &srv_cred, - &new_password); - - /* Always check returned credentials. */ - if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { - DEBUG(0,("rpccli_netr_ServerPasswordSet: " - "credentials chain check failed\n")); - return NT_STATUS_ACCESS_DENIED; - } - } - - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("just_change_the_password: unable to change password (%s)!\n", - nt_errstr(result))); - } - return result; -} - -/********************************************************* - Change the domain password on the PDC. Store the password ourselves, but use the supplied password Caller must have already setup the connection to the NETLOGON pipe **********************************************************/ @@ -144,11 +46,11 @@ NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *m E_md4hash(new_trust_passwd, new_trust_passwd_hash); - nt_status = just_change_the_password(cli, mem_ctx, - orig_trust_passwd_hash, - new_trust_passwd, - new_trust_passwd_hash, - sec_channel_type); + nt_status = rpccli_netlogon_set_trust_password(cli, mem_ctx, + orig_trust_passwd_hash, + new_trust_passwd, + new_trust_passwd_hash, + sec_channel_type); if (NT_STATUS_IS_OK(nt_status)) { DEBUG(3,("%s : trust_pw_change_and_store_it: Changed password.\n", diff --git a/source3/modules/vfs_acl_xattr.c b/source3/modules/vfs_acl_xattr.c index fd59310755..a2f3477b76 100644 --- a/source3/modules/vfs_acl_xattr.c +++ b/source3/modules/vfs_acl_xattr.c @@ -38,7 +38,7 @@ static NTSTATUS parse_acl_blob(const DATA_BLOB *pblob, size_t sd_size; struct timespec ts; - ndr_err = ndr_pull_struct_blob(pblob, ctx, &xacl, + ndr_err = ndr_pull_struct_blob(pblob, ctx, NULL, &xacl, (ndr_pull_flags_fn_t)ndr_pull_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -245,7 +245,7 @@ static NTSTATUS create_acl_blob(SEC_DESC *psd, DATA_BLOB *pblob) unix_timespec_to_nt_time(&xacl.info.sd_ts->last_changed, curr); ndr_err = ndr_push_struct_blob( - pblob, ctx, &xacl, + pblob, ctx, NULL, &xacl, (ndr_push_flags_fn_t)ndr_push_xattr_NTACL); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { diff --git a/source3/modules/vfs_xattr_tdb.c b/source3/modules/vfs_xattr_tdb.c index 7b5e510747..c707a1828f 100644 --- a/source3/modules/vfs_xattr_tdb.c +++ b/source3/modules/vfs_xattr_tdb.c @@ -48,7 +48,7 @@ static NTSTATUS xattr_tdb_pull_attrs(TALLOC_CTX *mem_ctx, blob = data_blob_const(data->dptr, data->dsize); ndr_err = ndr_pull_struct_blob( - &blob, result, result, + &blob, result, NULL, result, (ndr_pull_flags_fn_t)ndr_pull_tdb_xattrs); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { @@ -74,7 +74,7 @@ static NTSTATUS xattr_tdb_push_attrs(TALLOC_CTX *mem_ctx, enum ndr_err_code ndr_err; ndr_err = ndr_push_struct_blob( - &blob, mem_ctx, attribs, + &blob, mem_ctx, NULL, attribs, (ndr_push_flags_fn_t)ndr_push_tdb_xattrs); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index df87ed13d1..23618efd9f 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -538,3 +538,94 @@ NTSTATUS rpccli_netlogon_sam_network_logon_ex(struct rpc_pipe_client *cli, return result; } + +/********************************************************* + Change the domain password on the PDC. + + Just changes the password betwen the two values specified. + + Caller must have the cli connected to the netlogon pipe + already. +**********************************************************/ + +NTSTATUS rpccli_netlogon_set_trust_password(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const unsigned char orig_trust_passwd_hash[16], + const char *new_trust_pwd_cleartext, + const unsigned char new_trust_passwd_hash[16], + uint32_t sec_channel_type) +{ + NTSTATUS result; + uint32_t neg_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS; + struct netr_Authenticator clnt_creds, srv_cred; + + result = rpccli_netlogon_setup_creds(cli, + cli->desthost, /* server name */ + lp_workgroup(), /* domain */ + global_myname(), /* client name */ + global_myname(), /* machine account name */ + orig_trust_passwd_hash, + sec_channel_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3,("rpccli_netlogon_set_trust_password: unable to setup creds (%s)!\n", + nt_errstr(result))); + return result; + } + + netlogon_creds_client_step(cli->dc, &clnt_creds); + + if (neg_flags & NETLOGON_NEG_PASSWORD_SET2) { + + struct netr_CryptPassword new_password; + + init_netr_CryptPassword(new_trust_pwd_cleartext, + cli->dc->sess_key, + &new_password); + + result = rpccli_netr_ServerPasswordSet2(cli, mem_ctx, + cli->dc->remote_machine, + cli->dc->mach_acct, + sec_channel_type, + global_myname(), + &clnt_creds, + &srv_cred, + &new_password); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("rpccli_netr_ServerPasswordSet2 failed: %s\n", + nt_errstr(result))); + return result; + } + } else { + + struct samr_Password new_password; + + cred_hash3(new_password.hash, + new_trust_passwd_hash, + cli->dc->sess_key, 1); + + result = rpccli_netr_ServerPasswordSet(cli, mem_ctx, + cli->dc->remote_machine, + cli->dc->mach_acct, + sec_channel_type, + global_myname(), + &clnt_creds, + &srv_cred, + &new_password); + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0,("rpccli_netr_ServerPasswordSet failed: %s\n", + nt_errstr(result))); + return result; + } + } + + /* Always check returned credentials. */ + if (!netlogon_creds_client_check(cli->dc, &srv_cred.cred)) { + DEBUG(0,("credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + + return result; +} + diff --git a/source3/rpc_client/init_netlogon.c b/source3/rpc_client/init_netlogon.c index 61841953fc..e4c39e739e 100644 --- a/source3/rpc_client/init_netlogon.c +++ b/source3/rpc_client/init_netlogon.c @@ -391,3 +391,20 @@ void init_netr_PasswordInfo(struct netr_PasswordInfo *r, r->lmpassword = lmpassword; r->ntpassword = ntpassword; } + +/************************************************************************* + inits a netr_CryptPassword structure + *************************************************************************/ + +void init_netr_CryptPassword(const char *pwd, + unsigned char session_key[16], + struct netr_CryptPassword *pwd_buf) +{ + struct samr_CryptPassword password_buf; + + encode_pw_buffer(password_buf.data, pwd, STR_UNICODE); + + SamOEMhash(password_buf.data, session_key, 516); + memcpy(pwd_buf->data, password_buf.data, 512); + pwd_buf->length = IVAL(password_buf.data, 512); +} diff --git a/source3/samba4.m4 b/source3/samba4.m4 index c02d3d4b3b..728fd2d45d 100644 --- a/source3/samba4.m4 +++ b/source3/samba4.m4 @@ -95,7 +95,6 @@ m4_include(ntvfs/unixuid/config.m4) m4_include(auth/config.m4) m4_include(kdc/config.m4) m4_include(ntvfs/sysdep/config.m4) -m4_include(lib/appweb/config.m4) m4_include(nsswitch/config.m4) dnl Samba 4 files diff --git a/source3/samba4.mk b/source3/samba4.mk index 294eef8b8f..2646b12a0d 100644 --- a/source3/samba4.mk +++ b/source3/samba4.mk @@ -7,7 +7,7 @@ PARTLINK = $(PROG_LD) -r MDLD = $(SHLD) MDLD_FLAGS = $(LDSHFLAGS) -samba4srcdir = $(call abspath,$(srcdir)/../source4) +samba4srcdir = $(srcdir)/../source4 # Flags used for the samba 4 files # $(srcdir)/include is required for config.h @@ -83,7 +83,6 @@ libcmdlinesrcdir := $(samba4srcdir)/lib/cmdline poptsrcdir := $(samba4srcdir)/../lib/popt socketwrappersrcdir := $(samba4srcdir)/../lib/socket_wrapper nsswrappersrcdir := $(samba4srcdir)/../lib/nss_wrapper -appwebsrcdir := $(samba4srcdir)/lib/appweb libstreamsrcdir := $(samba4srcdir)/lib/stream libutilsrcdir := $(samba4srcdir)/lib/util libtdrsrcdir := $(samba4srcdir)/lib/tdr @@ -108,7 +107,6 @@ ntvfssrcdir := $(samba4srcdir)/ntvfs ntptrsrcdir := $(samba4srcdir)/ntptr clientsrcdir := $(samba4srcdir)/client libclisrcdir := $(samba4srcdir)/libcli -ejsscriptsrcdir := $(samba4srcdir)/scripting/ejs pyscriptsrcdir := $(samba4srcdir)/scripting/python kdcsrcdir := $(samba4srcdir)/kdc smbreadlinesrcdir := $(samba4srcdir)/lib/smbreadline @@ -116,6 +114,7 @@ ntp_signdsrcdir := $(samba4srcdir)/ntp_signd tdbsrcdir := $(samba4srcdir)/../lib/tdb ldbsrcdir := $(samba4srcdir)/lib/ldb tallocsrcdir := $(samba4srcdir)/../lib/talloc +comsrcdir := $(samba4srcdir)/lib/com override ASN1C = bin/asn1_compile4 override ET_COMPILER = bin/compile_et4 include samba4-data.mk diff --git a/source3/script/build_idl.sh b/source3/script/build_idl.sh index 8ff5dcd949..2027fd3937 100755 --- a/source3/script/build_idl.sh +++ b/source3/script/build_idl.sh @@ -19,7 +19,7 @@ for f in ${IDL_FILES}; do basename=`basename $f .idl` ndr="librpc/gen_ndr/ndr_$basename.c" - if [ -f $ndr ] && false; then + if [ -f $ndr ]; then if [ "x`find librpc/idl/$f -newer $ndr -print`" = "xlibrpc/idl/$f" ]; then list="$list librpc/idl/$f" fi diff --git a/source3/smbd/notify_internal.c b/source3/smbd/notify_internal.c index 84b8e1098e..06da717799 100644 --- a/source3/smbd/notify_internal.c +++ b/source3/smbd/notify_internal.c @@ -166,7 +166,7 @@ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec status = NT_STATUS_OK; if (blob.length > 0) { enum ndr_err_code ndr_err; - ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array, + ndr_err = ndr_pull_struct_blob(&blob, notify->array, NULL, notify->array, (ndr_pull_flags_fn_t)ndr_pull_notify_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); @@ -220,7 +220,7 @@ static NTSTATUS notify_save(struct notify_context *notify, struct db_record *rec tmp_ctx = talloc_new(notify); NT_STATUS_HAVE_NO_MEMORY(tmp_ctx); - ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, notify->array, + ndr_err = ndr_push_struct_blob(&blob, tmp_ctx, NULL, notify->array, (ndr_push_flags_fn_t)ndr_push_notify_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); @@ -258,7 +258,7 @@ static void notify_handler(struct messaging_context *msg_ctx, void *private_data return; } - ndr_err = ndr_pull_struct_blob(data, tmp_ctx, &ev, + ndr_err = ndr_pull_struct_blob(data, tmp_ctx, NULL, &ev, (ndr_pull_flags_fn_t)ndr_pull_notify_event); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); @@ -561,7 +561,7 @@ static NTSTATUS notify_send(struct notify_context *notify, struct notify_entry * tmp_ctx = talloc_new(notify); - ndr_err = ndr_push_struct_blob(&data, tmp_ctx, &ev, + ndr_err = ndr_push_struct_blob(&data, tmp_ctx, NULL, &ev, (ndr_push_flags_fn_t)ndr_push_notify_event); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { talloc_free(tmp_ctx); diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c index 124af00b57..005e3ca556 100644 --- a/source3/utils/net_rpc_registry.c +++ b/source3/utils/net_rpc_registry.c @@ -1186,7 +1186,7 @@ static NTSTATUS rpc_registry_getsd_internal(struct net_context *c, blob.data = sd->data; blob.length = sd->size; - ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, &sec_desc, + ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, NULL, &sec_desc, (ndr_pull_flags_fn_t)ndr_pull_security_descriptor); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { status = ndr_map_error2ntstatus(ndr_err); diff --git a/source3/winbindd/idmap_adex/cell_util.c b/source3/winbindd/idmap_adex/cell_util.c new file mode 100644 index 0000000000..f5c08a0454 --- /dev/null +++ b/source3/winbindd/idmap_adex/cell_util.c @@ -0,0 +1,292 @@ +/* + * idmap_adex: Support for AD Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/********************************************************************** +**********************************************************************/ + + char *find_attr_string(char **list, size_t num_lines, const char *substr) +{ + int i; + int cmplen = strlen(substr); + + for (i = 0; i < num_lines; i++) { + /* make sure to avoid substring matches like uid + and uidNumber */ + if ((StrnCaseCmp(list[i], substr, cmplen) == 0) && + (list[i][cmplen] == '=')) { + /* Don't return an empty string */ + if (list[i][cmplen + 1] != '\0') + return &(list[i][cmplen + 1]); + + return NULL; + } + } + + return NULL; +} + +/********************************************************************** +**********************************************************************/ + + bool is_object_class(char **list, size_t num_lines, const char *substr) +{ + int i; + + for (i = 0; i < num_lines; i++) { + if (strequal(list[i], substr)) { + return true; + } + } + + return false; +} + +/********************************************************************** + Find out about the cell (e.g. use2307Attrs, etc...) +**********************************************************************/ + + NTSTATUS cell_lookup_settings(struct likewise_cell * cell) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + + /* Parameter check */ + + if (!cell) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Only supporting Forest-wide, schema based searches */ + + cell_set_flags(cell, LWCELL_FLAG_USE_RFC2307_ATTRS); + cell_set_flags(cell, LWCELL_FLAG_SEARCH_FOREST); + + cell->provider = &ccp_unified; + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1,("LWI: Failed to obtain cell settings (%s)\n", + nt_errstr(nt_status))); + } + + return nt_status; +} + + +static NTSTATUS cell_lookup_forest(struct likewise_cell *c) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct gc_info *gc = NULL; + + if (!c) { + return NT_STATUS_INVALID_PARAMETER; + } + + if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Query the rootDSE for the forest root naming conect first. + Check that the a GC server for the forest has not already + been added */ + + nt_status = gc_find_forest_root(gc, cell_dns_domain(c)); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + c->forest_name = talloc_strdup(c, gc->forest_name); + BAIL_ON_PTR_ERROR(c->forest_name, nt_status); + +done: + if (gc) { + talloc_free(gc); + } + + return nt_status; +} + +/********************************************************************** +**********************************************************************/ + + NTSTATUS cell_locate_membership(ADS_STRUCT * ads) +{ + ADS_STATUS status; + char *domain_dn = ads_build_dn(lp_realm()); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + DOM_SID sid; + struct likewise_cell *cell = NULL; + + /* In the Likewise plugin, I had to support the concept of cells + based on the machine's membership in an OU. However, now I'll + just assume our membership in the forest cell */ + + DEBUG(2, ("locate_cell_membership: Located membership " + "in cell \"%s\"\n", domain_dn)); + + if ((cell = cell_new()) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + status = ads_domain_sid(ads, &sid); + if (!ADS_ERR_OK(status)) { + DEBUG(3,("locate_cell_membership: Failed to find " + "domain SID for %s\n", domain_dn)); + } + + /* save the SID and search base for our domain */ + + cell_set_dns_domain(cell, lp_realm()); + cell_set_connection(cell, ads); + cell_set_dn(cell, domain_dn); + cell_set_domain_sid(cell, &sid); + + /* Now save our forest root */ + + cell_lookup_forest(cell); + + /* Add the cell to the list */ + + if (!cell_list_add(cell)) { + nt_status = NT_STATUS_INSUFFICIENT_RESOURCES; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Done! */ + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("LWI: Failed to locate cell membership (%s)\n", + nt_errstr(nt_status))); + } + + SAFE_FREE(domain_dn); + + return nt_status; +} + +/********************************************************************* + ********************************************************************/ + + int min_id_value(void) +{ + int id_val; + + id_val = lp_parm_int(-1, "lwidentity", "min_id_value", MIN_ID_VALUE); + + /* Still don't let it go below 50 */ + + return MAX(50, id_val); +} + +/******************************************************************** + *******************************************************************/ + + char *cell_dn_to_dns(const char *dn) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *domain = NULL; + char *dns_name = NULL; + const char *tmp_dn; + char *buffer = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!dn || !*dn) { + goto done; + } + + tmp_dn = talloc_strdup(frame, dn); + BAIL_ON_PTR_ERROR(tmp_dn, nt_status); + + while (next_token_talloc(frame, &tmp_dn, &buffer, ",")) { + + /* skip everything up the where DC=... begins */ + if (StrnCaseCmp(buffer, "DC=", 3) != 0) + continue; + + if (!domain) { + domain = talloc_strdup(frame, &buffer[3]); + } else { + domain = talloc_asprintf_append(domain, ".%s", + &buffer[3]); + } + BAIL_ON_PTR_ERROR(domain, nt_status); + } + + dns_name = SMB_STRDUP(domain); + BAIL_ON_PTR_ERROR(dns_name, nt_status); + + nt_status = NT_STATUS_OK; + +done: + PRINT_NTSTATUS_ERROR(nt_status, "cell_dn_to_dns", 1); + + talloc_destroy(frame); + + return dns_name; +} + +/********************************************************************* + ********************************************************************/ + + NTSTATUS get_sid_type(ADS_STRUCT *ads, + LDAPMessage *msg, + enum lsa_SidType *type) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + uint32_t atype; + + if (!ads_pull_uint32(ads, msg, "sAMAccountType", &atype)) { + nt_status = NT_STATUS_INVALID_USER_BUFFER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + switch (atype &0xF0000000) { + case ATYPE_SECURITY_GLOBAL_GROUP: + *type = SID_NAME_DOM_GRP; + break; + case ATYPE_SECURITY_LOCAL_GROUP: + *type = SID_NAME_ALIAS; + break; + case ATYPE_NORMAL_ACCOUNT: + case ATYPE_WORKSTATION_TRUST: + case ATYPE_INTERDOMAIN_TRUST: + *type = SID_NAME_USER; + break; + default: + *type = SID_NAME_USE_NONE; + nt_status = NT_STATUS_INVALID_ACCOUNT_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + return nt_status; +} diff --git a/source3/winbindd/idmap_adex/domain_util.c b/source3/winbindd/idmap_adex/domain_util.c new file mode 100644 index 0000000000..ab31ccef7a --- /dev/null +++ b/source3/winbindd/idmap_adex/domain_util.c @@ -0,0 +1,278 @@ +/* + * idmap_adex: Domain search interface + * + * Copyright (C) Gerald (Jerry) Carter 2007-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +struct dc_info { + struct dc_info *prev, *next; + char *dns_name; + struct likewise_cell *domain_cell; +}; + +static struct dc_info *_dc_server_list = NULL; + + +/********************************************************************** + *********************************************************************/ + +static struct dc_info *dc_list_head(void) +{ + return _dc_server_list; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS dc_add_domain(const char *domain) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct dc_info *dc = NULL; + + /* Check for duplicates */ + + dc = dc_list_head(); + while (dc) { + if (strequal (dc->dns_name, domain)) + break; + dc = dc->next; + } + + if (dc) { + DEBUG(10,("dc_add_domain: %s already in list\n", domain)); + return NT_STATUS_OK; + } + + dc = TALLOC_ZERO_P(NULL, struct dc_info); + BAIL_ON_PTR_ERROR(dc, nt_status); + + dc->dns_name = talloc_strdup(dc, domain); + BAIL_ON_PTR_ERROR(dc->dns_name, nt_status); + + DLIST_ADD_END(_dc_server_list, dc, struct dc_info*); + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_destroy(dc); + DEBUG(0,("LWI: Failed to add new DC connection for %s (%s)\n", + domain, nt_errstr(nt_status))); + } + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static void dc_server_list_destroy(void) +{ + struct dc_info *dc = dc_list_head(); + + while (dc) { + struct dc_info *p = dc->next; + + cell_destroy(dc->domain_cell); + talloc_destroy(dc); + + dc = p; + } + + return; +} + + +/********************************************************************** + *********************************************************************/ + + NTSTATUS domain_init_list(void) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct winbindd_tdc_domain *domains = NULL; + size_t num_domains = 0; + int i; + + if (_dc_server_list != NULL) { + dc_server_list_destroy(); + } + + /* Add our domain */ + + nt_status = dc_add_domain(lp_realm()); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if (!wcache_tdc_fetch_list(&domains, &num_domains)) { + nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Add all domains with an incoming trust path */ + + for (i=0; i<num_domains; i++) { + uint32_t flags = (NETR_TRUST_FLAG_INBOUND|NETR_TRUST_FLAG_IN_FOREST); + + /* We just require one of the flags to be set here */ + + if (domains[i].trust_flags & flags) { + nt_status = dc_add_domain(domains[i].dns_name); + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + } + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2,("LWI: Failed to initialize DC list (%s)\n", + nt_errstr(nt_status))); + } + + TALLOC_FREE(domains); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS dc_do_search(struct dc_info *dc, + const char *search_base, + int scope, + const char *expr, + const char **attrs, + LDAPMessage ** msg) +{ + ADS_STATUS status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + + status = cell_do_search(dc->domain_cell, search_base, + scope, expr, attrs, msg); + nt_status = ads_ntstatus(status); + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static struct dc_info *dc_find_domain(const char *dns_domain) +{ + struct dc_info *dc = dc_list_head(); + + if (!dc) + return NULL; + + while (dc) { + if (strequal(dc->dns_name, dns_domain)) { + return dc; + } + + dc = dc->next; + } + + return NULL; +} + +/********************************************************************** + *********************************************************************/ + + NTSTATUS dc_search_domains(struct likewise_cell **cell, + LDAPMessage **msg, + const char *dn, + const DOM_SID *sid) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *frame = talloc_stackframe(); + char *dns_domain; + const char *attrs[] = { "*", NULL }; + struct dc_info *dc = NULL; + const char *base = NULL; + + if (!dn || !*dn) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + dns_domain = cell_dn_to_dns(dn); + BAIL_ON_PTR_ERROR(dns_domain, nt_status); + + if ((dc = dc_find_domain(dns_domain)) == NULL) { + nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Reparse the cell settings for the domain if necessary */ + + if (!dc->domain_cell) { + char *base_dn; + + base_dn = ads_build_dn(dc->dns_name); + BAIL_ON_PTR_ERROR(base_dn, nt_status); + + nt_status = cell_connect_dn(&dc->domain_cell, base_dn); + SAFE_FREE(base_dn); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = cell_lookup_settings(dc->domain_cell); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* By definition this is already part of a larger + forest-wide search scope */ + + cell_set_flags(dc->domain_cell, LWCELL_FLAG_SEARCH_FOREST); + } + + /* Check whether we are operating in non-schema or RFC2307 + mode */ + + if (cell_flags(dc->domain_cell) & LWCELL_FLAG_USE_RFC2307_ATTRS) { + nt_status = dc_do_search(dc, dn, LDAP_SCOPE_BASE, + "(objectclass=*)", attrs, msg); + } else { + const char *sid_str = NULL; + char *filter = NULL; + + sid_str = sid_string_talloc(frame, sid); + BAIL_ON_PTR_ERROR(sid_str, nt_status); + + filter = talloc_asprintf(frame, "(keywords=backLink=%s)", + sid_str); + BAIL_ON_PTR_ERROR(filter, nt_status); + + base = cell_search_base(dc->domain_cell); + BAIL_ON_PTR_ERROR(base, nt_status); + + nt_status = dc_do_search(dc, base, LDAP_SCOPE_SUBTREE, + filter, attrs, msg); + } + BAIL_ON_NTSTATUS_ERROR(nt_status); + + *cell = dc->domain_cell; + +done: + talloc_destroy(CONST_DISCARD(char*, base)); + talloc_destroy(frame); + + return nt_status; +} diff --git a/source3/winbindd/idmap_adex/gc_util.c b/source3/winbindd/idmap_adex/gc_util.c new file mode 100644 index 0000000000..87dd3c058d --- /dev/null +++ b/source3/winbindd/idmap_adex/gc_util.c @@ -0,0 +1,848 @@ +/* + * idmap_adex: Global Catalog search interface + * + * Copyright (C) Gerald (Jerry) Carter 2007-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +static struct gc_info *_gc_server_list = NULL; + + +/********************************************************************** + *********************************************************************/ + +static struct gc_info *gc_list_head(void) +{ + return _gc_server_list; +} + +/********************************************************************** + Checks if either of the domains is a subdomain of the other + *********************************************************************/ + +static bool is_subdomain(const char* a, const char *b) +{ + char *s; + TALLOC_CTX *frame = talloc_stackframe(); + char *x, *y; + bool ret = false; + + /* Trivial cases */ + + if (!a && !b) + return true; + + if (!a || !b) + return false; + + /* Normalize the case */ + + x = talloc_strdup(frame, a); + y = talloc_strdup(frame, b); + if (!x || !y) { + ret = false; + goto done; + } + + strupper_m(x); + strupper_m(y); + + /* Exact match */ + + if (strcmp(x, y) == 0) { + ret = true; + goto done; + } + + /* Check for trailing substrings */ + + s = strstr_m(x, y); + if (s && (strlen(s) == strlen(y))) { + ret = true; + goto done; + } + + s = strstr_m(y, x); + if (s && (strlen(s) == strlen(x))) { + ret = true; + goto done; + } + +done: + talloc_destroy(frame); + + return ret; +} + +/********************************************************************** + *********************************************************************/ + + NTSTATUS gc_find_forest_root(struct gc_info *gc, const char *domain) +{ + ADS_STRUCT *ads = NULL; + ADS_STATUS ads_status; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct nbt_cldap_netlogon_5 cldap_reply; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!gc || !domain) { + return NT_STATUS_INVALID_PARAMETER; + } + + ZERO_STRUCT(cldap_reply); + + ads = ads_init(domain, NULL, NULL); + BAIL_ON_PTR_ERROR(ads, nt_status); + + ads->auth.flags = ADS_AUTH_NO_BIND; + ads_status = ads_connect(ads); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4, ("find_forest_root: ads_connect(%s) failed! (%s)\n", + domain, ads_errstr(ads_status))); + } + nt_status = ads_ntstatus(ads_status); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if (!ads_cldap_netlogon_5(frame, + ads->config.ldap_server_name, + ads->config.realm, + &cldap_reply)) + { + DEBUG(4,("find_forest_root: Failed to get a CLDAP reply from %s!\n", + ads->server.ldap_server)); + nt_status = NT_STATUS_IO_TIMEOUT; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + gc->forest_name = talloc_strdup(gc, cldap_reply.forest); + BAIL_ON_PTR_ERROR(gc->forest_name, nt_status); + +done: + if (ads) { + ads_destroy(&ads); + } + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS gc_add_forest(const char *domain) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct gc_info *gc = NULL; + struct gc_info *find_gc = NULL; + char *dn; + ADS_STRUCT *ads = NULL; + struct likewise_cell *primary_cell = NULL; + + primary_cell = cell_list_head(); + if (!primary_cell) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Check for duplicates based on domain name first as this + requires no connection */ + + find_gc = gc_list_head(); + while (find_gc) { + if (strequal (find_gc->forest_name, domain)) + break; + find_gc = find_gc->next; + } + + if (find_gc) { + DEBUG(10,("gc_add_forest: %s already in list\n", find_gc->forest_name)); + return NT_STATUS_OK; + } + + if ((gc = TALLOC_ZERO_P(NULL, struct gc_info)) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Query the rootDSE for the forest root naming conect first. + Check that the a GC server for the forest has not already + been added */ + + nt_status = gc_find_forest_root(gc, domain); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + find_gc = gc_list_head(); + while (find_gc) { + if (strequal (find_gc->forest_name, gc->forest_name)) + break; + find_gc = find_gc->next; + } + + if (find_gc) { + DEBUG(10,("gc_add_forest: Forest %s already in list\n", + find_gc->forest_name)); + return NT_STATUS_OK; + } + + /* Not found, so add it here. Make sure we connect to + a DC in _this_ domain and not the forest root. */ + + dn = ads_build_dn(gc->forest_name); + BAIL_ON_PTR_ERROR(dn, nt_status); + + gc->search_base = talloc_strdup(gc, dn); + SAFE_FREE(dn); + BAIL_ON_PTR_ERROR(gc->search_base, nt_status); + +#if 0 + /* Can't use cell_connect_dn() here as there is no way to + specifiy the LWCELL_FLAG_GC_CELL flag setting for cell_connect() */ + + nt_status = cell_connect_dn(&gc->forest_cell, gc->search_base); + BAIL_ON_NTSTATUS_ERROR(nt_status); +#else + + gc->forest_cell = cell_new(); + BAIL_ON_PTR_ERROR(gc->forest_cell, nt_status); + + /* Set the DNS domain, dn, etc ... and add it to the list */ + + cell_set_dns_domain(gc->forest_cell, gc->forest_name); + cell_set_dn(gc->forest_cell, gc->search_base); + cell_set_flags(gc->forest_cell, LWCELL_FLAG_GC_CELL); +#endif + + /* It is possible to belong to a non-forest cell and a + non-provisioned forest (at our domain levele). In that + case, we should just inherit the flags from our primary + cell since the GC searches will match our own schema + model. */ + + if (strequal(primary_cell->forest_name, gc->forest_name) + || is_subdomain(primary_cell->dns_domain, gc->forest_name)) + { + cell_set_flags(gc->forest_cell, cell_flags(primary_cell)); + } else { + /* outside of our domain */ + + nt_status = cell_connect(gc->forest_cell); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = cell_lookup_settings(gc->forest_cell); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Drop the connection now that we have the settings */ + + ads = cell_connection(gc->forest_cell); + ads_destroy(&ads); + cell_set_connection(gc->forest_cell, NULL); + } + + DLIST_ADD_END(_gc_server_list, gc, struct gc_info*); + + DEBUG(10,("gc_add_forest: Added %s to Global Catalog list of servers\n", + gc->forest_name)); + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_destroy(gc); + DEBUG(3,("LWI: Failed to add new GC connection for %s (%s)\n", + domain, nt_errstr(nt_status))); + } + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static void gc_server_list_destroy(void) +{ + struct gc_info *gc = gc_list_head(); + + while (gc) { + struct gc_info *p = gc->next; + + cell_destroy(gc->forest_cell); + talloc_destroy(gc); + + gc = p; + } + + _gc_server_list = NULL; + + return; +} + +/********************************************************************** + Setup the initial list of forests and initial the forest cell + settings for each. FIXME!!! + *********************************************************************/ + + NTSTATUS gc_init_list(void) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct winbindd_tdc_domain *domains = NULL; + size_t num_domains = 0; + int i; + + if (_gc_server_list != NULL) { + gc_server_list_destroy(); + } + + if (!wcache_tdc_fetch_list(&domains, &num_domains)) { + nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Find our forest first. Have to try all domains here starting + with our own. gc_add_forest() filters duplicates */ + + nt_status = gc_add_forest(lp_realm()); + WARN_ON_NTSTATUS_ERROR(nt_status); + + for (i=0; i<num_domains; i++) { + uint32_t flags = (NETR_TRUST_FLAG_IN_FOREST); + + /* I think we should be able to break out of loop once + we add a GC for our forest and not have to test every one. + In fact, this entire loop is probably irrelevant since + the GC location code should always find a GC given lp_realm(). + Will have to spend time testing before making the change. + --jerry */ + + if ((domains[i].trust_flags & flags) == flags) { + nt_status = gc_add_forest(domains[i].dns_name); + WARN_ON_NTSTATUS_ERROR(nt_status); + /* Don't BAIL here since not every domain may + have a GC server */ + } + } + + /* Now add trusted forests. gc_add_forest() will filter out + duplicates. Check everything with an incoming trust path + that is not in our own forest. */ + + for (i=0; i<num_domains; i++) { + uint32_t flags = domains[i].trust_flags; + uint32_t attribs = domains[i].trust_attribs; + + /* Skip non_AD domains */ + + if (strlen(domains[i].dns_name) == 0) { + continue; + } + + /* Only add a GC for a forest outside of our own. + Ignore QUARANTINED/EXTERNAL trusts */ + + if ((flags & NETR_TRUST_FLAG_INBOUND) + && !(flags & NETR_TRUST_FLAG_IN_FOREST) + && (attribs & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) + { + nt_status = gc_add_forest(domains[i].dns_name); + WARN_ON_NTSTATUS_ERROR(nt_status); + } + } + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2,("LWI: Failed to initialized GC list (%s)\n", + nt_errstr(nt_status))); + } + + TALLOC_FREE(domains); + + return nt_status; +} + + +/********************************************************************** + *********************************************************************/ + + struct gc_info *gc_search_start(void) +{ + NTSTATUS nt_status = NT_STATUS_OK; + struct gc_info *gc = gc_list_head(); + + if (!gc) { + nt_status = gc_init_list(); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + gc = gc_list_head(); + } + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2,("LWI: Failed to initialize GC list (%s)\n", + nt_errstr(nt_status))); + } + + return gc; +} + +/********************************************************************** + Search Global Catalog. Always search our own forest. The flags set + controls whether or not we search cross forest. Assume that the + resulting set is always returned from one GC so that we don't have to + both combining the LDAPMessage * results + *********************************************************************/ + + NTSTATUS gc_search_forest(struct gc_info *gc, + LDAPMessage **msg, + const char *filter) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + const char *attrs[] = {"*", NULL}; + LDAPMessage *m = NULL; + + if (!gc || !msg || !filter) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* When you have multiple domain trees in a forest, the + GC will search all naming contexts when you send it + and empty ("") base search suffix. Tested against + Windows 2003. */ + + ads_status = cell_do_search(gc->forest_cell, "", + LDAP_SCOPE_SUBTREE, filter, attrs, &m); + nt_status = ads_ntstatus(ads_status); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + *msg = m; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(2,("LWI: Forest wide search %s failed (%s)\n", + filter, nt_errstr(nt_status))); + } + + return nt_status; +} + +/********************************************************************** + Search all forests via GC and return the results in an array of + ADS_STRUCT/LDAPMessage pairs. + *********************************************************************/ + + NTSTATUS gc_search_all_forests(const char *filter, + ADS_STRUCT ***ads_list, + LDAPMessage ***msg_list, + int *num_resp, uint32_t flags) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct gc_info *gc = NULL; + uint32_t test_flags = ADEX_GC_SEARCH_CHECK_UNIQUE; + + *ads_list = NULL; + *msg_list = NULL; + *num_resp = 0; + + if ((gc = gc_search_start()) == NULL) { + nt_status = NT_STATUS_INVALID_DOMAIN_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + while (gc) { + LDAPMessage *m = NULL; + + nt_status = gc_search_forest(gc, &m, filter); + if (!NT_STATUS_IS_OK(nt_status)) { + gc = gc->next; + continue; + } + + nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell), + m, ads_list, msg_list, + num_resp); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* If there can only be one match, then we are done */ + + if ((*num_resp > 0) && ((flags & test_flags) == test_flags)) { + break; + } + + gc = gc->next; + } + + if (*num_resp == 0) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + return nt_status; +} + +/********************************************************************** + Search all forests via GC and return the results in an array of + ADS_STRUCT/LDAPMessage pairs. + *********************************************************************/ + + NTSTATUS gc_search_all_forests_unique(const char *filter, + ADS_STRUCT **ads, + LDAPMessage **msg) +{ + ADS_STRUCT **ads_list = NULL; + LDAPMessage **msg_list = NULL; + int num_resp; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + + nt_status = gc_search_all_forests(filter, &ads_list, + &msg_list, &num_resp, + ADEX_GC_SEARCH_CHECK_UNIQUE); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = check_result_unique(ads_list[0], msg_list[0]); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + *ads = ads_list[0]; + *msg = msg_list[0]; + +done: + /* Be care that we don't free the msg result being returned */ + + if (!NT_STATUS_IS_OK(nt_status)) { + free_result_array(ads_list, msg_list, num_resp); + } else { + talloc_destroy(ads_list); + talloc_destroy(msg_list); + } + + return nt_status; +} + +/********************************************************************* + ********************************************************************/ + + NTSTATUS gc_name_to_sid(const char *domain, + const char *name, + DOM_SID *sid, + enum lsa_SidType *sid_type) +{ + TALLOC_CTX *frame = talloc_stackframe(); + char *p, *name_user; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *name_filter; + ADS_STRUCT *ads = NULL; + LDAPMessage *msg = NULL; + LDAPMessage *e = NULL; + char *dn = NULL; + char *dns_domain = NULL; + ADS_STRUCT **ads_list = NULL; + LDAPMessage **msg_list = NULL; + int num_resp = 0; + int i; + + /* Strip the "DOMAIN\" prefix if necessary and search for + a matching sAMAccountName in the forest */ + + if ((p = strchr_m( name, '\\' )) == NULL) + name_user = talloc_strdup( frame, name ); + else + name_user = talloc_strdup( frame, p+1 ); + BAIL_ON_PTR_ERROR(name_user, nt_status); + + name_filter = talloc_asprintf(frame, "(sAMAccountName=%s)", name_user); + BAIL_ON_PTR_ERROR(name_filter, nt_status); + + nt_status = gc_search_all_forests(name_filter, &ads_list, + &msg_list, &num_resp, 0); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Assume failure until we know otherwise*/ + + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + + /* Match the domain name from the DN */ + + for (i=0; i<num_resp; i++) { + ads = ads_list[i]; + msg = msg_list[i]; + + e = ads_first_entry(ads, msg); + while (e) { + struct winbindd_tdc_domain *domain_rec; + + dn = ads_get_dn(ads, e); + BAIL_ON_PTR_ERROR(dn, nt_status); + + dns_domain = cell_dn_to_dns(dn); + SAFE_FREE(dn); + BAIL_ON_PTR_ERROR(dns_domain, nt_status); + + domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); + SAFE_FREE(dns_domain); + + /* Ignore failures and continue the search */ + + if (!domain_rec) { + e = ads_next_entry(ads, e); + continue; + } + + /* Check for a match on the domain name */ + + if (strequal(domain, domain_rec->domain_name)) { + if (!ads_pull_sid(ads, e, "objectSid", sid)) { + nt_status = NT_STATUS_INVALID_SID; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + talloc_destroy(domain_rec); + + nt_status = get_sid_type(ads, msg, sid_type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* We're done! */ + nt_status = NT_STATUS_OK; + break; + } + + /* once more around thew merry-go-round */ + + talloc_destroy(domain_rec); + e = ads_next_entry(ads, e); + } + } + +done: + free_result_array(ads_list, msg_list, num_resp); + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + Pull an attribute string value + *******************************************************************/ + +static NTSTATUS get_object_account_name(ADS_STRUCT *ads, + LDAPMessage *msg, + char **name) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *sam_name = NULL; + struct winbindd_tdc_domain *domain_rec = NULL; + char *dns_domain = NULL; + char *dn = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + int len; + + /* Check parameters */ + + if (!ads || !msg || !name) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* get the name and domain */ + + dn = ads_get_dn(ads, msg); + BAIL_ON_PTR_ERROR(dn, nt_status); + + DEBUG(10,("get_object_account_name: dn = \"%s\"\n", dn)); + + dns_domain = cell_dn_to_dns(dn); + SAFE_FREE(dn); + BAIL_ON_PTR_ERROR(dns_domain, nt_status); + + domain_rec = wcache_tdc_fetch_domain(frame, dns_domain); + SAFE_FREE(dns_domain); + + if (!domain_rec) { + nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + sam_name = ads_pull_string(ads, frame, msg, "sAMAccountName"); + BAIL_ON_PTR_ERROR(sam_name, nt_status); + + len = asprintf(name, "%s\\%s", domain_rec->domain_name, sam_name); + if (len == -1) { + *name = NULL; + BAIL_ON_PTR_ERROR((*name), nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(frame); + + return nt_status; +} + +/********************************************************************* + ********************************************************************/ + + NTSTATUS gc_sid_to_name(const DOM_SID *sid, + char **name, + enum lsa_SidType *sid_type) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char *filter; + ADS_STRUCT *ads = NULL; + LDAPMessage *msg = NULL; + char *sid_string; + + *name = NULL; + + sid_string = sid_binstring(sid); + BAIL_ON_PTR_ERROR(sid_string, nt_status); + + filter = talloc_asprintf(frame, "(objectSid=%s)", sid_string); + SAFE_FREE(sid_string); + BAIL_ON_PTR_ERROR(filter, nt_status); + + nt_status = gc_search_all_forests_unique(filter, &ads, &msg); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_object_account_name(ads, msg, name); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_sid_type(ads, msg, sid_type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + ads_msgfree(ads, msg); + talloc_destroy(frame); + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + + NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads, + LDAPMessage *msg, + ADS_STRUCT ***ads_list, + LDAPMessage ***msg_list, + int *size) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + ADS_STRUCT **ads_tmp = NULL; + LDAPMessage **msg_tmp = NULL; + int count = *size; + + if (!ads || !msg) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + +#if 0 + /* Don't add a response with no entries */ + + if (ads_count_replies(ads, msg) == 0) { + return NT_STATUS_OK; + } +#endif + + if (count == 0) { + ads_tmp = TALLOC_ARRAY(NULL, ADS_STRUCT*, 1); + BAIL_ON_PTR_ERROR(ads_tmp, nt_status); + + msg_tmp = TALLOC_ARRAY(NULL, LDAPMessage*, 1); + BAIL_ON_PTR_ERROR(msg_tmp, nt_status); + } else { + ads_tmp = TALLOC_REALLOC_ARRAY(*ads_list, *ads_list, ADS_STRUCT*, + count+1); + BAIL_ON_PTR_ERROR(ads_tmp, nt_status); + + msg_tmp = TALLOC_REALLOC_ARRAY(*msg_list, *msg_list, LDAPMessage*, + count+1); + BAIL_ON_PTR_ERROR(msg_tmp, nt_status); + } + + ads_tmp[count] = ads; + msg_tmp[count] = msg; + count++; + + *ads_list = ads_tmp; + *msg_list = msg_tmp; + *size = count; + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + talloc_destroy(ads_tmp); + talloc_destroy(msg_tmp); + } + + return nt_status; +} + +/********************************************************************** + Frees search results. Do not free the ads_list as these are + references back to the GC search structures. + *********************************************************************/ + + void free_result_array(ADS_STRUCT **ads_list, + LDAPMessage **msg_list, + int num_resp) +{ + int i; + + for (i=0; i<num_resp; i++) { + ads_msgfree(ads_list[i], msg_list[i]); + } + + talloc_destroy(ads_list); + talloc_destroy(msg_list); +} + +/********************************************************************** + Check that we have exactly one entry from the search + *********************************************************************/ + + NTSTATUS check_result_unique(ADS_STRUCT *ads, LDAPMessage *msg) +{ + NTSTATUS nt_status; + int count; + + count = ads_count_replies(ads, msg); + + if (count <= 0) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if (count > 1) { + nt_status = NT_STATUS_DUPLICATE_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + return nt_status; +} diff --git a/source3/winbindd/idmap_adex/idmap_adex.c b/source3/winbindd/idmap_adex/idmap_adex.c new file mode 100644 index 0000000000..23ab843e95 --- /dev/null +++ b/source3/winbindd/idmap_adex/idmap_adex.c @@ -0,0 +1,460 @@ +/* + * idmap_adex: Support for D Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +#define WINBIND_CCACHE_NAME "MEMORY:winbind_ccache" + +NTSTATUS init_module(void); + +/* + * IdMap backend + */ + +/******************************************************************** + Basic init function responsible for determining our current mode + (standalone or using Centeris Cells). This must return success or + it will be dropped from the idmap backend list. + *******************************************************************/ + +static NTSTATUS _idmap_adex_init(struct idmap_domain *dom, + const char *params) +{ + ADS_STRUCT *ads = NULL; + ADS_STATUS status; + static NTSTATUS init_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + DOM_SID domain_sid; + fstring dcname; + struct sockaddr_storage ip; + struct likewise_cell *lwcell; + + if (NT_STATUS_IS_OK(init_status)) + return NT_STATUS_OK; + + /* Silently fail if we are not a member server in security = ads */ + + if ((lp_server_role() != ROLE_DOMAIN_MEMBER) || + (lp_security() != SEC_ADS)) { + init_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + /* fetch our domain SID first */ + + if (!secrets_fetch_domain_sid(lp_workgroup(), &domain_sid)) { + init_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + /* reuse the same ticket cache as winbindd */ + + setenv("KRB5CCNAME", WINBIND_CCACHE_NAME, 1); + + /* Establish a connection to a DC */ + + if ((ads = ads_init(lp_realm(), lp_workgroup(), NULL)) == NULL) { + init_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(init_status); + } + + ads->auth.password = + secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + ads->auth.realm = SMB_STRDUP(lp_realm()); + + /* get the DC name here to setup the server affinity cache and + local krb5.conf */ + + get_dc_name(lp_workgroup(), lp_realm(), dcname, &ip); + + status = ads_connect(ads); + if (!ADS_ERR_OK(status)) { + DEBUG(0, ("_idmap_adex_init: ads_connect() failed! (%s)\n", + ads_errstr(status))); + } + init_status = ads_ntstatus(status); + BAIL_ON_NTSTATUS_ERROR(init_status); + + + /* Find out cell membership */ + + init_status = cell_locate_membership(ads); + if (!NT_STATUS_IS_OK(init_status)) { + DEBUG(0,("LWI: Fail to locate cell membership (%s).", + nt_errstr(init_status))); + goto done; + } + + /* Fill in the cell information */ + + lwcell = cell_list_head(); + + init_status = cell_lookup_settings(lwcell); + BAIL_ON_NTSTATUS_ERROR(init_status); + + /* Miscellaneous setup. E.g. set up the list of GC + servers and domain list for our forest (does not actually + connect). */ + + init_status = gc_init_list(); + BAIL_ON_NTSTATUS_ERROR(init_status); + + init_status = domain_init_list(); + BAIL_ON_NTSTATUS_ERROR(init_status); + +done: + if (!NT_STATUS_IS_OK(init_status)) { + DEBUG(1,("Likewise initialization failed (%s)\n", + nt_errstr(init_status))); + } + + /* cleanup */ + + if (!NT_STATUS_IS_OK(init_status)) { + cell_list_destroy(); + + /* init_status stores the failure reason but we need to + return success or else idmap_init() will drop us from the + backend list */ + return NT_STATUS_OK; + } + + init_status = NT_STATUS_OK; + + return init_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_get_sid_from_id(struct + idmap_domain + *dom, struct + id_map + **ids) +{ + int i; + bool one_mapped = false; + bool all_mapped = true; + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(dom, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + /* have to work through these one by one */ + for (i = 0; ids[i]; i++) { + NTSTATUS status; + status = cell->provider->get_sid_from_id(ids[i]->sid, + ids[i]->xid.id, + ids[i]->xid.type); + /* Fail if we cannot find any DC */ + if (NT_STATUS_EQUAL + (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + return status; + } + + if (!NT_STATUS_IS_OK(status)) { + ids[i]->status = ID_UNMAPPED; + all_mapped = false; + continue; + } + + ids[i]->status = ID_MAPPED; + one_mapped = true; + } + + return NT_STATUS_OK; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_get_id_from_sid(struct + idmap_domain + *dom, struct + id_map + **ids) +{ + int i; + bool one_mapped = false; + bool all_mapped = true; + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(dom, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + /* have to work through these one by one */ + for (i = 0; ids[i]; i++) { + NTSTATUS status; + status = cell->provider->get_id_from_sid(&ids[i]->xid.id, + &ids[i]->xid. + type, ids[i]->sid); + /* Fail if we cannot find any DC */ + if (NT_STATUS_EQUAL + (status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) { + return status; + } + + if (!NT_STATUS_IS_OK(status)) { + ids[i]->status = ID_UNMAPPED; + all_mapped = false; + continue; + } + + ids[i]->status = ID_MAPPED; + one_mapped = true; + } + + return NT_STATUS_OK; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_set_mapping(struct + idmap_domain + *dom, const struct + id_map *map) +{ + DEBUG(0, ("_idmap_adex_set_mapping: not implemented\n")); + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_remove_mapping(struct + idmap_domain + *dom, const + struct + id_map + *map) +{ + DEBUG(0, ("_idmap_adex_remove_mapping: not implemented\n")); + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_dump(struct idmap_domain + *dom, struct id_map **maps, int *num_map) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _idmap_adex_close(struct idmap_domain + *dom) +{ + /* FIXME! need to do cleanup here */ + + return NT_STATUS_OK; +} + +/* + * IdMap NSS plugin + */ + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_init(struct nss_domain_entry + *e) +{ + return _idmap_adex_init(NULL, NULL); +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_get_info(struct + nss_domain_entry *e, + const DOM_SID * sid, + TALLOC_CTX * ctx, + ADS_STRUCT * ads, + LDAPMessage * msg, + char **homedir, + char **shell, char **gecos, gid_t * p_gid) +{ + NTSTATUS nt_status; + struct likewise_cell *cell; + + nt_status = _idmap_adex_init(NULL, NULL); + if (!NT_STATUS_IS_OK(nt_status)) + return nt_status; + + if ((cell = cell_list_head()) == NULL) { + return NT_STATUS_INVALID_SERVER_STATE; + } + + return cell->provider->get_nss_info(sid, ctx, homedir, + shell, gecos, p_gid); +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_map_to_alias(TALLOC_CTX * mem_ctx, const char + *domain, const char + *name, char **alias) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *cell = NULL; + + nt_status = _idmap_adex_init(NULL, NULL); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if ((cell = cell_list_head()) == NULL) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = cell->provider->map_to_alias(mem_ctx, domain, + name, alias); + + /* go ahead and allow the cache mgr to mark this in + negative cache */ + + if (!NT_STATUS_IS_OK(nt_status)) + nt_status = NT_STATUS_NONE_MAPPED; + +done: + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_map_from_alias(TALLOC_CTX * mem_ctx, const char + *domain, const char + *alias, char **name) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *cell = NULL; + + nt_status = _idmap_adex_init(NULL, NULL); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if ((cell = cell_list_head()) == NULL) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + + nt_status = cell->provider->map_from_alias(mem_ctx, domain, + alias, name); + + /* go ahead and allow the cache mgr to mark this in + negative cache */ + + if (!NT_STATUS_IS_OK(nt_status)) + nt_status = NT_STATUS_NONE_MAPPED; + +done: + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _nss_adex_close(void) +{ + return NT_STATUS_NOT_IMPLEMENTED; +} + +/********************************************************************** + *********************************************************************/ + +static struct idmap_methods adex_idmap_methods = { + + .init = _idmap_adex_init, + .unixids_to_sids = _idmap_adex_get_sid_from_id, + .sids_to_unixids = _idmap_adex_get_id_from_sid, + .set_mapping = _idmap_adex_set_mapping, + .remove_mapping = _idmap_adex_remove_mapping, + .dump_data = _idmap_adex_dump, + .close_fn = _idmap_adex_close +}; +static struct nss_info_methods adex_nss_methods = { + .init = _nss_adex_init, + .get_nss_info = _nss_adex_get_info, + .map_to_alias = _nss_adex_map_to_alias, + .map_from_alias = _nss_adex_map_from_alias, + .close_fn = _nss_adex_close +}; + +/********************************************************************** + Register with the idmap and idmap_nss subsystems. We have to protect + against the idmap and nss_info interfaces being in a half-registered + state. + **********************************************************************/ +NTSTATUS idmap_adex_init(void) +{ + static NTSTATUS idmap_status = NT_STATUS_UNSUCCESSFUL; + static NTSTATUS nss_status = NT_STATUS_UNSUCCESSFUL; + if (!NT_STATUS_IS_OK(idmap_status)) { + idmap_status = + smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, + "adex", &adex_idmap_methods); + if (!NT_STATUS_IS_OK(idmap_status)) { + DEBUG(0, + ("idmap_centeris_init: Failed to register the adex" + "idmap plugin.\n")); + return idmap_status; + } + } + + if (!NT_STATUS_IS_OK(nss_status)) { + nss_status = + smb_register_idmap_nss(SMB_NSS_INFO_INTERFACE_VERSION, + "adex", &adex_nss_methods); + if (!NT_STATUS_IS_OK(nss_status)) { + DEBUG(0, + ("idmap_adex_init: Failed to register the adex" + "nss plugin.\n")); + return nss_status; + } + } + + return NT_STATUS_OK; +} + +NTSTATUS nss_info_adex_init(void) +{ + return idmap_adex_init(); +} diff --git a/source3/winbindd/idmap_adex/idmap_adex.h b/source3/winbindd/idmap_adex/idmap_adex.h new file mode 100644 index 0000000000..f91bba8d07 --- /dev/null +++ b/source3/winbindd/idmap_adex/idmap_adex.h @@ -0,0 +1,257 @@ +/* + * idmap_centeris: Support for Local IDs and Centeris Cell Structure + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#ifndef _IDMAP_ADEX_H +#define _IDMAP_ADEX_H + +#include "winbindd/winbindd.h" + +#define ADEX_CELL_RDN "$LikewiseIdentityCell" + +#define ADEX_OC_USER "centerisLikewiseUser" +#define ADEX_OC_GROUP "centerisLikewiseGroup" + +#define AD_USER "User" +#define AD_GROUP "Group" + +#define ADEX_OC_POSIX_USER "posixAccount" +#define ADEX_OC_POSIX_GROUP "posixGroup" + +#define ADEX_ATTR_UIDNUM "uidNumber" +#define ADEX_ATTR_GIDNUM "gidNUmber" +#define ADEX_ATTR_HOMEDIR "unixHomeDirectory" +#define ADEX_ATTR_USERPW "unixUserPassword" +#define ADEX_ATTR_GROUPALIAS "groupAlias" /* Not part of RFC2307 */ +#define ADEX_ATTR_SHELL "loginShell" +#define ADEX_ATTR_GECOS "gecos" +#define ADEX_ATTR_UID "uid" +#define ADEX_ATTR_DISPLAYNAME "displayName" + +#define MIN_ID_VALUE 100 + +#define BAIL_ON_NTSTATUS_ERROR(x) \ + do { \ + if (!NT_STATUS_IS_OK(x)) { \ + DEBUG(10,("Failed! (%s)\n", nt_errstr(x))); \ + goto done; \ + } \ + } \ + while (0); \ + +#define WARN_ON_NTSTATUS_ERROR(x) \ + do { \ + if (!NT_STATUS_IS_OK(x)) { \ + DEBUG(10,("Failure ignored! (%s)\n", nt_errstr(x))); \ + } \ + } \ + while (0); \ + +#define BAIL_ON_ADS_ERROR(x) \ + do { \ + if (!ADS_ERR_OK(x)) { \ + goto done; \ + } \ + } \ + while (0); + +#define BAIL_ON_PTR_ERROR(p, x) \ + do { \ + if ((p) == NULL ) { \ + DEBUG(10,("NULL pointer!\n")); \ + x = NT_STATUS_NO_MEMORY; \ + goto done; \ + } \ + } while (0); + +#define PRINT_NTSTATUS_ERROR(x, hdr, level) \ + do { \ + if (!NT_STATUS_IS_OK(x)) { \ + DEBUG(level,("LWI ("hdr"): %s\n", nt_errstr(x))); \ + } \ + } while(0); +/* + * Cell Provider API + */ + +struct cell_provider_api { + NTSTATUS(*get_sid_from_id) (DOM_SID * sid, + uint32_t id, enum id_type type); + NTSTATUS(*get_id_from_sid) (uint32_t * id, + enum id_type * type, const DOM_SID * sid); + NTSTATUS(*get_nss_info) (const DOM_SID * sid, + TALLOC_CTX * ctx, + char **homedir, + char **shell, char **gecos, gid_t * p_gid); + NTSTATUS(*map_to_alias) (TALLOC_CTX * mem_ctx, + const char *domain, + const char *name, char **alias); + NTSTATUS(*map_from_alias) (TALLOC_CTX * mem_ctx, + const char *domain, + const char *alias, char **name); +}; + +/* registered providers */ + +extern struct cell_provider_api ccp_unified; +extern struct cell_provider_api ccp_local; + +#define LWCELL_FLAG_USE_RFC2307_ATTRS 0x00000001 +#define LWCELL_FLAG_SEARCH_FOREST 0x00000002 +#define LWCELL_FLAG_GC_CELL 0x00000004 +#define LWCELL_FLAG_LOCAL_MODE 0x00000008 + +struct likewise_cell { + struct likewise_cell *prev, *next; + ADS_STRUCT *conn; + struct likewise_cell *gc_search_cell; + DOM_SID domain_sid; + char *dns_domain; + char *forest_name; + char *dn; + struct GUID *links; /* only held by owning cell */ + size_t num_links; + uint32_t flags; + struct cell_provider_api *provider; +}; + +/* Search flags used for Global Catalog API */ + +#define ADEX_GC_SEARCH_CHECK_UNIQUE 0x00000001 + +struct gc_info { + struct gc_info *prev, *next; + char *forest_name; + char *search_base; + struct likewise_cell *forest_cell; +}; + +/* Available functions outside of idmap_lwidentity.c */ + +/* cell_util.c */ + +char *find_attr_string(char **list, size_t num_lines, const char *substr); +bool is_object_class(char **list, size_t num_lines, const char *substr); +int min_id_value(void); +char *cell_dn_to_dns(const char *dn); +NTSTATUS get_sid_type(ADS_STRUCT *ads, + LDAPMessage *msg, + enum lsa_SidType *type); + +NTSTATUS cell_locate_membership(ADS_STRUCT * ads); +NTSTATUS cell_lookup_settings(struct likewise_cell * cell); +NTSTATUS cell_follow_links(struct likewise_cell *cell); +NTSTATUS cell_set_local_provider(void); + +/* likewise_cell.c */ + +struct likewise_cell *cell_new(void); +struct likewise_cell *cell_list_head(void); + +bool cell_list_add(struct likewise_cell *cell); +bool cell_list_remove(struct likewise_cell * cell); + +void cell_list_destroy(); +void cell_destroy(struct likewise_cell *c); +void cell_set_forest_searches(struct likewise_cell *c, + bool search); +void cell_set_dns_domain(struct likewise_cell *c, + const char *dns_domain); +void cell_set_connection(struct likewise_cell *c, + ADS_STRUCT *ads); +void cell_set_dn(struct likewise_cell *c, + const char *dn); +void cell_set_domain_sid(struct likewise_cell *c, + DOM_SID *sid); +void cell_set_flags(struct likewise_cell *c, uint32_t flags); +void cell_clear_flags(struct likewise_cell *c, uint32_t flags); + +const char* cell_search_base(struct likewise_cell *c); +const char *cell_dns_domain(struct likewise_cell *c); +ADS_STRUCT *cell_connection(struct likewise_cell *c); +bool cell_search_forest(struct likewise_cell *c); +ADS_STATUS cell_do_search(struct likewise_cell *c, + const char *search_base, + int scope, + const char *expr, + const char **attrs, + LDAPMessage ** msg); +uint32_t cell_flags(struct likewise_cell *c); + +NTSTATUS cell_connect_dn(struct likewise_cell **c, + const char *dn); +NTSTATUS cell_connect(struct likewise_cell *c); + + +/* gc_util.c */ + +NTSTATUS gc_init_list(void); + +NTSTATUS gc_find_forest_root(struct gc_info *gc, + const char *domain); + +struct gc_info *gc_search_start(void); + +NTSTATUS gc_search_forest(struct gc_info *gc, + LDAPMessage **msg, + const char *filter); + +NTSTATUS gc_search_all_forests(const char *filter, + ADS_STRUCT ***ads_list, + LDAPMessage ***msg_list, + int *num_resp, uint32_t flags); + +NTSTATUS gc_search_all_forests_unique(const char *filter, + ADS_STRUCT **ads, + LDAPMessage **msg); + +NTSTATUS gc_name_to_sid(const char *domain, + const char *name, + DOM_SID *sid, + enum lsa_SidType *sid_type); + +NTSTATUS gc_sid_to_name(const DOM_SID *sid, + char **name, + enum lsa_SidType *sid_type); + +NTSTATUS add_ads_result_to_array(ADS_STRUCT *ads, + LDAPMessage *msg, + ADS_STRUCT ***ads_list, + LDAPMessage ***msg_list, + int *size); + +void free_result_array(ADS_STRUCT **ads_list, + LDAPMessage **msg_list, + int num_resp); + +NTSTATUS check_result_unique(ADS_STRUCT *ads, + LDAPMessage *msg); + + +/* domain_util.c */ + +NTSTATUS domain_init_list(void); + +NTSTATUS dc_search_domains(struct likewise_cell **cell, + LDAPMessage **msg, + const char *dn, + const DOM_SID *user_sid); + + +#endif /* _IDMAP_ADEX_H */ diff --git a/source3/winbindd/idmap_adex/likewise_cell.c b/source3/winbindd/idmap_adex/likewise_cell.c new file mode 100644 index 0000000000..77eeee406b --- /dev/null +++ b/source3/winbindd/idmap_adex/likewise_cell.c @@ -0,0 +1,425 @@ +/* + * idmap_adex: Support for AD Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +static struct likewise_cell *_lw_cell_list = NULL; + +/********************************************************************** + Return the current HEAD of the list + *********************************************************************/ + + struct likewise_cell *cell_list_head(void) +{ + return _lw_cell_list; +} + + +/********************************************************************** + *********************************************************************/ + + void cell_destroy(struct likewise_cell *c) +{ + if (!c) + return; + + if (c->conn) + ads_destroy(&c->conn); + + talloc_destroy(c); +} + +/********************************************************************** + Free all cell entries and reset the list head to NULL + *********************************************************************/ + + void cell_list_destroy(void) +{ + struct likewise_cell *p = _lw_cell_list; + + while (p) { + struct likewise_cell *q = p->next; + + cell_destroy(p); + + p = q; + } + + _lw_cell_list = NULL; + + return; +} + +/********************************************************************** + Add a new cell structure to the list + *********************************************************************/ + + struct likewise_cell* cell_new(void) +{ + struct likewise_cell *c; + + /* Each cell struct is a TALLOC_CTX* */ + + c = TALLOC_ZERO_P(NULL, struct likewise_cell); + if (!c) { + DEBUG(0,("cell_new: memory allocation failure!\n")); + return NULL; + } + + return c; +} + +/********************************************************************** + Add a new cell structure to the list + *********************************************************************/ + + bool cell_list_add(struct likewise_cell * cell) +{ + if (!cell) { + return false; + } + + /* Always add to the end */ + + DLIST_ADD_END(_lw_cell_list, cell, struct likewise_cell *); + + return true; +} + +/********************************************************************** + Add a new cell structure to the list + *********************************************************************/ + + bool cell_list_remove(struct likewise_cell * cell) +{ + if (!cell) { + return false; + } + + /* Remove and drop the cell structure */ + + DLIST_REMOVE(_lw_cell_list, cell); + talloc_destroy(cell); + + return true; +} + +/********************************************************************** + Set the containing DNS domain for a cell + *********************************************************************/ + + void cell_set_dns_domain(struct likewise_cell *c, const char *dns_domain) +{ + c->dns_domain = talloc_strdup(c, dns_domain); +} + +/********************************************************************** + Set ADS connection for a cell + *********************************************************************/ + + void cell_set_connection(struct likewise_cell *c, ADS_STRUCT *ads) +{ + c->conn = ads; +} + +/********************************************************************** + *********************************************************************/ + + void cell_set_flags(struct likewise_cell *c, uint32_t flags) +{ + c->flags |= flags; +} + +/********************************************************************** + *********************************************************************/ + + void cell_clear_flags(struct likewise_cell *c, uint32_t flags) +{ + c->flags &= ~flags; +} + +/********************************************************************** + Set the Cell's DN + *********************************************************************/ + + void cell_set_dn(struct likewise_cell *c, const char *dn) +{ + if ( c->dn) { + talloc_free(c->dn); + c->dn = NULL; + } + + c->dn = talloc_strdup(c, dn); +} + +/********************************************************************** + *********************************************************************/ + + void cell_set_domain_sid(struct likewise_cell *c, DOM_SID *sid) +{ + sid_copy(&c->domain_sid, sid); +} + +/* + * Query Routines + */ + +/********************************************************************** + *********************************************************************/ + + const char* cell_search_base(struct likewise_cell *c) +{ + if (!c) + return NULL; + + return talloc_asprintf(c, "cn=%s,%s", ADEX_CELL_RDN, c->dn); +} + +/********************************************************************** + *********************************************************************/ + + bool cell_search_forest(struct likewise_cell *c) +{ + uint32_t test_flags = LWCELL_FLAG_SEARCH_FOREST; + + return ((c->flags & test_flags) == test_flags); +} + +/********************************************************************** + *********************************************************************/ + + uint32_t cell_flags(struct likewise_cell *c) +{ + if (!c) + return 0; + + return c->flags; +} + +/********************************************************************** + *********************************************************************/ + + const char *cell_dns_domain(struct likewise_cell *c) +{ + if (!c) + return NULL; + + return c->dns_domain; +} + +/********************************************************************** + *********************************************************************/ + + ADS_STRUCT *cell_connection(struct likewise_cell *c) +{ + if (!c) + return NULL; + + return c->conn; +} + +/* + * Connection functions + */ + +/******************************************************************** + *******************************************************************/ + + NTSTATUS cell_connect(struct likewise_cell *c) +{ + ADS_STRUCT *ads = NULL; + ADS_STATUS ads_status; + fstring dc_name; + struct sockaddr_storage dcip; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + + /* have to at least have the AD domain name */ + + if (!c->dns_domain) { + nt_status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* clear out any old information */ + + if (c->conn) { + ads_destroy(&c->conn); + c->conn = NULL; + } + + /* now setup the new connection */ + + ads = ads_init(c->dns_domain, NULL, NULL); + BAIL_ON_PTR_ERROR(ads, nt_status); + + ads->auth.password = + secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + ads->auth.realm = SMB_STRDUP(lp_realm()); + + /* Make the connection. We should already have an initial + TGT using the machine creds */ + + if (cell_flags(c) & LWCELL_FLAG_GC_CELL) { + ads_status = ads_connect_gc(ads); + } else { + /* Set up server affinity for normal cells and the client + site name cache */ + + if (!get_dc_name("", c->dns_domain, dc_name, &dcip)) { + nt_status = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + ads_status = ads_connect(ads); + } + + + c->conn = ads; + + nt_status = ads_ntstatus(ads_status); + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + ads_destroy(&ads); + c->conn = NULL; + } + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + + NTSTATUS cell_connect_dn(struct likewise_cell **c, const char *dn) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *new_cell = NULL; + char *dns_domain = NULL; + + if (*c || !dn) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if ((new_cell = cell_new()) == NULL) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Set the DNS domain, dn, etc ... and add it to the list */ + + dns_domain = cell_dn_to_dns(dn); + cell_set_dns_domain(new_cell, dns_domain); + SAFE_FREE(dns_domain); + + cell_set_dn(new_cell, dn); + + nt_status = cell_connect(new_cell); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + *c = new_cell; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(1,("LWI: Failled to connect to cell \"%s\" (%s)\n", + dn ? dn : "NULL", nt_errstr(nt_status))); + talloc_destroy(new_cell); + } + + return nt_status; +} + + +/******************************************************************** + *******************************************************************/ + +#define MAX_SEARCH_COUNT 2 + + ADS_STATUS cell_do_search(struct likewise_cell *c, + const char *search_base, + int scope, + const char *expr, + const char **attrs, + LDAPMessage ** msg) +{ + int search_count = 0; + ADS_STATUS status; + NTSTATUS nt_status; + + /* check for a NULL connection */ + + if (!c->conn) { + nt_status = cell_connect(c); + if (!NT_STATUS_IS_OK(nt_status)) { + status = ADS_ERROR_NT(nt_status); + return status; + } + } + + DEBUG(10, ("cell_do_search: Base = %s, Filter = %s, Scope = %d, GC = %s\n", + search_base, expr, scope, + c->conn->server.gc ? "yes" : "no")); + + /* we try multiple times in case the ADS_STRUCT is bad + and we need to reconnect */ + + while (search_count < MAX_SEARCH_COUNT) { + *msg = NULL; + status = ads_do_search(c->conn, search_base, + scope, expr, attrs, msg); + if (ADS_ERR_OK(status)) { + return status; + } + + + DEBUG(5, ("cell_do_search: search[%d] failed (%s)\n", + search_count, ads_errstr(status))); + + search_count++; + + /* Houston, we have a problem */ + + if (status.error_type == ENUM_ADS_ERROR_LDAP) { + switch (status.err.rc) { + case LDAP_TIMELIMIT_EXCEEDED: + case LDAP_TIMEOUT: + case -1: /* we get this error if we cannot contact + the LDAP server */ + nt_status = cell_connect(c); + if (!NT_STATUS_IS_OK(nt_status)) { + status = ADS_ERROR_NT(nt_status); + return status; + } + break; + default: + /* we're all done here */ + return status; + } + } + } + + DEBUG(5, ("cell_do_search: exceeded maximum search count!\n")); + + return ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); +} diff --git a/source3/winbindd/idmap_adex/provider_unified.c b/source3/winbindd/idmap_adex/provider_unified.c new file mode 100644 index 0000000000..f18534797e --- /dev/null +++ b/source3/winbindd/idmap_adex/provider_unified.c @@ -0,0 +1,1180 @@ +/* + * idmap_adex + * + * Provider for RFC2307 and SFU AD Forests + * + * Copyright (C) Gerald (Jerry) Carter 2006-2008 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include "includes.h" +#include "idmap_adex.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +/* Information needed by the LDAP search filters */ + +enum filterType { SidFilter, IdFilter, AliasFilter }; + +struct lwcell_filter +{ + enum filterType ftype; + bool use2307; + union { + DOM_SID sid; + struct { + uint32_t id; + enum id_type type; + } id; + fstring alias; + } filter; +}; + +/******************************************************************** + *******************************************************************/ + +static char* build_id_filter(uint32_t id, + enum id_type type, + uint32_t search_flags) +{ + char *filter = NULL; + char *oc_filter, *attr_filter; + NTSTATUS nt_status; + TALLOC_CTX *frame = talloc_stackframe(); + bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS) + == LWCELL_FLAG_USE_RFC2307_ATTRS); + bool use_gc = ((search_flags & LWCELL_FLAG_SEARCH_FOREST) + == LWCELL_FLAG_SEARCH_FOREST); + const char *oc; + + /* Construct search filter for objectclass and attributes */ + + switch (type) { + case ID_TYPE_UID: + oc = ADEX_OC_USER; + if (use2307) { + oc = ADEX_OC_POSIX_USER; + if (use_gc) { + oc = AD_USER; + } + } + oc_filter = talloc_asprintf(frame, "objectclass=%s", oc); + attr_filter = talloc_asprintf(frame, "%s=%u", + ADEX_ATTR_UIDNUM, id); + break; + + case ID_TYPE_GID: + oc = ADEX_OC_GROUP; + if (use2307) { + oc = ADEX_OC_POSIX_GROUP; + if (use_gc) { + oc = AD_GROUP; + } + } + oc_filter = talloc_asprintf(frame, "objectclass=%s", oc); + attr_filter = talloc_asprintf(frame, "%s=%u", + ADEX_ATTR_GIDNUM, id); + break; + default: + return NULL; + } + + BAIL_ON_PTR_ERROR(oc_filter, nt_status); + BAIL_ON_PTR_ERROR(attr_filter, nt_status); + + /* Use "keywords=%s" for non-schema cells */ + + if (use2307) { + filter = talloc_asprintf(frame, "(&(%s)(%s))", + oc_filter, attr_filter); + } else { + filter = talloc_asprintf(frame, "(&(keywords=%s)(keywords=%s))", + oc_filter, attr_filter); + } + + talloc_destroy(oc_filter); + talloc_destroy(attr_filter); + +done: + /* Don't destroy the stackframe CTX since we are returning + memory from it */ + + return filter; +} + +/******************************************************************** + *******************************************************************/ + +static char* build_alias_filter(const char *alias, uint32_t search_flags) +{ + char *filter = NULL; + char *user_attr_filter, *group_attr_filter; + NTSTATUS nt_status; + TALLOC_CTX *frame = talloc_stackframe(); + bool use2307 = ((search_flags & LWCELL_FLAG_USE_RFC2307_ATTRS) + == LWCELL_FLAG_USE_RFC2307_ATTRS); + bool search_forest = ((search_flags & LWCELL_FLAG_SEARCH_FOREST) + == LWCELL_FLAG_SEARCH_FOREST); + + /* Construct search filter for objectclass and attributes */ + + user_attr_filter = talloc_asprintf(frame, "%s=%s", + ADEX_ATTR_UID, alias); + group_attr_filter = talloc_asprintf(frame, "%s=%s", + ADEX_ATTR_DISPLAYNAME, alias); + BAIL_ON_PTR_ERROR(user_attr_filter, nt_status); + BAIL_ON_PTR_ERROR(group_attr_filter, nt_status); + + /* Use "keywords=%s" for non-schema cells */ + + if (use2307) { + filter = talloc_asprintf(frame, + "(|(&(%s)(objectclass=%s))(&(%s)(objectclass=%s)))", + user_attr_filter, + search_forest ? AD_USER : ADEX_OC_POSIX_USER, + group_attr_filter, + search_forest ? AD_GROUP : ADEX_OC_POSIX_GROUP); + } else { + filter = talloc_asprintf(frame, + "(|(keywords=%s)(keywords=%s))", + user_attr_filter, + group_attr_filter); + } + + talloc_destroy(user_attr_filter); + talloc_destroy(group_attr_filter); + +done: + /* Don't destroy the stackframe CTX since we are returning + memory from it */ + + return filter; +} + + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS search_cell(struct likewise_cell *c, + LDAPMessage **msg, + const struct lwcell_filter *fdata) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX* frame = talloc_stackframe(); + char *filter = NULL; + const char *base = NULL; + ADS_STATUS ads_status = ADS_ERROR_NT(NT_STATUS_UNSUCCESSFUL); + const char *attrs[] = { "*", NULL }; + int count; + char *sid_str; + + /* get the filter and other search parameters */ + + switch (fdata->ftype) { + case SidFilter: + sid_str = sid_string_talloc(frame, &fdata->filter.sid); + BAIL_ON_PTR_ERROR(sid_str, nt_status); + + filter = talloc_asprintf(frame, "(keywords=backLink=%s)", + sid_str); + break; + case IdFilter: + filter = build_id_filter(fdata->filter.id.id, + fdata->filter.id.type, + cell_flags(c)); + break; + case AliasFilter: + filter = build_alias_filter(fdata->filter.alias, + cell_flags(c)); + break; + default: + nt_status = NT_STATUS_INVALID_PARAMETER; + break; + } + BAIL_ON_PTR_ERROR(filter, nt_status); + + base = cell_search_base(c); + BAIL_ON_PTR_ERROR(base, nt_status); + + ads_status = cell_do_search(c, base, LDAP_SCOPE_SUBTREE, + filter, attrs, msg); + + nt_status = ads_ntstatus(ads_status); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Now check that we got only one reply */ + + count = ads_count_replies(c->conn, *msg); + if (count < 1) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if ( count > 1) { + nt_status = NT_STATUS_DUPLICATE_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + +done: + PRINT_NTSTATUS_ERROR(nt_status, "search_cell", 4); + + talloc_destroy(CONST_DISCARD(char*, base)); + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS search_domain(struct likewise_cell **cell, + LDAPMessage **msg, + const char *dn, + const DOM_SID *sid) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX* frame = talloc_stackframe(); + int count; + + nt_status = dc_search_domains(cell, msg, dn, sid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Now check that we got only one reply */ + + count = ads_count_replies(cell_connection(*cell), *msg); + if (count < 1) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if ( count > 1) { + nt_status = NT_STATUS_DUPLICATE_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + +done: + PRINT_NTSTATUS_ERROR(nt_status, "search_domain", 4); + talloc_destroy(frame); + + return nt_status; +} + + +/******************************************************************** + Check that a DN is within the forest scope. + *******************************************************************/ + +static bool check_forest_scope(const char *dn) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *frame = talloc_stackframe(); + char *p = NULL; + char *q = NULL; + char *dns_domain = NULL; + struct winbindd_tdc_domain *domain; + + /* If the DN does *not* contain "$LikewiseIdentityCell", + assume this is a schema mode forest and it is in the + forest scope by definition. */ + + if ((p = strstr_m(dn, ADEX_CELL_RDN)) == NULL) { + nt_status = NT_STATUS_OK; + goto done; + } + + /* If this is a non-schema forest, then make sure that the DN + is in the form "...,cn=$LikewiseIdentityCell,DC=..." */ + + if ((q = strchr_m(p, ',')) == NULL) { + nt_status = NT_STATUS_OBJECT_NAME_INVALID; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + q++; + if (StrnCaseCmp(q, "dc=", 3) != 0) { + nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + + dns_domain = cell_dn_to_dns(q); + BAIL_ON_PTR_ERROR(dns_domain, nt_status); + + domain = wcache_tdc_fetch_domain(frame, dns_domain); + if (!domain) { + nt_status = NT_STATUS_TRUSTED_DOMAIN_FAILURE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(frame); + SAFE_FREE(dns_domain); + + return NT_STATUS_IS_OK(nt_status); +} + + + +/******************************************************************** + Check that only one result was returned within the forest cell + scope. + *******************************************************************/ + +static NTSTATUS check_result_unique_scoped(ADS_STRUCT **ads_list, + LDAPMessage **msg_list, + int num_resp, + char **dn, + DOM_SID *user_sid) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + int i; + ADS_STRUCT *ads = NULL; + LDAPMessage *msg = NULL; + int count = 0; + char *entry_dn = NULL; + TALLOC_CTX *frame = talloc_stackframe(); + + if (!dn || !user_sid) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + *dn = NULL; + + if (!ads_list || !msg_list || (num_resp == 0)) { + nt_status = NT_STATUS_NO_SUCH_FILE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Loop over all msgs */ + + for (i=0; i<num_resp; i++) { + LDAPMessage *e = ads_first_entry(ads_list[i], msg_list[i]); + + while (e) { + entry_dn = ads_get_dn(ads_list[i], e); + BAIL_ON_PTR_ERROR(entry_dn, nt_status); + + if (check_forest_scope(entry_dn)) { + count++; + + /* If we've already broken the condition, no + need to continue */ + + if (count > 1) { + nt_status = NT_STATUS_DUPLICATE_NAME; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + ads = ads_list[i]; + msg = e; + *dn = SMB_STRDUP(entry_dn); + BAIL_ON_PTR_ERROR((*dn), nt_status); + } + + e = ads_next_entry(ads_list[i], e); + SAFE_FREE(entry_dn); + } + } + + if (!ads || !msg) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* If we made is through the loop, then grab the user_sid and + run home to base */ + + /* + Try and get the SID from either objectSid or keywords. + We cannot use pull_sid() here since we want to try + both methods and not only one or the other (and we + have no full likewise_cell struct. + + Fail if both are unavailable + */ + + if (!ads_pull_sid(ads, msg, "objectSid", user_sid)) { + char **keywords; + char *s; + size_t num_lines = 0; + + keywords = ads_pull_strings(ads, frame, msg, "keywords", + &num_lines); + BAIL_ON_PTR_ERROR(keywords, nt_status); + + s = find_attr_string(keywords, num_lines, "backLink"); + if (!s) { + nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if (!string_to_sid(user_sid, s)) { + nt_status = NT_STATUS_INVALID_SID; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + } + + nt_status = NT_STATUS_OK; + +done: + if (!NT_STATUS_IS_OK(nt_status)) { + SAFE_FREE(*dn); + } + + talloc_destroy(frame); + SAFE_FREE(entry_dn); + + return nt_status; +} + +/******************************************************************** + Search all forests. Each forest can have it's own forest-cell + settings so we have to generate the filter for each search. + We don't use gc_search_all_forests() since we may have a different + schema model in each forest and need to construct the search + filter for each GC search. + *******************************************************************/ + +static NTSTATUS search_forest(struct likewise_cell *forest_cell, + LDAPMessage **msg, + const struct lwcell_filter *fdata) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *frame = talloc_stackframe(); + char *filter = NULL; + char *dn = NULL; + struct gc_info *gc = NULL; + ADS_STRUCT **ads_list = NULL; + LDAPMessage **msg_list = NULL; + int num_resp = 0; + LDAPMessage *m; + DOM_SID user_sid; + struct likewise_cell *domain_cell = NULL; + + if ((gc = gc_search_start()) == NULL) { + nt_status = NT_STATUS_INVALID_DOMAIN_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + while (gc) { + char *sid_binstr = NULL; + uint32_t flags = LWCELL_FLAG_SEARCH_FOREST; + + m = NULL; + + flags |= cell_flags(gc->forest_cell); + + switch (fdata->ftype) { + case SidFilter: + sid_binstr = sid_binstring(&fdata->filter.sid); + BAIL_ON_PTR_ERROR(sid_binstr, nt_status); + + filter = talloc_asprintf(frame, "(objectSid=%s)", sid_binstr); + SAFE_FREE(sid_binstr); + break; + case IdFilter: + filter = build_id_filter(fdata->filter.id.id, + fdata->filter.id.type, flags); + break; + case AliasFilter: + filter = build_alias_filter(fdata->filter.alias, flags); + break; + } + + /* First find the sparse object in GC */ + nt_status = gc_search_forest(gc, &m, filter); + if (!NT_STATUS_IS_OK(nt_status)) { + gc = gc->next; + continue; + } + + nt_status = add_ads_result_to_array(cell_connection(gc->forest_cell), + m, &ads_list, &msg_list, + &num_resp); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + gc = gc->next; + } + + /* Uniqueness check across forests */ + + nt_status = check_result_unique_scoped(ads_list, msg_list, num_resp, + &dn, &user_sid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = search_domain(&domain_cell, &m, dn, &user_sid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Save the connection and results in the return parameters */ + + forest_cell->gc_search_cell = domain_cell; + *msg = m; + +done: + PRINT_NTSTATUS_ERROR(nt_status, "search_forest", 4); + + SAFE_FREE(dn); + + free_result_array(ads_list, msg_list, num_resp); + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS search_cell_list(struct likewise_cell **c, + LDAPMessage **m, + const struct lwcell_filter *fdata) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + struct likewise_cell *cell = NULL; + LDAPMessage *msg = NULL; + struct likewise_cell *result_cell = NULL; + + if ((cell = cell_list_head()) == NULL) { + nt_status = NT_STATUS_INVALID_SERVER_STATE; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + while (cell) { + /* Clear any previous GC search results */ + + cell->gc_search_cell = NULL; + + if (cell_search_forest(cell)) { + nt_status = search_forest(cell, &msg, fdata); + } else { + nt_status = search_cell(cell, &msg, fdata); + } + + /* Always point to the search result cell. + In forests this might be for another domain + which means the schema model may be different */ + + result_cell = cell->gc_search_cell ? + cell->gc_search_cell : cell; + + /* Check if we are done */ + + if (NT_STATUS_IS_OK(nt_status)) { + break; + } + + /* No luck. Free memory and hit the next cell. + Forest searches always set the gc_search_cell + so give preference to that connection if possible. */ + + ads_msgfree(cell_connection(result_cell), msg); + msg = NULL; + + cell = cell->next; + } + + /* This might be assigning NULL but that is ok as long as we + give back the proper error code */ + + *c = result_cell; + *m = msg; + +done: + PRINT_NTSTATUS_ERROR(nt_status, "search_cell_list", 3); + + return nt_status; +} + +/******************************************************************** + Pull the SID from an object which is always stored in the keywords + attribute as "backLink=S-1-5-21-..." + *******************************************************************/ + +static NTSTATUS pull_sid(struct likewise_cell *c, + LDAPMessage *msg, + DOM_SID *sid) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + TALLOC_CTX *frame = talloc_stackframe(); + ADS_STRUCT *ads = NULL; + + ads = cell_connection(c); + + /* + We have two ways of getting the sid: + (a) from the objectSID in case of a GC search, + (b) from backLink in the case of a cell search. + Pull the keywords attributes and grab the backLink. + */ + + if (!ads_pull_sid(ads, msg, "objectSid", sid)) { + char **keywords; + char *s; + size_t num_lines = 0; + + keywords = ads_pull_strings(ads, frame, msg, + "keywords", &num_lines); + BAIL_ON_PTR_ERROR(keywords, nt_status); + + s = find_attr_string(keywords, num_lines, "backLink"); + if (!s) { + nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + if (!string_to_sid(sid, s)) { + nt_status = NT_STATUS_INVALID_SID; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS get_object_type(struct likewise_cell *c, + LDAPMessage *msg, + enum id_type *type) +{ + TALLOC_CTX *ctx = talloc_stackframe(); + char **oc_list = NULL; + NTSTATUS nt_status = NT_STATUS_OK; + size_t list_size = 0; + char *s = NULL; + ADS_STRUCT *ads = NULL; + + ads = cell_connection(c); + + /* Deal with RFC 2307 support first */ + + if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { + oc_list = ads_pull_strings(ads, ctx, msg, + "objectClass", &list_size); + if (!oc_list) { + nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } + + /* Check for posix classes and AD classes */ + + if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_USER) + || is_object_class(oc_list, list_size, AD_USER)) { + *type = ID_TYPE_UID; + } else if (is_object_class(oc_list, list_size, ADEX_OC_POSIX_GROUP) + || is_object_class(oc_list, list_size, AD_GROUP)) { + *type = ID_TYPE_GID; + } else { + *type = ID_TYPE_NOT_SPECIFIED; + nt_status = NT_STATUS_INVALID_PARAMETER; + } + } else { + /* Default to non-schema mode */ + + oc_list = ads_pull_strings(ads, ctx, msg, + "keywords", &list_size); + if (!oc_list) { + nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } + + s = find_attr_string(oc_list, list_size, "objectClass"); + if (!s) { + nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto done; + } + + if (strequal(s, ADEX_OC_USER)) { + *type = ID_TYPE_UID; + } else if (strequal(s, ADEX_OC_GROUP)) { + *type = ID_TYPE_GID; + } else { + *type = ID_TYPE_NOT_SPECIFIED; + nt_status = NT_STATUS_INVALID_PARAMETER; + } + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(ctx); + + return nt_status; +} + +/******************************************************************** + Pull an attribute uint32_t value + *******************************************************************/ + +static NTSTATUS get_object_uint32(struct likewise_cell *c, + LDAPMessage *msg, + const char *attrib, + uint32_t *x) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char **keywords = NULL; + size_t list_size = 0; + TALLOC_CTX *frame = talloc_stackframe(); + ADS_STRUCT *ads = NULL; + + ads = cell_connection(c); + + /* Deal with RFC2307 schema */ + + if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { + if (!ads_pull_uint32(ads, msg, attrib, x)) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + } else { + /* Non-schema mode */ + char *s = NULL; + uint32_t num; + + keywords = ads_pull_strings(ads, frame, msg, "keywords", + &list_size); + BAIL_ON_PTR_ERROR(keywords, nt_status); + + s = find_attr_string(keywords, list_size, attrib); + if (!s) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + num = strtoll(s, NULL, 10); + if (errno == ERANGE) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + *x = num; + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS get_object_id(struct likewise_cell *c, + LDAPMessage *msg, + enum id_type type, + uint32_t *id) +{ + NTSTATUS nt_status = NT_STATUS_OK; + const char *id_attr; + + /* Figure out which attribute we need to pull */ + + switch (type) { + case ID_TYPE_UID: + id_attr = ADEX_ATTR_UIDNUM; + break; + case ID_TYPE_GID: + id_attr = ADEX_ATTR_GIDNUM; + break; + default: + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + break; + } + + nt_status = get_object_uint32(c, msg, id_attr, id); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + return nt_status; +} + +/******************************************************************** + Pull the uid/gid and type from an object. This differs depending on + the cell flags. + *******************************************************************/ + +static NTSTATUS pull_id(struct likewise_cell *c, + LDAPMessage *msg, + uint32_t *id, + enum id_type *type) +{ + NTSTATUS nt_status; + + nt_status = get_object_type(c, msg, type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_object_id(c, msg, *type, id); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + return nt_status; +} + +/******************************************************************** + Pull an attribute string value + *******************************************************************/ + +static NTSTATUS get_object_string(struct likewise_cell *c, + LDAPMessage *msg, + TALLOC_CTX *ctx, + const char *attrib, + char **string) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + char **keywords = NULL; + size_t list_size = 0; + TALLOC_CTX *frame = talloc_stackframe(); + ADS_STRUCT *ads = NULL; + + *string = NULL; + + ads = cell_connection(c); + + /* Deal with RFC2307 schema */ + + if (cell_flags(c) & LWCELL_FLAG_USE_RFC2307_ATTRS) { + *string = ads_pull_string(ads, ctx, msg, attrib); + } else { + /* Non-schema mode */ + + char *s = NULL; + + keywords = ads_pull_strings(ads, frame, msg, + "keywords", &list_size); + if (!keywords) { + nt_status = NT_STATUS_NO_MEMORY; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + s = find_attr_string(keywords, list_size, attrib); + if (s) { + *string = talloc_strdup(ctx, s); + } + } + + if (!*string) { + nt_status = NT_STATUS_OBJECT_NAME_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = NT_STATUS_OK; + +done: + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + Pull the struct passwd fields for a user + *******************************************************************/ + +static NTSTATUS pull_nss_info(struct likewise_cell *c, + LDAPMessage *msg, + TALLOC_CTX *ctx, + char **homedir, + char **shell, + char **gecos, + gid_t *p_gid) +{ + NTSTATUS nt_status; + + nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_HOMEDIR, homedir); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_SHELL, shell); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_object_string(c, msg, ctx, ADEX_ATTR_GECOS, gecos); + /* Gecos is often not set so ignore failures */ + + nt_status = get_object_uint32(c, msg, ADEX_ATTR_GIDNUM, p_gid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + return nt_status; +} + +/******************************************************************** + Pull the struct passwd fields for a user + *******************************************************************/ + +static NTSTATUS pull_alias(struct likewise_cell *c, + LDAPMessage *msg, + TALLOC_CTX *ctx, + char **alias) +{ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + enum id_type type; + const char *attr = NULL; + + /* Figure out if this is a user or a group */ + + nt_status = get_object_type(c, msg, &type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + switch (type) { + case ID_TYPE_UID: + attr = ADEX_ATTR_UID; + break; + case ID_TYPE_GID: + /* What is the group attr for RFC2307 Forests? */ + attr = ADEX_ATTR_DISPLAYNAME; + break; + default: + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + break; + } + + nt_status = get_object_string(c, msg, ctx, attr, alias); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS _ccp_get_sid_from_id(DOM_SID * sid, + uint32_t id, enum id_type type) +{ + struct likewise_cell *cell = NULL; + LDAPMessage *msg = NULL; + NTSTATUS nt_status; + struct lwcell_filter filter; + + filter.ftype = IdFilter; + filter.filter.id.id = id; + filter.filter.id.type = type; + + nt_status = search_cell_list(&cell, &msg, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = pull_sid(cell, msg, sid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + ads_msgfree(cell->conn, msg); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS _ccp_get_id_from_sid(uint32_t * id, + enum id_type *type, + const DOM_SID * sid) +{ + struct likewise_cell *cell = NULL; + LDAPMessage *msg = NULL; + NTSTATUS nt_status; + struct lwcell_filter filter; + + filter.ftype = SidFilter; + sid_copy(&filter.filter.sid, sid); + + nt_status = search_cell_list(&cell, &msg, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = pull_id(cell, msg, id, type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if (*id < min_id_value()) { + nt_status = NT_STATUS_INVALID_PARAMETER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + +done: + ads_msgfree(cell->conn, msg); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +static NTSTATUS _ccp_nss_get_info(const DOM_SID * sid, + TALLOC_CTX * ctx, + char **homedir, + char **shell, + char **gecos, gid_t * p_gid) +{ + struct likewise_cell *cell = NULL; + LDAPMessage *msg = NULL; + NTSTATUS nt_status; + struct lwcell_filter filter; + enum id_type type; + + filter.ftype = SidFilter; + sid_copy(&filter.filter.sid, sid); + + nt_status = search_cell_list(&cell, &msg, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = get_object_type(cell, msg, &type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if (type != ID_TYPE_UID) { + nt_status = NT_STATUS_NO_SUCH_USER; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + nt_status = pull_nss_info(cell, msg, ctx, homedir, shell, gecos, + (uint32_t*) p_gid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + ads_msgfree(cell->conn, msg); + + return nt_status; +} + +/********************************************************************** + *********************************************************************/ + +static NTSTATUS _ccp_map_to_alias(TALLOC_CTX *ctx, + const char *domain, + const char *name, char **alias) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + DOM_SID sid; + struct likewise_cell *cell = NULL; + LDAPMessage *msg = NULL; + struct lwcell_filter filter; + enum lsa_SidType sid_type; + + /* Convert the name to a SID */ + + nt_status = gc_name_to_sid(domain, name, &sid, &sid_type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Find the user/group */ + + filter.ftype = SidFilter; + sid_copy(&filter.filter.sid, &sid); + + nt_status = search_cell_list(&cell, &msg, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Pull the alias and return */ + + nt_status = pull_alias(cell, msg, ctx, alias); + BAIL_ON_NTSTATUS_ERROR(nt_status); + +done: + PRINT_NTSTATUS_ERROR(nt_status, "map_to_alias", 3); + + talloc_destroy(frame); + ads_msgfree(cell_connection(cell), msg); + + return nt_status; +} + +/********************************************************************** + Map from an alias name to the canonical, qualified name. + Ensure that the alias is only pull from the closest in which + the user or gorup is enabled in + *********************************************************************/ + +static NTSTATUS _ccp_map_from_alias(TALLOC_CTX *mem_ctx, + const char *domain, + const char *alias, char **name) +{ + TALLOC_CTX *frame = talloc_stackframe(); + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; + DOM_SID sid; + struct likewise_cell *cell_alias = NULL; + LDAPMessage *msg_alias = NULL; + struct likewise_cell *cell_sid = NULL; + LDAPMessage *msg_sid = NULL; + struct lwcell_filter filter; + char *canonical_name = NULL; + enum lsa_SidType type; + + /* Find the user/group */ + + filter.ftype = AliasFilter; + fstrcpy(filter.filter.alias, alias); + + nt_status = search_cell_list(&cell_alias, &msg_alias, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + nt_status = pull_sid(cell_alias, msg_alias, &sid); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + /* Now search again for the SID according to the cell list. + Verify that the cell of both search results is the same + so that we only match an alias from the closest cell + in which a user/group has been instantied. */ + + filter.ftype = SidFilter; + sid_copy(&filter.filter.sid, &sid); + + nt_status = search_cell_list(&cell_sid, &msg_sid, &filter); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + if (cell_alias != cell_sid) { + nt_status = NT_STATUS_OBJECT_PATH_NOT_FOUND; + BAIL_ON_NTSTATUS_ERROR(nt_status); + } + + /* Finally do the GC sid/name conversion */ + + nt_status = gc_sid_to_name(&sid, &canonical_name, &type); + BAIL_ON_NTSTATUS_ERROR(nt_status); + + *name = talloc_strdup(mem_ctx, canonical_name); + BAIL_ON_PTR_ERROR((*name), nt_status); + + nt_status = NT_STATUS_OK; + +done: + PRINT_NTSTATUS_ERROR(nt_status, "map_from_alias", 3); + + ads_msgfree(cell_connection(cell_alias), msg_alias); + ads_msgfree(cell_connection(cell_sid), msg_sid); + + SAFE_FREE(canonical_name); + + talloc_destroy(frame); + + return nt_status; +} + +/******************************************************************** + *******************************************************************/ + +struct cell_provider_api ccp_unified = { + .get_sid_from_id = _ccp_get_sid_from_id, + .get_id_from_sid = _ccp_get_id_from_sid, + .get_nss_info = _ccp_nss_get_info, + .map_to_alias = _ccp_map_to_alias, + .map_from_alias = _ccp_map_from_alias +}; diff --git a/source3/winbindd/winbindd_ads.c b/source3/winbindd/winbindd_ads.c index 894e7866b3..1febddf110 100644 --- a/source3/winbindd/winbindd_ads.c +++ b/source3/winbindd/winbindd_ads.c @@ -1023,10 +1023,11 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, DEBUG(10,("ads: lookup_groupmem: got sid %s from " "cache\n", sid_string_dbg(&sid))); sid_copy(&(*sid_mem)[*num_names], &sid); - (*names)[*num_names] = talloc_asprintf(*names, "%s%c%s", - domain_name, - *lp_winbind_separator(), - name ); + (*names)[*num_names] = fill_domain_username_talloc( + *names, + domain_name, + name, + true); (*name_types)[*num_names] = name_type; (*num_names)++; @@ -1071,11 +1072,12 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, { sid_copy(&(*sid_mem)[*num_names], &sid_mem_nocache[i]); - (*names)[*num_names] = talloc_asprintf( *names, - "%s%c%s", - domains_nocache[i], - *lp_winbind_separator(), - names_nocache[i] ); + (*names)[*num_names] = + fill_domain_username_talloc( + *names, + domains_nocache[i], + names_nocache[i], + true); (*name_types)[*num_names] = name_types_nocache[i]; (*num_names)++; } diff --git a/source3/winbindd/winbindd_async.c b/source3/winbindd/winbindd_async.c index 1481aed8e1..7500bcbe5b 100644 --- a/source3/winbindd/winbindd_async.c +++ b/source3/winbindd/winbindd_async.c @@ -366,7 +366,7 @@ static void lookupname_recv(TALLOC_CTX *mem_ctx, bool success, /******************************************************************** The lookup name call first contacts a DC in its own domain - and fallbacks to contact a DC in the forest in our domain doesn't + and fallbacks to contact a DC if the forest in our domain doesn't know the name. ********************************************************************/ diff --git a/source3/winbindd/winbindd_group.c b/source3/winbindd/winbindd_group.c index 088f946877..f2b6fbefb5 100644 --- a/source3/winbindd/winbindd_group.c +++ b/source3/winbindd/winbindd_group.c @@ -35,7 +35,11 @@ static void add_member(const char *domain, const char *user, { fstring name; - fill_domain_username(name, domain, user, True); + if (domain != NULL) { + fill_domain_username(name, domain, user, True); + } else { + fstrcpy(name, user); + } safe_strcat(name, ",", sizeof(name)-1); string_append(pp_members, name); *p_num_members += 1; @@ -136,7 +140,7 @@ static void add_expanded_sid(const DOM_SID *sid, continue; } - add_member(domain->name, names[i], pp_members, p_num_members); + add_member(NULL, names[i], pp_members, p_num_members); } done: diff --git a/source3/winbindd/winbindd_pam.c b/source3/winbindd/winbindd_pam.c index d9104ca600..9ff3899661 100644 --- a/source3/winbindd/winbindd_pam.c +++ b/source3/winbindd/winbindd_pam.c @@ -127,7 +127,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, DATA_BLOB blob; enum ndr_err_code ndr_err; - ndr_err = ndr_push_struct_blob(&blob, mem_ctx, info3, + ndr_err = ndr_push_struct_blob(&blob, mem_ctx, NULL, info3, (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { DEBUG(0,("append_info3_as_ndr: failed to append\n")); diff --git a/source3/winbindd/winbindd_proto.h b/source3/winbindd/winbindd_proto.h index 4774bc8106..3836c46e36 100644 --- a/source3/winbindd/winbindd_proto.h +++ b/source3/winbindd/winbindd_proto.h @@ -569,6 +569,10 @@ bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser, void parse_add_domuser(void *buf, char *domuser, int *len); bool canonicalize_username(fstring username_inout, fstring domain, fstring user); void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume); +char *fill_domain_username_talloc(TALLOC_CTX *ctx, + const char *domain, + const char *user, + bool can_assume); const char *get_winbind_pipe_dir(void) ; char *get_winbind_priv_pipe_dir(void) ; int open_winbindd_socket(void); diff --git a/source3/winbindd/winbindd_rpc.c b/source3/winbindd/winbindd_rpc.c index df80ad8029..9fbea8e45b 100644 --- a/source3/winbindd/winbindd_rpc.c +++ b/source3/winbindd/winbindd_rpc.c @@ -854,7 +854,10 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain, } for (r=0; r<tmp_names.count; r++) { - (*names)[i+r] = CONST_DISCARD(char *, tmp_names.names[r].string); + (*names)[i+r] = fill_domain_username_talloc(mem_ctx, + domain->name, + tmp_names.names[r].string, + true); (*name_types)[i+r] = tmp_types.ids[r]; } diff --git a/source3/winbindd/winbindd_util.c b/source3/winbindd/winbindd_util.c index e7b6576317..5b5ca41a74 100644 --- a/source3/winbindd/winbindd_util.c +++ b/source3/winbindd/winbindd_util.c @@ -1160,7 +1160,7 @@ void parse_add_domuser(void *buf, char *domuser, int *len) } } - safe_strcpy(buf, user, *len); + safe_strcpy((char *)buf, user, *len); } /* Ensure an incoming username from NSS is fully qualified. Replace the @@ -1213,6 +1213,33 @@ void fill_domain_username(fstring name, const char *domain, const char *user, bo } } +/** + * talloc version of fill_domain_username() + * return NULL on talloc failure. + */ +char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx, + const char *domain, + const char *user, + bool can_assume) +{ + char *tmp_user, *name; + + tmp_user = talloc_strdup(mem_ctx, user); + strlower_m(tmp_user); + + if (can_assume && assume_domain(domain)) { + name = tmp_user; + } else { + name = talloc_asprintf(mem_ctx, "%s%c%s", + domain, + *lp_winbind_separator(), + tmp_user); + TALLOC_FREE(tmp_user); + } + + return name; +} + /* * Winbindd socket accessor functions */ diff --git a/source4/Makefile b/source4/Makefile index 7a5ec4c0d0..2a267c3e7b 100644 --- a/source4/Makefile +++ b/source4/Makefile @@ -13,7 +13,6 @@ pidldir := $(srcdir)/../pidl BASEDIR = $(prefix) TORTUREDIR = $(libdir)/torture SWATDIR = $(datadir)/swat -JSDIR = $(datadir)/js SETUPDIR = $(datadir)/setup NCALRPCDIR = $(localstatedir)/ncalrpc @@ -98,12 +97,12 @@ ntvfssrcdir := ntvfs ntptrsrcdir := ntptr librpcsrcdir := librpc libclisrcdir := libcli -ejsscriptsrcdir := scripting/ejs pyscriptsrcdir := $(srcdir)/scripting/python kdcsrcdir := kdc ntp_signdsrcdir := ntp_signd wmisrcdir := lib/wmi tallocsrcdir := ../lib/talloc +comsrcdir := $(srcdir)/lib/com include data.mk @@ -164,7 +163,6 @@ showlayout:: @echo ' lockdir: $(lockdir)' @echo ' logfilebase: $(logfilebase)' @echo ' setupdir: $(SETUPDIR)' - @echo ' jsdir: $(JSDIR)' @echo ' swatdir: $(SWATDIR)' @echo ' mandir: $(mandir)' @echo ' torturedir: $(TORTUREDIR)' @@ -234,7 +232,7 @@ installman:: manpages installdirs @$(SHELL) $(srcdir)/script/installman.sh $(DESTDIR)$(mandir) $(MANPAGES) installmisc:: installdirs - @$(SHELL) $(srcdir)/script/installmisc.sh $(srcdir) $(DESTDIR)$(JSDIR) $(DESTDIR)$(SETUPDIR) $(DESTDIR)$(bindir) + @$(SHELL) $(srcdir)/script/installmisc.sh $(srcdir) $(DESTDIR)$(SETUPDIR) $(DESTDIR)$(bindir) installpc:: installdirs @$(SHELL) $(srcdir)/script/installpc.sh $(builddir) $(DESTDIR)$(PKGCONFIGDIR) $(PC_FILES) diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c index 1334e799ae..e791226cf6 100644 --- a/source4/auth/gensec/gensec_gssapi.c +++ b/source4/auth/gensec/gensec_gssapi.c @@ -1181,6 +1181,10 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit OM_uint32 maj_stat, min_stat; krb5_keyblock *subkey; + if (gensec_gssapi_state->sasl_state != STAGE_DONE) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + if (gensec_gssapi_state->session_key.data) { *session_key = gensec_gssapi_state->session_key; return NT_STATUS_OK; @@ -1200,10 +1204,7 @@ static NTSTATUS gensec_gssapi_session_key(struct gensec_security *gensec_securit *session_key = data_blob_talloc(gensec_gssapi_state, KRB5_KEY_DATA(subkey), KRB5_KEY_LENGTH(subkey)); krb5_free_keyblock(gensec_gssapi_state->smb_krb5_context->krb5_context, subkey); - if (gensec_gssapi_state->sasl_state == STAGE_DONE) { - /* only cache in the done stage */ - gensec_gssapi_state->session_key = *session_key; - } + gensec_gssapi_state->session_key = *session_key; dump_data_pw("KRB5 Session Key:\n", session_key->data, session_key->length); return NT_STATUS_OK; diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c index 47df2ccfcc..1f54043038 100644 --- a/source4/auth/gensec/gensec_krb5.c +++ b/source4/auth/gensec/gensec_krb5.c @@ -515,6 +515,10 @@ static NTSTATUS gensec_krb5_session_key(struct gensec_security *gensec_security, krb5_keyblock *skey; krb5_error_code err = -1; + if (gensec_krb5_state->state_position != GENSEC_KRB5_DONE) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + if (gensec_krb5_state->session_key.data) { *session_key = gensec_krb5_state->session_key; return NT_STATUS_OK; diff --git a/source4/auth/ntlmssp/ntlmssp.c b/source4/auth/ntlmssp/ntlmssp.c index 0b7f0da9af..cea18c45a7 100644 --- a/source4/auth/ntlmssp/ntlmssp.c +++ b/source4/auth/ntlmssp/ntlmssp.c @@ -235,6 +235,10 @@ NTSTATUS gensec_ntlmssp_session_key(struct gensec_security *gensec_security, { struct gensec_ntlmssp_state *gensec_ntlmssp_state = (struct gensec_ntlmssp_state *)gensec_security->private_data; + if (gensec_ntlmssp_state->expected_state != NTLMSSP_DONE) { + return NT_STATUS_NO_USER_SESSION_KEY; + } + if (!gensec_ntlmssp_state->session_key.data) { return NT_STATUS_NO_USER_SESSION_KEY; } diff --git a/source4/configure.ac b/source4/configure.ac index a445dc62a6..fa2d8d9950 100644 --- a/source4/configure.ac +++ b/source4/configure.ac @@ -104,7 +104,6 @@ m4_include(../lib/nss_wrapper/config.m4) m4_include(auth/config.m4) m4_include(kdc/config.m4) m4_include(ntvfs/sysdep/config.m4) -m4_include(lib/appweb/config.m4) m4_include(nsswitch/config.m4) ################################################# diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py index 428e6b4d4b..2ca5b80c67 100644 --- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py +++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py @@ -1,7 +1,7 @@ #!/usr/bin/python # Unix SMB/CIFS implementation. -# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2005-2007 +# Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2005-2008 # Copyright (C) Martin Kuehl <mkhl@samba.org> 2006 # # This is a Python port of the original in testprogs/ejs/samba3sam.js @@ -23,19 +23,23 @@ """Tests for the samba3sam LDB module, which maps Samba3 LDAP to AD LDAP.""" import os -import sys -import samba import ldb from ldb import SCOPE_DEFAULT, SCOPE_BASE, SCOPE_SUBTREE from samba import Ldb, substitute_var from samba.tests import LdbTestCase, TestCaseInTempDir -datadir = os.path.join(os.path.dirname(__file__), "../../../../../testdata/samba3") +datadir = os.path.join(os.path.dirname(__file__), + "../../../../../testdata/samba3") + +def read_datafile(filename): + return open(os.path.join(datadir, filename), 'r').read() + +def ldb_debug(l, text): + print text + class MapBaseTestCase(TestCaseInTempDir): - def setup_data(self, obj, ldif): - self.assertTrue(ldif is not None) - obj.db.add_ldif(substitute_var(ldif, obj.substvars)) + """Base test case for mapping tests.""" def setup_modules(self, ldb, s3, s4): ldb.add({"dn": "@MAP=samba3sam", @@ -46,26 +50,27 @@ class MapBaseTestCase(TestCaseInTempDir): "@LIST": "rootdse,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition"}) ldb.add({"dn": "@PARTITION", - "partition": [s4.basedn + ":" + s4.url, s3.basedn + ":" + s3.url], + "partition": ["%s:%s" % (s4.basedn, s4.url), + "%s:%s" % (s3.basedn, s3.url)], "replicateEntries": ["@ATTRIBUTES", "@INDEXLIST"]}) def setUp(self): super(MapBaseTestCase, self).setUp() def make_dn(basedn, rdn): - return rdn + ",sambaDomainName=TESTS," + basedn + return "%s,sambaDomainName=TESTS,%s" % (rdn, basedn) def make_s4dn(basedn, rdn): - return rdn + "," + basedn + return "%s,%s" % (rdn, basedn) self.ldbfile = os.path.join(self.tempdir, "test.ldb") self.ldburl = "tdb://" + self.ldbfile tempdir = self.tempdir - print tempdir class Target: - """Simple helper class that contains data for a specific SAM connection.""" + """Simple helper class that contains data for a specific SAM + connection.""" def __init__(self, file, basedn, dn): self.file = os.path.join(tempdir, file) self.url = "tdb://" + self.file @@ -75,11 +80,23 @@ class MapBaseTestCase(TestCaseInTempDir): self._dn = dn def dn(self, rdn): - return self._dn(rdn, self.basedn) + return self._dn(self.basedn, rdn) def connect(self): return self.db.connect(self.url) + def setup_data(self, path): + self.add_ldif(read_datafile(path)) + + def subst(self, text): + return substitute_var(text, self.substvars) + + def add_ldif(self, ldif): + self.db.add_ldif(self.subst(ldif)) + + def modify_ldif(self, ldif): + self.db.modify_ldif(self.subst(ldif)) + self.samba4 = Target("samba4.ldb", "dc=vernstok,dc=nl", make_s4dn) self.samba3 = Target("samba3.ldb", "cn=Samba3Sam", make_dn) self.templates = Target("templates.ldb", "cn=templates", None) @@ -97,54 +114,58 @@ class MapBaseTestCase(TestCaseInTempDir): class Samba3SamTestCase(MapBaseTestCase): + def setUp(self): super(Samba3SamTestCase, self).setUp() ldb = Ldb(self.ldburl) - self.setup_data(self.samba3, open(os.path.join(datadir, "samba3.ldif"), 'r').read()) - self.setup_data(self.templates, open(os.path.join(datadir, "provision_samba3sam_templates.ldif"), 'r').read()) - ldif = open(os.path.join(datadir, "provision_samba3sam.ldif"), 'r').read() - ldb.add_ldif(substitute_var(ldif, self.samba4.substvars)) + self.samba3.setup_data("samba3.ldif") + self.templates.setup_data("provision_samba3sam_templates.ldif") + ldif = read_datafile("provision_samba3sam.ldif") + ldb.add_ldif(self.samba4.subst(ldif)) self.setup_modules(ldb, self.samba3, self.samba4) + del ldb self.ldb = Ldb(self.ldburl) - def test_s3sam_search(self): - print "Looking up by non-mapped attribute" + def test_search_non_mapped(self): + """Looking up by non-mapped attribute""" msg = self.ldb.search(expression="(cn=Administrator)") self.assertEquals(len(msg), 1) self.assertEquals(msg[0]["cn"], "Administrator") - print "Looking up by mapped attribute" + def test_search_non_mapped(self): + """Looking up by mapped attribute""" msg = self.ldb.search(expression="(name=Backup Operators)") self.assertEquals(len(msg), 1) self.assertEquals(msg[0]["name"], "Backup Operators") - print "Looking up by old name of renamed attribute" + def test_old_name_of_renamed(self): + """Looking up by old name of renamed attribute""" msg = self.ldb.search(expression="(displayName=Backup Operators)") self.assertEquals(len(msg), 0) - print "Looking up mapped entry containing SID" + def test_mapped_containing_sid(self): + """Looking up mapped entry containing SID""" msg = self.ldb.search(expression="(cn=Replicator)") self.assertEquals(len(msg), 1) - print msg[0].dn - self.assertEquals(str(msg[0].dn), "cn=Replicator,ou=Groups,dc=vernstok,dc=nl") - self.assertEquals(msg[0]["objectSid"], "S-1-5-21-4231626423-2410014848-2360679739-552") - - print "Checking mapping of objectClass" + self.assertEquals(str(msg[0].dn), + "cn=Replicator,ou=Groups,dc=vernstok,dc=nl") + self.assertTrue("objectSid" in msg[0]) + # FIXME: NDR unpack msg[0]["objectSid"] before comparing: + # self.assertEquals(msg[0]["objectSid"], + # "S-1-5-21-4231626423-2410014848-2360679739-552") + # Check mapping of objectClass oc = set(msg[0]["objectClass"]) - self.assertTrue(oc is not None) - for i in oc: - self.assertEquals(oc[i] == "posixGroup" or oc[i], "group") + self.assertEquals(oc, set(["group"])) - print "Looking up by objectClass" + def test_search_by_objclass(self): + """Looking up by objectClass""" msg = self.ldb.search(expression="(|(objectClass=user)(cn=Administrator))") - self.assertEquals(len(msg), 2) - for i in range(len(msg)): - self.assertEquals((str(msg[i].dn), "unixName=Administrator,ou=Users,dc=vernstok,dc=nl") or - (str(msg[i].dn) == "unixName=nobody,ou=Users,dc=vernstok,dc=nl")) - + self.assertEquals(set([str(m.dn) for m in msg]), + set(["unixName=Administrator,ou=Users,dc=vernstok,dc=nl", + "unixName=nobody,ou=Users,dc=vernstok,dc=nl"])) def test_s3sam_modify(self): - print "Adding a record that will be fallbacked" + # Adding a record that will be fallbacked self.ldb.add({"dn": "cn=Foo", "foo": "bar", "blah": "Blie", @@ -152,33 +173,36 @@ class Samba3SamTestCase(MapBaseTestCase): "showInAdvancedViewOnly": "TRUE"} ) - print "Checking for existence of record (local)" - # TODO: This record must be searched in the local database, which is currently only supported for base searches + # Checking for existence of record (local) + # TODO: This record must be searched in the local database, which is + # currently only supported for base searches # msg = ldb.search(expression="(cn=Foo)", ['foo','blah','cn','showInAdvancedViewOnly')] # TODO: Actually, this version should work as well but doesn't... # # - msg = self.ldb.search(expression="(cn=Foo)", base="cn=Foo", scope=SCOPE_BASE, attrs=['foo','blah','cn','showInAdvancedViewOnly']) + msg = self.ldb.search(expression="(cn=Foo)", base="cn=Foo", + scope=SCOPE_BASE, + attrs=['foo','blah','cn','showInAdvancedViewOnly']) self.assertEquals(len(msg), 1) self.assertEquals(msg[0]["showInAdvancedViewOnly"], "TRUE") self.assertEquals(msg[0]["foo"], "bar") self.assertEquals(msg[0]["blah"], "Blie") - print "Adding record that will be mapped" + # Adding record that will be mapped self.ldb.add({"dn": "cn=Niemand,cn=Users,dc=vernstok,dc=nl", "objectClass": "user", "unixName": "bin", "sambaUnicodePwd": "geheim", "cn": "Niemand"}) - print "Checking for existence of record (remote)" + # Checking for existence of record (remote) msg = self.ldb.search(expression="(unixName=bin)", attrs=['unixName','cn','dn', 'sambaUnicodePwd']) self.assertEquals(len(msg), 1) self.assertEquals(msg[0]["cn"], "Niemand") self.assertEquals(msg[0]["sambaUnicodePwd"], "geheim") - print "Checking for existence of record (local && remote)" + # Checking for existence of record (local && remote) msg = self.ldb.search(expression="(&(unixName=bin)(sambaUnicodePwd=geheim))", attrs=['unixName','cn','dn', 'sambaUnicodePwd']) self.assertEquals(len(msg), 1) # TODO: should check with more records @@ -186,21 +210,23 @@ class Samba3SamTestCase(MapBaseTestCase): self.assertEquals(msg[0]["unixName"], "bin") self.assertEquals(msg[0]["sambaUnicodePwd"], "geheim") - print "Checking for existence of record (local || remote)" + # Checking for existence of record (local || remote) msg = self.ldb.search(expression="(|(unixName=bin)(sambaUnicodePwd=geheim))", attrs=['unixName','cn','dn', 'sambaUnicodePwd']) - print "got " + len(msg) + " replies" + #print "got %d replies" % len(msg) self.assertEquals(len(msg), 1) # TODO: should check with more records self.assertEquals(msg[0]["cn"], "Niemand") - self.assertEquals(msg[0]["unixName"] == "bin" or msg[0]["sambaUnicodePwd"], "geheim") + self.assertEquals(msg[0]["unixName"], "bin") + self.assertEquals(msg[0]["sambaUnicodePwd"], "geheim") - print "Checking for data in destination database" - msg = s3.db.search("(cn=Niemand)") + # Checking for data in destination database + msg = self.samba3.db.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) - self.assertEquals(msg[0]["sambaSID"], "S-1-5-21-4231626423-2410014848-2360679739-2001") + self.assertEquals(msg[0]["sambaSID"], + "S-1-5-21-4231626423-2410014848-2360679739-2001") self.assertEquals(msg[0]["displayName"], "Niemand") - print "Adding attribute..." + # Adding attribute... self.ldb.modify_ldif(""" dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl changetype: modify @@ -208,13 +234,13 @@ add: description description: Blah """) - print "Checking whether changes are still there..." + # Checking whether changes are still there... msg = self.ldb.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) self.assertEquals(msg[0]["cn"], "Niemand") self.assertEquals(msg[0]["description"], "Blah") - print "Modifying attribute..." + # Modifying attribute... self.ldb.modify_ldif(""" dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl changetype: modify @@ -222,64 +248,66 @@ replace: description description: Blie """) - print "Checking whether changes are still there..." + # Checking whether changes are still there... msg = self.ldb.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) self.assertEquals(msg[0]["description"], "Blie") - print "Deleting attribute..." + # Deleting attribute... self.ldb.modify_ldif(""" dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl changetype: modify delete: description """) - print "Checking whether changes are no longer there..." + # Checking whether changes are no longer there... msg = self.ldb.search(expression="(cn=Niemand)") self.assertTrue(len(msg) >= 1) - self.assertTrue(not "description" in res[0]) + self.assertTrue(not "description" in msg[0]) - print "Renaming record..." - self.ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", "cn=Niemand2,cn=Users,dc=vernstok,dc=nl") + # Renaming record... + self.ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", + "cn=Niemand2,cn=Users,dc=vernstok,dc=nl") - print "Checking whether DN has changed..." + # Checking whether DN has changed... msg = self.ldb.search(expression="(cn=Niemand2)") self.assertEquals(len(msg), 1) - self.assertEquals(str(msg[0].dn), "cn=Niemand2,cn=Users,dc=vernstok,dc=nl") + self.assertEquals(str(msg[0].dn), + "cn=Niemand2,cn=Users,dc=vernstok,dc=nl") - print "Deleting record..." + # Deleting record... self.ldb.delete("cn=Niemand2,cn=Users,dc=vernstok,dc=nl") - print "Checking whether record is gone..." + # Checking whether record is gone... msg = self.ldb.search(expression="(cn=Niemand2)") self.assertEquals(len(msg), 0) - class MapTestCase(MapBaseTestCase): + def setUp(self): super(MapTestCase, self).setUp() ldb = Ldb(self.ldburl) - self.setup_data(self.templates, open(os.path.join(datadir, "provision_samba3sam_templates.ldif"), 'r').read()) - ldif = open(os.path.join(datadir, "provision_samba3sam.ldif"), 'r').read() - ldb.add_ldif(substitute_var(ldif, self.samba4.substvars)) + self.templates.setup_data("provision_samba3sam_templates.ldif") + ldif = read_datafile("provision_samba3sam.ldif") + ldb.add_ldif(self.samba4.subst(ldif)) self.setup_modules(ldb, self.samba3, self.samba4) + del ldb self.ldb = Ldb(self.ldburl) def test_map_search(self): - print "Running search tests on mapped data" - ldif = """ -dn: """ + "sambaDomainName=TESTS,""" + self.samba3.basedn + """ -objectclass: sambaDomain -objectclass: top -sambaSID: S-1-5-21-4231626423-2410014848-2360679739 -sambaNextRid: 2000 -sambaDomainName: TESTS""" - self.samba3.db.add_ldif(substitute_var(ldif, self.samba3.substvars)) - - print "Add a set of split records" - ldif = """ -dn: """ + self.samba4.dn("cn=X") + """ + """Running search tests on mapped data.""" + self.samba3.db.add({ + "dn": "sambaDomainName=TESTS," + self.samba3.basedn, + "objectclass": ["sambaDomain", "top"], + "sambaSID": "S-1-5-21-4231626423-2410014848-2360679739", + "sambaNextRid": "2000", + "sambaDomainName": "TESTS" + }) + + # Add a set of split records + self.ldb.add_ldif(""" +dn: """+ self.samba4.dn("cn=X") + """ objectClass: user cn: X codePage: x @@ -291,127 +319,128 @@ description: x objectSid: S-1-5-21-4231626423-2410014848-2360679739-552 primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512 -dn: """ + self.samba4.dn("cn=Y") + """ -objectClass: top -cn: Y -codePage: x -revision: x -dnsHostName: y -nextRid: y -lastLogon: y -description: x - -dn: """ + self.samba4.dn("cn=Z") + """ -objectClass: top -cn: Z -codePage: x -revision: y -dnsHostName: z -nextRid: y -lastLogon: z -description: y -""" - - self.ldb.add_ldif(substitute_var(ldif, self.samba4.substvars)) - - print "Add a set of remote records" - - ldif = """ -dn: """ + self.samba3.dn("cn=A") + """ -objectClass: posixAccount -cn: A -sambaNextRid: x -sambaBadPasswordCount: x -sambaLogonTime: x -description: x -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 -sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 - -dn: """ + self.samba3.dn("cn=B") + """ -objectClass: top -cn:B -sambaNextRid: x -sambaBadPasswordCount: x -sambaLogonTime: y -description: x +""") -dn: """ + self.samba3.dn("cn=C") + """ -objectClass: top -cn: C -sambaNextRid: x -sambaBadPasswordCount: y -sambaLogonTime: z -description: y -""" - self.samba3.add_ldif(substitute_var(ldif, self.samba3.substvars)) + self.ldb.add({ + "dn": self.samba4.dn("cn=Y"), + "objectClass": "top", + "cn": "Y", + "codePage": "x", + "revision": "x", + "dnsHostName": "y", + "nextRid": "y", + "lastLogon": "y", + "description": "x"}) - print "Testing search by DN" + self.ldb.add({ + "dn": self.samba4.dn("cn=Z"), + "objectClass": "top", + "cn": "Z", + "codePage": "x", + "revision": "y", + "dnsHostName": "z", + "nextRid": "y", + "lastLogon": "z", + "description": "y"}) + + # Add a set of remote records + + self.samba3.db.add({ + "dn": self.samba3.dn("cn=A"), + "objectClass": "posixAccount", + "cn": "A", + "sambaNextRid": "x", + "sambaBadPasswordCount": "x", + "sambaLogonTime": "x", + "description": "x", + "sambaSID": "S-1-5-21-4231626423-2410014848-2360679739-552", + "sambaPrimaryGroupSID": "S-1-5-21-4231626423-2410014848-2360679739-512"}) + + self.samba3.db.add({ + "dn": self.samba3.dn("cn=B"), + "objectClass": "top", + "cn": "B", + "sambaNextRid": "x", + "sambaBadPasswordCount": "x", + "sambaLogonTime": "y", + "description": "x"}) + + self.samba3.db.add({ + "dn": self.samba3.dn("cn=C"), + "objectClass": "top", + "cn": "C", + "sambaNextRid": "x", + "sambaBadPasswordCount": "y", + "sambaLogonTime": "z", + "description": "y"}) + + # Testing search by DN # Search remote record by local DN dn = self.samba4.dn("cn=A") - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 1) - self.assertEquals(str(str(res[0].dn)), dn) + self.assertEquals(str(res[0].dn), dn) self.assertTrue(not "dnsHostName" in res[0]) self.assertEquals(res[0]["lastLogon"], "x") # Search remote record by remote DN dn = self.samba3.dn("cn=A") - attrs = ["dnsHostName", "lastLogon", "sambaLogonTime"] - res = self.samba3.db.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn, scope=SCOPE_BASE, + attrs=["dnsHostName", "lastLogon", "sambaLogonTime"]) self.assertEquals(len(res), 1) - self.assertEquals(str(str(res[0].dn)), dn) + self.assertEquals(str(res[0].dn), dn) self.assertTrue(not "dnsHostName" in res[0]) self.assertTrue(not "lastLogon" in res[0]) self.assertEquals(res[0]["sambaLogonTime"], "x") # Search split record by local DN dn = self.samba4.dn("cn=X") - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 1) - self.assertEquals(str(str(res[0].dn)), dn) + self.assertEquals(str(res[0].dn), dn) self.assertEquals(res[0]["dnsHostName"], "x") self.assertEquals(res[0]["lastLogon"], "x") # Search split record by remote DN dn = self.samba3.dn("cn=X") - attrs = ["dnsHostName", "lastLogon", "sambaLogonTime"] - res = self.samba3.db.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn, scope=SCOPE_BASE, + attrs=["dnsHostName", "lastLogon", "sambaLogonTime"]) self.assertEquals(len(res), 1) - self.assertEquals(str(str(res[0].dn)), dn) + self.assertEquals(str(res[0].dn), dn) self.assertTrue(not "dnsHostName" in res[0]) self.assertTrue(not "lastLogon" in res[0]) self.assertEquals(res[0]["sambaLogonTime"], "x") - print "Testing search by attribute" + # Testing search by attribute # Search by ignored attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(revision=x)", scope=SCOPE_DEFAULT, attrs=attrs) + res = self.ldb.search(expression="(revision=x)", scope=SCOPE_DEFAULT, + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) - self.assertEquals(str(str(res[0].dn)), self.samba4.dn("cn=Y")) + self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") self.assertEquals(res[0]["lastLogon"], "y") - self.assertEquals(str(str(res[1].dn)), self.samba4.dn("cn=X")) + self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) self.assertEquals(res[1]["dnsHostName"], "x") self.assertEquals(res[1]["lastLogon"], "x") # Search by kept attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(description=y)", scope=SCOPE_DEFAULT, attrs=attrs) + res = self.ldb.search(expression="(description=y)", + scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) - self.assertEquals(str(str(res[0].dn)), self.samba4.dn("cn=Z")) + self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Z")) self.assertEquals(res[0]["dnsHostName"], "z") self.assertEquals(res[0]["lastLogon"], "z") - self.assertEquals(str(str(res[1].dn)), self.samba4.dn("cn=C")) + self.assertEquals(str(res[1].dn), self.samba4.dn("cn=C")) self.assertTrue(not "dnsHostName" in res[1]) self.assertEquals(res[1]["lastLogon"], "z") # Search by renamed attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(badPwdCount=x)", scope=SCOPE_DEFAULT, attrs=attrs) + res = self.ldb.search(expression="(badPwdCount=x)", scope=SCOPE_DEFAULT, + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) @@ -421,27 +450,33 @@ description: y self.assertEquals(res[1]["lastLogon"], "x") # Search by converted attribute - attrs = ["dnsHostName", "lastLogon", "objectSid"] # TODO: # Using the SID directly in the parse tree leads to conversion # errors, letting the search fail with no results. #res = self.ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", scope=SCOPE_DEFAULT, attrs) - res = self.ldb.search(expression="(objectSid=*)", attrs=attrs) + res = self.ldb.search(expression="(objectSid=*)", base=None, scope=SCOPE_DEFAULT, attrs=["dnsHostName", "lastLogon", "objectSid"]) self.assertEquals(len(res), 3) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) self.assertEquals(res[0]["dnsHostName"], "x") self.assertEquals(res[0]["lastLogon"], "x") - self.assertEquals(res[0]["objectSid"], "S-1-5-21-4231626423-2410014848-2360679739-552") + # FIXME:Properly compare sid,requires converting between NDR encoding + # and string + #self.assertEquals(res[0]["objectSid"], + # "S-1-5-21-4231626423-2410014848-2360679739-552") + self.assertTrue("objectSid" in res[0]) self.assertEquals(str(res[1].dn), self.samba4.dn("cn=A")) self.assertTrue(not "dnsHostName" in res[1]) self.assertEquals(res[1]["lastLogon"], "x") - self.assertEquals(res[1]["objectSid"], "S-1-5-21-4231626423-2410014848-2360679739-552") + # FIXME: Properly compare sid,see above + #self.assertEquals(res[1]["objectSid"], + # "S-1-5-21-4231626423-2410014848-2360679739-552") + self.assertTrue("objectSid" in res[1]) # Search by generated attribute # In most cases, this even works when the mapping is missing # a `convert_operator' by enumerating the remote db. - attrs = ["dnsHostName", "lastLogon", "primaryGroupID"] - res = self.ldb.search(expression="(primaryGroupID=512)", attrs=attrs) + res = self.ldb.search(expression="(primaryGroupID=512)", + attrs=["dnsHostName", "lastLogon", "primaryGroupID"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue(not "dnsHostName" in res[0]) @@ -463,8 +498,8 @@ description: y # # Search by remote name of renamed attribute */ - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(sambaBadPasswordCount=*)", attrs=attrs) + res = self.ldb.search(expression="(sambaBadPasswordCount=*)", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 0) # Search by objectClass @@ -474,39 +509,34 @@ description: y self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) self.assertEquals(res[0]["dnsHostName"], "x") self.assertEquals(res[0]["lastLogon"], "x") - self.assertTrue(res[0]["objectClass"] is not None) self.assertEquals(res[0]["objectClass"][0], "user") self.assertEquals(str(res[1].dn), self.samba4.dn("cn=A")) self.assertTrue(not "dnsHostName" in res[1]) self.assertEquals(res[1]["lastLogon"], "x") - self.assertTrue(res[1]["objectClass"] is not None) self.assertEquals(res[1]["objectClass"][0], "user") # Prove that the objectClass is actually used for the search - res = self.ldb.search(expression="(|(objectClass=user)(badPwdCount=x))", attrs=attrs) + res = self.ldb.search(expression="(|(objectClass=user)(badPwdCount=x))", + attrs=attrs) self.assertEquals(len(res), 3) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) self.assertEquals(res[0]["lastLogon"], "y") - self.assertTrue(res[0]["objectClass"] is not None) - for oc in set(res[0]["objectClass"]): - self.assertEquals(oc, "user") + self.assertEquals(set(res[0]["objectClass"]), set(["top"])) self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) self.assertEquals(res[1]["dnsHostName"], "x") self.assertEquals(res[1]["lastLogon"], "x") - self.assertTrue(res[1]["objectClass"] is not None) self.assertEquals(res[1]["objectClass"][0], "user") self.assertEquals(str(res[2].dn), self.samba4.dn("cn=A")) self.assertTrue(not "dnsHostName" in res[2]) self.assertEquals(res[2]["lastLogon"], "x") - self.assertTrue(res[2]["objectClass"] is not None) self.assertEquals(res[2]["objectClass"][0], "user") - print "Testing search by parse tree" + # Testing search by parse tree # Search by conjunction of local attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(&(codePage=x)(revision=x))", attrs=attrs) + res = self.ldb.search(expression="(&(codePage=x)(revision=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") @@ -516,8 +546,8 @@ description: y self.assertEquals(res[1]["lastLogon"], "x") # Search by conjunction of remote attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(&(lastLogon=x)(description=x))", attrs=attrs) + res = self.ldb.search(expression="(&(lastLogon=x)(description=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=X")) self.assertEquals(res[0]["dnsHostName"], "x") @@ -527,8 +557,8 @@ description: y self.assertEquals(res[1]["lastLogon"], "x") # Search by conjunction of local and remote attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(&(codePage=x)(description=x))", attrs=attrs) + res = self.ldb.search(expression="(&(codePage=x)(description=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") @@ -539,14 +569,16 @@ description: y # Search by conjunction of local and remote attribute w/o match attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(&(codePage=x)(nextRid=x))", attrs=attrs) + res = self.ldb.search(expression="(&(codePage=x)(nextRid=x))", + attrs=attrs) self.assertEquals(len(res), 0) - res = self.ldb.search(expression="(&(revision=x)(lastLogon=z))", attrs=attrs) + res = self.ldb.search(expression="(&(revision=x)(lastLogon=z))", + attrs=attrs) self.assertEquals(len(res), 0) # Search by disjunction of local attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(|(revision=x)(dnsHostName=x))", attrs=attrs) + res = self.ldb.search(expression="(|(revision=x)(dnsHostName=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 2) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") @@ -556,41 +588,41 @@ description: y self.assertEquals(res[1]["lastLogon"], "x") # Search by disjunction of remote attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(|(badPwdCount=x)(lastLogon=x))", attrs=attrs) + res = self.ldb.search(expression="(|(badPwdCount=x)(lastLogon=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 3) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) - self.assertTrue("dnsHostName" in res[0]) + self.assertFalse("dnsHostName" in res[0]) self.assertEquals(res[0]["lastLogon"], "y") self.assertEquals(str(res[1].dn), self.samba4.dn("cn=X")) self.assertEquals(res[1]["dnsHostName"], "x") self.assertEquals(res[1]["lastLogon"], "x") self.assertEquals(str(res[2].dn), self.samba4.dn("cn=A")) - self.assertTrue("dnsHostName" in res[2]) + self.assertFalse("dnsHostName" in res[2]) self.assertEquals(res[2]["lastLogon"], "x") # Search by disjunction of local and remote attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(|(revision=x)(lastLogon=y))", attrs=attrs) + res = self.ldb.search(expression="(|(revision=x)(lastLogon=y))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 3) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") self.assertEquals(res[0]["lastLogon"], "y") self.assertEquals(str(res[1].dn), self.samba4.dn("cn=B")) - self.assertTrue("dnsHostName" in res[1]) + self.assertFalse("dnsHostName" in res[1]) self.assertEquals(res[1]["lastLogon"], "y") self.assertEquals(str(res[2].dn), self.samba4.dn("cn=X")) self.assertEquals(res[2]["dnsHostName"], "x") self.assertEquals(res[2]["lastLogon"], "x") # Search by disjunction of local and remote attribute w/o match - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(|(codePage=y)(nextRid=z))", attrs=attrs) + res = self.ldb.search(expression="(|(codePage=y)(nextRid=z))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 0) # Search by negated local attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(revision=x))", attrs=attrs) + res = self.ldb.search(expression="(!(revision=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 5) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) @@ -606,8 +638,8 @@ description: y self.assertEquals(res[3]["lastLogon"], "z") # Search by negated remote attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(description=x))", attrs=attrs) + res = self.ldb.search(expression="(!(description=x))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 3) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Z")) self.assertEquals(res[0]["dnsHostName"], "z") @@ -617,8 +649,8 @@ description: y self.assertEquals(res[1]["lastLogon"], "z") # Search by negated conjunction of local attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))", attrs=attrs) + res = self.ldb.search(expression="(!(&(codePage=x)(revision=x)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 5) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) @@ -634,8 +666,8 @@ description: y self.assertEquals(res[3]["lastLogon"], "z") # Search by negated conjunction of remote attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))", attrs=attrs) + res = self.ldb.search(expression="(!(&(lastLogon=x)(description=x)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 5) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") @@ -651,8 +683,8 @@ description: y self.assertEquals(res[3]["lastLogon"], "z") # Search by negated conjunction of local and remote attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))", attrs=attrs) + res = self.ldb.search(expression="(!(&(codePage=x)(description=x)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 5) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) @@ -668,8 +700,8 @@ description: y self.assertEquals(res[3]["lastLogon"], "z") # Search by negated disjunction of local attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(|(revision=x)(dnsHostName=x)))", attrs=attrs) + res = self.ldb.search(expression="(!(|(revision=x)(dnsHostName=x)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) self.assertEquals(res[0]["lastLogon"], "y") @@ -684,8 +716,8 @@ description: y self.assertEquals(res[3]["lastLogon"], "z") # Search by negated disjunction of remote attributes - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))", attrs=attrs) + res = self.ldb.search(expression="(!(|(badPwdCount=x)(lastLogon=x)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 4) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=Y")) self.assertEquals(res[0]["dnsHostName"], "y") @@ -698,8 +730,8 @@ description: y self.assertEquals(res[2]["lastLogon"], "z") # Search by negated disjunction of local and remote attribute - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))", attrs=attrs) + res = self.ldb.search(expression="(!(|(revision=x)(lastLogon=y)))", + attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 4) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=A")) self.assertTrue(not "dnsHostName" in res[0]) @@ -711,9 +743,8 @@ description: y self.assertTrue(not "dnsHostName" in res[2]) self.assertEquals(res[2]["lastLogon"], "z") - print "Search by complex parse tree" - attrs = ["dnsHostName", "lastLogon"] - res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=attrs) + # Search by complex parse tree + res = self.ldb.search(expression="(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", attrs=["dnsHostName", "lastLogon"]) self.assertEquals(len(res), 6) self.assertEquals(str(res[0].dn), self.samba4.dn("cn=B")) self.assertTrue(not "dnsHostName" in res[0]) @@ -754,10 +785,12 @@ description: y self.assertEquals(res[0]["revision"], "1") self.assertEquals(res[0]["description"], "test") # Check it's not in the local db - res = self.samba4.db.search(expression="(cn=test)", scope=SCOPE_DEFAULT, attrs=attrs) + res = self.samba4.db.search(expression="(cn=test)", + scope=SCOPE_DEFAULT, attrs=attrs) self.assertEquals(len(res), 0) # Check it's not in the remote db - res = self.samba3.db.search(expression="(cn=test)", scope=SCOPE_DEFAULT, attrs=attrs) + res = self.samba3.db.search(expression="(cn=test)", + scope=SCOPE_DEFAULT, attrs=attrs) self.assertEquals(len(res), 0) # Modify local record @@ -805,8 +838,8 @@ description: foo "sambaBadPasswordCount": "3", "sambaNextRid": "1001"}) # Check it's there - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid"] - res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn2, scope=SCOPE_BASE, + attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) self.assertEquals(res[0]["description"], "foo") @@ -814,7 +847,7 @@ description: foo self.assertEquals(res[0]["sambaNextRid"], "1001") # Check in mapped db attrs = ["description", "badPwdCount", "nextRid"] - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs, expression="") self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn) self.assertEquals(res[0]["description"], "foo") @@ -834,16 +867,16 @@ badPwdCount: 4 """ self.ldb.modify_ldif(ldif) # Check in mapped db - attrs = ["description", "badPwdCount", "nextRid"] - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, + attrs=["description", "badPwdCount", "nextRid"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn) self.assertEquals(res[0]["description"], "test") self.assertEquals(res[0]["badPwdCount"], "4") self.assertEquals(res[0]["nextRid"], "1001") # Check in remote db - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid"] - res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn2, scope=SCOPE_BASE, + attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) self.assertEquals(res[0]["description"], "test") @@ -855,8 +888,8 @@ badPwdCount: 4 self.ldb.rename(dn, dn2) # Check in mapped db dn = dn2 - attrs = ["description", "badPwdCount", "nextRid"] - res = self.ldb.search(dn, scope=SCOPE_BASE, attrs=attrs) + res = self.ldb.search(dn, scope=SCOPE_BASE, + attrs=["description", "badPwdCount", "nextRid"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn) self.assertEquals(res[0]["description"], "test") @@ -864,8 +897,8 @@ badPwdCount: 4 self.assertEquals(res[0]["nextRid"], "1001") # Check in remote db dn2 = self.samba3.dn("cn=toast") - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid"] - res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn2, scope=SCOPE_BASE, + attrs=["description", "sambaBadPasswordCount", "sambaNextRid"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) self.assertEquals(res[0]["description"], "test") @@ -874,7 +907,7 @@ badPwdCount: 4 # Delete remote record self.ldb.delete(dn) - # Check in mapped db + # Check in mapped db that it's removed res = self.ldb.search(dn, scope=SCOPE_BASE) self.assertEquals(len(res), 0) # Check in remote db @@ -899,6 +932,7 @@ add: revision revision: 1 replace: description description: test + """ self.ldb.modify_ldif(ldif) # Check in mapped db @@ -954,7 +988,8 @@ description: test self.assertTrue(not "nextRid" in res[0]) self.assertEquals(res[0]["revision"], "1") # Check in remote db - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", "revision"] + attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", + "revision"] res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) @@ -992,7 +1027,8 @@ revision: 2 self.assertTrue(not "nextRid" in res[0]) self.assertEquals(res[0]["revision"], "2") # Check in remote db - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", "revision"] + attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", + "revision"] res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) @@ -1024,8 +1060,9 @@ revision: 2 self.assertEquals(res[0]["revision"], "2") # Check in remote db dn2 = self.samba3.dn("cn=toast") - attrs = ["description", "sambaBadPasswordCount", "sambaNextRid", "revision"] - res = self.samba3.db.search(dn2, scope=SCOPE_BASE, attrs=attrs) + res = self.samba3.db.search(dn2, scope=SCOPE_BASE, + attrs=["description", "sambaBadPasswordCount", "sambaNextRid", + "revision"]) self.assertEquals(len(res), 1) self.assertEquals(str(res[0].dn), dn2) self.assertEquals(res[0]["description"], "test") diff --git a/source4/kdc/kdc.c b/source4/kdc/kdc.c index b7009b030f..030eb23c10 100644 --- a/source4/kdc/kdc.c +++ b/source4/kdc/kdc.c @@ -484,7 +484,7 @@ static NTSTATUS kdc_add_socket(struct kdc_server *kdc, const char *address, /* within the kdc task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(kdc->task->event_ctx, "single"); if (!model_ops) { DEBUG(0,("Can't find 'single' process model_ops\n")); talloc_free(kdc_socket); @@ -584,13 +584,11 @@ static NTSTATUS kdc_check_generic_kerberos(struct irpc_message *msg, return NT_STATUS_INVALID_PARAMETER; } -#if 0 - /* Windows does not check this */ if (pac_validate.MessageType != 3) { /* We don't implement any other message types - such as certificate validation - yet */ return NT_STATUS_INVALID_PARAMETER; } -#endif + if (pac_validate.ChecksumAndSignature.length != (pac_validate.ChecksumLength + pac_validate.SignatureLength) || pac_validate.ChecksumAndSignature.length < pac_validate.ChecksumLength || pac_validate.ChecksumAndSignature.length < pac_validate.SignatureLength ) { diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 39a55f4420..57a63a8516 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -529,7 +529,7 @@ static void ldapsrv_task_init(struct task_server *task) task_server_set_title(task, "task[ldapsrv]"); /* run the ldap server as a single process */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) goto failed; ldap_service = talloc_zero(task, struct ldapsrv_service); diff --git a/source4/lib/appweb/README b/source4/lib/appweb/README deleted file mode 100644 index bdc943446b..0000000000 --- a/source4/lib/appweb/README +++ /dev/null @@ -1,6 +0,0 @@ -The lib/appweb directory is a partial import of the appweb ejs and esp -code from http://www.appwebserver.org/ - -Many thanks to the mbedthis people, and especially Michael O'Brien for -his assistance in getting this code integrated into Samba4. - diff --git a/source4/lib/appweb/config.m4 b/source4/lib/appweb/config.m4 deleted file mode 100644 index 69b4048c4a..0000000000 --- a/source4/lib/appweb/config.m4 +++ /dev/null @@ -1 +0,0 @@ -AC_CHECK_HEADERS(math.h) diff --git a/source4/lib/appweb/config.mk b/source4/lib/appweb/config.mk deleted file mode 100644 index 4d27b69fb5..0000000000 --- a/source4/lib/appweb/config.mk +++ /dev/null @@ -1,25 +0,0 @@ -####################### -# Start SUBSYSTEM MPR -[SUBSYSTEM::MPR] -# End SUBSYSTEM MPR -####################### - -MPR_OBJ_FILES = $(addprefix $(appwebsrcdir)/mpr/, miniMpr.o var.o) - -####################### -# Start SUBSYSTEM EJS -[SUBSYSTEM::EJS] -PUBLIC_DEPENDENCIES = MPR -# End SUBSYSTEM EJS -####################### - -EJS_OBJ_FILES = $(addprefix $(appwebsrcdir)/ejs/, ejsLib.o ejsLex.o ejsParser.o ejsProcs.o) - -####################### -# Start SUBSYSTEM ESP -[SUBSYSTEM::ESP] -PUBLIC_DEPENDENCIES = EJS -# End SUBSYSTEM ESP -####################### - -ESP_OBJ_FILES = $(addprefix $(appwebsrcdir)/esp/, esp.o espProcs.o) diff --git a/source4/lib/appweb/ejs-2.0/.bashrc b/source4/lib/appweb/ejs-2.0/.bashrc deleted file mode 100644 index c05ee0e6e8..0000000000 --- a/source4/lib/appweb/ejs-2.0/.bashrc +++ /dev/null @@ -1,153 +0,0 @@ -# -# .bashrc -- Login shell startup script for windows using Mbedthis winTools -# -# Copyright (c) Mbedthis Software, 2003-2005. All Rights Reserved. -# - -TERM=ansi -# -# Set the desired .NET Framework -# -# FRAMEWORK=v1.0.3705 -FRAMEWORK=v1.1.4322 -# FRAMEWORK=v2.0.40607 - -# -# Set the desired Microsoft C Compiler version -# -# PREFERRED_CC=VS2005 -# PREFERRED_CC=VS2003 -# PREFERRED_CC=VS.NET -PREFERRED_CC=VS6 - -# -# Set to 1 if VXWORKS support is required -# -# VXWORKS=1 - -HOME=`pwd` -if [ ! -x winTools -o ! -x winTools/cygpath.exe ] -then - echo "Can't find build tools. Install build tools in $HOME/winTools" -fi - -ROOT=`winTools/cygpath -u $HOMEDRIVE` -: ${ROOT:=C:/} -APPWEB_PATH="${HOME}/bin/DEBUG:${HOME}/bin/RELEASE:${HOME}/bin:${HOME}/winTools" -CDPATH=".:${HOME}:${HOME}/http:${HOME}/http/modules:${HOME}/packages" -PS1="$ " - -export CDPATH INCLUDE LIB LIBPATH PATH PS1 TERM - -echo -e "\n\n###################################################" -echo "Mbedthis AppWeb, Cygwin build tools." -echo "Using compiler: $PREFERRED_CC, .NET framework: $FRAMEWORK" -echo -e "###################################################" - -################################################################################ - -# -# Setup for Visual Studio and SDK -# -if [ $PREFERRED_CC == "VS2005" ] -then - # - # Visual Studio .NET 2005 defines. - # - CYNET="${ROOT}/Program Files/Microsoft Visual Studio 8" - DOSNET="C:/Program Files/Microsoft Visual Studio 8" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC/BIN:$CYNET/VC/VCPackages:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin:$CYNET/SDK/v2.0/bin:`cygpath -W`/Microsoft.NET/Framework/v2.0.40607:$CYNET/SDK/v2.0/bin:$PATH" - INCLUDE="$DOSNET/VC/ATLMFC/INCLUDE;$DOSNET/VC/INCLUDE;$DOSNET/VC/PlatformSDK/include;$DOSNET/SDK/v2.0/include;$INCLUDE" - LIB="$DOSNET/VC/ATLMFC/LIB;$DOSNET/VC/LIB;$DOSNET/VC/PlatformSDK/lib;$DOSNET/SDK/v2.0/lib;$LIB" - LIBPATH=c:/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK -fi - -if [ $PREFERRED_CC == "VS2003" ] -then - # - # Visual Studio .NET 2003 defines. - # - CYNET="${ROOT}/Program Files/Microsoft Visual Studio .NET 2003" - DOSNET="C:/Program Files/Microsoft Visual Studio .NET 2003" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC7/BIN:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin/prerelease:$CYNET/Common7/Tools/bin:$CYNET/FrameworkSDK/bin:${ROOT}/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$CYNET/SDK/v1.1/bin:$PATH" - INCLUDE="$DOSNET/VC7/ATLMFC/INCLUDE;$DOSNET/VC7/INCLUDE;$DOSNET/VC7/PlatformSDK/include/prerelease;$DOSNET/VC7/PlatformSDK/include;$DOSNET/FrameworkSDK/include;$INCLUDE" - LIB="$DOSNET/VC7/ATLMFC/LIB;$DOSNET/VC7/LIB;$DOSNET/VC7/PlatformSDK/lib/prerelease;$DOSNET/VC7/PlatformSDK/lib;$DOSNET/FrameworkSDK/lib;$LIB" -fi - - -if [ $PREFERRED_CC == "VS.NET" ] -then - # - # Visual Studio .NET defines. - # - CYNET="${ROOT}/Program Files/Microsoft Visual Studio .NET" - DOSNET="C:/Program Files/Microsoft Visual Studio .NET" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC7/BIN:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin/prerelease:$CYNET/Common7/Tools/bin:$CYNET/FrameworkSDK/bin:${ROOT}/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$CYNET/SDK/v1.0/bin:$PATH" - INCLUDE="$DOSNET/VC7/ATLMFC/INCLUDE;$DOSNET/VC7/INCLUDE;$DOSNET/VC7/PlatformSDK/include/prerelease;$DOSNET/VC7/PlatformSDK/include;$DOSNET/FrameworkSDK/include;$INCLUDE" - LIB="$DOSNET/VC7/ATLMFC/LIB;$DOSNET/VC7/LIB;$DOSNET/VC7/PlatformSDK/lib/prerelease;$DOSNET/VC7/PlatformSDK/lib;$DOSNET/FrameworkSDK/lib;$LIB" -fi - - -if [ $PREFERRED_CC == "VS6" ] -then - # Visual Studio 6 defines. - # - CYNET="${ROOT}/Program Files/Microsoft Visual Studio" - DOSNET="C:/Program Files/Microsoft Visual Studio" - PATH="$APPWEB_PATH:$CYNET/Common/MSDev98/bin:$CYNET/VC98/BIN:$CYNET/Common/IDE:$CYNET/Common/Tools/WinNT:$CYNET/Common/Tools:$PATH" - INCLUDE="$DOSNET/VC98/ATLMFC/INCLUDE;$DOSNET/VC98/INCLUDE;$DOSNET/VC98/MFC/INCLUDE;$INCLUDE" - LIB="$DOSNET/VC98/LIB;$DOSNET/VC98/MFC/LIB;$LIB" -fi - -if [ $VXWORKS ] -then - # - # Required by VxWorks - # - WIND_BASE=C:/tornado - WIND_HOST_TYPE=x86-win32 - WIND_REGISTRY=coalsack - WIND_LMHOST=coalsack - BLD_VX_HOST=i386-wrs-vxworks - VX_TOOLS=`cygpath $WIND_BASE`/host/$WIND_HOST_TYPE - export WIND_BASE WIND_HOST_TYPE WIND_REGISTRY WIND_LMHOST BLD_VX_HOST - - # - # Use cygwin make and tools by preference - # - PATH="$APPWEB_PATH:$VX_TOOLS/bin:$PATH" -fi - -# -# Make required directories for CYGWIN -# -if [ ! -x /bin/bash.exe ] -then - DIR=`cygpath -w "$HOME/winTools"` - echo -e "\nCreating /bin" - echo Mounting \"${DIR}\" as /bin - mount -f -b "$DIR" /bin -fi - -if [ ! -x /tmp ] -then - mkdir -p tmp - DIR=`cygpath -w "$HOME/tmp"` - echo -e "\nCreating /tmp" - echo Mounting \"${DIR}\" as /tmp - mount -f -b "$DIR" /tmp -fi -echo - -################################################################################ -# -# Do a bit of validation -# -type cl 2>/dev/null >/dev/null -if [ $? -ne 0 ] -then - echo "Can't find compiler: cl. Check WIN/bashrc settings for PATH" -fi -set -o vi - -################################################################################ diff --git a/source4/lib/appweb/ejs-2.0/.exrc b/source4/lib/appweb/ejs-2.0/.exrc deleted file mode 100644 index dd37846529..0000000000 --- a/source4/lib/appweb/ejs-2.0/.exrc +++ /dev/null @@ -1 +0,0 @@ -set ts=4 sw=4 diff --git a/source4/lib/appweb/ejs-2.0/.ignore b/source4/lib/appweb/ejs-2.0/.ignore deleted file mode 100644 index 866f06c6c1..0000000000 --- a/source4/lib/appweb/ejs-2.0/.ignore +++ /dev/null @@ -1,57 +0,0 @@ -*.class -*.dll -*.exe -*.exp -*.jar -*.lib -*.lnk -*.map -*.new -*.old -*.pdb -*.res -*.sln -*.suo -*.sym -*.tmp -*.sav -.ICEauthority -.bash_history -.changes -.cvsignore -.esd_auth -.fonts.cache-1 -.viminfo -make.dep -thumbs.db -vc70.pdb -*.ncb -*.opt -*.idb -*.pch -*.dep -*.aps -all -tmp -make.vars -sh.vars -config.make -config.h -config.sh -configure -make.os -.firstBuild -.viminfo -.ssh -_viminfo -buildConfig.h -buildConfig.make -buildConfig.sh -.ccache -appWeb.kdev* -subversion -.vimrc -.subversion -.ignore -njs -msvc diff --git a/source4/lib/appweb/ejs-2.0/.loginrc b/source4/lib/appweb/ejs-2.0/.loginrc deleted file mode 100644 index 90b76a2ad0..0000000000 --- a/source4/lib/appweb/ejs-2.0/.loginrc +++ /dev/null @@ -1,218 +0,0 @@ -# -# .loginrc -- Michael's login shell startup script (used only for Windows) -# -# NOTE: this should not be distributed with releases. -# -# Copyright (c) Mbedthis Software, 2003-2005. All Rights Reserved. -# -HOME=`pwd` - -TERM=ansi -CYROOT=/cygdrive/c -JDK="/cygdrive/c/program files/java/jdk1.5.0_07/bin" -H=$CYROOT -R=usr/svn/appWeb/main -CDPATH=".:${H}/usr/svn/appWeb:${H}/${R}/http:${H}/${R}/http/modules:${H}/${R}:${H}/usr/svn/appWeb/releases:${H}/usr/svn/packages:${H}/usr/svn/bling/player/trunk:${H}/usr/svn/bling/player/trunk/src:${H}/usr/svn/bling/player/trunk/appdir:${H}/usr/svn:${H}:${H}/usr/svn:${H}/usr" -APPWEB_PATH="${H}/${R}/bin/DEBUG:${H}/${R}/bin/RELEASE:${H}/${R}/bin:${H}/usr/bin" -PATH="${H}/usr/bin:/usr/local/bin:/usr/bin:/bin:/usr/X11R6/bin:$PATH:${H}/tcl/bin:${JDK}" - -CLASSPATH="c:/usr/svn/j/ggperf" -PS1='`cygpath -m $PWD`> ' -SVN_EDITOR=C:/cygwin/bin/vim.exe - -umask 022 - -export TERM CDPATH INCLUDE LIB LIBPATH PATH PS1 SVN_EDITOR MSCL CLASSPATH - -################################################################################ -# -# Set the dev environment PATH and other critical environment variables -# - -# export BLD_ALTERNATE_CONFIG=WIN/buildConfig - -# -# Desired .NET Framework -# -# FRAMEWORK=v1.0.3705 -# FRAMEWORK=v1.1.4322 -FRAMEWORK=v2.0.50727 - -# -# Desired C Compiler -# -# MSCL=VS2005 -# MSCL=VS2003 -# MSCL=VS.NET -MSCL=VS6 -VXWORKS=1 - -echo "Using compiler: $MSCL, .NET framework: $FRAMEWORK" - -# -# Setup for Visual Studio and SDK -# -if [ $MSCL == "VS2005" ] -then - # - # Visual Studio .NET 2005 defines. - # - CYNET="$H/Program Files/Microsoft Visual Studio 8" - DOSNET="C:/Program Files/Microsoft Visual Studio 8" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC/BIN:$CYNET/VC/VCPackages:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin:$CYNET/SDK/v2.0/bin:$CYROOT/WINDOWS/Microsoft.NET/Framework/v2.0.40607:$CYNET/SDK/v2.0/bin:$PATH" - INCLUDE="$DOSNET/VC/ATLMFC/INCLUDE;$DOSNET/VC/INCLUDE;$DOSNET/VC/PlatformSDK/include;$DOSNET/SDK/v2.0/include;$INCLUDE" - LIB="$DOSNET/VC/ATLMFC/LIB;$DOSNET/VC/LIB;$DOSNET/VC/PlatformSDK/lib;$DOSNET/SDK/v2.0/lib;$LIB" - LIBPATH=c:/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK - - # MOB -- old - # PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC/BIN:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin/prerelease:$CYNET/Common7/Tools/bin:$CYNET/FrameworkSDK/bin:$H/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$PATH" - # INCLUDE="$DOSNET/VC/ATLMFC/INCLUDE;$DOSNET/VC/INCLUDE;$DOSNET/VC/PlatformSDK/include/prerelease;$DOSNET/VC/PlatformSDK/include;$DOSNET/FrameworkSDK/include;$INCLUDE" - # LIB="$DOSNET/VC/ATLMFC/LIB;$DOSNET/VC/LIB;$DOSNET/VC/PlatformSDK/lib/prerelease;$DOSNET/VC/PlatformSDK/lib;$DOSNET/FrameworkSDK/lib;$LIB" -fi - -if [ $MSCL == "VS2003" ] -then - # - # Visual Studio .NET 2003 defines. - # - CYNET="$H/Program Files/Microsoft Visual Studio .NET 2003" - DOSNET="C:/Program Files/Microsoft Visual Studio .NET 2003" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC7/BIN:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin/prerelease:$CYNET/Common7/Tools/bin:$CYNET/FrameworkSDK/bin:$H/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$CYNET/SDK/v1.1/bin:$PATH" - INCLUDE="$DOSNET/VC7/ATLMFC/INCLUDE;$DOSNET/VC7/INCLUDE;$DOSNET/VC7/PlatformSDK/include/prerelease;$DOSNET/VC7/PlatformSDK/include;$DOSNET/FrameworkSDK/include;$INCLUDE" - LIB="$DOSNET/VC7/ATLMFC/LIB;$DOSNET/VC7/LIB;$DOSNET/VC7/PlatformSDK/lib/prerelease;$DOSNET/VC7/PlatformSDK/lib;$DOSNET/FrameworkSDK/lib;$LIB" -fi - - -if [ $MSCL == "VS.NET" ] -then - # - # Visual Studio .NET defines. - # - CYNET="$H/Program Files/Microsoft Visual Studio .NET" - DOSNET="C:/Program Files/Microsoft Visual Studio .NET" - PATH="$APPWEB_PATH:$CYNET/Common7/IDE:$CYNET/VC7/BIN:$CYNET/Common7/Tools:$CYNET/Common7/Tools/bin/prerelease:$CYNET/Common7/Tools/bin:$CYNET/FrameworkSDK/bin:$H/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$CYNET/SDK/v1.0/bin:$PATH" - INCLUDE="$DOSNET/VC7/ATLMFC/INCLUDE;$DOSNET/VC7/INCLUDE;$DOSNET/VC7/PlatformSDK/include/prerelease;$DOSNET/VC7/PlatformSDK/include;$DOSNET/FrameworkSDK/include;$INCLUDE" - LIB="$DOSNET/VC7/ATLMFC/LIB;$DOSNET/VC7/LIB;$DOSNET/VC7/PlatformSDK/lib/prerelease;$DOSNET/VC7/PlatformSDK/lib;$DOSNET/FrameworkSDK/lib;$LIB" -fi - - -if [ $MSCL == "VS6" ] -then - # Visual Studio 6 defines. - # - CYNET="$H/Program Files/Microsoft Visual Studio" - DOSNET="C:/Program Files/Microsoft Visual Studio" - PATH="$APPWEB_PATH:$CYNET/Common/MSDev98/bin:$CYNET/VC98/BIN:$CYNET/Common/IDE:$CYNET/Common/Tools/WinNT:$CYNET/Common/Tools:$PATH" - # OLD PATH="$APPWEB_PATH:$CYNET/Common/IDE:$CYNET/VC98/BIN:$CYNET/Common/MSDev98/bin:$CYNET/Common/Tools:$CYNET/Common/Tools/bin/prerelease:$CYNET/Common/Tools/bin:$CYNET/FrameworkSDK/bin:$H/WINDOWS/Microsoft.NET/Framework/$FRAMEWORK:$PATH" - INCLUDE="$DOSNET/VC98/ATLMFC/INCLUDE;$DOSNET/VC98/INCLUDE;$DOSNET/VC98/MFC/INCLUDE;$INCLUDE" - LIB="$DOSNET/VC98/LIB;$DOSNET/VC98/MFC/LIB;$LIB" -fi - -if [ $VXWORKS ] -then - # - # Required by VxWorks - # - WIND_BASE=C:/tornado - WIND_HOST_TYPE=x86-win32 - WIND_REGISTRY=coalsack - WIND_LMHOST=coalsack - BLD_VX_HOST=i386-wrs-vxworks - export WIND_BASE WIND_HOST_TYPE WIND_REGISTRY WIND_LMHOST BLD_VX_HOST - - VX_TOOLS=`cygpath $WIND_BASE`/host/$WIND_HOST_TYPE - # - # Use cygwin make and tools by preference - # - PATH="$APPWEB_PATH:$PATH:$VX_TOOLS/bin" -fi - -# -# Make required directories for CYGWIN -# -if [ ! -x /bin/bash.exe ] -then - DIR=`cygpath -w "$HOME/winTools"` - echo -e "\nCreating /bin" - echo Mounting \"${DIR}\" as /bin - mount -f -b "$DIR" /bin -fi - -if [ ! -x /tmp ] -then - mkdir -p tmp - DIR=`cygpath -w "$HOME/tmp"` - echo -e "\nCreating /tmp" - echo Mounting \"${DIR}\" as /tmp - mount -f -b "$DIR" /tmp -fi -echo - - -################################################################################ -# -# Do a bit of validation (MOB -- extend) -# -type cl 2>/dev/null >/dev/null -if [ $? -ne 0 ] -then - echo "Can't find compiler: cl. Check WIN/bashrc settings for PATH" -fi - -################################################################################ -# -# Some convenient functions -# -pvi () { - - pattern=$1 - shift - files=$* - if [ -z "${files}" ] - then - files='*.c *.cpp *.h Makefile *.html *.aspx *.cs' - fi - vi -c "/${pattern}" $(grep -l "${pattern}" ${files}) -} - -################################################################################ - -g() { - pattern=$1 - shift - files=$* - if [ -z "${files}" ] - then - files=`echo *.c *.cpp *.h Makefile *.html *.aspx *.cs` - fi - eval grep "${pattern}" ${files} -} - -################################################################################ - -usedvi() { - pvi $1 $HOME/mr/*.c $HOME/mr/*.h $HOME/mr/WIN/*.c $HOME/lib/*/*.c -} - -################################################################################ - -alias ls='ls -CF $*' -alias lc='ls -CF $*' -alias lr='ls -R $*' -alias xwin='startxwin.sh' -alias htmlview='"C:/Program Files/Internet Explorer/iexplore.exe" $*' -set -o vi - -if [ `uname -o` = "Cygwin" ] -then - alias vim='"C:/Program Files/vim/vim64/vim.exe" $*' - alias gvim='"C:/Program Files/vim/vim64/gvim.exe" $*' -fi - -brew() { - "C:/Program Files/BREW SDK v2.1.3/Bin/BREW_Emulator.exe" -} - -js() { - cscript /nologo $* -} diff --git a/source4/lib/appweb/ejs-2.0/ejs/.ignore b/source4/lib/appweb/ejs-2.0/ejs/.ignore deleted file mode 100644 index 47f4ac63b2..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/.ignore +++ /dev/null @@ -1,2 +0,0 @@ -ejs -future diff --git a/source4/lib/appweb/ejs-2.0/ejs/Makefile b/source4/lib/appweb/ejs-2.0/ejs/Makefile deleted file mode 100644 index ea6be8c401..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/Makefile +++ /dev/null @@ -1,61 +0,0 @@ -# -# Makefile for Embedded Javascript (EJS) -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -# -# Ejs may be linked into shared handlers so we must build the objects both -# shared and static if --shared was specified to configure. -# -COMPILE := *.c -EXPORT_OBJECTS := yes -PRE_DIRS := classes system db -MAKE_IFLAGS := -I../mpr -I../exml - -include make.dep - -ifeq ($(BLD_PRODUCT),ejs) -POST_DIRS := package -endif - -ifeq ($(BLD_FEATURE_TEST),1) -POST_DIRS += test -endif - -ifeq ($(BLD_FEATURE_EJS_DB),1) -LIBS += sqlite -endif - -TARGETS += $(BLD_BIN_DIR)/libejs$(BLD_LIB) -TARGETS += $(BLD_BIN_DIR)/ejs$(BLD_EXE) - -ifeq ($(BLD_FEATURE_EJS),1) -compileExtra: $(TARGETS) -endif - -$(BLD_BIN_DIR)/libejs$(BLD_LIB): files \ - $(shell BLD_OBJ=$(BLD_OBJ) \; BLD_OBJ_DIR=$(BLD_OBJ_DIR) \; \ - eval echo `cat files`) - @bld --library $(BLD_BIN_DIR)/libejs \ - --objectsDir $(BLD_OBJ_DIR) --objectList files \ - --libs "exml mpr $(LIBS)" - -$(BLD_BIN_DIR)/ejs$(BLD_EXE): $(BLD_BIN_DIR)/libejs$(BLD_LIB) \ - $(BLD_BIN_DIR)/libmpr$(BLD_LIB) \ - $(BLD_BIN_DIR)/libejs$(BLD_LIB) $(FILES) - @bld --executable $(BLD_BIN_DIR)/ejs$(BLD_EXE) \ - --rpath "$(BLD_PREFIX)/bin" \ - --preferStatic --smartLibs "ejs exml mpr $(LIBS)" \ - --objectsDir $(BLD_OBJ_DIR) \ - --objects "$(BLD_OBJ_DIR)/ejsCmd$(BLD_OBJ)" - -cleanExtra: - @echo "rm -f $(TARGETS)" | $(BLDOUT) - @rm -f $(TARGETS) - @rm -f $(BLD_BIN_DIR)/libejs.* - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore b/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore deleted file mode 100644 index fb5a29031e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/.ignore +++ /dev/null @@ -1 +0,0 @@ -.updated diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile b/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile deleted file mode 100644 index ce12bb3829..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile to build the EJS Classes -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I.. -I../../mpr -I../../exml - -include make.dep - -compileExtra: .updated - -.updated: $(FILES) - @touch .updated - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c deleted file mode 100644 index feb64b1aa8..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsArray.c +++ /dev/null @@ -1,167 +0,0 @@ -/* - * @file ejsArray.c - * @brief Array class - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/************************************ Code ************************************/ - -int ejsDefineArrayClass(Ejs *ep) -{ - if (ejsDefineClass(ep, "Array", "Object", ejsArrayConstructor) == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ -/* - * Routine to create the base array type - */ - -EjsVar *ejsCreateArrayInternal(EJS_LOC_DEC(ep, loc), int size) -{ - EjsProperty *pp; - EjsVar *obj, *vp; - - /* MOB -- need to supply hash size -- max(size, 503)); */ - - obj = ejsCreateSimpleObjInternal(EJS_LOC_PASS(ep, loc), "Array"); - if (obj == 0) { - mprAssert(0); - return obj; - } - obj->isArray = 1; - - /* MOB -- call constructor here and replace this code */ - - pp = ejsSetPropertyToInteger(ep, obj, "length", size); - ejsMakePropertyEnumerable(pp, 0); - - vp = ejsGetVarPtr(pp); - vp->isArrayLength = 1; - - return obj; -} - -/******************************************************************************/ - -EjsVar *ejsAddArrayElt(Ejs *ep, EjsVar *op, EjsVar *element, - EjsCopyDepth copyDepth) -{ - EjsProperty *pp; - EjsVar *vp; - char idx[16]; - int length; - - mprAssert(op->isArray); - - length = ejsGetPropertyAsInteger(ep, op, "length"); - - mprItoa(idx, sizeof(idx), length); - pp = ejsCreateProperty(ep, op, idx); - vp = ejsGetVarPtr(pp); - - ejsWriteVar(ep, vp, element, copyDepth); - - ejsSetPropertyToInteger(ep, op, "length", length + 1); - - return vp; -} - -/******************************************************************************/ -/* - * Constructor - */ - -int ejsArrayConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsProperty *pp; - EjsVar *vp; - char idx[16]; - int i, max; - - thisObj->isArray = 1; - max = 0; - - if (argc > 0) { - if (argc == 1 && ejsVarIsNumber(argv[0])) { - /* - * x = new Array(size); - */ - max = (int) ejsVarToInteger(argv[0]); - - } else { - /* - * x = new Array(element0, element1, ..., elementN): - */ - max = argc; - for (i = 0; i < max; i++) { - mprItoa(idx, sizeof(idx), i); - pp = ejsCreateSimpleProperty(ep, thisObj, idx); - vp = ejsGetVarPtr(pp); - ejsWriteVar(ep, vp, argv[i], EJS_SHALLOW_COPY); - } - } - } - - pp = ejsCreateSimpleProperty(ep, thisObj, "length"); - ejsMakePropertyEnumerable(pp, 0); - vp = ejsGetVarPtr(pp); - ejsWriteVarAsInteger(ep, vp, max); - vp->isArrayLength = 1; - - return 0; -} - -/******************************************************************************/ - -#else -void ejsArrayDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c deleted file mode 100755 index 096316a822..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsDate.c +++ /dev/null @@ -1,197 +0,0 @@ -/* - * @file ejsStndClasses.c - * @brief EJS support methods - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS && 0 - -/******************************************************************************/ -/* - * Date constructor - - * - * Date(); - * Date(milliseconds); - * Date(dateString); - * Date(year, month, date); - * Date(year, month, date, hour, minute, second); - */ - -int ejsDateConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - return 0; -} - -/******************************************************************************/ - -static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *fileName; - XmlState *parser; - Exml *xp; - MprFile *file; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: load(fileName);"); - return -1; - } - fileName = argv[0]->string; - - /* FUTURE -- not romable - Need rom code in MPR not MprServices - */ - file = mprOpen(ep, fileName, O_RDONLY, 0664); - if (file == 0) { - ejsError(ep, EJS_IO_ERROR, "Can't open: %s", fileName); - return -1; - } - - xp = initParser(ep, thisObj, fileName); - parser = exmlGetParseArg(xp); - - exmlSetInputStream(xp, readFileData, (void*) file); - - if (exmlParse(xp) < 0) { - if (! ejsGotException(ep)) { - ejsError(ep, EJS_IO_ERROR, "Can't parse XML file: %s\nDetails %s", - fileName, exmlGetErrorMsg(xp)); - } - termParser(xp); - mprClose(file); - return -1; - } - - ejsSetReturnValue(ep, parser->nodeStack[0].obj); - - termParser(xp); - mprClose(file); - - return 0; -} - -/******************************************************************************/ - -int ejsDefineDateClass(Ejs *ep) -{ - EjsVar *dateClass; - - dateClass = ejsDefineClass(ep, "Date", "Object", ejsDateConstructor); - if (dateClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - ejsDefineCMethod(ep, dateClass, "getDate", xxxProc, EJS_NO_LOCAL); - - /* Returns "Friday" or 4 ? */ - ejsDefineCMethod(ep, dateClass, "getDay", xxxProc, EJS_NO_LOCAL); - - ejsDefineCMethod(ep, dateClass, "getMonth", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getFullYear", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getYear", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getHours", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getMinutes", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getSeconds", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getMilliseconds", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getTime", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "getTimeZoneOffset", xxxProc, EJS_NO_LOCAL); - - ejsDefineCMethod(ep, dateClass, "parse", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setDate", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setMonth", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setFullYear", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setYear", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setMinutes", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setSeconds", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setMilliseconds", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "setTime", xxxProc, EJS_NO_LOCAL); - - ejsDefineCMethod(ep, dateClass, "toString", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "toGMTString", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "toUTCString", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "toLocaleString", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "UTC", xxxProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, dateClass, "valueOf", xxxProc, EJS_NO_LOCAL); - /* - UTC: getUTCDate, getUTCDay, getUTCMonth, getUTCFullYear, getUTCHours, - getUTCMinutes, getUTCSeconds, getUTCMilliseconds - setUTCDate, setUTCDay, setUTCMonth, setUTCFullYear, setUTCHours, - setUTCMinutes, setUTCSeconds, setUTCMilliseconds - */ - - return ejsObjHasErrors(dateClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ -/* - Time is since 1970/01/01 GMT - - Normal: Fri Feb 10 2006 05:06:44 GMT-0800 (Pacific Standard Time) - UTC: Sat, 11 Feb 2006 05:06:44 GMT - - // Using without New - - println(Date()); - - var myDate = new Date(); - myDate.setFullYear(2010, 0, 14); - - var today = new Date(); - - if (myDate > today) { - } else { - } - - - X=Date() should be equivalent to X=(new Date()).toString() - - */ -/******************************************************************************/ - -#else -void ejsStndClassesDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c deleted file mode 100755 index 99445afc7c..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsError.c +++ /dev/null @@ -1,140 +0,0 @@ -/* - * @file ejsError.c - * @brief Error class - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/************************************ Code ************************************/ -/* - * Parse the args and return the message. Convert non-string args using - * .toString. - */ - -static char *getMessage(Ejs *ep, int argc, EjsVar **argv) -{ - if (argc == 0) { - return ""; - - } else if (argc == 1) { - if (! ejsVarIsString(argv[0])) { - if (ejsRunMethod(ep, argv[0], "toString", 0) < 0) { - return 0; - } - return ep->result->string; - - } else { - return argv[0]->string; - } - - } else { - /* Don't call ejsError here or it will go recursive. */ - return 0; - } -} - - -/******************************************************************************/ -/* - * Error Constructor and also used for constructor for sub classes. - * - * Usage: new Error([message]) - */ - -int ejsErrorCons(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *msg, *stack; - - msg = getMessage(ep, argc, argv); - if (msg == 0) { - return -1; - } - - ejsSetPropertyToString(ep, thisObj, "name", ejsGetBaseClassName(thisObj)); - ejsSetPropertyToString(ep, thisObj, "message", msg); - - ejsSetPropertyToUndefined(ep, thisObj, "stack"); - - stack = ejsFormatStack(ep); - if (stack) { - ejsSetPropertyToString(ep, thisObj, "stack", stack); - mprFree(stack); - } - - if (ejsObjHasErrors(thisObj)) { - return -1; - } - - return 0; -} - -/******************************************************************************/ - -int ejsDefineErrorClasses(Ejs *ep) -{ - if (ejsDefineClass(ep, "Error", "Object", ejsErrorCons) == 0 || - ejsDefineClass(ep, "AssertError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "EvalError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "InternalError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "IOError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "MemoryError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "RangeError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "ReferenceError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "SyntaxError", "Error", ejsErrorCons) == 0 || - ejsDefineClass(ep, "TypeError", "Error", ejsErrorCons) == 0) { - - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ - -#else -void ejsErrorDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c deleted file mode 100644 index 4f2e23beb2..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsObject.c +++ /dev/null @@ -1,588 +0,0 @@ -/* - * @file ejsObject.c - * @brief Object class - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ -/* - * Support routines - */ - -static void formatVar(Ejs *ep, MprBuf *bp, EjsVar *vp); - -/******************************************************************************/ -/* - * Routine to create an object of the desired class. Class name may - * contain "." - * - * The created object will be a stand-alone class NOT entered into the - * properties of any other object. Callers must do this if required. ClassName - * may contain "." and is interpreted relative to "obj" if supplied. - * - * Note: this does not call the constructors for the various objects and base - * classes. - */ - -EjsVar *ejsCreateSimpleObjInternal(EJS_LOC_DEC(ep, loc), const char *className) -{ - EjsVar *baseClass; - - if (className && *className) { - baseClass = ejsGetClass(ep, 0, className); - if (baseClass == 0) { - mprError(ep, MPR_LOC, "Can't find base class %s", className); - return 0; - } - } else { - baseClass = 0; - } - - return ejsCreateSimpleObjUsingClassInt(EJS_LOC_PASS(ep, loc), - baseClass); -} - -/******************************************************************************/ -/* - * Create an object based upon the specified base class object. It will be a - * stand-alone class not entered into the properties of any other object. - * Callers must do this if required. - * - * Note: this does not call the constructors for the various objects and base - * classes. - */ - -EjsVar *ejsCreateSimpleObjUsingClassInt(EJS_LOC_DEC(ep, loc), - EjsVar *baseClass) -{ - EjsVar *vp; - - mprAssert(baseClass); - - if (baseClass == 0) { - mprError(ep, MPR_LOC, "Missing base class\n"); - return 0; - } - - vp = ejsCreateObjVarInternal(EJS_LOC_PASS(ep, loc)); - if (vp == 0) { - return vp; - } - - ejsSetBaseClass(vp, baseClass); - - /* - * This makes all internal method accesses faster - * NOTE: this code is duplicated in ejsCreateSimpleClass - */ - mprAssert(vp->objectState); - vp->objectState->methods = baseClass->objectState->methods; - - return vp; -} - -/******************************************************************************/ - -void ejsSetMethods(Ejs *ep, EjsVar *op) -{ - op->objectState->methods = ep->global->objectState->methods; -} - -/******************************************************************************/ -/******************************** Internal Methods ****************************/ -/******************************************************************************/ - -static EjsVar *createObjProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsGetVarPtr(ejsCreateSimpleProperty(ep, obj, property)); -} - -/******************************************************************************/ - -static int deleteObjProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsDeleteProperty(ep, obj, property); -} - -/******************************************************************************/ - -static EjsVar *getObjProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property)); -} - -/******************************************************************************/ -/* - * Set the value of a property. Create if it does not exist - */ - -static EjsVar *setObjProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value) -{ - EjsProperty *pp; - EjsVar *vp; - - pp = ejsCreateSimpleProperty(ep, obj, property); - if (pp == 0) { - mprAssert(pp); - return 0; - } - vp = ejsGetVarPtr(pp); - if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0) { - mprAssert(0); - return 0; - } - return ejsGetVarPtr(pp); -} - -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -#if UNUSED -/* - * Object constructor. We don't use this for speed. Think very carefully if - * you add an object constructor. - */ - -int ejsObjectConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - return 0; -} - -#endif -/******************************************************************************/ -/******************************** Visible Methods *****************************/ -/******************************************************************************/ - -static int cloneMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int copyDepth; - - copyDepth = EJS_DEEP_COPY; - - if (argc == 1 && ejsVarToBoolean(argv[0])) { - copyDepth = EJS_RECURSIVE_DEEP_COPY; - } - - ejsWriteVar(ep, ep->result, thisObj, copyDepth); - - return 0; -} - -/******************************************************************************/ - -static int toStringMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprBuf *bp; - int saveMaxDepth, saveDepth, saveFlags; - - saveMaxDepth = ep->maxDepth; - - if (argc >= 1) { - ep->maxDepth = ejsVarToInteger(argv[0]); - } else if (ep->maxDepth == 0) { - ep->maxDepth = MAXINT; - } - - saveFlags = ep->flags; - if (argc >= 2) { - if (ejsVarToBoolean(argv[1])) { - ep->flags |= EJS_FLAGS_ENUM_HIDDEN; - } - } - if (argc == 3) { - if (ejsVarToBoolean(argv[2])) { - ep->flags |= EJS_FLAGS_ENUM_BASE; - } - } - - bp = mprCreateBuf(ep, 0, 0); - - saveDepth = ep->depth; - - formatVar(ep, bp, thisObj); - - ep->depth = saveDepth; - ep->maxDepth = saveMaxDepth; - - mprAddNullToBuf(bp); - - ejsWriteVarAsString(ep, ep->result, mprGetBufStart(bp)); - mprFree(bp); - - ep->flags = saveFlags; - - return 0; -} - -/******************************************************************************/ - -static int valueOfMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 0) { - mprAssert(0); - return -1; - } - - switch (thisObj->type) { - default: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_OBJECT: - case EJS_TYPE_METHOD: - case EJS_TYPE_STRING_CMETHOD: - ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY); - break; - - case EJS_TYPE_STRING: - ejsWriteVarAsInteger(ep, ep->result, atoi(thisObj->string)); - break; - - case EJS_TYPE_BOOL: - case EJS_TYPE_INT: -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: -#endif -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: -#endif - ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY); - break; - } - return 0; -} - -/******************************************************************************/ - -static int hashGetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ejs, (int) thisObj->objectState); - return 0; -} - -/******************************************************************************/ - -static int classGetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (thisObj->objectState == 0 || thisObj->objectState->baseClass == 0) { - ejsSetReturnValueToString(ejs, "object"); - } else { - ejsSetReturnValueToString(ejs, - thisObj->objectState->baseClass->objectState->className); - } - return 0; -} - -/******************************************************************************/ -/* - * Format an object. Called recursively to format properties and contained - * objects. - */ - -static void formatVar(Ejs *ep, MprBuf *bp, EjsVar *vp) -{ - EjsProperty *pp, *first; - EjsVar *propVar, *baseClass; - char *buf, *value; - int i; - - if (vp->type == EJS_TYPE_OBJECT) { - if (!vp->objectState->visited) { - - mprPutStringToBuf(bp, vp->isArray ? "[\n" : "{\n"); - - ep->depth++; - vp->objectState->visited = 1; - - if (ep->depth <= ep->maxDepth) { - first = ejsGetFirstProperty(vp, EJS_ENUM_ALL); - - if (ep->flags & EJS_FLAGS_ENUM_BASE) { - baseClass = vp->objectState->baseClass; - if (baseClass) { - for (i = 0; i < ep->depth; i++) { - mprPutStringToBuf(bp, " "); - } - mprPutStringToBuf(bp, baseClass->objectState->objName); - mprPutStringToBuf(bp, ": /* Base Class */ "); - if (baseClass->objectState == vp->objectState) { - value = "this"; - } else if (ejsRunMethodCmd(ep, baseClass, "toString", - "%d", ep->maxDepth) < 0) { - value = "[object Object]"; - } else { - mprAssert(ejsVarIsString(ep->result)); - value = ep->result->string; - } - mprPutStringToBuf(bp, value); - if (first) { - mprPutStringToBuf(bp, ",\n"); - } - } - } - - pp = first; - while (pp) { - if (! pp->dontEnumerate || - ep->flags & EJS_FLAGS_ENUM_HIDDEN) { - for (i = 0; i < ep->depth; i++) { - mprPutStringToBuf(bp, " "); - } - - if (! vp->isArray) { - mprPutStringToBuf(bp, pp->name); - mprPutStringToBuf(bp, ": "); - } - - propVar = ejsGetVarPtr(pp); - if (propVar->type == EJS_TYPE_OBJECT) { - if (pp->var.objectState == vp->objectState) { - value = "this"; - } else if (ejsRunMethodCmd(ep, propVar, - "toString", "%d", ep->maxDepth) < 0) { - value = "[object Object]"; - } else { - mprAssert(ejsVarIsString(ep->result)); - value = ep->result->string; - } - mprPutStringToBuf(bp, value); - - } else { - formatVar(ep, bp, &pp->var); - } - - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - if (pp) { - mprPutStringToBuf(bp, ",\n"); - } - } else { - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - } - } - vp->objectState->visited = 0; - - mprPutCharToBuf(bp, '\n'); - - ep->depth--; - for (i = 0; i < ep->depth; i++) { - mprPutStringToBuf(bp, " "); - } - mprPutCharToBuf(bp, vp->isArray ? ']' : '}'); - } - - } else if (vp->type == EJS_TYPE_METHOD) { - - mprPutStringToBuf(bp, "function ("); - for (i = 0; i < vp->method.args->length; i++) { - mprPutStringToBuf(bp, vp->method.args->items[i]); - if ((i + 1) < vp->method.args->length) { - mprPutStringToBuf(bp, ", "); - } - } - mprPutStringToBuf(bp, ") {"); - mprPutStringToBuf(bp, vp->method.body); - for (i = 0; i < ep->depth; i++) { - mprPutStringToBuf(bp, " "); - } - mprPutStringToBuf(bp, "}"); - - } else { - - if (vp->type == EJS_TYPE_STRING) { - mprPutCharToBuf(bp, '\"'); - } - - /* - * We don't use ejsVarToString for arrays, objects and strings. - * This is because ejsVarToString does not call "obj.toString" - * and it is not required for strings. - * MOB - rc - */ - buf = ejsVarToString(ep, vp); - mprPutStringToBuf(bp, buf); - - if (vp->type == EJS_TYPE_STRING) { - mprPutCharToBuf(bp, '\"'); - } - } -} - -/******************************************************************************/ -/* - * mixin code. Blends code at the "thisObj" level. - */ - -static int mixinMethod(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsProperty *pp; - char *buf; - int fid, i, rc; - - mprAssert(argv); - - /* - * Create a variable scope block set to the current object - */ - rc = 0; - fid = ejsSetBlock(ep, thisObj); - - for (i = 0; i < argc; i++) { - - if (ejsVarIsString(argv[i])) { - rc = ejsEvalScript(ep, argv[i]->string, 0); - - } else if (ejsVarIsObject(argv[i])) { - - /* MOB -- OPT. When we have proper scope chains, we should just - refer to the module and not copy */ - pp = ejsGetFirstProperty(argv[i], EJS_ENUM_ALL); - while (pp) { - ejsSetProperty(ep, thisObj, pp->name, ejsGetVarPtr(pp)); - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - - } else { - /* MOB - rc */ - buf = ejsVarToString(ep, argv[i]); - rc = ejsEvalScript(ep, buf, 0); - - } - if (rc < 0) { - ejsCloseBlock(ep, fid); - return -1; - } - } - ejsCloseBlock(ep, fid); - return 0; -} - -/******************************************************************************/ -/* - * Create the object class - */ - -int ejsDefineObjectClass(Ejs *ep) -{ - EjsMethods *methods; - EjsProperty *objectProp, *protoProp; - EjsVar *op, *globalClass; - - /* - * Must specially hand-craft the object class as it is the base class - * of all objects. - */ - op = ejsCreateObjVar(ep); - if (op == 0) { - return MPR_ERR_CANT_CREATE; - } - ejsSetClassName(ep, op, "Object"); - - /* - * Don't use a constructor for objects for speed - */ - ejsMakeClassNoConstructor(op); - - /* - * MOB -- should mark properties as public / private and class or instance. - */ - ejsDefineCMethod(ep, op, "clone", cloneMethod, EJS_NO_LOCAL); - ejsDefineCMethod(ep, op, "toString", toStringMethod, EJS_NO_LOCAL); - ejsDefineCMethod(ep, op, "valueOf", valueOfMethod, EJS_NO_LOCAL); - ejsDefineCMethod(ep, op, "mixin", mixinMethod, EJS_NO_LOCAL); - - ejsDefineCAccessors(ep, op, "hash", hashGetAccessor, 0, EJS_NO_LOCAL); - ejsDefineCAccessors(ep, op, "baseClass", classGetAccessor, 0, EJS_NO_LOCAL); - - /* - * MOB -- make this an accessor - */ - protoProp = ejsSetProperty(ep, op, "prototype", op); - if (protoProp == 0) { - ejsFreeVar(ep, op); - return MPR_ERR_CANT_CREATE; - } - - /* - * Setup the internal methods. Most classes will never override these. - * The XML class will. We rely on talloc to free internal. Use "ep" as - * the parent as we need "methods" to live while the interpreter lives. - */ - methods = mprAllocTypeZeroed(ep, EjsMethods); - op->objectState->methods = methods; - - methods->createProperty = createObjProperty; - methods->deleteProperty = deleteObjProperty; - methods->getProperty = getObjProperty; - methods->setProperty = setObjProperty; - - objectProp = ejsSetPropertyAndFree(ep, ep->global, "Object", op); - - /* - * Change the global class to use Object's methods - */ - globalClass = ep->service->globalClass; - globalClass->objectState->methods = methods; - globalClass->objectState->baseClass = ejsGetVarPtr(protoProp); - - ep->objectClass = ejsGetVarPtr(objectProp); - - if (ejsObjHasErrors(ejsGetVarPtr(objectProp))) { - ejsFreeVar(ep, op); - return MPR_ERR_CANT_CREATE; - } - return 0; -} - -/******************************************************************************/ - -#else -void ejsObjectDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c deleted file mode 100644 index fd6cda7813..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsStndClasses.c +++ /dev/null @@ -1,144 +0,0 @@ -/* - * @file ejsStndClasses.c - * @brief EJS support methods - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/******************************************************************************/ -/******************************* Function Class *******************************/ -/******************************************************************************/ - -int ejsDefineFunctionClass(Ejs *ep) -{ - if (ejsDefineClass(ep, "Function", "Object", ejsFunctionConstructor) == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ -/* - * Function constructor - */ - -int ejsFunctionConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsArgError(ep, "Usage: Function(\"function (arg) { script };\");"); - } - - rc = ejsEvalScript(ep, argv[0]->string, 0); - - /* - * Note: this will convert the object into a method. It will cease to be - * an object. - */ - if (rc == 0 && ejsVarIsMethod(ep->result)) { - /* - * Must make thisObj collectable. - */ - ejsMakeObjPermanent(thisObj, 0); - ejsMakeObjLive(thisObj, 1); - mprAssert(ejsObjIsCollectable(thisObj)); - ejsWriteVar(ep, thisObj, ep->result, EJS_SHALLOW_COPY); - } - return rc; -} - -/******************************************************************************/ -/******************************* Boolean Class ********************************/ -/******************************************************************************/ - -int ejsDefineBooleanClass(Ejs *ep) -{ - if (ejsDefineClass(ep, "Boolean", "Object", ejsBooleanConstructor) == 0){ - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ -/* - * Boolean constructor - */ - -int ejsBooleanConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - return 0; -} - -/******************************************************************************/ -/******************************** Number Class ********************************/ -/******************************************************************************/ - -int ejsDefineNumberClass(Ejs *ep) -{ - if (ejsDefineClass(ep, "Number", "Object", ejsNumberConstructor) == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ -/* - * Number constructor - */ - -int ejsNumberConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - return 0; -} - -/******************************************************************************/ - -#else -void ejsStndClassesDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c deleted file mode 100644 index 2339650361..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsString.c +++ /dev/null @@ -1,381 +0,0 @@ -/* - * @file ejsString.c - * @brief EJScript string class - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -/* - * String constructor. - */ - -int ejsStringConstructor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *str; - - if (argc == 0) { - ejsSetReturnValueToString(ejs, ""); - - } else if (argc == 1) { - /* MOB -- rc */ - str = ejsVarToString(ejs, argv[0]); - ejsSetReturnValueToString(ejs, str); - - } else { - ejsArgError(ejs, "usage: String([var])"); - return -1; - } - - return 0; -} - -/******************************************************************************/ -/******************************** Visible Methods *****************************/ -/******************************************************************************/ -/* - * Return a string containing the character at a given index - * - * String string.charAt(Number) - */ - -static int charAt(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsNum num; - char buf[2]; - - if (argc != 1) { - ejsArgError(ejs, "usage: charAt(integer)"); - return -1; - } - - num = ejsVarToNumber(argv[0]); - if (num < 0 || num >= thisObj->length) { - ejsError(ejs, EJS_RANGE_ERROR, "Bad index"); - return -1; - } - - mprAssert(ejsVarIsString(thisObj)); - - buf[0] = argv[0]->string[num]; - buf[1] = '\0'; - ejsSetReturnValueToString(ejs, buf); - - return 0; -} - -/******************************************************************************/ -/* - * Return an integer containing the character at a given index - * - * Number string.charCodeAt(Number) - */ - -static EjsNum charCodeAt(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsNum num; - - if (argc != 1) { - ejsArgError(ejs, "usage: charCodeAt(integer)"); - return -1; - } - - num = ejsVarToNumber(argv[0]); - if (num < 0 || num >= thisObj->length) { - ejsError(ejs, EJS_RANGE_ERROR, "Bad index"); - return -1; - } - ejsSetReturnValueToNumber(ejs, (EjsNum) argv[0]->string[num]); - - return 0; -} - -/******************************************************************************/ -/* - * Catenate - * - * String string.catenate(var, ...) - */ - -static int concat(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int i; - - if (argc == 0) { - ejsArgError(ejs, "usage: concat(String, ...)"); - return -1; - } - - mprAssert(ejsVarIsString(thisObj)); - - for (i = 0; i < argc; i++) { - if (ejsStrcat(ejs, thisObj, argv[i]) < 0) { - ejsMemoryError(ejs); - return -1; - } - } - ejsSetReturnValue(ejs, thisObj); - return 0; -} - -/******************************************************************************/ -/* - * Return the position of the first occurance of a substring - * - * Number string.indexOf(String subString [, Number start]) - */ - -static int indexOf(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *pat, *s1, *s2, *origin; - int start, i; - - if (argc == 0 || argc > 2) { - ejsArgError(ejs, "usage: indexOf(String [, Number])"); - return -1; - } - - pat = ejsVarToString(ejs, argv[0]); - - if (argc == 2) { - start = ejsVarToNumber(argv[1]); - if (start > thisObj->length) { - start = thisObj->length; - } - } else { - start = 0; - } - - i = start; - for (origin = &thisObj->string[i]; i < thisObj->length; i++, origin++) { - s1 = origin; - for (s2 = pat; *s1 && *s2; s1++, s2++) { - if (*s1 != *s2) { - break; - } - } - if (*s2 == '\0') { - ejsSetReturnValueToNumber(ejs, (EjsNum) (origin - thisObj->string)); - } - } - - ejsSetReturnValueToNumber(ejs, (EjsNum) -1); - return 0; -} - -/******************************************************************************/ -/* - * Return the position of the last occurance of a substring - * - * Number string.lastIndexOf(String subString [, Number start]) - */ - -static int lastIndexOf(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *pat, *s1, *s2, *origin; - int start; - - if (argc == 0 || argc > 2) { - ejsArgError(ejs, "usage: indexOf(String [, Number])"); - return -1; - } - - pat = ejsVarToString(ejs, argv[0]); - - if (argc == 2) { - start = ejsVarToNumber(argv[1]); - if (start > thisObj->length) { - start = thisObj->length; - } - } else { - start = 0; - } - - origin = &thisObj->string[thisObj->length - 1]; - for (; origin >= &thisObj->string[start]; origin--) { - - s1 = origin; - for (s2 = pat; *s1 && *s2; s1++, s2++) { - if (*s1 != *s2) { - break; - } - } - if (*s2 == '\0') { - ejsSetReturnValueToNumber(ejs, (EjsNum) (origin - thisObj->string)); - } - } - - ejsSetReturnValueToNumber(ejs, (EjsNum) -1); - return 0; -} - -/******************************************************************************/ -/* - * Return a substring - * - * Number string.slice(Number start, Number end) - */ - -static int slice(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsNum start, end; - - if (argc != 2) { - ejsArgError(ejs, "usage: slice(Number, Number)"); - return -1; - } - - start = ejsVarToNumber(argv[0]); - end = ejsVarToNumber(argv[1]); - if (start < 0 || start >= thisObj->length) { - ejsError(ejs, EJS_RANGE_ERROR, "Bad start index"); - return-1; - } - if (end < 0 || end >= thisObj->length) { - ejsError(ejs, EJS_RANGE_ERROR, "Bad end index"); - return -1; - } - - mprAssert(ejsVarIsString(thisObj)); - - ejsSetReturnValueToBinaryString(ejs, (uchar*) &thisObj->string[start], - end - start); - - return 0; -} - -/******************************************************************************/ -/* - * Split a string - * - * Number string.split(String delimiter [, Number limit]) - */ - -static int split(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *array, *vp; - char *delim, *last, *cp; - int len, limit, alloc; - - if (argc == 0 || argc > 2) { - ejsArgError(ejs, "usage: split(String [, Number])"); - return -1; - } - - delim = ejsVarToStringEx(ejs, argv[0], &alloc); - - limit = ejsVarToNumber(argv[1]); - - array = ejsCreateArray(ejs, 0); - - len = strlen(delim); - - last = thisObj->string; - for (cp = last; *cp; cp++) { - if (*cp == *delim && strncmp(cp, delim, len) == 0) { - if (cp > last) { - vp = ejsCreateBinaryStringVar(ejs, (uchar*) last, (cp - last)); - ejsAddArrayElt(ejs, array, vp, EJS_SHALLOW_COPY); - ejsFreeVar(ejs, vp); - } - } - } - - ejsSetReturnValue(ejs, array); - ejsFreeVar(ejs, array); - - if (alloc) { - mprFree(delim); - } - - return 0; -} - -/******************************************************************************/ -/* - * Create the object class - */ - -int ejsDefineStringClass(Ejs *ejs) -{ - EjsVar *sc; - - sc = ejsDefineClass(ejs, "String", "Object", ejsStringConstructor); - if (sc == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - ejsDefineCMethod(ejs, sc, "charAt", charAt, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "charCodeAt", charCodeAt, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "concat", concat, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "indexOf", indexOf, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "lastIndexOf", lastIndexOf, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "slice", slice, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "split", split, EJS_NO_LOCAL); -#if UNUSED - ejsDefineCMethod(ejs, sc, "match", match, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "replace", replace, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "search", search, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "substring", substring, EJS_NO_LOCAL); - // MOB bad name - ejsDefineCMethod(ejs, sc, "substr", substr, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "toLowerCase", toLowerCase, EJS_NO_LOCAL); - ejsDefineCMethod(ejs, sc, "toUpperCase", toUpperCase, EJS_NO_LOCAL); - - // Static method - ejsDefineCMethod(ejs, sc, "fromCharCode", fromCharCode, 0, EJS_NO_LOCAL); -#endif - - if (ejsObjHasErrors(sc)) { - ejsFreeVar(ejs, sc); - return MPR_ERR_CANT_CREATE; - } - return 0; -} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c b/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c deleted file mode 100644 index a2ef8d1390..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/classes/ejsXml.c +++ /dev/null @@ -1,1327 +0,0 @@ -/* - * @file ejsXml.c - * @brief E4X XML support - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/************************************ Doc *************************************/ -/* - * Javascript class definition - * - * class XML { - * public XML(); - * public XML(string xmlString); // "<tag... " - * public XML(string file); // "file" - * - * public void load(string file); - * public void save(string file); - * public Array children(); - * public Array attributes(); - * } - * - [[Internal Properties / Methods]] - - prototype - Ptr to class prototype (base class) - - class - Type of class - Object.prototype.toString - - Value - - - Get(name) - Returns the value - - Put(name, value) - Sets the value - - HasProperty(name) - Bool if property exists - - Delete(name) - Delete property - - DefaultValue(hint) - Return default primitive (not obj) value - toString, if result is obj, then call valueOf - if hint is number, then call valueOf, then toString - - Construct(arg list) - Constructor - - Call(arg list) - Function call - - HasInstance(value) - ?? - - Scope - Frame scope chain - - Match(string, index) - Regexp match - - - Example: - XML attribute @name - @* - * - var node = new XML("<order/>"); - Operators: - var prices = order..price; - var urgentItems = order.item(@level == "rush"); - var itemAttrs = order.item[0].@*; # @ for attributes - XML Literals - order.customer.address = - <address>..... - <zip>{zipCode}</zip> Where {var} is a JS var - <tag attribute={prefix}> ... Also for attributes - </address> - Omit namespaces - Example: - var html = <html/>; - html.head.title = "My title"; - head.body@bgcolor = "#e4e4e4"; -*/ - -/********************************** Includes **********************************/ - -#include "ejs.h" -#include "exml.h" - -/************************************ Data ************************************/ -#if BLD_FEATURE_EJS_E4X - -/* - * Per tag state - */ -typedef struct XmlTagState { - EjsVar *obj; - EjsVar *attributes; - EjsVar *comments; -} XmlTagState; - -/* - * Parser state - */ -typedef struct XmlState { - Ejs *ep; - EjsVar *xmlClass; - EjsVar *xmlListClass; - XmlTagState nodeStack[E4X_MAX_NODE_DEPTH]; - int topOfStack; - long inputSize; - long inputPos; - const char *inputBuf; - const char *fileName; -} XmlState; - -/****************************** Forward Declarations **************************/ -/* - * XML methods - */ -static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int name(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int save(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int toString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int valueOf(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); - -/* MOB -- temp */ -static int getList(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int setText(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); - -#if FUTURE -static int length(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int toXmlString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); - -static int appendChild(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int attributes(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int child(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int children(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int comments(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int decendants(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int elements(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int insertChildAfter(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int insertChildBefore(Ejs *ep, EjsVar *thisObj, int argc, - EjsVar **argv); -static int replace(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int setName(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv); -#endif - -/* - * Internal methods - */ -static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property); -static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property); -static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property); -static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value); -static int loadXmlString(Ejs *ep, EjsVar *thisObj, const char *xmlString); - -/* - * XMLList methods - */ -static EjsVar *createXmlListProperty(Ejs *ep, EjsVar *obj, - const char *property); -static int deleteXmlListProperty(Ejs *ep, EjsVar *obj, - const char *property); -static EjsVar *getXmlListProperty(Ejs *ep, EjsVar *obj, const char *property); -static EjsVar *setXmlListProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value); - -/* - * Misc - */ -static int readFileData(Exml *xp, void *data, char *buf, int size); -static int readStringData(Exml *xp, void *data, char *buf, int size); -static int parserHandler(Exml *xp, int state, const char *tagName, - const char *attName, const char *value); -static void termParser(Exml *xp); -static Exml *initParser(Ejs *ep, EjsVar *thisObj, const char *fileName); -static int getNumElements(EjsVar *obj); -static int getText(MprBuf *buf, EjsVar *obj); -static int xmlToString(Ejs *ep, MprBuf *buf, EjsVar *obj, int indentLevel); -static void indent(MprBuf *bp, int level); -static char *cleanTagName(char *name); - -/******************************************************************************/ -/* - * Define the E4X classes (XML, XMLList) - */ - -int ejsDefineXmlClasses(Ejs *ep) -{ - EjsMethods *methods; - EjsVar *xmlClass, *xmlListClass; - - /* - * Create the XML class - */ - xmlClass = ejsDefineClass(ep, "XML", "Object", ejsXmlConstructor); - if (xmlClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the XML class methods - */ - ejsDefineCMethod(ep, xmlClass, "text", text, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "name", name, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "load", load, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "save", save, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "toString", toString, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "valueOf", valueOf, EJS_NO_LOCAL); - -/* MOB -- temporary only */ - ejsDefineCMethod(ep, xmlClass, "getList", getList, EJS_NO_LOCAL); - ejsDefineCMethod(ep, xmlClass, "setText", setText, EJS_NO_LOCAL); - - /* - * Setup the XML internal methods. - */ - methods = mprAllocTypeZeroed(ep, EjsMethods); - xmlClass->objectState->methods = methods; - - methods->createProperty = createXmlProperty; - methods->deleteProperty = deleteXmlProperty; - methods->getProperty = getXmlProperty; - methods->setProperty = setXmlProperty; - - /* - * Create the XMLList class - */ - xmlListClass = ejsDefineClass(ep, "XMLList", "Array", - ejsXmlListConstructor); - - /* - * Define the XMLList class methods - */ - - /* - * Setup the XML internal methods. - */ - methods = mprAllocTypeZeroed(ep, EjsMethods); - xmlListClass->objectState->methods = methods; - - methods->createProperty = createXmlListProperty; - methods->deleteProperty = deleteXmlListProperty; - methods->getProperty = getXmlListProperty; - methods->setProperty = setXmlListProperty; - - /* MOB -- need to complete xmlListClass */ - - return (ejsObjHasErrors(xmlClass) || ejsObjHasErrors(xmlListClass)) - ? MPR_ERR_CANT_INITIALIZE : 0; - return 0; -} - -/******************************************************************************/ -/* - * Routine to create an XML object using a default constructor - */ - -EjsVar *ejsCreateXml(Ejs *ep) -{ - EjsVar *op; - - op = ejsCreateSimpleObj(ep, "XML"); - if (op == 0) { - mprAssert(op); - return op; - } - ejsSetVarName(ep, op, "xmlNode"); - - /* - * Invoke class constructors manually (for speed and space) - */ - if (ejsXmlConstructor(ep, op, 0, 0) < 0) { - mprFree(op); - mprAssert(0); - return 0; - } - return op; -} - -/******************************************************************************/ -/* - * XML constructor - */ - -int ejsXmlConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *vp; - const char *str; - - ejsSetVarFlags(thisObj, EJS_XML_FLAGS_ELEMENT); - - if (argc == 1) { - vp = argv[0]; - - if (ejsVarIsObject(vp)) { - /* Convert DOM to XML. Not implemented */; - - } else if (ejsVarIsString(vp)) { - str = vp->string; - if (str == 0) { - return 0; - } - if (*str == '<') { - /* XML Literal */ - return loadXmlString(ep, thisObj, str); - - } else { - /* Load from file */ - return load(ep, thisObj, argc, argv); - } - } else { - ejsError(ep, EJS_TYPE_ERROR, "Bad type passed to XML constructor"); - return -1; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Routine to create an XMLList object - */ - -EjsVar *ejsCreateXmlList(Ejs *ep) -{ - EjsVar *op; - - /* Sanity limit for size of hash table */ - - op = ejsCreateSimpleObj(ep, "XMLList"); - if (op == 0) { - mprAssert(0); - return op; - } - if (ejsArrayConstructor(ep, op, 0, 0) < 0 || - ejsXmlConstructor(ep, op, 0, 0) < 0) { - mprFree(op); - mprAssert(0); - return 0; - } - return op; -} - -/******************************************************************************/ -/* - * XMLList constructor - */ - -int ejsXmlListConstructor(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - // ejsSetVarFlags(vp, EJS_XML_FLAGS_ELEMENT); - return 0; -} - -/******************************************************************************/ -/******************************** Internal Methods ****************************/ -/******************************************************************************/ - -static EjsVar *createXmlProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsGetVarPtr(ejsCreateSimpleProperty(ep, obj, property)); -} - -/******************************************************************************/ - -static int deleteXmlProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsDeleteProperty(ep, obj, property); -} - -/******************************************************************************/ -/* MOB -- need ep as an arg */ -static EjsVar *getXmlProperty(Ejs *ep, EjsVar *obj, const char *property) -{ -#if NEW - EjsVar *lp; - - lp = ejsCreateXmlList(ep); - if (isdigit(*property)) { - /* MOB -- where do we store these. Do we need them ? */ - lp->targetObject = obj - lp->targetProperty = property - return getXmlListProperty(lp, property); - } - - /* What about a simple elment. Should it not return the text */ - - if (*property == '@') { - ap = ejsGetFirstProperty(obj, EJS_ENUM_ALL); - while (ap) { - vp = ejsGetVarPtr(ap); - /* MOB -- are attributes unique ? */ - if (vp->flags & EJS_XML_FLAGS_ATTRIBUTE && - strcmp(property, ap->name) == 0) { - ejsAppendXml(lp, vp); - } - ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL); - } - } else { - while (ap) { - vp = ejsGetVarPtr(ap); - /* MOB -- are attributes unique ? */ - if (vp->flags & EJS_XML_FLAGS_ELEMENT && - strcmp(property, ap->name) == 0) { - ejsAppendXml(lp, vp); - } - ap = ejsGetNexttProperty(ap, EJS_ENUM_ALL); - } - } - return l; - - // Must always return XML or XMLList event for comments and attributes -#endif - return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property)); -} - -/******************************************************************************/ - -static EjsVar *setXmlProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value) -{ - EjsProperty *pp; - EjsVar *vp; - - pp = ejsCreateSimpleProperty(ep, obj, property); - if (pp == 0) { - /* Should never happen */ - mprAssert(pp); - return 0; - } - vp = ejsGetVarPtr(pp); - if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0) { - return 0; - } - return ejsGetVarPtr(pp); -} - -/******************************************************************************/ -/* - NEW - -static EjsVar *setXmlProperty(Ejs *ep, EjsVar *op, const char *property, - EjsVar *value) -{ - - if ((value->objectState->baseClass != XML && - value->objectState->baseClass != XMLList) || - value->string[0] != '<') { - ejsVarToString(luevalue.toString(); - ejsRunMethod(ep, value, "toString", 0); - value = ejsDupVar(ep->result); - - } else { - value = ejsDupVar(value); - } - - if (isdigit(*property)) { - // ERROR -- reserved for future versions - return 0; - } - - if (*property == '@') { - if (op->objectState->baseClass == XMLList) { - if (op->obj.LENGTH_PROPERTY == 0) { - c = ""; - } else { - // Catenate all result of toString on all elts in list - } - } else { - c = c.toString(); - } - // Replace existing attribute of same name or insert - return; - } - for (i = op->obj.LENGTH - 1; i >= 0; i--) { - // Delete item of same name - } - if (not Found) { - Append new Xml object - - set [[name]], [[class]] == "element" - } - - mprFree(value); -} - - */ -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ - -static int load(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *fileName; - XmlState *parser; - Exml *xp; - MprFile *file; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: load(fileName);"); - return -1; - } - fileName = argv[0]->string; - - /* MOB -- not romable - Need rom code in MPR not MprServices - */ - file = mprOpen(ep, fileName, O_RDONLY, 0664); - if (file == 0) { - ejsError(ep, EJS_IO_ERROR, "Can't open: %s", fileName); - return -1; - } - - /* MOB -- should we empty thisObj of all existing properties ? */ - - xp = initParser(ep, thisObj, fileName); - parser = exmlGetParseArg(xp); - - exmlSetInputStream(xp, readFileData, (void*) file); - - if (exmlParse(xp) < 0) { - if (! ejsGotException(ep)) { - ejsError(ep, EJS_IO_ERROR, "Can't parse XML file: %s\nDetails %s", - fileName, exmlGetErrorMsg(xp)); - } - termParser(xp); - mprClose(file); - return -1; - } - - ejsSetReturnValue(ep, parser->nodeStack[0].obj); - - termParser(xp); - mprClose(file); - - return 0; -} - -/******************************************************************************/ - -static int loadXmlString(Ejs *ep, EjsVar *thisObj, const char *xmlString) -{ - XmlState *parser; - Exml *xp; - - xp = initParser(ep, thisObj, "string"); - parser = exmlGetParseArg(xp); - - parser->inputBuf = xmlString; - parser->inputSize = strlen(xmlString); - - exmlSetInputStream(xp, readStringData, (void*) 0); - - if (exmlParse(xp) < 0) { - if (! ejsGotException(ep)) { - ejsError(ep, EJS_IO_ERROR, "Can't parse XML string\nError %s", - exmlGetErrorMsg(xp)); - } - termParser(xp); - return -1; - } - - ejsSetReturnValue(ep, parser->nodeStack[0].obj); - - termParser(xp); - - return 0; -} - -/******************************************************************************/ - -static int text(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetSimpleProperty(ep, thisObj, E4X_TEXT_PROPERTY)); - if (vp == 0) { - ejsSetReturnValueToString(ep, ""); - return 0; - } - ejsSetReturnValue(ep, vp); - return 0; -} - -/******************************************************************************/ -/* - * Return the tag name - */ - -static int name(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetSimpleProperty(ep, thisObj, E4X_TAG_NAME_PROPERTY)); - if (vp == 0) { - ejsSetReturnValueToString(ep, ""); - return 0; - } - ejsSetReturnValue(ep, vp); -#if UNDEFINED - char *name; - /* MOB -- not ideal as we can't guarantee thisObj is a property */ - name = ejsGetPropertyPtr(thisObj)->name; - if (name == 0) { - name = ""; - } - ejsSetReturnValueToString(ep, name); -#endif - return 0; -} - -/******************************************************************************/ -/* MOB -- temporary only */ - -static int setText(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ep, "usage: setText(string)"); - } - - ejsSetProperty(ep, thisObj, E4X_TEXT_PROPERTY, argv[0]); - ejsSetReturnValue(ep, argv[0]); - return 0; -} - -/******************************************************************************/ - -static Exml *initParser(Ejs *ep, EjsVar *thisObj, const char *fileName) -{ - XmlState *parser; - Exml *xp; - - xp = exmlOpen(ep, 512, E4X_BUF_MAX); - mprAssert(xp); - - /* - * Create the parser stack - */ - parser = mprAllocTypeZeroed(ep, XmlState); - parser->ep = ep; - parser->nodeStack[0].obj = thisObj; - parser->xmlClass = ejsGetClass(ep, 0, "XML"); - parser->xmlListClass = ejsGetClass(ep, 0, "XMLList"); - parser->fileName = fileName; - - exmlSetParseArg(xp, parser); - exmlSetParserHandler(xp, parserHandler); - - return xp; -} - -/******************************************************************************/ - -static void termParser(Exml *xp) -{ - mprFree(exmlGetParseArg(xp)); - exmlClose(xp); -} - -/******************************************************************************/ -/* - * XML parsing callback. Called for each elt and attribute/value pair. - * For speed, we handcraft the object model here rather than calling - * putXmlProperty. - * - * "<!-- txt -->" parseHandler(efd, , EXML_COMMENT); - * "<elt" parseHandler(efd, , EXML_NEW_ELT); - * "...att=value" parseHandler(efd, , EXML_NEW_ATT); - * "<elt ...>" parseHandler(efd, , EXML_ELT_DEFINED); - * "<elt/>" parseHandler(efd, , EXML_SOLO_ELT_DEFINED); - * "<elt> ...<" parseHandler(efd, , EXML_ELT_DATA); - * "...</elt>" parseHandler(efd, , EXML_END_ELT); - * - * Note: we recurse on every new nested elt. - */ - -static int parserHandler(Exml *xp, int state, const char *tagName, - const char *attName, const char *value) -{ - XmlState *parser; - XmlTagState *tos; - EjsVar *currentNode, *vp, *tagNode, *parent, *vpx; - EjsProperty *pp; - Ejs *ep; - char *name; - - parser = (XmlState*) xp->parseArg; - ep = parser->ep; - tos = &parser->nodeStack[parser->topOfStack]; - currentNode = tos->obj; - - mprAssert(state >= 0); - mprAssert(tagName && *tagName); - - switch (state) { - case EXML_PI: - /* - * By using a property name with a leading space, we can store - * non-user-visible processing instructions as regular properties. - */ - pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, E4X_PI_PROPERTY); - ejsMakePropertyEnumerable(pp, 1); - vp = ejsGetVarPtr(pp); - ejsWriteVarAsString(ep, vp, value); - ejsSetVarFlags(vp, EJS_XML_FLAGS_PI); - break; - - case EXML_COMMENT: - /* - * By using a property name with a leading space, we can store - * non- user-visible comments as regular properties. - */ - pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, - E4X_COMMENT_PROPERTY); - ejsMakePropertyEnumerable(pp, 1); - vp = ejsGetVarPtr(pp); - ejsWriteVarAsString(ep, vp, value); - ejsSetVarFlags(vp, EJS_XML_FLAGS_COMMENT); - break; - - case EXML_NEW_ELT: - if (parser->topOfStack > E4X_MAX_NODE_DEPTH) { - ejsError(ep, EJS_IO_ERROR, - "XML nodes nested too deeply in %s at line %d", - parser->fileName, exmlGetLineNumber(xp)); - return MPR_ERR_BAD_SYNTAX; - } - - name = mprStrdup(xp, tagName); - if (name == 0) { - return MPR_ERR_MEMORY; - } - - if (cleanTagName(name) < 0) { - ejsError(ep, EJS_TYPE_ERROR, "Bad XML tag name in %s at %d", - parser->fileName, exmlGetLineNumber(xp)); - mprFree(name); - return MPR_ERR_BAD_SYNTAX; - } - - pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, name); - ejsMakePropertyEnumerable(pp, 1); - - tagNode = ejsGetVarPtr(pp); - - /* MOB -- OPT */ - vpx = ejsCreateXml(ep); - vp = ejsWriteVar(ep, tagNode, vpx, EJS_SHALLOW_COPY); - ejsMakeObjLive(vp, 1); - ejsFreeVar(ep, vpx); - - /* MOB -- return code */ - pp = ejsSetPropertyToString(ep, vp, E4X_TAG_NAME_PROPERTY, name); - ejsMakePropertyEnumerable(pp, 0); - - ejsSetVarFlags(vp, EJS_XML_FLAGS_ELEMENT); - ejsMakePropertyEnumerable(ejsGetPropertyPtr(vp), 1); - - tos = &parser->nodeStack[++(parser->topOfStack)]; - currentNode = tos->obj = vp; - tos->attributes = 0; - tos->comments = 0; - mprFree(name); - break; - - case EXML_NEW_ATT: - if (mprAllocSprintf(MPR_LOC_ARGS(xp), &name, 0, "@%s", attName) < 0) { - return MPR_ERR_MEMORY; - } - pp = ejsCreateProperty(ep, currentNode, name); - ejsMakePropertyEnumerable(pp, 1); - - vp = ejsGetVarPtr(pp); - ejsWriteVarAsString(ep, vp, value); - ejsSetVarFlags(vp, EJS_XML_FLAGS_ATTRIBUTE); - mprFree(name); - break; - - case EXML_SOLO_ELT_DEFINED: - parser->topOfStack--; - mprAssert(parser->topOfStack >= 0); - tos = &parser->nodeStack[parser->topOfStack]; - break; - - case EXML_ELT_DEFINED: - if (parser->topOfStack > 0) { - parent = parser->nodeStack[parser->topOfStack - 1].obj; - ejsSetProperty(ep, currentNode, E4X_PARENT_PROPERTY, parent); - } - break; - - case EXML_ELT_DATA: - case EXML_CDATA: - pp = ejsCreateSimpleNonUniqueProperty(ep, currentNode, - E4X_TEXT_PROPERTY); - ejsMakePropertyEnumerable(pp, 1); - vp = ejsGetVarPtr(pp); - ejsWriteVarAsString(ep, vp, value); - ejsSetVarFlags(vp, EJS_XML_FLAGS_TEXT); - break; - - case EXML_END_ELT: - /* - * This is the closing element in a pair "<x>...</x>". - * Pop the stack frame off the elt stack - */ - parser->topOfStack--; - mprAssert(parser->topOfStack >= 0); - tos = &parser->nodeStack[parser->topOfStack]; - break; - - default: - ejsError(ep, EJS_IO_ERROR, "XML error in %s at %d\nDetails %s", - parser->fileName, exmlGetLineNumber(xp), exmlGetErrorMsg(xp)); - mprAssert(0); - return MPR_ERR_BAD_SYNTAX; - } - return 0; -} - -/******************************************************************************/ - -static char *cleanTagName(char *name) -{ - char *cp; - - for (cp = name; *cp; cp++) { - if (*cp == ':') { - *cp = '_'; - } else if (!isalnum(*cp) && *cp != '_' && *cp != '$' && *cp != '@') { - return 0; - } - } - return name; -} - -/******************************************************************************/ - -static int readFileData(Exml *xp, void *data, char *buf, int size) -{ - mprAssert(xp); - mprAssert(data); - mprAssert(buf); - mprAssert(size > 0); - - return mprRead((MprFile*) data, buf, size); -} - -/******************************************************************************/ - -static int readStringData(Exml *xp, void *data, char *buf, int size) -{ - XmlState *parser; - int rc, len; - - mprAssert(xp); - mprAssert(buf); - mprAssert(size > 0); - - parser = (XmlState*) xp->parseArg; - - if (parser->inputPos < parser->inputSize) { - len = min(size, (parser->inputSize - parser->inputPos)); - rc = mprMemcpy(buf, size, &parser->inputBuf[parser->inputPos], len); - parser->inputPos += len; - return rc; - } - return 0; -} - -/******************************************************************************/ - -static int save(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *fileName; - MprBuf *buf; - MprFile *file; - int bytes, len; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ep, EJS_ARG_ERROR, "Bad args. Usage: save(fileName);"); - return -1; - } - fileName = argv[0]->string; - - /* MOB -- not romable - Need rom code in MPR not MprServices - */ - - /* - * Convert to a string - */ - buf = mprCreateBuf(ep, E4X_BUF_SIZE, E4X_BUF_MAX); - if (xmlToString(ep, buf, thisObj, -1) < 0) { - mprFree(buf); - return -1; - } - - file = mprOpen(ep, fileName, - O_CREAT | O_TRUNC | O_WRONLY | O_TEXT, 0664); - if (file == 0) { - ejsError(ep, EJS_IO_ERROR, "Can't open: %s, %d", fileName, - mprGetOsError()); - return -1; - } - - len = mprGetBufLength(buf); - bytes = mprWrite(file, buf->start, len); - if (bytes != len) { - ejsError(ep, EJS_IO_ERROR, "Can't write to: %s", fileName); - mprClose(file); - return -1; - } - mprWrite(file, "\n", 1); - mprFree(buf); - - mprClose(file); - - return 0; -} - -/******************************************************************************/ - -static int toString(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprBuf *buf; - - buf = mprCreateBuf(ep, E4X_BUF_SIZE, E4X_BUF_MAX); - - if (xmlToString(ep, buf, thisObj, -1) < 0) { - mprFree(buf); - return -1; - } - ejsWriteVarAsString(ep, ep->result, (char*) buf->start); - - mprFree(buf); - - return 0; -} - -/******************************************************************************/ -/* MOB -- need to support XMLList */ - -static int xmlToString(Ejs *ep, MprBuf *buf, EjsVar *obj, int indentLevel) -{ - EjsProperty *pp; - EjsVar *vp; - char *varBuf; - int endTag, sawElements; - - if (indentLevel < 0) { - mprPutStringToBuf(buf, "<?xml version=\"1.0\"?>"); - } - - switch (obj->type) { - case EJS_TYPE_STRING: - if (obj->flags & EJS_XML_FLAGS_ATTRIBUTE) { - mprPutFmtStringToBuf(buf, " %s=\"%s\"", - &ejsGetPropertyPtr(obj)->name[1], obj->string); - /* No new line */ - - } else if (obj->flags & EJS_XML_FLAGS_COMMENT) { - mprPutCharToBuf(buf, '\n'); - indent(buf, indentLevel); - mprPutFmtStringToBuf(buf, "<!-- %s -->", obj->string); - - } else if (obj->flags & EJS_XML_FLAGS_TEXT) { - mprPutStringToBuf(buf, obj->string); - - } else { -// indent(buf, indentLevel); - mprPutStringToBuf(buf, obj->string); -// mprPutCharToBuf(buf, '\n'); - } - break; - - default: - /* Primitive types come here */ - indent(buf, indentLevel); - /* MOB -- rc */ - varBuf = ejsVarToString(ep, obj); - mprPutStringToBuf(buf, varBuf); - break; - - case EJS_TYPE_OBJECT: - if (obj->objectState->baseClass == ejsGetClass(ep, 0, "XML")) { - if (!obj->objectState->visited) { - obj->objectState->visited = 1; - - /* MOB -- opt. Flags would be quicker */ - if (strcmp(ejsGetPropertyPtr(obj)->name, - E4X_PARENT_PROPERTY) == 0) { - return 0; - } - /* - * MOB -- short term fix for tags with no body but with - * attributes - */ - if (getNumElements(obj) == 0 && 0) { - /* - * XML element is simple with no elements, so return just - * the text. - */ - if (getText(buf, obj) < 0) { - ejsError(ep, EJS_IO_ERROR, - "XML is to big to convert to a string"); - obj->objectState->visited = 0; - return -1; - } - - } else if (obj->flags & (EJS_XML_FLAGS_ELEMENT)) { - /* - * XML object is complex (has elements) so return full XML - * content. - */ - mprPutCharToBuf(buf, '\n'); - indent(buf, indentLevel); - - /* - * When called from toString, obj is not a property - */ - if (indentLevel >= 0) { - mprPutFmtStringToBuf(buf, "<%s", - ejsGetPropertyPtr(obj)->name); - endTag = 0; - - } else { - endTag = 1; - } - - sawElements = 0; - pp = ejsGetFirstProperty(obj, 0); - while (pp) { - vp = ejsGetVarPtr(pp); - - if (! (vp->flags & EJS_XML_FLAGS_ATTRIBUTE)) { - if (endTag == 0) { - endTag++; - mprPutStringToBuf(buf, ">"); - } - } - if (vp->flags & EJS_XML_FLAGS_ELEMENT) { - if (strcmp(ejsGetPropertyPtr(vp)->name, - E4X_PARENT_PROPERTY) != 0) { - sawElements++; - } - } - - if (xmlToString(ep, buf, ejsGetVarPtr(pp), - indentLevel + 1) < 0){ - return -1; - } - - pp = ejsGetNextProperty(pp, 0); - } - if (indentLevel >= 0) { - if (sawElements) { - mprPutCharToBuf(buf, '\n'); - indent(buf, indentLevel); - } - mprPutFmtStringToBuf(buf, "</%s>", - ejsGetPropertyPtr(obj)->name); - } - } - obj->objectState->visited = 0; - } - return 0; - } - - if (obj->objectState->baseClass == ejsGetClass(ep, 0, "XMLList")) { - indent(buf, indentLevel); - /* MOB -- TBD */ - return 0; - } - - /* - * All other objects. Allow other objects to override toString - */ - if (ejsRunMethod(ep, obj->objectState->baseClass, "toString", - 0) < 0) { - return -1; - } - if (ejsVarIsString(ep->result)) { - indent(buf, indentLevel); - mprPutStringToBuf(buf, obj->string); - } - break; - } - return 0; -} - -/******************************************************************************/ - -static void indent(MprBuf *bp, int level) -{ - int i; - - for (i = 0; i < level; i++) { - mprPutCharToBuf(bp, '\t'); - } -} - -/******************************************************************************/ - -static int valueOf(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 0) { - mprAssert(0); - return -1; - } - - switch (thisObj->type) { - default: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_OBJECT: - case EJS_TYPE_METHOD: - case EJS_TYPE_STRING_CMETHOD: - ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY); - break; - - case EJS_TYPE_STRING: - ejsWriteVarAsInteger(ep, ep->result, atoi(thisObj->string)); - break; - - case EJS_TYPE_BOOL: - case EJS_TYPE_INT: -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: -#endif -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: -#endif - ejsWriteVar(ep, ep->result, thisObj, EJS_SHALLOW_COPY); - break; - } - return 0; -} - -/******************************************************************************/ - -static int getList(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *nodeName; - EjsProperty *pp; - EjsVar *list, *vp; - - if (argc != 1) { - nodeName = 0; - } else { - nodeName = argv[0]->string; - } - - list = ejsCreateArray(ep, 0); - - pp = ejsGetFirstProperty(thisObj, EJS_ENUM_ALL); - while (pp) { - vp = ejsGetVarPtr(pp); - if (vp->type == EJS_TYPE_OBJECT) { - if (strcmp(ejsGetPropertyPtr(vp)->name, E4X_PARENT_PROPERTY) != 0) { - if (vp->flags & EJS_XML_FLAGS_ELEMENT && - (nodeName == 0 || strcmp(nodeName, pp->name) == 0)) { - ejsAddArrayElt(ep, list, vp, EJS_SHALLOW_COPY); - } - } - } - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - - ejsSetReturnValueAndFree(ep, list); - return 0; -} - -/******************************************************************************/ - -static int getNumElements(EjsVar *obj) -{ - EjsProperty *pp; - int count; - - count = 0; - pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL); - while (pp) { - if (ejsGetVarPtr(pp)->flags & EJS_XML_FLAGS_ELEMENT) { - count++; - } - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - return count; -} - -/******************************************************************************/ -/* MOB - This needs to be a public method */ - -static int getText(MprBuf *buf, EjsVar *obj) -{ - EjsProperty *pp; - EjsVar *vp; - - pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL); - while (pp) { - vp = ejsGetVarPtr(pp); - if (vp->flags & EJS_XML_FLAGS_TEXT) { - /* MOB -- should test for overflow */ - mprPutStringToBuf(buf, vp->string); - } - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - return 0; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************** Internal Methods ****************************/ -/******************************************************************************/ - -static EjsVar *createXmlListProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsGetVarPtr(ejsCreateProperty(ep, obj, property)); -} - -/******************************************************************************/ - -static int deleteXmlListProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - return ejsDeleteProperty(ep, obj, property); -} - -/******************************************************************************/ - -static EjsVar *getXmlListProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - // Must always return XML or XMLList event for comments and attributes - return ejsGetVarPtr(ejsGetSimpleProperty(ep, obj, property)); -} - -/******************************************************************************/ - -static EjsVar *setXmlListProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value) -{ - EjsProperty *pp; - EjsVar *vp; - - pp = ejsGetSimpleProperty(ep, obj, property); - if (pp == 0) { - mprAssert(pp); - return 0; - } - vp = ejsGetVarPtr(pp); - if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) < 0){ - mprAssert(0); - return 0; - } - return ejsGetVarPtr(pp); -} - -/******************************************************************************/ -/* - NEW - -static EjsVar *putXmlListProperty(EjsVar *op, const char *property, - EjsVar *value) -{ - - if ((value->objectState->baseClass != XML && - value->objectState->baseClass != XMLList) || - value->string[0] != '<') { - c = value.toString(); - } else { - value = ejsDupVar(value); - ?? - } - if (isdigit(*property)) { - // ERROR - return 0; - } - if (*property == '@') { - if (op->objectState->baseClass == XMLList) { - if (op->obj.LENGTH_PROPERTY == 0) { - c = ""; - } else { - // Catenate all result of toString on all elts in list - } - } else { - c = c.toString(); - } - // Replace existing attribute of same name or insert - return; - } - for (i = op->obj.LENGTH - 1; i >= 0; i--) { - // Delete item of same name - } - if (not Found) { - Append new Xml object - - set [[name]], [[class]] == "element" - } -} - - */ - -/******************************************************************************/ -#else -void ejs4xDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS_E4X */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejs.c b/source4/lib/appweb/ejs-2.0/ejs/ejs.c deleted file mode 100644 index 0fcc6f0545..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejs.c +++ /dev/null @@ -1,1378 +0,0 @@ -/* - * @file ejs.c - * @brief Embedded JavaScript (EJS) - * @overview Main module interface logic. - * @remarks The initialization code must be run single-threaded. Includes: - * ejsOpen, ejsClose. - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/************************************* Code ***********************************/ -/* - * Initialize the EJS subsystem - */ - -EjsService *ejsOpenService(MprCtx ctx) -{ - EjsService *service; - Ejs *interp; - - service = mprAllocTypeZeroed(ctx, EjsService); - if (service == 0) { - mprError(ctx, MPR_LOC, "Can't allocate service memory"); - return 0; - } - - interp = ejsCreateInterp(service, 0, 0, 0, 1); - if (interp == 0) { - mprError(ctx, MPR_LOC, "Can't create master interpreter"); - mprFree(service); - return 0; - } - service->master = interp; - - /* - * Restore the default GC settings for the master interpreter. - * ejsCreateInterp will have initialized them. - */ - ejsGCInit(interp, EJS_DEFAULT_OBJ_INC, EJS_DEFAULT_PROP_INC, - EJS_DEFAULT_VAR_INC, EJS_DEFAULT_STR_INC); - - /* - * Save the default interpreter and global class for all to access - * MOB -- don't store these. Store the service - */ - mprSetKeyValue(interp, "ejsMaster", interp); - mprSetKeyValue(interp, "ejsGlobalClass", interp->global); - - /* - * Once the Object class is created, this routine will also make the - * Global class a subclass of Object. - */ - if (ejsDefineObjectClass(interp) < 0) { - mprError(ctx, MPR_LOC, "Can't define EJS object class"); - mprFree(service); - return 0; - } - - /* - * Create all the standard classes - */ - if (ejsDefineStandardClasses(interp) < 0) { - mprError(ctx, MPR_LOC, "Can't define EJS standard classes"); - mprFree(service); - return 0; - } - - if (ejsDefineSystemClasses(interp) < 0) { - mprError(ctx, MPR_LOC, "Can't define EJS system classes"); - mprFree(service); - return 0; - } - - if (ejsCreateObjectModel(interp) < 0) { - mprError(ctx, MPR_LOC, "Can't create EJS object model"); - mprFree(service); - return 0; - } - -#if UNUSED && BLD_FEATURE_ALLOC_STATS -{ - EjsVar v; - mprLog(ctx, 0, "Obj %d, Var %d, Prop %d\n", sizeof(EjsObj), sizeof(EjsVar), - sizeof(EjsProperty)); - mprLog(ctx, 0, "GCLink %d\n", sizeof(EjsGCLink)); - mprLog(ctx, 0, "objectState %d\n", (uint) &v.objectState - (uint) &v); -} -#endif - - return service; -} - -/******************************************************************************/ -/* - * Close down the EJS Service - */ - -void ejsCloseService(EjsService *sp, bool doStats) -{ - Ejs *ep; - - mprAssert(sp); - - ep = sp->master; - mprAssert(ep); - - ejsTermSystemClasses(ep); - - if (ep) { - ejsFreeVar(ep, sp->globalClass); - -#if BLD_FEATURE_ALLOC_STATS - if (doStats) { - mprLog(sp, 0, "GC Statistics for the Global Interpreter"); - } -#endif - ejsDestroyInterp(ep, doStats); - } - - mprRemoveKeyValue(sp, "ejsMaster"); - mprRemoveKeyValue(sp, "ejsGlobalClass"); - - mprFree(sp); -} - -/******************************************************************************/ - -Ejs *ejsGetMasterInterp(EjsService *sp) -{ - return sp->master; -} - -/******************************************************************************/ -#if BLD_FEATURE_MULTITHREAD - -int ejsSetServiceLocks(EjsService *sp, EjsLockFn lock, EjsUnlockFn unlock, - void *data) -{ - mprAssert(sp); - - sp->lock = lock; - sp->unlock = unlock; - sp->lockData = data; - return 0; -} - -#endif -/******************************************************************************/ -/* - * Create and initialize an EJS interpreter. Interpreters have a global object - * that has the service global class set as a base class. This way, it - * inherits all the desired global properties, methods and classes. - * - * The primary and alternate handles are provided to C methods depending on - * the flags provided when the C methods are defined. The global variable - * (optionally) defines a predefined global variable space. - */ - -Ejs *ejsCreateInterp(EjsService *sp, void *primaryHandle, void *altHandle, - EjsVar *global, bool useOwnSlab) -{ - EjsProperty *pp; - EjsVar *baseClass; - Ejs *ep; - - ep = mprAllocTypeZeroed(sp, Ejs); - if (ep == 0) { - mprAssert(0); - return ep; - } - - ep->stkPtr = &ep->stack[EJS_MAX_STACK]; - - ep->service = sp; - ep->primaryHandle = primaryHandle; - ep->altHandle = altHandle; - - if (sp->master) { - ep->objectClass = sp->master->objectClass; - } - - if (useOwnSlab) { - ep->slabs = (EjsSlab*) mprAllocZeroed(ep, sizeof(EjsSlab) * - EJS_SLAB_MAX); - ep->slabAllocContext = ep; - - } else { - ep->slabs = sp->master->slabs; - ep->slabAllocContext = sp->master; - ep->flags |= EJS_FLAGS_SHARED_SLAB; - } - - ep->frames = mprCreateItemArray(ep, EJS_INC_FRAMES, EJS_MAX_FRAMES); - if (ep->frames == 0) { - mprFree(ep); - return 0; - } - - ejsGCInit(ep, EJS_OBJ_INC, EJS_PROP_INC, EJS_VAR_INC, EJS_STR_INC); - - if (sp->globalClass == 0) { - /* - * Only do this for the Global interpreter. Create a global class - * (prototype) object. This is base class from which all global - * spaces will inherit. - */ - sp->globalClass = ejsCreateObjVar(ep); - if (sp->globalClass == 0) { - mprFree(ep); - return 0; - } - ejsSetClassName(ep, sp->globalClass, "Global"); - global = sp->globalClass; - } - - if (global) { - /* - * The default interpreter uses the Global class as its global - * space. - */ - ep->global = ejsDupVar(ep, global, EJS_SHALLOW_COPY); - if (ep->global == 0) { - mprFree(ep); - return 0; - } - if (ep->global->objectState != sp->globalClass->objectState) { - ejsSetBaseClass(ep->global, sp->globalClass); - } - - } else { - /* - * Use the global class as our global so we can find the object class - */ - baseClass = ejsGetClass(ep, sp->globalClass, "Object"); - if (baseClass) { - ep->global = ejsCreateSimpleObjUsingClass(ep, baseClass); - if (ep->global == 0) { - mprFree(ep); - return 0; - } - - /* - * Override the base class and set to the master Global class - */ - ejsSetBaseClass(ep->global, sp->globalClass); - - } else { - ep->global = ejsCreateObjVar(ep); - } - } - - /* - * The "global" variable points to the global space - */ - pp = ejsSetProperty(ep, ep->global, "global", ep->global); - if (pp == 0) { - mprFree(ep); - return 0; - } - ejsMakePropertyEnumerable(pp, 0); - - /* - * The "Global" variable points to the Global class - */ - pp = ejsSetProperty(ep, ep->global, "Global", sp->globalClass); - if (pp == 0) { - mprFree(ep); - return 0; - } - ejsMakePropertyEnumerable(pp, 0); - - ep->local = ejsDupVar(ep, ep->global, EJS_SHALLOW_COPY); - if (ep->frames == 0 || ep->global == 0 || ep->local == 0) { - mprFree(ep); - return 0; - } - ejsSetVarName(ep, ep->local, "topLevelLocal"); - - if (mprAddItem(ep->frames, ep->global) < 0 || - mprAddItem(ep->frames, ep->local) < 0) { - mprFree(ep); - return 0; - } - - ep->result = ejsCreateUndefinedVar(ep); - if (ep->result == 0) { - mprFree(ep); - return 0; - } - - return ep; -} - -/******************************************************************************/ -/* - * Close an EJS interpreter - */ - -void ejsDestroyInterp(Ejs *ep, bool doStats) -{ - ejsCleanInterp(ep, doStats); - - mprFree(ep); -} - -/******************************************************************************/ -/* - * Clean an EJS interpreter of all allocated variables, but DONT destroy. - * We use this rather than DestroyInterp so we delay freeing the Ejs struct - * until after the service is closed. - */ - -void ejsCleanInterp(Ejs *ep, bool doStats) -{ - int i; - - if (ep->global) { - ejsDeleteProperty(ep, ep->local, "global"); - ejsDeleteProperty(ep, ep->global, "global"); - ep->global = 0; - } - if (ep->local) { - ejsFreeVar(ep, ep->local); - ep->local = 0; - } - if (ep->global) { - ejsFreeVar(ep, ep->global); - ep->global = 0; - } - if (ep->result) { - ejsFreeVar(ep, ep->result); - ep->result = 0; - } - if (ep->castAlloc && ep->castTemp) { - mprFree(ep->castTemp); - ep->castTemp = 0; - } - if (ep->frames) { - for (i = ep->frames->length - 1; i >= 0; i--) { - mprRemoveItemByIndex(ep->frames, i); - } - mprFree(ep->frames); - ep->frames = 0; - } - - if (doStats) { - -#if BLD_FEATURE_ALLOC_STATS - mprLog(ep, 0, " "); - mprLog(ep, 0, "GC Statistics for Interpreter (0x%X)", (uint) ep); -#endif - - /* - * Cleanup before printing the alloc report - */ - ejsSetGCDebugLevel(ep, 3); - ejsCollectGarbage(ep, -1); - -#if BLD_DEBUG - /* - * If we are the master, dump objects - */ - if (ep->service->master == ep) { - ejsDumpObjects(ep); - } -#endif - -#if BLD_FEATURE_ALLOC_STATS - /* - * Print an alloc report. 1 == do leak report - */ - ejsPrintAllocReport(ep, 1); -#endif - - } else { - /* - * Must collect garbage here incase sharing interpreters with the - * master. If we don't, the mprFree later in DestroyInterp will free - * all memory and when the master does GC --> crash. - */ - ejsCollectGarbage(ep, -1); - } -} - -/******************************************************************************/ -/* - * Evaluate an EJS script file. This will evaluate the script at the current - * context. Ie. if inside a function, declarations will be local. - */ - -int ejsEvalFile(Ejs *ep, const char *path, EjsVar *result) -{ - MprFile *file; - MprFileInfo info; - char *script; - char *saveFileName; - int rc; - - mprAssert(path && *path); - - if ((file = mprOpen(ep, path, O_RDONLY | O_BINARY, 0666)) == 0) { - ejsError(ep, EJS_IO_ERROR, "Can't open %s", path); - return -1; - } - - if (mprGetFileInfo(ep, path, &info) < 0) { - ejsError(ep, EJS_IO_ERROR, "Can't get file info for %s", path); - goto error; - } - - if ((script = (char*) mprAlloc(ep, info.size + 1)) == NULL) { - ejsError(ep, "MemoryError", "Cant malloc %d", (int) info.size); - goto error; - } - - if (mprRead(file, script, info.size) != (int) info.size) { - mprFree(script); - ejsError(ep, EJS_IO_ERROR, "Error reading %s", path); - goto error; - } - mprClose(file); - script[info.size] = '\0'; - - saveFileName = ep->fileName; - ep->fileName = mprStrdup(ep, path); - - rc = ejsEvalScript(ep, script, result); - mprFree(script); - - mprFree(ep->fileName); - ep->fileName = saveFileName; - - return rc; - -/* - * Error return - */ -error: - mprClose(file); - return -1; -} - -/******************************************************************************/ -/* - * Create a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsOpenBlock(Ejs *ep) -{ - EjsProperty *pp; - int fid; - - ep->local = ejsCreateSimpleObj(ep, "Object"); - ejsSetVarName(ep, ep->local, "local"); - - if (ep->local == 0) { - ejsMemoryError(ep); - return -1; - } - - if (ep->frames->length > EJS_MAX_FRAMES && !ep->gotException) { - ejsError(ep, EJS_RANGE_ERROR, "Recursion too deep: Max depth %d", - EJS_MAX_FRAMES); - return -1; - } - - /* - * Must add to frames before ejsSetProperty which will make the object live - */ - fid = mprAddItem(ep->frames, ep->local); - if (fid < 0) { - ejsMemoryError(ep); - return -1; - } - - /* Self reference */ - pp = ejsSetProperty(ep, ep->local, "local", ep->local); - ejsMakePropertyEnumerable(pp, 0); - - return fid; -} - -/******************************************************************************/ -/* - * Set a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsSetBlock(Ejs *ep, EjsVar *local) -{ - ep->local = ejsDupVar(ep, local, EJS_SHALLOW_COPY); - ejsMakeObjPermanent(ep->local, 1); - return mprAddItem(ep->frames, ep->local); -} - -/******************************************************************************/ -/* - * Close a variable scope block opened via ejsOpenBlock. Pop back the old - * local variables frame. - */ - -int ejsCloseBlock(Ejs *ep, int fid) -{ - mprAssert(ep->local >= 0); - mprAssert(fid >= 0); - - mprAssert(ep->local == (EjsVar*) mprGetItem(ep->frames, fid)); - - if (ep->local) { - /* Allow GC */ - ejsMakeObjPermanent(ep->local, 0); - ejsFreeVar(ep, ep->local); - } - - mprRemoveItemByIndex(ep->frames, fid); - - ep->local = (EjsVar*) mprGetItem(ep->frames, - mprGetItemCount(ep->frames) - 1); - - return 0; -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All frames - * created during this context will be automatically deleted when complete. - * vp is optional. i.e. created local variables will be discarded - * when this routine returns. - */ - -int ejsEvalBlock(Ejs *ep, char *script, EjsVar *vp) -{ - int rc, fid; - - mprAssert(script); - - fid = ejsOpenBlock(ep); - if (fid < 0) { - return fid; - } - - rc = ejsEvalScript(ep, script, vp); - - ejsCloseBlock(ep, fid); - - return rc; -} - -/******************************************************************************/ -/* - * Parse and evaluate a EJS. The script is evaluated at the current context. - * Return the result in *vp. The result is "owned" by EJ and the caller - * must not free it. Returns -1 on errors and zero for success. - */ - -int ejsEvalScript(Ejs *ep, const char *script, EjsVar *vp) -{ - int state; - - ejsClearVar(ep, ep->result); - ep->gotException = 0; - - if (script == 0) { - return 0; - } - - /* - * Allocate a new evaluation block, and save the old one - */ - if (ejsLexOpenScript(ep, script) < 0) { - return MPR_ERR_MEMORY; - } - - /* - * Do the actual parsing and evaluation - */ - ep->scriptStatus = 0; - - do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); - - if (state == EJS_STATE_RET) { - state = EJS_STATE_EOF; - } - } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); - - ejsLexCloseScript(ep); - - if (state == EJS_STATE_ERR) { - return -1; - } - - if (vp) { - /* Caller must not free. */ - *vp = *ep->result; - } - - return ep->scriptStatus; -} - -/******************************************************************************/ - -void ejsSetFileName(Ejs *ep, const char *fileName) -{ - mprFree(ep->fileName); - ep->fileName = mprStrdup(ep, fileName); -} - -/******************************************************************************/ -/* - * Format the stack backtrace - */ - -char *ejsFormatStack(Ejs* ep) -{ - EjsInput *ip; - char *errbuf; - int frame, len; - - mprAssert(ep); - - ip = ep->input; - - errbuf = 0; - - len = 0; - frame = 0; - while (ip && frame < EJS_MAX_BACKTRACE) { - char *traceLine, *newErrbuf, *line; - for (line = ip->line; *line && isspace(*line); line++) { - ; - } - mprAllocSprintf(MPR_LOC_ARGS(ep), &traceLine, MPR_MAX_STRING, - " [%02d] %s, %s, line %d -> %s\n", - frame++, - ip->fileName ? ip->fileName : "script", - ip->procName ? ip->procName: "global", - ip->lineNumber, line); - if (traceLine == 0) { - break; - } - newErrbuf = mprRealloc(ep, errbuf, len + strlen(traceLine) + 1); - if (newErrbuf == NULL) { - break; - } - errbuf = newErrbuf; - memcpy(&errbuf[len], traceLine, strlen(traceLine) + 1); - len += strlen(traceLine); - mprFree(traceLine); - ip = ip->next; - } - return errbuf; -} - -/******************************************************************************/ -/* - * Internal use method to set the error message - * - * Error, ArgError, AssertError, IOError, MemoryError, RangeError, - * ReferenceError, SyntaxError, TypeError, MemoryError - */ - -void ejsError(Ejs* ep, const char *errorType, const char* fmt, ...) -{ - va_list fmtArgs; - EjsVar *error; - char *msg, *stack; - - va_start(fmtArgs, fmt); - mprAllocVsprintf(MPR_LOC_ARGS(ep), &msg, MPR_MAX_STRING, fmt, fmtArgs); - va_end(fmtArgs); - - /* - * Create a new Error exception object. If bad error type, default to - * "Error" - */ - if (ejsGetClass(ep, 0, errorType) == 0) { - errorType = "Error"; - } - ep->gotException = 1; - - error = ejsCreateObj(ep, 0, errorType, msg); - if (error == 0) { - return; - } - mprFree(msg); - - stack = ejsFormatStack(ep); - ejsSetPropertyToString(ep, error, "stack", stack); - mprFree(stack); - - ejsWriteVar(ep, ep->result, error, EJS_SHALLOW_COPY); - ejsFreeVar(ep, error); -} - -/******************************************************************************/ - -void ejsSyntaxError(Ejs *ep, const char *msg) -{ - if (msg == 0) { - msg = " "; - } - ejsError(ep, EJS_SYNTAX_ERROR, msg); -} - -/******************************************************************************/ - -void ejsMemoryError(Ejs *ep) -{ - ejsError(ep, EJS_MEMORY_ERROR, "Memory allocation error"); -} - -/******************************************************************************/ - -void ejsArgError(Ejs *ep, const char *msg) -{ - mprAssert(msg && *msg); - - ejsError(ep, EJS_ARG_ERROR, msg); -} - -/******************************************************************************/ - -void ejsInternalError(Ejs *ep, const char *msg) -{ - mprAssert(msg && *msg); - - ejsError(ep, EJS_INTERNAL_ERROR, msg); -} - -/******************************************************************************/ -/* - * Public routine to set the error message. Caller MUST NOT free. - */ - -char *ejsGetErrorMsg(Ejs *ep) -{ - EjsVar *error; - const char *message, *stack, *name; - char *buf; - - error = ep->result; - - if (! ejsVarIsObject(error)) { - name = message = stack = 0; - } else { - name = ejsGetPropertyAsString(ep, error, "name"); - message = ejsGetPropertyAsString(ep, error, "message"); - stack = ejsGetPropertyAsString(ep, error, "stack"); - } - if (name == 0 || message == 0) { - buf = mprStrdup(ep, "Unspecified execution error\n"); - } else { - mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, - "%s Exception: %s\nStack:\n%s\n", - name, message, stack ? stack : " " ); - } - mprFree(ep->errorMsg); - ep->errorMsg = buf; - return buf; -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejsGetLineNumber(Ejs *ep) -{ - if (ep->input == 0) { - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Return the local object - */ - -EjsVar *ejsGetLocalObj(Ejs *ep) -{ - return ep->local; -} - -/******************************************************************************/ -/* - * Return the global object - */ - -EjsVar *ejsGetGlobalObj(Ejs *ep) -{ - return ep->global; -} - -/******************************************************************************/ -/* - * Set the expression return value - */ - -void ejsSetReturnValue(Ejs *ep, EjsVar *vp) -{ - mprAssert(ep); - mprAssert(vp); - - if (vp == 0) { - return; - } - ejsWriteVar(ep, ep->result, vp, EJS_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Set the expression return value and free the arg. - */ - -void ejsSetReturnValueAndFree(Ejs *ep, EjsVar *vp) -{ - mprAssert(ep); - mprAssert(vp); - - ejsWriteVar(ep, ep->result, vp, EJS_SHALLOW_COPY); - ejsFreeVar(ep, vp); -} - -/******************************************************************************/ -/* - * Set the expression return value to a string value. - */ - -void ejsSetReturnValueToString(Ejs *ep, const char *value) -{ - mprAssert(ep); - mprAssert(value); - - ejsWriteVarAsString(ep, ep->result, value); -} - -/******************************************************************************/ -/* - * Set the expression return value to a binary string value. - */ - -void ejsSetReturnValueToBinaryString(Ejs *ep, const uchar *value, int len) -{ - mprAssert(ep); - mprAssert(value); - - ejsWriteVarAsBinaryString(ep, ep->result, value, len); -} - -/******************************************************************************/ -/* - * Set the expression return value to a integer value. - */ - -void ejsSetReturnValueToInteger(Ejs *ep, int value) -{ - mprAssert(ep); - - ejsWriteVarAsInteger(ep, ep->result, value); -} - -/******************************************************************************/ -/* - * Set the expression return value to an EjsNum value. - */ - -void ejsSetReturnValueToNumber(Ejs *ep, EjsNum value) -{ - mprAssert(ep); - - ejsWriteVarAsNumber(ep, ep->result, value); -} - -/******************************************************************************/ -/* - * Set the expression return value to a boolean value. - */ - -void ejsSetReturnValueToBoolean(Ejs *ep, int value) -{ - mprAssert(ep); - - ejsWriteVarAsBoolean(ep, ep->result, value); -} - -/******************************************************************************/ -/* - * Set the expression return value to a boolean value. - */ - -void ejsSetReturnValueToUndefined(Ejs *ep) -{ - mprAssert(ep); - - ejsWriteVarAsUndefined(ep, ep->result); -} - -/******************************************************************************/ -/* - * Get the expression return value - */ - -EjsVar *ejsGetReturnValue(Ejs *ep) -{ - mprAssert(ep); - - return ep->result; -} - -/******************************************************************************/ - -void *ejsGetUserData(Ejs *ep) -{ - mprAssert(ep); - - return ep->userData; -} - -/******************************************************************************/ -/* - * Get a variable given a full variable spec possibly containing "." or "[]". - */ - -EjsVar *ejsGetVar(Ejs *ep, const char *fullName) -{ - mprAssert(ep); - mprAssert(fullName && *fullName); - - return ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 0); -} - -/******************************************************************************/ -/* - * Get a string var given a full variable spec possibly containing "." or "[]". - */ - -const char *ejsGetStr(Ejs *ep, const char *fullName, const char *defaultValue) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 0); - if (vp == 0 || !ejsVarIsString(vp)) { - return defaultValue; - } - /* MOB -- what about VarToStr */ - return vp->string; -} - -/******************************************************************************/ -/* - * Get an int var given a full variable spec possibly containing "." or "[]". - */ - -int ejsGetInt(Ejs *ep, const char *fullName, int defaultValue) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 0); - if (vp == 0 || !ejsVarIsInteger(vp)) { - return defaultValue; - } - /* MOB -- should use VarToInt */ - return vp->integer; -} - -/******************************************************************************/ -/* - * Get an bool var given a full variable spec possibly containing "." or "[]". - */ - -int ejsGetBool(Ejs *ep, const char *fullName, int defaultValue) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 0); - if (vp == 0 || !ejsVarIsBoolean(vp)) { - return defaultValue; - } - /* MOB -- should use VarToBool */ - return vp->boolean; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsSetVar(Ejs *ep, const char *fullName, const EjsVar *value) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 1); - if (vp == 0) { - return MPR_ERR_CANT_CREATE; - } - - if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) == 0) { - return MPR_ERR_CANT_WRITE; - } - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsSetStr(Ejs *ep, const char *fullName, const char *value) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 1); - if (vp == 0) { - return MPR_ERR_CANT_CREATE; - } - - if (ejsWriteVarAsString(ep, vp, value) == 0) { - return MPR_ERR_CANT_WRITE; - } - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsSetInt(Ejs *ep, const char *fullName, int value) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 1); - if (vp == 0) { - return MPR_ERR_CANT_CREATE; - } - - /* Can't fail */ - ejsWriteVarAsInteger(ep, vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsSetBool(Ejs *ep, const char *fullName, bool value) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 1); - if (vp == 0) { - return MPR_ERR_CANT_CREATE; - } - - /* Can't fail */ - ejsWriteVarAsBoolean(ep, vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. Free the value passed in. - */ - -int ejsSetVarAndFree(Ejs *ep, const char *fullName, EjsVar *value) -{ - EjsVar *vp; - - mprAssert(fullName && *fullName); - - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, fullName, 1); - if (vp == 0) { - return MPR_ERR_CANT_CREATE; - } - - if (ejsWriteVar(ep, vp, value, EJS_SHALLOW_COPY) == 0) { - ejsFreeVar(ep, value); - return MPR_ERR_CANT_WRITE; - } - - ejsFreeVar(ep, value); - return 0; -} - -/******************************************************************************/ -/* - * Delete a variable - */ - -int ejsDeleteVar(Ejs *ep, const char *fullName) -{ - EjsVar *vp; - EjsVar *obj; - char *propertyName; - - vp = ejsFindProperty(ep, &obj, &propertyName, ep->global, ep->local, - fullName, 0); - if (vp == 0) { - return -1; - } - - mprAssert(propertyName); - mprAssert(propertyName); - - return ejsDeleteProperty(ep, obj, propertyName); -} - -/******************************************************************************/ -/* - * Utility routine to crack JavaScript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { - * // Insufficient args - * return -1; - * } - */ - -int ejsParseArgs(int argc, char **argv, const char *fmt, ...) -{ - va_list vargs; - const char *cp; - char **sp, *s; - int *bp, *ip, argn; - - va_start(vargs, fmt); - - if (argv == 0) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - s = argv[argn]; - switch (*cp) { - case 'b': - bp = va_arg(vargs, int*); - if (bp) { - if (strcmp(s, "true") == 0 || s[0] == '1') { - *bp = 1; - } else { - *bp = 0; - } - } else { - *bp = 0; - } - break; - - case 'd': - ip = va_arg(vargs, int*); - *ip = atoi(s); - break; - - case 's': - sp = va_arg(vargs, char**); - *sp = s; - break; - - default: - mprAssert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ -/* - * Define the standard classes - */ - -int ejsDefineStandardClasses(Ejs *master) -{ - if (ejsDefineArrayClass(master) != 0 || - ejsDefineBooleanClass(master) != 0 || - ejsDefineErrorClasses(master) != 0 || - ejsDefineFunctionClass(master) != 0 || - ejsDefineNumberClass(master) != 0 || -#if FUTURE - ejsDefineDateClass(master) != 0 || -#endif -#if BLD_FEATURE_EJS_E4X - ejsDefineXmlClasses(master) != 0 || -#endif -#if BLD_FEATURE_EJS_DB && NOT_HERE - ejsDefineDbClasses(master) != 0 || -#endif - ejsDefineStringClass(master) != 0) { - return MPR_ERR_MEMORY; - } - return 0; -} - -/******************************************************************************/ -/* - * Define the EJS System Object Model - */ - -int ejsDefineSystemClasses(Ejs *master) -{ - if (ejsDefineSystemClass(master) != 0 || - ejsDefineAppClass(master) != 0 || - ejsDefineMemoryClass(master) != 0 || - ejsDefineLogClass(master) != 0 || - ejsDefineDebugClass(master) != 0 || - ejsDefineGCClass(master) != 0 || - ejsDefineFileSystemClass(master) != 0 || -#if BREW - ejsDefineFileClass(master) != 0 || - ejsDefineHTTPClass(master) != 0 || -#endif - ejsDefineGlobalProperties(master) != 0) { - return MPR_ERR_MEMORY; - } - return 0; -} - -/******************************************************************************/ -/* - * Terminate the system object model and classes - */ - -int ejsTermSystemClasses(Ejs *master) -{ -#if BREW - ejsTermHTTPClass(master); -#endif - return 0; -} - -/******************************************************************************/ -/* - * Define the EJS object model - */ - -int ejsCreateObjectModel(Ejs *ejs) -{ - EjsProperty *pp; - - pp = ejsSetPropertyToNewObj(ejs, ejs->global, "system", "System", 0); - if (pp == 0) { - return MPR_ERR_MEMORY; - } - - if (ejsSetPropertyToNewObj(ejs, ejsGetVarPtr(pp), "app", "System.App", - 0) == 0) { - return MPR_ERR_MEMORY; - } - return 0; -} - -/******************************************************************************/ - -void ejsTrace(Ejs *ep, const char *fmt, ...) -{ - va_list args; - char buf[MPR_MAX_LOG_STRING]; - int len; - - va_start(args, fmt); - len = mprVsprintf(buf, sizeof(buf) - 1, fmt, args); - va_end(args); - - mprLog(ep, 0, buf, len); - - va_end(args); -} - -/******************************************************************************/ - -bool ejsGotException(Ejs *ep) -{ - return (bool) ep->gotException; -} - -/******************************************************************************/ - -void ejsSetPrimaryHandle(Ejs *ep, void *primaryHandle) -{ - mprAssert(ep); - - ep->primaryHandle = primaryHandle; -} - -/******************************************************************************/ - -void ejsSetAlternateHandle(Ejs *ep, void *alternateHandle) -{ - mprAssert(ep); - - ep->altHandle = alternateHandle; -} - -/******************************************************************************/ - -#else -void ejsDummy() {} - -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejs.h b/source4/lib/appweb/ejs-2.0/ejs/ejs.h deleted file mode 100644 index a926446524..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejs.h +++ /dev/null @@ -1,849 +0,0 @@ -/* - * ejs.h - EJScript Language (ECMAScript) header. - */ - -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#ifndef _h_EJS -#define _h_EJS 1 - -#include "mpr.h" -#include "ejsVar.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************* Prototypes *********************************/ -/* - * Constants - */ -#if BLD_FEATURE_SQUEEZE - #define EJS_GC_WORK_QUOTA 160 /* Allocations required before - garbage colllection */ - - #define EJS_PARSE_INCR 256 /* Growth factor */ - #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 8 /* Growth increment for lists */ - #define EJS_MAX_BACKTRACE 10 /* Recursion limit for assert */ - -#else - #define EJS_GC_WORK_QUOTA 500 - - #define EJS_PARSE_INCR 1024 - #define EJS_MAX_RECURSE 100 - #define EJS_SMALL_OBJ_HASH_SIZE 11 - #define EJS_LIST_INCR 16 - #define EJS_MAX_BACKTRACE 25 - -#endif - -/* - * Allocation increments for the default interpreter - */ -#define EJS_DEFAULT_VAR_INC 8 /* Var allocation increment */ -#define EJS_DEFAULT_PROP_INC 96 /* Property allocation increment */ -#define EJS_DEFAULT_OBJ_INC 24 /* Object allocation increment */ -#define EJS_DEFAULT_STR_INC 64 /* Object allocation increment */ - -#define EJS_MIN_TIME_FOR_GC 300 /**< Need 1/3 sec for GC */ -#define EJS_GC_MIN_WORK_QUOTA 50 /**< Min to stop thrashing */ - -/* - * Allocation increments for all non-default interpreters - */ -#define EJS_VAR_INC 32 -#define EJS_PROP_INC 64 -#define EJS_OBJ_INC 64 -#define EJS_STR_INC 64 - -#define EJS_INC_FRAMES 8 /* Frame stack increment */ -#define EJS_MAX_FRAMES 64 /* Max frame stack */ - -/* - * Lexical analyser tokens - */ -#define EJS_TOK_ERR -1 /* Any error */ -#define EJS_TOK_LPAREN 1 /* ( */ -#define EJS_TOK_RPAREN 2 /* ) */ -#define EJS_TOK_IF 3 /* if */ -#define EJS_TOK_ELSE 4 /* else */ -#define EJS_TOK_LBRACE 5 /* { */ -#define EJS_TOK_RBRACE 6 /* } */ -#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ -#define EJS_TOK_EXPR 8 /* +, -, /, % */ -#define EJS_TOK_SEMI 9 /* ; */ -#define EJS_TOK_LITERAL 10 /* literal string */ -#define EJS_TOK_METHOD_NAME 11 /* methodName( */ -#define EJS_TOK_NEWLINE 12 /* newline white space */ -#define EJS_TOK_ID 13 /* Identifier */ -#define EJS_TOK_EOF 14 /* End of script */ -#define EJS_TOK_COMMA 15 /* Comma */ -#define EJS_TOK_VAR 16 /* var */ -#define EJS_TOK_ASSIGNMENT 17 /* = */ -#define EJS_TOK_FOR 18 /* for */ -#define EJS_TOK_INC_DEC 19 /* ++, -- */ -#define EJS_TOK_RETURN 20 /* return */ -#define EJS_TOK_PERIOD 21 /* . */ -#define EJS_TOK_LBRACKET 22 /* [ */ -#define EJS_TOK_RBRACKET 23 /* ] */ -#define EJS_TOK_NEW 24 /* new */ -#define EJS_TOK_DELETE 25 /* delete */ -#define EJS_TOK_IN 26 /* in */ -#define EJS_TOK_FUNCTION 27 /* function */ -#define EJS_TOK_NUMBER 28 /* Number */ -#define EJS_TOK_CLASS 29 /* class */ -#define EJS_TOK_EXTENDS 30 /* extends */ -#define EJS_TOK_PUBLIC 31 /* public */ -#define EJS_TOK_PRIVATE 32 /* private */ -#define EJS_TOK_PROTECTED 33 /* private */ -#define EJS_TOK_TRY 34 /* try */ -#define EJS_TOK_CATCH 35 /* catch */ -#define EJS_TOK_FINALLY 36 /* finally */ -#define EJS_TOK_THROW 37 /* throw */ -#define EJS_TOK_COLON 38 /* : */ -#define EJS_TOK_GET 39 /* get */ -#define EJS_TOK_SET 40 /* set */ -#define EJS_TOK_MODULE 41 /* module */ -#define EJS_TOK_EACH 42 /* each */ - -/* - * Expression operators - */ -#define EJS_EXPR_LESS 1 /* < */ -#define EJS_EXPR_LESSEQ 2 /* <= */ -#define EJS_EXPR_GREATER 3 /* > */ -#define EJS_EXPR_GREATEREQ 4 /* >= */ -#define EJS_EXPR_EQ 5 /* == */ -#define EJS_EXPR_NOTEQ 6 /* != */ -#define EJS_EXPR_PLUS 7 /* + */ -#define EJS_EXPR_MINUS 8 /* - */ -#define EJS_EXPR_DIV 9 /* / */ -#define EJS_EXPR_MOD 10 /* % */ -#define EJS_EXPR_LSHIFT 11 /* << */ -#define EJS_EXPR_RSHIFT 12 /* >> */ -#define EJS_EXPR_MUL 13 /* * */ -#define EJS_EXPR_ASSIGNMENT 14 /* = */ -#define EJS_EXPR_INC 15 /* ++ */ -#define EJS_EXPR_DEC 16 /* -- */ -#define EJS_EXPR_BOOL_COMP 17 /* ! */ - -/* - * Conditional operators - */ -#define EJS_COND_AND 1 /* && */ -#define EJS_COND_OR 2 /* || */ -#define EJS_COND_NOT 3 /* ! */ - -/** - * EJ Parsing States. Error and Return are be negative. - */ -#define EJS_STATE_ERR -1 /**< Error state */ -#define EJS_STATE_RET -2 /**< Return statement */ -#define EJS_STATE_EOF -3 /**< End of file */ -#define EJS_STATE_COND 2 /* Parsing a conditional stmt */ -#define EJS_STATE_COND_DONE 3 -#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ -#define EJS_STATE_RELEXP_DONE 5 -#define EJS_STATE_EXPR 6 /* Parsing an expression */ -#define EJS_STATE_EXPR_DONE 7 -#define EJS_STATE_STMT 8 /* Parsing General statement */ -#define EJS_STATE_STMT_DONE 9 -#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ -#define EJS_STATE_ARG_LIST 11 /* Method arg list */ -#define EJS_STATE_ARG_LIST_DONE 12 -#define EJS_STATE_DEC_LIST 16 /* Declaration list */ -#define EJS_STATE_DEC_LIST_DONE 17 -#define EJS_STATE_DEC 18 /* Declaration statement */ -#define EJS_STATE_DEC_DONE 19 - -#define EJS_STATE_BEGIN EJS_STATE_STMT - -/* - * General parsing flags. - */ -#define EJS_FLAGS_EXE 0x1 /* Execute statements */ -#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ -#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ -#define EJS_FLAGS_CREATE 0x8 /* Create var */ -#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ -#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ -#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ -#define EJS_FLAGS_EXIT 0x100 /* Must exit */ -#define EJS_FLAGS_LHS 0x200 /* Left-hand-side of assignment */ -#define EJS_FLAGS_FORIN 0x400 /* In "for (v in ..." */ -#define EJS_FLAGS_CLASS_DEC 0x800 /* "class name [extends] name " */ -#define EJS_FLAGS_TRY 0x2000 /* In a try {} block */ -#define EJS_FLAGS_CATCH 0x4000 /* "catch (variable)" */ -#define EJS_FLAGS_DONT_GC 0x8000 /* Don't garbage collect */ -#define EJS_FLAGS_NO_ARGS 0x10000 /* Accessors don't use args */ -#define EJS_FLAGS_ENUM_HIDDEN 0x20000 /* Enumerate hidden fields */ -#define EJS_FLAGS_ENUM_BASE 0x40000 /* Enumerate base classes */ -#define EJS_FLAGS_TRACE_ARGS 0x80000 /* Support for printv */ -#define EJS_FLAGS_SHARED_SLAB 0x100000/* Using a shared slab */ - -/* - * Exceptions - */ -#define EJS_ARG_ERROR "ArgError" /**< Method argument error */ -#define EJS_ASSERT_ERROR "AssertError" /**< Assertion error */ -#define EJS_EVAL_ERROR "EvalError" /**< General evalation error */ -#define EJS_INTERNAL_ERROR "InternalError" /**< Internal error */ -#define EJS_IO_ERROR "IOError" /**< IO or data error */ -#define EJS_MEMORY_ERROR "MemoryError" /**< Memory allocation error */ -#define EJS_RANGE_ERROR "RangeError" /**< Data out of range (div by 0) */ -#define EJS_REFERENCE_ERROR "ReferenceError"/**< Object or property reference */ -#define EJS_SYNTAX_ERROR "SyntaxError" /**< Javascript syntax error */ -#define EJS_TYPE_ERROR "TypeError" /**< Wrong type supplied */ - -/* - * E4X - */ -#if BLD_FEATURE_EJS_E4X -#if BLD_FEATURE_SQUEEZE -#define E4X_BUF_SIZE 512 /* Initial buffer size for tokens */ -#define E4X_BUF_MAX (32 * 1024) /* Max size for tokens */ -#define E4X_MAX_NODE_DEPTH 24 /* Max nesting of tags */ -#else -#define E4X_BUF_SIZE 4096 -#define E4X_BUF_MAX (128 * 1024) -#define E4X_MAX_NODE_DEPTH 128 -#endif - -#define E4X_MAX_ELT_SIZE (E4X_BUF_MAX-1) -#define E4X_TEXT_PROPERTY "-txt" -#define E4X_TAG_NAME_PROPERTY "-tag" -#define E4X_COMMENT_PROPERTY "-com" -#define E4X_ATTRIBUTES_PROPERTY "-att" -#define E4X_PI_PROPERTY "-pi" -#define E4X_PARENT_PROPERTY "-parent" -#endif - -#if BLD_FEATURE_MULTITHREAD -/** - * Multithreaded lock function - */ -typedef void (*EjsLockFn)(void *lockData); -/** - * Multithreaded unlock function - */ -typedef void (*EjsUnlockFn)(void *lockData); -#endif - -/* - * Token limits - */ -#define EJS_MAX_LINE 128 /* Maximum input line buffer */ -#define EJS_MAX_TOKEN 640 /* Max input parse token */ -#define EJS_TOKEN_STACK 3 /* Put back token stack */ - -/* - * Putback token - */ - -typedef struct EjsToken { - char tokbuf[EJS_MAX_TOKEN]; - int tid; /* Token ID */ -} EjsToken; - -/* - * EJ evaluation block structure - */ -typedef struct EjsInput { - EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ - int putBackIndex; /* Top of stack index */ - char line[EJS_MAX_LINE]; /* Current line */ - char *fileName; /* File or script name */ - int lineLength; /* Current line length */ - int lineNumber; /* Parse line number */ - int lineColumn; /* Column in line */ - struct EjsInput *next; /* Used for backtraces */ - const char *procName; /* Gives name in backtrace */ - const char *script; /* Input script for parsing */ - char *scriptServp; /* Next token in the script */ - int scriptSize; /* Length of script */ - char tokbuf[EJS_MAX_TOKEN]; /* Current token */ - int tid; /* Token ID */ - char *tokEndp; /* Pointer past end of token */ - char *tokServp; /* Pointer to next token char */ - struct EjsInput *nextInput; /* Free list of input structs */ -} EjsInput; - -/* - * Method call structure - */ -typedef struct EjsProc { - MprArray *args; /* Args for method */ - EjsVar *fn; /* Method definition */ - char *procName; /* Method name */ -} EjsProc; - - -/** - * @overview EJScript Service structure - * @description The EJScript service manages the overall language runtime. It - * is the factory that creates interpreter instances via ejsCreateInterp. - * The EJScript service creates a master interpreter that holds the - * standard language classes and properties. When user interpreters are - * created, they reference (without copying) the master interpreter to - * gain access to the standard classes and types. - * @stability Prototype. - * @library libejs. - * @see ejsOpenService, ejsCloseService, ejsCreateInterp, ejsDestoryInterp - */ -typedef struct EjsService { - EjsVar *globalClass; /* Global class */ - struct Ejs *master; /* Master Interp inherited by all */ -#if BLD_FEATURE_MULTITHREAD - EjsLockFn lock; - EjsUnlockFn unlock; - void *lockData; -#endif -} EjsService; - - -/* - * Memory statistics - */ -typedef struct EjsMemStats { - uint maxMem; - uint usedMem; -} EjsMemStats; - - -/* - * Garbage collection block alignment - */ -#define EJS_ALLOC_ALIGN(ptr) \ - (((ptr) + sizeof(void*) - 1) & ~(sizeof(void*) - 1)) - -/* - * Default GC tune factors - */ -#define EJS_GC_START_THRESHOLD (32 * 1024) - -/* - * The Garbage collector is a generational collector. It ages blocks and - * optimizes the mark / sweep algorithm to focus on new and recent blocks - */ -typedef enum EjsGeneration { - EJS_GEN_NEW = 0, - EJS_GEN_RECENT_1 = 1, - EJS_GEN_RECENT_2 = 2, - EJS_GEN_OLD = 3, - EJS_GEN_PERMANENT = 4, - EJS_GEN_MAX = 5, -} EjsGeneration; - -/* - * Garbage collector control - */ -typedef struct EjsGC { - bool enable; - bool enableDemandCollect; - bool enableIdleCollect; - /* - * maxMemory should be set to be 95% of the real max memory limit - */ - uint maxMemory; /* Above this, Throw Memory exception. */ - int workQuota; /* Quota of work before GC */ - int workDone; /* Count of allocations */ - int degraded; /* Have exceeded maxMemory */ - - /* - * Debug Levels 0-N (increases verbosity) - * 1 -- Sweep and collection count - * 2 -- Trace objects deleted - * 3 -- Trace objects marked - * 4 -- Print alloc report when needing a demand allocation - * - */ - int debugLevel; /* In debug mode */ - int collecting; /* Running garbage collection */ - uint collectionCount; /* Number of times GC ran */ -#if BLD_DEBUG - int gcIndent; /* Indent formatting */ - int objectsInUse; /* Objects currently reachable */ - int propertiesInUse; /* Properties currently reachable */ -#endif -} EjsGC; - -/* - * Slab memory allocation - */ -typedef struct EjsSlab { - uint allocIncrement; /* Growth increment in slab */ - uint size; /* Size of allocations */ - EjsGCLink freeList; /* Free list (only next ptr is used) */ - EjsObj *lastRecentBlock; /* Saved for GC age generations phase */ - EjsGCLink allocList[EJS_GEN_MAX]; /* Allocated block list */ - -#if BLD_FEATURE_ALLOC_STATS - uint totalAlloc; /* Total count of allocation calls */ - uint freeCount; /* Number of blocks on the slab freelist */ - uint allocCount; /* Number of allocated blocks */ - uint peakAllocated; /* Peak allocated */ - uint peakFree; /* Peak on the free list */ - uint totalReclaimed; /* Total blocks reclaimed on sweeps */ - uint totalSweeps; /* Total sweeps */ -#endif -} EjsSlab; - - -/** - * @overview EJ interpreter control structure. - * @description EJ allocates one control structure per active interpreter. - * The \ref ejsCreateInterp routine creates the Ejs structure and returns - * a reference to be used in subsequent EJ API calls. - * @stability Prototype. - * @library libejs. - * @see ejsCreateInterp, ejsDestroyInterp, ejsOpenService - */ -struct Ejs { - void *altHandle; /* Alternate callback handle */ - bool castAlloc; /* True if castTemp is allocated */ - char *castTemp; /* Temporary string for casting */ - char *currentClass; /* Current class name */ - EjsVar *currentObj; /* Ptr to current object */ - EjsVar *thisObject; /* Ptr to current "this" */ - EjsProperty *currentProperty; /* Ptr to current property */ - EjsGC gc; /* Garbage collector control */ - char *errorMsg; /* Error message */ - char *fileName; /* File or script name */ - int lineNumber; /* File line number */ - int scriptStatus; /* Status to exit() */ - int flags; /* Flags */ - MprArray *frames; /* List of variable frames */ - EjsVar *global; /* Global object */ - EjsVar *objectClass; /* Object class */ - int gotException; /* Exception thrown */ - EjsInput *input; /* Input evaluation block */ - int depth; /* Recursion depth */ - EjsVar *local; /* Local object */ - int maxDepth; /* Maximum depth for formatting */ - void *primaryHandle; /* primary callback handle */ - EjsProc *proc; /* Current method */ - int recurseCount; /* Recursion counter */ - EjsVar *result; /* Variable result */ - int tid; /* Current token id */ - char *token; /* Pointer to token string */ - EjsVar tokenNumber; /* Parsed number */ - EjsService *service; /* Service object */ - void *userData; /* Method user data */ - - EjsSlab *slabs; /* Memory allocation slabs */ - MprCtx slabAllocContext; /* Allocation context */ - EjsInput *inputList; /* Free list of input structs */ - -#if BLD_FEATURE_MULTITHREAD - EjsLockFn lock; /* Lock method */ - EjsUnlockFn unlock; /* Unlock method */ - void *lockData; /* Lock data argument */ -#endif -#define EJS_MAX_STACK (10 * 1024) - char stack[EJS_MAX_STACK]; /* Local variable stack */ - char *stkPtr; /* Local variable stack ptr */ - void *inputMarker; /* Recurse protection */ -}; - - -typedef struct EjsModule -{ - int dummy; -} EjsModule; - - -/* - * Method callback when using Alternate handles. GaCompat uses these and - * passes the web server request structure via the altHandle. - */ -typedef void *EjsHandle; -typedef int (*EjsAltCMethod)(Ejs *ejs, EjsHandle altHandle, - EjsVar *thisObj, int argc, EjsVar **argv); -typedef int (*EjsAltStringCMethod)(Ejs *ejs, EjsHandle altHandle, - EjsVar *thisObj, int argc, char **argv); - - -/* - * API Constants - */ -#define EJS_USE_OWN_SLAB 1 - -/******************************** Internal API ********************************/ -/* - * Ejs Lex - */ -extern int ejsLexOpenScript(Ejs *ejs, const char *script); -extern void ejsLexCloseScript(Ejs *ejs); -extern int ejsInitInputState(EjsInput *ip); -extern void ejsLexSaveInputState(Ejs *ejs, EjsInput* state); -extern void ejsLexFreeInputState(Ejs *ejs, EjsInput* state); -extern void ejsLexRestoreInputState(Ejs *ejs, EjsInput* state); -extern int ejsLexGetToken(Ejs *ejs, int state); -extern void ejsLexPutbackToken(Ejs *ejs, int tid, char *string); - -/* - * Parsing - */ -extern int ejsParse(Ejs *ejs, int state, int flags); -extern int ejsGetFlags(Ejs *ejs); - -/* - * Create variable scope blocks - */ -extern int ejsOpenBlock(Ejs *ejs); -extern int ejsSetBlock(Ejs *ejs, EjsVar *local); -extern int ejsCloseBlock(Ejs *ejs, int vid); -extern int ejsEvalBlock(Ejs *ejs, char *script, EjsVar *vp); -extern void ejsSetFileName(Ejs *ejs, const char *fileName); - -/* - * Class definitions - */ -extern EjsVar *ejsCreateSimpleClass(Ejs *ejs, EjsVar *baseClass, - const char *className); -extern int ejsDefineObjectClass(Ejs *ejs); -extern int ejsDefineArrayClass(Ejs *ejs); -extern int ejsDefineBooleanClass(Ejs *ejs); -extern int ejsDefineErrorClasses(Ejs *ejs); -extern int ejsDefineFileClass(Ejs *ejs); -extern int ejsDefineFileSystemClass(Ejs *ejs); -extern int ejsDefineHTTPClass(Ejs *ejs); -extern int ejsDefineFunctionClass(Ejs *ejs); -extern int ejsDefineNumberClass(Ejs *ejs); -extern int ejsDefineStringClass(Ejs *ejs); -extern int ejsDefineDateClass(Ejs *ejs); -extern int ejsDefineStandardClasses(Ejs *ejs); - -#if BLD_FEATURE_EJS_E4X -extern int ejsDefineXmlClasses(Ejs *ejs); -extern EjsVar *ejsCreateXml(Ejs *ejs); -#endif - -#if BLD_FEATURE_EJS_DB -extern int ejsDefineDbClasses(Ejs *ejs); -#endif - -/* - * System class definitions - */ -extern int ejsDefineSystemClasses(Ejs *ejs); -extern int ejsDefineSystemClass(Ejs *ejs); -extern int ejsDefineAppClass(Ejs *ejs); -extern int ejsDefineDebugClass(Ejs *ejs); -extern int ejsDefineLogClass(Ejs *ejs); -extern int ejsDefineMemoryClass(Ejs *ejs); -extern int ejsDefineGCClass(Ejs *ejs); -extern int ejsDefineGlobalProperties(Ejs *ejs); - -extern int ejsTermSystemClasses(Ejs *ejs); -extern void ejsTermHTTPClass(Ejs *ejs); - -extern int ejsCreateObjectModel(Ejs *ejs); - -/* - * Class constructors - */ -extern int ejsArrayConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv); -extern int ejsXmlConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv); -extern int ejsXmlListConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv); -extern int ejsBooleanConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **agv); -extern int ejsFunctionConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **agv); -extern int ejsNumberConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv); -extern int ejsStringConstructor(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv); -extern int ejsDateConstructor(Ejs *ejs, EjsVar *thisObj, - int argc, EjsVar **argv); - -/* - * Garbage collection - */ -extern void ejsGCInit(Ejs *ejs, int objInc, int propInc, int varInc, - int strInc); -extern int ejsIsTimeForGC(Ejs *ep, int timeTillNextEvent); - -extern bool ejsSetGCDebugLevel(Ejs *ep, int debugLevel); -extern void ejsSweepAll(Ejs *ep); - -extern EjsObj *ejsAllocObj(EJS_LOC_DEC(ejs, loc)); -extern EjsProperty *ejsAllocProperty(EJS_LOC_DEC(ejs, loc)); -extern EjsVar *ejsAllocVar(EJS_LOC_DEC(ejs, loc)); -extern void ejsFree(Ejs *ejs, void *ptr, int slabIndex); - -extern int ejsCollectGarbage(Ejs *ejs, int slabIndex); -extern int ejsIncrementalCollectGarbage(Ejs *ejs); - -#if BLD_DEBUG -extern void ejsDumpObjects(Ejs *ejs); -#endif - -#if BLD_FEATURE_ALLOC_STATS -extern void ejsPrintAllocReport(Ejs *ejs, bool printLeakReport); -#endif - -extern void ejsCleanInterp(Ejs *ejs, bool doStats); -extern void ejsSetInternalMethods(Ejs *ejs, EjsVar *op); -extern void ejsSetPrimaryHandle(Ejs *ep, void *primaryHandle); -extern void ejsSetAlternateHandle(Ejs *ep, void *alternateHandle); -extern void *ejsGetUserData(Ejs *ejs); - -/* - * Could possibly make these routines public - */ - -extern int ejsSetGCMaxMemory(Ejs *ep, uint maxMemory); -extern uint ejsGetUsedMemory(Ejs *ejs); -extern uint ejsGetAllocatedMemory(Ejs *ejs); -extern uint ejsGetAvailableMemory(Ejs *ejs); -extern char *ejsFormatStack(Ejs* ep);; - -/********************************* Prototypes *********************************/ -#if BLD_FEATURE_MULTITHREAD -extern int ejsSetServiceLocks(EjsService *sp, EjsLockFn lock, - EjsUnlockFn unlock, void *data); -#endif - -/* - * Ejs service and interpreter management - */ -extern EjsService *ejsOpenService(MprCtx ctx); -extern void ejsCloseService(EjsService *sp, bool doStats); - -extern Ejs *ejsCreateInterp(EjsService *sp, void *primaryHandle, - void *altHandle, EjsVar *global, bool useOwnSlab); -extern void ejsDestroyInterp(Ejs *ejs, bool doStats); - -extern Ejs *ejsGetMasterInterp(EjsService *sp); -extern EjsVar *ejsGetGlobalClass(Ejs *ejs); - -/* - * Module support - */ -extern EjsModule *ejsCreateModule(const char *name, const char *version, - int (*start)(EjsModule*), int (*stop)(EjsModule*)); - -/* - * Native Objects - */ - -void ejsSetNativeData(EjsVar *obj, void *data); -void ejsSetNativeHelpers(Ejs *ejs, EjsVar *nativeClass, - int (*createInstance)(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv), - void (*disposeInstance)(Ejs *ejs, EjsVar *thisObj), - bool (*hasProperty)(Ejs *ejs, EjsVar *thisObj, const char *prop), - int (*deleteProperty)(Ejs *ejs, EjsVar *thisObj, const char *prop), - int (*getProperty)(Ejs *ejs, EjsVar *thisObj, const char *prop, - EjsVar *dest), - int (*setProperty)(Ejs *ejs, EjsVar *thisObj, const char *prop, - EjsVar *value), - int (*doOperator)(Ejs *ejs, EjsVar *thisObj, EjsOp *op, EjsVar - *result, EjsVar *lhs, EjsVar *rhs, int *code) - ); - -/* - * Evaluation methods - */ -extern int ejsEvalFile(Ejs *ejs, const char *path, EjsVar *result); -extern int ejsEvalScript(Ejs *ejs, const char *script, EjsVar *result); -extern int ejsRunMethod(Ejs *ejs, EjsVar *obj, - const char *methodName, MprArray *args); -extern int ejsRunMethodCmd(Ejs *ejs, EjsVar *obj, - const char *methodName, const char *cmdFmt, ...); -extern EjsVar *ejsGetReturnValue(Ejs *ejs); - -extern EjsVar *ejsGetLocalObj(Ejs *ejs); -extern EjsVar *ejsGetGlobalObj(Ejs *ejs); - -/* - * Define a class in the specified interpreter. If used with the default - * interpeter, then the class is defined for all interpreters. - */ -extern EjsVar *ejsDefineClass(Ejs *ejs, const char *className, - const char *extends, EjsCMethod constructor); -extern EjsVar *ejsGetClass(Ejs *ejs, EjsVar *parentClass, - const char *className); - -extern const char *ejsGetClassName(EjsVar *obj); -extern const char *ejsGetBaseClassName(EjsVar *obj); - -extern bool ejsIsSubClass(EjsVar *target, EjsVar *baseClass); -extern EjsVar *ejsGetBaseClass(EjsVar *obj); -extern void ejsSetBaseClass(EjsVar *obj, EjsVar *baseClass); - - -#define ejsCreateSimpleObj(ejs, className) \ - ejsCreateSimpleObjInternal(EJS_LOC_ARGS(ejs), className) -extern EjsVar *ejsCreateSimpleObjInternal(EJS_LOC_DEC(ejs, loc), - const char *className); - -#define ejsCreateSimpleObjUsingClass(ejs, baseClass) \ - ejsCreateSimpleObjUsingClassInt(EJS_LOC_ARGS(ejs), \ - baseClass) -extern EjsVar *ejsCreateSimpleObjUsingClassInt(EJS_LOC_DEC(ejs, loc), - EjsVar *baseClass); - -/* - * This will create an object and call all required constructors - */ -extern EjsVar *ejsCreateObj(Ejs *ejs, EjsVar *obj, - const char *className, const char *constructorArgs); - -#define ejsCreateObjUsingArgv(ejs, obj, className, args) \ - ejsCreateObjUsingArgvInternal(EJS_LOC_ARGS(ejs), obj, \ - className, args) -extern EjsVar *ejsCreateObjUsingArgvInternal(EJS_LOC_DEC(ejs, loc), - EjsVar *obj, const char *className, MprArray *args); - -#define ejsCreateArray(ejs, size) \ - ejsCreateArrayInternal(EJS_LOC_ARGS(ejs), size) -extern EjsVar *ejsCreateArrayInternal(EJS_LOC_DEC(ejs, loc), - int size); - -/* - * Array methods. MOB -- need other array methods - */ -/* MOB -- spell out element */ -extern EjsVar *ejsAddArrayElt(Ejs *ejs, EjsVar *op, EjsVar *element, - EjsCopyDepth copyDepth); -/* - * Required: Array methods - * - array = obj.getMethods(); - array = obj.getProperties(); - - array.property.isPublic(); - array.property.isPrivate(); - array.property.isMethod(); - array.property.isEnumerable(); - array.property.isReadOnly(); - array.property.allowsNonUnique(); - array.property.getParent(); -*/ - -/* MOB -- should we have an API that takes a EjsCopyDepth */ -extern void ejsSetReturnValue(Ejs *ejs, EjsVar *vp); -extern void ejsSetReturnValueAndFree(Ejs *ejs, EjsVar *vp); -extern void ejsSetReturnValueToBoolean(Ejs *ejs, bool value); -extern void ejsSetReturnValueToBinaryString(Ejs *ejs, - const uchar *value, int len); -extern void ejsSetReturnValueToInteger(Ejs *ejs, int value); -extern void ejsSetReturnValueToNumber(Ejs *ejs, EjsNum value); -extern void ejsSetReturnValueToString(Ejs *ejs, const char *value); -extern void ejsSetReturnValueToUndefined(Ejs *ejs); - -/* - * Variable access and control. The fullName arg can contain "[]" and "." - */ -extern bool ejsGetBool(Ejs *ejs, const char *fullName, bool defaultValue); -extern int ejsGetInt(Ejs *ejs, const char *fullName, int defaultValue); -extern const char *ejsGetStr(Ejs *ejs, const char *fullName, - const char *defaultValue); -extern EjsVar *ejsGetVar(Ejs *ejs, const char *fullName); - -extern int ejsSetBool(Ejs *ejs, const char *fullName, bool value); -extern int ejsSetInt(Ejs *ejs, const char *fullName, int value); -extern int ejsSetStr(Ejs *ejs, const char *fullName, const char *value); -extern int ejsSetVar(Ejs *ejs, const char *fullName, const EjsVar *value); -extern int ejsSetVarAndFree(Ejs *ejs, const char *fullName, EjsVar *value); - -extern int ejsDeleteVar(Ejs *ejs, const char *fullName); - -/* - * Error handling - */ -extern void ejsError(Ejs *ejs, const char *errorType, const char *fmt, - ...) PRINTF_ATTRIBUTE(3,4); -/* MOB -- this should take no arguments */ -extern void ejsArgError(Ejs *ejs, const char *msg); -extern void ejsInternalError(Ejs *ejs, const char *msg); -extern void ejsMemoryError(Ejs *ejs); -extern void ejsSyntaxError(Ejs *ejs, const char *msg); - -/* - * Utility methods - */ -extern int ejsParseArgs(int argc, char **argv, const char *fmt, ...); - -extern void ejsExit(Ejs *ejs, int status); -extern bool ejsIsExiting(Ejs *ejs); -extern void ejsClearExiting(Ejs *ejs); - -extern bool ejsGotException(Ejs *ejs); - -/* MOB -- rename Method to Function */ -extern void ejsFreeMethodArgs(Ejs *ep, MprArray *args); -extern int ejsStrcat(Ejs *ep, EjsVar *dest, EjsVar *src); - -/* - * Debugging routines - */ -extern char *ejsGetErrorMsg(Ejs *ejs); -extern int ejsGetLineNumber(Ejs *ejs); -extern void ejsTrace(Ejs *ejs, const char *fmt, ...); - -/* - * Multithreaded lock routines - */ -#if BLD_FEATURE_MULTITHREAD -#define ejsLock(sp) if (sp->lock) { (sp->lock)(sp->lockData); } else -#define ejsUnlock(sp) if (sp->unlock) { (sp->unlock)(sp->lockData); } else -#else -#define ejsLock(sp) -#define ejsUnlock(sp) -#endif - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsClass.c b/source4/lib/appweb/ejs-2.0/ejs/ejsClass.c deleted file mode 100644 index 58609adf3f..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsClass.c +++ /dev/null @@ -1,273 +0,0 @@ -/* - * @file ejsClass.c - * @brief EJS class support - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************* Includes ***********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/************************************ Code ************************************/ -/* - * Internal API - * - * Routine to create a simple class object. This routine will create a - * stand-alone class object. Callers must insert this into the relevant - * "global" object for name resolution. From these class objects, instance - * objects may be created via the javascript "new" command. - * - * Users should use ejsDefineClass - */ - -EjsVar *ejsCreateSimpleClass(Ejs *ep, EjsVar *baseClass, const char *className) -{ - EjsProperty *pp; - EjsVar *classObj; - - /* - * Create an instance of an Object to act as the static class object - */ - classObj = ejsCreateSimpleObjUsingClass(ep, baseClass); - if (classObj == 0) { - mprAssert(classObj); - return 0; - } - ejsSetClassName(ep, classObj, className); - - /* - * Set the propotype property to point to this class. - * Note: this is a self reference so the alive bit will not be turned on. - */ - pp = ejsSetProperty(ep, classObj, "prototype", classObj); - ejsMakePropertyEnumerable(pp, 0); - - return classObj; -} - -/******************************************************************************/ -/* - * Define a class in the given interpreter. If parentClass is specified, the - * class is defined in the parent. Otherwise, the class will be defined - * locally/globally. ClassName and extends are full variable specs - * (may contain ".") - */ - -EjsVar *ejsDefineClass(Ejs *ep, const char *className, const char *extends, - EjsCMethod constructor) -{ - EjsVar *parentClass, *classObj, *baseClass, *vp; - char *name; - char *cp; - - /* - * If the className is a qualified name (with "."), then get the - * parent class name. - */ - name = mprStrdup(ep, className); - cp = strrchr(name, '.'); - if (cp != 0) { - *cp++ = '\0'; - className = cp; - parentClass = ejsFindProperty(ep, 0, 0, ep->global, ep->local, name, 0); - if (parentClass == 0 || parentClass->type != EJS_TYPE_OBJECT) { - mprError(ep, MPR_LOC, "Can't find class's parent class %s", name); - mprFree(name); - return 0; - } - - } else { - /* - * Simple class name without a "." so create the class locally - * if a local scope exists, otherwise globally. - */ - parentClass = (ep->local) ? ep->local : ep->global; - } - - if (parentClass == 0) { - mprError(ep, MPR_LOC, "Can't find parent class"); - mprFree(name); - return 0; - } - - /* OPT should use function that doesn't parse [] . */ - baseClass = ejsGetClass(ep, 0, extends); - if (baseClass == 0) { - mprAssert(baseClass); - mprFree(name); - return 0; - } - - classObj = ejsCreateSimpleClass(ep, baseClass, className); - if (classObj == 0) { - mprAssert(classObj); - mprFree(name); - return 0; - } - - if (constructor) { - ejsDefineCMethod(ep, classObj, className, constructor, 0); - } - - ejsSetPropertyAndFree(ep, parentClass, className, classObj); - - vp = ejsGetPropertyAsVar(ep, parentClass, className); - mprFree(name); - - return vp; -} - -/******************************************************************************/ -/* - * Find a class and return the property defining the class. ClassName may - * contain "." and is interpreted relative to obj. Obj is typically some - * parent object, ep->local or ep->global. If obj is null, then the global - * space is used. - */ - -EjsVar *ejsGetClass(Ejs *ep, EjsVar *obj, const char *className) -{ - EjsVar *vp; - - mprAssert(ep); - - /* - * Search first for a constructor of the name of class - * global may not be defined yet. - */ - if (obj) { - vp = ejsFindProperty(ep, 0, 0, obj, 0, className, 0); - - } else { - mprAssert(ep->global); - vp = ejsFindProperty(ep, 0, 0, ep->global, ep->local, className, 0); - } - if (vp == 0 || vp->type != EJS_TYPE_OBJECT) { - return 0; - } - - /* - * Return a reference to the prototype (self) reference. This - * ensures that even if "obj" is deleted, this reference will remain - * usable. - */ - return ejsGetPropertyAsVar(ep, vp, "prototype"); -} - -/******************************************************************************/ -/* - * Return the class name of a class or object - */ - -const char *ejsGetClassName(EjsVar *vp) -{ - EjsObj *obj; - - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_OBJECT); - mprAssert(vp->objectState->baseClass); - - if (vp == 0 || !ejsVarIsObject(vp)) { - return 0; - } - obj = vp->objectState; - - return obj->className; -} - -/******************************************************************************/ -/* - * Return the class name of an objects underlying class - * If called on an object, it returns the base class. - * If called on a class, it returns the base class for the class. - */ - -const char *ejsGetBaseClassName(EjsVar *vp) -{ - EjsObj *obj; - - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_OBJECT); - mprAssert(vp->objectState->baseClass); - - if (vp == 0 || !ejsVarIsObject(vp)) { - return 0; - } - obj = vp->objectState; - if (obj->baseClass == 0) { - return 0; - } - mprAssert(obj->baseClass->objectState); - - return obj->baseClass->objectState->className; -} - -/******************************************************************************/ - -EjsVar *ejsGetBaseClass(EjsVar *vp) -{ - if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) { - mprAssert(0); - return 0; - } - return vp->objectState->baseClass; -} - -/******************************************************************************/ - -void ejsSetBaseClass(EjsVar *vp, EjsVar *baseClass) -{ - if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) { - mprAssert(0); - return; - } - vp->objectState->baseClass = baseClass; -} - -/******************************************************************************/ - -#else -void ejsProcsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsCmd.c b/source4/lib/appweb/ejs-2.0/ejs/ejsCmd.c deleted file mode 100644 index 74b57de4d0..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsCmd.c +++ /dev/null @@ -1,468 +0,0 @@ -/* - * @file ejsCmd.c - * @brief Embedded JavaScript (EJS) command line program. - * @overview - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS && !BREW - -/************************************ Defines *********************************/ - -#define EJS_MAX_CMD_LINE (16 * 1024) -#define EJS_MAX_SCRIPT (4 * 1024 * 1024) -#define EJS_MAX_RESULT_SIZE (4 * 1024 * 1024) -#define EJS_PROMPT "ejs> " - -/****************************** Forward Declarations **************************/ - -static int parseFile(EjsService *ejsService, Ejs *ejs, const char *fileName, - const char *testName, MprFile *testLogFile); -static int ifConsole(); - -static int interactiveUse(MprApp *app, Ejs *ejs, FILE *input, - char *fileName); -static char *readCmd(MprApp *app, FILE *input); - -static int memoryFailure(MprApp *app, uint size, uint total, bool granted); - -static int isConsole = 0; -static int traceCmds = 0; -static int stats = 0; -static int verbose = 0; - -/************************************ Main ************************************/ - -int main(int argc, char *argv[]) -{ - MprApp *app; - const char *programName; - MprFile *testLogFile; - EjsService *ejsService; - Ejs *ejs; - char *commandLine; - const char *testName; - char *argp, *cmd, *testLog; - int i, rc, nextArg, err, len, firstArg, iterations, debugLevel; - - app = mprInit(memoryFailure); - - isConsole = ifConsole(); - programName = mprGetBaseName(argv[0]); - debugLevel = 0; - - ejsService = ejsOpenService(app); - if (ejsService == 0) { - mprError(app, MPR_LOC, "Can't initialize the EJS service."); - return -1; - } - - err = 0; - iterations = 1; - stats = 0; - testLog = getenv("TEST_LOG"); - testLogFile = 0; - testName = 0; - - for (nextArg = 1; nextArg < argc; nextArg++) { - argp = argv[nextArg]; - if (*argp != '-') { - break; - } - if (strcmp(argp, "--debug") == 0) { - if (nextArg >= argc) { - err++; - } else { - debugLevel = atoi(argv[++nextArg]); - } - - } else if (strcmp(argp, "--stats") == 0) { - stats++; - - } else if (strcmp(argp, "--trace") == 0) { - traceCmds++; - - } else if (strcmp(argp, "--iterations") == 0) { - if (nextArg >= argc) { - err++; - } else { - iterations = atoi(argv[++nextArg]); - } - - } else if (strcmp(argp, "--log") == 0) { - /* Get file to log test results to when using ejs as a test shell */ - if (nextArg >= argc) { - err++; - } else { - testLog = argv[++nextArg]; - } - - } else if (strcmp(argp, "--testName") == 0) { - if (nextArg >= argc) { - err++; - } else { - testName = argv[++nextArg]; - } - - } else if (strcmp(argp, "-v") == 0) { - verbose++; - - } else if (strcmp(argp, "-vv") == 0) { - verbose += 2; - - } else if (strcmp(argp, "--verbose") == 0) { - verbose += 2; - - } else { - err++; - break; - } - if (err) { - mprErrorPrintf(app, - "Usage: %s [options] files... or\n" - " %s < file or\n" - " %s or\n" - " Switches:\n" - " --iterations num # Number of iterations to eval file\n" - " --stats # Output stats on exit\n" - " --testName name # Set the test name", - programName, programName, programName); - return -1; - } - } - - if (testName) { - i = 0; - commandLine = 0; - len = mprAllocStrcat(MPR_LOC_ARGS(app), &commandLine, 0, " ", - mprGetBaseName(argv[i++]), NULL); - for (; i < argc; i++) { - len = mprReallocStrcat(MPR_LOC_ARGS(app), &commandLine, 0, len, - " ", argv[i], NULL); - } - mprPrintf(app, " %s\n", commandLine); - } - if (testLog) { - testLogFile = mprOpen(app, testLog, - O_CREAT | O_APPEND | O_WRONLY | O_TEXT, 0664); - if (testLogFile == 0) { - mprError(app, MPR_LOC, "Can't open %s", testLog); - return MPR_ERR_CANT_OPEN; - } - mprFprintf(testLogFile, "\n %s\n", commandLine); - } - - ejs = ejsCreateInterp(ejsService, 0, 0, 0, 0); - if (ejs == 0) { - mprError(app, MPR_LOC, "Can't create EJS interpreter"); - ejsCloseService(ejsService, stats); - if (testLogFile) { - mprClose(testLogFile); - } - mprTerm(app, stats); - exit(-1); - } - - if (debugLevel > 0) { - ejsSetGCDebugLevel(ejs, debugLevel); - } - - rc = 0; - - if (nextArg < argc) { - /* - * Process files supplied on the command line - */ - firstArg = nextArg; - for (i = 0; i < iterations; i++) { - for (nextArg = firstArg; nextArg < argc; nextArg++) { - rc = parseFile(ejsService, ejs, argv[nextArg], testName, - testLogFile); - if (rc < 0) { - return rc; - } - } - } - if (testName) { - if (verbose == 1) { - mprPrintf(app, "\n"); - } - if (verbose <= 1) { - mprPrintf(app, " # PASSED all tests for \"%s\"\n", testName); - } - } - - } else if (! isConsole) { - /* - * Read a script from stdin - */ - cmd = readCmd(app, stdin); - - ejsSetFileName(ejs, "stdin"); - - rc = ejsEvalScript(ejs, cmd, 0); - if (rc < 0) { - mprPrintf(app, "ejs: Error: %s\n", ejsGetErrorMsg(ejs)); - } - mprFree(cmd); - - } else { - /* - * Interactive use. Read commands from the command line. - */ - rc = interactiveUse(app, ejs, stdin, "stdin"); - } - - /* - * Cleanup. Do stats if required. - */ - if (ejs) { - ejsCleanInterp(ejs, 0); - ejsCleanInterp(ejs->service->master, 0); - ejsDestroyInterp(ejs, 0); - } - - ejsCloseService(ejsService, stats); - - if (testLogFile) { - mprClose(testLogFile); - } - - mprTerm(app, stats); - return rc; -} - -/******************************************************************************/ - -static int parseFile(EjsService *ejsService, Ejs *ejs, const char *fileName, - const char *testName, MprFile *testLogFile) -{ - int rc; - - if (testName && verbose == 1) { - mprPrintf(ejs, "."); - } - if (verbose > 1) { - mprPrintf(ejs, "File: %s\n", fileName); - } - - rc = ejsEvalFile(ejs, fileName, 0); - - if (testName) { - char fileBuf[MPR_MAX_FNAME], *cp; - mprStrcpy(fileBuf, sizeof(fileBuf), fileName); - if ((cp = strstr(fileBuf, ".ejs")) != 0) { - *cp = '\0'; - } - if (rc == 0) { - if (verbose > 1) { - mprPrintf(ejs, " # PASSED test \"%s.%s\"\n", testName, - fileBuf); - } - if (testLogFile) { - mprFprintf(testLogFile, " # PASSED test \"%s.%s\"\n", - testName, fileBuf); - } - - } else { - - mprPrintf(ejs, "FAILED test \"%s.%s\"\nDetails: %s\n", - testName, fileBuf, ejsGetErrorMsg(ejs)); - - if (testLogFile) { - mprFprintf(testLogFile, - "FAILED test \"%s.%s\"\nDetails: %s\n", - testName, fileBuf, ejsGetErrorMsg(ejs)); - } - } - } else if (rc < 0) { - mprPrintf(ejs, "ejs: %sIn file \"%s\"\n", - ejsGetErrorMsg(ejs), fileName); - } - return rc; -} - -/******************************************************************************/ - -static char *readCmd(MprApp *app, FILE *input) -{ - char line[EJS_MAX_CMD_LINE]; - char *cmd; - int len, cmdLen; - - cmd = 0; - cmdLen = 0; - - line[sizeof(line) - 1] = '\0'; - - while (1) { - - if (fgets(line, sizeof(line) - 1, input) == NULL) { - break; - } - - len = strlen(line); - - if (line[len - 1] == '\\') { - line[len - 1] = '\0'; - } - cmdLen = mprReallocStrcat(MPR_LOC_ARGS(app), &cmd, EJS_MAX_SCRIPT, - cmdLen, 0, line, NULL); - } - return cmd; -} - -/******************************************************************************/ - -static int interactiveUse(MprApp *app, Ejs *ejs, FILE *input, char *fileName) -{ - EjsVar result; - char line[EJS_MAX_CMD_LINE]; - char *cmd, *buf; - int len, cmdLen, rc; - - cmd = 0; - cmdLen = 0; - - line[sizeof(line) - 1] = '\0'; - - ejsSetFileName(ejs, "console"); - - while (! ejsIsExiting(ejs)) { - - if (isConsole) { - write(1, EJS_PROMPT, strlen(EJS_PROMPT)); - } - - if (fgets(line, sizeof(line) - 1, input) == NULL) { - break; - } - - len = strlen(line); - while (len > 0 && - (line[len - 1] == '\n' || line[len - 1] == '\r')) { - len--; - line[len] = '\0'; - } - - if (line[len - 1] == '\\') { - line[len - 1] = '\0'; - cmdLen = mprReallocStrcat(MPR_LOC_ARGS(app), &cmd, EJS_MAX_SCRIPT, - cmdLen, 0, line, NULL); - - } else { - - cmdLen = mprReallocStrcat(MPR_LOC_ARGS(app), &cmd, EJS_MAX_SCRIPT, - cmdLen, 0, line, NULL); - - - if (traceCmds) { - mprPrintf(ejs, "# %s\n", cmd); - } - - if (cmd[0] == 0x4 || cmd[0] == 0x26 || strcmp(cmd, "quit") == 0) { - ejsExit(ejs, 0); - - } else if ((rc = ejsEvalScript(ejs, cmd, &result)) < 0) { - - mprPrintf(app, "ejs: Error: %s\n", ejsGetErrorMsg(ejs)); - - if (! isConsole) { - return rc; - } - - } else { - if (isConsole || traceCmds) { - buf = ejsVarToString(ejs, &result); - mprPrintf(ejs, "%s\n", buf); - } - } - mprFree(cmd); - cmd = 0; - cmdLen = 0; - } - } - return 0; -} - -/******************************************************************************/ - -static int ifConsole() -{ -#if WIN - INPUT_RECORD irec[1]; - int records = 0; - - if (PeekConsoleInput(GetStdHandle(STD_INPUT_HANDLE), irec, 1, - &records) != 0) { - return 1; - } -#else - return isatty(0); -#endif - return 0; -} - -/******************************************************************************/ - -static int memoryFailure(MprApp *app, uint size, uint total, bool granted) -{ - if (!granted) { - mprPrintf(app, "Can't allocate memory block of size %d\n", size); - mprPrintf(app, "Total memory used %d\n", total); - exit(255); - } - mprPrintf(app, "Memory request for %d bytes exceeds memory red-line\n", - size); - mprPrintf(app, "Total memory used %d\n", total); - return 0; -} - -/******************************************************************************/ - -#else -void ejsCmdLineDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsGarbage.c b/source4/lib/appweb/ejs-2.0/ejs/ejsGarbage.c deleted file mode 100755 index 264da05721..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsGarbage.c +++ /dev/null @@ -1,1214 +0,0 @@ -/* - * @file ejsGarbage.c - * @brief EJS Garbage collector. - * @overview This implements a generational mark and sweep collection scheme. - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static void mark(Ejs *ep); -static void markObjByVar(Ejs *ep, EjsVar *op); -static void markObj(EjsObj *obj); -static void markPerm(Ejs *ep, uint gen); -static int sweep(Ejs *ep, uint gen); -static EjsGCLink *ejsAlloc(EJS_LOC_DEC(ep, loc), int slabIndex); -static void ejsGracefulDegrade(Ejs *ep); -static void resetMarks(Ejs *ep, EjsSlab *slab); - -#if FUTURE -static void ageGenerations(Ejs *ep); -#endif - -#if BLD_DEBUG && (!BREW || BREW_SIMULATOR) -uint breakAddr; -#endif - -/************************************* Code ***********************************/ - -void ejsGCInit(Ejs *ep, int objInc, int propInc, int varInc, int strInc) -{ - EjsSlab *slab; - - if (ep->service && ep->service->globalClass) { - ep->service->globalClass->objectState->gcMarked = 1; - } - - slab = &ep->slabs[EJS_SLAB_OBJ]; - slab->allocIncrement = objInc; - slab->size = EJS_ALLOC_ALIGN(sizeof(EjsObj)); - - slab = &ep->slabs[EJS_SLAB_PROPERTY]; - slab->allocIncrement = propInc; - slab->size = EJS_ALLOC_ALIGN(sizeof(EjsProperty)); - - slab = &ep->slabs[EJS_SLAB_VAR]; - slab->allocIncrement = varInc; - slab->size = EJS_ALLOC_ALIGN(sizeof(EjsVar)); - - /* - * Initialize GC. - * Enable GC both idle and demand collections. - * Set no limits and garbage collect if the slabs are - * empty and we have used more than the THRESHOLD of ram. - */ - ep->gc.debugLevel = 0; - ep->gc.enable = 1; - ep->gc.enableIdleCollect = 1; - ep->gc.enableDemandCollect = 1; - ep->gc.workQuota = EJS_GC_WORK_QUOTA; - ep->gc.maxMemory = 0; -} - - -/******************************************************************************/ -#if BLD_FEATURE_ALLOC_STATS - -void ejsPrintAllocReport(Ejs *ep, bool printLeakReport) -{ - EjsSlab *slab; - char *name; - int slabIndex, isObj; - - for (slabIndex = 0; slabIndex < EJS_SLAB_MAX; slabIndex++) { - slab = &ep->slabs[slabIndex]; - if (slabIndex == EJS_SLAB_VAR) { - name = "var"; - } else if (slabIndex == EJS_SLAB_PROPERTY) { - name = "prop"; - } else { - name = "obj"; - } - mprLog(ep, 0, " "); - mprLog(ep, 0, " GC \"%s\" local slab", name); - mprLog(ep, 0, " Total blocks %14d", - slab->allocCount + slab->freeCount); - mprLog(ep, 0, " Block size %14d", slab->size); - mprLog(ep, 0, " Slab RAM allocated %14d", - (slab->allocCount + slab->freeCount) * slab->size); - mprLog(ep, 0, " Slab RAM in use %14d", - slab->allocCount * slab->size); - mprLog(ep, 0, " Blocks in use %14d", slab->allocCount); - mprLog(ep, 0, " Free blocks %14d", slab->freeCount); - mprLog(ep, 0, " Peak allocated %14d", slab->peakAllocated); - mprLog(ep, 0, " Peak free %14d", slab->peakFree); - mprLog(ep, 0, " Total allocations %14d", slab->totalAlloc); - mprLog(ep, 0, " Total blocks reclaimed %14d", slab->totalReclaimed); - mprLog(ep, 0, " Total sweeps %14d", slab->totalSweeps); - mprLog(ep, 0, " Allocation inc %14d", slab->allocIncrement); - } - - mprLog(ep, 0, " "); - mprLog(ep, 0, " Total EJS memory in use %10d", ejsGetUsedMemory(ep)); - mprLog(ep, 0, " Total EJS memory allocated %10d", - ejsGetAllocatedMemory(ep)); - - if (printLeakReport) { - mprLog(ep, 0, " "); - for (slabIndex = 0; slabIndex < EJS_SLAB_MAX; slabIndex++) { - int size; - - slab = &ep->slabs[slabIndex]; - - isObj = 0; - mprLog(ep, 0, " "); - if (slabIndex == EJS_SLAB_VAR) { - name = "var"; - size = sizeof(EjsVar); - } else if (slabIndex == EJS_SLAB_PROPERTY) { - name = "prop"; - size = sizeof(EjsProperty); - } else { - name = "obj"; - size = sizeof(EjsObj); - isObj++; - } -#if BLD_FEATURE_ALLOC_LEAK_TRACK -{ - EjsGCLink *lp; - EjsObj *obj; - int count; - - mprLog(ep, 0, "EJS Leak Report for \"%s\"", name); - count = 0; - - for (lp = slab->allocList[0].next; lp; lp = lp->next) { - mprLog(ep, 0, " %-20s %10d", lp->allocatedBy, size); - if (isObj) { - obj = (EjsObj*) lp; - mprLog(ep, 0, " %-20s %10d %s %s", - lp->allocatedBy, size, - obj->permanent ? "permanent" : "", - obj->alive ? "alive" : "" - ); - } else { - mprLog(ep, 0, " %-20s %10d", lp->allocatedBy, - size); - } - count++; - } - mprLog(ep, 0, " Total blocks %14d", count); -} -#endif - } - mprLog(ep, 0, " "); - } -} - -#endif -/******************************************************************************/ -/* - * Slab allocator - */ - -static EjsGCLink *ejsAlloc(EJS_LOC_DEC(ep, loc), int slabIndex) -{ - EjsSlab *slab; - EjsGCLink *block; - EjsGC *gc; - uint allocatedMemory; - int i; - - mprStackCheck(ep); - - if (slabIndex < 0 || slabIndex >= EJS_SLAB_MAX) { - mprAssert(0); - return 0; - } - - /* - * See if the slab has some free blocks - */ - slab = &ep->slabs[slabIndex]; - if ((block = slab->freeList.next) == 0) { - - allocatedMemory = ejsGetAllocatedMemory(ep); - gc = &ep->gc; - - /* - * No blocks available. If demand collection is enabled, try - * to garbage collect first. We collect if we have done a good - * work quota or we are over the max memory limit. - */ - if (slabIndex != EJS_SLAB_VAR && - ep->gc.enable && ep->gc.enableDemandCollect) { - if ((ep->gc.workDone > ep->gc.workQuota) || - (gc->maxMemory > 0 && allocatedMemory > gc->maxMemory)) { - -#if DEBUG_USE_ONLY - if (ep->gc.debugLevel > 0) { - mprLog(ep, 0, "Need GC, EJS RAM %d, MPR RAM %d\n", - allocatedMemory, mprGetAllocatedMemory(ep)); - if (ep->gc.debugLevel > 4) { - ejsPrintAllocReport(ep, 0); - } - } -#endif - if (ejsCollectGarbage(ep, slabIndex) == 0) { - block = slab->freeList.next; - } - } - } - - if (block == 0) { - if (gc->maxMemory > 0 && allocatedMemory > gc->maxMemory) { - /* - * We are above the max memory limit. We will fail this - * memory allocation, but allow subsequent allocations to - * permit error recovery. We gracefully degrade by setting - * slab chunk sizes to 1. This minimizes real memory - * consumption. This allows us to create - * an exception block to be created by upper layers. - */ - if (! gc->degraded) { - ejsGracefulDegrade(ep); - return 0; - } - } - - /* - * Still non available, so allocate more memory for a set of blocks - * OPT -- should bypass mprAlloc. Need mprMalloc. - */ - block = mprAlloc(ep->slabAllocContext, - slab->size * slab->allocIncrement); - if (block == 0) { - /* - * Now we're in trouble. We should really never get here - * as the graceful degrade will have signaled a memory - * allocation failure. - */ - mprAssert(block != 0); - return 0; - } - - /* - * Chain all the blocks together onto the slab free list - */ - for (i = slab->allocIncrement - 1; i >= 0; i--) { - block->next = slab->freeList.next; -#if BLD_DEBUG - block->magic = EJS_MAGIC_FREE; -#endif - slab->freeList.next = block; - block = (EjsGCLink*) ((char*) block + slab->size); - } - - block = slab->freeList.next; - -#if BLD_FEATURE_ALLOC_STATS - slab->freeCount += slab->allocIncrement; - if (slab->freeCount > slab->peakFree) { - slab->peakFree = slab->freeCount; - } -#endif - } - } - - /* - * We use block to point to the user data in the block. We only - * store the magic number (if debug). No other data is stored in the - * user block. - */ -#if BLD_DEBUG - mprAssert(block->magic == EJS_MAGIC_FREE); -#endif - - /* - * Remove from the free list - */ - slab->freeList.next = block->next; - - /* - * Zero block - */ - memset(block, 0, slab->size); - -#if BLD_DEBUG - block->magic = EJS_MAGIC; -#endif - -#if BLD_FEATURE_ALLOC_STATS - slab->totalAlloc++; - if (++slab->allocCount > slab->peakAllocated) { - slab->peakAllocated = slab->allocCount; - } - slab->freeCount--; -#endif - -#if BLD_DEBUG && (!BREW || BREW_SIMULATOR) - if ((uint) block == breakAddr) { - mprBreakpoint(MPR_LOC, "Watched Block"); - } -#endif - return block; -} - - -/******************************************************************************/ - -EjsObj *ejsAllocObj(EJS_LOC_DEC(ep, loc)) -{ - EjsObj *obj; - EjsSlab *slab; - - obj = (EjsObj*) ejsAlloc(EJS_LOC_PASS(ep, loc), EJS_SLAB_OBJ); - - /* - * Add to the allocated block list for the New generation. - */ - if (obj) { - slab = &ep->slabs[EJS_SLAB_OBJ]; - obj->gc.next = slab->allocList[EJS_GEN_NEW].next; - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - obj->gc.allocatedBy = loc; -#endif - - obj->ejs = ep; - slab->allocList[EJS_GEN_NEW].next = (EjsGCLink*) obj; - - ep->gc.workDone++; - } - - return obj; -} - - -/******************************************************************************/ - -EjsProperty *ejsAllocProperty(EJS_LOC_DEC(ep, loc)) -{ - EjsProperty *prop; - - prop = (EjsProperty*) ejsAlloc(EJS_LOC_PASS(ep, loc), EJS_SLAB_PROPERTY); - mprAssert(prop); - - if (prop) { - prop->var.type = EJS_TYPE_NULL; - prop->var.isProperty = 1; -#if BLD_FEATURE_ALLOC_LEAK_TRACK - prop->var.gc.allocatedBy = loc; -#endif - } - return prop; -} - - -/******************************************************************************/ - -EjsVar *ejsAllocVar(EJS_LOC_DEC(ep, loc)) -{ - EjsVar *vp; - - vp = (EjsVar*) ejsAlloc(EJS_LOC_PASS(ep, loc), EJS_SLAB_VAR); - mprAssert(vp); - - if (vp) { -#if BLD_FEATURE_ALLOC_LEAK_TRACK - EjsSlab *slab; - vp->gc.allocatedBy = loc; - slab = &ep->slabs[EJS_SLAB_VAR]; - vp->gc.next = slab->allocList[EJS_GEN_NEW].next; - slab->allocList[EJS_GEN_NEW].next = (EjsGCLink*) vp; -#endif -#if BLD_DEBUG - vp->propertyName = 0; -#endif - } - return vp; -} - - -/******************************************************************************/ -/* - * Return the block back to the relevant slab - */ - -void ejsFree(Ejs *ep, void *ptr, int slabIndex) -{ - EjsSlab *slab; - EjsGCLink *block; - - mprAssert(ep); - mprAssert(ptr); - - if (slabIndex < 0 || slabIndex >= EJS_SLAB_MAX) { - mprAssert(slabIndex >= 0 && slabIndex < EJS_SLAB_MAX); - return; - } - slab = &ep->slabs[slabIndex]; - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - if (slabIndex == EJS_SLAB_VAR) { - EjsVar *vp, *np, *prev; - - /* - * Remove the block rom the alloc list. WARNING: this is slow - * and should not be used in production code. - */ - vp = (EjsVar*) ptr; - prev = 0; - for (np = (EjsVar*) slab->allocList[0].next; np; - np = (EjsVar*) np->gc.next) { - if (vp == np) { - if (prev) { - prev->gc.next = (EjsGCLink*) np->gc.next; - } else { - slab->allocList[0].next = (EjsGCLink*) np->gc.next; - } - break; - } - prev = np; - } - if (np == 0) { - mprAssert(0); - } - } -#endif - - /* - * Insert into the free list. Only use the next ptr - */ - block = (EjsGCLink*) ptr; - -#if BLD_DEBUG -#if !BREW || BREW_SIMULATOR - if ((uint) block == breakAddr) { - mprBreakpoint(MPR_LOC, "Watched Block"); - } -#endif - mprAssert(block->magic == EJS_MAGIC); - block->magic = EJS_MAGIC_FREE; -#endif - - block->next = slab->freeList.next; - slab->freeList.next = block; - -#if BLD_FEATURE_ALLOC_STATS - slab->allocCount--; - if (++slab->freeCount >= slab->peakFree) { - slab->peakFree = slab->freeCount; - } - slab->totalReclaimed++; - if (slabIndex != 2) { - slabIndex = slabIndex; - } -#endif -} - -/******************************************************************************/ -/* - * Mark an object as being in-use. Traverse all properties for referenced - * objects and base classes. - */ - -static void markObjByVar(Ejs *ep, EjsVar *obj) -{ - EjsProperty *pp; - EjsVar *vp, *baseClass; - - mprAssert(ep); - mprAssert(obj); - - obj->objectState->gcMarked = 1; - -#if BLD_DEBUG - if (ep->gc.debugLevel >= 3) { - int indent = min(ep->gc.gcIndent * 2, 32); - mprLog(ep, 0, "%.*s %-24s %.*s 0x%08X", - indent, " ", - obj->propertyName, - 32 - indent, "................................ ", - (uint) obj->objectState); - ep->gc.gcIndent++; - } - ep->gc.objectsInUse++; -#endif - - /* - * Traverse all referenced objects - * OPT -- optimize by directly accessing the object links and not using - * ejsGetFirst/NextProperty. Then just examine objects - * OPT -- first property in global is global. Should optimize this. - */ - pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL); - while (pp) { - vp = ejsGetVarPtr(pp); - if (vp->type == EJS_TYPE_OBJECT) { - if (!vp->objectState->gcMarked) { -#if FUTURE - /* - * OPT -- we can use the dirty bit on objects to avoid - * visiting permanent objects that are clean. If so, don't - * forget the else case below. - */ - obj = vp->objectState; - if ((!obj->alive && !obj->permanent) || obj->dirty) -#endif - markObjByVar(ep, vp); - } - - } else { -#if BLD_DEBUG - if (ep->gc.debugLevel >= 3) { - int indent = min(ep->gc.gcIndent * 2, 32); - mprLog(ep, 0, "%.*s %-24s %.*s %s", - indent, " ", - vp->propertyName, - 32 - indent, "................................ ", - ejsGetVarTypeAsString(vp)); - } - ep->gc.propertiesInUse++; -#endif - } - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - - /* - * Traverse the base class - */ - baseClass = obj->objectState->baseClass; - if (baseClass) { - mprAssert(baseClass->type == EJS_TYPE_OBJECT); - mprAssert(baseClass->objectState); - if (baseClass->objectState) { - if (! baseClass->objectState->gcMarked) { - markObjByVar(ep, baseClass); - } - } - } -#if BLD_DEBUG - if (ep->gc.debugLevel >= 3) { - ep->gc.gcIndent--; - } -#endif -} - - -/******************************************************************************/ -/* - * Mark phase. Examine all variable frames and the return result. - */ - -static void mark(Ejs *ep) -{ - EjsVar *vp; - int i; - -#if BLD_DEBUG - if (ep->gc.debugLevel >= 3) { - mprLog(ep, 0, " "); - mprLog(ep, 0, "GC: Marked Blocks:"); - } -#endif - - if (ep->frames) { - for (i = 0; i < mprGetItemCount(ep->frames); i++) { - - vp = (EjsVar*) mprGetItem(ep->frames, i); - mprAssert(vp->type == EJS_TYPE_OBJECT); - - if (! vp->objectState->gcMarked) { - markObjByVar(ep, vp); - } - } - } - - vp = ep->result; - if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) { - markObjByVar(ep, vp); - } - - vp = ep->currentObj; - if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) { - markObjByVar(ep, vp); - } - - vp = ejsGetVarPtr(ep->currentProperty); - if (vp && vp->type == EJS_TYPE_OBJECT && ! vp->objectState->gcMarked) { - markObjByVar(ep, vp); - } - - /* - * OPT -- we could mark master as "mark permanent" somehow and - * then we would not need to walk the master objects. - */ - if (ep->slabAllocContext == ep->service->master) { - if (ep->service->master->global) { - markObjByVar(ep, ep->service->master->global); - } - } - -#if BLD_DEBUG - if (ep->gc.debugLevel >= 3) { - mprLog(ep, 0, " "); - } -#endif -} - - -/******************************************************************************/ -#if UNUSED - -static void resetMark(EjsVar *obj) -{ - EjsProperty *pp; - EjsVar *vp, *baseClass; - - obj->objectState->gcMarked = 0; - obj->objectState->visited = 1; - - pp = ejsGetFirstProperty(obj, EJS_ENUM_ALL); - while (pp) { - vp = ejsGetVarPtr(pp); - if (vp->type == EJS_TYPE_OBJECT && !vp->objectState->visited) { - resetMark(vp); - } - pp = ejsGetNextProperty(pp, EJS_ENUM_ALL); - } - - baseClass = obj->objectState->baseClass; - if (baseClass) { - mprAssert(baseClass->type == EJS_TYPE_OBJECT); - mprAssert(baseClass->objectState); - if (baseClass->objectState) { - if (! baseClass->objectState->visited) { - resetMark(baseClass); - } - } - } - obj->objectState->visited = 0; -} - -/******************************************************************************/ -/* - * Mark phase. Examine all variable frames and the return result. - */ - -static void resetAllMarks(Ejs *ep) -{ - EjsVar *vp; - int i; - - for (i = 0; i < mprGetItemCount(ep->frames); i++) { - vp = (EjsVar*) mprGetItem(ep->frames, i); - resetMark(vp); - } - - if (ep->result && ep->result->type == EJS_TYPE_OBJECT && - ! ep->result->objectState->gcMarked) { - resetMark(ep->result); - } -} - -#endif -/******************************************************************************/ -/* - * Sweep up the garbage - */ - -static void resetMarks(Ejs *ep, EjsSlab *slab) -{ - EjsVar *vp; - EjsObj *obj; - int gen, i; - - for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) { - obj = (EjsObj*) slab->allocList[gen].next; - for (; obj; obj = (EjsObj*) obj->gc.next) { - obj->gcMarked = 0; - obj->visited = 0; - } - } - - if (ep->frames) { - for (i = 0; i < mprGetItemCount(ep->frames); i++) { - - vp = (EjsVar*) mprGetItem(ep->frames, i); - mprAssert(vp->type == EJS_TYPE_OBJECT); - - vp->objectState->gcMarked = 0; - vp->objectState->visited = 0; - } - } - - if (ep->result && ep->result->type == EJS_TYPE_OBJECT) { - ep->result->objectState->gcMarked = 0; - } -} - -/******************************************************************************/ -/* - * Mark all permanent and non-alive objects - */ - -static void markPerm(Ejs *ep, uint gen) -{ - EjsSlab *slab; - EjsObj *obj; - - slab = &ep->slabs[EJS_SLAB_OBJ]; - - for (obj = (EjsObj*) slab->allocList[gen].next; obj; ) { - - if (! obj->gcMarked) { - if (!obj->alive || obj->permanent) { - markObj(obj); - } - } - obj = (EjsObj*) obj->gc.next; - - } -} - -/******************************************************************************/ - -static void markObj(EjsObj *obj) -{ - EjsProperty *pp; - EjsPropLink *lp, *head; - EjsObj *op; - - mprAssert(obj); - - obj->gcMarked = 1; - - head = &obj->link; - for (lp = head->next; lp != head; lp = lp->next) { - - pp = ejsGetPropertyFromLink(lp); - - if (pp->var.type == EJS_TYPE_OBJECT) { - op = pp->var.objectState; - if (op != 0 && !op->gcMarked) { - markObj(op); - } - } - } -} - -/******************************************************************************/ -/* - * Sweep up the garbage. Return the number of objects freed. - */ - -static int sweep(Ejs *ep, uint gen) -{ - EjsSlab *slab; - EjsObj *obj, *next, *prev; - int count; - - slab = &ep->slabs[EJS_SLAB_OBJ]; - - /* - * Examine allocated objects in the specified generation (only). - * NOTE: we only sweep object allocated to this interpreter and so - * we do not sweep any permanent objects in the default interpreter. - */ - prev = 0; - count = 0; - for (obj = (EjsObj*) slab->allocList[gen].next; obj; obj = next) { - - next = (EjsObj*) obj->gc.next; - -#if BLD_DEBUG && (!BREW || BREW_SIMULATOR) - if ((uint) obj == breakAddr) { - mprBreakpoint(MPR_LOC, "Watched Block"); - } -#endif - - /* - * If object has not been marked inuse and is not a permanent - * object, then free it. - */ - if (! obj->gcMarked && obj->alive && !obj->permanent) { - -#if BLD_DEBUG - if (ep->gc.debugLevel >= 2) { - if (obj->objName) { - mprLog(ep, 0, "GC: destroy %-18s %10d, %8X", - obj->objName, (uint) obj, (uint) obj); - } else { - mprLog(ep, 0, "GC: destroy UNKNOWN %x", (uint) obj); - } - } -#endif - if (ejsDestroyObj(ep, obj) < 0) { - prev = obj; - obj->gcMarked = 0; - continue; - } - - if (prev) { - prev->gc.next = (EjsGCLink*) next; - } else { - slab->allocList[gen].next = (EjsGCLink*) next; - } - count++; - - } else { - prev = obj; - /* Reset for next time */ - obj->gcMarked = 0; - } - } - - if (gen == (EJS_GEN_OLD - 1)) { - slab->lastRecentBlock = prev; - } -#if BLD_FEATURE_ALLOC_STATS - slab->totalSweeps++; -#endif -#if BLD_DEBUG - if (ep->gc.debugLevel > 0) { - mprLog(ep, 0, "GC: Sweep freed %d objects", count); - } -#endif - return count; -} - -/******************************************************************************/ -/* - * Sweep all variables - */ - -void ejsSweepAll(Ejs *ep) -{ - EjsSlab *slab; - EjsObj *obj, *next, *prev; - int gen; - - slab = &ep->slabs[EJS_SLAB_OBJ]; - - for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) { - prev = 0; - for (obj = (EjsObj*) slab->allocList[gen].next; obj; obj = next) { - next = (EjsObj*) obj->gc.next; - ejsDestroyObj(ep, obj); - } - break; - } -} - -/******************************************************************************/ - -bool ejsObjIsCollectable(EjsVar *vp) -{ - if (vp == 0 || !ejsVarIsObject(vp)) { - return 0; - } - return (vp->objectState->alive && !vp->objectState->permanent); -} - -/******************************************************************************/ -#if FUTURE - -static void ageGenerations(Ejs *ep) -{ - EjsSlab *slab; - EjsGCLink *oldList; - int gen; - - slab = &ep->slabs[EJS_SLAB_OBJ]; - - /* - * Age all blocks. First append all (old - 1) blocks onto the old - * alloc list - */ - oldList = &slab->allocList[EJS_GEN_OLD]; - - if (slab->lastRecentBlock) { - slab->lastRecentBlock->gc.next = oldList->next; - oldList->next = (EjsGCLink*) slab->lastRecentBlock; - } - - /* - * Now simply copy all allocation lists up one generation - */ - for (gen = EJS_GEN_OLD - 1; gen > 0; gen--) { - slab->allocList[gen] = slab->allocList[gen - 1]; - } - slab->allocList[0].next = 0; -} - -#endif -/******************************************************************************/ -/* - * Collect the garbage. This is a mark and sweep over all possible objects. - * If an object is not referenced, it and all contained properties will be - * freed. If a slabIndex is provided, the collection halts when a block is - * available for allocation on that slab. - * - * Return 0 if memory is now available after collecting garbage. Otherwise, - * return MPR_ERR_MEMORY. - */ - -int ejsCollectGarbage(Ejs *ep, int slabIndex) -{ - EjsGeneration gen; - - if (ep->flags & EJS_FLAGS_DONT_GC) { - return -1; - } - - /* - * Prevent destructors invoking the garbage collector - */ - if (ep->gc.collecting) { - return 0; - } - ep->gc.collecting = 1; - - resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]); - - /* - * Examine each generation of objects starting with the most recent - * generation. Stop scanning when we have a free block to use. - */ - for (gen = EJS_GEN_NEW; gen < EJS_GEN_MAX; gen++) { - - if (slabIndex >= 0 && ep->slabs[slabIndex].freeList.next) { - break; - } - - /* - * FUTURE OPT. Should mark objects in new generation and those - * with a dirty bit set in older generations. Don't need to mark - * entire heap. But how to keep list of dirty objects. - */ - mark(ep); - markPerm(ep, gen); - sweep(ep, gen); - - /* FUTURE - not using generations yet */ - break; - } - - /* - * FUTURE -- not using generations yet. - * - * ageGenerations(ep); - */ - - ep->gc.workDone = 0; - ep->gc.collecting = 0; - - return (gen < EJS_GEN_MAX) ? 0 : MPR_ERR_MEMORY; -} - - -/******************************************************************************/ -/* - * Should be called when the app has been idle for a little while and when it - * is likely to be idle a bit longer. Call ejsIsTimeForGC to see if this is - * true. Return the count of objects collected . - */ - -int ejsIncrementalCollectGarbage(Ejs *ep) -{ - int count; - - if (ep->gc.collecting) { - return 0; - } - - ep->gc.collecting = 1; - - resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]); - mark(ep); - - /* Not generational yet */ - count = sweep(ep, EJS_GEN_NEW); - - ep->gc.collecting = 0; - ep->gc.workDone = 0; - - return count; -} - -/******************************************************************************/ -#if BLD_DEBUG - -void ejsDumpObjects(Ejs *ep) -{ - int oldDebugLevel; - - mprLog(ep, 0, "Dump of objects in use\n"); - - oldDebugLevel = ep->gc.debugLevel; - - ep->gc.debugLevel = 3; - ep->gc.objectsInUse = 0; - ep->gc.propertiesInUse = 0; - ep->gc.collecting = 1; - - resetMarks(ep, &ep->slabs[EJS_SLAB_OBJ]); - mark(ep); - - ep->gc.collecting = 0; - ep->gc.debugLevel = oldDebugLevel; - - mprLog(ep, 0, "%d objects and %d properties in use", - ep->gc.objectsInUse, ep->gc.propertiesInUse); - mprLog(ep, 0, "%d object bytes, %d property bytes and %d total", - (int) (ep->gc.objectsInUse * sizeof(EjsObj)), - (int) (ep->gc.propertiesInUse * sizeof(EjsProperty)), - (int) ((ep->gc.objectsInUse * sizeof(EjsObj) + - ep->gc.propertiesInUse * sizeof(EjsProperty)))); -} - -#endif -/******************************************************************************/ -/* - * Return true if there is time to do a garbage collection and if we will - * benefit from it. - */ - -int ejsIsTimeForGC(Ejs *ep, int timeTillNextEvent) -{ - EjsGC *gc; - - if (timeTillNextEvent < EJS_MIN_TIME_FOR_GC) { - /* - * Not enough time to complete a collection - */ - return 0; - } - - gc = &ep->gc; - - /* - * Return if we haven't done enough work to warrant a collection - * Trigger a little short of the work quota to try to run GC before - * a demand allocation requires it. - */ - if (!gc->enable || !gc->enableIdleCollect || - (gc->workDone < (gc->workQuota - EJS_GC_MIN_WORK_QUOTA))) { - return 0; - } - -#if UNUSED - mprLog(ep, 0, "Time for GC. Work done %d, time till next event %d", - gc->workDone, timeTillNextEvent); -#endif - return 1; -} - -/******************************************************************************/ -/* - * Return the amount of memory in use by EJS - */ - -uint ejsGetUsedMemory(Ejs *ep) -{ -#if BLD_FEATURE_ALLOC_STATS - EjsSlab *slab; - int i, totalMemory, slabMemory; - - totalMemory = 0; - for (i = 0; i < EJS_SLAB_MAX; i++) { - slab = &ep->slabs[i]; - slabMemory = slab->allocCount * slab->size; - totalMemory += slabMemory; - } - return totalMemory; -#else - return 0; -#endif -} - -/******************************************************************************/ -/* - * Return the amount of memory allocated by EJS - */ - -uint ejsGetAllocatedMemory(Ejs *ep) -{ -#if BLD_FEATURE_ALLOC_STATS - EjsSlab *slab; - int i, totalMemory, slabMemory; - - totalMemory = 0; - for (i = 0; i < EJS_SLAB_MAX; i++) { - slab = &ep->slabs[i]; - slabMemory = (slab->allocCount + slab->freeCount) * slab->size; - totalMemory += slabMemory; - } - return totalMemory; -#else - return 0; -#endif -} - -/******************************************************************************/ -/* - * On a memory allocation failure, go into graceful degrade mode. Set all - * slab allocation chunk increments to 1 so we can create an exception block - * to throw. - */ - -static void ejsGracefulDegrade(Ejs *ep) -{ - EjsSlab *slab; - int i; - - mprLog(ep, 1, "WARNING: Memory almost depleted. In graceful degrade mode"); - for (i = 0; i < EJS_SLAB_MAX; i++) { - slab = &ep->slabs[i]; - slab->allocIncrement = 8; - } - ep->gc.degraded = 1; -} - -/******************************************************************************/ - -int ejsSetGCDebugLevel(Ejs *ep, int debugLevel) -{ - int old; - - old = ep->gc.debugLevel; - ep->gc.debugLevel = debugLevel; - return old; -} - -/******************************************************************************/ - -int ejsSetGCMaxMemory(Ejs *ep, uint maxMemory) -{ - int old; - - old = ep->gc.maxMemory; - ep->gc.maxMemory = maxMemory; - - return old; -} - -/******************************************************************************/ - -bool ejsBlockInUseInt(EjsVar *vp) -{ - if (vp) { -#if BLD_DEBUG - if (vp->gc.magic != EJS_MAGIC) { - return 0; - } - if (vp->type == EJS_TYPE_OBJECT && vp->objectState && - vp->objectState->gc.magic != EJS_MAGIC) { - return 0; - } -#endif - return 1; - } - return 1; -} - -/******************************************************************************/ -#else -void ejsGarbageDummy() {} - -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c b/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c deleted file mode 100644 index fbfee6e4d5..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsLex.c +++ /dev/null @@ -1,1033 +0,0 @@ -/* - * @file ejsLex.c - * @brief EJS Lexical Analyser - * @overview EJS lexical analyser. This implementes a lexical analyser - * for a subset of the JavaScript language. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static int getLexicalToken(Ejs *ep, int state); -static int tokenAddChar(Ejs *ep, int c); -static int inputGetc(Ejs *ep); -static void inputPutback(Ejs *ep, int c); -static int charConvert(Ejs *ep, int base, int maxDig); -static void parseNumber(Ejs *ep, EjsType type); - -/************************************* Code ***********************************/ -/* - * Open a new input script - */ - -int ejsLexOpenScript(Ejs *ep, const char *script) -{ - EjsInput *ip; - - mprAssert(ep); - mprAssert(script); - - if ((ip = mprAllocTypeZeroed(ep, EjsInput)) == NULL) { - return MPR_ERR_MEMORY; - } - ip->next = ep->input; - ep->input = ip; - ip->procName = ep->proc ? ep->proc->procName : NULL; - ip->fileName = ep->fileName ? ep->fileName : NULL; - -/* - * Create the parse token buffer and script buffer - */ - ip->tokServp = ip->tokbuf; - ip->tokEndp = ip->tokbuf; - - ip->script = script; - ip->scriptSize = strlen(script); - ip->scriptServp = (char*) ip->script; - - ip->lineNumber = 1; - ip->lineColumn = 0; - - ip->putBackIndex = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the input script - */ - -void ejsLexCloseScript(Ejs *ep) -{ - EjsInput *ip; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - ep->input = ip->next; - - mprFree(ip); -} - -/******************************************************************************/ -/* - * Initialize an input state structure - */ - -int ejsInitInputState(EjsInput *ip) -{ - mprAssert(ip); - - memset(ip, 0, sizeof(*ip)); - ip->putBackIndex = -1; - - return 0; -} -/******************************************************************************/ -/* - * Save the input state - */ - -void ejsLexSaveInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - - *state = *ip; - - for (i = 0; i <= ip->putBackIndex; i++) { - mprStrcpy(state->putBack[i].tokbuf, EJS_MAX_TOKEN, - ip->putBack[i].tokbuf); - state->putBack[i].tid = ip->putBack[i].tid; - } - - mprStrcpy(state->line, sizeof(state->line), ip->line); - - state->lineColumn = ip->lineColumn; - state->lineNumber = ip->lineNumber; -} - -/******************************************************************************/ -/* - * Restore the input state - */ - -void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - EjsToken *tp; - int i; - - mprAssert(ep); - mprAssert(state); - - ip = ep->input; - mprAssert(ip); - - mprStrcpy(ip->tokbuf, sizeof(ip->tokbuf), state->tokbuf); - ip->tokServp = state->tokServp; - ip->tokEndp = state->tokEndp; - - ip->script = state->script; - ip->scriptServp = state->scriptServp; - ip->scriptSize = state->scriptSize; - - ip->putBackIndex = state->putBackIndex; - for (i = 0; i <= ip->putBackIndex; i++) { - tp = &ip->putBack[i]; - tp->tid = state->putBack[i].tid; - mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), state->putBack[i].tokbuf); - } - - mprStrcpy(ip->line, sizeof(ip->line), state->line); - - ip->lineColumn = state->lineColumn; - ip->lineNumber = state->lineNumber; -} - -/******************************************************************************/ -/* - * Free a saved input state - */ - -void ejsLexFreeInputState(Ejs *ep, EjsInput *state) -{ - mprAssert(ep); - mprAssert(state); - - state->putBackIndex = -1; - state->lineColumn = 0; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -int ejsLexGetToken(Ejs *ep, int state) -{ - mprAssert(ep); - - ep->tid = getLexicalToken(ep, state); - return ep->tid; -} - -/******************************************************************************/ - -/* - * Check for reserved words "if", "else", "var", "for", "delete", "function", - * "class", "extends", "public", "private", "protected", "try", "catch", - * "finally", "throw", "return", "get", "set", "this", "module", "each" - * - * The "new" and "in" reserved words are handled below. The "true", "false", - * "null" "typeof" and "undefined" reserved words are handled as global - * objects. - * - * Other reserved words not supported: - * "break", "case", "continue", "default", "do", - * "instanceof", "switch", "while", "with" - * - * ECMA extensions reserved words (not supported): - * "abstract", "boolean", "byte", "char", "const", - * "debugger", "double", "enum", "export", - * "final", "float", "goto", "implements", "import", "int", - * "interface", "long", "native", "package", - * "short", "static", "super", "synchronized", "transient", "volatile" - * - * FUTURE -- use a hash lookup - */ - -static int checkReservedWord(Ejs *ep, int state, int c, int tid) -{ - /* FUTURE -- probably should return for all tokens != EJS_TOK_ID */ - /* FUTURE -- Should have a hash for this. MUCH faster. */ - - if (!isalpha(ep->token[0]) || tid == EJS_TOK_LITERAL) { - return tid; - } - if (state == EJS_STATE_STMT) { - /* FUTURE OPT -- convert to hash lookup */ - if (strcmp(ep->token, "if") == 0) { - inputPutback(ep, c); - return EJS_TOK_IF; - } else if (strcmp(ep->token, "else") == 0) { - inputPutback(ep, c); - return EJS_TOK_ELSE; - } else if (strcmp(ep->token, "var") == 0) { - inputPutback(ep, c); - return EJS_TOK_VAR; - } else if (strcmp(ep->token, "new") == 0) { - inputPutback(ep, c); - return EJS_TOK_NEW; - } else if (strcmp(ep->token, "for") == 0) { - inputPutback(ep, c); - return EJS_TOK_FOR; - } else if (strcmp(ep->token, "delete") == 0) { - inputPutback(ep, c); - return EJS_TOK_DELETE; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } else if (strcmp(ep->token, "class") == 0) { - inputPutback(ep, c); - return EJS_TOK_CLASS; - } else if (strcmp(ep->token, "module") == 0) { - inputPutback(ep, c); - return EJS_TOK_MODULE; - } else if (strcmp(ep->token, "extends") == 0) { - inputPutback(ep, c); - return EJS_TOK_EXTENDS; - } else if (strcmp(ep->token, "try") == 0) { - inputPutback(ep, c); - return EJS_TOK_TRY; - } else if (strcmp(ep->token, "catch") == 0) { - inputPutback(ep, c); - return EJS_TOK_CATCH; - } else if (strcmp(ep->token, "finally") == 0) { - inputPutback(ep, c); - return EJS_TOK_FINALLY; - } else if (strcmp(ep->token, "throw") == 0) { - inputPutback(ep, c); - return EJS_TOK_THROW; - } else if (strcmp(ep->token, "public") == 0) { - inputPutback(ep, c); - return EJS_TOK_PUBLIC; - } else if (strcmp(ep->token, "protected") == 0) { - inputPutback(ep, c); - return EJS_TOK_PROTECTED; - } else if (strcmp(ep->token, "private") == 0) { - inputPutback(ep, c); - return EJS_TOK_PRIVATE; - } else if (strcmp(ep->token, "get") == 0) { - inputPutback(ep, c); - return EJS_TOK_GET; - } else if (strcmp(ep->token, "set") == 0) { - inputPutback(ep, c); - return EJS_TOK_SET; - } else if (strcmp(ep->token, "extends") == 0) { - inputPutback(ep, c); - return EJS_TOK_EXTENDS; - } else if (strcmp(ep->token, "try") == 0) { - inputPutback(ep, c); - return EJS_TOK_TRY; - } else if (strcmp(ep->token, "catch") == 0) { - inputPutback(ep, c); - return EJS_TOK_CATCH; - } else if (strcmp(ep->token, "finally") == 0) { - inputPutback(ep, c); - return EJS_TOK_FINALLY; - } else if (strcmp(ep->token, "throw") == 0) { - inputPutback(ep, c); - return EJS_TOK_THROW; - } else if (strcmp(ep->token, "public") == 0) { - inputPutback(ep, c); - return EJS_TOK_PUBLIC; - } else if (strcmp(ep->token, "protected") == 0) { - inputPutback(ep, c); - return EJS_TOK_PROTECTED; - } else if (strcmp(ep->token, "private") == 0) { - inputPutback(ep, c); - return EJS_TOK_PRIVATE; - } else if (strcmp(ep->token, "get") == 0) { - inputPutback(ep, c); - return EJS_TOK_GET; - } else if (strcmp(ep->token, "set") == 0) { - inputPutback(ep, c); - return EJS_TOK_SET; - } else if (strcmp(ep->token, "each") == 0) { - inputPutback(ep, c); - return EJS_TOK_EACH; - } else if (strcmp(ep->token, "return") == 0) { - if ((c == ';') || (c == '(')) { - inputPutback(ep, c); - } - return EJS_TOK_RETURN; - } - - } else if (state == EJS_STATE_EXPR) { - if (strcmp(ep->token, "new") == 0) { - inputPutback(ep, c); - return EJS_TOK_NEW; - } else if (strcmp(ep->token, "in") == 0) { - inputPutback(ep, c); - return EJS_TOK_IN; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } - - } else if (state == EJS_STATE_DEC) { - if (strcmp(ep->token, "extends") == 0) { - inputPutback(ep, c); - return EJS_TOK_EXTENDS; - } - } - return tid; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -static int getLexicalToken(Ejs *ep, int state) -{ - EjsType type; - EjsInput *ip; - int done, tid, c, quote, style, idx, isHex; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ep->tid = -1; - tid = -1; - type = BLD_FEATURE_NUM_TYPE_ID; - isHex = 0; - - /* - * Use a putback tokens first. Don't free strings as caller needs access. - */ - if (ip->putBackIndex >= 0) { - idx = ip->putBackIndex; - tid = ip->putBack[idx].tid; - ep->token = (char*) ip->putBack[idx].tokbuf; - tid = checkReservedWord(ep, state, 0, tid); - ip->putBackIndex--; - return tid; - } - ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; - *ip->tokServp = '\0'; - - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - - /* - * Main lexical analyser - */ - for (done = 0; !done; ) { - switch (c) { - case -1: - return EJS_TOK_EOF; - - case ' ': - case '\t': - case '\r': - do { - if ((c = inputGetc(ep)) < 0) - break; - } while (c == ' ' || c == '\t' || c == '\r'); - break; - - case '\n': - return EJS_TOK_NEWLINE; - - case '(': - tokenAddChar(ep, c); - return EJS_TOK_LPAREN; - - case ')': - tokenAddChar(ep, c); - return EJS_TOK_RPAREN; - - case '[': - tokenAddChar(ep, c); - return EJS_TOK_LBRACKET; - - case ']': - tokenAddChar(ep, c); - return EJS_TOK_RBRACKET; - - case '.': - tokenAddChar(ep, c); - return EJS_TOK_PERIOD; - - case '{': - tokenAddChar(ep, c); - return EJS_TOK_LBRACE; - - case '}': - tokenAddChar(ep, c); - return EJS_TOK_RBRACE; - - case '+': - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c != '+' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_PLUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_INC); - return EJS_TOK_INC_DEC; - - case '-': - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c != '-' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_MINUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_DEC); - return EJS_TOK_INC_DEC; - - case '*': - tokenAddChar(ep, EJS_EXPR_MUL); - return EJS_TOK_EXPR; - - case '%': - tokenAddChar(ep, EJS_EXPR_MOD); - return EJS_TOK_EXPR; - - case '/': - /* - * Handle the division operator and comments - */ - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c != '*' && c != '/') { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_DIV); - return EJS_TOK_EXPR; - } - style = c; - /* - * Eat comments. Both C and C++ comment styles are supported. - */ - while (1) { - if ((c = inputGetc(ep)) < 0) { - if (style == '/') { - return EJS_TOK_EOF; - } - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c == '\n' && style == '/') { - break; - } else if (c == '*') { - c = inputGetc(ep); - if (style == '/') { - if (c == '\n') { - break; - } - } else { - if (c == '/') { - break; - } - } - } - } - /* - * Continue looking for a token, so get the next character - */ - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - break; - - case '<': /* < and <= */ - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c == '<') { - tokenAddChar(ep, EJS_EXPR_LSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_LESSEQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_LESS); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '>': /* > and >= */ - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c == '>') { - tokenAddChar(ep, EJS_EXPR_RSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_GREATEREQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_GREATER); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '=': /* "==" */ - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_EQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - return EJS_TOK_ASSIGNMENT; - - case '!': /* "!=" or "!"*/ - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_NOTEQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_BOOL_COMP); - return EJS_TOK_EXPR; - - case ';': - tokenAddChar(ep, c); - return EJS_TOK_SEMI; - - case ',': - tokenAddChar(ep, c); - return EJS_TOK_COMMA; - - case ':': - tokenAddChar(ep, c); - return EJS_TOK_COLON; - - case '|': /* "||" */ - if ((c = inputGetc(ep)) < 0 || c != '|') { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_OR); - return EJS_TOK_LOGICAL; - - case '&': /* "&&" */ - if ((c = inputGetc(ep)) < 0 || c != '&') { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_AND); - return EJS_TOK_LOGICAL; - - case '\"': /* String quote */ - case '\'': - quote = c; - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, 0); - return EJS_TOK_ERR; - } - - while (c != quote) { - /* - * Check for escape sequence characters - */ - if (c == '\\') { - c = inputGetc(ep); - - if (isdigit(c)) { - /* - * Octal support, \101 maps to 65 = 'A'. Put first - * char back so converter will work properly. - */ - inputPutback(ep, c); - c = charConvert(ep, 8, 3); - - } else { - switch (c) { - case 'n': - c = '\n'; break; - case 'b': - c = '\b'; break; - case 'f': - c = '\f'; break; - case 'r': - c = '\r'; break; - case 't': - c = '\t'; break; - case 'x': - /* - * Hex support, \x41 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - break; - case 'u': - /* - * Unicode support, \x0401 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - c = c*16 + charConvert(ep, 16, 2); - - break; - case '\'': - case '\"': - case '\\': - break; - default: - if (tokenAddChar(ep, '\\') < 0) { - return EJS_TOK_ERR; - } - } - } - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } else { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } - if ((c = inputGetc(ep)) < 0) { - ejsSyntaxError(ep, "Unmatched Quote"); - return EJS_TOK_ERR; - } - } - return EJS_TOK_LITERAL; - - case '0': - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (tolower(c) == 'x') { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - isHex = 1; - if (! isxdigit(c)) { - parseNumber(ep, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - } else if (! isdigit(c)) { -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { - /* Fall through */ - type = EJS_TYPE_FLOAT; - } else -#endif - { - parseNumber(ep, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - } - /* Fall through to get more digits */ - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (isHex) { - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - } while (isxdigit(c)); - - } else { -#if BLD_FEATURE_FLOATING_POINT - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - c = tolower(c); - if (c == '.' || c == 'e' || c == 'f') { - type = EJS_TYPE_FLOAT; - } - } while (isdigit(c) || c == '.' || c == 'e' || - c == 'f' || - ((type == EJS_TYPE_FLOAT) && (c == '+' || c == '-'))); -#else - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - } while (isdigit(c)); -#endif - } - - parseNumber(ep, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - - default: - /* - * Identifiers or a function names - */ - while (1) { - if (c == '\\') { - if ((c = inputGetc(ep)) < 0) { - break; - } - if (c == '\n' || c == '\r') { - break; - } - } else if (tokenAddChar(ep, c) < 0) { - break; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (!isalnum(c) && c != '$' && c != '_' && - c != '\\' && c != '@') { - break; - } - } - if (*ep->token == '\0') { - c = inputGetc(ep); - break; - } - - if (! isalpha((int) *ep->token) && *ep->token != '$' && - *ep->token != '_' && *ep->token != '@') { - ejsError(ep, EJS_SYNTAX_ERROR, "Invalid identifier %s", - ep->token); - return EJS_TOK_ERR; - } - - tid = checkReservedWord(ep, state, c, EJS_TOK_ID); - if (tid != EJS_TOK_ID) { - return tid; - } - - /* - * Skip white space after token to find out whether this is - * a function or not. - */ - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if ((c = inputGetc(ep)) < 0) - break; - } - - tid = EJS_TOK_ID; - if ((strlen(ep->token) + 1) >= EJS_MAX_ID) { - ejsError(ep, EJS_SYNTAX_ERROR, - "Identifier too big. Max is %d letters.", EJS_MAX_ID); - return EJS_TOK_ERR; - } - done++; - } - } - - /* - * Putback the last extra character for next time - */ - inputPutback(ep, c); - return tid; -} - -/******************************************************************************/ - -static void parseNumber(Ejs *ep, EjsType type) -{ - switch (type) { - case EJS_TYPE_INT: - ep->tokenNumber.integer = ejsParseInteger(ep->token); - ep->tokenNumber.type = type; - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - ep->tokenNumber.floating = atof(ep->token); - ep->tokenNumber.type = type; - break; -#endif - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - ep->tokenNumber.integer64 = ejsParseInteger64(ep->token); - ep->tokenNumber.type = type; - break; -#endif - } -} - -/******************************************************************************/ -/* - * Convert a hex or octal character back to binary, return original char if - * not a hex digit - */ - -static int charConvert(Ejs *ep, int base, int maxDig) -{ - int i, c, lval, convChar; - - lval = 0; - for (i = 0; i < maxDig; i++) { - if ((c = inputGetc(ep)) < 0) { - break; - } - /* - * Initialize to out of range value - */ - convChar = base; - if (isdigit(c)) { - convChar = c - '0'; - } else if (c >= 'a' && c <= 'f') { - convChar = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - convChar = c - 'A' + 10; - } - /* - * If unexpected character then return it to buffer. - */ - if (convChar >= base) { - inputPutback(ep, c); - break; - } - lval = (lval * base) + convChar; - } - return lval; -} - -/******************************************************************************/ -/* - * Putback the last token read. Accept at most one push back token. - */ - -void ejsLexPutbackToken(Ejs *ep, int tid, char *string) -{ - EjsInput *ip; - EjsToken *tp; - int idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ip->putBackIndex += 1; - - mprAssert(ip->putBackIndex < EJS_TOKEN_STACK); - idx = ip->putBackIndex; - - tp = &ip->putBack[idx]; - tp->tid = tid; - - mprStrcpy(tp->tokbuf, sizeof(tp->tokbuf), string); -} - -/******************************************************************************/ -/* - * Add a character to the token buffer - */ - -static int tokenAddChar(Ejs *ep, int c) -{ - EjsInput *ip; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - if (ip->tokEndp >= &ip->tokbuf[sizeof(ip->tokbuf) - 1]) { - ejsSyntaxError(ep, "Token too big"); - return -1; - } - *ip->tokEndp++ = c; - *ip->tokEndp = '\0'; - - return 0; -} - -/******************************************************************************/ -/* - * Get another input character - */ - -static int inputGetc(Ejs *ep) -{ - EjsInput *ip; - int c; - - mprAssert(ep); - ip = ep->input; - - if (ip->scriptSize <= 0) { - return -1; - } - - c = (uchar) (*ip->scriptServp++); - ip->scriptSize--; - - /* - * For debugging, accumulate the line number and the currenly parsed line - */ - if (c == '\n') { -#if 0 && BLD_DEBUG - if (ip->lineColumn > 0) { - printf("PARSED: %s\n", ip->line); - } -#endif - ip->lineNumber++; - ip->lineColumn = 0; - } else if ((ip->lineColumn + 2) < sizeof(ip->line)) { - ip->line[ip->lineColumn++] = c; - ip->line[ip->lineColumn] = '\0'; - } - return c; -} - -/******************************************************************************/ -/* - * Putback a character onto the input queue - */ - -static void inputPutback(Ejs *ep, int c) -{ - EjsInput *ip; - - mprAssert(ep); - - if (c > 0) { - ip = ep->input; - *--ip->scriptServp = c; - ip->scriptSize++; - if (--(ip->lineColumn) < 0) { - ip->lineColumn = 0; - } - mprAssert(ip->line); - mprAssert(ip->lineColumn >= 0); - mprAssert(ip->lineColumn < sizeof(ip->line)); - ip->line[ip->lineColumn] = '\0'; - } -} - -/******************************************************************************/ - -#else -void ejsLexDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsParser.c b/source4/lib/appweb/ejs-2.0/ejs/ejsParser.c deleted file mode 100644 index 9fce6d27ee..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsParser.c +++ /dev/null @@ -1,4514 +0,0 @@ -/* - * @file ejsParser.c - * @brief EJS Parser and Execution - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static int createClass(Ejs *ep, EjsVar *parentClass, - const char *className, EjsVar *baseClass); -static int createProperty(Ejs *ep, EjsVar **obj, const char *id, - int state); -static int evalCond(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs); -static int evalExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs); -#if BLD_FEATURE_FLOATING_POINT -static int evalFloatExpr(Ejs *ep, double l, int rel, double r); -#endif -static int evalBoolExpr(Ejs *ep, int l, int rel, int r); -static int evalNumericExpr(Ejs *ep, EjsNum l, int rel, EjsNum r); -static int evalObjExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) ; -static int evalStringExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs); -static int evalMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, int flags); -static EjsProperty *findProperty(Ejs *ep, EjsVar *op, const char *property, - int flags); -static EjsVar *pickSpace(Ejs *ep, int state, const char *property, int flags); -static void freeProc(Ejs *ep, EjsProc *proc); -static int parseArgs(Ejs *ep, int state, int flags); -static int parseArrayLiteral(Ejs *ep, int state, int flags, char *id); -static int parseAssignment(Ejs *ep, int state, int flags, char *id); -static int parseClass(Ejs *ep, int state, int flags); -static int parseForInner(Ejs *ep, int state, int flags, - EjsInput *condScript, EjsInput *incrScript, - EjsInput *bodyScript, EjsInput *endScript); -static int parseCond(Ejs *ep, int state, int flags); -static int parseDeclaration(Ejs *ep, int state, int flags); -static int parseExpr(Ejs *ep, int state, int flags); -static int parseFor(Ejs *ep, int state, int flags); -static int parseRegFor(Ejs *ep, int state, int flags); -static int parseForIn(Ejs *ep, int state, int flags, int each); -static int parseId(Ejs *ep, int state, int flags, char **id, int *done); -static int parseInc(Ejs *ep, int state, int flags); -static int parseIf(Ejs *ep, int state, int flags, int *done); -static int parseFunction(Ejs *ep, int state, int flags); -static int parseMethod(Ejs *ep, int state, int flags, char *id); -static int parseObjectLiteral(Ejs *ep, int state, int flags, char *id); -static int parseStmt(Ejs *ep, int state, int flags); -static int parseThrow(Ejs *ep, int state, int flags); -static int parseTry(Ejs *ep, int state, int flags); -static void removeNewlines(Ejs *ep, int state); -static EjsProperty *searchSpacesForProperty(Ejs *ep, int state, EjsVar *obj, - char *property, int flags); -static int assignPropertyValue(Ejs *ep, char *id, int state, EjsVar *value, - int flags); -static int updateProperty(Ejs *ep, EjsVar *obj, const char *id, int state, - EjsVar *value); -static void updateResult(Ejs *ep, int state, int flags, EjsVar *vp); -static int getNextNonSpaceToken(Ejs *ep, int state); - -static int callConstructor(Ejs *ep, EjsVar *thisObj, EjsVar *baseClass, - MprArray *args); -static int callCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, - EjsVar *prototype); -static int callStringCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, - EjsVar *prototype); -static int callMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, - EjsVar *prototype); -static int runMethod(Ejs *ep, EjsVar *thisObj, EjsVar *method, - const char *methodName, MprArray *args); - -static EjsInput *getInputStruct(Ejs *ep); -static void freeInputStruct(Ejs *ep, EjsInput *input); - -static void *pushFrame(Ejs *ep, int size); -static void *popFrame(Ejs *ep, int size); - -/************************************* Code ***********************************/ -/* - * Recursive descent parser for EJS - */ - -int ejsParse(Ejs *ep, int state, int flags) -{ - mprAssert(ep); - -#if MOB - if (mprStackCheck(ep)) { - char *stack; - stack = ejsFormatStack(ep); - mprLog(ep, 0, "\nStack grew : MAX %d\n", mprStackSize(ep)); - mprLog(ep, 0, "Stack\n %s\n", stack); - mprFree(stack); - } -#endif - - if (ep->flags & EJS_FLAGS_EXIT) { - return EJS_STATE_RET; - } - - ep->inputMarker = ep->input->scriptServp; - - switch (state) { - /* - * Any statement, method arguments or conditional expressions - */ - case EJS_STATE_STMT: - state = parseStmt(ep, state, flags); - if (state != EJS_STATE_STMT_BLOCK_DONE && state != EJS_STATE_STMT_DONE){ - goto err; - } - break; - - case EJS_STATE_DEC: - state = parseStmt(ep, state, flags); - if (state != EJS_STATE_DEC_DONE) { - goto err; - } - break; - - case EJS_STATE_EXPR: - state = parseStmt(ep, state, flags); - if (state != EJS_STATE_EXPR_DONE) { - goto err; - } - break; - - /* - * Variable declaration list - */ - case EJS_STATE_DEC_LIST: - state = parseDeclaration(ep, state, flags); - if (state != EJS_STATE_DEC_LIST_DONE) { - goto err; - } - break; - - /* - * Method argument string - */ - case EJS_STATE_ARG_LIST: - state = parseArgs(ep, state, flags); - if (state != EJS_STATE_ARG_LIST_DONE) { - goto err; - } - break; - - /* - * Logical condition list (relational operations separated by &&, ||) - */ - case EJS_STATE_COND: - state = parseCond(ep, state, flags); - if (state != EJS_STATE_COND_DONE) { - goto err; - } - break; - - /* - * Expression list - */ - case EJS_STATE_RELEXP: - state = parseExpr(ep, state, flags); - if (state != EJS_STATE_RELEXP_DONE) { - goto err; - } - break; - } - - /* - * Recursion protection - */ - if (ep->input->scriptServp == ep->inputMarker) { - if (ep->recurseCount++ > 20) { - ejsSyntaxError(ep, "Input syntax error"); - state = EJS_STATE_ERR; - } - } else { - ep->recurseCount = 0; - } - - if (state == EJS_STATE_RET || state == EJS_STATE_EOF) { - return state; - } - -done: - return state; - -err: - if (state == EJS_STATE_RET || state == EJS_STATE_EOF) { - goto done; - } - if (state != EJS_STATE_ERR) { - ejsSyntaxError(ep, 0); - } - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseStmt { - EjsProc *saveProc; - EjsProperty *pp; - EjsVar *saveObj, *exception; - char *str, *id; - int done, tid, rs, saveObjPerm, expectEndOfStmt; -} ParseStmt; - -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - - -static int parseStmt(Ejs *ep, int state, int flags) -{ - ParseStmt *sp; - - mprAssert(ep); - - if ((sp = pushFrame(ep, sizeof(ParseStmt))) == 0) { - return EJS_STATE_ERR; - } - - sp->id = 0; - sp->expectEndOfStmt = 0; - sp->saveProc = NULL; - - ep->currentObj = 0; - ep->currentProperty = 0; - - for (sp->done = 0; !sp->done && state != EJS_STATE_ERR; ) { - sp->tid = ejsLexGetToken(ep, state); - -#if (WIN || BREW_SIMULATOR) && BLD_DEBUG && DISABLED - /* MOB -- make cross platform */ - _CrtCheckMemory(); -#endif - - switch (sp->tid) { - default: - ejsLexPutbackToken(ep, sp->tid, ep->token); - goto done; - - case EJS_TOK_EXPR: - if (state == EJS_STATE_EXPR) { - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - } - goto done; - - case EJS_TOK_LOGICAL: - ejsLexPutbackToken(ep, sp->tid, ep->token); - goto done; - - case EJS_TOK_ERR: - if (state != EJS_STATE_ERR && !ep->gotException) { - ejsSyntaxError(ep, 0); - } - state = EJS_STATE_ERR; - goto done; - - case EJS_TOK_EOF: - state = EJS_STATE_EOF; - goto done; - - case EJS_TOK_NEWLINE: - break; - - case EJS_TOK_SEMI: - /* - * This case is when we discover no statement and just a lone ';' - */ - if (state != EJS_STATE_STMT) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - } - goto done; - - case EJS_TOK_LBRACKET: - if (flags & EJS_FLAGS_EXE) { - ep->currentObj = &ep->currentProperty->var; - if (ep->currentObj != 0 && ep->currentObj->type != - EJS_TYPE_OBJECT) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Property reference to a non-object type \"%s\"\n", - sp->id); - goto err; - } - } - - sp->saveObj = ep->currentObj; - sp->saveObjPerm = ejsMakeObjPermanent(sp->saveObj, 1); - - sp->rs = ejsParse(ep, EJS_STATE_RELEXP, flags); - - ejsMakeObjPermanent(sp->saveObj, sp->saveObjPerm); - ep->currentObj = sp->saveObj; - - if (sp->rs < 0) { - state = sp->rs; - goto done; - } - - mprFree(sp->id); - /* MOB rc */ - sp->str = ejsVarToString(ep, ep->result); - sp->id = mprStrdup(ep, sp->str); - - if (sp->id[0] == '\0') { - if (flags & EJS_FLAGS_EXE) { - ejsError(ep, EJS_RANGE_ERROR, - "[] expression evaluates to the empty string\n"); - goto err; - } - } else { - sp->pp = searchSpacesForProperty(ep, state, ep->currentObj, - sp->id, flags); - ep->currentProperty = sp->pp; - updateResult(ep, state, flags, ejsGetVarPtr(sp->pp)); - } - - if ((sp->tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { - ejsSyntaxError(ep, "Missing ']'"); - goto err; - } - break; - - case EJS_TOK_PERIOD: - if (flags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Undefined object \"%s\"", sp->id); - goto err; - } - } - ep->currentObj = &ep->currentProperty->var; - if (flags & EJS_FLAGS_EXE) { - if (ep->currentObj != 0 && ep->currentObj->type != - EJS_TYPE_OBJECT) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Property reference to a non-object type \"%s\"\n", - sp->id); - goto err; - } - } - if ((sp->tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - ejsError(ep, EJS_REFERENCE_ERROR, "Bad property after '.': %s", - ep->token); - goto err; - } - /* Fall through */ - - case EJS_TOK_ID: - state = parseId(ep, state, flags, &sp->id, &sp->done); - if (sp->done && state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - } - break; - - case EJS_TOK_ASSIGNMENT: - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid == EJS_TOK_LBRACE) { - /* - * var = { name: value, name: value, ... } - */ - if (parseObjectLiteral(ep, state, flags, sp->id) < 0) { - ejsSyntaxError(ep, "Bad object literal"); - goto err; - } - - } else if (sp->tid == EJS_TOK_LBRACKET) { - /* - * var = [ array elements ] - */ - if (parseArrayLiteral(ep, state, flags, sp->id) < 0) { - ejsSyntaxError(ep, "Bad array literal"); - goto err; - } - - } else if (sp->tid == EJS_TOK_EXPR && - (int) *ep->token == EJS_EXPR_LESS) { - /* - * var = <xmlTag> .../</xmlTag> - */ - ejsSyntaxError(ep, "XML literals are not yet supported"); - goto err; - - } else { - /* - * var = expression - */ - ejsLexPutbackToken(ep, sp->tid, ep->token); - state = parseAssignment(ep, state, flags, sp->id); - if (state == EJS_STATE_ERR) { - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - goto done; - } - if (!ep->gotException) { - ejsSyntaxError(ep, 0); - } - goto err; - } - } - - if (flags & EJS_FLAGS_EXE) { - if (assignPropertyValue(ep, sp->id, state, ep->result, - flags) < 0) { - if (ep->gotException == 0) { - ejsError(ep, EJS_EVAL_ERROR, "Can't set property %s", - sp->id); - } - goto err; - } - } - - if (state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - goto done; - } - break; - - case EJS_TOK_INC_DEC: - state = parseInc(ep, state, flags); - if (state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - } - break; - - case EJS_TOK_NEW: - /* MOB -- could we remove rs and just use state */ - sp->rs = ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW); - if (sp->rs < 0) { - state = sp->rs; - goto done; - } - break; - - case EJS_TOK_DELETE: - sp->rs = ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_DELETE); - if (sp->rs < 0) { - state = sp->rs; - goto done; - } - if (flags & EJS_FLAGS_EXE) { - /* Single place where properties are deleted */ - if (ep->currentObj == 0 || ep->currentProperty == 0) { - ejsError(ep, EJS_EVAL_ERROR, - "Can't find property to delete"); - goto err; - } - if (ep->currentObj->isArray) { - ejsSetArrayLength(ep, ep->currentObj, 0, - ep->currentProperty->name, 0); - } - ejsDeleteProperty(ep, ep->currentObj, - ep->currentProperty->name); - ep->currentProperty = 0; - } - goto done; - - case EJS_TOK_FUNCTION: - /* - * Parse a function declaration - */ - state = parseFunction(ep, state, flags); - goto done; - - case EJS_TOK_THROW: - state = parseThrow(ep, state, flags); - goto done; - - case EJS_TOK_TRY: - state = parseTry(ep, state, flags); - goto done; - - case EJS_TOK_CLASS: - case EJS_TOK_MODULE: - state = parseClass(ep, state, flags); - goto done; - - case EJS_TOK_LITERAL: - /* - * Set the result to the string literal - */ - if (flags & EJS_FLAGS_EXE) { - ejsWriteVarAsString(ep, ep->result, ep->token); - ejsSetVarName(ep, ep->result, ""); - } - if (state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - } - goto done; - - case EJS_TOK_NUMBER: - /* - * Set the result to the parsed number - */ - if (flags & EJS_FLAGS_EXE) { - ejsWriteVar(ep, ep->result, &ep->tokenNumber, 0); - } - if (state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - } - goto done; - - case EJS_TOK_METHOD_NAME: - /* - * parse a method() invocation - */ - mprAssert(ep->currentObj); - state = parseMethod(ep, state, flags, sp->id); - if (state == EJS_STATE_STMT) { - sp->expectEndOfStmt = 1; - } - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - } - goto done; - - case EJS_TOK_IF: - state = parseIf(ep, state, flags, &sp->done); - if (state < 0) { - goto done; - } - break; - - case EJS_TOK_FOR: - state = parseFor(ep, state, flags); - goto done; - - case EJS_TOK_VAR: - if ((sp->rs = ejsParse(ep, EJS_STATE_DEC_LIST, flags)) < 0) { - state = sp->rs; - goto done; - } - goto done; - - case EJS_TOK_COMMA: - ejsLexPutbackToken(ep, sp->tid, ep->token); - goto done; - - case EJS_TOK_LPAREN: - if (state == EJS_STATE_EXPR) { - if ((sp->rs = ejsParse(ep, EJS_STATE_RELEXP, flags)) < 0) { - state = sp->rs; - goto done; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - ejsSyntaxError(ep, 0); - goto err; - } - goto done; - - } else if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, EJS_TOK_METHOD_NAME, ep->token); - } - break; - - case EJS_TOK_RPAREN: - ejsLexPutbackToken(ep, sp->tid, ep->token); - goto done; - - case EJS_TOK_EXTENDS: - if (! (flags & EJS_FLAGS_CLASS_DEC)) { - ejsSyntaxError(ep, 0); - goto err; - } - sp->saveObj = ep->currentObj; - sp->saveObjPerm = ejsMakeObjPermanent(sp->saveObj, 1); - - sp->rs = ejsParse(ep, EJS_STATE_STMT, flags); - ejsMakeObjPermanent(sp->saveObj, sp->saveObjPerm); - - if (sp->rs < 0) { - state = sp->rs; - goto done; - } - - if (flags & EJS_FLAGS_EXE) { - if (createClass(ep, sp->saveObj, sp->id, - ejsGetVarPtr(ep->currentProperty)) < 0) { - goto err; - } - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LBRACE) { - ejsSyntaxError(ep, 0); - goto err; - } - ejsLexPutbackToken(ep, ep->tid, ep->token); - goto done; - - case EJS_TOK_LBRACE: - if (flags & EJS_FLAGS_CLASS_DEC) { - if (state == EJS_STATE_DEC) { - if (flags & EJS_FLAGS_EXE) { - if (createClass(ep, ep->currentObj, sp->id, 0) < 0) { - goto err; - } - } - ejsLexPutbackToken(ep, sp->tid, ep->token); - - } else if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - } - goto done; - } - - /* - * This handles any code in braces except "if () {} else {}" - */ - if (state != EJS_STATE_STMT) { - ejsSyntaxError(ep, 0); - goto err; - } - - /* - * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE - * is seen. - */ - sp->exception = 0; - do { - state = ejsParse(ep, EJS_STATE_STMT, flags); - if (state == EJS_STATE_ERR) { - /* - * We need to keep parsing to get to the end of the block - */ - if (sp->exception == 0) { - sp->exception = ejsDupVar(ep, ep->result, - EJS_SHALLOW_COPY); - if (sp->exception == 0) { - ejsMemoryError(ep); - goto err; - } - if (sp->exception->type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(sp->exception, 0); - mprAssert(sp->exception->objectState->alive == 0); - } - - /* - * If we're in a try block, we need to keep parsing - * so we can find the end of the block and the start - * of the catch block. Otherwise, we are done. - */ - if (!(flags & EJS_FLAGS_TRY)) { - break; - } - } - flags &= ~EJS_FLAGS_EXE; - if (ep->recurseCount > 20) { - break; - } - state = EJS_STATE_STMT_DONE; - ep->gotException = 0; - } - - } while (state == EJS_STATE_STMT_DONE); - - if (sp->exception) { - ep->gotException = 1; - ejsWriteVar(ep, ep->result, sp->exception, EJS_SHALLOW_COPY); - - /* Eat the closing brace */ - ejsLexGetToken(ep, state); - ejsFreeVar(ep, sp->exception); - - goto err; - } - ejsFreeVar(ep, sp->exception); - - if (state < 0) { - goto done; - } - - if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { - ejsSyntaxError(ep, 0); - goto err; - } - state = EJS_STATE_STMT_DONE; - goto done; - - case EJS_TOK_RBRACE: - if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - state = EJS_STATE_STMT_BLOCK_DONE; - - } else if (state == EJS_STATE_EXPR) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - state = EJS_STATE_EXPR; - - } else { - ejsSyntaxError(ep, 0); - state = EJS_STATE_ERR; - } - goto done; - - case EJS_TOK_RETURN: - if ((sp->rs = ejsParse(ep, EJS_STATE_RELEXP, flags)) < 0) { - state = sp->rs; - goto done; - } - if (flags & EJS_FLAGS_EXE) { - state = EJS_STATE_RET; - goto done; - } - break; - } - } -done: - mprFree(sp->id); - - if (sp->expectEndOfStmt && state >= 0) { - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid == EJS_TOK_RBRACE) { - ejsLexPutbackToken(ep, EJS_TOK_RBRACE, ep->token); - - } else if (sp->tid != EJS_TOK_SEMI && sp->tid != EJS_TOK_NEWLINE && - sp->tid != EJS_TOK_EOF) { - ejsSyntaxError(ep, 0); - state = EJS_STATE_ERR; - - } else { - /* - * Skip newlines after semi-colon - */ - removeNewlines(ep, state); - } - } - - /* - * Advance the state - */ - switch (state) { - case EJS_STATE_STMT: - case EJS_STATE_STMT_DONE: - state = EJS_STATE_STMT_DONE; - break; - - case EJS_STATE_DEC: - case EJS_STATE_DEC_DONE: - state = EJS_STATE_DEC_DONE; - break; - - case EJS_STATE_EXPR: - case EJS_STATE_EXPR_DONE: - state = EJS_STATE_EXPR_DONE; - break; - - case EJS_STATE_STMT_BLOCK_DONE: - case EJS_STATE_EOF: - case EJS_STATE_RET: - break; - - default: - if (state != EJS_STATE_ERR) { - ejsSyntaxError(ep, 0); - } - state = EJS_STATE_ERR; - } - popFrame(ep, sizeof(ParseStmt)); - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseFor { - char *initToken; - int tid, foundVar, initId, each; -} ParseFor; - -/* - * Parse method arguments - */ - -static int parseFor(Ejs *ep, int state, int flags) -{ - ParseFor *sp; - - if ((sp = pushFrame(ep, sizeof(ParseFor))) == 0) { - return EJS_STATE_ERR; - } - - mprAssert(ep); - - if (state != EJS_STATE_STMT) { - ejsSyntaxError(ep, 0); - goto err; - } - - if ((sp->tid = ejsLexGetToken(ep, state)) == EJS_TOK_EACH) { - sp->each = 1; - sp->tid = ejsLexGetToken(ep, state); - - } else { - sp->each = 0; - } - - if (sp->tid != EJS_TOK_LPAREN) { - ejsSyntaxError(ep, 0); - goto err; - } - - /* - * Need to peek 2-3 tokens ahead and see if this is a - * for [each] ([var] x in set) - * or - * for (init ; whileCond; incr) - */ - sp->initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - sp->foundVar = 0; - if (sp->initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { - sp->foundVar = 1; - sp->initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - } - sp->initToken = mprStrdup(ep, ep->token); - - sp->tid = ejsLexGetToken(ep, EJS_STATE_EXPR); - - ejsLexPutbackToken(ep, sp->tid, ep->token); - ejsLexPutbackToken(ep, sp->initId, sp->initToken); - mprFree(sp->initToken); - - if (sp->foundVar) { - ejsLexPutbackToken(ep, EJS_TOK_ID, "var"); - } - - if (sp->tid == EJS_TOK_IN) { - state = parseForIn(ep, state, flags, sp->each); - - } else { - state = parseRegFor(ep, state, flags); - } - -done: - popFrame(ep, sizeof(ParseFor)); - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse method arguments - */ - -static int parseArgs(Ejs *ep, int state, int flags) -{ - EjsVar *vp; - int tid; - - mprAssert(ep); - - do { - /* - * Peek and see if there are no args - */ - tid = ejsLexGetToken(ep, state); - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RPAREN) { - break; - } - - /* - * If this is part of a constructor, must run methods in args normally - */ - flags &= ~EJS_FLAGS_NEW; - - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state < 0) { - return state; - } - if (flags & EJS_FLAGS_EXE) { - mprAssert(ep->proc->args); - vp = ejsDupVar(ep, ep->result, EJS_SHALLOW_COPY); - if (vp == 0) { - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - /* MOB */ - if (vp->type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(vp, 0); - mprAssert(vp->objectState->alive == 0); - } - - /* - * Propagate the name - */ - ejsSetVarName(ep, vp, ep->result->propertyName); - - mprAddItem(ep->proc->args, vp); - - } - /* - * Peek at the next token, continue if more args (ie. comma seen) - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_COMMA) { - ejsLexPutbackToken(ep, tid, ep->token); - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - return EJS_STATE_ARG_LIST_DONE; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseAssign { - EjsProperty *saveProperty; - EjsVar *saveObj; - int saveObjPerm, savePropPerm, rc; -} ParseAssign; - -/* - * Parse an assignment statement - */ - -static int parseAssignment(Ejs *ep, int state, int flags, char *id) -{ - ParseAssign *sp; - - - if (id == 0) { - if (!ep->gotException) { - ejsSyntaxError(ep, 0); - } - return EJS_STATE_ERR; - } - - if ((sp = pushFrame(ep, sizeof(ParseAssign))) == 0) { - return EJS_STATE_ERR; - } - - mprAssert(ep->currentObj); - - /* - * Parse the right hand side of the "=" - */ - sp->saveObj = ep->currentObj; - sp->saveProperty = ep->currentProperty; - - sp->saveObjPerm = ejsMakeObjPermanent(sp->saveObj, 1); - sp->savePropPerm = ejsMakeObjPermanent(ejsGetVarPtr(sp->saveProperty), 1); - - sp->rc = ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT); - - ejsMakeObjPermanent(sp->saveObj, sp->saveObjPerm); - ejsMakeObjPermanent(ejsGetVarPtr(sp->saveProperty), sp->savePropPerm); - - if (sp->rc < 0) { - state = EJS_STATE_ERR; - } - - ep->currentObj = sp->saveObj; - ep->currentProperty = sp->saveProperty; - - popFrame(ep, sizeof(ParseAssign)); - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - return state; -} - -/******************************************************************************/ - -static int assignPropertyValue(Ejs *ep, char *id, int state, EjsVar *value, - int flags) -{ - EjsProperty *saveProperty; - EjsVar *saveObj, *obj, *vp; - char *procName; - int saveObjPerm, savePropPerm, rc; - - mprAssert(flags & EJS_FLAGS_EXE); - - if (ep->currentProperty && - !ep->currentProperty->var.flags & EJS_GET_ACCESSOR) { - obj = ep->currentObj; - - } else { - /* - * Handle any set accessors. - * FUTURE OPT -- could be faster - * FUTURE OPT -- coming here even when doing just a set "x = value"; - */ - procName = 0; - if (mprAllocStrcat(MPR_LOC_ARGS(ep), &procName, EJS_MAX_ID + 5, 0, - "-set-", id, 0) > 0) { - - MprArray *args; - - ep->currentProperty = searchSpacesForProperty(ep, state, - ep->currentObj, procName, flags); - - if (ep->currentProperty) { - args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - - vp = ejsDupVar(ep, value, EJS_SHALLOW_COPY); - mprAddItem(args, vp); - mprAssert(! ejsObjIsCollectable(vp)); - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - - saveObjPerm = ejsMakeObjPermanent(saveObj, 1); - savePropPerm = ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), - 1); - - /* - * Invoke the set accessor - */ - rc = ejsRunMethod(ep, ep->currentObj, procName, args); - mprFree(procName); - ejsFreeMethodArgs(ep, args); - - ejsMakeObjPermanent(saveObj, saveObjPerm); - ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), savePropPerm); - - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - if (rc < 0) { - return EJS_STATE_ERR; - } - return state; - } - mprFree(procName); - } - - if (ep->currentProperty == 0) { - /* - * MOB -- can we omit this as updateProperty below will create - */ - if (createProperty(ep, &obj, id, state) < 0) { - return EJS_STATE_ERR; - } - } - } - - if (updateProperty(ep, obj, id, state, value) < 0) { - return EJS_STATE_ERR; - } - - vp = ejsGetVarPtr(ep->currentProperty); - if (vp->type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(vp, 1); - } - - return state; -} - -/******************************************************************************/ - -static int parseObjectLiteral(Ejs *ep, int state, int flags, char *id) -{ - EjsProperty *saveProperty; - EjsVar *saveObj; - EjsVar *obj; - char *name; - int saveObjPerm, savePropPerm, tid; - - name = 0; - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - - saveObjPerm = ejsMakeObjPermanent(saveObj, 1); - savePropPerm = ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), 1); - - if (flags & EJS_FLAGS_EXE) { - obj = ejsCreateSimpleObj(ep, "Object"); - if (obj == 0) { - ejsMemoryError(ep); - goto err; - } - mprAssert(! ejsObjIsCollectable(obj)); - - } else { - obj = 0; - } - - do { - tid = getNextNonSpaceToken(ep, state); - if (tid != EJS_TOK_ID) { - ejsSyntaxError(ep, 0); - goto err; - } - name = mprStrdup(ep, ep->token); - - tid = getNextNonSpaceToken(ep, state); - if (tid != EJS_TOK_COLON) { - ejsSyntaxError(ep, 0); - goto err; - } - - if (flags & EJS_FLAGS_EXE) { - /* FUTURE OPT -- can we optimize this. We are double accessing id - with the Put below. Should we be using this or ejsSetProperty - */ - if (ejsCreatePropertyMethod(ep, obj, name) == 0) { - ejsMemoryError(ep); - goto err; - } - } - - if (ejsParse(ep, EJS_STATE_RELEXP, flags) < 0) { - goto err; - } - if (flags & EJS_FLAGS_EXE) { - if (ejsSetPropertyMethod(ep, obj, name, ep->result) == 0) { - ejsMemoryError(ep); - goto err; - } - } - mprFree(name); - name = 0; - - tid = getNextNonSpaceToken(ep, state); - - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RBRACE) { - ejsSyntaxError(ep, 0); - goto err; - } - - if (flags & EJS_FLAGS_EXE) { - ejsMakeObjLive(obj, 1); - ejsWriteVar(ep, ep->result, obj, EJS_SHALLOW_COPY); - } - -done: - ejsMakeObjPermanent(saveObj, saveObjPerm); - ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), savePropPerm); - - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - if (obj) { - ejsFreeVar(ep, obj); - } - return state; - -err: - mprFree(name); - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ - -static int parseArrayLiteral(Ejs *ep, int state, int flags, char *id) -{ - EjsProperty *saveProperty; - EjsVar *saveObj; - EjsVar *obj; - int saveObjPerm, savePropPerm, tid; - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - - saveObjPerm = ejsMakeObjPermanent(saveObj, 1); - savePropPerm = ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), 1); - - if (flags & EJS_FLAGS_EXE) { - obj = ejsCreateArray(ep, 0); - if (obj == 0) { - ejsMemoryError(ep); - goto err; - } - mprAssert(! ejsObjIsCollectable(obj)); - - } else { - obj = 0; - } - - do { - if (ejsParse(ep, EJS_STATE_RELEXP, flags) < 0) { - goto err; - } - if (flags & EJS_FLAGS_EXE) { - /* MOB _- should this be put[array.length] */ - if (ejsAddArrayElt(ep, obj, ep->result, EJS_SHALLOW_COPY) == 0) { - goto err; - } - } - - tid = getNextNonSpaceToken(ep, state); - - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RBRACKET) { - ejsSyntaxError(ep, "Missing right bracket"); - goto err; - } - - if (flags & EJS_FLAGS_EXE) { - ejsMakeObjLive(obj, 1); - ejsWriteVar(ep, ep->result, obj, EJS_SHALLOW_COPY); - } - -done: - ejsMakeObjPermanent(saveObj, saveObjPerm); - ejsMakeObjPermanent(ejsGetVarPtr(saveProperty), savePropPerm); - - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - ejsFreeVar(ep, obj); - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Create a property. - */ - -/* -MOB -- simplify this. Enforce ep->currentObj to be always set. -Then we can delete this and just call - - ejsCreatePropertyMethod(ep->currentObj, id); -*/ -//XX -static int createProperty(Ejs *ep, EjsVar **objp, const char *id, int state) -{ - EjsVar *obj, *vp; - - mprAssert(id && *id); - mprAssert(objp); - - /* - * Determine the variable scope to use for the property. - * Standard says: "var x" means declare locally. - * "x = 2" means declare globally if x is undefined. - */ - if (ep->currentObj) { - if (ep->currentObj->type != EJS_TYPE_OBJECT) { - ejsSyntaxError(ep, "Reference is not an object"); - return EJS_STATE_ERR; - } - obj = ep->currentObj; - - } else { - /* MOB -- we should never be doing this here. ep->currentObj should - always be set already */ - obj = (state == EJS_STATE_DEC) ? ep->local : ep->global; - } - mprAssert(obj); - - vp = ejsCreatePropertyMethod(ep, obj, id); - if (vp == 0) { - if (!ep->gotException) { - ejsMemoryError(ep); - } - return EJS_STATE_ERR; - } - - *objp = obj; - return state; -} - -/******************************************************************************/ -/* - * Update a property. - * - * Return with ep->currentProperty updated to point to the property. - */ - -static int updateProperty(Ejs *ep, EjsVar *obj, const char *id, int state, - EjsVar *value) -{ - EjsVar *vp; - - /* - * MOB -- do ready-only check here - */ - vp = ejsSetPropertyMethod(ep, obj, id, value); - if (vp == 0) { - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - ep->currentProperty = ejsGetPropertyPtr(vp); - - obj->objectState->dirty = 1; - - return state; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseCond { - EjsVar lhs, rhs; - int tid, operator; -} ParseCond; - -/* - * Parse conditional expression (relational ops separated by ||, &&) - */ - -static int parseCond(Ejs *ep, int state, int flags) -{ - ParseCond *sp; - - if ((sp = pushFrame(ep, sizeof(ParseCond))) == 0) { - return EJS_STATE_ERR; - } - - mprAssert(ep); - - if (flags & EJS_FLAGS_EXE) { - ejsClearVar(ep, ep->result); - } - - sp->lhs.type = sp->rhs.type = EJS_TYPE_UNDEFINED; - sp->lhs.objectState = sp->rhs.objectState = 0; - sp->lhs.allocatedData = sp->rhs.allocatedData = 0; - - ejsSetVarName(ep, &sp->lhs, "lhs"); - ejsSetVarName(ep, &sp->rhs, "rhs"); - - sp->operator = 0; - - do { - /* - * Recurse to handle one side of a conditional. Accumulate the - * left hand side and the final result in ep->result. - */ - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state < 0) { - break; - } - - if (flags & EJS_FLAGS_EXE) { - if (sp->operator > 0) { - /* - * FUTURE -- does not do precedence - */ - ejsWriteVar(ep, &sp->rhs, ep->result, EJS_SHALLOW_COPY); - if (evalCond(ep, &sp->lhs, sp->operator, &sp->rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - /* Result left in ep->result */ - /* MOB */ - if (sp->lhs.type == EJS_TYPE_OBJECT) { - mprAssert(sp->lhs.objectState->alive == 0); - } - if (sp->rhs.type == EJS_TYPE_OBJECT) { - mprAssert(sp->rhs.objectState->alive == 0); - } - } - } - - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid == EJS_TOK_LOGICAL) { - sp->operator = (int) *ep->token; - - } else if (sp->tid == EJS_TOK_RPAREN || sp->tid == EJS_TOK_SEMI) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - state = EJS_STATE_COND_DONE; - break; - - } else { - ejsLexPutbackToken(ep, sp->tid, ep->token); - } - - if (flags & EJS_FLAGS_EXE) { - ejsWriteVar(ep, &sp->lhs, ep->result, EJS_SHALLOW_COPY); - } - - } while (state == EJS_STATE_RELEXP_DONE); - - ejsClearVar(ep, &sp->lhs); - ejsClearVar(ep, &sp->rhs); - - popFrame(ep, sizeof(ParseCond)); - - return state; -} - -/******************************************************************************/ -/* - * Parse variable declaration list. Declarations can be of the following forms: - * var x; - * var x, y, z; - * var x = 1 + 2 / 3, y = 2 + 4; - * var x = { property: value, property: value ... }; - * var x = [ property: value, property: value ... ]; - * - * We set the variable to NULL if there is no associated assignment. - */ - -static int parseDeclaration(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - ejsLexPutbackToken(ep, tid, ep->token); - - /* - * Parse the entire assignment or simple identifier declaration - */ - if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { - return EJS_STATE_ERR; - } - - /* - * Peek at the next token, continue if comma seen - * Stop on ";" or "in" which is used in a "for (var x in ..." - */ - tid = ejsLexGetToken(ep, state); - - if (tid == EJS_TOK_SEMI) { - return EJS_STATE_DEC_LIST_DONE; - - } else if (tid == EJS_TOK_IN) { - ejsLexPutbackToken(ep, tid, ep->token); - return EJS_STATE_DEC_LIST_DONE; - - } else if (flags & EJS_FLAGS_CLASS_DEC && - (tid == EJS_TOK_LBRACE || tid == EJS_TOK_EXTENDS)) { - ejsLexPutbackToken(ep, tid, ep->token); - return EJS_STATE_DEC_LIST_DONE; - - } else if (tid == EJS_TOK_RPAREN && flags & EJS_FLAGS_CATCH) { - ejsLexPutbackToken(ep, tid, ep->token); - return EJS_STATE_DEC_LIST_DONE; - - } else if (tid != EJS_TOK_COMMA) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_SEMI) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - return EJS_STATE_DEC_LIST_DONE; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseExpr { - EjsVar lhs, rhs; - int rel, tid, unaryMinus; -} ParseExpr; - -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - -static int parseExpr(Ejs *ep, int state, int flags) -{ - ParseExpr *sp; - - mprAssert(ep); - - if ((sp = pushFrame(ep, sizeof(ParseExpr))) == 0) { - return EJS_STATE_ERR; - } - - if (flags & EJS_FLAGS_EXE) { - ejsClearVar(ep, ep->result); - } - - sp->lhs.type = sp->rhs.type = EJS_TYPE_UNDEFINED; - sp->lhs.objectState = sp->rhs.objectState = 0; - sp->lhs.allocatedData = sp->rhs.allocatedData = 0; - - ejsSetVarName(ep, &sp->lhs, "lhs"); - ejsSetVarName(ep, &sp->rhs, "rhs"); - - sp->rel = 0; - sp->tid = 0; - sp->unaryMinus = 0; - - do { - /* - * This loop will handle an entire expression list. We call parse - * to evalutate each term which returns the result in ep->result. - */ - if (sp->tid == EJS_TOK_LOGICAL) { - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state < 0) { - break; - } - } else { - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { - sp->unaryMinus = 1; - - } else { - ejsLexPutbackToken(ep, sp->tid, ep->token); - } - - state = ejsParse(ep, EJS_STATE_EXPR, flags); - if (state < 0) { - break; - } - } - - if (flags & EJS_FLAGS_EXE) { - if (sp->unaryMinus) { - switch (ep->result->type) { - default: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - case EJS_TYPE_PTR: - case EJS_TYPE_OBJECT: - case EJS_TYPE_STRING: - case EJS_TYPE_BOOL: - ejsError(ep, EJS_SYNTAX_ERROR, "Invalid unary minus"); - state = EJS_STATE_ERR; - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - ep->result->floating = - ep->result->floating; - break; -#endif - - case EJS_TYPE_INT: - ep->result->integer = - ep->result->integer; - break; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - ep->result->integer64 = - ep->result->integer64; - break; -#endif - } - } - sp->unaryMinus = 0; - - if (sp->rel > 0) { - ejsWriteVar(ep, &sp->rhs, ep->result, EJS_SHALLOW_COPY); - if (sp->tid == EJS_TOK_LOGICAL) { - if (evalCond(ep, &sp->lhs, sp->rel, &sp->rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } else { - if (evalExpr(ep, &sp->lhs, sp->rel, &sp->rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - } - /* MOB */ - if (sp->lhs.type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(&sp->lhs, 0); - mprAssert(sp->lhs.objectState->alive == 0); - } - if (sp->rhs.type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(&sp->rhs, 0); - mprAssert(sp->rhs.objectState->alive == 0); - } - } - - if ((sp->tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || - sp->tid == EJS_TOK_INC_DEC || sp->tid == EJS_TOK_LOGICAL) { - sp->rel = (int) *ep->token; - ejsWriteVar(ep, &sp->lhs, ep->result, EJS_SHALLOW_COPY); - - } else { - ejsLexPutbackToken(ep, sp->tid, ep->token); - state = EJS_STATE_RELEXP_DONE; - } - - } while (state == EJS_STATE_EXPR_DONE); - - ejsClearVar(ep, &sp->lhs); - ejsClearVar(ep, &sp->rhs); - - popFrame(ep, sizeof(ParseExpr)); - - return state; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseForIn { - EjsInput *endScript, *bodyScript; - EjsProperty *pp, *nextp; - EjsVar *iteratorVar, *setVar, *vp; - int forFlags, tid; -} ParseForIn; - -/* - * Parse the "for ... in" statement. Format for the statement is: - * - * for [each] (var varName in expression) { - * body; - * } - */ - -static int parseForIn(Ejs *ep, int state, int flags, int each) -{ - ParseForIn *sp; - - mprAssert(ep); - - if ((sp = pushFrame(ep, sizeof(ParseForIn))) == 0) { - return EJS_STATE_ERR; - } - - sp->setVar = 0; - sp->iteratorVar = 0; - sp->bodyScript = 0; - sp->endScript = 0; - - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid != EJS_TOK_ID && sp->tid != EJS_TOK_VAR) { - ejsSyntaxError(ep, 0); - goto err; - } - ejsLexPutbackToken(ep, sp->tid, ep->token); - - state = ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FORIN | flags); - if (state < 0) { - goto done; - } - if (flags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsSyntaxError(ep, 0); - goto err; - } - sp->iteratorVar = &ep->currentProperty->var; - } else { - sp->iteratorVar = 0; - } - - if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { - ejsSyntaxError(ep, 0); - goto err; - } - - /* - * Get the set - */ - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid != EJS_TOK_ID) { - ejsSyntaxError(ep, 0); - goto err; - } - ejsLexPutbackToken(ep, sp->tid, ep->token); - - state = ejsParse(ep, EJS_STATE_EXPR, flags); - if (state < 0) { - goto done; - } - - if ((flags & EJS_FLAGS_EXE) && - (ep->result == 0 || ep->result->type == EJS_TYPE_UNDEFINED)) { - ejsError(ep, EJS_REFERENCE_ERROR, "Can't access array or object"); - goto err; - } - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - ejsSyntaxError(ep, 0); - goto err; - } - - sp->setVar = ejsDupVar(ep, ep->result, EJS_SHALLOW_COPY); - - sp->bodyScript = getInputStruct(ep); - - /* - * Parse the body and remember the end of the body script - */ - sp->forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, sp->bodyScript); - - state = ejsParse(ep, EJS_STATE_STMT, sp->forFlags); - if (state < 0) { - goto done; - } - - sp->endScript = getInputStruct(ep); - ejsInitInputState(sp->endScript); - ejsLexSaveInputState(ep, sp->endScript); - - /* - * Enumerate the properties - */ - if (flags & EJS_FLAGS_EXE) { - if (sp->setVar->type == EJS_TYPE_OBJECT) { - - sp->setVar->objectState->preventDeleteProp = 1; - - sp->pp = ejsGetFirstProperty(sp->setVar, 0); - while (sp->pp) { - sp->nextp = ejsGetNextProperty(sp->pp, 0); - if (! sp->pp->dontEnumerate && !sp->pp->delayedDelete) { - if (each) { - sp->vp = ejsWriteVar(ep, sp->iteratorVar, - ejsGetVarPtr(sp->pp), EJS_SHALLOW_COPY); - } else { - sp->vp = ejsWriteVarAsString(ep, sp->iteratorVar, - sp->pp->name); - } - if (sp->vp == 0) { - ejsError(ep, EJS_MEMORY_ERROR, - "Can't write to variable"); - goto err; - } - - ejsLexRestoreInputState(ep, sp->bodyScript); - - state = ejsParse(ep, EJS_STATE_STMT, flags); - - if (state < 0) { - if (sp->setVar->objectState) { - sp->setVar->objectState->preventDeleteProp = 0; - } - goto done; - } - } - sp->pp = sp->nextp; - } - - /* - * Process delayed deletes - */ - if (sp->setVar->objectState) { - sp->setVar->objectState->preventDeleteProp = 0; - if (sp->setVar->objectState->delayedDeleteProp) { - sp->pp = ejsGetFirstProperty(sp->setVar, 0); - while (sp->pp) { - sp->nextp = ejsGetNextProperty(sp->pp, 0); - if (sp->pp->delayedDelete) { - ejsDeleteProperty(ep, sp->setVar, sp->pp->name); - } - sp->pp = sp->nextp; - } - sp->setVar->objectState->delayedDeleteProp = 0; - } - } - - } else { - ejsError(ep, EJS_REFERENCE_ERROR, - "Variable to iterate over is not an array or object"); - goto err; - } - } - - ejsLexRestoreInputState(ep, sp->endScript); - -done: - if (sp->endScript) { - ejsLexFreeInputState(ep, sp->endScript); - ejsLexFreeInputState(ep, sp->bodyScript); - } - - if (sp->bodyScript) { - freeInputStruct(ep, sp->bodyScript); - } - if (sp->endScript) { - freeInputStruct(ep, sp->endScript); - } - - if (sp->setVar) { - ejsFreeVar(ep, sp->setVar); - } - - popFrame(ep, sizeof(ParseForIn)); - - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse the for statement. Format for the expression is: - * - * for (initial; condition; incr) { - * body; - * } - */ - -static int parseRegFor(Ejs *ep, int state, int flags) -{ - EjsInput *condScript, *endScript, *bodyScript, *incrScript; - - endScript = getInputStruct(ep); - bodyScript = getInputStruct(ep); - incrScript = getInputStruct(ep); - condScript = getInputStruct(ep); - - ejsInitInputState(endScript); - ejsInitInputState(bodyScript); - ejsInitInputState(incrScript); - ejsInitInputState(condScript); - - state = parseForInner(ep, state, flags, - condScript, incrScript, bodyScript, endScript); - - ejsLexFreeInputState(ep, condScript); - ejsLexFreeInputState(ep, incrScript); - ejsLexFreeInputState(ep, endScript); - ejsLexFreeInputState(ep, bodyScript); - - freeInputStruct(ep, condScript); - freeInputStruct(ep, incrScript); - freeInputStruct(ep, endScript); - freeInputStruct(ep, bodyScript); - - return state; -} - -/******************************************************************************/ - -static int parseForInner(Ejs *ep, int state, int flags, EjsInput *condScript, - EjsInput *incrScript, EjsInput *bodyScript, EjsInput *endScript) -{ - int forFlags, cond, rs; - - mprAssert(ep); - - /* - * Evaluate the for loop initialization statement - */ - if ((state = ejsParse(ep, EJS_STATE_STMT, flags)) < 0) { - return state; - } - - /* - * The first time through, we save the current input context just prior - * to each step: prior to the conditional, the loop increment and - * the loop body. - */ - ejsLexSaveInputState(ep, condScript); - if ((rs = ejsParse(ep, EJS_STATE_COND, flags)) < 0) { - return rs; - } - - cond = (ep->result->boolean != 0); - - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - /* - * Don't execute the loop increment statement or the body - * first time. - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, incrScript); - if ((rs = ejsParse(ep, EJS_STATE_EXPR, forFlags)) < 0) { - return rs; - } - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - /* - * Parse the body and remember the end of the body script - */ - ejsLexSaveInputState(ep, bodyScript); - if ((rs = ejsParse(ep, EJS_STATE_STMT, forFlags)) < 0) { - return rs; - } - ejsLexSaveInputState(ep, endScript); - - /* - * Now actually do the for loop. Note loop has been rotated - */ - while (cond && (flags & EJS_FLAGS_EXE)) { - /* - * Evaluate the body - */ - ejsLexRestoreInputState(ep, bodyScript); - - if ((rs = ejsParse(ep, EJS_STATE_STMT, flags)) < 0) { - return rs; - } - - /* - * Evaluate the increment script - */ - ejsLexRestoreInputState(ep, incrScript); - if ((rs = ejsParse(ep, EJS_STATE_EXPR, flags)) < 0) { - return rs; - } - /* - * Evaluate the condition - */ - ejsLexRestoreInputState(ep, condScript); - if ((rs = ejsParse(ep, EJS_STATE_COND, flags)) < 0) { - return 0; - } - mprAssert(ep->result->type == EJS_TYPE_BOOL); - cond = (ep->result->boolean != 0); - } - - ejsLexRestoreInputState(ep, endScript); - - return state; -} - -/******************************************************************************/ -/* - * Create the bare class object - */ - -static int createClass(Ejs *ep, EjsVar *obj, const char *className, - EjsVar *baseClass) -{ - EjsVar *classObj, *existingClass; - - existingClass = ejsGetClass(ep, obj, className); - if (existingClass) { - /* - * We allow partial clases and method redefinition - * FUTURE -- should prevent this if the class is sealed. - * DISABLED Error message and return OK. - */ - /* ejsError(ep, EJS_EVAL_ERROR, "Can't create class %s", className); */ - return 0; - } - - if (baseClass == 0) { - baseClass = ejsGetClass(ep, ep->service->globalClass, "Object"); - mprAssert(baseClass); - } - - classObj = ejsCreateSimpleClass(ep, baseClass, className); - if (classObj == 0) { - ejsMemoryError(ep); - return -1; - } - mprAssert(! ejsObjIsCollectable(classObj)); - - ep->currentProperty = ejsSetPropertyAndFree(ep, obj, className, classObj); - mprAssert(ep->currentProperty); - - if (ep->currentProperty == 0) { - return -1; - } - - return 0; -} - -/******************************************************************************/ -/* - * Local vars for parseTry - */ - -typedef struct ParseTry { - EjsVar *exception; - int tid, caught, rs, catchFlags; -} ParseTry; - -/* - * Parse try block - * - * try {} - */ - -static int parseTry(Ejs *ep, int state, int flags) -{ - ParseTry *sp; - - if ((sp = pushFrame(ep, sizeof(ParseTry))) == 0) { - return EJS_STATE_ERR; - } - - mprAssert(ep); - - sp->caught = 0; - sp->exception = 0; - sp->catchFlags = flags; - - /* - * Execute the code in the try block - */ - sp->rs = ejsParse(ep, EJS_STATE_STMT, flags | EJS_FLAGS_TRY); - if (sp->rs < 0) { - if (sp->rs == EJS_STATE_ERR) { - sp->exception = ejsDupVar(ep, ep->result, EJS_SHALLOW_COPY); - if (sp->exception == 0) { - ejsMemoryError(ep); - goto err; - } - } else { - state = sp->rs; - goto done; - } - - } else { - sp->catchFlags = flags & ~EJS_FLAGS_EXE; - } - - /* - * On success path or when an exception is caught, we must parse all - * catch and finally blocks. - */ - sp->tid = getNextNonSpaceToken(ep, state); - - if (sp->tid == EJS_TOK_CATCH) { - - ep->gotException = 0; - - sp->tid = getNextNonSpaceToken(ep, state); - - if (sp->tid == EJS_TOK_LBRACE) { - /* - * Unqualified "catch " - */ - ejsLexPutbackToken(ep, sp->tid, ep->token); - if (ejsParse(ep, EJS_STATE_STMT, sp->catchFlags) >= 0) { - sp->caught++; - } - - } else if (sp->tid == EJS_TOK_LPAREN) { - - /* - * Qualified "catch (variable) " - */ - if ((sp->rs = ejsParse(ep, EJS_STATE_DEC_LIST, - sp->catchFlags | EJS_FLAGS_CATCH)) < 0) { - ejsSyntaxError(ep, "Bad catch statement"); - state = sp->rs; - goto done; - } - - sp->tid = getNextNonSpaceToken(ep, state); - if (sp->tid != EJS_TOK_RPAREN) { - ejsSyntaxError(ep, 0); - goto err; - } - - if (sp->catchFlags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsError(ep, EJS_EVAL_ERROR, "Can't define catch variable"); - goto err; - } - - /* - * Set the catch variable - */ - if (ejsWriteVar(ep, - ejsGetVarPtr(ep->currentProperty), sp->exception, - EJS_SHALLOW_COPY) == 0) { - ejsError(ep, EJS_EVAL_ERROR, "Can't update catch variable"); - goto err; - } - } - - /* - * Parse the catch block - */ - if ((sp->rs = ejsParse(ep, EJS_STATE_STMT, sp->catchFlags)) < 0) { - state = sp->rs; - goto done; - } - sp->caught++; - ep->gotException = 0; - } - sp->tid = getNextNonSpaceToken(ep, state); - } - - /* - * Parse the finally block - */ - if (sp->tid == EJS_TOK_FINALLY) { - if (ejsParse(ep, EJS_STATE_STMT, flags) < 0) { - goto err; - } - } else { - ejsLexPutbackToken(ep, sp->tid, ep->token); - } - - /* - * Set the exception value - */ - if (sp->exception && !sp->caught) { - ejsWriteVar(ep, ep->result, sp->exception, EJS_SHALLOW_COPY); - goto err; - } - - state = EJS_STATE_STMT_DONE; - -done: - if (sp->exception) { - ejsFreeVar(ep, sp->exception); - } - - popFrame(ep, sizeof(ParseTry)); - return state; - - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse throw statement - * - * throw expression - */ - -static int parseThrow(Ejs *ep, int state, int flags) -{ - int rc; - - mprAssert(ep); - - if ((rc = ejsParse(ep, EJS_STATE_EXPR, flags)) < 0) { - return rc; - } - - - if (flags & EJS_FLAGS_EXE) { - /* - * We have thrown the exception so set the state to ERR - */ - ep->gotException = 1; - return EJS_STATE_ERR; - } - return state; -} - -/******************************************************************************/ -/* - * Parse a class and module declaration - * - * class <name> [extends baseClass] { - * [public | private | ... ] var declarations ... - * [constructor] function declarations ... - * } - * - * Modules are identical except declared with a "module" instead of - * "class". Modules cannot be instantiated and are used for mixins. - * - */ - -static int parseClass(Ejs *ep, int state, int flags) -{ - int originalToken, tid, fid; - - mprAssert(ep); - - originalToken = ep->tid; - - /* - * Parse "class Name [extends BaseClass]" - */ - if (ejsParse(ep, EJS_STATE_DEC_LIST, flags | EJS_FLAGS_CLASS_DEC) < 0) { - return EJS_STATE_ERR; - } - - tid = getNextNonSpaceToken(ep, state); - - if (tid != EJS_TOK_LBRACE) { - return EJS_STATE_ERR; - } - - /* - * After parsing the class body, ep->local will contain the actual - * class/module object. So, we save ep->local by creating a new block. - */ - if (flags & EJS_FLAGS_EXE) { - fid = ejsSetBlock(ep, ejsGetVarPtr(ep->currentProperty)); - ejsSetVarName(ep, ep->local, ep->currentProperty->name); - - } else { - fid = -1; - } - - /* FUTURE -- should prevent modules from being instantiated */ - - /* - * Parse class body - */ - do { - state = ejsParse(ep, EJS_STATE_STMT, flags); - if (state < 0) { - if (fid >= 0) { - ejsCloseBlock(ep, fid); - } - return state; - } - tid = getNextNonSpaceToken(ep, state); - if (tid == EJS_TOK_RBRACE) { - break; - } - ejsLexPutbackToken(ep, tid, ep->token); - - } while (state >= 0); - - if (fid >= 0) { - ejsCloseBlock(ep, fid); - } - - if (tid != EJS_TOK_RBRACE) { - ejsSyntaxError(ep, 0); - state = EJS_STATE_ERR; - } - - return state; -} - -/******************************************************************************/ -/* - * Parse a function declaration - */ - -static int parseFunction(Ejs *ep, int state, int flags) -{ - EjsInput *endScript, *bodyScript; - EjsProperty *pp; - EjsVar *func, *funcProp, *currentObj, *vp, *baseClass; - char *procName; - int varFlags, len, tid, bodyFlags, innerState; - - mprAssert(ep); - - func = 0; - varFlags = 0; - - /* - * method <name>(arg, arg, arg) { body }; - * method name(arg, arg, arg) { body }; - */ - - tid = ejsLexGetToken(ep, state); - - if (tid == EJS_TOK_GET) { - varFlags |= EJS_GET_ACCESSOR; - tid = ejsLexGetToken(ep, state); - - } else if (tid == EJS_TOK_SET) { - varFlags |= EJS_SET_ACCESSOR; - tid = ejsLexGetToken(ep, state); - } - - if (tid == EJS_TOK_ID) { - if (varFlags & EJS_SET_ACCESSOR) { - - if (mprAllocStrcat(MPR_LOC_ARGS(ep), &procName, EJS_MAX_ID + 5, - 0, "-set-", ep->token, 0) < 0) { - ejsError(ep, EJS_SYNTAX_ERROR, - "Name %s is too long", ep->token); - return EJS_STATE_ERR; - } - - } else { - procName = mprStrdup(ep, ep->token); - } - - tid = ejsLexGetToken(ep, state); - - } else { - procName = 0; - } - - if (tid != EJS_TOK_LPAREN) { - mprFree(procName); - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - /* - * Hand craft the method value structure. - */ - if (flags & EJS_FLAGS_EXE) { - func = ejsCreateMethodVar(ep, 0, 0, 0); - if (func == 0) { - mprFree(procName); - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - func->flags = varFlags; - } - - tid = ejsLexGetToken(ep, state); - while (tid == EJS_TOK_ID) { - if (flags & EJS_FLAGS_EXE) { - mprAddItem(func->method.args, - mprStrdup(func->method.args, ep->token)); - } - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { - break; - } - tid = ejsLexGetToken(ep, state); - } - if (tid != EJS_TOK_RPAREN) { - mprFree(procName); - ejsFreeVar(ep, func); - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - /* Allow new lines before opening brace */ - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - if (tid != EJS_TOK_LBRACE) { - mprFree(procName); - ejsFreeVar(ep, func); - ejsSyntaxError(ep, 0); - return EJS_STATE_ERR; - } - - /* - * Register the method name early to allow for recursive - * method calls (see note in ECMA standard, page 71) - */ - funcProp = 0; - if (flags & EJS_FLAGS_EXE && procName) { - currentObj = pickSpace(ep, 0, procName, flags | EJS_FLAGS_LOCAL); - pp = ejsSetProperty(ep, currentObj, procName, func); - if (pp == 0) { - ejsFreeVar(ep, func); - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - funcProp = ejsGetVarPtr(pp); - } - - - bodyScript = getInputStruct(ep); - - /* - * Parse the method body. Turn execute off. - */ - bodyFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, bodyScript); - - do { - innerState = ejsParse(ep, EJS_STATE_STMT, bodyFlags); - } while (innerState == EJS_STATE_STMT_DONE); - - tid = ejsLexGetToken(ep, state); - - if (innerState != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { - mprFree(procName); - ejsFreeVar(ep, func); - ejsLexFreeInputState(ep, bodyScript); - if (innerState != EJS_STATE_ERR) { - ejsSyntaxError(ep, 0); - } - freeInputStruct(ep, bodyScript); - return EJS_STATE_ERR; - } - - if (flags & EJS_FLAGS_EXE) { - endScript = getInputStruct(ep); - ejsLexSaveInputState(ep, endScript); - - /* - * Save the method body between the starting and ending parse - * positions. Overwrite the trailing '}' with a null. - */ - len = endScript->scriptServp - bodyScript->scriptServp; - func->method.body = mprAlloc(ep, len + 1); - memcpy(func->method.body, bodyScript->scriptServp, len); - - if (len <= 0) { - func->method.body[0] = '\0'; - } else { - func->method.body[len - 1] = '\0'; - } - ejsLexFreeInputState(ep, bodyScript); - ejsLexFreeInputState(ep, endScript); - freeInputStruct(ep, endScript); - - /* - * If we are in an assignment, don't register the method name, rather - * return the method structure in the parser result. - */ - if (procName) { - currentObj = pickSpace(ep, 0, procName, flags | EJS_FLAGS_LOCAL); - pp = ejsSetProperty(ep, currentObj, procName, func); - if (pp == 0) { - ejsFreeVar(ep, func); - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - - if (currentObj->objectState->className && - strcmp(currentObj->objectState->className, procName) == 0) { - baseClass = currentObj->objectState->baseClass; - if (baseClass) { - if (strstr(func->method.body, "super(") != 0) { - funcProp->callsSuper = 1; - /* - * Define super() to point to the baseClass constructor - */ - vp = ejsGetPropertyAsVar(ep, baseClass, - baseClass->objectState->className); - if (vp) { - mprAssert(vp); - if (ejsSetProperty(ep, currentObj, "super", - vp) == 0) { - ejsFreeVar(ep, func); - ejsMemoryError(ep); - return EJS_STATE_ERR; - } - } - } - } - } - } - /* - * Always return the function. Try for all stmts to be expressions. - */ - /* MOB - rc */ - ejsWriteVar(ep, ep->result, func, EJS_SHALLOW_COPY); - } - freeInputStruct(ep, bodyScript); - - mprFree(procName); - ejsFreeVar(ep, func); - - return state; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseMethod { - EjsProc proc, *saveProc; - EjsVar *saveObj, *newObj; - int saveObjPerm, rc; - -} ParseMethod; - -/* - * Parse a method name and invoke the method. See parseFunction for - * function declarations. - */ - -static int parseMethod(Ejs *ep, int state, int flags, char *id) -{ - ParseMethod *sp; - - if ((sp = pushFrame(ep, sizeof(ParseMethod))) == 0) { - return EJS_STATE_ERR; - } - - /* - * Must save any current ep->proc value for the current stack frame - * to allow for recursive method calls. - */ - sp->saveProc = (ep->proc) ? ep->proc: 0; - - memset(&sp->proc, 0, sizeof(EjsProc)); - sp->proc.procName = mprStrdup(ep, id); - sp->proc.fn = &ep->currentProperty->var; - sp->proc.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - ep->proc = &sp->proc; - -#if BLD_DEBUG - if (strcmp(sp->proc.procName, "printv") == 0) { - flags |= EJS_FLAGS_TRACE_ARGS; - } -#endif - - if (flags & EJS_FLAGS_EXE) { - ejsClearVar(ep, ep->result); - } - - if (! (flags & EJS_FLAGS_NO_ARGS)) { - sp->saveObj = ep->currentObj; - sp->saveObjPerm = ejsMakeObjPermanent(sp->saveObj, 1); - sp->rc = ejsParse(ep, EJS_STATE_ARG_LIST, flags); - ejsMakeObjPermanent(sp->saveObj, sp->saveObjPerm); - if (sp->rc < 0) { - goto err; - } - ep->currentObj = sp->saveObj; - } - -#if BLD_DEBUG - flags &= ~EJS_FLAGS_TRACE_ARGS; -#endif - - /* - * Evaluate the method if required - */ - if (flags & EJS_FLAGS_EXE) { - if (flags & EJS_FLAGS_NEW) { - sp->newObj = ejsCreateObjUsingArgv(ep, ep->currentObj, - sp->proc.procName, sp->proc.args); - - if (sp->newObj == 0) { - state = EJS_STATE_ERR; - - } else { - mprAssert(! ejsObjIsCollectable(sp->newObj)); - - /* - * Return the newly created object as the result of the - * command. NOTE: newObj may not be an object! - */ - /* MOB - rc */ - ejsWriteVar(ep, ep->result, sp->newObj, EJS_SHALLOW_COPY); - if (ejsVarIsObject(sp->newObj)) { - ejsMakeObjLive(sp->newObj, 1); - mprAssert(ejsObjIsCollectable(sp->newObj)); - mprAssert(ejsBlockInUse(sp->newObj)); - } - ejsFreeVar(ep, sp->newObj); - } - - } else { - - if (evalMethod(ep, ep->currentObj, &sp->proc, flags) < 0) { - /* Methods must call ejsError to set exceptions */ - state = EJS_STATE_ERR; - } - } - } - - if (! (flags & EJS_FLAGS_NO_ARGS)) { - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - if (state != EJS_STATE_ERR) { - ejsSyntaxError(ep, 0); - } - state = EJS_STATE_ERR; - } - } - -done: - freeProc(ep, &sp->proc); - ep->proc = sp->saveProc; - - popFrame(ep, sizeof(ParseMethod)); - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse an identifier. This is a segment of a fully qualified variable. - * May come here for an initial identifier or for property names - * after a "." or "[...]". - */ - -static int parseId(Ejs *ep, int state, int flags, char **id, int *done) -{ - EjsVar *null; - int tid; - - mprFree(*id); - *id = mprStrdup(ep, ep->token); - - if (ep->currentObj == 0) { - /* First identifier segement */ - ep->currentObj = pickSpace(ep, state, *id, flags); - } - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_ASSIGNMENT) { - flags |= EJS_FLAGS_LHS; - } - - /* - * Find the referenced variable and store it in currentProperty. - */ - if (flags & EJS_FLAGS_EXE) { - ep->currentProperty = searchSpacesForProperty(ep, state, - ep->currentObj, *id, flags); - - /* - * Handle properties that have been deleted inside an enumeration - */ - if (ep->currentProperty && ep->currentProperty->delayedDelete) { - ep->currentProperty = 0; - } - - if (ep->currentProperty && - ejsVarIsMethod(&ep->currentProperty->var) && - tid != EJS_TOK_LPAREN) { - if (ep->currentProperty->var.flags & EJS_GET_ACCESSOR) { - ejsLexPutbackToken(ep, tid, ep->token); - state = parseMethod(ep, state, flags | EJS_FLAGS_NO_ARGS, *id); - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - } - if (state >= 0) { - ejsSetVarName(ep, ep->result, ep->currentProperty->name); - } - return state; - } - } - /* - * OPT. We should not have to do this always - */ - updateResult(ep, state, flags, ejsGetVarPtr(ep->currentProperty)); - } - - flags &= ~EJS_FLAGS_LHS; - - if (tid == EJS_TOK_LPAREN) { - if (ep->currentProperty == 0 && (flags & EJS_FLAGS_EXE)) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Method name not defined \"%s\"", *id); - return EJS_STATE_ERR; - } - ejsLexPutbackToken(ep, EJS_TOK_METHOD_NAME, ep->token); - return state; - } - - if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || - tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { - ejsLexPutbackToken(ep, tid, ep->token); - return state; - } - - if (flags & EJS_FLAGS_CLASS_DEC) { - if (tid == EJS_TOK_LBRACE || tid == EJS_TOK_EXTENDS) { - ejsLexPutbackToken(ep, tid, ep->token); - return state; - } - } - - if (flags & EJS_FLAGS_DELETE) { - if (tid == EJS_TOK_RBRACE) { - ejsLexPutbackToken(ep, tid, ep->token); - } - } - - /* - * Only come here for variable access and declarations. - * Assignment handled elsewhere. - */ - if (flags & EJS_FLAGS_EXE) { - if (state == EJS_STATE_DEC) { - /* - * Declare a variable. Standard allows: var x ; var x ; - */ -#if DISABLED - if (ep->currentProperty != 0) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Variable already defined \"%s\"", *id); - return EJS_STATE_ERR; - } -#endif - /* - * Create or overwrite if it already exists - * Set newly declared variables to the null value. - */ - null = ejsCreateNullVar(ep); - ep->currentProperty = ejsSetPropertyAndFree(ep, ep->currentObj, - *id, null); - ejsClearVar(ep, ep->result); - - } else if (flags & EJS_FLAGS_FORIN) { - /* - * This allows "for (x" when x has not yet been defined - */ - if (ep->currentProperty == 0) { - /* MOB -- return code */ - ep->currentProperty = ejsCreateProperty(ep, - ep->currentObj, *id); - } - - } else if (ep->currentProperty == 0) { - - if (ep->currentObj && ((ep->currentObj == ep->global || - (ep->currentObj == ep->local)))) { - /* - * Test against currentObj and not currentObj->objectState - * as we must allow "i = global.x" and not allow - * "i = x" where x does not exist. - */ - ejsError(ep, EJS_REFERENCE_ERROR, - "Undefined variable \"%s\"", *id); - return EJS_STATE_ERR; - } - - if (flags & EJS_FLAGS_DELETE) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Undefined variable \"%s\"", *id); - return EJS_STATE_ERR; - } - } - } - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || - tid == EJS_TOK_IN) { - *done = 1; - } - return state; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct ParseIf { - int ifResult, thenFlags, elseFlags, tid, rs; -} ParseIf; - -/* - * Parse an "if" statement - */ - -static int parseIf(Ejs *ep, int state, int flags, int *done) -{ - ParseIf *sp; - - if ((sp = pushFrame(ep, sizeof(ParseIf))) == 0) { - return EJS_STATE_ERR; - } - - if (state != EJS_STATE_STMT) { - goto err; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - goto err; - } - - /* - * Evaluate the entire condition list "(condition)" - */ - if (ejsParse(ep, EJS_STATE_COND, flags) < 0) { - goto err; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto err; - } - - /* - * This is the "then" case. We need to always parse both cases and - * execute only the relevant case. - */ - sp->ifResult = ejsVarToBoolean(ep->result); - if (sp->ifResult) { - sp->thenFlags = flags; - sp->elseFlags = flags & ~EJS_FLAGS_EXE; - } else { - sp->thenFlags = flags & ~EJS_FLAGS_EXE; - sp->elseFlags = flags; - } - - /* - * Process the "then" case. - */ - if ((sp->rs = ejsParse(ep, EJS_STATE_STMT, sp->thenFlags)) < 0) { - if (! ep->gotException) { - state = sp->rs; - goto done; - } - } - - /* - * Check to see if there is an "else" case - */ - removeNewlines(ep, state); - sp->tid = ejsLexGetToken(ep, state); - if (sp->tid != EJS_TOK_ELSE) { - ejsLexPutbackToken(ep, sp->tid, ep->token); - *done = 1; - if (ep->gotException) { - goto err; - } - goto done; - } - - /* - * Process the "else" case. - */ - state = ejsParse(ep, EJS_STATE_STMT, sp->elseFlags); - -done: - *done = 1; - if (ep->gotException) { - state = EJS_STATE_ERR; - } - popFrame(ep, sizeof(ParseIf)); - return state; - - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse a postix "++" or "--" statement - */ - -static int parseInc(Ejs *ep, int state, int flags) -{ - EjsVar *one; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty == 0) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Undefined variable \"%s\"", ep->token); - return EJS_STATE_ERR; - } - one = ejsCreateIntegerVar(ep, 1); - if (evalExpr(ep, &ep->currentProperty->var, (int) *ep->token, one) < 0) { - ejsFreeVar(ep, one); - return EJS_STATE_ERR; - } - if (ejsWriteVar(ep, &ep->currentProperty->var, ep->result, - EJS_SHALLOW_COPY) < 0) { - ejsError(ep, EJS_IO_ERROR, "Can't write to variable"); - ejsFreeVar(ep, one); - return EJS_STATE_ERR; - } - ejsFreeVar(ep, one); - return state; -} - -/******************************************************************************/ -/* - * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result - * in ep->result. Returns EJS_STATE_ERR on errors, zero if successful. - */ - -static int evalCond(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) -{ - int l, r, lval; - - mprAssert(rel > 0); - - l = ejsVarToBoolean(lhs); - r = ejsVarToBoolean(rhs); - - switch (rel) { - case EJS_COND_AND: - lval = l && r; - break; - case EJS_COND_OR: - lval = l || r; - break; - default: - ejsError(ep, EJS_SYNTAX_ERROR, "Bad operator %d", rel); - return -1; - } - - /* MOB - rc */ - ejsWriteVarAsBoolean(ep, ep->result, lval); - return 0; -} - - -/******************************************************************************/ -/* - * return true if this string is a valid number - */ - -static int stringIsNumber(const char *s) -{ - char *endptr = NULL; - - if (s == NULL || *s == 0) { - return 0; - } - /* MOB -- not ideal */ -#if BREW - /* MOB this should check all digits and not just the first. */ - /* Does not support floating point - easy */ - - if (isdigit(*s) || (*s == '-' && isdigit(s[1]))) { - return 1; - } -#else - strtod(s, &endptr); -#endif - if (endptr != NULL && *endptr == 0) { - return 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Evaluate an operation. Returns with the result in ep->result. Returns -1 - * on errors, otherwise zero is returned. - */ - -static int evalExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) -{ - EjsNum lval; - char *str; - int rc; - - mprAssert(rel > 0); - str = 0; - lval = 0; - - /* - * Type conversion. This is tricky and must be according to the standard. - * Only numbers (including floats) and strings can be compared. All other - * types are first converted to numbers by preference and if that fails, - * to strings. - * - * MOB -- should we do "valueOf" here also. - */ - if (lhs->type == EJS_TYPE_OBJECT && - (rhs->type != EJS_TYPE_OBJECT && - (rhs->type != EJS_TYPE_UNDEFINED && rhs->type != EJS_TYPE_NULL))) { - if (ejsVarIsNumber(rhs)) { - if (ejsRunMethod(ep, lhs, "toValue", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, lhs, ep->result, EJS_SHALLOW_COPY); - } else { - if (ejsRunMethod(ep, lhs, "toString", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, lhs, ep->result, EJS_SHALLOW_COPY); - } - } - - } else { - if (ejsRunMethod(ep, lhs, "toString", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, lhs, ep->result, EJS_SHALLOW_COPY); - } else { - if (ejsRunMethod(ep, lhs, "toValue", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, lhs, ep->result, EJS_SHALLOW_COPY); - } - } - } - /* Nothing more can be done */ - } - - if (rhs->type == EJS_TYPE_OBJECT && - (lhs->type != EJS_TYPE_OBJECT && - (lhs->type != EJS_TYPE_UNDEFINED && lhs->type != EJS_TYPE_NULL))) { - if (ejsVarIsNumber(lhs)) { - /* If LHS is number, then convert to a value first */ - if (ejsRunMethod(ep, rhs, "toValue", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, rhs, ep->result, EJS_SHALLOW_COPY); - } else { - if (ejsRunMethod(ep, rhs, "toString", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, rhs, ep->result, EJS_SHALLOW_COPY); - } - } - - } else { - /* If LHS is not a number, then convert to a string first */ - if (ejsRunMethod(ep, rhs, "toString", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, rhs, ep->result, EJS_SHALLOW_COPY); - - } else { - if (ejsRunMethod(ep, rhs, "toValue", 0) == 0) { - /* MOB - rc */ - ejsWriteVar(ep, rhs, ep->result, EJS_SHALLOW_COPY); - } - } - } - /* Nothing more can be done */ - } - - /* - * undefined and null are special, in that they don't get promoted when - * comparing. - */ - if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) { - if (lhs->type == EJS_TYPE_UNDEFINED || - rhs->type == EJS_TYPE_UNDEFINED) { - return evalBoolExpr(ep, - lhs->type == EJS_TYPE_UNDEFINED, - rel, - rhs->type == EJS_TYPE_UNDEFINED); - } - - if (lhs->type == EJS_TYPE_NULL || rhs->type == EJS_TYPE_NULL) { - return evalBoolExpr(ep, - lhs->type == EJS_TYPE_NULL, - rel, - rhs->type == EJS_TYPE_NULL); - } - } - - /* - * From here on, lhs and rhs may contain allocated data (strings), so - * we must always destroy before overwriting. - */ - - /* - * Only allow a few bool operations. Otherwise convert to number. - */ - if (lhs->type == EJS_TYPE_BOOL && rhs->type == EJS_TYPE_BOOL && - (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && - rel != EJS_EXPR_BOOL_COMP)) { - ejsWriteVarAsNumber(ep, lhs, ejsVarToNumber(lhs)); - } - - /* - * Types do not match, so try to coerce the right operand to match the left - * But first, try to convert a left operand that is a numeric stored as a - * string, into a numeric. - */ - if (lhs->type != rhs->type) { - if (lhs->type == EJS_TYPE_STRING) { - if (stringIsNumber(lhs->string)) { - ejsWriteVarAsNumber(ep, lhs, ejsVarToNumber(lhs)); - - /* Examine further below */ - - } else { - /* - * Convert the RHS to a string - * MOB rc - */ - str = ejsVarToString(ep, rhs); - ejsWriteVarAsString(ep, rhs, str); - } - -#if BLD_FEATURE_FLOATING_POINT - } else if (lhs->type == EJS_TYPE_FLOAT) { - /* - * Convert rhs to floating - */ - ejsWriteVarAsFloat(ep, rhs, ejsVarToFloat(rhs)); - -#endif -#if BLD_FEATURE_INT64 - } else if (lhs->type == EJS_TYPE_INT64) { - /* - * Convert the rhs to 64 bit - */ - ejsWriteVarAsInteger64(ep, rhs, ejsVarToInteger64(rhs)); -#endif - } else if (lhs->type == EJS_TYPE_BOOL || lhs->type == EJS_TYPE_INT) { - - if (rhs->type == EJS_TYPE_STRING) { - if (stringIsNumber(rhs->string)) { - ejsWriteVarAsNumber(ep, rhs, ejsVarToNumber(rhs)); - } else { - /* - * Convert to lhs to a string - */ - str = ejsVarToString(ep, lhs); - /* MOB -- rc */ - if (str) { - ejsWriteVarAsString(ep, lhs, str); - } - } - -#if BLD_FEATURE_FLOATING_POINT - } else if (rhs->type == EJS_TYPE_FLOAT) { - /* - * Convert lhs to floating - */ - ejsWriteVarAsFloat(ep, lhs, ejsVarToFloat(lhs)); -#endif - - } else { - /* - * Forcibly convert both operands to numbers - */ - ejsWriteVarAsNumber(ep, lhs, ejsVarToNumber(lhs)); - ejsWriteVarAsNumber(ep, rhs, ejsVarToNumber(rhs)); - } - } - } - - /* - * We have failed to coerce the types to be the same. Special case here - * for undefined and null. We need to allow comparisions against these - * special values. - */ - if (lhs->type == EJS_TYPE_UNDEFINED || lhs->type == EJS_TYPE_NULL) { - switch (rel) { - case EJS_EXPR_EQ: - lval = lhs->type == rhs->type; - break; - case EJS_EXPR_NOTEQ: - lval = lhs->type != rhs->type; - break; - case EJS_EXPR_BOOL_COMP: - lval = ! ejsVarToBoolean(rhs); - break; - default: - ejsWriteVar(ep, ep->result, rhs, EJS_SHALLOW_COPY); - return 0; - } - ejsWriteVarAsBoolean(ep, ep->result, lval); - return 0; - } - - /* - * Types are the same here - */ - switch (lhs->type) { - default: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - /* Should be handled above */ - mprAssert(0); - return 0; - - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - case EJS_TYPE_PTR: - ejsWriteVarAsBoolean(ep, ep->result, 0); - return 0; - - case EJS_TYPE_OBJECT: - rc = evalObjExpr(ep, lhs, rel, rhs); - break; - - case EJS_TYPE_BOOL: - rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); - break; -#endif - - case EJS_TYPE_INT: - rc = evalNumericExpr(ep, (EjsNum) lhs->integer, rel, - (EjsNum) rhs->integer); - break; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - rc = evalNumericExpr(ep, (EjsNum) lhs->integer64, rel, - (EjsNum) rhs->integer64); - break; -#endif - - case EJS_TYPE_STRING: - rc = evalStringExpr(ep, lhs, rel, rhs); - } - - /* MOB */ - if (lhs->type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(lhs, 0); - mprAssert(lhs->objectState->alive == 0); - } - if (rhs->type == EJS_TYPE_OBJECT) { - ejsMakeObjLive(rhs, 0); - mprAssert(rhs->objectState->alive == 0); - } - - return rc; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Expressions with floating operands - */ - -static int evalFloatExpr(Ejs *ep, double l, int rel, double r) -{ - double lval; - int logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - lval = l / r; - break; - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, EJS_SYNTAX_ERROR, "Bad operator %d", rel); - return -1; - } - ejsWriteVarAsBoolean(ep, ep->result, lval != 0); - - } else { - ejsWriteVarAsFloat(ep, ep->result, lval); - } - return 0; -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ -/* - * Expressions with object operands - */ - -static int evalObjExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) -{ - int lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = lhs->objectState == rhs->objectState; - break; - case EJS_EXPR_NOTEQ: - lval = lhs->objectState != rhs->objectState; - break; - default: - ejsError(ep, EJS_SYNTAX_ERROR, "Bad operator %d", rel); - return -1; - } - ejsWriteVarAsBoolean(ep, ep->result, lval); - return 0; -} - -/******************************************************************************/ -/* - * Expressions with boolean operands - */ - -static int evalBoolExpr(Ejs *ep, int l, int rel, int r) -{ - int lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, EJS_SYNTAX_ERROR, "Bad operator %d", rel); - return -1; - } - ejsWriteVarAsBoolean(ep, ep->result, lval); - return 0; -} - -/******************************************************************************/ -/* - * Expressions with numeric operands - */ - -static int evalNumericExpr(Ejs *ep, EjsNum l, int rel, EjsNum r) -{ - EjsNum lval; - int logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - if (r != 0) { - lval = l / r; - } else { - ejsError(ep, EJS_RANGE_ERROR, "Divide by zero"); - return -1; - } - break; - case EJS_EXPR_MOD: - if (r != 0) { - lval = l % r; - } else { - ejsError(ep, EJS_RANGE_ERROR, "Modulo zero"); - return -1; - } - break; - case EJS_EXPR_LSHIFT: - lval = l << r; - break; - case EJS_EXPR_RSHIFT: - lval = l >> r; - break; - - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, EJS_SYNTAX_ERROR, "Bad operator %d", rel); - return -1; - } - ejsWriteVarAsBoolean(ep, ep->result, lval != 0); - - } else { - ejsWriteVarAsNumber(ep, ep->result, lval); - } - return 0; -} - -/******************************************************************************/ -/* - * Expressions with string operands - */ - -static int evalStringExpr(Ejs *ep, EjsVar *lhs, int rel, EjsVar *rhs) -{ - int lval; - - mprAssert(ep); - mprAssert(lhs); - mprAssert(rhs); - - switch (rel) { - case EJS_EXPR_LESS: - lval = strcmp(lhs->string, rhs->string) < 0; - break; - case EJS_EXPR_LESSEQ: - lval = strcmp(lhs->string, rhs->string) <= 0; - break; - case EJS_EXPR_GREATER: - lval = strcmp(lhs->string, rhs->string) > 0; - break; - case EJS_EXPR_GREATEREQ: - lval = strcmp(lhs->string, rhs->string) >= 0; - break; - case EJS_EXPR_EQ: - lval = strcmp(lhs->string, rhs->string) == 0; - break; - case EJS_EXPR_NOTEQ: - lval = strcmp(lhs->string, rhs->string) != 0; - break; - case EJS_EXPR_PLUS: - /* - * This differs from all the above operations. We append rhs to lhs. - */ - ejsClearVar(ep, ep->result); - ejsStrcat(ep, ep->result, lhs); - ejsStrcat(ep, ep->result, rhs); - return 0; - - case EJS_EXPR_INC: - case EJS_EXPR_DEC: - case EJS_EXPR_MINUS: - case EJS_EXPR_DIV: - case EJS_EXPR_MOD: - case EJS_EXPR_LSHIFT: - case EJS_EXPR_RSHIFT: - default: - ejsSyntaxError(ep, "Bad operator"); - return -1; - } - - ejsWriteVarAsBoolean(ep, ep->result, lval); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a method. obj is set to the current object if a method is being - * run. - */ - -static int evalMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, int flags) -{ - EjsProperty *pp; - EjsVar *saveThis, *prototype; - int saveThisPerm, rc, fid; - - mprAssert(ep); - - rc = 0; - fid = -1; - saveThis = 0; - saveThisPerm = 0; - prototype = proc->fn; - - if (prototype == 0) { - ejsError(ep, EJS_EVAL_ERROR, "Undefined method"); - return EJS_STATE_ERR; - } - - if (prototype->type == EJS_TYPE_OBJECT) { - prototype = ejsGetPropertyAsVar(ep, prototype, proc->procName); - } - - if (prototype) { - /* - * Create a new variable stack frame. ie. new local variables. - * Some C methods (eg. include) don't create a new local context. - */ - if (! (prototype->flags & EJS_NO_LOCAL)) { - fid = ejsOpenBlock(ep); - if (fid < 0) { - return EJS_STATE_ERR; - } - mprAssert(ejsBlockInUse(ep->local)); - - pp = ejsSetProperty(ep, ep->local, "this", obj); - ejsMakePropertyEnumerable(pp, 0); - - /* - * Optimization. Save "this" during this block. - */ - saveThis = ep->thisObject; - ep->thisObject = ejsGetVarPtr(pp); - saveThisPerm = ejsMakeObjPermanent(saveThis, 1); - } - - switch (prototype->type) { - default: - mprAssert(0); - break; - - case EJS_TYPE_STRING_CMETHOD: - rc = callStringCMethod(ep, obj, proc, prototype); - break; - - case EJS_TYPE_CMETHOD: - rc = callCMethod(ep, obj, proc, prototype); - break; - - case EJS_TYPE_METHOD: - rc = callMethod(ep, obj, proc, prototype); - break; - } - - if (fid >= 0) { - ejsMakeObjPermanent(saveThis, saveThisPerm); - ep->thisObject = saveThis; - mprAssert(ejsBlockInUse(ep->local)); - mprAssert(ejsBlockInUse(ep->thisObject)); - ejsCloseBlock(ep, fid); - } - } - - return rc; -} - -/******************************************************************************/ -/* - * Create a new object and call all required constructors. - * obj may be null in which case we look globally for className. - */ - -EjsVar *ejsCreateObjUsingArgvInternal(EJS_LOC_DEC(ep, loc), EjsVar *obj, - const char *className, MprArray *args) -{ - EjsVar *baseClass, *objectClass, *thisObj; - int rc; - - mprAssert(className && *className); - - /* - * Create a new object of the required class and pass it into the - * constructor as the "this" local variable. - */ - baseClass = ejsGetClass(ep, obj, className); - if (baseClass == 0) { - - if (obj && obj->objectState->className && - strcmp(obj->objectState->className, className) == 0) { - /* - * Handle case where we are calling the constructor inside - * the class. In this case, obj == baseClass. - */ - thisObj = ejsCreateSimpleObjUsingClassInt(EJS_LOC_PASS(ep, loc), - obj); - - } else { - - /* - * If the baseClass does not exist, try to create an Object - * We do this for compatibility with JS 1.5 style new Function. - * MOB -- but this masks an error if we really need className. - */ - objectClass = ejsGetClass(ep, 0, "Object"); - thisObj = ejsCreateSimpleObjUsingClassInt(EJS_LOC_PASS(ep, loc), - objectClass); - } - - } else { - thisObj = ejsCreateSimpleObjUsingClassInt(EJS_LOC_PASS(ep, loc), - baseClass); - } - - if (thisObj == 0) { - ejsMemoryError(ep); - return 0; - } - - /* - * Make the object permanent. While currently not alive, the constructor - * below may make the object alive. - */ - ejsMakeObjPermanent(thisObj, 1); - mprAssert(! ejsObjIsCollectable(thisObj)); - - rc = 0; - if (baseClass) { - if (! baseClass->objectState->noConstructor) { - rc = callConstructor(ep, thisObj, baseClass, args); - } - } else { - /* - * className is the function name when calling new on functions - */ - rc = ejsRunMethod(ep, thisObj, className, args); - } - - /* - * Constructor may change the type to a non-object. - * Function() does this. Ensure object is not collectable yet. - */ - if (ejsVarIsObject(thisObj)) { - ejsMakeObjPermanent(thisObj, 0); - ejsMakeObjLive(thisObj, 0); - } - - if (rc < 0) { - if (rc == MPR_ERR_NOT_FOUND) { - /* No constructor (default) */ - return thisObj; - } - if (! (ep->flags & EJS_FLAGS_EXIT)) { - if (! ep->gotException) { - ejsMemoryError(ep); - } - } - ejsFreeVar(ep, thisObj); - return 0; - } - - mprAssert(ejsBlockInUse(thisObj)); - - return thisObj; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct CallCons { - EjsVar *subClassConstructor, *subClass, *method; -} CallCons; - -/* - * Create a new object and call all required constructors. - */ - -static int callConstructor(Ejs *ep, EjsVar *thisObj, EjsVar *baseClass, - MprArray *args) -{ - CallCons *sp; - int state; - - if ((sp = pushFrame(ep, sizeof(CallCons))) == 0) { - return EJS_STATE_ERR; - } - - mprAssert(baseClass); - mprAssert(baseClass->objectState); - - state = 0; - - /* - * method will be null if there is no constructor for this class - */ - sp->method = ejsGetPropertyAsVar(ep, baseClass, - baseClass->objectState->className); - - if (sp->method == 0 || !ejsVarIsMethod(sp->method) || - !sp->method->callsSuper) { - /* - * Invoke base class constructors in reverse order (RECURSIVE) - */ - sp->subClass = baseClass->objectState->baseClass; - if (sp->subClass) { - - /* - * Note that the Object class does not have a constructor for - * speed. Construction for the base Object is done via - * ejsCreateObj above. The code below will invoke constructors - * in the right order (bottom up) via recursion. MOB -- need to - * scan for super() MOB -- Bug. Fails poorly if no constructor. - * Should allows this and invoke a default constructor. - */ - sp->subClassConstructor = ejsGetPropertyAsVar(ep, sp->subClass, - sp->subClass->objectState->className); - - if (sp->subClassConstructor) { - - if (callConstructor(ep, thisObj, sp->subClass, 0) < 0) { - if (! ep->gotException) { - ejsMemoryError(ep); - } - goto err; - } - } - } - } - - if (sp->method) { - /* - * Finally, invoke the constructor for this class itself. - */ - state = runMethod(ep, thisObj, sp->method, - baseClass->objectState->className, args); - } - -done: - popFrame(ep, sizeof(CallCons)); - return state; - -err: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Create a new object and call all required constructors using string args. - * MOB -- would be good to parse constructorArgs for "," and break into - * separate args. - * Returned object is not yet collectable. Will have alive bit cleared. - */ - -EjsVar *ejsCreateObj(Ejs *ep, EjsVar *obj, const char *className, - const char *constructorArgs) -{ - MprArray *args; - EjsVar *newp, *vp; - - args = mprCreateItemArray(ep, 0, 0); - if (args == 0) { - return 0; - } - - if (constructorArgs && *constructorArgs) { - vp = ejsCreateStringVarInternal(EJS_LOC_ARGS(ep), constructorArgs); - - if (mprAddItem(args, vp) < 0) { - mprFree(args); - return 0; - } - } - - newp = ejsCreateObjUsingArgv(ep, obj, className, args); - - ejsFreeMethodArgs(ep, args); - - mprAssert(! ejsObjIsCollectable(newp)); - mprAssert(ejsBlockInUse(newp)); - - return newp; -} - -/******************************************************************************/ - -static int callStringCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, - EjsVar *prototype) -{ - EjsVar **argValues; - MprArray *actualArgs; - char **argBuf, *str; - int i, rc; - - actualArgs = proc->args; - argValues = (EjsVar**) actualArgs->items; - - if (actualArgs->length > 0) { - argBuf = mprAlloc(ep, actualArgs->length * sizeof(char*)); - for (i = 0; i < actualArgs->length; i++) { - str = ejsVarToString(ep, argValues[i]); - /* MOB rc */ - argBuf[i] = mprStrdup(ep, str); - } - } else { - argBuf = 0; - } - - /* - * Call the method depending on the various handle flags - */ - ep->userData = prototype->cMethodWithStrings.userData; - if (prototype->flags & EJS_ALT_HANDLE) { - /* - * Used by the AppWeb GaCompat module. The alt handle is set to the - * web server request struct - */ - rc = ((EjsAltStringCMethod) - prototype->cMethodWithStrings.fn) - (ep, ep->altHandle, obj, actualArgs->length, argBuf); - - } else if (prototype->flags & EJS_PRIMARY_HANDLE) { - /* - * Used by ESP. The primary handle is set to the esp struct - */ - rc = (prototype->cMethodWithStrings.fn)(ep->primaryHandle, - obj, actualArgs->length, argBuf); - - } else { - /* - * Used EJS for the standard procs - */ - rc = (prototype->cMethodWithStrings.fn)(ep, obj, actualArgs->length, - argBuf); - } - - if (actualArgs->length > 0) { - for (i = 0; i < actualArgs->length; i++) { - mprFree(argBuf[i]); - } - mprFree(argBuf); - } - ep->userData = 0; - - return rc; -} - -/******************************************************************************/ - -static int callCMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, EjsVar *prototype) -{ - EjsVar **argValues; - MprArray *actualArgs; - int rc; - - actualArgs = proc->args; - argValues = (EjsVar**) actualArgs->items; - - ep->userData = prototype->cMethod.userData; - - /* - * Call the method depending on the various handle flags - * Sometimes cMethod.fn is NULL if there is no constructor for - * an object. - */ - if (prototype->flags & EJS_ALT_HANDLE) { - /* - * Use by the GaCompat module. The alt handle is set to the - * web server request struct - */ - rc = ((EjsAltCMethod) prototype->cMethod.fn) - (ep, ep->altHandle, obj, actualArgs->length, argValues); - - } else if (prototype->flags & EJS_PRIMARY_HANDLE) { - /* - * Used by ESP. The primary handle is set to the esp struct - */ - rc = (prototype->cMethod.fn) - (ep->primaryHandle, obj, actualArgs->length, argValues); - - } else { - /* - * Used EJS for the standard procs - */ - rc = (prototype->cMethod.fn)(ep, obj, actualArgs->length, argValues); - } - - ep->userData = 0; - - return rc; -} - -/******************************************************************************/ -/* - * Local vars - */ - -typedef struct CallMethod { - MprArray *formalArgs, *actualArgs; - EjsVar *arguments, *callee, **argValues; - char **argNames, buf[16]; - int i, argumentsObj; -} CallMethod; - - -static int callMethod(Ejs *ep, EjsVar *obj, EjsProc *proc, EjsVar *prototype) -{ - CallMethod *sp; - int i; - - if ((sp = pushFrame(ep, sizeof(CallMethod))) == 0) { - return EJS_STATE_ERR; - } - - sp->arguments = 0; - sp->callee = 0; - - sp->actualArgs = proc->args; - sp->argValues = (EjsVar**) sp->actualArgs->items; - sp->formalArgs = prototype->method.args; - sp->argNames = (char**) sp->formalArgs->items; - - /* - * Only create arguments and callee if the function actually uses them - */ - sp->argumentsObj = 0; - if (strstr(prototype->method.body, "arguments") != 0) { - sp->argumentsObj++; - - /* - * Create the arguments and callee variables - * MOB -- should we make real arrays here ? YES - */ - sp->arguments = ejsCreateSimpleObj(ep, "Object"); - ejsSetVarName(ep, sp->arguments, "arguments"); - mprAssert(! ejsObjIsCollectable(sp->arguments)); - - sp->callee = ejsCreateSimpleObj(ep, "Object"); - ejsSetVarName(ep, sp->callee, "callee"); - mprAssert(! ejsObjIsCollectable(sp->callee)); - - /* - * Overwrite the length property - */ - ejsSetPropertyToInteger(ep, sp->arguments, "length", - sp->actualArgs->length); - ejsSetPropertyToInteger(ep, sp->callee, "length", - sp->formalArgs->length); - } - - /* - * Define all the agruments to be set to the actual parameters - */ - for (i = 0; i < sp->formalArgs->length; i++) { - if (i >= sp->actualArgs->length) { - /* MOB -- return code */ - ejsCreateProperty(ep, ep->local, sp->argNames[i]); - - } else { - /* MOB -- return code */ - ejsSetProperty(ep, ep->local, sp->argNames[i], sp->argValues[i]); - } - } - - if (sp->argumentsObj) { - for (i = 0; i < sp->actualArgs->length; i++) { - mprItoa(sp->buf, sizeof(sp->buf), i); - ejsSetProperty(ep, sp->arguments, sp->buf, sp->argValues[i]); - } - - ejsSetPropertyAndFree(ep, sp->arguments, "callee", sp->callee); - ejsSetPropertyAndFree(ep, ep->local, "arguments", sp->arguments); - } - - /* - * Actually run the method - */ - - i = ejsEvalScript(ep, prototype->method.body, 0); - - popFrame(ep, sizeof(CallMethod)); - return i; -} - -/******************************************************************************/ -/* - * Run a method. Obj is set to "this" object. MethodName must exist in it - * or in a sub class. - */ - -int ejsRunMethod(Ejs *ep, EjsVar *obj, const char *methodName, MprArray *args) -{ - EjsProperty *pp; - EjsProc proc, *saveProc; - int rc; - - mprAssert(obj); - mprAssert(methodName && *methodName); - - pp = ejsGetProperty(ep, obj, methodName); - if (pp == 0) { - /* MOB -- this should be all in some common accessor routine */ - pp = ejsGetProperty(ep, ep->local, methodName); - if (pp == 0) { - pp = ejsGetProperty(ep, ep->global, methodName); - if (pp == 0) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Undefined method \"%s\"", methodName); - return MPR_ERR_NOT_FOUND; - } - } - } - - saveProc = ep->proc; - ep->proc = &proc; - - memset(&proc, 0, sizeof(EjsProc)); - - ejsClearVar(ep, ep->result); - - /* MOB -- if closures are going to work, we need to have proc be an - Object and let the GC look after it */ - - proc.fn = &pp->var; - if (proc.fn == 0 || proc.fn->type == EJS_TYPE_UNDEFINED) { - ep->proc = saveProc; - return MPR_ERR_NOT_FOUND; - } - - proc.procName = mprStrdup(ep, methodName); - if (args == 0) { - proc.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - } else { - proc.args = args; - } - - rc = evalMethod(ep, obj, &proc, 0); - - if (args) { - proc.args = 0; - } - freeProc(ep, &proc); - - ep->proc = saveProc; - - return rc; -} - -/******************************************************************************/ -/* - * Run a method. Obj is set to "this" object. MethodName must exist in it - * or in a sub class. - */ - -int ejsRunMethodCmd(Ejs *ep, EjsVar *obj, const char *methodName, - const char *cmdFmt, ...) -{ - MprArray *args; - va_list cmdArgs; - char *buf, *arg, *cp; - int rc; - - mprAssert(methodName && *methodName); - mprAssert(cmdFmt && *cmdFmt); - - va_start(cmdArgs, cmdFmt); - mprAllocVsprintf(MPR_LOC_ARGS(ep), &buf, 0, cmdFmt, cmdArgs); - va_end(cmdArgs); - - args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - - for (arg = cp = buf; cp && *cp; cp++) { - if (*cp == ',') { - *cp = 0; - mprAddItem(args, ejsParseVar(ep, arg, 0)); - arg = cp + 1; - } - } - if (cp > arg) { - mprAddItem(args, ejsParseVar(ep, arg, 0)); - } - - rc = ejsRunMethod(ep, obj, methodName, args); - - ejsFreeMethodArgs(ep, args); - mprFree(buf); - - return rc; -} - -/******************************************************************************/ -/* - * Run a method. Obj is set to "this" object. - */ - -static int runMethod(Ejs *ep, EjsVar *thisObj, EjsVar *method, - const char *methodName, MprArray *args) -{ - EjsProc proc, *saveProc; - int rc; - - mprAssert(thisObj); - mprAssert(method); - - saveProc = ep->proc; - ep->proc = &proc; - - memset(&proc, 0, sizeof(EjsProc)); - - ejsClearVar(ep, ep->result); - - /* MOB -- if closures are going to work, we need to have proc be an - Object and let the GC look after it */ - - proc.fn = method; - if (proc.fn == 0 || proc.fn->type == EJS_TYPE_UNDEFINED) { - ep->proc = saveProc; - return MPR_ERR_NOT_FOUND; - } - - proc.procName = mprStrdup(ep, methodName); - if (args == 0) { - proc.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - } else { - proc.args = args; - } - - rc = evalMethod(ep, thisObj, &proc, 0); - - if (args) { - proc.args = 0; - } - freeProc(ep, &proc); - - ep->proc = saveProc; - - return rc; -} - -/******************************************************************************/ -/* - * Find which object contains the property given the current context. - * We call this when there is no explicit object and the object must be - * determined by the context. - */ - -static EjsVar *pickSpace(Ejs *ep, int state, const char *property, int flags) -{ - EjsVar *obj; - - mprAssert(ep); - mprAssert(property && *property); - - /* MOB - this is ugly and the logic is confused */ - - if (flags & EJS_FLAGS_GLOBAL) { - obj = ep->global; - - } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { - obj = ep->local; - - } else { - /* First look local, then this and finally global */ - - if (ejsGetSimpleProperty(ep, ep->local, property)) { - obj = ep->local; - - } else if (ep->thisObject && - findProperty(ep, ep->thisObject, property, flags)) { - obj = ep->thisObject; - - } else { -#if EJS_ECMA_STND - obj = ep->global; -#else - if (flags & EJS_FLAGS_EXE && - !findProperty(ep, ep->global, property, flags)) { - obj = ep->local; - } else { - obj = ep->global; - } -#endif - } - } - return obj; -} - -/******************************************************************************/ -/* - * Find an object property given a object and a property name. We - * intelligently look in the local and global namespaces depending on - * our state. If not found in local or global, try base classes for method - * names only. Returns the property or NULL. - * MOB -- need to rework this API. - */ - -static EjsProperty *searchSpacesForProperty(Ejs *ep, int state, EjsVar *obj, - char *property, int flags) -{ - EjsProperty *pp; - - if (obj) { - return findProperty(ep, obj, property, flags); - } - - /* MOB -- really should have a search stack */ - - pp = findProperty(ep, ep->local, property, flags); - if (pp == 0 && state != EJS_STATE_DEC) { - - if (ep->thisObject) { - pp = findProperty(ep, ep->thisObject, property, flags); - } - if (pp == 0) { - pp = findProperty(ep, ep->global, property, flags); - } - } - return pp; -} - -/******************************************************************************/ -/* - * Search an object and its base classes to find an object given an object - * an a property name. If not an assignment (LHS), then follow base classes. - * Otherwise, just look in the specified object. - */ - -static EjsProperty *findProperty(Ejs *ep, EjsVar *op, const char *property, - int flags) -{ - /* MOB -- NEW. Remove when EXE fixes are in. */ - if (! (flags & EJS_FLAGS_EXE) && op->type == EJS_TYPE_UNDEFINED) { - return 0; - } - - if (flags & EJS_FLAGS_LHS) { - return ejsGetPropertyPtr(ejsGetSimpleProperty(ep, op, property)); - - } else { - /* - * Follow base classes - */ - return ejsGetPropertyPtr(ejsGetProperty(ep, op, property)); - } -} - -/******************************************************************************/ -/* - * Update result - */ - -static void updateResult(Ejs *ep, int state, int flags, EjsVar *vp) -{ - if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { - ejsClearVar(ep, ep->result); - if (vp) { - ejsWriteVar(ep, ep->result, vp, EJS_SHALLOW_COPY); - ejsSetVarName(ep, ep->result, vp->propertyName); - } - } -} - -/******************************************************************************/ -/* - * Append to the pointer value - */ - -int ejsStrcat(Ejs *ep, EjsVar *dest, EjsVar *src) -{ - char *oldBuf, *buf, *str; - int oldLen, newLen, len; - - mprAssert(dest); - mprAssert(ejsVarIsString(src)); - - if (ejsVarIsValid(dest)) { - - if (! ejsVarIsString(dest)) { - /* Bad type for dest */ - return -1; - } - - if (! ejsVarIsString(src)) { - str = ejsVarToString(ep, src); - if (str == 0) { - return -1; - } - len = strlen(str); - - } else { - str = src->string; - len = src->length; - } - - oldBuf = dest->string; - oldLen = dest->length; - newLen = oldLen + len + 1; - - if (newLen < MPR_SLAB_STR_MAX) { - buf = oldBuf; - } else { - buf = mprRealloc(ep, oldBuf, newLen); - if (buf == 0) { - return -1; - } - dest->string = buf; - } - memcpy(&buf[oldLen], str, len); - dest->length += len; - - } else { - ejsWriteVarAsString(ep, dest, src->string); - } - return 0; -} - -/******************************************************************************/ -/* - * Exit the script - */ - -void ejsExit(Ejs *ep, int status) -{ - ep->scriptStatus = status; - ep->flags |= EJS_FLAGS_EXIT; -} - -/******************************************************************************/ -/* - * Free an argument list - */ - -static void freeProc(Ejs *ep, EjsProc *proc) -{ - if (proc->args) { - ejsFreeMethodArgs(ep, proc->args); - } - - if (proc->procName) { - mprFree(proc->procName); - proc->procName = NULL; - } -} - -/******************************************************************************/ - -void ejsFreeMethodArgs(Ejs *ep, MprArray *args) -{ - int i; - - for (i = args->length - 1; i >= 0; i--) { - ejsFreeVar(ep, args->items[i]); - mprRemoveItemByIndex(args, i); - } - mprFree(args); -} - -/******************************************************************************/ -/* - * This method removes any new lines. Used for else cases, etc. - */ - -static void removeNewlines(Ejs *ep, int state) -{ - int tid; - - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - ejsLexPutbackToken(ep, tid, ep->token); -} - -/******************************************************************************/ - -static int getNextNonSpaceToken(Ejs *ep, int state) -{ - int tid; - - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - return tid; -} - -/******************************************************************************/ - -int ejsGetFlags(Ejs *ep) -{ - return ep->flags; -} - -/******************************************************************************/ - -bool ejsIsExiting(Ejs *ep) -{ - return (ep->flags & EJS_FLAGS_EXIT) ? 1: 0; -} - -/******************************************************************************/ - -void ejsClearExiting(Ejs *ep) -{ - ep->flags &= ~EJS_FLAGS_EXIT; -} - -/******************************************************************************/ - -static EjsInput *getInputStruct(Ejs *ep) -{ - EjsInput *input; - - if (ep->inputList) { - input = ep->inputList; - ep->inputList = input->nextInput; - - } else { - input = mprAlloc(ep, sizeof(EjsInput)); - } - return input; -} - -/******************************************************************************/ - -static void freeInputStruct(Ejs *ep, EjsInput *input) -{ - input->nextInput = ep->inputList; - ep->inputList = input; -} - -/******************************************************************************/ - -static void *pushFrame(Ejs *ep, int size) -{ - /* - * Grow down stack - */ - ep->stkPtr -= size; - if (ep->stkPtr < ep->stack) { - mprError(ep, MPR_LOC, "Exceeded parse stack"); - return 0; - } - return ep->stkPtr; -} - -/******************************************************************************/ - -static void *popFrame(Ejs *ep, int size) -{ - ep->stkPtr += size; - if (ep->stkPtr > &ep->stack[EJS_MAX_STACK]) { - mprError(ep, MPR_LOC, "Over poped parse stack"); - return 0; - } - return ep->stkPtr; -} - -/******************************************************************************/ -#else -void ejsParserDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsVar.c b/source4/lib/appweb/ejs-2.0/ejs/ejsVar.c deleted file mode 100644 index 1f8e9266a3..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsVar.c +++ /dev/null @@ -1,4033 +0,0 @@ -/** - * @file ejsVar.c - * @brief Mbedthis Portable Runtime Universal Variable Type - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This module is NOT multithreaded. - * - * Properties are variables that are stored in an object type variable. - * Properties can be primitive data types, other objects or methods. - * Properties are indexed by a character name. - */ - -/********************************** Includes **********************************/ - -#include "ejs.h" - -/***************************** Forward Declarations ***************************/ - -static EjsProperty *allocProperty(Ejs *ep, EjsVar *op, const char *property, - int propertyIndex, EjsProperty *last); -static EjsVar *copyVar(EJS_LOC_DEC(ep, loc), EjsVar *dest, - const EjsVar *src, EjsCopyDepth copyDepth); -static EjsObj *createObj(EJS_LOC_DEC(ep, loc)); -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); -static int hash(const char *property); -static void unlinkProperty(EjsObj *obj, EjsPropLink *propLink); -static void linkPropertyBefore(EjsObj *obj, EjsPropLink *at, - EjsPropLink *propLink); -static int sortAllProperties(Ejs *ep, EjsProperty *p1, - EjsProperty *p2, const char *propertyName, int order); -static int sortByProperty(Ejs *ep, EjsProperty *p1, EjsProperty *p2, - const char *propertyName, int order); -static int dupString(MPR_LOC_DEC(ctx, loc), uchar **dest, - const void *src, int nbytes); -#if UNUSED && KEEP -static void linkPropertyAfter(EjsObj *obj, EjsPropLink *at, - EjsPropLink *propLink); -#endif - -static EjsProperty *hashLookup(EjsObj *obj, const char *property, - int *propertyIndex, EjsProperty **hashTail); - -/******************************************************************************/ -/********************************** Var Routines ******************************/ -/******************************************************************************/ - -EjsType ejsGetVarType(EjsVar *vp) -{ - mprAssert(vp); - - return vp->type; -} - -/******************************************************************************/ - -void ejsFreeVar(Ejs *ep, EjsVar *vp) -{ - if (vp) { - ejsClearVar(ep, vp); - ejsFree(ep, vp, EJS_SLAB_VAR); - } -} - -/******************************************************************************/ -#if UNUSED -/* - * Clear the value by freeing any allocated data. This will release objects - * so that later garbage collection can reclaim storage if there are no other - * object references. - */ - -void ejsZeroVar(Ejs *ep, EjsVar *vp) -{ - vp->type = EJS_TYPE_UNDEFINED; - vp->objectState = 0; - vp->method.body = 0; - vp->method.args = 0; - vp->callsSuper = 0; - vp->ptr.destructor = 0; - vp->allocatedData = 0; -} - -#endif -/******************************************************************************/ -/* - * Clear the value by freeing any allocated data. This will release objects - * so that later garbage collection can reclaim storage if there are no other - * object references. - */ - -void ejsClearVar(Ejs *ep, EjsVar *vp) -{ - MprArray *argList; - int i; - - mprAssert(vp); - mprAssert(ep); - - if (! vp->allocatedData) { - vp->type = EJS_TYPE_UNDEFINED; - return; - } - if (vp->type == EJS_TYPE_UNDEFINED) { - return; - } - - switch (vp->type) { - default: - break; - - case EJS_TYPE_STRING: - mprFree(vp->string); - vp->string = 0; - break; - - case EJS_TYPE_OBJECT: - /* - * Set the "alive" bit so that the GC will cleanup if no - * other references. - */ - if (vp->objectState) { - vp->objectState->alive = 1; - } - vp->objectState = 0; - break; - - case EJS_TYPE_METHOD: - argList = vp->method.args; - /* - * MOB OPT -- should be able to do just one mprFree(vp->method.args) - */ - mprFree(vp->method.body); - if (argList) { - for (i = 0; i < argList->length; i++) { - mprFree(argList->items[i]); - } - mprFree(vp->method.args); - } - vp->method.args = 0; - vp->method.body = 0; - vp->callsSuper = 0; - break; - - case EJS_TYPE_PTR: - if (vp->ptr.destructor) { - (vp->ptr.destructor)(ep, vp); - } - break; - } - - vp->type = EJS_TYPE_UNDEFINED; - vp->allocatedData = 0; -} - -/******************************************************************************/ -/* - * Initialize an undefined value. - */ - -EjsVar *ejsCreateUndefinedVar(Ejs *ep) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_UNDEFINED; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize an null value. - */ - -EjsVar *ejsCreateNullVar(Ejs *ep) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_NULL; - } - return vp; -} - -/******************************************************************************/ - -EjsVar *ejsCreateBoolVar(Ejs *ep, int value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_BOOL; - vp->boolean = value; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize a C method. - */ - -EjsVar *ejsCreateCMethodVar(Ejs *ep, EjsCMethod fn, void *userData, int flags) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_CMETHOD; - vp->cMethod.fn = fn; - vp->cMethod.userData = userData; - vp->flags = flags; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize a C method. - */ - -EjsVar *ejsCreateStringCMethodVar(Ejs *ep, EjsStringCMethod fn, - void *userData, int flags) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(fn); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_STRING_CMETHOD; - vp->cMethodWithStrings.fn = fn; - vp->cMethodWithStrings.userData = userData; - vp->flags = flags; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize an opaque pointer. - */ - -EjsVar *ejsCreatePtrVar(Ejs *ep, void *ptr, EjsDestructor destructor) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(ptr); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_PTR; - vp->ptr.userPtr = ptr; - vp->ptr.destructor = destructor; - vp->allocatedData = 1; - } - return vp; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Initialize a floating value. - */ - -EjsVar *ejsCreateFloatVar(Ejs *ep, double value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_FLOAT; - vp->floating = value; - } - return vp; -} - -#endif -/******************************************************************************/ -/* - * Initialize an integer value. - */ - -EjsVar *ejsCreateIntegerVar(Ejs *ep, int value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_INT; - vp->integer = value; - } - return vp; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Initialize a 64-bit integer value. - */ - -EjsVar *ejsCreateInteger64Var(Ejs *ep, int64 value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_INT64; - vp->integer64 = value; - } - return vp; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Initialize an number variable. Type is defined by configure. - */ - -EjsVar *ejsCreateNumberVar(Ejs *ep, EjsNum value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - mprAssert(vp); - - if (vp) { - vp->type = BLD_FEATURE_NUM_TYPE_ID; -#if BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_INT64 - vp->integer64 = value; -#elif BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_FLOAT - vp->float = value; -#else - vp->integer = value; -#endif - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize a (bare) JavaScript method. args and body can be null. - */ - -EjsVar *ejsCreateMethodVar(Ejs *ep, const char *body, MprArray *args, int flags) -{ - EjsVar *vp; - int i; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - mprAssert(vp); - - if (vp == 0) { - return 0; - } - - vp->type = EJS_TYPE_METHOD; - - vp->allocatedData = 1; - - vp->method.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - if (vp->method.args == 0) { - mprAssert(vp->method.args); - ejsFreeVar(ep, vp); - return 0; - } - - if (args) { - for (i = 0; i < args->length; i++) { - mprAddItem(vp->method.args, - mprStrdup(vp->method.args, mprGetItem(args, i))); - } - } - vp->method.body = mprStrdup(vp->method.args, body); - - if (vp->method.body == 0) { - ejsFreeVar(ep, vp); - return 0; - } - vp->flags = flags; - - return vp; -} - -/******************************************************************************/ -/* - * Initialize an object variable. - */ - -EjsVar *ejsCreateObjVarInternal(EJS_LOC_DEC(ep, loc)) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); - mprAssert(vp); - - if (vp) { - vp->type = EJS_TYPE_OBJECT; - vp->objectState = createObj(EJS_LOC_PASS(ep, loc)); - if (vp->objectState == 0) { - ejsFreeVar(ep, vp); - return 0; - } - vp->allocatedData = 1; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -EjsVar *ejsCreateStringVarInternal(EJS_LOC_DEC(ep, loc), const char *value) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); - mprAssert(vp); - - if (vp) { - vp->type = EJS_TYPE_STRING; - vp->string = mprStrdupInternal(EJS_LOC_PASS(ep, loc), value); - if (vp->string == 0) { - ejsFreeVar(ep, vp); - return 0; - } - vp->length = strlen(vp->string); - vp->allocatedData = 1; - } - return vp; -} - -/******************************************************************************/ -/* - * Initialize a binary string value. - */ - -EjsVar *ejsCreateBinaryStringVar(Ejs *ep, const uchar *value, int len) -{ - EjsVar *vp; - - mprAssert(ep); - - vp = ejsAllocVar(EJS_LOC_ARGS(ep)); - if (vp) { - vp->type = EJS_TYPE_STRING; - vp->length = dupString(MPR_LOC_ARGS(ep), &vp->ustring, value, len); - if (vp->length < 0) { - ejsFreeVar(ep, vp); - return 0; - } - vp->allocatedData = 1; - } - return vp; -} - -/******************************************************************************/ - -void ejsSetClassName(Ejs *ep, EjsVar *vp, const char *name) -{ - EjsObj *obj; - - if (vp == 0 || !ejsVarIsObject(vp) || vp->objectState == 0) { - mprAssert(0); - return; - } - obj = vp->objectState; - - if (obj->className) { - mprFree(obj->className); - } - obj->className = mprStrdup(ep, name); -} - -/******************************************************************************/ - -EjsVar *ejsDupVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *src, - EjsCopyDepth copyDepth) -{ - EjsVar *vp; - - vp = ejsAllocVar(EJS_LOC_PASS(ep, loc)); - if (vp == 0) { - return 0; - } - - vp->type = EJS_TYPE_UNDEFINED; - - return copyVar(EJS_LOC_PASS(ep, loc), vp, src, copyDepth); -} - -/******************************************************************************/ -/* - * Set a var to a new value - */ - -EjsVar *ejsWriteVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *dest, - const EjsVar *src, EjsCopyDepth copyDepth) -{ - mprAssert(dest); - mprAssert(src); - - return copyVar(EJS_LOC_PASS(ep, loc), dest, src, copyDepth); -} - -/******************************************************************************/ -/* - * Set a var using a new bool value - */ - -EjsVar *ejsWriteVarAsBoolean(Ejs *ep, EjsVar *dest, int value) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_BOOL; - dest->boolean = value; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var using a new C Method - */ - -EjsVar *ejsWriteVarAsCMethod(Ejs *ep, EjsVar *dest, EjsCMethod fn, - void *userData, int flags) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_CMETHOD; - dest->cMethod.fn = fn; - dest->cMethod.userData = userData; - dest->flags = flags; - dest->allocatedData = 0; - - return dest; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Set a var using a new float value - */ - -EjsVar *ejsWriteVarAsFloat(Ejs *ep, EjsVar *dest, double value) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_FLOAT; - dest->floating = value; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -#endif -/******************************************************************************/ -/* - * Set a var using a new integer value - */ - -EjsVar *ejsWriteVarAsInteger(Ejs *ep, EjsVar *dest, int value) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_INT; - dest->integer = value; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Set a var using a new integer value - */ - -EjsVar *ejsWriteVarAsInteger64(Ejs *ep, EjsVar *dest, int64 value) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_INT64; - dest->integer64 = value; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -#endif -/******************************************************************************/ -/* - * Set a var using a new Method - */ - -EjsVar *ejsWriteVarAsMethod(Ejs *ep, EjsVar *dest, const char *body, - MprArray *args) -{ - EjsVar **srcArgs, *arg; - int i; - - mprAssert(ep); - mprAssert(dest); - mprAssert(body); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->method.args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - if (dest->method.args == 0) { - return 0; - } - - dest->type = EJS_TYPE_METHOD; - - if (args) { - srcArgs = (EjsVar**) args->items; - for (i = 0; i < args->length; i++) { - arg = ejsDupVar(ep, srcArgs[i], EJS_SHALLOW_COPY); - if (arg == 0) { - return 0; - } - if (mprAddItem(dest->method.args, arg) < 0) { - return 0; - } - } - } - - dest->method.body = mprStrdup(dest->method.args, body); - if (dest->method.body == 0) { - return 0; - } - - dest->allocatedData = 1; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var to null - */ - -EjsVar *ejsWriteVarAsNull(Ejs *ep, EjsVar *dest) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_NULL; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var using a new number value - */ - -EjsVar *ejsWriteVarAsNumber(Ejs *ep, EjsVar *dest, EjsNum value) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_NUM_VAR; - dest->ejsNumber = value; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var using a new C Method - */ - -EjsVar *ejsWriteVarAsStringCMethod(Ejs *ep, EjsVar *dest, EjsStringCMethod fn, - void *userData, int flags) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_CMETHOD; - dest->cMethodWithStrings.fn = fn; - dest->cMethodWithStrings.userData = userData; - dest->flags = flags; - dest->allocatedData = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var using a new string value - */ - -EjsVar *ejsWriteVarAsStringInternal(EJS_LOC_DEC(ep, loc), EjsVar *dest, - const char *value) -{ - mprAssert(dest); - mprAssert(value); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->string = mprStrdupInternal(EJS_LOC_PASS(ep, loc), value); - if (dest->string == 0) { - return 0; - } - - dest->length = strlen(dest->string); - - dest->type = EJS_TYPE_STRING; - dest->allocatedData = 1; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var using a new string value - */ - -EjsVar *ejsWriteVarAsBinaryString(Ejs *ep, EjsVar *dest, const uchar *value, - int len) -{ - mprAssert(dest); - mprAssert(value); - - ejsClearVar(ep, dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->length = dupString(MPR_LOC_ARGS(ep), &dest->ustring, value, len); - if (dest->length < 0) { - return 0; - } - - dest->type = EJS_TYPE_STRING; - dest->allocatedData = 1; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Set a var to undefined - */ - -EjsVar *ejsWriteVarAsUndefined(Ejs *ep, EjsVar *dest) -{ - mprAssert(dest); - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->type = EJS_TYPE_UNDEFINED; - dest->allocatedData = 0; - dest->flags = 0; - - return dest; -} - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - * If you provide a format, you MUST ensure you know the type. - * Caller must free the result. - */ - -char *ejsFormatVar(Ejs *ep, const char *fmt, EjsVar *vp) -{ - char *buf, *src, *value, *allocValue; - uchar *ubuf; - int len; - - buf = 0; - allocValue = 0; - value = 0; - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - value = "undefined"; - break; - - case EJS_TYPE_NULL: - value = "null"; - break; - - case EJS_TYPE_PTR: - if (fmt == NULL || *fmt == '\0') { - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, - "[Opaque Pointer %p]", vp->ptr.userPtr); - } else { - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, vp->ptr); - } - goto done; - - case EJS_TYPE_BOOL: - value = (vp->boolean) ? "true" : "false"; - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - if (fmt == NULL || *fmt == '\0') { - fmt = "%f"; - } - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, vp->floating); - goto done; -#endif - - case EJS_TYPE_INT: - if (fmt == NULL || *fmt == '\0') { - fmt = "%d"; - } - mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, vp->integer); - goto done; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - if (fmt == NULL || *fmt == '\0') { - fmt = "%Ld"; - } - mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, vp->integer64); - goto done; -#endif - - case EJS_TYPE_CMETHOD: - value = "[C Method]"; - break; - - case EJS_TYPE_STRING_CMETHOD: - value = "[C StringMethod]"; - break; - - case EJS_TYPE_METHOD: - value = ejsVarToString(ep, vp); - break; - - case EJS_TYPE_OBJECT: - value = ejsVarToString(ep, vp); - break; - - case EJS_TYPE_STRING: - src = vp->string; - mprAssert(src); - - if (fmt && *fmt && src) { - mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, src); - - } else if (src == NULL) { - buf = mprStrdup(ep, "null"); - - } else { - ubuf = (uchar*) buf; - if (dupString(MPR_LOC_ARGS(ep), &ubuf, src, vp->length) < 0) { - return mprStrdup(ep, ""); - } - buf = (char*) ubuf; - } - break; - - default: - mprAssert(0); - } - - if (fmt == NULL || *fmt == '\0') { - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, "%s", value); - } else { - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &buf, 0, fmt, value); - } - -done: - if (allocValue) { - mprFree(allocValue); - } - return buf; -} - -/******************************************************************************/ -/* - * Convert the variable to a boolean. Only for primitive types. - */ - -int ejsVarToBoolean(EjsVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - return 0; - - case EJS_TYPE_OBJECT: - return (vp->objectState != NULL); - - case EJS_TYPE_PTR: - return (vp->ptr.userPtr != NULL); - - case EJS_TYPE_BOOL: - return vp->boolean; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - return (vp->floating != 0 && !ejsIsNan(vp->floating)); -#endif - - case EJS_TYPE_INT: - return (vp->integer != 0); - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - return (vp->integer64 != 0); -#endif - - case EJS_TYPE_STRING: - return (vp->length > 0); -#if UNUSED - if (strcmp(vp->string, "true") == 0 || - strcmp(vp->string, "TRUE") == 0) { - return 1; - - } else if (strcmp(vp->string, "false") == 0 || - strcmp(vp->string, "FALSE") == 0) { - return 0; - - } else { - return atoi(vp->string); - } -#endif - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the variable to a floating point number. Only for primitive types. - */ - -double ejsVarToFloat(EjsVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - case EJS_TYPE_OBJECT: - case EJS_TYPE_PTR: - return 0; - - case EJS_TYPE_BOOL: - return (vp->boolean) ? 1.0 : 0.0; - - case EJS_TYPE_FLOAT: - return vp->floating; - - case EJS_TYPE_INT: - return (double) vp->integer; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - return (double) vp->integer64; -#endif - - case EJS_TYPE_STRING: - if (vp->length == 0) { - return 0.0; - } else { - return atof(vp->string); - } - } - - /* Not reached */ - return 0; -} - -#endif -/******************************************************************************/ -/* - * Convert the variable to an Integer type. Only works for primitive types. - */ - -int ejsVarToInteger(EjsVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - case EJS_TYPE_OBJECT: - return 0; - - case EJS_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - if (ejsIsNan(vp->floating)) { - return 0; - } - return (int) vp->floating; -#endif - - case EJS_TYPE_INT: - return vp->integer; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - return (int) vp->integer64; -#endif - - case EJS_TYPE_STRING: - if (vp->length == 0) { - return 0; - } else { - return ejsParseInteger(vp->string); - } - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the variable to an Integer64 type. Only works for primitive types. - */ - -int64 ejsVarToInteger64(EjsVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_STRING_CMETHOD: - case EJS_TYPE_CMETHOD: - case EJS_TYPE_METHOD: - case EJS_TYPE_OBJECT: - case EJS_TYPE_PTR: - return 0; - - case EJS_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - if (ejsIsNan(vp->floating)) { - return 0; - } - return (int64) vp->floating; -#endif - - case EJS_TYPE_INT: - return vp->integer; - - case EJS_TYPE_INT64: - return vp->integer64; - - case EJS_TYPE_STRING: - if (vp->length == 0) { - return 0; - } else { - return ejsParseInteger64(vp->string); - } - } - - /* Not reached */ - return 0; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -EjsNum ejsVarToNumber(EjsVar *vp) -{ -#if BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_INT64 - return ejsVarToInteger64(vp); -#elif BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_FLOAT - return ejsVarToFloat(vp); -#else - return ejsVarToInteger(vp); -#endif -} - -/******************************************************************************/ -/* - * Convert a var to a string. Store the result in ep->castTemp. If allocated - * set ep->castAlloc to TRUE. Caller must NOT free the result. - */ - -char *ejsVarToString(Ejs *ep, EjsVar *vp) -{ - MprBuf *bp; - char numBuf[16]; - int len, i; - - if (ep->castAlloc) { - mprFree(ep->castTemp); - } - ep->castTemp = 0; - ep->castAlloc = 0; - - switch (vp->type) { - case EJS_TYPE_UNDEFINED: - ep->castTemp = "undefined"; - break; - - case EJS_TYPE_NULL: - ep->castTemp = "null"; - break; - - case EJS_TYPE_PTR: - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &ep->castTemp, 0, - "[Opaque Pointer %p]", vp->ptr.userPtr); - ep->castAlloc = 1; - break; - - case EJS_TYPE_BOOL: - if (vp->boolean) { - ep->castTemp = "true"; - } else { - ep->castTemp = "false"; - } - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - len = mprAllocSprintf(MPR_LOC_ARGS(ep), &ep->castTemp, 0, - "%f", vp->floating); - ep->castAlloc = 1; - break; -#endif - - case EJS_TYPE_INT: - mprItoa(numBuf, sizeof(numBuf), vp->integer); - ep->castTemp = mprStrdup(ep, numBuf); - ep->castAlloc = 1; - break; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - mprAllocSprintf(MPR_LOC_ARGS(ep), &ep->castTemp, 0, - "%Ld", vp->integer64); - ep->castAlloc = 1; - break; -#endif - - case EJS_TYPE_CMETHOD: - ep->castTemp = "[C Method]"; - break; - - case EJS_TYPE_STRING_CMETHOD: - ep->castTemp = "[C StringMethod]"; - break; - - case EJS_TYPE_METHOD: - bp = mprCreateBuf(ep, 0, 0); - mprPutStringToBuf(bp, "function ("); - for (i = 0; i < vp->method.args->length; i++) { - mprPutStringToBuf(bp, vp->method.args->items[i]); - if ((i + 1) < vp->method.args->length) { - mprPutStringToBuf(bp, ", "); - } - } - mprPutStringToBuf(bp, ") {"); - mprPutStringToBuf(bp, vp->method.body); - mprPutStringToBuf(bp, "}"); - mprAddNullToBuf(bp); - ep->castTemp = mprStealBuf(ep, bp); - ep->castAlloc = 1; - mprFree(bp); - break; - - case EJS_TYPE_OBJECT: - if (ejsRunMethod(ep, vp, "toString", 0) < 0) { - return mprStrdup(ep, "[object Object]"); - } - ep->castTemp = mprStrdup(ep, ep->result->string); - ep->castAlloc = 1; - break; - - case EJS_TYPE_STRING: - if (vp->string == 0) { - ep->castTemp = "null"; - } else { - ep->castTemp = vp->string; - } - break; - - default: - mprAssert(0); - } - - mprAssert(ep->castTemp); - return ep->castTemp; -} - -/******************************************************************************/ - -char *ejsVarToStringEx(Ejs *ep, EjsVar *vp, bool *alloc) -{ - char *str; - - mprAssert(alloc); - - str = ejsVarToString(ep, vp); - *alloc = ep->castAlloc; - ep->castAlloc = 0; - ep->castTemp = 0; - return str; -} - -/******************************************************************************/ -/* - * Parse a string based on formatting instructions and intelligently - * create a variable. - * - * Float format: [+|-]DIGITS][DIGITS][(e|E)[+|-]DIGITS] - */ - -EjsVar *ejsParseVar(Ejs *ep, const char *buf, EjsType preferredType) -{ - EjsType type; - const char *cp; - int isHex; - - mprAssert(buf); - - type = preferredType; - - if (preferredType == EJS_TYPE_UNDEFINED) { - isHex = 0; - if (*buf == '-' || *buf == '+') { - type = EJS_NUM_VAR; - - } else if (!isdigit((int) *buf)) { - if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { - type = EJS_TYPE_BOOL; - } else { - type = EJS_TYPE_STRING; - } - - } else if (isdigit((int) *buf)) { - type = EJS_NUM_VAR; - cp = buf; - if (*cp && tolower(cp[1]) == 'x') { - cp = &cp[2]; - isHex = 1; - for (cp = buf; *cp; cp++) { - if (! isxdigit((int) *cp)) { - break; - } - } - } else { -#if BLD_FEATURE_FLOATING_POINT - /* Could be integer or float */ - for (cp = buf; *cp; cp++) { - if (! isdigit((int) *cp)) { - int c = tolower(*cp); - if (c == '.' || c == 'e' || c == 'f') { - type = EJS_TYPE_FLOAT; - break; - } - } - } -#endif - } - } - } - - switch (type) { - case EJS_TYPE_OBJECT: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - case EJS_TYPE_PTR: - default: - break; - - case EJS_TYPE_BOOL: - return ejsCreateBoolVar(ep, ejsParseBoolean(buf)); - - case EJS_TYPE_INT: - return ejsCreateIntegerVar(ep, ejsParseInteger(buf)); - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - return ejsCreateInteger64Var(ep, ejsParseInteger64(buf)); -#endif - - case EJS_TYPE_STRING: - if (strcmp(buf, "null") == 0) { - return ejsCreateNullVar(ep); - - } else if (strcmp(buf, "undefined") == 0) { - return ejsCreateUndefinedVar(ep); - } - - return ejsCreateStringVar(ep, buf); - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - return ejsCreateFloatVar(ep, atof(buf)); -#endif - - } - return ejsCreateUndefinedVar(ep); -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -bool ejsParseBoolean(const char *s) -{ - if (s == 0 || *s == '\0') { - return 0; - } - if (strcmp(s, "false") == 0 || strcmp(s, "FALSE") == 0) { - return 0; - } - return 1; -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -EjsNum ejsParseNumber(const char *s) -{ -#if BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_INT64 - return ejsParseInteger64(s); -#elif BLD_FEATURE_NUM_TYPE_ID == EJS_TYPE_FLOAT - return ejsParseFloat(s); -#else - return ejsParseInteger(s); -#endif -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the string buffer to an Integer64. - */ - -int64 ejsParseInteger64(const char *str) -{ - const char *cp; - int64 num64; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num64 = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } else if (*cp == '+') { - cp++; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num64 = (*cp - '0') + (num64 * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num64 = (c - '0') + (num64 * radix); - } else if (c >= 'a' && c <= 'f') { - num64 = (c - 'a' + 10) + (num64 * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num64 = (c - '0') + (num64 * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num64; - } - return num64; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the string buffer to an Integer. - */ - -int ejsParseInteger(const char *str) -{ - const char *cp; - int num; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } else if (*cp == '+') { - cp++; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num = (*cp - '0') + (num * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num = (c - '0') + (num * radix); - } else if (c >= 'a' && c <= 'f') { - num = (c - 'a' + 10) + (num * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num = (c - '0') + (num * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num; - } - return num; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the string buffer to an Floating. - */ - -double ejsParseFloat(const char *str) -{ - return atof(str); -} - -/******************************************************************************/ - -int ejsIsNan(double f) -{ -#if WIN - return _isnan(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_NAN); -#endif -} -/******************************************************************************/ - -int ejsIsInfinite(double f) -{ -#if WIN - return !_finite(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#else - return (f == FP_INFINITE); -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ - -/******************************************************************************/ -/* - * Single point of control for all assignment to properties. - * - * Copy an objects core value (only). This preserves the destination object's - * name. This implements copy by reference for objects and copy by value for - * strings and other types. Caller must free dest prior to calling. - */ - -static EjsVar *copyVar(EJS_LOC_DEC(ep, loc), EjsVar *dest, const EjsVar *src, - EjsCopyDepth copyDepth) -{ - Ejs *ejsContext; - EjsObj *srcObj; - EjsProperty *destp; - const char **srcArgs; - char *str; - int i; - - mprAssert(dest); - mprAssert(src); - - if (dest == src) { - return dest; - } - - if (dest->type != EJS_TYPE_UNDEFINED) { - ejsClearVar(ep, dest); - } - - dest->allocatedData = 0; - - switch (src->type) { - default: - case EJS_TYPE_UNDEFINED: - case EJS_TYPE_NULL: - break; - - case EJS_TYPE_BOOL: - dest->boolean = src->boolean; - break; - - case EJS_TYPE_PTR: - dest->ptr = src->ptr; - if (dest->ptr.destructor) { - dest->allocatedData = 1; - } - break; - - case EJS_TYPE_STRING_CMETHOD: - dest->cMethodWithStrings = src->cMethodWithStrings; - break; - - case EJS_TYPE_CMETHOD: - dest->cMethod = src->cMethod; - break; - -#if BLD_FEATURE_FLOATING_POINT - case EJS_TYPE_FLOAT: - dest->floating = src->floating; - break; -#endif - - case EJS_TYPE_INT: - dest->integer = src->integer; - break; - -#if BLD_FEATURE_INT64 - case EJS_TYPE_INT64: - dest->integer64 = src->integer64; - break; -#endif - - case EJS_TYPE_OBJECT: - if (copyDepth == EJS_SHALLOW_COPY) { - - /* - * If doing a shallow copy and the src object is from the same - * interpreter, or we are copying from the master interpreter, or - * we are using a shared slab, then we can do a shallow copy. - * Otherwise, we must do a deep copy. - */ - srcObj = src->objectState; - if (srcObj->ejs == ep || srcObj->ejs == ep->service->master || - (ep->flags & EJS_FLAGS_SHARED_SLAB)) { - dest->objectState = src->objectState; - dest->allocatedData = 1; - break; - } - } - - /* - * Doing a deep or recursive deep. Can get here if doing a shallow - * copy and the object is from another non-master interpeter and not - * using a shared slab. - * - * We must make sure the data is allocated using the right memory - * context. It must be the same as the destination parent object. - * Otherwise, when we free the property memory, the parent may - * have a dangling pointer. - */ - if (dest->isProperty) { - destp = ejsGetPropertyPtr(dest); - if (destp->parentObj == 0) { - ejsContext = ep; - - } else { - mprAssert(destp->parentObj); - ejsContext = destp->parentObj->ejs; - mprAssert(ejsContext); - } - - } else { - ejsContext = ep; - } - - dest->objectState = createObj(EJS_LOC_PASS(ejsContext, loc)); - if (dest->objectState == 0) { - /* Memory Error */ - return 0; - } - - dest->objectState->baseClass = src->objectState->baseClass; - dest->objectState->methods = src->objectState->methods; - dest->objectState->noConstructor = src->objectState->noConstructor; - dest->objectState->objName = - mprStrdup(ejsContext, src->objectState->objName); - - if (dest->objectState->objName == 0) { - return 0; - } - - if (ejsCopyProperties(ep, dest, src, copyDepth) == 0) { - return 0; - } - dest->allocatedData = 1; - break; - - case EJS_TYPE_METHOD: - dest->method.args = mprCreateItemArray(ep, EJS_INC_ARGS, - EJS_MAX_ARGS); - if (dest->method.args == 0) { - return 0; - } - dest->allocatedData = 1; - if (src->method.args) { - srcArgs = (const char**) src->method.args->items; - for (i = 0; i < src->method.args->length; i++) { - str = mprStrdupInternal(EJS_LOC_PASS(dest->method.args, - loc), srcArgs[i]); - if (str == 0) { - mprFree(dest->method.args); - dest->method.args = 0; - return 0; - } - if (mprAddItem(dest->method.args, str) < 0) { - mprFree(dest->method.args); - dest->method.args = 0; - return 0; - } - } - } - dest->method.body = mprStrdup(dest->method.args, src->method.body); - if (dest->method.body == 0) { - mprFree(dest->method.args); - dest->method.args = 0; - return 0; - } - dest->callsSuper = src->callsSuper; - break; - - case EJS_TYPE_STRING: - dest->length = src->length; - if (src->string) { - /* Shallow, deep or recursive deep */ - dest->length = dupString(MPR_LOC_PASS(ep, loc), &dest->ustring, - src->ustring, src->length); - if (dest->length < 0) { - return 0; - } - dest->allocatedData = 1; - - } else { - dest->string = src->string; - dest->allocatedData = 0; - } - break; - } - - dest->type = src->type; - dest->flags = src->flags; - dest->isArray = src->isArray; - - return dest; -} - -/******************************************************************************/ -/* - * Copy all properies in an object. Must preserve property order - */ - -EjsVar *ejsCopyProperties(Ejs *ep, EjsVar *dest, const EjsVar *src, - EjsCopyDepth copyDepth) -{ - EjsProperty *srcProp, *destProp, *last, *next; - int propertyIndex; - - srcProp = ejsGetFirstProperty(src, EJS_ENUM_ALL); - while (srcProp) { - next = ejsGetNextProperty(srcProp, EJS_ENUM_ALL); - if (srcProp->visited) { - srcProp = next; - continue; - } - - /* - * This finds the last variable in the hash chain - * FUTURE OPT. This is slow. If used double link, we could locate the - * tail more easily. - */ - destProp = hashLookup(dest->objectState, srcProp->name, - &propertyIndex, &last); - mprAssert(destProp == 0); - - destProp = allocProperty(ep, dest, srcProp->name, propertyIndex, last); - if (destProp == 0) { - mprAssert(destProp); - return 0; - } - - /* - * Recursively copy the object. If DEEP_COPY, then we - * will do a shallow copy of the object contents. If - * RECURSIVE_DEEP, then we do a deep copy at all levels. - */ - srcProp->visited = 1; - - if (copyVar(EJS_LOC_ARGS(ep), ejsGetVarPtr(destProp), - ejsGetVarPtr(srcProp), - (copyDepth == EJS_DEEP_COPY) ? EJS_SHALLOW_COPY : copyDepth) - == 0) { - return 0; - } - srcProp->visited = 0; - - srcProp = next; - } - return dest; -} - -/******************************************************************************/ -/********************************** Properties ********************************/ -/******************************************************************************/ -/* - * Create a property in an object and return a pointer to it. If the property - * already exists then just return a pointer to it (no error). - * To test for existance of a property, use GetProperty - */ - -static EjsProperty *hashLookup(EjsObj *obj, const char *property, - int *propertyIndex, EjsProperty **hashTail) -{ - EjsProperty *prop, *last; - int index; - - mprAssert(obj); - mprAssert(property); - - if (obj == 0 || property == 0 || *property == '\0') { - mprAssert(0); - return 0; - } - - /* - * Find the property in the hash chain if it exists - */ - index = hash(property); - prop = obj->propertyHash[index]; - for (last = 0; prop != 0; last = prop, prop = prop->hashNext) { - if (prop->name[0] == property[0] && - strcmp(prop->name, property) == 0) { - break; - } - } - if (propertyIndex) { - *propertyIndex = index; - } - if (hashTail) { - *hashTail = last; - } - - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object and return a pointer to it. If the property - * already exists then just return a pointer to it (no error). If the property - * does not exist, create an undefined variable. To test for existance of a - * property, use GetProperty. - */ - -EjsProperty *ejsCreateSimpleProperty(Ejs *ep, EjsVar *op, const char *property) -{ - EjsProperty *prop, *last; - int propertyIndex; - - if (op == 0 || op->type != EJS_TYPE_OBJECT || property == 0 || - *property == '\0') { - mprAssert(0); - return 0; - } - - /* - * Find the property in the hash chain if it exists - */ - prop = hashLookup(op->objectState, property, &propertyIndex, &last); - - if (prop == 0) { - /* - * Create a new property - */ - prop = allocProperty(ep, op, property, propertyIndex, last); - if (prop == 0) { - mprAssert(prop == 0); - return 0; - } - } - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object and return a pointer to it. If the property - * already exists then just return a pointer to it (no error). - * To test for existance of a property, use GetProperty - */ - -EjsProperty *ejsCreateSimpleNonUniqueProperty(Ejs *ep, EjsVar *op, - const char *property) -{ - EjsProperty *prop, *last; - int propertyIndex; - - if (op == 0 || op->type != EJS_TYPE_OBJECT || property == 0 || - *property == '\0') { - mprAssert(0); - return 0; - } - - /* - * Find end of chain - */ - propertyIndex = hash(property); - prop = op->objectState->propertyHash[propertyIndex]; - for (last = 0; prop != 0; last = prop, prop = prop->hashNext) { - ; - } - - return allocProperty(ep, op, property, propertyIndex, last); -} - -/******************************************************************************/ -/* - * Find a property in an object and return a pointer to it. - * This does NOT traverse base classes. - */ - -EjsProperty *ejsGetSimpleProperty(Ejs *ep, EjsVar *op, const char *property) -{ - mprAssert(op); - mprAssert(op->type == EJS_TYPE_OBJECT); - mprAssert(property && *property); - - /* - * This is an internal API. It has very little checking. - */ - return hashLookup(op->objectState, property, 0, 0); -} - -/******************************************************************************/ - -/* - * NOTE: There is no ejsSetSimpleProperty as all the ejsSetProperty routines - * operate only on the instance and don't follow base classes. ie. there is - * no simple version required. However, there is a ejsSetBaseProperty routine - * that will follow base classes and is used to set static properties in base - * classes - */ - -/******************************************************************************/ -/******************************* Property Access ******************************/ -/******************************************************************************/ -/* - * The property get routines follow base classes and utilize the propery - * method access routines. The property set routines do not follow base - * classes. The property ejsSetBase... routines do follow base classes. - */ - -/* - * Find a property in an object and return a pointer to it. - * This follows base classes. - */ - -EjsProperty *ejsGetProperty(Ejs *ep, EjsVar *op, const char *property) -{ - EjsVar *vp, *newOp; - int maxBaseClasses = 50; - - do { - if (op->type != EJS_TYPE_OBJECT) { - mprAssert(op->type == EJS_TYPE_OBJECT); - return 0; - } - mprAssert(op->objectState); - - vp = ejsGetPropertyMethod(ep, op, property); - if (vp != 0) { - /* - * Found - */ - break; - } - - newOp = op->objectState->baseClass; - if (newOp == 0) { - if (op->objectState != ep->objectClass->objectState) { - newOp = ep->objectClass; - } - } - op = newOp; - - /* - * A little bit of sanity checking - */ - if (--maxBaseClasses <= 0) { - mprAssert(maxBaseClasses > 0); - break; - } - - } while (op); - - return ejsGetPropertyPtr(vp); -} - -/******************************************************************************/ -/* - * Get the property's variable. Optionally create if it does not exist. - */ - -EjsVar *ejsGetPropertyAsVar(Ejs *ep, EjsVar *vp, const char *property) -{ - return ejsGetVarPtr(ejsGetProperty(ep, vp, property)); -} - -/******************************************************************************/ -/* - * Get the property's value as a binary string. - */ - -const uchar *ejsGetPropertyAsBinaryString(Ejs *ep, EjsVar *obj, - const char *property, int *length) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - - if (vp->type == EJS_TYPE_STRING) { - if (length) { - *length = vp->length; - } - return vp->ustring; - } - return 0; -} - -/******************************************************************************/ -/* - * Get the property's value as a string. - */ - -const char *ejsGetPropertyAsString(Ejs *ep, EjsVar *obj, const char *property) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - - if (vp->type == EJS_TYPE_STRING) { - return vp->string; - } - return 0; -} - -/******************************************************************************/ -/* - * Get the property's value as a number. - */ - -BLD_FEATURE_NUM_TYPE ejsGetPropertyAsNumber(Ejs *ep, EjsVar *obj, - const char *property) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - - return ejsVarToNumber(vp); -} - -/******************************************************************************/ -/* - * Get the property's value as a integer. - */ - -int ejsGetPropertyAsInteger(Ejs *ep, EjsVar *obj, const char *property) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - - return ejsVarToInteger(vp); -} - -/******************************************************************************/ -/* - * Get the property's value as a boolean. - */ - -bool ejsGetPropertyAsBoolean(Ejs *ep, EjsVar *obj, const char *property) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - - return ejsVarToBoolean(vp); -} - -/******************************************************************************/ -/* - * Get the property's value as a pointer. - */ - -void *ejsGetPropertyAsPtr(Ejs *ep, EjsVar *obj, const char *property) -{ - EjsVar *vp; - - vp = ejsGetVarPtr(ejsGetProperty(ep, obj, property)); - if (vp == 0 || ejsVarIsUndefined(vp)) { - return 0; - } - if (vp->type == EJS_TYPE_PTR) { - return vp->ptr.userPtr; - } - return 0; -} - -/******************************************************************************/ -/* - * Create a property in the object. This will override any base class - * properties. - * - * MOB -- need to spell out the difference between ejsSetProperty and - * ejsCreateProperty. - */ - -EjsProperty *ejsCreateProperty(Ejs *ep, EjsVar *obj, const char *property) -{ - EjsVar *vp; - - vp = ejsCreatePropertyMethod(ep, obj, property); - return ejsGetPropertyPtr(vp); -} - -/******************************************************************************/ -/* - * Set a property's variable value. Create the property if it does not exist. - * This routine DOES follow base classes. - */ - -EjsProperty *ejsSetBaseProperty(Ejs *ep, EjsVar *op, const char *property, - const EjsVar *value) -{ - EjsVar *vp, *newOp; - int maxBaseClasses = 50; - - do { - if (op->type != EJS_TYPE_OBJECT) { - mprAssert(op->type == EJS_TYPE_OBJECT); - return 0; - } - mprAssert(op->objectState); - - vp = ejsGetPropertyMethod(ep, op, property); - if (vp != 0) { - /* - * Found - */ - vp = ejsSetPropertyMethod(ep, op, property, value); - break; - } - - newOp = op->objectState->baseClass; - if (newOp == 0) { - if (op->objectState != ep->objectClass->objectState) { - newOp = ep->objectClass; - } - } - op = newOp; - - /* - * A little bit of sanity checking - */ - if (--maxBaseClasses <= 0) { - mprAssert(maxBaseClasses > 0); - break; - } - - } while (op); - - return ejsGetPropertyPtr(vp); -} - -/******************************************************************************/ -/* - * Set a property's variable value. Create the property if it does not exist. - * This does NOT follow base classes. Okay when updating instance properties, - * but not for class (static) properties. This does a shallow copy which - * will copy references. - */ - -EjsProperty *ejsSetProperty(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value) -{ - EjsVar *vp; - - vp = ejsSetPropertyMethod(ep, obj, property, value); - - return ejsGetPropertyPtr(vp); -} - -/******************************************************************************/ -/* - * Set a property's variable value by assigning the given value. The caller - * must NOT free value as it is assigned directly into the property's value. - */ - -EjsProperty *ejsSetPropertyAndFree(Ejs *ep, EjsVar *obj, - const char *property, EjsVar *value) -{ - EjsVar *vp; - - vp = ejsSetPropertyMethod(ep, obj, property, value); - - ejsFree(ep, value, EJS_SLAB_VAR); - - return ejsGetPropertyPtr(vp); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToCMethod(Ejs *ep, EjsVar *vp, const char *prop, - EjsCMethod fn, void *userData, int flags) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_CMETHOD); - v.cMethod.fn = fn; - v.cMethod.userData = userData; - v.flags = flags; - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToBoolean(Ejs *ep, EjsVar *vp, const char *prop, - int value) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_BOOL); - v.boolean = value; - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT - -EjsProperty *ejsSetPropertyToFloat(Ejs *ep, EjsVar *vp, const char *prop, - double value) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_FLOAT); - v.floating = value; - - return ejsSetProperty(ep, vp, prop, &v); -} - -#endif -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToInteger(Ejs *ep, EjsVar *vp, const char *prop, - int value) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_INT); - v.integer = value; - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 - -EjsProperty *ejsSetPropertyToInteger64(Ejs *ep, EjsVar *vp, const char *prop, - int64 value) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_INT64); - v.integer64 = value; - - return ejsSetProperty(ep, vp, prop, &v); -} - -#endif -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToNull(Ejs *ep, EjsVar *vp, const char *prop) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_NULL); - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToMethod(Ejs *ep, EjsVar *vp, const char *prop, - const char *body, MprArray *args, int flags) -{ - return ejsSetPropertyAndFree(ep, vp, prop, - ejsCreateMethodVar(ep, body, args, flags)); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToNumber(Ejs *ep, EjsVar *vp, const char *prop, - EjsNum value) -{ - return ejsSetPropertyAndFree(ep, vp, prop, ejsCreateNumberVar(ep, value)); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToStringCMethod(Ejs *ep, EjsVar *vp, - const char *prop, EjsStringCMethod fn, void *userData, int flags) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_STRING_CMETHOD); - v.cMethodWithStrings.fn = fn; - v.cMethodWithStrings.userData = userData; - v.flags = flags; - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToString(Ejs *ep, EjsVar *vp, const char *prop, - const char *value) -{ - EjsProperty *pp; - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_STRING); - - /* FUTURE OPT */ - v.string = mprStrdupInternal(EJS_LOC_ARGS(ep), value); - if (v.string == 0) { - return 0; - } - v.length = strlen(v.string); - v.allocatedData = 1; - - pp = ejsSetProperty(ep, vp, prop, &v); - - mprFree(v.string); - - return pp; -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToBinaryString(Ejs *ep, EjsVar *vp, - const char *prop, const uchar *value, int len) -{ - EjsProperty *pp; - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_STRING); - - /* FUTURE OPT */ - v.length = dupString(MPR_LOC_ARGS(ep), &v.ustring, value, len); - if (v.length < 0) { - return 0; - } - v.allocatedData = 1; - - pp = ejsSetProperty(ep, vp, prop, &v); - - mprFree(v.ustring); - - return pp; -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToUndefined(Ejs *ep, EjsVar *vp, const char *prop) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_UNDEFINED); - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToPtr(Ejs *ep, EjsVar *vp, const char *prop, - void *ptr, EjsDestructor destructor) -{ - EjsVar v; - - ejsInitVar(&v, EJS_TYPE_PTR); - v.ptr.userPtr = ptr; - v.ptr.destructor = destructor; - v.allocatedData = 1; - - return ejsSetProperty(ep, vp, prop, &v); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToNewObj(Ejs *ep, EjsVar *vp, const char *prop, - const char *className, MprArray *args) -{ - return ejsSetPropertyAndFree(ep, vp, prop, - ejsCreateObjUsingArgv(ep, 0, className, args)); -} - -/******************************************************************************/ - -EjsProperty *ejsSetPropertyToObj(Ejs *ep, EjsVar *op, const char *prop) -{ - return ejsSetPropertyAndFree(ep, op, prop, ejsCreateObjVar(ep)); -} - -/******************************************************************************/ -/* - * Convenience routines - */ - -EjsVar *ejsSetPropertyToObjAsVar(Ejs *ep, EjsVar *op, const char *prop) -{ - return ejsGetVarPtr(ejsSetPropertyToObj(ep, op, prop)); -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* - * Create a script method - */ - -EjsProperty *ejsDefineMethod(Ejs *ep, EjsVar *vp, const char *prop, - const char *body, MprArray *args) -{ - if (vp == 0) { - vp = ejsGetGlobalObj(ep); - } - return ejsSetPropertyToMethod(ep, vp, prop, body, args, 0); -} - -/******************************************************************************/ -/* - * Create a C language method - */ - -EjsProperty *ejsDefineCMethod(Ejs *ep, EjsVar *vp, const char *prop, - EjsCMethod fn, int flags) -{ - if (vp == 0) { - vp = ejsGetGlobalObj(ep); - } - return ejsSetPropertyToCMethod(ep, vp, prop, fn, 0, flags); -} - -/******************************************************************************/ -/* - * Define accessors - */ - -EjsProperty *ejsDefineAccessors(Ejs *ep, EjsVar *vp, const char *prop, - const char *getBody, const char *setBody) -{ - EjsProperty *pp; - MprArray *args; - char *propName; - - if (vp == 0) { - vp = ejsGetGlobalObj(ep); - } - - if (ejsSetPropertyToMethod(ep, vp, prop, getBody, 0, EJS_GET_ACCESSOR) < 0){ - ejsMemoryError(ep); - return 0; - } - - /* MOB -- OPT to use SLAB */ - /* MOB -- need to encapsulate this logic */ - - if (mprAllocStrcat(MPR_LOC_ARGS(ep), &propName, EJS_MAX_ID+5, 0, - "-set-", prop, NULL) < 0) { - ejsMemoryError(ep); - return 0; - } - - args = mprCreateItemArray(ep, EJS_INC_ARGS, EJS_MAX_ARGS); - mprAddItem(args, mprStrdup(args, "value")); - - pp = ejsSetPropertyToMethod(ep, vp, propName, setBody, args, - EJS_SET_ACCESSOR); - mprFree(propName); - - if (pp == 0) { - ejsMemoryError(ep); - return 0; - } - - return pp; -} - -/******************************************************************************/ -/* - * Define C accessors - */ - -EjsProperty *ejsDefineCAccessors(Ejs *ep, EjsVar *vp, const char *prop, - EjsCMethod getFn, EjsCMethod setFn, int flags) -{ - EjsProperty *pp; - char *propName; - - if (vp == 0) { - vp = ejsGetGlobalObj(ep); - } - pp = ejsSetPropertyToCMethod(ep, vp, prop, getFn, 0, - flags | EJS_GET_ACCESSOR); - if (pp == 0) { - ejsMemoryError(ep); - return 0; - } - - /* MOB -- OPT to use SLAB */ - if (mprAllocStrcat(MPR_LOC_ARGS(ep), &propName, EJS_MAX_ID + 5, 0, - "-set-", prop, NULL) < 0) { - ejsMemoryError(ep); - return 0; - } - pp = ejsSetPropertyToCMethod(ep, vp, propName, setFn, 0, - flags | EJS_SET_ACCESSOR); - mprFree(propName); - - if (pp == 0) { - ejsMemoryError(ep); - return 0; - } - return pp; -} - -/******************************************************************************/ -/* - * Create a C language method with string arguments - */ - -EjsProperty *ejsDefineStringCMethod(Ejs *ep, EjsVar *vp, const char *prop, - EjsStringCMethod fn, int flags) -{ - if (vp == 0) { - vp = ejsGetGlobalObj(ep); - } - return ejsSetPropertyToStringCMethod(ep, vp, prop, fn, 0, flags); -} - -/******************************************************************************/ - -void ejsSetCMethodUserData(EjsVar *obj, void *userData) -{ - /* - * This is a little dirty. We rely on the userData being in the same - * place in the var structure. - */ - obj->cMethod.userData = userData; -} - -/******************************************************************************/ - -void ejsSetVarFlags(EjsVar *obj, int flags) -{ - obj->flags = flags; -} - -/******************************************************************************/ - -void *ejsGetCMethodUserData(EjsVar *obj) -{ - return obj->cMethod.userData; -} - -/******************************************************************************/ - -int ejsGetVarFlags(EjsVar *obj) -{ - return obj->flags; -} - -/******************************************************************************/ - -void ejsSetObjDestructor(Ejs *ep, EjsVar *obj, EjsDestructor destructor) -{ - obj->objectState->destructor = destructor; -} - -/******************************************************************************/ - -void ejsClearObjDestructor(Ejs *ep, EjsVar *obj) -{ - obj->objectState->destructor = 0; -} - -/******************************************************************************/ -/* - * Create a new property - */ - -static EjsProperty *allocProperty(Ejs *ep, EjsVar *op, const char *property, - int propertyIndex, EjsProperty *last) -{ - EjsProperty *prop; - EjsObj *obj; - - obj = op->objectState; - - /* - * Allocate the property using the memory context of the owning object - */ - prop = ejsAllocProperty(EJS_LOC_ARGS(obj->ejs)); - if (prop == 0) { - return 0; - } - if (mprStrcpy(prop->name, sizeof(prop->name), property) < 0) { - ejsError(ep, EJS_REFERENCE_ERROR, - "Property name %s is too long. Max is %d letters.", - prop->name, EJS_MAX_ID); - return 0; - } - - ejsSetVarName(ep, ejsGetVarPtr(prop), &prop->name[0]); - - /* - * Do hash linkage - */ - if (last) { - last->hashNext = prop; - } else { - obj->propertyHash[propertyIndex] = prop; - } - -#if BLD_DEBUG - prop->link.propertyName = prop->name; - prop->link.property = prop; - prop->link.head = &obj->link; -#endif - - /* - * Inserting before the dummy head will append to the end - */ - linkPropertyBefore(obj, &obj->link, &prop->link); - - obj->numProperties++; - prop->parentObj = obj; - mprAssert(obj->ejs); - - return prop; -} - -/******************************************************************************/ -/* - * Delete a property from this object - */ - -int ejsDeleteProperty(Ejs *ep, EjsVar *vp, const char *property) -{ - EjsProperty *prop, *last; - EjsObj *obj; - int propertyIndex; - - mprAssert(vp); - mprAssert(property && *property); - mprAssert(vp->type == EJS_TYPE_OBJECT); - - if (vp->type != EJS_TYPE_OBJECT) { - mprAssert(vp->type == EJS_TYPE_OBJECT); - return MPR_ERR_BAD_ARGS; - } - - prop = hashLookup(vp->objectState, property, &propertyIndex, &last); - if (prop == (EjsProperty*) 0) { - return MPR_ERR_NOT_FOUND; - } - obj = vp->objectState; - -#if FUTURE - if (prop->readonly) { - mprAssert(! prop->readonly); - return MPR_ERR_READ_ONLY; - } -#endif - - /* - * If doing enumerations, then the object will mark preventDelete to - * prevent any properties being deleted and thus disturbing the - * traversal. - */ - if (obj->preventDeleteProp) { - obj->delayedDeleteProp = 1; - prop->delayedDelete = 1; - return 0; - } - - /* - * Remove from hash - */ - if (last) { - last->hashNext = prop->hashNext; - } else { - obj->propertyHash[propertyIndex] = prop->hashNext; - } - - unlinkProperty(obj, &prop->link); - obj->numProperties--; - - /* - * Free any property data and return to the slab - */ - if (prop->var.type != EJS_TYPE_OBJECT) { - ejsClearVar(ep, ejsGetVarPtr(prop)); - } - ejsFree(ep, prop, EJS_SLAB_PROPERTY); - - return 0; -} - -/******************************************************************************/ -/* - * Remove a property's value from this object. The property is set to - * undefined. - */ - -EjsVar *ejsClearProperty(Ejs *ep, EjsVar *vp, const char *property) -{ - EjsProperty *prop; - - mprAssert(vp); - mprAssert(property && *property); - mprAssert(vp->type == EJS_TYPE_OBJECT); - - if (vp->type != EJS_TYPE_OBJECT) { - mprAssert(vp->type == EJS_TYPE_OBJECT); - return 0; - } - - prop = hashLookup(vp->objectState, property, 0, 0); - if (prop == (EjsProperty*) 0) { - return 0; - } -#if FUTURE - if (prop->readonly) { - mprAssert(! prop->readonly); - return 0; - } -#endif - - ejsClearVar(ep, &prop->var); - return &prop->var; -} - -/******************************************************************************/ -/* - * Unlink a property from the ordered list of properties - */ - -static void unlinkProperty(EjsObj *obj, EjsPropLink *propLink) -{ - propLink->prev->next = propLink->next; - propLink->next->prev = propLink->prev; -} - -/******************************************************************************/ -#if UNUSED && KEEP -/* - * Insert a link after a specified link. - */ - -static void linkPropertyAfter(EjsObj *obj, EjsPropLink *at, - EjsPropLink *propLink) -{ - propLink->next = at->next; - propLink->prev = at; - - at->next->prev = propLink; - at->next = propLink; -} - -#endif -/******************************************************************************/ -/* - * Insert a link before a specified link. - */ - -static void linkPropertyBefore(EjsObj *obj, EjsPropLink *at, - EjsPropLink *propLink) -{ - propLink->prev = at->prev; - propLink->next = at; - - at->prev->next = propLink; - at->prev = propLink; -} - -/******************************************************************************/ -/* - * This routine will sort properties in an object. If propertyName is not - * null, then the properties in op must be objects with a property of the - * name propertyName. If propertyName is null, then the properties of op - * are directly sorted. If order is 1, they are sorted in ascending order. - * If -1, they are sorted in descending order. - * - * NOTE: arrays keep their original index values. - */ - -void ejsSortProperties(Ejs *ep, EjsVar *op, EjsSortFn fn, - const char *propertyName, int order) -{ - EjsProperty *p1, *p2, *tmp; - EjsPropLink *l1, *l2, *oldL1Spot; - EjsObj *obj; - - obj = op->objectState; - - p1 = ejsGetFirstProperty(op, 0); - while (p1) { - if (p1->dontEnumerate) { - p1 = ejsGetNextProperty(p1, 0); - continue; - } - - p2 = ejsGetFirstProperty(op, 0); - while (p2 && p2 != p1) { - - if (p2->dontEnumerate) { - p2 = ejsGetNextProperty(p2, 0); - continue; - } - - if (fn == 0) { - if (propertyName) { - fn = sortByProperty; - } else { - fn = sortAllProperties; - } - } - - if (fn(ep, p1, p2, propertyName, order) < 0) { - - l1 = &p1->link; - l2 = &p2->link; - - /* - * Swap the properties without disturbing the hash chains. - * l1 is always after l2 in the list. Unlink l1 and remember - * the one after l1. - */ - oldL1Spot = l1->next; - unlinkProperty(obj, l1); - - /* - * Manually reinsert l1 by replacing l2 with l1. l2 is out of - * the chain. - */ - l2->prev->next = l1; - l2->next->prev = l1; - l1->prev = l2->prev; - l1->next = l2->next; - - /* - * Reinsert l2 before the spot where l1 was. - */ - linkPropertyBefore(obj, oldL1Spot, l2); - - /* - * Swap the pointers so we continue to traverse correctly - */ - tmp = p1; - p1 = p2; - p2 = tmp; - } - p2 = ejsGetNextProperty(p2, 0); - } - p1 = ejsGetNextProperty(p1, 0); - } -} - -/******************************************************************************/ -/* - * Sort properties. Strings are sorted in ascending ASCII collating sequence - * Numbers are sorted in increasing numerical order. - */ -static int sortAllProperties(Ejs *ep, EjsProperty *p1, EjsProperty *p2, - const char *propertyName, int order) -{ - EjsVar *v1, *v2; - char *buf1, *buf2; - int rc, buf1Alloc; - - v1 = ejsGetVarPtr(p1); - v2 = ejsGetVarPtr(p2); - - if (v1->type == v2->type) { - /* MOB -- should support Numbers */ - if (v1->type == EJS_TYPE_INT) { - if (v1->integer < v2->integer) { - return - order; - - } else if (v1->integer == v2->integer) { - return 0; - } - return order; - -#if BLD_FEATURE_FLOATING_POINT - } else if (v1->type == EJS_TYPE_FLOAT) { - if (v1->floating < v2->floating) { - return - order; - - } else if (v1->floating == v2->floating) { - return 0; - } - return order; - -#endif - } else if (v1->type == EJS_TYPE_STRING) { - /* MOB -- need binary support ? */ - return strcmp(v1->string, v2->string) * order; - - } else { - - buf1 = ejsVarToStringEx(ep, v1, &buf1Alloc); - buf2 = ejsVarToString(ep, v2); - - rc = strcmp(buf1, buf2); - - if (buf1Alloc) { - mprFree(buf1); - } - - return rc * order; - } - - } else { - /* Type mismatch in array */ - return 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Sort an object by a given property. - */ -static int sortByProperty(Ejs *ep, EjsProperty *p1, EjsProperty *p2, - const char *propertyName, int order) -{ - EjsVar *o1, *o2, *v1, *v2; - char *buf1, *buf2; - int rc, buf1Alloc; - - o1 = ejsGetVarPtr(p1); - o2 = ejsGetVarPtr(p2); - - if (!ejsVarIsObject(o1) || !ejsVarIsObject(o2)) { - mprAssert(ejsVarIsObject(o1)); - mprAssert(ejsVarIsObject(o2)); - return 0; - } - - v1 = ejsGetPropertyAsVar(ep, o1, propertyName); - v2 = ejsGetPropertyAsVar(ep, o2, propertyName); - - if (v1 == 0 || v2 == 0) { - /* Property name not found */ - return 0; - } - - if (v1->type != v2->type) { - mprAssert(v1->type == v2->type); - return 0; - } - - if (v1->type == v2->type) { - /* MOB -- should support Numbers */ - if (v1->type == EJS_TYPE_INT) { - if (v1->integer < v2->integer) { - return -order; - - } else if (v1->integer == v2->integer) { - return 0; - } - return order; - -#if BLD_FEATURE_FLOATING_POINT - } else if (v1->type == EJS_TYPE_FLOAT) { - if (v1->floating < v2->floating) { - return -order; - - } else if (v1->floating == v2->floating) { - return 0; - } - return order; - -#endif - } else if (v1->type == EJS_TYPE_STRING) { - /* MOB -- need binary support ? */ - return strcmp(v1->string, v2->string) * order; - - } else { - buf1 = ejsVarToStringEx(ep, v1, &buf1Alloc); - - buf2 = ejsVarToString(ep, v2); - - rc = strcmp(buf1, buf2); - - if (buf1Alloc) { - mprFree(buf1); - } - - return rc * order; - } - - } else { - /* Type mismatch in array */ - return 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Set a property's name - */ - -void ejsSetPropertyName(EjsProperty *pp, const char *property) -{ - mprStrcpy(pp->name, sizeof(pp->name), property); -} - -/******************************************************************************/ - -int ejsMakePropertyEnumerable(EjsProperty *prop, int enumerate) -{ - int oldValue; - - oldValue = prop->dontEnumerate; - prop->dontEnumerate = !enumerate; - return oldValue; -} - -/******************************************************************************/ - -void ejsMakePropertyPrivate(EjsProperty *prop, int isPrivate) -{ - prop->isPrivate = isPrivate; -} - -/******************************************************************************/ -/* - * Make a variable read only. Can still be deleted. - */ - -void ejsMakePropertyReadOnly(EjsProperty *prop, int readonly) -{ - prop->readonly = readonly; -} - -/******************************************************************************/ - -int ejsMakeObjPermanent(EjsVar *vp, int permanent) -{ - int oldValue; - - if (vp && vp->type == EJS_TYPE_OBJECT) { - oldValue = vp->objectState->permanent; - vp->objectState->permanent = permanent; - } else { - oldValue = 0; - } - return oldValue; -} - -/******************************************************************************/ - -int ejsMakeObjLive(EjsVar *vp, bool alive) -{ - int oldValue; - - oldValue = 0; - if (vp && vp->type == EJS_TYPE_OBJECT) { - oldValue = vp->objectState->alive; - vp->objectState->alive = alive; - } else { - oldValue = 0; - } - return oldValue; -} - -/******************************************************************************/ - -void ejsMakeClassNoConstructor(EjsVar *vp) -{ - mprAssert(vp->type == EJS_TYPE_OBJECT); - - if (vp->type == EJS_TYPE_OBJECT) { - vp->objectState->noConstructor = 1; - } -} - -/******************************************************************************/ -/* - * Get the count of properties. - */ - -int ejsGetPropertyCount(EjsVar *vp) -{ - EjsProperty *pp; - EjsPropLink *lp, *head; - int count; - - mprAssert(vp); - - if (vp->type != EJS_TYPE_OBJECT) { - return 0; - } - - count = 0; - - head = &vp->objectState->link; - for (lp = head->next; lp != head; lp = lp->next) { - pp = ejsGetPropertyFromLink(lp); - if (! pp->dontEnumerate) { - count++; - } - } - return count; -} - -/******************************************************************************/ -/* - * Get the first property in an object. Used for walking all properties in an - * object. This will only enumerate properties in this class and not in base - * classes. - */ - -EjsProperty *ejsGetFirstProperty(const EjsVar *op, int flags) -{ - EjsProperty *pp; - EjsObj *obj; - EjsPropLink *head, *lp; - - mprAssert(op); - mprAssert(op->type == EJS_TYPE_OBJECT); - - if (op->type != EJS_TYPE_OBJECT) { - mprAssert(op->type == EJS_TYPE_OBJECT); - return 0; - } - pp = 0; - - do { - obj = op->objectState; - - head = &obj->link; - lp = head->next; - - while (lp != head) { - pp = ejsGetPropertyFromLink(lp); - if (! pp->dontEnumerate || (flags & EJS_ENUM_HIDDEN)) { - break; - } - lp = lp->next; - } - if (lp != head || op->type != EJS_TYPE_OBJECT || - !(flags & EJS_ENUM_CLASSES)) { - break; - } - - op = obj->baseClass; - - } while (lp == 0 && op); - - return pp; -} - -/******************************************************************************/ -/* - * Get the next property in sequence. This will only enumerate properties in - * this class and not in base classes. - */ - -EjsProperty *ejsGetNextProperty(EjsProperty *last, int flags) -{ - EjsProperty *pp; - EjsObj *obj; - EjsPropLink *lp, *head; - - obj = last->parentObj; - - lp = last->link.next; - head = &obj->link; - pp = 0; - - while (obj) { - while (lp != head) { - pp = ejsGetPropertyFromLink(lp); - if (! pp->dontEnumerate || (flags & EJS_ENUM_HIDDEN)) { - break; - } - lp = lp->next; - } - if (lp != head || !(flags & EJS_ENUM_CLASSES)) { - break; - } - - /* - * Now iterate over properties in base classes (down the chain) - */ - if (obj->baseClass == 0) { - break; - } - - obj = obj->baseClass->objectState; - if (obj == 0) { - break; - } - } - return pp; -} - -/******************************************************************************/ -/* - * Find a variable given a variable name and return the parent object and - * the variable itself. This routine supports literal variable and property - * names that may be objects or arrays but may NOT have expressions. - * Returns -1 on errors or if the variable is not found. - * FUTURE -- Needs OPT - */ - -EjsVar *ejsFindProperty(Ejs *ep, EjsVar **obj, char **property, EjsVar *global, - EjsVar *local, const char *fullName, int create) -{ - EjsProperty *currentProp; - EjsVar *currentObj; - /* MOB -- WARNING BIG */ - char tokBuf[EJS_MAX_ID], propertyName[EJS_MAX_ID]; - char *token, *next, *cp, *endp; - - mprAssert(fullName && *fullName); - - currentProp = 0; - currentObj = 0; - - if (global == 0) { - global = ep->global; - } - - if (obj) { - *obj = 0; - } - if (property) { - *property = 0; - } - - if (fullName == 0) { - return 0; - } - - next = (char*) fullName; - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - mprStrcpy(propertyName, sizeof(propertyName), token); - - if (local) { - currentProp = ejsGetProperty(ep, local, token); - currentObj = local; - } - if (currentProp == 0) { - currentProp = ejsGetProperty(ep, global, token); - currentObj = global; - } - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - while (currentObj != 0 && token != 0 && *token) { - - if (currentProp == 0) { - return 0; - } - currentObj = ¤tProp->var; - currentProp = 0; - - if (*token == '[') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - mprStrcpy(propertyName, sizeof(propertyName), token); - cp = propertyName; - if (*cp == '\"') { - cp++; - if ((endp = strchr(cp, '\"')) != 0) { - *endp = '\0'; - } - } else if (*cp == '\'') { - cp++; - if ((endp = strchr(cp, '\'')) != 0) { - *endp = '\0'; - } - } - - currentProp = ejsGetProperty(ep, currentObj, propertyName); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (*token != ']') { - return 0; - } - - } else if (*token == '.') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (!isalpha((int) token[0]) && - token[0] != '_' && token[0] != '$') { - return 0; - } - - mprStrcpy(propertyName, sizeof(propertyName), token); - currentProp = ejsGetProperty(ep, currentObj, token); - - } else { - currentProp = ejsGetProperty(ep, currentObj, token); - } - - if (next == 0 || *next == '\0') { - break; - } - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - } - - if (obj) { - *obj = currentObj; - } - - - if (currentProp == 0 && currentObj >= 0 && create) { - currentProp = ejsCreateSimpleProperty(ep, currentObj, propertyName); - } - - if (property) { - *property = currentProp->name; - } - return ejsGetVarPtr(currentProp); -} - -/******************************************************************************/ -/* - * Get the next token as part of a variable specification. This will return - * a pointer to the next token and will return a pointer to the next token - * (after this one) in "next". The tokBuf holds the parsed token. - */ - -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) -{ - char *start, *cp; - int len; - - start = *next; - while (isspace((int) *start) || *start == '\n' || *start == '\r') { - start++; - } - cp = start; - - if (*cp == '.' || *cp == '[' || *cp == ']') { - cp++; - } else { - while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && - !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { - cp++; - } - } - len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); - tokBuf[len] = '\0'; - - *next = cp; - return tokBuf; -} - -/******************************************************************************/ - -EjsVar *ejsGetGlobalClass(Ejs *ep) -{ - return ep->global; -} - -/******************************************************************************/ -/*************************** Property Access Methods **************************/ -/******************************************************************************/ -/* - * Create an undefined property. This routine calls the object method hooks. - */ - -/* MOB -- better suffix than "Method" */ -EjsVar *ejsCreatePropertyMethod(Ejs *ep, EjsVar *op, const char *property) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(op); - mprAssert(property && *property); - - if (op == 0) { - return 0; - } - - mprAssert(op->type == EJS_TYPE_OBJECT); - mprAssert(op->objectState); - - if (op->objectState == 0) { - return 0; - } - - if (op->objectState->methods == 0) { - vp = ejsGetVarPtr(ejsCreateSimpleProperty(ep, op, property)); - } else { - vp = (op->objectState->methods->createProperty)(ep, op, property); - } - - if (vp == 0) { - mprAssert(vp); - op->objectState->hasErrors = 1; - return 0; - } - - /* - * FUTURE - find a better way. - */ - if (op->isArray) { - ejsSetArrayLength(ep, op, property, 0, 0); - } - return vp; -} - -/******************************************************************************/ - -int ejsDeletePropertyMethod(Ejs *ep, EjsVar *op, const char *property) -{ - int rc; - - mprAssert(ep); - mprAssert(op); - mprAssert(property && *property); - - if (op == 0) { - return -1; - } - - mprAssert(op->type == EJS_TYPE_OBJECT); - mprAssert(op->objectState); - - if (op->objectState == 0) { - return -1; - } - - if (op->objectState->methods == 0) { - rc = ejsDeleteProperty(ep, op, property); - } else { - rc = (op->objectState->methods->deleteProperty)(ep, op, property); - } - - if (rc < 0) { - op->objectState->hasErrors = 1; - } - - op->objectState->dirty = 1; - - return rc; -} - -/******************************************************************************/ -/* - * Set the value of a property. Create if it does not exist - * If the object has property accessor methods defined, use those. - */ - -EjsVar *ejsSetPropertyMethod(Ejs *ep, EjsVar *op, const char *property, - const EjsVar *value) -{ - EjsVar *vp; - - mprAssert(ep); - mprAssert(op); - mprAssert(property && *property); - mprAssert(value); - - if (op == 0) { - return 0; - } - - mprAssert(op->type == EJS_TYPE_OBJECT); - mprAssert(op->objectState); - - if (op->objectState == 0) { - return 0; - } - - if (op->objectState->methods == 0) { - vp = ejsGetVarPtr(ejsCreateSimpleProperty(ep, op, property)); - if (vp && ejsWriteVar(ep, vp, (EjsVar*) value, EJS_SHALLOW_COPY) < 0) { - mprAssert(0); - op->objectState->hasErrors = 1; - return 0; - } - - } else { - vp = (op->objectState->methods->setProperty)(ep, op, property, value); - } - - if (vp == 0) { - mprAssert(vp); - op->objectState->hasErrors = 1; - return 0; - } - - if (vp->type == EJS_TYPE_OBJECT) { - /* - * We make an object alive (and subject to garbage collection) when - * it is referenced in some other object. If this is undesirable, the - * caller should make the object permanent while calling this routine - * and then afterward clear the alive bit by calling ejsMakeObjLive(). - */ - if (op->objectState != vp->objectState) { - vp->objectState->alive = 1; - } -#if BLD_DEBUG - { - EjsProperty *pp = ejsGetPropertyPtr(vp); - ejsSetVarName(ep, vp, &pp->name[0]); - if (value->propertyName == 0) { - ejsSetVarName(ep, (EjsVar*) value, &pp->name[0]); - } - } -#endif - } - - /* - * Trap assignments to array.length. MOB - find a better way. - */ - if (vp->isArrayLength) { - ejsSetArrayLength(ep, op, 0, 0, value); - } - - op->objectState->dirty = 1; - - return vp; -} - -/******************************************************************************/ - -EjsVar *ejsGetPropertyMethod(Ejs *ep, EjsVar *op, const char *property) -{ - mprAssert(ep); - mprAssert(op); - mprAssert(property && *property); - - if (op == 0) { - return 0; - } - - mprAssert(op->type == EJS_TYPE_OBJECT); - mprAssert(op->objectState); - - if (op->objectState == 0) { - return 0; - } - - if (op->objectState->methods == 0) { - return ejsGetVarPtr(ejsGetSimpleProperty(ep, op, property)); - } else { - return (op->objectState->methods->getProperty)(ep, op, property); - } -} - -/******************************************************************************/ -/*************************** Advisory Locking Support *************************/ -/******************************************************************************/ -#if BLD_FEATURE_MULTITHREAD - -void ejsLockObj(EjsVar *vp) -{ - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_OBJECT); - mprAssert(vp->objectState); - - if (vp->objectState->mutex == 0) { - vp->objectState->mutex = mprCreateLock(vp->objectState->ejs); - } - mprLock(vp->objectState->mutex); -} - -/******************************************************************************/ - -void ejsUnlockObj(EjsVar *vp) -{ - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_OBJECT); - mprAssert(vp->objectState); - - if (vp->objectState->mutex) { - mprUnlock(vp->objectState->mutex); - } -} - -#endif -/******************************************************************************/ -/************************** Internal Support Routines *************************/ -/******************************************************************************/ -/* - * Create an object. - */ - -static EjsObj *createObj(EJS_LOC_DEC(ep, loc)) -{ - EjsObj *op; - EjsPropLink *lp; - - op = (EjsObj*) ejsAllocObj(EJS_LOC_PASS(ep, loc)); - if (op == NULL) { - return 0; - } - - /* - * The objectState holds the dummy head for the ordered list of properties - */ - lp = &op->link; - lp->next = lp->prev = lp; - -#if BLD_DEBUG - /* - * This makes it much easier to debug the list - */ - lp->head = lp; - lp->propertyName = "dummyHead"; -#endif - - return op; -} - -/******************************************************************************/ -/* - * Destroy an object. Called by the garbage collector if there are no more - * references to an object. - */ - -int ejsDestroyObj(Ejs *ep, EjsObj *obj) -{ - EjsProperty *pp; - EjsPropLink *lp, *head, *nextLink; - - mprAssert(obj); - - if (obj->destructor) { - EjsVar v; - memset(&v, 0, sizeof(v)); - v.type = EJS_TYPE_OBJECT; - v.objectState = obj; - ejsSetVarName(ep, &v, "destructor"); - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - v.gc.allocatedBy = "static"; -#endif - - if ((obj->destructor)(ep, &v) < 0) { - return -1; - } - } - mprFree(obj->objName); - obj->objName = 0; - - /* - * Just for safety. An object may be marked by a GC on the default - * interpreter. After destroying, it won't be on the free list and so - * won't be reset. - */ - obj->gcMarked = 0; - obj->visited = 0; - - head = &obj->link; - for (lp = head->next; lp != head; lp = nextLink) { - - pp = ejsGetPropertyFromLink(lp); - nextLink = lp->next; - - /* - * We don't unlink as we are destroying all properties. - * If an object, we don't need to clear either. - */ - if (pp->var.type != EJS_TYPE_OBJECT) { - ejsClearVar(ep, ejsGetVarPtr(pp)); - } - ejsFree(ep, pp, EJS_SLAB_PROPERTY); - } - -#if BLD_FEATURE_MULTITHREAD - if (obj->mutex) { - mprDestroyLock(obj->mutex); - } -#endif - - ejsFree(ep, obj, EJS_SLAB_OBJ); - return 0; -} - -/******************************************************************************/ -/* - * Fast hash. The history of this algorithm is part of lost computer science - * folk lore. - */ - -static int hash(const char *property) -{ - uint sum; - - mprAssert(property); - - sum = 0; - while (*property) { - sum += (sum * 33) + *property++; - } - - return sum % EJS_OBJ_HASH_SIZE; -} - -/******************************************************************************/ -/* - * Set a new length for an array. If create is non-null, then it is the name - * of a new array index. If delete is set, it is the name of an index being - * deleted. If setLength is set to a variable, it counts the new length for the - * array. Note that create and delete are ignored if they are non-integer - * array indexes (eg. normal properties). - */ - -void ejsSetArrayLength(Ejs *ep, EjsVar *obj, const char *create, - const char *delete, const EjsVar *setLength) -{ - EjsVar *vp; - char idx[16]; - int oldSize, newSize, i; - - vp = ejsGetPropertyAsVar(ep, obj, "length"); - oldSize = vp->integer; - newSize = oldSize; - - if (create) { - if (isdigit(*create)) { - i = atoi(create); - newSize = max(i + 1, oldSize); - } - } else if (delete) { - if (isdigit(*delete)) { - i = atoi(delete); - newSize = (i == (oldSize - 1) ? oldSize - 1 : oldSize); - } - } else { - newSize = setLength->integer; - } - - for (i = newSize; i < oldSize; i++) { - mprItoa(idx, sizeof(idx), i); - ejsDeleteProperty(ep, obj, idx); - } - - if (ejsWriteVarAsInteger(ep, vp, newSize) == 0) { - mprAssert(0); - } -} - -/******************************************************************************/ - -void ejsClearObjErrors(EjsVar *vp) -{ - if (vp == 0 || vp->type != EJS_TYPE_OBJECT || vp->objectState == 0) { - mprAssert(0); - return; - } - vp->objectState->hasErrors = 0; -} - -/******************************************************************************/ - -int ejsObjHasErrors(EjsVar *vp) -{ - if (vp == 0 || vp->type != EJS_TYPE_OBJECT || vp->objectState == 0) { - mprAssert(0); - return -1; - } - return vp->objectState->hasErrors; -} - -/******************************************************************************/ - -bool ejsIsObjDirty(EjsVar *vp) -{ - mprAssert(vp->type == EJS_TYPE_OBJECT && vp->objectState); - - if (vp->type == EJS_TYPE_OBJECT && vp->objectState) { - return vp->objectState->dirty; - } - return 0; -} - -/******************************************************************************/ - -void ejsResetObjDirtyBit(EjsVar *vp) -{ - mprAssert(vp->type == EJS_TYPE_OBJECT && vp->objectState); - - if (vp->type == EJS_TYPE_OBJECT && vp->objectState) { - vp->objectState->dirty = 0; - } -} - -/******************************************************************************/ -/* - * Copy a string. Always null terminate. - */ - -static int dupString(MPR_LOC_DEC(ctx, loc), uchar **dest, const void *src, - int nbytes) -{ - mprAssert(dest); - mprAssert(src); - - if (nbytes > 0) { - *dest = mprMemdupInternal(MPR_LOC_PASS(ctx, loc), src, nbytes + 1); - if (*dest == 0) { - return MPR_ERR_MEMORY; - } - - } else { - *dest = (uchar*) mprAlloc(ctx, 1); - nbytes = 0; - } - - (*dest)[nbytes] = '\0'; - - return nbytes; -} - -/******************************************************************************/ - -const char *ejsGetVarTypeAsString(EjsVar *vp) -{ - switch (vp->type) { - default: - case EJS_TYPE_UNDEFINED: - return "undefined"; - case EJS_TYPE_NULL: - return "null"; - case EJS_TYPE_BOOL: - return "bool"; - case EJS_TYPE_CMETHOD: - return "cmethod"; - case EJS_TYPE_FLOAT: - return "float"; - case EJS_TYPE_INT: - return "int"; - case EJS_TYPE_INT64: - return "int64"; - case EJS_TYPE_OBJECT: - return "object"; - case EJS_TYPE_METHOD: - return "method"; - case EJS_TYPE_STRING: - return "string"; - case EJS_TYPE_STRING_CMETHOD: - return "string method"; - case EJS_TYPE_PTR: - return "ptr"; - } -} - -/******************************************************************************/ - -void *ejsGetVarUserPtr(EjsVar *vp) -{ - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_PTR); - - if (!ejsVarIsPtr(vp)) { - return 0; - } - return vp->ptr.userPtr; -} - -/******************************************************************************/ - -void ejsSetVarUserPtr(EjsVar *vp, void *data) -{ - mprAssert(vp); - mprAssert(vp->type == EJS_TYPE_PTR); - - vp->ptr.userPtr = data; -} - -/******************************************************************************/ -/* - * Return TRUE if target is a subclass (or the same class) as baseClass. - */ - -bool ejsIsSubClass(EjsVar *target, EjsVar *baseClass) -{ - do { - if (target->objectState == baseClass->objectState) { - return 1; - } - target = target->objectState->baseClass; - } while (target); - - return 0; -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/ejsVar.h b/source4/lib/appweb/ejs-2.0/ejs/ejsVar.h deleted file mode 100644 index 071665e00b..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/ejsVar.h +++ /dev/null @@ -1,1091 +0,0 @@ -/* - * ejsVar.h -- EJS Universal Variable Type - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/* - * Variables can efficiently store primitive types and can hold references to - * objects. Objects can store properties which are themselves variables. - * Properties can be primitive data types, other objects or methods. - * Properties are indexed by a character name. A variable may store one of - * the following types: - * - * string, integer, integer-64bit, C method, C method with string args, - * Javascript method, Floating point number, boolean value, Undefined - * value and the Null value. - * - * Variables have names while objects may be referenced by multiple variables. - * Objects use reference counting for garbage collection. - * - * This module is not thread safe for performance and compactness. It relies - * on upper modules to provide thread synchronization as required. The API - * provides primitives to get variable/object references or to get copies of - * variables which will help minimize required lock times. - */ - -#ifndef _h_EJS_VAR -#define _h_EJS_VAR 1 - -/********************************* Includes ***********************************/ - -#include "mpr.h" - -/********************************** Defines ***********************************/ -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Defined in ejs.h - */ -typedef struct Ejs Ejs; - -/* - * Constants - */ -#if BLD_FEATURE_SQUEEZE - /** - * Maximum property or variable name size - */ - #define EJS_MAX_ID 64 - - /* - * EJS_VAR_HASH_SIZE must be less than the size of the bit field - * propertyIndex in EjsProperty. - */ - #define EJS_OBJ_HASH_SIZE 13 - - /** - * Maximum number of arguments per function call - */ - #define EJS_MAX_ARGS 32 - #define EJS_INC_ARGS 8 /* Frame stack increment */ - -#else - #define EJS_MAX_ID 256 - #define EJS_OBJ_HASH_SIZE 29 - #define EJS_MAX_ARGS 64 - #define EJS_INC_ARGS 8 -#endif - -#define EJS_VAR_MAX_RECURSE 5 /* Max object loops */ - -#if !DOXYGEN -/* - * Forward declare types - */ -struct Ejs; -struct EjsObj; -struct EjsProperty; -struct EjsVar; -#endif - -/** - * @overview EJ primitive variable type - * @description EJ primitive variable values are stored in EjsVar structures. - * The type of the primitive data is described by an EjsType field. - * EjsVar variable types. - * @stability Prototype. - * @library libejs. - * @see EJS_TYPE_UNDEFINED, EJS_TYPE_NULL, EJS_TYPE_BOOL, EJS_TYPE_CMETHOD, - * EJS_TYPE_FLOAT, EJS_TYPE_INT, EJS_TYPE_INT64, EJS_TYPE_OBJECT, - * EJS_TYPE_METHOD, EJS_TYPE_STRING, EJS_TYPE_STRING_CMETHOD, EJS_TYPE_PTR, - */ -typedef uint EjsType; -#define EJS_TYPE_UNDEFINED 0 /**< Undefined. No value has been set */ -#define EJS_TYPE_NULL 1 /**< Value defined to be null. */ -#define EJS_TYPE_BOOL 2 /**< Boolean type. */ -#define EJS_TYPE_CMETHOD 3 /**< C method */ -#define EJS_TYPE_FLOAT 4 /**< Floating point number */ -#define EJS_TYPE_INT 5 /**< Integer number */ -#define EJS_TYPE_INT64 6 /**< 64-bit Integer number */ -#define EJS_TYPE_OBJECT 7 /**< Object reference */ -#define EJS_TYPE_METHOD 8 /**< JavaScript method */ -#define EJS_TYPE_STRING 9 /**< String (immutable) */ -#define EJS_TYPE_STRING_CMETHOD 10 /**< C method with string args */ -#define EJS_TYPE_PTR 11 /**< Opaque pointer */ - -/* - * Create a type for the default number type - * Config.h will define the default number type. For example: - * - * BLD_FEATURE_NUM_TYPE=int - * BLD_FEATURE_NUM_TYPE_ID=EJS_TYPE_INT - */ - -/** - * Set to the type used for EJS numeric variables. Will equate to int, int64 - * or double. - */ -typedef BLD_FEATURE_NUM_TYPE EjsNum; - -/** - * Set to the EJS_TYPE used for EJS numeric variables. Will equate to - * EJS_TYPE_INT, EJS_TYPE_INT64 or EJS_TYPE_FLOAT. - */ -#define EJS_NUM_VAR BLD_FEATURE_NUM_TYPE_ID -#define EJS_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID - -/* - * Return TRUE if a variable is a method type - */ -#define ejsVarIsMethod(vp) \ - ((vp)->type == EJS_TYPE_METHOD || (vp)->type == EJS_TYPE_STRING_CMETHOD || \ - (vp)->type == EJS_TYPE_CMETHOD) - -/* - * Return TRUE if a variable is a numeric type - */ -#define ejsVarIsNumber(vp) \ - ((vp)->type == EJS_TYPE_INT || (vp)->type == EJS_TYPE_INT64 || \ - (vp)->type == EJS_TYPE_FLOAT) - -/* - * Return TRUE if a variable is a boolean - */ -#define ejsVarIsBoolean(vp) \ - ((vp)->type == EJS_TYPE_BOOL) - -/* - * Return TRUE if a variable is an integer type - */ -#define ejsVarIsInteger(vp) ((vp)->type == EJS_TYPE_INT) - -/* - * Return TRUE if a variable is a string - */ -#define ejsVarIsString(vp) \ - ((vp)->type == EJS_TYPE_STRING) - -/* - * Return TRUE if a variable is an object - */ -#define ejsVarIsObject(vp) \ - ((vp)->type == EJS_TYPE_OBJECT) - -/* - * Return TRUE if a variable is a floating number - */ -#define ejsVarIsFloating(vp) \ - ((vp)->type == EJS_TYPE_FLOAT) - -/* - * Return TRUE if a variable is undefined - */ -#define ejsVarIsUndefined(var) \ - ((var)->type == EJS_TYPE_UNDEFINED) - -/* - * Return TRUE if a variable is null - */ -#define ejsVarIsNull(var) \ - ((var)->type == EJS_TYPE_NULL) - -/* - * Return TRUE if a variable is a valid type (not null or undefined) - */ -#define ejsVarIsValid(var) \ - (((var)->type != EJS_TYPE_NULL) && ((var)->type != EJS_TYPE_UNDEFINED)) - -/* - * Return TRUE if a variable is a ptr type - */ -#define ejsVarIsPtr(vp) \ - ((vp)->type == EJS_TYPE_PTR) - -/* MOB -- convert all ep to ejs */ -/** - * @overview C Method signature - * @description This is the calling signature for C Methods. - * @param ejs Ejs reference returned from ejsCreateInterp - * @param thisObj Reference to the "this" object. (The object containing the - * method). - * @param argc Number of arguments. - * @param argv Array of arguments. Each argument is held in an EjsVar type. - * @stability Prototype. - * @library libejs. - * @see ejsCreateCMethodVar - */ -typedef int (*EjsCMethod)(struct Ejs *ejs, struct EjsVar *thisObj, - int argc, struct EjsVar **argv); - -/** - * C Method with string arguments signature - * @overview C Method with string arguments signature - * @description This is the calling signature for C Methods. - * @param ejs Ejs reference returned from ejsCreateInterp - * @param thisObj Reference to the "this" object (object containing the - * method. - * @param argc Number of arguments. - * @param argv Array of arguments. Each argument is held in an C string - * pointer. - * @stability Prototype. - * @library libejs. - * @see ejsCreateStringCMethodVar - */ -typedef int (*EjsStringCMethod)(struct Ejs *ep, struct EjsVar *thisObj, - int argc, char **argv); - -/** - * Flags for types: EJS_TYPE_CMETHOD, EJS_TYPE_STRING_CMETHOD - * NOTE: flags == 0 means to use the EJS handle on method callbacks - */ -/* Use the primary handle on method callbacks */ -#define EJS_PRIMARY_HANDLE 0x1 - -/* Use the alternate handle on method callbacks */ -#define EJS_ALT_HANDLE 0x2 - -/** Method should not create a new local variable block */ -#define EJS_NO_LOCAL 0x4 - -/* Method is a get accessor */ -#define EJS_GET_ACCESSOR 0x8 - -/* Method is a set accessor */ -#define EJS_SET_ACCESSOR 0x10 - -/* - * Flags for E4X (Xml type) - */ -/* Node is a text node */ -#define EJS_XML_FLAGS_TEXT 0x1 - -/* Node is a processing instruction */ -#define EJS_XML_FLAGS_PI 0x2 - -/* Node is a comment */ -#define EJS_XML_FLAGS_COMMENT 0x4 - -/* Node is an attribute */ -#define EJS_XML_FLAGS_ATTRIBUTE 0x8 - -/* Node is an element */ -#define EJS_XML_FLAGS_ELEMENT 0x10 - -/** - * Copy depth - * @overview Specifies how an object should be copied - * @description The EjsCopyDepth type specifies how an object's properties - * should be copied. Several routines take EjsCopyDepth parameters to - * control how the properties of an object should be copied. It provides - * three copy options: - * @see ejsWriteVar - */ -typedef enum EjsCopyDepth { - /** - * During an object copy, object property references will be copied so - * that the original object and the copy will share the same reference to - * a property object. Properties containing primitive types including - * strings will have their values copied and will not share references. - */ - EJS_SHALLOW_COPY, /** Copy strings. Copy object references. */ - /* - * During an object copy, object properties will be replicated so that - * the original object and the copy will not share references to the same - * object properties. If the original object's properties are themselves - * objects, their properties will not be copied. Only their references - * will be copied. i.e. the deep copy is one level deep. - */ - EJS_DEEP_COPY, /** Copy strings and copy object contents. */ - /* - * During an object copy, all object properties will be replicated so that - * the original object and the copy will not share references to the same - * object properties. If the original object's properties are themselves - * objects, their properties will be copied. i.e. the copy is of infinite - * depth. - */ - EJS_RECURSIVE_DEEP_COPY /** Copy strings and copy object contents - recursively (complete copy). */ -} EjsCopyDepth; - - -/* - * Enumeration flags - */ -/** Enumerate data properties */ -#define EJS_ENUM_DATA 0x0 - -/** Enumerate sub classes */ -#define EJS_ENUM_CLASSES 0x1 - -/** Enumerate non-enumerable properties */ -#define EJS_ENUM_HIDDEN 0x2 - -/** Enumerate all properties */ -#define EJS_ENUM_ALL (0x3) - -/** Magic number when allocated */ -#define EJS_MAGIC 0xe801e2ec -#define EJS_MAGIC_FREE 0xe701e3ea - - -/* - * Garbage Collection Linkage. Free list only uses the next pointers. - */ -typedef struct EjsGCLink { -#if BLD_DEBUG - uint magic; /* Magic number */ -#endif -#if BLD_FEATURE_ALLOC_LEAK_TRACK - const char *allocatedBy; /* Who allocated this */ -#endif - struct EjsGCLink *next; /* Next property */ -} EjsGCLink; - - -/** - * @overview EJS Variable Type - * @description The EJ language supports an extensive set of primitive types. - * These variable types can efficiently store primitive data types such as - * integers, strings, binary string, booleans, floating point numbers, - * pointer references, and objects. EjsVars are the universal type used by - * EJ to hold objects, classes and properties. - * \n\n - * An EjsVar may store one of the following types: - * @li Boolean - * @li Floating point (if supported in this build) - * @li Integer - * @li 64 bit integer (if supported in this build) - * @li String - * @li Binary string - * @li C function or C++ method - * @li C function with string args - * @li Javascript method - * @li Object - * @li Null value. - * @li Undefined value - * \n\n - * Objects can hold object properties which are themselves EJS variables. - * Properties are hash indexed by the property name and are stored in - * an ordered sequence. i.e. Order of properties is maintained. Objects may - * be referenced by multiple variables and they use garbage collection to - * reclaim memory no longer in use by objects and properties. - * - * @warning This module is @e not thread safe for performance and - * compactness. It relies on upper modules to provide thread - * synchronization as required. The API provides primitives to get - * variable/object references or to get copies of variables which should - * help minimize required lock times. - * @stability Prototype. - * @library libejs - * @see Ejs, EjsProperty, ejsCreateStringVar, ejsFreeVar - */ - -typedef struct EjsVar { /* Size 12 bytes */ - /* - * GC must be first - */ -#if BLD_DEBUG || BLD_FEATURE_ALLOC_LEAK_TRACK - EjsGCLink gc; /* Garbage collection links */ -#endif - -#if BLD_DEBUG - const char *propertyName; /* Ptr to property name */ -#endif - - /* - * Union of primitive types. When debugging on Linux, don't use unions - * as the gdb debugger can't display them. - */ -#if (!BLD_DEBUG && !VXWORKS) || WIN || BREW_SIMULATOR - union { -#endif - /* - * For debugging, we order the common types first - */ - struct EjsObj *objectState; /* Object state information */ - int integer; - bool boolean; - -#if BLD_FEATURE_FLOATING_POINT - double floating; -#endif -#if BLD_FEATURE_INT64 - int64 integer64; -#endif - - struct { - int length; /* String length (sans null) */ - /* - * All strings always have a trailing null allocated - */ - union { - char *string; /* String */ - uchar *ustring; /* Binary string */ - }; - }; - - struct { /* Javascript methods */ - MprArray *args; /* Null terminated */ - char *body; - } method; - - struct { /* Method with EjsVar args */ - EjsCMethod fn; /* Method pointer */ - void *userData; /* User data for method */ - } cMethod; - - struct { /* Method with string args */ - EjsStringCMethod fn; /* Method pointer */ - void *userData; /* User data for method */ - } cMethodWithStrings; - - struct { - void *userPtr; /* Opaque pointer */ - int (*destructor)(Ejs *ejs, struct EjsVar *vp); - } ptr; - -#if (!BLD_DEBUG && !VXWORKS) || WIN || BREW_SIMULATOR - }; -#endif - - /* - * Packed bit field (32 bits) - */ - uint flags : 8; /* Type specific flags */ - EjsType type : 4; /* Selector into union */ - uint stringLen : 4; /* Length of string if inline */ - uint allocatedData : 1; /* Node needs freeing */ - uint isArray : 1; /* Var is an array */ - uint isArrayLength : 1; /* Var is array.length */ - uint callsSuper : 1; /* Method calls super() */ - uint isProperty : 1; /* Part of a property */ - uint reserved : 11; /* Unused */ - -} EjsVar; - - -/* - * Linkage for the ordered list of properties - */ -typedef struct EjsPropLink { - struct EjsPropLink *next; /* Next property */ - struct EjsPropLink *prev; /* Previous property */ - - /* - * To make debugging easier - */ -#if BLD_DEBUG - const char *propertyName; /* Pointer to name */ - struct EjsProperty *property; /* Pointer to property */ - struct EjsPropLink *head; /* Dummy head of list */ -#endif -} EjsPropLink; - - -/** - * @overview Object Property Type - * @description The EjsProperty type is used to store all object properties. - * It contains the property name, property linkage, propery attributes - * such as public/private, enumerable and readonly settings. It also - * contains an EjsVar to store the property data value. - * @stability Prototype. - * @library libejs - * @see Ejs, EjsVar - */ -typedef struct EjsProperty { /* Size 96 bytes in squeeze */ - /* - * EjsVar must be first. We often take the address of "var" and take - * advantage of if an EjsProperty is null, then &prop->var will be null - * also. Be WARNED. External users should use ejsGetVarPtr and - * ejsGetPropertyPtr to convert between the two. - */ - EjsVar var; /* Property value */ - - /* OPT change this to a pointer to the base class property */ - char name[EJS_MAX_ID]; /* Name */ - - uint visited : 1; /* Has been traversed */ - uint isPrivate : 1; /* Property is private */ - uint isProtected : 1; /* Property is protected */ - uint dontEnumerate : 1; /* Not enumerable */ - uint dontDelete : 1; /* Prevent delete */ - uint readonly : 1; /* Unmodifiable */ - uint allowNonUnique : 1; /* Multiple of same name ok */ - uint delayedDelete : 1; - uint reserved : 24; - - EjsPropLink link; /* Ordered linked list */ - struct EjsProperty *hashNext; /* Hash table linkage */ - - /* MOB -- is this really required */ - struct EjsObj *parentObj; /* Pointer to parent object */ - -} EjsProperty; - - -#define EJS_OP_DOT 0x1 -#define EJS_OP_INDEX 0x2 -#define EJS_OP_PLUS 0x3 -#define EJS_OP_MINUS 0x4 -#define EJS_OP_MULTIPLY 0x5 -#define EJS_OP_DIVIDE 0x6 -#define EJS_OP_CALL 0x7 - -typedef struct EjsOp { - int opType; - -} EjsOp; - -/* - * Propety Access Methods. Used per class. - * MOB -- rename EjsHelpers - */ -typedef struct EjsMethods { -#if FUTURE - int (*create)(Ejs *ep, EjsVar *thisObj); - int (*deleteProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); - EjsVar *(*getProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); - EjsVar *(*setProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); - int (*hasProperty)(Ejs *ep, EjsVar *thisObj, const char *prop); - int (*hasInstance)(Ejs *ep, EjsVar *thisObj, const char *prop); - int (*operate)(Ejs *ep, EjsVar *thisObj, EjsOp op, EjsVar *result, - EjsVar *lhs, EjsVar *rhs, int *code); -#else - - EjsVar *(*createProperty)(Ejs *ep, EjsVar *obj, const char *property); - int (*deleteProperty)(Ejs *ep, EjsVar *obj, const char *property); - EjsVar *(*getProperty)(Ejs *ep, EjsVar *obj, const char *property); - EjsVar *(*setProperty)(Ejs *ep, EjsVar *obj, const char *property, - const EjsVar *value); - /* - * Other implemented internal properties in ECMA-262 are: - * - * [[Construct]] implemented via EjsVar methods - * [[Prototype]] implemented via EjsObj->baseClass - * [[Class]] implemented via EjsObj->baseClass->name - * [[Value]] Implemented via EjsProperty + EjsVar + EjsObj - */ - - /* - * FUTURE -- not implemented - */ - int (*canPut)(Ejs *ep, EjsVar *obj, const char *property); - int (*defaultValue)(Ejs *ep, EjsVar *obj, const char *property, - const char *hint); - int (*hasProperty)(Ejs *ep, EjsVar *obj, const char *property); - EjsVar *(*call)(Ejs *ep, EjsVar *obj, const char *property, - EjsVar *args); - int (*hasInstance)(Ejs *ep, EjsVar *obj, const char *property); - int (*scope)(Ejs *ep, EjsVar *obj, const char *property); - int (*match)(Ejs *ep, EjsVar *obj, const char *property, - const char *string, int index); -#endif -} EjsMethods; - - -/* - * Ejs Object Type - */ -typedef struct EjsObj { - /* - * GC must be first - */ - EjsGCLink gc; /* Garbage collection links */ - - union { - char *objName; /* Object name */ - char *className; /* Class name */ - }; - - struct EjsVar *baseClass; /* Pointer to base class object */ - - EjsPropLink link; /* Ordered list of properties */ - - /* OPT -- dynamically allocate this only if required */ - EjsProperty *propertyHash[EJS_OBJ_HASH_SIZE]; /* Hash chains */ - - /* OPT -- could save this and store off baseClass only */ - EjsMethods *methods; /* Property access methods */ - void *nativeData; /* Native object data */ - - int (*destructor)(Ejs *ejs, struct EjsVar *vp); - - uint numProperties : 16; /* Total count of items */ - uint visited : 1; /* Has been traversed */ - uint gcMarked : 1; /* Node marked in-use by GC */ - uint permanent : 1; /* Permanent object, dont GC */ - uint alive : 1; /* Only GC if alive */ - uint noConstructor : 1; /* Object has no constructor */ - uint dirty : 1; /* Object has been modified */ - uint hasErrors : 1; /* Update error */ - uint preventDeleteProp : 1; /* Don't allow prop deletion */ - uint delayedDeleteProp : 1; /* Delayed delete of props */ - uint reserved : 7; /* Unused */ - - Ejs *ejs; /* Owning interp */ - -#if BLD_FEATURE_MULTITHREAD - MprLock *mutex; /* Advisory mutex lock */ -#endif -} EjsObj; - - -/* - * Define a field macro so code an use numbers in a "generic" fashion. - */ -#if EJS_NUM_VAR == EJS_TYPE_INT || DOXYGEN -/* - * Default numeric type - */ -#define ejsNumber integer -#endif -#if EJS_NUM_VAR == EJS_TYPE_INT64 -/* Default numeric type */ -#define ejsNumber integer64 -#endif -#if EJS_NUM_VAR == EJS_TYPE_FLOAT -/* Default numeric type */ -#define ejsNumber floating -#endif - -typedef BLD_FEATURE_NUM_TYPE EjsNumber; - -/* - * Memory allocation slabs - */ -#define EJS_SLAB_OBJ 0 -#define EJS_SLAB_PROPERTY 1 -#define EJS_SLAB_VAR 2 -#define EJS_SLAB_MAX 3 - -/** - * Object and pointer property destructory type - */ -typedef int (*EjsDestructor)(Ejs *ejs, EjsVar *vp); - -#if BLD_FEATURE_ALLOC_LEAK_TRACK || DOXYGEN -/* - * Line number information args and declarations for ejsAlloc. - * Use EJS_LOC_ARGS in normal user code. - * Use EJS_LOC_DEC in declarations. - * Use EJS_LOC_PASS in layered APIs to pass original line info down. - */ -#define EJS_LOC_ARGS(ejs) ejs, MPR_LOC -#define EJS_LOC_DEC(ejs, loc) Ejs *ejs, const char *loc -#define EJS_LOC_PASS(ejs, loc) ejs, loc -#else -#define EJS_LOC_ARGS(ejs) ejs -#define EJS_LOC_DEC(ejs, loc) Ejs *ejs -#define EJS_LOC_PASS(ejs, loc) ejs -#endif - -/******************************* Internal Prototypes **************************/ - -#define ejsInitVar(vp, varType) \ - if (1) { \ - (vp)->type = varType; \ - (vp)->isArray = 0; \ - (vp)->flags = 0; \ - } else -extern void ejsClearVar(Ejs *ep, EjsVar *vp); - -extern int ejsDestroyObj(Ejs *ep, EjsObj *obj); -extern EjsVar *ejsCreatePropertyMethod(Ejs *ep, EjsVar *obj, - const char *name); -extern EjsVar *ejsSetPropertyMethod(Ejs *ep, EjsVar *obj, const char *name, - const EjsVar *value); -extern EjsVar *ejsGetPropertyMethod(Ejs *ep, EjsVar *obj, const char *name); -extern int ejsDeletePropertyMethod(Ejs *ep, EjsVar *obj, - const char *name); -extern void ejsSetArrayLength(Ejs *ep, EjsVar *obj, const char *creating, - const char *deleting, const EjsVar *setLength); - -/* - * At the moment, these are the same routine - */ -extern void ejsSetClassName(Ejs *ep, EjsVar *obj, const char *name); -#define ejsSetObjName ejsSetObjName - -extern bool ejsIsObjDirty(EjsVar *vp); -extern void ejsResetObjDirtyBit(EjsVar *vp); - -extern int ejsObjHasErrors(EjsVar *vp); -extern void ejsClearObjErrors(EjsVar *vp); - -extern EjsVar *ejsClearProperty(Ejs *ep, EjsVar *obj, const char *prop); - -typedef int (*EjsSortFn)(Ejs *ep, EjsProperty *p1, EjsProperty *p2, - const char *propertyName, int order); -extern void ejsSortProperties(Ejs *ep, EjsVar *obj, EjsSortFn fn, - const char *propertyName, int order); - -#if BLD_DEBUG -#define ejsSetVarName(ep, vp, varName) \ - if (1) { \ - (vp)->propertyName = varName; \ - if ((vp)->type == EJS_TYPE_OBJECT && \ - (vp)->objectState && \ - ((vp)->objectState->objName == 0)) { \ - (vp)->objectState->objName = \ - mprStrdup(ep, varName); \ - } \ - } else -#else -#define ejsSetVarName(ep, vp, varName) -#endif - -EjsVar *ejsFindProperty(Ejs *ep, EjsVar **obj, char **property, - EjsVar *global, EjsVar *local, const char *fullName, - int create); - -extern EjsVar *ejsCopyProperties(Ejs *ep, EjsVar *dest, - const EjsVar *src, EjsCopyDepth copyDepth); - -#define EJS_LINK_OFFSET ((uint) (&((EjsProperty*) 0)->link)) -#define ejsGetPropertyFromLink(lp) \ - ((EjsProperty*) ((char*) lp - EJS_LINK_OFFSET)) - -#define ejsGetObjPtr(vp) ((EjsObj*) vp->objectState) - -extern void ejsMakePropertyPrivate(EjsProperty *pp, int isPrivate); -extern void ejsMakePropertyReadOnly(EjsProperty *pp, int readonly); -extern void ejsMakePropertyUndeleteable(EjsProperty *pp, int deletable); -extern int ejsMakeObjLive(EjsVar *vp, bool alive); -extern void ejsMakeClassNoConstructor(EjsVar *vp); - -extern bool ejsBlockInUseInt(EjsVar *vp); -#if BLD_DEBUG - #define ejsBlockInUse(vp) ejsBlockInUseInt(vp) -#else - #define ejsBlockInUse(vp) -#endif - -/********************************* Prototypes *********************************/ - -/* - * Variable constructors and destructors - */ -extern EjsVar *ejsCreateBinaryStringVar(Ejs *ep, const uchar *value, - int len); -extern EjsVar *ejsCreateBoolVar(Ejs *ep, int value); -extern EjsVar *ejsCreateCMethodVar(Ejs *ep, EjsCMethod fn, - void *userData, int flags); -#if BLD_FEATURE_FLOATING_POINT -extern EjsVar *ejsCreateFloatVar(Ejs *ep, double value); -#endif -extern EjsVar *ejsCreateIntegerVar(Ejs *ep, int value); -#if BLD_FEATURE_INT64 -extern EjsVar *ejsCreateInteger64Var(Ejs *ep, int64 value); -#endif - -extern EjsVar *ejsCreateMethodVar(Ejs *ep, const char *body, - MprArray *args, int flags); -extern EjsVar *ejsCreateNullVar(Ejs *ep); -extern EjsVar *ejsCreateNumberVar(Ejs *ep, EjsNumber value); - -#define ejsCreateObjVar(ep) \ - ejsCreateObjVarInternal(EJS_LOC_ARGS(ep)) -extern EjsVar *ejsCreateObjVarInternal(EJS_LOC_DEC(ep, loc)); - -extern EjsVar *ejsCreatePtrVar(Ejs *ep, void *ptr, EjsDestructor dest); - -extern EjsVar *ejsCreateStringCMethodVar(Ejs *ep, EjsStringCMethod fn, - void *userData, int flags); - -#define ejsCreateStringVar(ep, value) \ - ejsCreateStringVarInternal(EJS_LOC_ARGS(ep), value) -extern EjsVar *ejsCreateStringVarInternal(EJS_LOC_DEC(ep, loc), - const char *value); - -extern EjsVar *ejsCreateUndefinedVar(Ejs *ep); - -/* MOB -- naming. Should be Create/Destroy */ -extern void ejsFreeVar(Ejs *ep, EjsVar *vp); - -/* - * Var support routines - */ -extern int ejsGetVarFlags(EjsVar *vp); -extern void ejsSetVarFlags(EjsVar *obj, int flags); - -extern EjsType ejsGetVarType(EjsVar *vp); -extern const char *ejsGetVarTypeAsString(EjsVar *vp); - -extern void *ejsGetCMethodUserData(EjsVar *obj); -extern void ejsSetCMethodUserData(EjsVar *obj, void *userData); - -extern void *ejsGetVarUserPtr(EjsVar *vp); -extern void ejsSetVarUserPtr(EjsVar *vp, void *data); - - -/* - * Variable access and manipulation. These work on standalone objects. - */ -#define ejsDupVar(ep, src, copyDepth) \ - ejsDupVarInternal(EJS_LOC_ARGS(ep), src, copyDepth) -extern EjsVar *ejsDupVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *src, - EjsCopyDepth copyDepth); -#define ejsWriteVar(ep, dest, src, copyDepth) \ - ejsWriteVarInternal(EJS_LOC_ARGS(ep), dest, src, copyDepth) -extern EjsVar *ejsWriteVarInternal(EJS_LOC_DEC(ep, loc), EjsVar *dest, - const EjsVar *src, EjsCopyDepth copyDepth); -extern EjsVar *ejsWriteVarAsBinaryString(Ejs *ep, EjsVar *dest, - const uchar *value, int len); -extern EjsVar *ejsWriteVarAsBoolean(Ejs *ep, EjsVar *dest, bool value); -extern EjsVar *ejsWriteVarAsCMethod(Ejs *ep, EjsVar *dest, EjsCMethod fn, - void *userData, int flags); -#if BLD_FEATURE_FLOATING_POINT -extern EjsVar *ejsWriteVarAsFloat(Ejs *ep, EjsVar *dest, double value); -#endif -extern EjsVar *ejsWriteVarAsInteger(Ejs *ep, EjsVar *dest, int value); -#if BLD_FEATURE_INT64 -extern EjsVar *ejsWriteVarAsInteger64(Ejs *ep, EjsVar *dest, int64 value); -#endif -extern EjsVar *ejsWriteVarAsMethod(Ejs *ep, EjsVar *dest, - const char *body, MprArray *args); -extern EjsVar *ejsWriteVarAsNull(Ejs *ep, EjsVar *dest); -extern EjsVar *ejsWriteVarAsNumber(Ejs *ep, EjsVar *dest, EjsNum value); -#define ejsWriteVarAsString(ep, dest, value) \ - ejsWriteVarAsStringInternal(EJS_LOC_ARGS(ep), dest, value) -extern EjsVar *ejsWriteVarAsStringInternal(EJS_LOC_DEC(ep, loc), - EjsVar *dest, const char *value); -extern EjsVar *ejsWriteVarAsStringCMethod(Ejs *ep, EjsVar *dest, - EjsStringCMethod fn, void *userData, int flags); -extern EjsVar *ejsWriteVarAsUndefined(Ejs *ep, EjsVar *dest); - -/* - * These routines do not convert types - */ -/* MOB -- make this a fn and pass back the length as an arg */ -#define ejsReadVarAsBinaryString(vp) ((const uchar*) (vp->ustring)); -#define ejsReadVarAsBoolean(vp) (vp->boolean); -#define ejsReadVarAsCMethod(vp) (vp->cMethod); -#if BLD_FEATURE_FLOATING_POINT -#define ejsReadVarAsFloat(vp) (vp->floating); -#endif -#define ejsReadVarAsInteger(vp) (vp->integer); -#if BLD_FEATURE_INT64 -#define ejsReadVarAsInteger64(vp) (vp->int64); -#endif -#define ejsReadVarAsString(vp) ((const char*) (vp->string)); -#define ejsReadVarAsStringCMethod(vp) (vp->cMethodWithStrings); -/* MOB -- remove this fn */ -#define ejsReadVarStringLength(vp) (vp->length); - -/* - * Object property creation routines - */ -extern EjsProperty *ejsCreateProperty(Ejs *ep, EjsVar *obj, const char *prop); -extern EjsProperty *ejsCreateSimpleProperty(Ejs *ep, EjsVar *obj, - const char *prop); -extern EjsProperty *ejsCreateSimpleNonUniqueProperty(Ejs *ep, EjsVar *obj, - const char *prop); -/* MOB -- should be destroy */ -extern int ejsDeleteProperty(Ejs *ep, EjsVar *obj, const char *prop); - - -/* - * Get property routines - */ -extern EjsProperty *ejsGetProperty(Ejs *ep, EjsVar *obj, const char *prop); -extern EjsProperty *ejsGetSimpleProperty(Ejs *ep, EjsVar *obj, - const char *prop); - -extern EjsVar *ejsGetPropertyAsVar(Ejs *ep, EjsVar *obj, - const char *prop); -extern int ejsGetPropertyCount(EjsVar *obj); - -extern const uchar *ejsGetPropertyAsBinaryString(Ejs *ep, EjsVar *obj, - const char *prop, int *length); -extern bool ejsGetPropertyAsBoolean(Ejs *ep, EjsVar *obj, - const char *prop); -extern int ejsGetPropertyAsInteger(Ejs *ep, EjsVar *obj, - const char *prop); -extern int64 ejsGetPropertyAsInteger64(Ejs *ep, EjsVar *obj, - const char *prop); -extern EjsNum ejsGetPropertyAsNumber(Ejs *ep, EjsVar *obj, - const char *prop); -extern void *ejsGetPropertyAsPtr(Ejs *ep, EjsVar *obj, - const char *prop); -extern const char *ejsGetPropertyAsString(Ejs *ep, EjsVar *obj, - const char *prop); - -/* - * Object property update routines - */ -extern EjsProperty *ejsSetBaseProperty(Ejs *ep, EjsVar *obj, const char *prop, - const EjsVar *value); -extern EjsProperty *ejsSetProperty(Ejs *ep, EjsVar *obj, const char *prop, - const EjsVar *value); -extern EjsProperty *ejsSetPropertyAndFree(Ejs *ep, EjsVar *obj, - const char *prop, EjsVar *value); -extern EjsProperty *ejsSetPropertyToBinaryString(Ejs *ep, EjsVar *obj, - const char *prop, const uchar *value, int len); -extern EjsProperty *ejsSetPropertyToBoolean(Ejs *ep, EjsVar *obj, - const char *prop, bool value); -extern EjsProperty *ejsSetPropertyToCMethod(Ejs *ep, EjsVar *obj, - const char *prop, EjsCMethod fn, void *userData, - int flags); -#if BLD_FEATURE_FLOATING_POINT -extern EjsProperty *ejsSetPropertyToFloat(Ejs *ep, EjsVar *obj, - const char *prop, double value); -#endif -extern EjsProperty *ejsSetPropertyToInteger(Ejs *ep, EjsVar *obj, - const char *prop, int value); -#if BLD_FEATURE_INT64 -extern EjsProperty *ejsSetPropertyToInteger64(Ejs *ep, EjsVar *obj, - const char *prop, int64 value); -#endif -extern EjsProperty *ejsSetPropertyToMethod(Ejs *ep, EjsVar *obj, - const char *prop, const char *body, MprArray *args, - int flags); -extern EjsProperty *ejsSetPropertyToNewObj(Ejs *ep, EjsVar *obj, - const char *prop, const char *className, - MprArray *args); -extern EjsProperty *ejsSetPropertyToNull(Ejs *ep, EjsVar *obj, - const char *prop); -extern EjsProperty *ejsSetPropertyToNumber(Ejs *ep, EjsVar *obj, - const char *prop, EjsNum value); -extern EjsProperty *ejsSetPropertyToObj(Ejs *ep, EjsVar *obj, - const char *prop); -extern EjsProperty *ejsSetPropertyToPtr(Ejs *ep, EjsVar *obj, - const char *prop, void *ptr, EjsDestructor destructor); - -extern EjsProperty *ejsSetPropertyToStringCMethod(Ejs *ep, EjsVar *obj, - const char *prop, EjsStringCMethod fn, - void *userData, int flags); -extern EjsProperty *ejsSetPropertyToString(Ejs *ep, EjsVar *obj, - const char *prop, const char *value); -extern EjsProperty *ejsSetPropertyToUndefined(Ejs *ep, EjsVar *obj, - const char *prop); - - -/* Convenience function */ -extern EjsVar *ejsSetPropertyToObjAsVar(Ejs *ep, EjsVar *obj, - const char *prop); -extern void ejsSetObjDestructor(Ejs *ep, EjsVar *obj, - EjsDestructor destructor); -extern void ejsClearObjDestructor(Ejs *ep, EjsVar *obj); - -/* - * Enumeration of properties - * MOB -- should these take an ejs parameter to be consistent - */ -extern EjsProperty *ejsGetFirstProperty(const EjsVar *obj, int flags); -extern EjsProperty *ejsGetNextProperty(EjsProperty *last, int flags); - -/* - * Method definition and control. - */ -extern EjsProperty *ejsDefineMethod(Ejs *ep, EjsVar *obj, const char *prop, - const char *body, MprArray *args); -extern EjsProperty *ejsDefineCMethod(Ejs *ep, EjsVar *obj, const char *prop, - EjsCMethod fn, int flags); - -extern EjsProperty *ejsDefineStringCMethod(Ejs *ep, EjsVar *obj, - const char *prop, EjsStringCMethod fn, int flags); - -extern EjsProperty *ejsDefineAccessors(Ejs *ep, EjsVar *obj, - const char *prop, const char *getBody, - const char *setBody); -extern EjsProperty *ejsDefineCAccessors(Ejs *ep, EjsVar *obj, - const char *prop, EjsCMethod getFn, EjsCMethod setFn, - int flags); - -/* - * Macro to get the variable value portion of a property - */ -#define ejsGetVarPtr(pp) (&((pp)->var)) -#define ejsGetPropertyPtr(vp) ((EjsProperty*) vp) - -/* MOB -- take ejs to be consistent */ -extern int ejsMakePropertyEnumerable(EjsProperty *pp, bool enumerable); -extern int ejsMakeObjPermanent(EjsVar *vp, bool permanent); - - -/* - * Var conversion routines - * MOB -- should these take an Ejs as first arg for consistency - */ -extern bool ejsVarToBoolean(EjsVar *vp); -#if BLD_FEATURE_FLOATING_POINT -extern double ejsVarToFloat(EjsVar *vp); -#endif -extern int ejsVarToInteger(EjsVar *vp); -#if BLD_FEATURE_INT64 -extern int64 ejsVarToInteger64(EjsVar *vp); -#endif -extern EjsNum ejsVarToNumber(EjsVar *vp); -extern char *ejsVarToString(Ejs *ep, EjsVar *vp); -extern char *ejsVarToStringEx(Ejs *ep, EjsVar *vp, bool *alloc); -extern char *ejsFormatVar(Ejs *ep, const char *fmt, EjsVar *vp); - -#if BLD_FEATURE_FLOATING_POINT -extern double ejsParseFloat(const char *str); -#endif -/* - * Parsing and type range checking routines - */ -extern bool ejsParseBoolean(const char *str); -extern int ejsParseInteger(const char *str); -#if BLD_FEATURE_INT64 -extern int64 ejsParseInteger64(const char *str); -#endif -extern EjsNum ejsParseNumber(const char *str); -extern EjsVar *ejsParseVar(Ejs *ep, const char *str, EjsType prefType); - -#if BLD_FEATURE_FLOATING_POINT -extern bool ejsIsInfinite(double f); -extern bool ejsIsNan(double f); -#endif - -/* - * Advisory locking support - */ -#if BLD_FEATURE_MULTITHREAD -extern void ejsLockObj(EjsVar *vp); -extern void ejsUnlockObj(EjsVar *vp); -#endif - -/* - * Just for debugging - */ -extern bool ejsObjIsCollectable(EjsVar *vp); - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ -#endif /* _h_EJS_VAR */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/lib/event.js b/source4/lib/appweb/ejs-2.0/ejs/lib/event.js deleted file mode 100644 index 283a3ec72f..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/lib/event.js +++ /dev/null @@ -1,141 +0,0 @@ -/* - * @file event.js - * @brief Event class - * @copy Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - * - * Usage: - * listener = new System.Listener(); - * listener.onClick = function() { - * // Any code here - * } - * eventTarget.addListener(eventName, listener); - * or - * listener = new System.Listener(obj, method); - * eventTarget.addListener(eventName, listener); - * - * To fire events: - * eventTarget.fire(eventName, new System.Event("My Event")); - */ - -/******************************************************************************/ -/* - * Base event class - */ -class System.Event -{ - var type; // keyboard - var timeStamp; - var arg; - - /* MOB -- constructor should take a type */ - function Event(arg) - { - timeStamp = time(); - type = "default"; - this.arg = arg; - } -} - -/* MOB -- should not be needed */ -Event = System.Event; - -class System.Listener -{ - var obj; - var method; - - function Listener(obj, method) - { - if (arguments.length >= 1) { - this.obj = obj; - } else { - this.obj = this; - } - if (arguments.length == 2) { - this.method = method; - } else { - this.method = "onEvent"; - } - } -} -/* MOB -- should not be needed */ -Listener = System.Listener; - - -/* - * The Event target class - */ -class System.EventTarget -{ - // Private - var events; /* Hash of a event names */ - - function EventTarget() - { - events = new Object(); - } - - // Public - function addListener(eventName, listener) - { - var listeners = events[eventName]; - if (listeners == undefined) { - listeners = events[eventName] = new Array(); - } - if (arguments.length == 2) { - var method = eventName; - } - /* MOB OPT */ - for (var i = 0; i < listeners.length; i++) { - var l = listeners[i]; - if (l == listener) { - return; - } - } - listeners[listeners.length] = listener; - } - - function removeListener(eventName, listener) - { - var listeners = events[eventName]; - - if (listeners == undefined) { - return; - } - - for (var i = 0; i < listeners.length; i++) { - var l = listeners[i]; - if (l == listener) { - // MOB -- want listeners.splice here - // listeners.splice(i, 1); - for (var j = i; j < (listeners.length - 1); j++) { - listeners[j] = listeners[j + 1]; - } - delete listeners[listeners.length - 1]; - i = listeners.length; - } - } - } - - function fire(eventName, event) - { - var listeners = events[eventName]; - - if (listeners == undefined) { - // println("Event.fire(): unknown eventName " + eventName); - return; - } - - for (var i = listeners.length - 1; i >= 0; i--) { - var listener = listeners[i]; - var method = listener.obj[listener.method]; - if (method == undefined) { - throw new EvalError("Undefined method: " + listener.method); - } - listener.obj[listener.method](listener, event); - } - } -} - -/* MOB -- should not be needed */ -EventTarget = System.EventTarget; diff --git a/source4/lib/appweb/ejs-2.0/ejs/lib/global.js b/source4/lib/appweb/ejs-2.0/ejs/lib/global.js deleted file mode 100644 index f2daaa57c0..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/lib/global.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * @file global.js - * @brief Misc global functions - * @copy Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ - -/******************************************************************************/ - -function min(a, b) -{ - if (a < b) { - return a; - } else { - return b; - } -} - - -function max(a, b) -{ - if (a > b) { - return a; - } else { - return b; - } -} - -function abs(a) -{ - if (a < 0) { - return -a; - } - return a; -} diff --git a/source4/lib/appweb/ejs-2.0/ejs/lib/startup.js b/source4/lib/appweb/ejs-2.0/ejs/lib/startup.js deleted file mode 100644 index e627a96e04..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/lib/startup.js +++ /dev/null @@ -1,15 +0,0 @@ -/* - * @file startup.js - * @brief Embedded JavaScript Startup Code - * @copy Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - * - * Invoked automatically on startup. - */ - -/******************************************************************************/ - -// println("Loading startup.js ..."); - -include("lib/event.js"); -include("lib/global.js"); -include("lib/timer.js"); diff --git a/source4/lib/appweb/ejs-2.0/ejs/lib/timer.js b/source4/lib/appweb/ejs-2.0/ejs/lib/timer.js deleted file mode 100644 index f4cb8b12ce..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/lib/timer.js +++ /dev/null @@ -1,158 +0,0 @@ -/* - * @file timer.js - * @brief Timer class - * @copy Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - * - * Usage: - * timer = new System.Timer("name", period); - * timer.onTick = function(arg) { - * // Anything here - * } - * timer.start(); - * or - * - * timer = new System.Timer("name", period, obj, method); - * timer.start(); - */ - -/******************************************************************************/ - -class System.Timer -{ - var id; - - /* MOB -- really need accessor on period. If user updates period, - then due must be updated. */ - var period; - var due; - var runOnce; // Run timer just once - var method; // Callback method - var obj; // Callback object - - function Timer(id, period, obj, method) - { - this.id = id; - this.period = period; - due = time() + period; - - if (arguments.length >= 3) { - this.obj = obj; - } else { - this.obj = this; - } - if (arguments.length >= 4) { - this.method = method; - } else { - this.method = "onTick"; - } - } - - /* MOB this should be deprecated */ - function reschedule(period) - { - /* MOB -- should update the timer service somehow */ - this.period = period; - } - - function run(now) - { - if (obj[method] == undefined) { - trace("Timer cant find timer method " + method); - due = now + this.period; - return; - } - - /* - * Run the timer - */ - try { - obj[method](this); - } - catch (error) { - trace("Timer exception: " + error); - } - - if (runOnce) { - timerService.removeTimer(this); - - } else { - due = now + this.period; - } - } - - function start() - { - if (obj[method] == undefined) { - throw new Error("Callback method is undefined"); - } else { - timerService.addTimer(this); - } - } - - function stop() - { - timerService.removeTimer(this); - } - -} - -/* MOB -- should not need this */ -Timer = System.Timer; - - -/* - * Timer service - */ -class System.TimerService -{ - var timers; - var nextDue; - - function TimerService() - { - timers = new Object(); - nextDue = 0; - global.timerService = this; - } - - function addTimer(timer) - { - timers[timer.id] = timer; - } - - function removeTimer(timer) - { - try { - delete timers[timer.id]; - } - catch {} - } - - function getIdleTime() - { - return nextDue - time(); - } - - function runTimers() - { - var now = time(); - - nextDue = 2147483647; /* MOB -- MATH.MAX_INT; */ - - for each (var timer in timers) - { - if (timer.due < now) { - timer.run(now); - } - } - for each (var timer in timers) - { - if (timer.due < nextDue) { - nextDue = timer.due; - } - } - // println("runTimers leaving with " + (nextDue - now)); - return nextDue - time(); - } -} -TimerService = System.TimerService; diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/.ignore b/source4/lib/appweb/ejs-2.0/ejs/system/.ignore deleted file mode 100755 index fb5a29031e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/.ignore +++ /dev/null @@ -1 +0,0 @@ -.updated diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/Makefile b/source4/lib/appweb/ejs-2.0/ejs/system/Makefile deleted file mode 100755 index 2d83662655..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/Makefile +++ /dev/null @@ -1,27 +0,0 @@ -# -# Makefile to build the EJS Object Model -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I.. -I../../mpr -I../../exml - -include make.dep - -ifeq ($(BLD_HOST_UNIX),1) -PRE_DIRS = UNIX -else -PRE_DIRS = $(BLD_HOST_OS) -endif - -compileExtra: .updated - -.updated: $(FILES) - @touch .updated - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/README.TXT b/source4/lib/appweb/ejs-2.0/ejs/system/README.TXT deleted file mode 100644 index a24e0e299c..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/README.TXT +++ /dev/null @@ -1,63 +0,0 @@ -Embedded JavaScript System Model - - -- Need args, arg types and exceptions thrown -- Error classes - -class Global - class System - class environment - var - class GC - void function run() - function tune() - function getUsedMemory() // Should be properties - function getAllocatedMemory() // Should be properties - - var javascript - var null - var undefined - var true - var false - var Nan - var Infinity - - function random // Not implemented - function sleep // Not implemented - function exit - function yield // Not implemented - - Debug - isDebugMode - - Limits - isLimitsMode // Not implemented - stack // Not implemented - heap // Not implemented - flash // Not implemented - - Memory - getUsedMemory() // Should be properties - getAvailableMemory() // Should be properties - used - flash // Not implemented - - assert() - breakpoint() - dirname() - basename() - eval() - exit() - print() - println() - printVars() - sleep() - sort() - time() - typeof() - include() - trace() - printf() // Not implemented - sprintf() - - diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore deleted file mode 100644 index fb5a29031e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/.ignore +++ /dev/null @@ -1 +0,0 @@ -.updated diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile deleted file mode 100755 index 424747052a..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile to build the EJS Object Model for WIN -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I../.. -I../../../mpr - -include make.dep - -compileExtra: .updated - -.updated: $(FILES) - @touch .updated - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c deleted file mode 100644 index 772303152e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFile.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * @file ejsFile.c - * @brief File class for the EJ System Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/* - * Default Constructor - */ - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function open(); - */ - -static int openProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.open()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function close(); - */ - -static int closeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.close()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function read(); - */ - -static int readProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.read()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function write(); - */ - -static int writeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.write()\n"); - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineFileClass(Ejs *ep) -{ - EjsVar *fileClass; - - fileClass = ejsDefineClass(ep, "File", "Object", 0); - if (fileClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ep, fileClass, "open", openProc, 0); - ejsDefineCMethod(ep, fileClass, "close", closeProc, 0); - ejsDefineCMethod(ep, fileClass, "read", readProc, 0); - ejsDefineCMethod(ep, fileClass, "write", writeProc, 0); - - return ejsObjHasErrors(fileClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c deleted file mode 100755 index 7b39c16e4d..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsFileSystem.c +++ /dev/null @@ -1,454 +0,0 @@ -/* - * @file ejsFileSystem.c - * @brief FileSystem class for the EJ System Object Model - * MOB -- this is almost the same as for Windows. Should common up. - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" -#include <dirent.h> - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function void access(string path); - * MOB - API insufficient. Access for read or write? - */ - -static int accessProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: access(path)"); - return -1; - } - - rc = access(argv[0]->string, 04); - - ejsSetReturnValueToBoolean(ejs, (rc == 0) ? 1 : 0); - return 0; -} - -/******************************************************************************/ -/* - * function void mkdir(string path); - */ - -static int mkdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); - return -1; - } - - if (mprMakeDirPath(ejs, argv[0]->string) < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create directory"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void rmdir(string path); - */ - -static int rmdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); - return -1; - } - - rc = mprDeleteDir(ejs, argv[0]->string); - - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant remove directory"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void dirList(string path, [bool enumDirs]); - * MOB -- need pattern to match (what about "." and ".." and ".*" - */ - -static int dirListProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - DIR *dir; - struct dirent *dirent; - char path[MPR_MAX_FNAME]; - EjsVar *array, *vp; - uchar enumDirs; - - if (argc < 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: dirList(path)"); - return -1; - } - if (argc == 2) { - enumDirs = ejsVarToBoolean(argv[1]); - } else { - enumDirs = 0; - } - array = ejsCreateArray(ejs, 0); - ejsMakeObjPermanent(array, 1); - - /* - * First collect the files - */ - mprSprintf(path, sizeof(path), "%s/*.*", argv[0]->string); - - dir = opendir(path); - if (dir == 0) { - ejsError(ejs, EJS_ARG_ERROR, "Can't enumerate dirList(path)"); - return -1; - } - - while ((dirent = readdir(dir)) != 0) { - if (dirent->d_name[0] == '.') { - continue; - } - if (!enumDirs || (dirent->d_type & DT_DIR)) { - mprSprintf(path, sizeof(path), "%s/%s", argv[0]->string, - dirent->d_name); - vp = ejsCreateStringVar(ejs, path); - ejsAddArrayElt(ejs, array, vp, EJS_SHALLOW_COPY); - ejsFreeVar(ejs, vp); - } - } - - closedir(dir); - - ejsSetReturnValue(ejs, array); - ejsMakeObjPermanent(array, 0); - - /* - * Can free now as the return value holds the reference - */ - ejsFreeVar(ejs, array); - - return 0; -} - -/******************************************************************************/ -/* - * function void getFreeSpace(); - */ - -static int getFreeSpaceProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ -#if UNUSED - MprApp *app; - uint space; - - app = mprGetApp(ejs); - space = IFILEMGR_GetFreeSpace(app->fileMgr, 0); - ejsSetReturnValueToInteger(ejs, space); -#endif - - return 0; -} - -/******************************************************************************/ -/* - * function void writeFile(string path, var data); - */ - -static int writeFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFile *file; - char *data, *buf; - int bytes, length, rc; - - if (argc != 2 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: writeFile(path, var)"); - return -1; - } - - if (ejsVarIsString(argv[1])) { - data = argv[1]->string; - length = argv[1]->length; - buf = 0; - } else { - buf = data = ejsVarToString(ejs, argv[1]); - length = strlen(data); - } - - /* - * Create fails if already present - */ - rc = mprDelete(ejs, argv[0]->string); - file = mprOpen(ejs, argv[0]->string, O_CREAT | O_WRONLY | O_BINARY, 0664); - if (file == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[0]->string); - mprFree(buf); - return -1; - } - - rc = 0; - bytes = mprWrite(file, data, length); - if (bytes != length) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - } - - mprClose(file); - - mprFree(buf); - return rc; -} - -/******************************************************************************/ -/* - * function string readFile(string path); - */ - -static int readFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprApp *app; - MprFile *file; - MprBuf *buf; - char *data; - int bytes, rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: readFile(path)"); - return -1; - } - buf = mprCreateBuf(ejs, MPR_BUF_INCR, MPR_MAX_BUF); - if (buf == 0) { - ejsMemoryError(ejs); - return -1; - } - - data = mprAlloc(ejs, MPR_BUFSIZE); - if (buf == 0) { - mprFree(buf); - ejsMemoryError(ejs); - return -1; - } - - app = mprGetApp(ejs); - file = mprOpen(ejs, argv[0]->string, O_RDONLY, 0664); - if (file == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); - mprFree(buf); - return -1; - } - - rc = 0; - while ((bytes = mprRead(file, data, MPR_BUFSIZE)) > 0) { - if (mprPutBlockToBuf(buf, data, bytes) != bytes) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - break; - } - } - - ejsSetReturnValueToBinaryString(ejs, (uchar*) mprGetBufStart(buf), - mprGetBufLength(buf)); - - mprClose(file); - mprFree(data); - mprFree(buf); - - return rc; -} - -/******************************************************************************/ -/* - * function void remove(string path); - */ - -static int removeProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: remove(path)"); - return -1; - } - - rc = unlink(argv[0]->string); - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant remove file"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void rename(string from, string to); - */ - -static int renameProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: rename(old, new)"); - return -1; - } - - unlink(argv[1]->string); - rc = rename(argv[0]->string, argv[1]->string); - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant rename file"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void copy(string old, string new); - */ - -static int copyProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFile *from, *to; - char *buf; - uint bytes; - int rc; - - if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: copy(old, new)"); - return -1; - } - - buf = mprAlloc(ejs, MPR_BUFSIZE); - if (buf == 0) { - ejsMemoryError(ejs); - return -1; - } - - from = mprOpen(ejs, argv[0]->string, O_RDONLY | O_BINARY, 0664); - if (from == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); - mprFree(buf); - return -1; - } - - to = mprOpen(ejs, argv[1]->string, O_CREAT | O_BINARY, 0664); - if (to == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[1]->string); - mprClose(from); - mprFree(buf); - return -1; - } - - rc = 0; - while ((bytes = mprRead(from, buf, MPR_BUFSIZE)) > 0) { - if (mprWrite(to, buf, bytes) != bytes) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - break; - } - } - - mprClose(from); - mprClose(to); - mprFree(buf); - - return rc; -} - -/******************************************************************************/ -/* - * function FileInfo getFileInfo(string path); - * - * MOB -- should create a real class FileInfo - */ - -static int getFileInfoProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFileInfo info; - EjsVar *fileInfo; - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: getFileInfo(path)"); - return -1; - } - - fileInfo = ejsCreateObjVar(ejs); - if (fileInfo == 0) { - ejsMemoryError(ejs); - return -1; - } - ejsMakeObjPermanent(fileInfo, 1); - - rc = mprGetFileInfo(ejs, argv[0]->string, &info); - if (rc < 0) { - ejsMakeObjPermanent(fileInfo, 0); - ejsFreeVar(ejs, fileInfo); - ejsError(ejs, EJS_IO_ERROR, "Cant get file info for %s", - argv[0]->string); - return -1; - } - - ejsSetPropertyToInteger(ejs, fileInfo, "created", info.ctime); - ejsSetPropertyToInteger(ejs, fileInfo, "length", info.size); - ejsSetPropertyToBoolean(ejs, fileInfo, "isDir", info.isDir); - - ejsSetReturnValue(ejs, fileInfo); - ejsMakeObjPermanent(fileInfo, 0); - - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineFileSystemClass(Ejs *ejs) -{ - EjsVar *fileSystemClass; - - fileSystemClass = ejsDefineClass(ejs, "FileSystem", "Object", 0); - if (fileSystemClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ejs, fileSystemClass, "access", accessProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "mkdir", mkdirProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "rmdir", rmdirProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "dirList", dirListProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "writeFile", writeFileProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "readFile", readFileProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "remove", removeProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "rename", renameProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "copy", copyProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "getFileInfo", getFileInfoProc, 0); - - // MOB -- should be a property with accessor - ejsDefineCMethod(ejs, fileSystemClass, "getFreeSpace", getFreeSpaceProc, 0); - - return ejsObjHasErrors(fileSystemClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c b/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c deleted file mode 100755 index 25821f6960..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/UNIX/ejsHTTP.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * @file ejsHTTP.c - * @brief HTTP class for the EJ System Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if UNUSED -/*********************************** Defines **********************************/ - -#define EJS_WEB_PROPERTY "-web" -#define EJS_HTTP_PROPERTY "-http" - -#define EJS_HTTP_DISPOSED 550 - -/* - * Control structure for one HTTP request structure - */ -typedef struct HTTPControl { - Ejs *ejs; - IWebResp *webResp; - AEECallback *callback; - MprBuf *buf; - EjsVar *thisObj; - char *url; - MprTime requestStarted; - uint timeout; -} HTTPControl; - -/****************************** Forward Declarations **************************/ - -static void cleanup(HTTPControl *hp); -static int createWeb(Ejs *ejs, EjsVar *thisObj); -static void brewCallback(HTTPControl *hp); -static int httpDestructor(Ejs *ejs, EjsVar *vp); -static void httpCallback(HTTPControl *hp, int responseCode); -static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv); - -/******************************************************************************/ -/* - * Constructor - */ - -int ejsHTTPConstructor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 0 && argc != 2) { - ejsError(ejs, EJS_ARG_ERROR, - "Bad usage: HTTP([obj = this, method = onComplete]);"); - return -1; - } - - if (createWeb(ejs, thisObj) < 0) { - return -1; - } - - setCallback(ejs, thisObj, argc, argv); - return 0; -} - -/******************************************************************************/ - -static int createWeb(Ejs *ejs, EjsVar *thisObj) -{ - MprApp *app; - void *web; - - app = mprGetApp(ejs); - - /* - * Create one instance of IWeb for the entire application. Do it here - * so only widgets that require HTTP incurr the overhead. - */ - web = mprGetKeyValue(ejs, "bpWeb"); - if (web == 0) { - if (ISHELL_CreateInstance(app->shell, AEECLSID_WEB, &web) != SUCCESS) { - ejsError(ejs, EJS_IO_ERROR, "Can't create IWEB"); - return -1; - } - } - mprSetKeyValue(ejs, "bpWeb", web); - return 0; -} - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function setCallback(obj, methodString); - */ - -static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc >= 1) { - ejsSetProperty(ejs, thisObj, "obj", argv[0]); - } else { - ejsSetProperty(ejs, thisObj, "obj", thisObj); - } - - if (argc >= 2) { - ejsSetProperty(ejs, thisObj, "method", argv[1]); - } else { - ejsSetPropertyToString(ejs, thisObj, "method", "onComplete"); - } - - return 0; -} - -/******************************************************************************/ -/* - * function fetch(); - */ - -static int fetchProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - HTTPControl *hp; - EjsProperty *pp; - MprApp *app; - IWeb *web; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: fetch(url)"); - return -1; - } - - app = mprGetApp(ejs); - web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); - - /* - * Web options - * - * WEBOPT_USERAGENT (char*) sets user agent - * WEBOPT_HANDLERDATA (void*) - * WEBOPT_CONNECTTIMEOUT (uint) msec - * WEBOPT_CONTENTLENGTH (long) - * WEBOPT_IDLECONNTIMEOUT (int) - * WEBOPT_ACTIVEXACTIONST (uint) Number of active requests - * - * WEBREQUEST_REDIRECT redirect transparently - * - */ - - hp = mprAllocType(ejs, HTTPControl); - if (hp == 0) { - ejsMemoryError(ejs); - return -1; - } - - hp->ejs = ejs; - hp->buf = mprCreateBuf(hp, MPR_BUF_INCR, MPR_MAX_BUF); - if (hp->buf == 0) { - mprFree(hp); - ejsMemoryError(ejs); - return -1; - } - - /* - * We copy thisObj because we need to preserve both the var and the object. - * We pass the var to brewCallback and so it must persist. The call to - * ejsMakeObjPermanent will stop the GC from collecting the object. - */ - hp->thisObj = ejsDupVar(ejs, thisObj, EJS_SHALLOW_COPY); - ejsSetVarName(ejs, hp->thisObj, "internalHttp"); - - /* - * Must keep a reference to the http object - */ - ejsMakeObjPermanent(hp->thisObj, 1); - - /* - * Make a property so we can access the HTTPControl structure from other - * methods. - */ - pp = ejsSetPropertyToPtr(ejs, thisObj, EJS_HTTP_PROPERTY, hp, 0); - ejsMakePropertyEnumerable(pp, 0); - ejsSetObjDestructor(ejs, hp->thisObj, httpDestructor); - - hp->url = mprStrdup(hp, argv[0]->string); - - hp->timeout = ejsGetPropertyAsInteger(ejs, thisObj, "timeout"); - mprGetTime(hp, &hp->requestStarted); - - hp->callback = mprAllocTypeZeroed(hp, AEECallback); - CALLBACK_Init(hp->callback, brewCallback, hp); - - hp->webResp = 0; - IWEB_GetResponse(web, - (web, &hp->webResp, hp->callback, hp->url, - WEBOPT_HANDLERDATA, hp, - WEBOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)", - WEBOPT_CONNECTTIMEOUT, hp->timeout, - WEBOPT_COPYOPTS, TRUE, - WEBOPT_CONTENTLENGTH, 0, - WEBOPT_END)); - - ejsSetPropertyToString(ejs, thisObj, "status", "active"); - - return 0; -} - -/******************************************************************************/ -/* - * Called whenver the http object is deleted. - */ - -static int httpDestructor(Ejs *ejs, EjsVar *thisObj) -{ - HTTPControl *hp; - - /* - * If the httpCallback has run, then this property will not exist - */ - hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); - - if (hp) { - cleanup(hp); - } - - return 0; -} - -/******************************************************************************/ -/* - * Stop the request immediately without calling the callback - */ - -static int stopProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - HTTPControl *hp; - - hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); - - if (hp) { - cleanup(hp); - } - - return 0; -} - -/******************************************************************************/ -/* - * Brew HTTP callback. Invoked for any return data. - */ - -static void brewCallback(HTTPControl *hp) -{ - Ejs *ejs; - EjsVar *thisObj; - ISource *source; - WebRespInfo *info; - char data[MPR_BUF_INCR]; - int bytes; - - mprAssert(hp); - mprAssert(hp->webResp); - - info = IWEBRESP_GetInfo(hp->webResp); - - if (info == 0) { - mprAssert(info); - /* should not happen */ - return; - } - - ejs = hp->ejs; - thisObj = hp->thisObj; - - if (! WEB_ERROR_SUCCEEDED(info->nCode)) { - ejsSetPropertyToString(ejs, thisObj, "status", "error"); - httpCallback(hp, info->nCode); - return; - } - - if (hp->timeout) { - if (mprGetTimeRemaining(hp, hp->requestStarted, hp->timeout) <= 0) { - ejsSetPropertyToString(ejs, thisObj, "status", "timeout"); - httpCallback(hp, 504); - return; - } - } - - /* - * Normal success - */ - source = info->pisMessage; - mprAssert(source); - - bytes = ISOURCE_Read(source, data, sizeof(data)); - - switch (bytes) { - case ISOURCE_WAIT: // No data yet - ISOURCE_Readable(source, hp->callback); - break; - - case ISOURCE_ERROR: - ejsSetPropertyToString(ejs, thisObj, "status", "error"); - httpCallback(hp, info->nCode); - break; - - case ISOURCE_END: - mprAddNullToBuf(hp->buf); - ejsSetPropertyToString(ejs, thisObj, "status", "complete"); - httpCallback(hp, info->nCode); - break; - - default: - if (bytes > 0) { - if (mprPutBlockToBuf(hp->buf, data, bytes) != bytes) { - ejsSetPropertyToString(ejs, thisObj, "status", "partialData"); - httpCallback(hp, 500); - } - } - ISOURCE_Readable(source, hp->callback); - break; - } -} - -/******************************************************************************/ -/* - * Invoke the HTTP completion method - */ - -static void httpCallback(HTTPControl *hp, int responseCode) -{ - Ejs *ejs; - EjsVar *thisObj, *callbackObj; - MprArray *args; - char *msg; - const char *callbackMethod; - - mprAssert(hp); - mprAssert(hp->webResp); - - thisObj = hp->thisObj; - ejs = hp->ejs; - - ejsSetPropertyToInteger(ejs, thisObj, "responseCode", responseCode); - if (mprGetBufLength(hp->buf) > 0) { - ejsSetPropertyToBinaryString(ejs, thisObj, "responseData", - mprGetBufStart(hp->buf), mprGetBufLength(hp->buf)); - } - - callbackObj = ejsGetPropertyAsVar(ejs, thisObj, "obj"); - callbackMethod = ejsGetPropertyAsString(ejs, thisObj, "method"); - - if (callbackObj != 0 && callbackMethod != 0) { - - args = mprCreateItemArray(ejs, EJS_INC_ARGS, EJS_MAX_ARGS); - mprAddItem(args, ejsDupVar(ejs, hp->thisObj, EJS_SHALLOW_COPY)); - - if (ejsRunMethod(ejs, callbackObj, callbackMethod, args) < 0) { - msg = ejsGetErrorMsg(ejs); - mprError(ejs, MPR_LOC, "HTTP callback failed. Details: %s", msg); - } - ejsFreeMethodArgs(ejs, args); - - } else if (ejsRunMethod(ejs, thisObj, "onComplete", 0) < 0) { - msg = ejsGetErrorMsg(ejs); - mprError(ejs, MPR_LOC, "HTTP onComplete failed. Details: %s", msg); - } - - cleanup(hp); -} - -/******************************************************************************/ -/* - * Cleanup - */ - -static void cleanup(HTTPControl *hp) -{ - Ejs *ejs; - MprApp *app; - int rc; - - mprAssert(hp); - mprAssert(hp->webResp); - - ejs = hp->ejs; - - if (hp->webResp) { - rc = IWEBRESP_Release(hp->webResp); - // mprAssert(rc == 0); - hp->webResp = 0; - } - - if (hp->callback) { - CALLBACK_Cancel(hp->callback); - mprFree(hp->callback); - hp->callback = 0; - } - - /* - * Once the property is deleted, then if the destructor runs, it will - * notice that the EJS_HTTP_PROPERTY is undefined. - */ - ejsDeleteProperty(ejs, hp->thisObj, EJS_HTTP_PROPERTY); - - /* - * Allow garbage collection to work on thisObj - */ - ejsMakeObjPermanent(hp->thisObj, 0); - ejsFreeVar(ejs, hp->thisObj); - - mprFree(hp->buf); - mprFree(hp->url); - - mprFree(hp); - - app = mprGetApp(ejs); - - - ISHELL_SendEvent(app->shell, (AEECLSID) app->classId, EVT_USER, 0, 0); -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineHTTPClass(Ejs *ejs) -{ - EjsVar *httpClass; - - httpClass = - ejsDefineClass(ejs, "HTTP", "Object", ejsHTTPConstructor); - if (httpClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ejs, httpClass, "fetch", fetchProc, 0); - ejsDefineCMethod(ejs, httpClass, "stop", stopProc, 0); - ejsDefineCMethod(ejs, httpClass, "setCallback", setCallback, 0); - -#if FUTURE - ejsDefineCMethod(ejs, httpClass, "put", put, 0); - ejsDefineCMethod(ejs, httpClass, "upload", upload, 0); - ejsDefineCMethod(ejs, httpClass, "addUploadFile", addUploadFile, 0); - ejsDefineCMethod(ejs, httpClass, "addPostData", addPostData, 0); - ejsDefineCMethod(ejs, httpClass, "setUserPassword", setUserPassword, 0); - ejsDefineCMethod(ejs, httpClass, "addCookie", addCookie, 0); -#endif - - /* - * Define properties - */ - ejsSetPropertyToString(ejs, httpClass, "status", "inactive"); - - /* This default should come from player.xml */ - - ejsSetPropertyToInteger(ejs, httpClass, "timeout", 30 * 1000); - ejsSetPropertyToInteger(ejs, httpClass, "responseCode", 0); - - return ejsObjHasErrors(httpClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -void ejsTermHTTPClass(Ejs *ejs) -{ - IWeb *web; - int rc; - - web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); - if (web) { - rc = IWEB_Release(web); - mprAssert(rc == 0); - } -} - -#endif -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/.ignore b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/.ignore deleted file mode 100644 index fb5a29031e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/.ignore +++ /dev/null @@ -1 +0,0 @@ -.updated diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/Makefile b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/Makefile deleted file mode 100755 index 424747052a..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# -# Makefile to build the EJS Object Model for WIN -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I../.. -I../../../mpr - -include make.dep - -compileExtra: .updated - -.updated: $(FILES) - @touch .updated - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFile.c b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFile.c deleted file mode 100644 index 24c521891e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFile.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * @file ejsFile.c - * @brief File class for the EJScript System Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/* - * Default Constructor - */ - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function open(); - */ - -static int openProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.open()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function close(); - */ - -static int closeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.close()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function read(); - */ - -static int readProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.read()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function write(); - */ - -static int writeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "File.write()\n"); - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineFileClass(Ejs *ep) -{ - EjsVar *fileClass; - - fileClass = ejsDefineClass(ep, "File", "Object", 0); - if (fileClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ep, fileClass, "open", openProc, 0); - ejsDefineCMethod(ep, fileClass, "close", closeProc, 0); - ejsDefineCMethod(ep, fileClass, "read", readProc, 0); - ejsDefineCMethod(ep, fileClass, "write", writeProc, 0); - - return ejsObjHasErrors(fileClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFileSystem.c b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFileSystem.c deleted file mode 100755 index 66c3b84870..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsFileSystem.c +++ /dev/null @@ -1,456 +0,0 @@ -/* - * @file ejsFileSystem.c - * @brief FileSystem class for the EJ System Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/* - * Default Constructor - */ - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function void access(string path); - * MOB - API insufficient. Access for read or write? - */ - -static int accessProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: access(path)"); - return -1; - } - - rc = access(argv[0]->string, 04); - - ejsSetReturnValueToBoolean(ejs, (rc == 0) ? 1 : 0); - return 0; -} - -/******************************************************************************/ -/* - * function void mkdir(string path); - */ - -static int mkdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); - return -1; - } - - if (mprMakeDirPath(ejs, argv[0]->string) < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create directory"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void rmdir(string path); - */ - -static int rmdirProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: mkdir(path)"); - return -1; - } - - rc = mprDeleteDir(ejs, argv[0]->string); - - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant remove directory"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void dirList(string path, [bool enumDirs]); - * MOB -- need pattern to match (what about "." and ".." and ".*" - */ - -static int dirListProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - WIN32_FIND_DATA findData; - HANDLE h; - char path[MPR_MAX_FNAME]; - EjsVar *array, *vp; - uchar enumDirs; - - if (argc < 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: dirList(path)"); - return -1; - } - if (argc == 2) { - enumDirs = ejsVarToBoolean(argv[1]); - } else { - enumDirs = 0; - } - array = ejsCreateArray(ejs, 0); - ejsMakeObjPermanent(array, 1); - - /* - * First collect the files - */ - mprSprintf(path, sizeof(path), "%s/*.*", argv[0]->string); - h = FindFirstFile(path, &findData); - if (h == INVALID_HANDLE_VALUE) { - ejsError(ejs, EJS_ARG_ERROR, "Can't enumerate dirList(path)"); - return -1; - } - - do { - if (findData.cFileName[0] == '.') { - continue; - } - if (!enumDirs || - (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { - mprSprintf(path, sizeof(path), "%s/%s", argv[0]->string, - findData.cFileName); - vp = ejsCreateStringVar(ejs, path); - ejsAddArrayElt(ejs, array, vp, EJS_SHALLOW_COPY); - ejsFreeVar(ejs, vp); - } - } while (FindNextFile(h, &findData) != 0); - - FindClose(h); - - ejsSetReturnValue(ejs, array); - ejsMakeObjPermanent(array, 0); - - /* - * Can free now as the return value holds the reference - */ - ejsFreeVar(ejs, array); - - return 0; -} - -/******************************************************************************/ -/* - * function void getFreeSpace(); - */ - -static int getFreeSpaceProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ -#if UNUSED - MprApp *app; - uint space; - - app = mprGetApp(ejs); - space = IFILEMGR_GetFreeSpace(app->fileMgr, 0); - ejsSetReturnValueToInteger(ejs, space); -#endif - - return 0; -} - -/******************************************************************************/ -/* - * function void writeFile(string path, var data); - */ - -static int writeFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFile *file; - char *data, *buf; - int bytes, length, rc; - - if (argc != 2 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: writeFile(path, var)"); - return -1; - } - - if (ejsVarIsString(argv[1])) { - data = argv[1]->string; - length = argv[1]->length; - buf = 0; - } else { - buf = data = ejsVarToString(ejs, argv[1]); - length = strlen(data); - } - - /* - * Create fails if already present - */ - rc = mprDelete(ejs, argv[0]->string); - file = mprOpen(ejs, argv[0]->string, O_CREAT | O_WRONLY | O_BINARY, 0664); - if (file == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[0]->string); - mprFree(buf); - return -1; - } - - rc = 0; - bytes = mprWrite(file, data, length); - if (bytes != length) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - } - - mprClose(file); - - mprFree(buf); - return rc; -} - -/******************************************************************************/ -/* - * function string readFile(string path); - */ - -static int readFileProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprApp *app; - MprFile *file; - MprBuf *buf; - char *data; - int bytes, rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: readFile(path)"); - return -1; - } - buf = mprCreateBuf(ejs, MPR_BUF_INCR, MPR_MAX_BUF); - if (buf == 0) { - ejsMemoryError(ejs); - return -1; - } - - data = mprAlloc(ejs, MPR_BUFSIZE); - if (buf == 0) { - mprFree(buf); - ejsMemoryError(ejs); - return -1; - } - - app = mprGetApp(ejs); - file = mprOpen(ejs, argv[0]->string, O_RDONLY, 0664); - if (file == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); - mprFree(buf); - return -1; - } - - rc = 0; - while ((bytes = mprRead(file, data, MPR_BUFSIZE)) > 0) { - if (mprPutBlockToBuf(buf, data, bytes) != bytes) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - break; - } - } - - ejsSetReturnValueToBinaryString(ejs, mprGetBufStart(buf), - mprGetBufLength(buf)); - - mprClose(file); - mprFree(data); - mprFree(buf); - - return rc; -} - -/******************************************************************************/ -/* - * function void remove(string path); - */ - -static int removeProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: remove(path)"); - return -1; - } - - rc = unlink(argv[0]->string); - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant remove file"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void rename(string from, string to); - */ - -static int renameProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int rc; - - if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: rename(old, new)"); - return -1; - } - - unlink(argv[1]->string); - rc = rename(argv[0]->string, argv[1]->string); - if (rc < 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant rename file"); - return -1; - } - return 0; -} - -/******************************************************************************/ -/* - * function void copy(string old, string new); - */ - -static int copyProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFile *from, *to; - char *buf; - int bytes, rc; - - if (argc != 2 || !ejsVarIsString(argv[0]) || !ejsVarIsString(argv[1])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: copy(old, new)"); - return -1; - } - - buf = mprAlloc(ejs, MPR_BUFSIZE); - if (buf == 0) { - ejsMemoryError(ejs); - return -1; - } - - from = mprOpen(ejs, argv[0]->string, O_RDONLY | O_BINARY, 0664); - if (from == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant open %s", argv[0]->string); - mprFree(buf); - return -1; - } - - to = mprOpen(ejs, argv[1]->string, O_CREAT | O_BINARY, 0664); - if (to == 0) { - ejsError(ejs, EJS_IO_ERROR, "Cant create %s", argv[1]->string); - mprClose(from); - mprFree(buf); - return -1; - } - - rc = 0; - while ((bytes = mprRead(from, buf, MPR_BUFSIZE)) > 0) { - if (mprWrite(to, buf, bytes) != bytes) { - ejsError(ejs, EJS_IO_ERROR, "Write error to %s", argv[1]->string); - rc = -1; - break; - } - } - - mprClose(from); - mprClose(to); - mprFree(buf); - - return rc; -} - -/******************************************************************************/ -/* - * function FileInfo getFileInfo(string path); - * - * MOB -- should create a real class FileInfo - */ - -static int getFileInfoProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprFileInfo info; - EjsVar *fileInfo; - int rc; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: getFileInfo(path)"); - return -1; - } - - fileInfo = ejsCreateObjVar(ejs); - if (fileInfo == 0) { - ejsMemoryError(ejs); - return -1; - } - ejsMakeObjPermanent(fileInfo, 1); - - rc = mprGetFileInfo(ejs, argv[0]->string, &info); - if (rc < 0) { - ejsMakeObjPermanent(fileInfo, 0); - ejsFreeVar(ejs, fileInfo); - ejsError(ejs, EJS_IO_ERROR, "Cant get file info for %s", - argv[0]->string); - return -1; - } - - ejsSetPropertyToInteger(ejs, fileInfo, "created", info.ctime); - ejsSetPropertyToInteger(ejs, fileInfo, "length", info.size); - ejsSetPropertyToBoolean(ejs, fileInfo, "isDir", info.isDir); - - ejsSetReturnValue(ejs, fileInfo); - ejsMakeObjPermanent(fileInfo, 0); - - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineFileSystemClass(Ejs *ejs) -{ - EjsVar *fileSystemClass; - - fileSystemClass = ejsDefineClass(ejs, "FileSystem", "Object", 0); - if (fileSystemClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ejs, fileSystemClass, "access", accessProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "mkdir", mkdirProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "rmdir", rmdirProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "dirList", dirListProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "writeFile", writeFileProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "readFile", readFileProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "remove", removeProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "rename", renameProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "copy", copyProc, 0); - ejsDefineCMethod(ejs, fileSystemClass, "getFileInfo", getFileInfoProc, 0); - - // MOB -- should be a property with accessor - ejsDefineCMethod(ejs, fileSystemClass, "getFreeSpace", getFreeSpaceProc, 0); - - return ejsObjHasErrors(fileSystemClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c b/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c deleted file mode 100755 index 25821f6960..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/WIN/ejsHTTP.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * @file ejsHTTP.c - * @brief HTTP class for the EJ System Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if UNUSED -/*********************************** Defines **********************************/ - -#define EJS_WEB_PROPERTY "-web" -#define EJS_HTTP_PROPERTY "-http" - -#define EJS_HTTP_DISPOSED 550 - -/* - * Control structure for one HTTP request structure - */ -typedef struct HTTPControl { - Ejs *ejs; - IWebResp *webResp; - AEECallback *callback; - MprBuf *buf; - EjsVar *thisObj; - char *url; - MprTime requestStarted; - uint timeout; -} HTTPControl; - -/****************************** Forward Declarations **************************/ - -static void cleanup(HTTPControl *hp); -static int createWeb(Ejs *ejs, EjsVar *thisObj); -static void brewCallback(HTTPControl *hp); -static int httpDestructor(Ejs *ejs, EjsVar *vp); -static void httpCallback(HTTPControl *hp, int responseCode); -static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv); - -/******************************************************************************/ -/* - * Constructor - */ - -int ejsHTTPConstructor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 0 && argc != 2) { - ejsError(ejs, EJS_ARG_ERROR, - "Bad usage: HTTP([obj = this, method = onComplete]);"); - return -1; - } - - if (createWeb(ejs, thisObj) < 0) { - return -1; - } - - setCallback(ejs, thisObj, argc, argv); - return 0; -} - -/******************************************************************************/ - -static int createWeb(Ejs *ejs, EjsVar *thisObj) -{ - MprApp *app; - void *web; - - app = mprGetApp(ejs); - - /* - * Create one instance of IWeb for the entire application. Do it here - * so only widgets that require HTTP incurr the overhead. - */ - web = mprGetKeyValue(ejs, "bpWeb"); - if (web == 0) { - if (ISHELL_CreateInstance(app->shell, AEECLSID_WEB, &web) != SUCCESS) { - ejsError(ejs, EJS_IO_ERROR, "Can't create IWEB"); - return -1; - } - } - mprSetKeyValue(ejs, "bpWeb", web); - return 0; -} - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function setCallback(obj, methodString); - */ - -static int setCallback(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc >= 1) { - ejsSetProperty(ejs, thisObj, "obj", argv[0]); - } else { - ejsSetProperty(ejs, thisObj, "obj", thisObj); - } - - if (argc >= 2) { - ejsSetProperty(ejs, thisObj, "method", argv[1]); - } else { - ejsSetPropertyToString(ejs, thisObj, "method", "onComplete"); - } - - return 0; -} - -/******************************************************************************/ -/* - * function fetch(); - */ - -static int fetchProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - HTTPControl *hp; - EjsProperty *pp; - MprApp *app; - IWeb *web; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsError(ejs, EJS_ARG_ERROR, "Bad usage: fetch(url)"); - return -1; - } - - app = mprGetApp(ejs); - web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); - - /* - * Web options - * - * WEBOPT_USERAGENT (char*) sets user agent - * WEBOPT_HANDLERDATA (void*) - * WEBOPT_CONNECTTIMEOUT (uint) msec - * WEBOPT_CONTENTLENGTH (long) - * WEBOPT_IDLECONNTIMEOUT (int) - * WEBOPT_ACTIVEXACTIONST (uint) Number of active requests - * - * WEBREQUEST_REDIRECT redirect transparently - * - */ - - hp = mprAllocType(ejs, HTTPControl); - if (hp == 0) { - ejsMemoryError(ejs); - return -1; - } - - hp->ejs = ejs; - hp->buf = mprCreateBuf(hp, MPR_BUF_INCR, MPR_MAX_BUF); - if (hp->buf == 0) { - mprFree(hp); - ejsMemoryError(ejs); - return -1; - } - - /* - * We copy thisObj because we need to preserve both the var and the object. - * We pass the var to brewCallback and so it must persist. The call to - * ejsMakeObjPermanent will stop the GC from collecting the object. - */ - hp->thisObj = ejsDupVar(ejs, thisObj, EJS_SHALLOW_COPY); - ejsSetVarName(ejs, hp->thisObj, "internalHttp"); - - /* - * Must keep a reference to the http object - */ - ejsMakeObjPermanent(hp->thisObj, 1); - - /* - * Make a property so we can access the HTTPControl structure from other - * methods. - */ - pp = ejsSetPropertyToPtr(ejs, thisObj, EJS_HTTP_PROPERTY, hp, 0); - ejsMakePropertyEnumerable(pp, 0); - ejsSetObjDestructor(ejs, hp->thisObj, httpDestructor); - - hp->url = mprStrdup(hp, argv[0]->string); - - hp->timeout = ejsGetPropertyAsInteger(ejs, thisObj, "timeout"); - mprGetTime(hp, &hp->requestStarted); - - hp->callback = mprAllocTypeZeroed(hp, AEECallback); - CALLBACK_Init(hp->callback, brewCallback, hp); - - hp->webResp = 0; - IWEB_GetResponse(web, - (web, &hp->webResp, hp->callback, hp->url, - WEBOPT_HANDLERDATA, hp, - WEBOPT_USERAGENT, "Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 5.0)", - WEBOPT_CONNECTTIMEOUT, hp->timeout, - WEBOPT_COPYOPTS, TRUE, - WEBOPT_CONTENTLENGTH, 0, - WEBOPT_END)); - - ejsSetPropertyToString(ejs, thisObj, "status", "active"); - - return 0; -} - -/******************************************************************************/ -/* - * Called whenver the http object is deleted. - */ - -static int httpDestructor(Ejs *ejs, EjsVar *thisObj) -{ - HTTPControl *hp; - - /* - * If the httpCallback has run, then this property will not exist - */ - hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); - - if (hp) { - cleanup(hp); - } - - return 0; -} - -/******************************************************************************/ -/* - * Stop the request immediately without calling the callback - */ - -static int stopProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - HTTPControl *hp; - - hp = ejsGetPropertyAsPtr(ejs, thisObj, EJS_HTTP_PROPERTY); - - if (hp) { - cleanup(hp); - } - - return 0; -} - -/******************************************************************************/ -/* - * Brew HTTP callback. Invoked for any return data. - */ - -static void brewCallback(HTTPControl *hp) -{ - Ejs *ejs; - EjsVar *thisObj; - ISource *source; - WebRespInfo *info; - char data[MPR_BUF_INCR]; - int bytes; - - mprAssert(hp); - mprAssert(hp->webResp); - - info = IWEBRESP_GetInfo(hp->webResp); - - if (info == 0) { - mprAssert(info); - /* should not happen */ - return; - } - - ejs = hp->ejs; - thisObj = hp->thisObj; - - if (! WEB_ERROR_SUCCEEDED(info->nCode)) { - ejsSetPropertyToString(ejs, thisObj, "status", "error"); - httpCallback(hp, info->nCode); - return; - } - - if (hp->timeout) { - if (mprGetTimeRemaining(hp, hp->requestStarted, hp->timeout) <= 0) { - ejsSetPropertyToString(ejs, thisObj, "status", "timeout"); - httpCallback(hp, 504); - return; - } - } - - /* - * Normal success - */ - source = info->pisMessage; - mprAssert(source); - - bytes = ISOURCE_Read(source, data, sizeof(data)); - - switch (bytes) { - case ISOURCE_WAIT: // No data yet - ISOURCE_Readable(source, hp->callback); - break; - - case ISOURCE_ERROR: - ejsSetPropertyToString(ejs, thisObj, "status", "error"); - httpCallback(hp, info->nCode); - break; - - case ISOURCE_END: - mprAddNullToBuf(hp->buf); - ejsSetPropertyToString(ejs, thisObj, "status", "complete"); - httpCallback(hp, info->nCode); - break; - - default: - if (bytes > 0) { - if (mprPutBlockToBuf(hp->buf, data, bytes) != bytes) { - ejsSetPropertyToString(ejs, thisObj, "status", "partialData"); - httpCallback(hp, 500); - } - } - ISOURCE_Readable(source, hp->callback); - break; - } -} - -/******************************************************************************/ -/* - * Invoke the HTTP completion method - */ - -static void httpCallback(HTTPControl *hp, int responseCode) -{ - Ejs *ejs; - EjsVar *thisObj, *callbackObj; - MprArray *args; - char *msg; - const char *callbackMethod; - - mprAssert(hp); - mprAssert(hp->webResp); - - thisObj = hp->thisObj; - ejs = hp->ejs; - - ejsSetPropertyToInteger(ejs, thisObj, "responseCode", responseCode); - if (mprGetBufLength(hp->buf) > 0) { - ejsSetPropertyToBinaryString(ejs, thisObj, "responseData", - mprGetBufStart(hp->buf), mprGetBufLength(hp->buf)); - } - - callbackObj = ejsGetPropertyAsVar(ejs, thisObj, "obj"); - callbackMethod = ejsGetPropertyAsString(ejs, thisObj, "method"); - - if (callbackObj != 0 && callbackMethod != 0) { - - args = mprCreateItemArray(ejs, EJS_INC_ARGS, EJS_MAX_ARGS); - mprAddItem(args, ejsDupVar(ejs, hp->thisObj, EJS_SHALLOW_COPY)); - - if (ejsRunMethod(ejs, callbackObj, callbackMethod, args) < 0) { - msg = ejsGetErrorMsg(ejs); - mprError(ejs, MPR_LOC, "HTTP callback failed. Details: %s", msg); - } - ejsFreeMethodArgs(ejs, args); - - } else if (ejsRunMethod(ejs, thisObj, "onComplete", 0) < 0) { - msg = ejsGetErrorMsg(ejs); - mprError(ejs, MPR_LOC, "HTTP onComplete failed. Details: %s", msg); - } - - cleanup(hp); -} - -/******************************************************************************/ -/* - * Cleanup - */ - -static void cleanup(HTTPControl *hp) -{ - Ejs *ejs; - MprApp *app; - int rc; - - mprAssert(hp); - mprAssert(hp->webResp); - - ejs = hp->ejs; - - if (hp->webResp) { - rc = IWEBRESP_Release(hp->webResp); - // mprAssert(rc == 0); - hp->webResp = 0; - } - - if (hp->callback) { - CALLBACK_Cancel(hp->callback); - mprFree(hp->callback); - hp->callback = 0; - } - - /* - * Once the property is deleted, then if the destructor runs, it will - * notice that the EJS_HTTP_PROPERTY is undefined. - */ - ejsDeleteProperty(ejs, hp->thisObj, EJS_HTTP_PROPERTY); - - /* - * Allow garbage collection to work on thisObj - */ - ejsMakeObjPermanent(hp->thisObj, 0); - ejsFreeVar(ejs, hp->thisObj); - - mprFree(hp->buf); - mprFree(hp->url); - - mprFree(hp); - - app = mprGetApp(ejs); - - - ISHELL_SendEvent(app->shell, (AEECLSID) app->classId, EVT_USER, 0, 0); -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineHTTPClass(Ejs *ejs) -{ - EjsVar *httpClass; - - httpClass = - ejsDefineClass(ejs, "HTTP", "Object", ejsHTTPConstructor); - if (httpClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the methods - */ - ejsDefineCMethod(ejs, httpClass, "fetch", fetchProc, 0); - ejsDefineCMethod(ejs, httpClass, "stop", stopProc, 0); - ejsDefineCMethod(ejs, httpClass, "setCallback", setCallback, 0); - -#if FUTURE - ejsDefineCMethod(ejs, httpClass, "put", put, 0); - ejsDefineCMethod(ejs, httpClass, "upload", upload, 0); - ejsDefineCMethod(ejs, httpClass, "addUploadFile", addUploadFile, 0); - ejsDefineCMethod(ejs, httpClass, "addPostData", addPostData, 0); - ejsDefineCMethod(ejs, httpClass, "setUserPassword", setUserPassword, 0); - ejsDefineCMethod(ejs, httpClass, "addCookie", addCookie, 0); -#endif - - /* - * Define properties - */ - ejsSetPropertyToString(ejs, httpClass, "status", "inactive"); - - /* This default should come from player.xml */ - - ejsSetPropertyToInteger(ejs, httpClass, "timeout", 30 * 1000); - ejsSetPropertyToInteger(ejs, httpClass, "responseCode", 0); - - return ejsObjHasErrors(httpClass) ? MPR_ERR_CANT_INITIALIZE: 0; -} - -/******************************************************************************/ - -void ejsTermHTTPClass(Ejs *ejs) -{ - IWeb *web; - int rc; - - web = (IWeb*) mprGetKeyValue(ejs, "bpWeb"); - if (web) { - rc = IWEB_Release(web); - mprAssert(rc == 0); - } -} - -#endif -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsGC.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsGC.c deleted file mode 100644 index 411975f80e..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsGC.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * @file ejsGC.c - * @brief Garbage collector class for the EJS Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -#if (WIN || BREW_SIMULATOR) && BLD_DEBUG - -static int checkProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - _CrtCheckMemory(); - return 0; -} - -#endif -/******************************************************************************/ - -static int debugProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "Bad args: debug(debugLevel)"); - return -1; - } - - ejsSetGCDebugLevel(ep, ejsVarToInteger(argv[0])); - return 0; -} - -/******************************************************************************/ -/* - * Print stats and dump objects - */ - -static int printStatsProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - bool leakStats; - - if (argc > 1) { - leakStats = ejsVarToInteger(argv[0]); - } else { - leakStats = 0; - } - -#if BLD_FEATURE_ALLOC_STATS - ejsPrintAllocReport(ep, 0); - - mprPrintAllocReport(mprGetApp(ep), leakStats, 0); -#endif - -#if BLD_DEBUG - ejsDumpObjects(ep); -#endif - - return 0; -} - -/******************************************************************************/ - -static int runProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc > 1) { - ejsError(ep, EJS_ARG_ERROR, "Bad args: run([quick])"); - return -1; - } - - if (argc == 1) { - ejsIncrementalCollectGarbage(ep); - } else { - ejsCollectGarbage(ep, -1); - } - return 0; -} - -/******************************************************************************/ - -static int usedMemoryProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ep, ejsGetUsedMemory(ep)); - return 0; -} - -/******************************************************************************/ - -static int allocatedMemoryProc(Ejs *ep, EjsVar *thisObj, int argc, - EjsVar **argv) -{ -#if BLD_FEATURE_ALLOC_STATS - ejsSetReturnValueToInteger(ep, ejsGetAllocatedMemory(ep)); -#endif - return 0; -} - -/******************************************************************************/ - -static int mprMemoryProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ -#if BLD_FEATURE_ALLOC_STATS - ejsSetReturnValueToInteger(ep, mprGetAllocatedMemory(ep)); -#endif - return 0; -} - -/******************************************************************************/ - -static int peakMprMemoryProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ -#if BLD_FEATURE_ALLOC_STATS - ejsSetReturnValueToInteger(ep, mprGetPeakAllocatedMemory(ep)); -#endif - return 0; -} - -/******************************************************************************/ - -static int getDebugLevel(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ep, ep->gc.debugLevel); - return 0; -} - -/******************************************************************************/ - -static int setDebugLevel(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - ep->gc.debugLevel= ejsVarToInteger(argv[0]); - return 0; -} - -/******************************************************************************/ - -static int getEnable(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToBoolean(ep, ep->gc.enable); - return 0; -} - -/******************************************************************************/ - -static int setEnable(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - ep->gc.enable= ejsVarToBoolean(argv[0]); - return 0; -} - -/******************************************************************************/ - -static int getDemandCollect(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToBoolean(ep, ep->gc.enableDemandCollect); - return 0; -} - -/******************************************************************************/ - -static int setDemandCollect(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - ep->gc.enableDemandCollect = ejsVarToBoolean(argv[0]); - return 0; -} - -/******************************************************************************/ - -static int getIdleCollect(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToBoolean(ep, ep->gc.enableIdleCollect); - return 0; -} - -/******************************************************************************/ - -static int setIdleCollect(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - ep->gc.enableIdleCollect = ejsVarToBoolean(argv[0]); - return 0; -} - -/******************************************************************************/ - -static int getWorkQuota(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ep, ep->gc.workQuota); - return 0; -} - -/******************************************************************************/ - -static int setWorkQuota(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int quota; - - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - quota = ejsVarToInteger(argv[0]); - if (quota < EJS_GC_MIN_WORK_QUOTA && quota != 0) { - ejsArgError(ep, "Bad work quota"); - return -1; - } - - ep->gc.workQuota = quota; - return 0; -} - -/******************************************************************************/ - -static int getMaxMemory(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ep, ep->gc.maxMemory); - return 0; -} - -/******************************************************************************/ - -static int setMaxMemory(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int maxMemory; - - if (argc != 1) { - ejsArgError(ep, "Bad arguments"); - return -1; - } - maxMemory = ejsVarToInteger(argv[0]); - if (maxMemory < 0) { - ejsArgError(ep, "Bad maxMemory"); - return -1; - } - - ep->gc.maxMemory = maxMemory; - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineGCClass(Ejs *ep) -{ - EjsVar *gcClass; - int flags; - - flags = EJS_NO_LOCAL; - - /* - * NOTE: We create the GC class and define static methods on it. There - * is no object instance - */ - gcClass = ejsDefineClass(ep, "System.GC", "Object", 0); - if (gcClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * MOB -- convert these to properties with accessors when available - */ - ejsDefineCMethod(ep, gcClass, "printStats", printStatsProc, flags); - ejsDefineCMethod(ep, gcClass, "run", runProc, flags); - - ejsDefineCMethod(ep, gcClass, "getUsedMemory", usedMemoryProc, flags); - ejsDefineCMethod(ep, gcClass, "getAllocatedMemory", allocatedMemoryProc, - flags); - ejsDefineCMethod(ep, gcClass, "getMprMemory", mprMemoryProc, flags); - ejsDefineCMethod(ep, gcClass, "getPeakMprMemory", peakMprMemoryProc, flags); - ejsDefineCMethod(ep, gcClass, "debug", debugProc, flags); - -#if (WIN || BREW_SIMULATOR) && BLD_DEBUG - ejsDefineCMethod(ep, gcClass, "check", checkProc, flags); -#endif - - ejsDefineCAccessors(ep, gcClass, "debugLevel", - getDebugLevel, setDebugLevel, flags); - - ejsDefineCAccessors(ep, gcClass, "enable", - getEnable, setEnable, flags); - - ejsDefineCAccessors(ep, gcClass, "demandCollect", - getDemandCollect, setDemandCollect, flags); - - ejsDefineCAccessors(ep, gcClass, "idleCollect", - getIdleCollect, setIdleCollect, flags); - - ejsDefineCAccessors(ep, gcClass, "workQuota", - getWorkQuota, setWorkQuota, flags); - - ejsDefineCAccessors(ep, gcClass, "maxMemory", - getMaxMemory, setMaxMemory, flags); - - return ejsObjHasErrors(gcClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsGlobal.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsGlobal.c deleted file mode 100755 index 6ab8f867e1..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsGlobal.c +++ /dev/null @@ -1,785 +0,0 @@ -/* - * @file ejsGlobal.c - * @brief EJS support methods - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -#if BLD_FEATURE_EJS - -/******************************************************************************/ -/************************************* Code ***********************************/ -/******************************************************************************/ -/* - * assert(condition) - */ - -static int assertProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int b; - - if (argc < 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: assert(condition)"); - return -1; - } - b = ejsVarToBoolean(argv[0]); - if (b == 0) { - ejsError(ep, EJS_ASSERT_ERROR, "Assertion failure at line %d", - ejsGetLineNumber(ep)); - return -1; - } - ejsWriteVarAsBoolean(ep, ep->result, b); - return 0; -} - -/******************************************************************************/ -/* - * breakpoint(msg) - */ - -static int breakpointProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *buf; - - if (argc < 1) { - return 0; - } - buf = ejsVarToString(ep, argv[0]); - if (buf) { - mprBreakpoint(0, buf); - } - return 0; -} - -/******************************************************************************/ -/* - * basename(path) - */ - -static int basenameProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *path; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: basename(path)"); - return -1; - } - - path = ejsVarToString(ep, argv[0]); - if (path == 0) { - return MPR_ERR_MEMORY; - } - ejsSetReturnValueToString(ep, mprGetBaseName(path)); - - return 0; -} - -/******************************************************************************/ -/* - * stripext(path) - */ - -static int stripextProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *cp, *path, *stripPath; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: stripext(path)"); - return -1; - } - - path = ejsVarToString(ep, argv[0]); - if (path == 0) { - return MPR_ERR_MEMORY; - } - stripPath = mprStrdup(ep, path); - - if ((cp = strrchr(stripPath, '.')) != 0) { - *cp = '\0'; - } - - ejsSetReturnValueToString(ep, stripPath); - - mprFree(stripPath); - - return 0; -} - -/******************************************************************************/ -/* - * dirname(path) - */ - -static int dirnameProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *path; - char dirname[MPR_MAX_FNAME]; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: dirname(path)"); - return -1; - } - - path = ejsVarToString(ep, argv[0]); - if (path == 0) { - return MPR_ERR_MEMORY; - } - - ejsSetReturnValueToString(ep, - mprGetDirName(dirname, sizeof(dirname), path)); - - return 0; -} - -/******************************************************************************/ -/* - * trim(string) -- trim white space - */ - -static int trimProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *str, *buf, *cp; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: trim(string)"); - return -1; - } - - str = ejsVarToString(ep, argv[0]); - if (str == 0) { - return MPR_ERR_MEMORY; - } - str = buf = mprStrdup(ep, str); - - while (isspace(*str)) { - str++; - } - cp = &str[strlen(str) - 1]; - while (cp >= str) { - if (isspace(*cp)) { - *cp = '\0'; - } else { - break; - } - cp--; - } - - ejsSetReturnValueToString(ep, str); - - mprFree(buf); - - return 0; -} - -/******************************************************************************/ -/* - * Terminate the script - */ - -static int exitScript(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int status; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "usage: exit(status)"); - return -1; - } - status = (int) ejsVarToInteger(argv[0]); - ejsExit(ep, status); - - ejsWriteVarAsString(ep, ep->result, ""); - return 0; -} - -/******************************************************************************/ -/* - * include javascript libraries. - */ - -static int includeProc(Ejs *ep, EjsVar *thisObj, int argc, char **argv) -{ - int i; - - mprAssert(argv); - - for (i = 0; i < argc; i++) { - if (ejsEvalFile(ep, argv[i], 0) < 0) { - return -1; - } - } - return 0; -} - -/******************************************************************************/ -/* - * include javascript libraries at the global level - */ - -static int includeGlobalProc(Ejs *ep, EjsVar *thisObj, int argc, char **argv) -{ - int fid, i; - - mprAssert(argv); - - /* - * Create a new block and set the context to be the global scope - */ - fid = ejsSetBlock(ep, ep->global); - - for (i = 0; i < argc; i++) { - if (ejsEvalFile(ep, argv[i], 0) < 0) { - ejsCloseBlock(ep, fid); - return -1; - } - } - ejsCloseBlock(ep, fid); - return 0; -} - -/******************************************************************************/ -#if BLD_DEBUG -/* - * Print variables to stdout - */ - -static int printvProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *vp; - char *buf; - int i; - - for (i = 0; i < argc; ) { - vp = argv[i++]; - - /* mprPrintf(ep, "arg[%d] = ", i); */ - - buf = ejsVarToString(ep, vp); - - if (vp->propertyName == 0 || *vp->propertyName == '\0') { - mprPrintf(ep, "%s: ", buf); - - } else if (i < argc) { - mprPrintf(ep, "%s = %s, ", vp->propertyName, buf); - } else { - mprPrintf(ep, "%s = %s\n", vp->propertyName, buf); - } - } - return 0; -} - -#endif -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *buf; - int i; - - for (i = 0; i < argc; i++) { - buf = ejsVarToString(ep, argv[i]); - mprPrintf(ep, "%s", buf); - } - return 0; -} - -/******************************************************************************/ -/* - * println - */ - -static int printlnProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - printProc(ep, thisObj, argc, argv); - mprPrintf(ep, "\n"); - return 0; -} - -/******************************************************************************/ -#if FUTURE -/* - * sprintf - */ - -static int sprintfProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - va_list ap; - char *buf; - void **args; - int result; - - if (argc <= 1) { - ejsError(ep, EJS_ARG_ERROR, "Usage: sprintf(fmt, [args ...])"); - return -1; - } - - args = mprAlloc(ep, sizeof(void*) * (argc - 1)); - if (args == 0) { - mprAssert(args); - return -1; - } - - for (i = 1; i < argc; i++) { - args[i - 1] = argv[i]); - } - - va_start(ap, fmt); - *buf = 0; - result = inner(0, &buf, MPR_MAX_STRING, fmt, args); - va_end(ap); - - ejsSetReturnValueToString(ep, buf); - - mprFree(buf); - return 0; -} - -/******************************************************************************/ - -inner(const char *fmt, void **args) -{ - va_list ap; - - va_start(ap, fmt); - *buf = 0; - mprSprintfCore(ctx, &buf, maxSize, fmt, ap, MPR_PRINTF_ARGV); - va_end(ap); -} - -#endif -/******************************************************************************/ -/* - * sleep - */ - -static int sleepProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "Usage: sleep(milliseconds)"); - return -1; - } - mprSleep(ep, ejsVarToInteger(argv[0])); - return 0; -} - -/******************************************************************************/ -/* - * sort properties - * FUTURE -- should have option to sort object based on a given property value - * ascending or descending - * Usage: sort(object, order = ascending, property = 0); - */ - -static int sortProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *property; - int error, order; - - error = 0; - property = 0; - - /* - * Default order is increasing - */ - order = 1; - - if (argc < 1 || argc > 3 || !ejsVarIsObject(argv[0])) { - error++; - } - - if (argc >= 2) { - order = ejsVarToInteger(argv[1]); - } - - /* - * If property is not defined, it sorts the properties in the object - */ - if (argc == 3) { - if (! ejsVarIsString(argv[2])) { - error++; - } else { - property = argv[2]->string; - } - } - - if (error) { - ejsError(ep, EJS_ARG_ERROR, "Usage: sort(object, [order], [property])"); - return -1; - } - ejsSortProperties(ep, argv[0], 0, property, order); - return 0; -} - -/******************************************************************************/ -/* - * Get a time mark - * MOB -- WARNING: this can overflow. OK on BREW, but other O/Ss it may have - * overflowed on the first call. It should be renamed. - * MOB -- replace with proper Date. - */ - -static int timeProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - MprTime now; - - mprGetTime(ep, &now); -#if WIN || LINUX || SOLARIS -{ - /* MOB -- poor hack */ - static MprTime initial; - if (initial.sec == 0) { - initial = now; - } - now.sec -= initial.sec; - - if (initial.msec > now.msec) { - now.msec = now.msec + 1000 - initial.msec; - now.sec--; - } else { - now.msec -= initial.msec; - } -} -#endif - /* MOB -- this can overflow */ - ejsSetReturnValueToInteger(ep, now.sec * 1000 + now.msec); - return 0; -} - -/******************************************************************************/ -/* - * MOB -- Temporary Get the date (time since Jan 6, 1980 GMT - */ - -static int dateProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ -#if BREW - uint now; - - now = GETTIMESECONDS(); - ejsSetReturnValueToInteger(ep, now); -#endif - return 0; -} - -/******************************************************************************/ -/* - * strlen(string) - */ - -static int strlenProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *buf; - int len; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "Usage: strlen(var)"); - return -1; - } - - len = 0; - if (! ejsVarIsString(argv[0])) { - buf = ejsVarToString(ep, argv[0]); - if (buf) { - len = strlen(buf); - } - - } else { - len = argv[0]->length; - } - - ejsSetReturnValueToInteger(ep, len); - return 0; -} - -/******************************************************************************/ -/* - * toint(num) - */ - -static int tointProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int i; - - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "Usage: toint(number)"); - return -1; - } - - i = ejsVarToInteger(argv[0]); - - ejsSetReturnValueToInteger(ep, i); - return 0; -} - -/******************************************************************************/ -/* - * string strstr(string, pat) - */ - -static int strstrProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - char *str, *pat; - char *s; - int strAlloc; - - if (argc != 2) { - ejsError(ep, EJS_ARG_ERROR, "Usage: strstr(string, pat)"); - return -1; - } - - str = ejsVarToString(ep, argv[0]); - - strAlloc = ep->castAlloc; - ep->castTemp = 0; - - pat = ejsVarToString(ep, argv[1]); - - s = strstr(str, pat); - - if (s == 0) { - ejsSetReturnValueToUndefined(ep); - } else { - ejsSetReturnValueToString(ep, s); - } - - if (strAlloc) { - mprFree(str); - } - - return 0; -} - -/******************************************************************************/ -/* - * Trace - */ - -static int traceProc(Ejs *ep, EjsVar *thisObj, int argc, char **argv) -{ - if (argc == 1) { - mprLog(ep, 0, "%s", argv[0]); - - } else if (argc == 2) { - mprLog(ep, atoi(argv[0]), "%s", argv[1]); - - } else { - ejsError(ep, EJS_ARG_ERROR, "Usage: trace([level], message)"); - return -1; - } - ejsWriteVarAsString(ep, ep->result, ""); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a sub-script. It is evaluated in the same variable scope as - * the calling script / method. - */ - -static int evalScriptProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - EjsVar *arg; - int i; - - ejsWriteVarAsUndefined(ep, ep->result); - - for (i = 0; i < argc; i++) { - arg = argv[i]; - if (arg->type != EJS_TYPE_STRING) { - continue; - } - if (ejsEvalScript(ep, arg->string, 0) < 0) { - return -1; - } - } - /* - * Return with the value of the last expression - */ - return 0; -} - -/******************************************************************************/ - -/* MOB -- need a real datatype returning int, int64, etc */ - -static int typeofProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const struct { - EjsType type; - const char *name; - } types[] = { - { EJS_TYPE_UNDEFINED, "undefined" }, -#if EJS_ECMA_STND - { EJS_TYPE_NULL, "object" }, -#else - { EJS_TYPE_NULL, "null" }, -#endif - { EJS_TYPE_BOOL, "boolean" }, - { EJS_TYPE_CMETHOD, "function" }, - { EJS_TYPE_FLOAT, "number" }, - { EJS_TYPE_INT, "number" }, - { EJS_TYPE_INT64, "number" }, - { EJS_TYPE_OBJECT, "object" }, - { EJS_TYPE_METHOD, "function" }, - { EJS_TYPE_STRING, "string" }, - { EJS_TYPE_STRING_CMETHOD, "function" }, - { EJS_TYPE_PTR, "pointer" } - }; - const char *type; - int i; - - type = NULL; - if (argc != 1) { - ejsError(ep, EJS_ARG_ERROR, "Bad args: typeof(var)"); - return -1; - } - - for (i = 0; i < MPR_ARRAY_SIZE(types); i++) { - if (argv[0]->type == types[i].type) { - type = types[i].name; - break; - } - } - if (type == NULL) { - mprAssert(type); - return -1; - } - - ejsSetReturnValueToString(ep, type); - return 0; -} - -/******************************************************************************/ -/* - * Define the standard properties and methods inherited by all interpreters - * Obj is set to the global class in the default interpreter. When an - * interpreter attempts to write to any property, a copy will be written - * into the interpeters own global space. This is like a "copy-on-write". - */ - -int ejsDefineGlobalProperties(Ejs *ep) -{ - EjsVar *obj; - - obj = ep->service->globalClass; - mprAssert(obj); - - ejsSetPropertyToNull(ep, obj, "null"); - ejsSetPropertyToUndefined(ep, obj, "undefined"); - ejsSetPropertyToBoolean(ep, obj, "true", 1); - ejsSetPropertyToBoolean(ep, obj, "false", 0); - -#if BLD_FEATURE_FLOATING_POINT - { - /* MOB. Fix. This generates warnings on some systems. - This is intended. */ - double d = 0.0; - double e = 0.0; - ejsSetPropertyToFloat(ep, obj, "NaN", e / d); - - d = MAX_FLOAT; - ejsSetPropertyToFloat(ep, obj, "Infinity", d * d); - } -#endif - -#if BLD_FEATURE_LEGACY_API - /* - * DEPRECATED: 2.0. - * So that ESP/ASP can ignore "language=javascript" statements - */ - ejsSetPropertyToInteger(ep, obj, "javascript", 0); -#endif - - /* - * Extension methods. We go directly to the mpr property APIs for speed. - * Flags will cause the callbacks to be supplied the Ejs handle. - */ - ejsDefineCMethod(ep, obj, "assert", assertProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "breakpoint", breakpointProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "basename", basenameProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "dirname", dirnameProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "stripext", stripextProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "trim", trimProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "eval", evalScriptProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "exit", exitScript, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "print", printProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "println", printlnProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "sleep", sleepProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "sort", sortProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "time", timeProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "date", dateProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "strlen", strlenProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "strstr", strstrProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "typeof", typeofProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "toint", tointProc, EJS_NO_LOCAL); - - ejsDefineStringCMethod(ep, obj, "include", includeProc, EJS_NO_LOCAL); - ejsDefineStringCMethod(ep, obj, "includeGlobal", includeGlobalProc, - EJS_NO_LOCAL); - ejsDefineStringCMethod(ep, obj, "trace", traceProc, EJS_NO_LOCAL); - -#if BLD_DEBUG - ejsDefineCMethod(ep, obj, "printv", printvProc, EJS_NO_LOCAL); -#endif - -#if FUTURE - ejsDefineCMethod(ep, obj, "printf", printfProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, obj, "sprintf", sprintfProc, EJS_NO_LOCAL); -#endif - - if (ejsObjHasErrors(obj)) { - return MPR_ERR_CANT_INITIALIZE; - } - return 0; -} - -/******************************************************************************/ - -#else -void ejsProcsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystem.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystem.c deleted file mode 100644 index e035e1c740..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystem.c +++ /dev/null @@ -1,112 +0,0 @@ -/* - * @file ejsSystem.c - * @brief System class for the EJS Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -#if UNUSED -/* - * function int random() - */ - -static int randomProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "random()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function void yield() - */ - -static int yieldProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "yield()\n"); - return 0; -} - -/******************************************************************************/ -/* - * function void sleep(int milliSeconds) - */ - -static int sleepProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ep, "sleep()\n"); - return 0; -} - -#endif -/******************************************************************************/ -/* - * function void exit(int status) - * - * Exit the widget with the given status. All JavaScript processing ceases. - */ - -static int exitProc(Ejs *ep, EjsVar *thisObj, int argc, EjsVar **argv) -{ - int status; - - status = 0; - if ((argc == 1) && ejsVarIsInteger(argv[0])) { - status = argv[0]->integer; - } - ejsExit(ep, status); - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineSystemClass(Ejs *ep) -{ - EjsVar *systemClass; - - /* - * We create the system class and define static methods on it. - * NOTE: There is no object instance - */ - systemClass = ejsDefineClass(ep, "System", "Object", 0); - if (systemClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - ejsDefineCMethod(ep, systemClass, "exit", exitProc, EJS_NO_LOCAL); - -#if UNUSED - ejsDefineCMethod(ep, systemClass, "random", randomProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, systemClass, "yield", yieldProc, EJS_NO_LOCAL); - ejsDefineCMethod(ep, systemClass, "sleep", sleepProc, EJS_NO_LOCAL); - - /* - * Define properties - */ - ejsSetPropertyToString(systemClass, "name", ""); -#endif - - return ejsObjHasErrors(systemClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemApp.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemApp.c deleted file mode 100644 index e2f1ceb363..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemApp.c +++ /dev/null @@ -1,49 +0,0 @@ -/* - * @file ejsSystemApp.c - * @brief App class - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software Inc, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/************************************ Code ************************************/ - -int ejsDefineAppClass(Ejs *ep) -{ - EjsVar *appClass; - - appClass = ejsDefineClass(ep, "System.App", "Object", 0); - if (appClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define properties - */ - ejsSetPropertyToString(ep, appClass, "name", BLD_PRODUCT); - ejsSetPropertyToString(ep, appClass, "title", BLD_NAME); - ejsSetPropertyToString(ep, appClass, "version", BLD_VERSION); - - /* - * Command line arguments - */ - ejsSetPropertyToNull(ep, appClass, "args"); - - return ejsObjHasErrors(appClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemDebug.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemDebug.c deleted file mode 100644 index 5a011e2a2d..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemDebug.c +++ /dev/null @@ -1,60 +0,0 @@ -/* - * @file ejsSystemDebug.c - * @brief System.Debug class - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function bool isDebugMode() - * MOB -- convert to accessor - */ - -static int isDebugMode(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsTrace(ejs, "isDebugMode()\n"); - ejsSetReturnValueToInteger(ejs, mprGetDebugMode(ejs)); - return 0; -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineDebugClass(Ejs *ejs) -{ - EjsVar *systemDebugClass; - - systemDebugClass = ejsDefineClass(ejs, "System.Debug", "Object", 0); - if (systemDebugClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the class methods - */ - ejsDefineCMethod(ejs, systemDebugClass, "isDebugMode", isDebugMode, - EJS_NO_LOCAL); - - return ejsObjHasErrors(systemDebugClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemLog.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemLog.c deleted file mode 100644 index 66467f8fcf..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemLog.c +++ /dev/null @@ -1,163 +0,0 @@ -/* - * @file ejsSystemLog.c - * @brief System.Log class for the EJS Object Model - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/*********************************** Usage ************************************/ -/* - * System.Log.setLog(path); - * System.Log.enable; - */ -/******************************************************************************/ - -static void logHandler(MPR_LOC_DEC(ctx, loc), int flags, int level, - const char *msg) -{ - MprApp *app; - char *buf; - int len; - - app = mprGetApp(ctx); - if (app->logFile == 0) { - return; - } - - if (flags & MPR_LOG_SRC) { - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "Log %d: %s\n", level, msg); - - } else if (flags & MPR_ERROR_SRC) { - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "Error: %s\n", msg); - - } else if (flags & MPR_FATAL_SRC) { - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "Fatal: %s\n", msg); - - } else if (flags & MPR_ASSERT_SRC) { -#if BLD_FEATURE_ALLOC_LEAK_TRACK - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "Assertion %s, failed at %s\n", - msg, loc); -#else - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "Assertion %s, failed\n", msg); -#endif - - } else if (flags & MPR_RAW) { - /* OPT */ - len = mprAllocSprintf(MPR_LOC_PASS(ctx, loc), &buf, 0, - "%s", msg); - - } else { - return; - } - - mprPuts(app->logFile, buf, len); - - mprFree(buf); -} - -/******************************************************************************/ -/************************************ Methods *********************************/ -/******************************************************************************/ -/* - * function int setLog(string path) - */ - -static int setLog(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - const char *path; - MprFile *file; - MprApp *app; - - if (argc != 1 || !ejsVarIsString(argv[0])) { - ejsArgError(ejs, "Usage: setLog(path)"); - return -1; - } - - app = mprGetApp(ejs); - - /* - * Ignore errors if we can't create the log file. - * Use the app context so this will live longer than the interpreter - * MOB -- this leaks files. - */ - path = argv[0]->string; - file = mprOpen(app, path, O_CREAT | O_TRUNC | O_WRONLY, 0664); - if (file) { - app->logFile = file; - mprSetLogHandler(ejs, logHandler); - } - mprLog(ejs, 0, "Test log"); - - return 0; -} - -/******************************************************************************/ -#if UNUSED - -static int enableSetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - if (argc != 1) { - ejsArgError(ejs, "Usage: set(value)"); - return -1; - } - ejsSetProperty(ejs, thisObj, "_enabled", argv[0]); - return 0; -} - -/******************************************************************************/ - -static int enableGetAccessor(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValue(ejs, ejsGetPropertyAsVar(ejs, thisObj, "_enabled")); - return 0; -} - -#endif -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineLogClass(Ejs *ejs) -{ - EjsVar *logClass; - - logClass = ejsDefineClass(ejs, "System.Log", "Object", 0); - if (logClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - ejsDefineCMethod(ejs, logClass, "setLog", setLog, EJS_NO_LOCAL); - -#if UNUSED - EjsProperty *pp; - ejsDefineCAccessors(ejs, logClass, "enable", enableSetAccessor, - enableGetAccessor, EJS_NO_LOCAL); - - pp = ejsSetPropertyToBoolean(ejs, logClass, "_enabled", 0); - ejsMakePropertyEnumerable(pp, 0); -#endif - - return ejsObjHasErrors(logClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemMemory.c b/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemMemory.c deleted file mode 100755 index d10787b1b4..0000000000 --- a/source4/lib/appweb/ejs-2.0/ejs/system/ejsSystemMemory.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * @file ejsSystemMemory.c - * @brief System.Memory class - */ -/********************************** Copyright *********************************/ -/* - * Copyright (c) Mbedthis Software LLC, 2005-2006. All Rights Reserved. - */ -/********************************** Includes **********************************/ - -#include "ejs.h" - -/****************************** Forward Declarations***************************/ - -static uint getUsedMemory(Ejs *ejs); - -/******************************************************************************/ -/*********************************** Methods *********************************/ -/******************************************************************************/ - -static int getUsedMemoryProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ejs, getUsedMemory(ejs)); - return 0; -} - -/******************************************************************************/ - -static int getUsedStackProc(Ejs *ejs, EjsVar *thisObj, int argc, EjsVar **argv) -{ - ejsSetReturnValueToInteger(ejs, mprStackSize(ejs)); - return 0; -} - -/******************************************************************************/ -/* - * Public function - */ - -uint ejsGetAvailableMemory(Ejs *ejs) -{ - EjsVar *memoryClass; - uint ram; - - memoryClass = ejsGetClass(ejs, 0, "System.Memory"); - - ram = ejsGetPropertyAsInteger(ejs, memoryClass, "ram"); - return ram - getUsedMemory(ejs); -} - -/******************************************************************************/ - -static int getAvailableMemoryProc(Ejs *ejs, EjsVar *thisObj, int argc, - EjsVar **argv) -{ - EjsVar *memoryClass; - uint ram; - - memoryClass = ejsGetClass(ejs, 0, "System.Memory"); - - ram = ejsGetPropertyAsInteger(ejs, memoryClass, "ram"); -#if BREW - ejsSetReturnValueToInteger(ejs, ram - getUsedMemory(ejs)); -#else - ejsSetReturnValueToInteger(ejs, 0); -#endif - return 0; -} - -/******************************************************************************/ - -static uint getUsedMemory(Ejs *ejs) -{ -#if BREW - MprApp *app; - IHeap *heap; - uint memInUse; - void *ptr; - - app = mprGetApp(ejs); - ptr = (void*) &heap; - if (ISHELL_CreateInstance(app->shell, AEECLSID_HEAP, (void**) ptr) - == SUCCESS) { - memInUse = IHEAP_GetMemStats(heap); - IHEAP_Release(heap); - } else { - memInUse = 0; - } - - return memInUse; -#else - return 0; -#endif -} - -/******************************************************************************/ -/******************************** Initialization ******************************/ -/******************************************************************************/ - -int ejsDefineMemoryClass(Ejs *ejs) -{ - EjsVar *memoryClass; - uint used; - -#if BREW - MprApp *app; - AEEDeviceInfo *info; - - /* - * Get needed information for class properties. - */ - info = mprAllocType(ejs, AEEDeviceInfo); - if (info == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - info->wStructSize = sizeof(AEEDeviceInfo); - app = mprGetApp(ejs); - ISHELL_GetDeviceInfo(app->shell, info); - used = getUsedMemory(ejs); -#else - used = 0; -#endif - - /* - * Create the class - */ - memoryClass = ejsDefineClass(ejs, "System.Memory", "Object", 0); - if (memoryClass == 0) { - return MPR_ERR_CANT_INITIALIZE; - } - - /* - * Define the class methods - * MOB -- change to accessors - */ - ejsDefineCMethod(ejs, memoryClass, "getUsedStack", getUsedStackProc, - EJS_NO_LOCAL); - ejsDefineCMethod(ejs, memoryClass, "getUsedMemory", getUsedMemoryProc, - EJS_NO_LOCAL); - ejsDefineCMethod(ejs, memoryClass, "getAvailableMemory", - getAvailableMemoryProc, EJS_NO_LOCAL); - - /* - * Define properties - */ -#if BREW - ejsSetPropertyToInteger(ejs, memoryClass, "ram", info->dwRAM); - -#if UNUSED - /* MOB -- delete this */ - ejsSetPropertyToInteger(ejs, memoryClass, "available", - info->dwRAM - used); -#endif -#endif - -#if UNUSED - ejsSetPropertyToInteger(ejs, memoryClass, "used", used); - ejsSetPropertyToInteger(ejs, memoryClass, "flash", 0); -#endif - - return ejsObjHasErrors(memoryClass) ? MPR_ERR_CANT_INITIALIZE : 0; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/exml/Makefile b/source4/lib/appweb/ejs-2.0/exml/Makefile deleted file mode 100644 index 663e65ed53..0000000000 --- a/source4/lib/appweb/ejs-2.0/exml/Makefile +++ /dev/null @@ -1,42 +0,0 @@ -# -# Makefile for Embedded XML (EXML) -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -# -# EXML may be linked into shared handlers so we must build the objects both -# shared and static. -# -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I../mpr - -include make.dep - -ifeq ($(BLD_FEATURE_TEST),1) -POST_DIRS := test -endif - -TARGETS += $(BLD_BIN_DIR)/libexml$(BLD_LIB) - -ifeq ($(BLD_FEATURE_XML),1) -compileExtra: $(TARGETS) -endif - -# MOB -- remove when FEATURE_XML is defined -compileExtra: $(TARGETS) - -$(BLD_BIN_DIR)/libexml$(BLD_LIB): $(FILES) - @bld --library $(BLD_BIN_DIR)/libexml \ - --objectsDir $(BLD_OBJ_DIR) --objectList files --libs mpr - -cleanExtra: - @echo "rm -f $(TARGETS)" | $(BLDOUT) - @rm -f $(TARGETS) - @rm -f $(BLD_BIN_DIR)/libexml.* - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/exml/exml.h b/source4/lib/appweb/ejs-2.0/exml/exml.h deleted file mode 100644 index 44c50a56b9..0000000000 --- a/source4/lib/appweb/ejs-2.0/exml/exml.h +++ /dev/null @@ -1,94 +0,0 @@ -/* - * exml.h -- Embedded Xml Parser header - * - * Copyright (c) Mbedthis Software, LLC, 2003-2003. All Rights Reserved. -- MOB - */ - -#ifndef _h_EXML -#define _h_EXML 1 - -/******************************** Description *********************************/ - -#include "mpr.h" - -/********************************** Defines ***********************************/ - -#if BLD_FEATURE_SQUEEZE - #define EXML_BUFSIZE 512 /* Read buffer size */ -#else - #define EXML_BUFSIZE 1024 /* Read buffer size */ -#endif - -/* - * XML parser states. The states that are passed to the user handler have - * "U" appended to the comment. The error states (ERR and EOF) must be - * negative. - */ -#define EXML_ERR -1 /* Error */ -#define EXML_EOF -2 /* End of input */ -#define EXML_BEGIN 1 /* Before next tag */ -#define EXML_AFTER_LS 2 /* Seen "<" */ -#define EXML_COMMENT 3 /* Seen "<!--" (usr) U */ -#define EXML_NEW_ELT 4 /* Seen "<tag" (usr) U */ -#define EXML_ATT_NAME 5 /* Seen "<tag att" */ -#define EXML_ATT_EQ 6 /* Seen "<tag att" = */ -#define EXML_NEW_ATT 7 /* Seen "<tag att = "val" U */ -#define EXML_SOLO_ELT_DEFINED 8 /* Seen "<tag../>" U */ -#define EXML_ELT_DEFINED 9 /* Seen "<tag...>" U */ -#define EXML_ELT_DATA 10 /* Seen "<tag>....<" U */ -#define EXML_END_ELT 11 /* Seen "<tag>....</tag>" U */ -#define EXML_PI 12 /* Seen "<?processingInst" U */ -#define EXML_CDATA 13 /* Seen "<![CDATA[" U */ - -/* - * Lex tokens - */ -typedef enum ExmlToken { - TOKEN_ERR, - TOKEN_TOO_BIG, /* Token is too big */ - TOKEN_CDATA, - TOKEN_COMMENT, - TOKEN_INSTRUCTIONS, - TOKEN_LS, /* "<" -- Opening a tag */ - TOKEN_LS_SLASH, /* "</" -- Closing a tag */ - TOKEN_GR, /* ">" -- End of an open tag */ - TOKEN_SLASH_GR, /* "/>" -- End of a solo tag */ - TOKEN_TEXT, - TOKEN_EQ, - TOKEN_EOF, - TOKEN_SPACE, -} ExmlToken; - -struct Exml; -typedef int (*ExmlHandler)(struct Exml *xp, int state, - const char *tagName, const char* attName, const char* value); -typedef int (*ExmlInputStream)(struct Exml *xp, void *arg, char *buf, int size); - -/* - * Per XML session structure - */ -typedef struct Exml { - ExmlHandler handler; /* Callback function */ - ExmlInputStream readFn; /* Read data function */ - MprBuf *inBuf; /* Input data queue */ - MprBuf *tokBuf; /* Parsed token buffer */ - int quoteChar; /* XdbAtt quote char */ - int lineNumber; /* Current line no for debug */ - void *parseArg; /* Arg passed to exmlParse() */ - void *inputArg; /* Arg passed to exmlSetInputStream() */ - char *errMsg; /* Error message text */ -} Exml; - -extern Exml *exmlOpen(MprCtx ctx, int initialSize, int maxSize); -extern void exmlClose(Exml *xp); -extern void exmlSetParserHandler(Exml *xp, ExmlHandler h); -extern void exmlSetInputStream(Exml *xp, ExmlInputStream s, void *arg); -extern int exmlParse(Exml *xp); -extern void exmlSetParseArg(Exml *xp, void *parseArg); -extern void *exmlGetParseArg(Exml *xp); -extern const char *exmlGetErrorMsg(Exml *xp); -extern int exmlGetLineNumber(Exml *xp); - -/******************************************************************************/ - -#endif /* _h_EXML */ diff --git a/source4/lib/appweb/ejs-2.0/exml/exmlParser.c b/source4/lib/appweb/ejs-2.0/exml/exmlParser.c deleted file mode 100644 index 14871411a6..0000000000 --- a/source4/lib/appweb/ejs-2.0/exml/exmlParser.c +++ /dev/null @@ -1,752 +0,0 @@ -/* - * exml.c -- A simple SAX style XML parser - */ - -/********************************* Description ********************************/ -/* - * This is a recursive descent parser for XML text files. It is a one-pass - * simple parser that invokes a user supplied callback for key tokens in the - * XML file. The user supplies a read function so that XML files can be parsed - * from disk or in-memory. - */ -/********************************** Includes **********************************/ - -#include "exml.h" - -/****************************** Forward Declarations **************************/ -/* MOB -- FIX */ -#if BLD_FEATURE_EXML || 1 - -static int parseNext(Exml *xp, int state); -static ExmlToken getToken(Exml *xp, int state); -static int getNextChar(Exml *xp); -static int scanFor(Exml *xp, char *str); -static int putLastChar(Exml *xp, int c); -static void error(Exml *xp, char *fmt, ...); -static void trimToken(Exml *xp); - -/************************************ Code ************************************/ - -Exml *exmlOpen(MprCtx ctx, int initialSize, int maxSize) -{ - Exml *xp; - - xp = mprAllocTypeZeroed(ctx, Exml); - - xp->inBuf = mprCreateBuf(xp, EXML_BUFSIZE, EXML_BUFSIZE); - xp->tokBuf = mprCreateBuf(xp, initialSize, maxSize); - - return xp; -} - -/******************************************************************************/ - -void exmlClose(Exml *xp) -{ - mprAssert(xp); - - mprFree(xp); -} - -/******************************************************************************/ - -void exmlSetParserHandler(Exml *xp, ExmlHandler h) -{ - mprAssert(xp); - - xp->handler = h; -} - -/******************************************************************************/ - -void exmlSetInputStream(Exml *xp, ExmlInputStream s, void *arg) -{ - mprAssert(xp); - - xp->readFn = s; - xp->inputArg = arg; -} - -/******************************************************************************/ -/* - * Set the parse arg - */ - -void exmlSetParseArg(Exml *xp, void *parseArg) -{ - mprAssert(xp); - - xp->parseArg = parseArg; -} - -/******************************************************************************/ -/* - * Set the parse arg - */ - -void *exmlGetParseArg(Exml *xp) -{ - mprAssert(xp); - - return xp->parseArg; -} - -/******************************************************************************/ -/* - * Parse an XML file. Return 0 for success, -1 for error. - */ - -int exmlParse(Exml *xp) -{ - mprAssert(xp); - - return parseNext(xp, EXML_BEGIN); -} - -/******************************************************************************/ -/* - * XML parser. This is a recursive descent parser. Return -1 for errors, 0 for - * EOF and 1 if there is still more data to parse. - */ - -static int parseNext(Exml *xp, int state) -{ - ExmlHandler handler; - ExmlToken token; - MprBuf *tokBuf; - char *tname, *aname; - int rc; - - mprAssert(state >= 0); - - tokBuf = xp->tokBuf; - handler = xp->handler; - tname = aname = 0; - rc = 0; - - /* - * In this parse loop, the state is never assigned EOF or ERR. In - * such cases we always return EOF or ERR. - */ - while (1) { - - token = getToken(xp, state); - - if (token == TOKEN_TOO_BIG) { - error(xp, "XML token is too big"); - goto err; - } - - switch (state) { - case EXML_BEGIN: /* ------------------------------------------ */ - /* - * Expect to get an element, comment or processing instruction - */ - switch (token) { - case TOKEN_EOF: - goto exit; - - case TOKEN_LS: - /* - * Recurse to handle the new element, comment etc. - */ - rc = parseNext(xp, EXML_AFTER_LS); - if (rc < 0) { - goto exit; - } - break; - - default: - error(xp, "Syntax error"); - goto err; - } - break; - - case EXML_AFTER_LS: /* ------------------------------------------ */ - switch (token) { - case TOKEN_COMMENT: - state = EXML_COMMENT; - rc = (*handler)(xp, state, "!--", 0, mprGetBufStart(tokBuf)); - if (rc < 0) { - goto err; - } - rc = 1; - goto exit; - - case TOKEN_CDATA: - state = EXML_CDATA; - rc = (*handler)(xp, state, "!--", 0, mprGetBufStart(tokBuf)); - if (rc < 0) { - goto err; - } - rc = 1; - goto exit; - - case TOKEN_INSTRUCTIONS: - /* Just ignore processing instructions */ - rc = 1; - goto exit; - - case TOKEN_TEXT: - state = EXML_NEW_ELT; - tname = mprStrdup(xp, mprGetBufStart(tokBuf)); - if (tname == 0) { - rc = MPR_ERR_MEMORY; - goto exit; - } - rc = (*handler)(xp, state, tname, 0, 0); - if (rc < 0) { - goto err; - } - break; - - default: - error(xp, "Syntax error"); - goto err; - } - break; - - case EXML_NEW_ELT: /* ------------------------------------------ */ - /* - * We have seen the opening "<element" for a new element and have - * not yet seen the terminating ">" of the opening element. - */ - switch (token) { - case TOKEN_TEXT: - /* - * Must be an attribute name - */ - aname = mprStrdup(xp, mprGetBufStart(tokBuf)); - token = getToken(xp, state); - if (token != TOKEN_EQ) { - error(xp, "Missing assignment for attribute \"%s\"", aname); - goto err; - } - - token = getToken(xp, state); - if (token != TOKEN_TEXT) { - error(xp, "Missing value for attribute \"%s\"", aname); - goto err; - } - state = EXML_NEW_ATT; - rc = (*handler)(xp, state, tname, aname, - mprGetBufStart(tokBuf)); - if (rc < 0) { - goto err; - } - state = EXML_NEW_ELT; - break; - - case TOKEN_GR: - /* - * This is ">" the termination of the opening element - */ - if (*tname == '\0') { - error(xp, "Missing element name"); - goto err; - } - - /* - * Tell the user that the opening element is now complete - */ - state = EXML_ELT_DEFINED; - rc = (*handler)(xp, state, tname, 0, 0); - if (rc < 0) { - goto err; - } - state = EXML_ELT_DATA; - break; - - case TOKEN_SLASH_GR: - /* - * If we see a "/>" then this is a solo element - */ - if (*tname == '\0') { - error(xp, "Missing element name"); - goto err; - } - state = EXML_SOLO_ELT_DEFINED; - rc = (*handler)(xp, state, tname, 0, 0); - if (rc < 0) { - goto err; - } - rc = 1; - goto exit; - - default: - error(xp, "Syntax error"); - goto err; - } - break; - - case EXML_ELT_DATA: /* -------------------------------------- */ - /* - * We have seen the full opening element "<name ...>" and now - * await data or another element. - */ - if (token == TOKEN_LS) { - /* - * Recurse to handle the new element, comment etc. - */ - rc = parseNext(xp, EXML_AFTER_LS); - if (rc < 0) { - goto exit; - } - break; - - } else if (token == TOKEN_LS_SLASH) { - state = EXML_END_ELT; - break; - - } else if (token != TOKEN_TEXT) { - goto err; - } - if (mprGetBufLength(tokBuf) > 0) { - /* - * Pass the data between the element to the user - */ - rc = (*handler)(xp, state, tname, 0, mprGetBufStart(tokBuf)); - if (rc < 0) { - goto err; - } - } - break; - - case EXML_END_ELT: /* -------------------------------------- */ - if (token != TOKEN_TEXT) { - error(xp, "Missing closing element name for \"%s\"", tname); - goto err; - } - /* - * The closing element name must match the opening element name - */ - if (strcmp(tname, mprGetBufStart(tokBuf)) != 0) { - error(xp, - "Closing element name \"%s\" does not match on line %d" - "opening name \"%s\"", - mprGetBufStart(tokBuf), xp->lineNumber, tname); - goto err; - } - rc = (*handler)(xp, state, tname, 0, 0); - if (rc < 0) { - goto err; - } - if (getToken(xp, state) != TOKEN_GR) { - error(xp, "Syntax error"); - goto err; - } - return 1; - - case EXML_EOF: /* ---------------------------------------------- */ - goto exit; - - case EXML_ERR: /* ---------------------------------------------- */ - default: - goto err; - } - } - mprAssert(0); - -err: - rc = -1; - -exit: - mprFree(tname); - mprFree(aname); - - return rc; -} - -/******************************************************************************/ -/* - * Lexical analyser for XML. Return the next token reading input as required. - * It uses a one token look ahead and push back mechanism (LAR1 parser). - * Text token identifiers are left in the tokBuf parser buffer on exit. - * This Lex has special cases for the states EXML_ELT_DATA where we - * have an optimized read of element data, and EXML_AFTER_LS where we - * distinguish between element names, processing instructions and comments. - */ - -static ExmlToken getToken(Exml *xp, int state) -{ - MprBuf *tokBuf, *inBuf; - uchar *cp; - int c, rc; - - tokBuf = xp->tokBuf; - inBuf = xp->inBuf; - - mprAssert(state >= 0); - - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - mprFlushBuf(tokBuf); - - /* - * Special case parsing for names and for element data. We do this for - * performance so we can return to the caller the largest token possible - */ - if (state == EXML_ELT_DATA) { - /* - * Read all the data up to the start of the closing element "<" or the - * start of a sub-element. - */ -#if UNUSED - while (isspace(c)) { - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - } -#endif - if (c == '<') { - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - if (c == '/') { - return TOKEN_LS_SLASH; - } - putLastChar(xp, c); - return TOKEN_LS; - } - do { - if (mprPutCharToBuf(tokBuf, c) < 0) { - return TOKEN_TOO_BIG; - } - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - } while (c != '<'); - - /* - * Put back the last look-ahead character - */ - putLastChar(xp, c); - - /* - * If all white space, then zero the token buffer - */ - for (cp = tokBuf->start; *cp; cp++) { - if (!isspace(*cp)) { - return TOKEN_TEXT; - } - } - mprFlushBuf(tokBuf); - return TOKEN_TEXT; - } - - while (1) { - switch (c) { - case ' ': - case '\n': - case '\t': - case '\r': - break; - - case '<': - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - if (c == '/') { - return TOKEN_LS_SLASH; - } - putLastChar(xp, c); - return TOKEN_LS; - - case '=': - return TOKEN_EQ; - - case '>': - return TOKEN_GR; - - case '/': - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - if (c == '>') { - return TOKEN_SLASH_GR; - } - return TOKEN_ERR; - - case '\"': - case '\'': - xp->quoteChar = c; - /* Fall through */ - - default: - /* - * We handle element names, attribute names and attribute values - * here. We do NOT handle data between elements here. Read the - * token. Stop on white space or a closing element ">" - */ - if (xp->quoteChar) { - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - while (c != xp->quoteChar) { - if (mprPutCharToBuf(tokBuf, c) < 0) { - return TOKEN_TOO_BIG; - } - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - } - xp->quoteChar = 0; - - } else { - while (!isspace(c) && c != '>' && c != '/' && c != '=') { - if (mprPutCharToBuf(tokBuf, c) < 0) { - return TOKEN_TOO_BIG; - } - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - } - putLastChar(xp, c); - } - if (mprGetBufLength(tokBuf) <= 0) { - return TOKEN_ERR; - } - mprAddNullToBuf(tokBuf); - - if (state == EXML_AFTER_LS) { - /* - * If we are just inside an element "<", then analyze what we - * have to see if we have an element name, instruction or - * comment. Tokbuf will hold "?" for instructions or "!--" - * for comments. - */ - if (mprLookAtNextCharInBuf(tokBuf) == '?') { - /* Just ignore processing instructions */ - rc = scanFor(xp, "?>"); - if (rc < 0) { - return TOKEN_TOO_BIG; - } else if (rc == 0) { - return TOKEN_ERR; - } - return TOKEN_INSTRUCTIONS; - - } else if (mprLookAtNextCharInBuf(tokBuf) == '!') { - /* - * First discard the comment leadin "!--" and eat leading - * white space. - */ - if (strcmp((char*) tokBuf->start, "![CDATA[") == 0) { - mprFlushBuf(tokBuf); -#if UNUSED - c = mprLookAtNextCharInBuf(inBuf); - while (isspace(c)) { - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - c = mprLookAtNextCharInBuf(inBuf); - } -#endif - rc = scanFor(xp, "]]>"); - if (rc < 0) { - return TOKEN_TOO_BIG; - } else if (rc == 0) { - return TOKEN_ERR; - } - return TOKEN_CDATA; - - } else { - mprFlushBuf(tokBuf); -#if UNUSED - c = mprLookAtNextCharInBuf(inBuf); - while (isspace(c)) { - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - c = mprLookAtNextCharInBuf(inBuf); - } -#endif - rc = scanFor(xp, "-->"); - if (rc < 0) { - return TOKEN_TOO_BIG; - } else if (rc == 0) { - return TOKEN_ERR; - } - return TOKEN_COMMENT; - } - } - } - trimToken(xp); - return TOKEN_TEXT; - } - if ((c = getNextChar(xp)) < 0) { - return TOKEN_EOF; - } - } - - /* Should never get here */ - mprAssert(0); - return TOKEN_ERR; -} - -/******************************************************************************/ -/* - * Scan for a pattern. Eat and discard input up to the pattern. Return 1 if - * the pattern was found, return 0 if not found. Return < 0 on errors. - */ - -static int scanFor(Exml *xp, char *str) -{ - MprBuf *tokBuf; - char *cp; - int c; - - mprAssert(str); - - tokBuf = xp->tokBuf; - - while (1) { - for (cp = str; *cp; cp++) { - if ((c = getNextChar(xp)) < 0) { - return 0; - } - if (tokBuf) { - if (mprPutCharToBuf(tokBuf, c) < 0) { - return -1; - } - } - if (c != *cp) { - break; - } - } - if (*cp == '\0') { - /* - * Remove the pattern from the tokBuf - */ - if (tokBuf) { - mprAdjustBufEnd(tokBuf, -(int) strlen(str)); - trimToken(xp); - } - return 1; - } - } -} - -/******************************************************************************/ -/* - * Get another character. We read and buffer blocks of data if we need more - * data to parse. - */ - -static int getNextChar(Exml *xp) -{ - MprBuf *inBuf; - char c; - int l; - - inBuf = xp->inBuf; - if (mprGetBufLength(inBuf) <= 0) { - /* - * Flush to reset the servp/endp pointers to the start of the buffer - * so we can do a maximal read - */ - mprFlushBuf(inBuf); - l = (xp->readFn)(xp, xp->inputArg, mprGetBufStart(inBuf), - mprGetBufLinearSpace(inBuf)); - if (l <= 0) { - return -1; - } - mprAdjustBufEnd(inBuf, l); - } - c = mprGetCharFromBuf(inBuf); - - if (c == '\n') { - xp->lineNumber++; - } - return c; -} - -/******************************************************************************/ -/* - * Put back a character in the input buffer - */ - -static int putLastChar(Exml *xp, int c) -{ - if (mprInsertCharToBuf(xp->inBuf, (char) c) < 0) { - mprAssert(0); - return -1; - } - if (c == '\n') { - xp->lineNumber--; - } - return 0; -} - -/******************************************************************************/ -/* - * Output a parse message - */ - -static void error(Exml *xp, char *fmt, ...) -{ - va_list args; - char *buf; - - mprAssert(fmt); - - va_start(args, fmt); - mprAllocVsprintf(MPR_LOC_ARGS(xp), &buf, MPR_MAX_STRING, fmt, args); - va_end(args); - - /* - * MOB need to add the failing line text and a pointer to which column - */ - mprFree(xp->errMsg); - mprAllocSprintf(MPR_LOC_ARGS(xp), &xp->errMsg, MPR_MAX_STRING, - "XML error: %s\nAt line %d\n", buf, xp->lineNumber); - - mprFree(buf); -} - -/******************************************************************************/ -/* - * Remove trailing whitespace in a token and ensure it is terminated with - * a NULL for easy parsing - */ - -static void trimToken(Exml *xp) -{ - while (isspace(mprLookAtLastCharInBuf(xp->tokBuf))) { - mprAdjustBufEnd(xp->tokBuf, -1); - } - mprAddNullToBuf(xp->tokBuf); -} - -/******************************************************************************/ - -const char *exmlGetErrorMsg(Exml *xp) -{ - if (xp->errMsg == 0) { - return ""; - } - return xp->errMsg; -} - -/******************************************************************************/ - -int exmlGetLineNumber(Exml *xp) -{ - return xp->lineNumber; -} - -/******************************************************************************/ -#else - -void exmlParserDummy() {} -#endif /* BLD_FEATURE_EXML */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/exml/files b/source4/lib/appweb/ejs-2.0/exml/files deleted file mode 100644 index 0f10ea44dd..0000000000 --- a/source4/lib/appweb/ejs-2.0/exml/files +++ /dev/null @@ -1 +0,0 @@ -${BLD_OBJ_DIR}/exmlParser${BLD_OBJ} diff --git a/source4/lib/appweb/ejs-2.0/mpr/Makefile b/source4/lib/appweb/ejs-2.0/mpr/Makefile deleted file mode 100644 index 6dd0e45d9e..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/Makefile +++ /dev/null @@ -1,41 +0,0 @@ -# -# Makefile for the Mbedthis Portable Runtime (MPR) library -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes - -include make.dep - -ifeq ($(BLD_HOST_UNIX),1) -PRE_DIRS = UNIX -else -PRE_DIRS = $(BLD_HOST_OS) -endif - -POST_DIRS = package - -TARGETS += $(BLD_BIN_DIR)/libmpr$(BLD_LIB) - -compileExtra: $(TARGETS) - -# -# Build the mpr libraries -# -$(BLD_BIN_DIR)/libmpr$(BLD_LIB): files \ - $(shell BLD_OBJ=$(BLD_OBJ) \; BLD_OBJ_DIR=$(BLD_OBJ_DIR) \; \ - eval echo `cat files`) - @bld --library $(BLD_BIN_DIR)/libmpr \ - --objectsDir $(BLD_OBJ_DIR) --objectList files - -cleanExtra: - @echo "rm -f $(TARGETS)" | $(BLDOUT) - @rm -f $(TARGETS) - @rm -f $(BLD_BIN_DIR)/libmpr.* - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile b/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile deleted file mode 100644 index 5259b1e3a0..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/UNIX/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the Mbedthis Portable Runtime (MPR) library for UNIX -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I.. - -include make.dep - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c deleted file mode 100644 index f647f1ed56..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprFile.c +++ /dev/null @@ -1,86 +0,0 @@ -/** - * @file mprFile.c - * @brief File services for Unix - * @overview - * @remarks - * See mprGenFile.c for other file services. - */ - -/******************************************************************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/************************************ Code ************************************/ - -int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info) -{ - struct stat s; - - mprAssert(path); - mprAssert(info); - - if (stat(path, &s) < 0) { - return -1; - } - - info->size = s.st_size; - info->ctime = s.st_ctime; - info->mtime = s.st_mtime; - info->inode = s.st_ino; - info->isDir = (s.st_mode & S_IFDIR) != 0; - info->isReg = (s.st_mode & S_IFREG) != 0; - - if (strcmp(path, "/dev/null") == 0) { - info->isReg = 0; - } - - return 0; -} - -/******************************************************************************/ - -int mprMakeDir(MprCtx ctx, const char *path, int perms) -{ - return mkdir(path, perms); -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c deleted file mode 100644 index 2c7fbf8a00..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprPlatform.c +++ /dev/null @@ -1,218 +0,0 @@ -/** - * @file mprPlatform.c - * @brief Cross platform routines - * @overview This module provides low level cross platform routines. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -#include "mpr.h" - -/************************************ Code ************************************/ - -char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in) -{ -#if HAVE_NTOA_R - inet_ntoa_r(in, buffer, bufsize); -#else - uchar *cp; - /* FUTURE -- this is not portable */ - cp = (uchar*) ∈ - mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); -#endif - return buffer; -} - -/******************************************************************************/ - -void mprSetShell(MprCtx ctx, void *shell) -{ -} - -/******************************************************************************/ - -void *mprGetShell(MprCtx ctx) -{ - return 0; -} - -/******************************************************************************/ -/* - * Sleep. Period given in milliseconds. - */ - -void mprSleep(MprCtx ctx, int milliseconds) -{ - struct timespec timeout; - int rc; - - mprAssert(milliseconds >= 0); - timeout.tv_sec = milliseconds / 1000; - timeout.tv_nsec = (milliseconds % 1000) * 1000000; - do { - rc = nanosleep(&timeout, 0); - } while (rc < 0 && errno == EINTR); -} - -/******************************************************************************/ -/* - * Make intervening directories - */ - -int mprMakeDirPath(MprCtx ctx, const char *path) -{ - char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH]; - char *dirSep; - char *next, *tok; - - dir[0] = '\0'; - dirSep = "/\\"; - - if (path == 0 || *path == '\0') { - return MPR_ERR_BAD_ARGS; - } - - mprStrcpy(buf, sizeof(buf), path); - next = mprStrTok(buf, dirSep, &tok); - if (*buf == '/') { - dir[0] = '/'; - } - while (next != NULL) { - if (strcmp(next, ".") == 0 ) { - next = mprStrTok(NULL, dirSep, &tok); - continue; - } - strcat(dir, next); - if (access(dir, R_OK) != 0) { - if (mkdir(dir, 0666) < 0) { - return MPR_ERR_CANT_CREATE; - } - } - strcat(dir, "/"); - next = mprStrTok(NULL, dirSep, &tok); - } - return 0; -} - -/******************************************************************************/ -/* - * Get a fully qualified file name for the given path. Return with forward - * slashes always - */ - -char *mprGetFullPathName(char *buf, int buflen, const char *path) -{ - if (mprStrcpy(buf, buflen, path) < 0) { - mprAssert(0); - return 0; - } - return buf; -} - -/******************************************************************************/ -/* - * Replacement for gethostbyname that is multi-thread safe - */ - -struct hostent *mprGetHostByName(MprCtx ctx, const char *name) -{ - MprApp *app; - struct hostent *hp; - struct hostent *ip; - int count, i; - - hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent)); - memset(hp, 0, sizeof(struct hostent)); - - app = mprGetApp(ctx); - - #undef gethostbyname - - mprGlobalLock(app); - ip = gethostbyname(name); - mprGlobalUnlock(app); - - if (ip == 0) { - return 0; - } - hp->h_addrtype = ip->h_addrtype; - hp->h_length = ip->h_length; - hp->h_name = mprStrdup(hp, ip->h_name); - hp->h_addr_list = 0; - hp->h_aliases = 0; - - for (count = 0; ip->h_addr_list[count] != 0; ) { - count++; - } - if (count > 0) { - count++; - hp->h_addr_list = mprAlloc(hp, count * sizeof(char*)); - for (i = 0; ip->h_addr_list[i] != 0; i++) { - memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length); - } - hp->h_addr_list[i] = 0; - } - - for (count = 0; ip->h_aliases[count] != 0; ) { - count++; - } - if (count > 0) { - count++; - hp->h_aliases = mprAlloc(hp, count * sizeof(char*)); - for (i = 0; ip->h_aliases[i] != 0; i++) { - hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]); - } - hp->h_aliases[i] = 0; - } - return hp; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c deleted file mode 100644 index 0153c0622d..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/UNIX/mprTime.c +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @file mprTime.c - * @brief Time handling for Unix - * @overview - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************* Includes ***********************************/ - -#include "mpr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#undef localtime -#undef localtime_r -#undef gmtime -#undef gmtime_r -#undef ctime -#undef ctime_r -#undef asctime -#undef asctime_r - -/******************************************************************************/ -/* - * Returns time in seconds and milliseconds. This is NOT time-of-day. - */ - -MprTime *mprGetTime(MprCtx ctx, MprTime *tp) -{ - struct timeval tv; - - if (gettimeofday(&tv, 0) < 0) { - mprAssert(0); - tp->sec = 0; - tp->msec = 0; - return tp; - } - tp->sec = tv.tv_sec; - tp->msec = tv.tv_usec / 1000; - return tp; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of localtime - */ - -struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now) -{ - localtime_r(now, timep); - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of gmtime - */ - -struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep) -{ - gmtime_r(now, timep); - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of ctime - */ - -int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer) -{ - char localBuf[80]; - char *cp; - int len; - - mprAssert(buf); - - mprGlobalLock(ctx); - - cp = ctime_r(timer, localBuf); - if ((int) strlen(cp) >= bufsize) { - mprStrcpy(buf, bufsize, "WONT FIT"); - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - len = mprStrcpy(buf, bufsize, cp); - - if (buf[len - 1] == '\n') { - buf[len - 1] = '\0'; - } - - mprGlobalUnlock(ctx); - - return 0; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of asctime - */ - -int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr) -{ - char *cp; - char localBuf[80]; - - cp = asctime_r(timeptr, localBuf); - if ((int) strlen(cp) >= bufsize) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - mprStrcpy(buf, bufsize, cp); - - return strlen(buf); -} - -/******************************************************************************/ - -#ifdef __cplusplus -} -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile deleted file mode 100644 index f3a2394b6e..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the Mbedthis Portable Runtime (MPR) library for VXWORKS -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I.. - -include make.dep - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c deleted file mode 100644 index ae0b523faa..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprFile.c +++ /dev/null @@ -1,85 +0,0 @@ -/** - * @file mprUnixFile.c - * @brief File services for Unix - * @overview - * @remarks - */ - -/******************************************************************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/************************************ Code ************************************/ - -int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info) -{ - struct stat s; - - mprAssert(path); - mprAssert(info); - - if (stat(path, &s) < 0) { - return -1; - } - - info->size = s.st_size; - info->ctime = s.st_ctime; - info->mtime = s.st_mtime; - info->inode = s.st_ino; - info->isDir = (s.st_mode & S_IFDIR) != 0; - info->isReg = (s.st_mode & S_IFREG) != 0; - - if (strcmp(path, "/dev/null") == 0) { - info->isReg = 0; - } - - return 0; -} - -/******************************************************************************/ - -int mprMakeDir(MprCtx ctx, const char *path, int perms) -{ - return mkdir(path, perms); -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c deleted file mode 100644 index 29258dfe1c..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprPlatform.c +++ /dev/null @@ -1,191 +0,0 @@ -/** - * @file mprPlatform.c - * @brief Cross platform routines - * @overview This module provides low level cross platform routines. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -#include "mpr.h" - -/************************************ Code ************************************/ - -char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in) -{ -#if HAVE_NTOA_R - inet_ntoa_r(in, buffer, bufsize); -#else - uchar *cp; - /* FUTURE -- this is not portable */ - cp = (uchar*) ∈ - mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); -#endif - return buffer; -} - -/******************************************************************************/ - -void mprSetShell(MprCtx ctx, void *shell) -{ -} - -/******************************************************************************/ - -void *mprGetShell(MprCtx ctx) -{ - return 0; -} - -/******************************************************************************/ -/* - * Sleep. Period given in milliseconds. - */ - -void mprSleep(MprCtx ctx, int milliseconds) -{ - struct timeval timeout; - int rc; - - timeout.tv_sec = milliseconds / 1000; - timeout.tv_usec = (milliseconds % 1000) * 1000; - do { - rc = select(1, 0, 0, 0, &timeout); - } while (rc < 0 && errno == EINTR); -} - -/******************************************************************************/ -/* - * Make intervening directories - */ - -int mprMakeDirPath(MprCtx ctx, const char *path) -{ - char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH]; - char *dirSep; - char *next, *tok; - - dir[0] = '\0'; - dirSep = "/\\"; - - if (path == 0 || *path == '\0') { - return MPR_ERR_BAD_ARGS; - } - - mprStrcpy(buf, sizeof(buf), path); - next = mprStrTok(buf, dirSep, &tok); - if (*buf == '/') { - dir[0] = '/'; - } - while (next != NULL) { - if (strcmp(next, ".") == 0 ) { - next = mprStrTok(NULL, dirSep, &tok); - continue; - } - strcat(dir, next); - if (access(dir, R_OK) != 0) { - if (mkdir(dir) < 0) { - return MPR_ERR_CANT_CREATE; - } - } - strcat(dir, "/"); - next = mprStrTok(NULL, dirSep, &tok); - } - return 0; -} - -/******************************************************************************/ -/* - * Get a fully qualified file name for the given path. Return with forward - * slashes always - */ - -char *mprGetFullPathName(char *buf, int buflen, const char *path) -{ - if (mprStrcpy(buf, buflen, path) < 0) { - mprAssert(0); - return 0; - } - return buf; -} - -/******************************************************************************/ -/* - * Replacement for gethostbyname that is multi-thread safe - */ - -struct hostent *mprGetHostByName(MprCtx ctx, const char *name) -{ - struct hostent *hp; - - hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent)); - memset(hp, 0, sizeof(struct hostent)); - - struct in_addr inaddr; - inaddr.s_addr = (ulong) hostGetByName(name); - if (inaddr.s_addr < 0) { - mprAssert(0); - return 0; - } - hp->h_addrtype = AF_INET; - hp->h_length = sizeof(int); - hp->h_name = mprStrdup(name); - hp->h_addr_list = 0; - hp->h_aliases = 0; - - hp->h_addr_list = new char*[2]; - hp->h_addr_list[0] = (char *) mprAlloc(hp, sizeof(struct in_addr)); - memcpy(&hp->h_addr_list[0], &inaddr, hp->h_length); - hp->h_addr_list[1] = 0; - - return hp; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c deleted file mode 100755 index c9b7560f46..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/VXWORKS/mprTime.c +++ /dev/null @@ -1,163 +0,0 @@ -/** - * @file mprTime.c - * @brief Time handling for VxWorks - * @overview - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************* Includes ***********************************/ - -#include "mpr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -#undef localtime -#undef localtime_r -#undef gmtime -#undef gmtime_r -#undef ctime -#undef ctime_r -#undef asctime -#undef asctime_r - -/******************************************************************************/ -/* - * Returns time in seconds and milliseconds. This is NOT time-of-day. - */ - -MprTime *mprGetTime(MprCtx ctx, MprTime *tp) -{ - struct timeval tv; - - if (gettimeofday(&tv, 0) < 0) { - mprAssert(0); - tp->sec = 0; - tp->msec = 0; - return tp; - } - tp->sec = tv.tv_sec; - tp->msec = tv.tv_usec / 1000; - return tp; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of localtime - */ - -struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now) -{ - localtime_r(now, timep); - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of gmtime - */ - -struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep) -{ - gmtime_r(now, timep); - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of ctime - */ - -int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer) -{ - char localBuf[80]; - char *cp; - int len; - - mprAssert(buf); - - mprGlobalLock(ctx); - - cp = ctime_r(timer, localBuf); - if ((int) strlen(cp) >= bufsize) { - mprStrcpy(buf, bufsize, "WONT FIT"); - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - len = mprStrcpy(buf, bufsize, cp); - - if (buf[len - 1] == '\n') { - buf[len - 1] = '\0'; - } - - mprGlobalUnlock(ctx); - - return 0; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of asctime - */ - -int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr) -{ - char *cp; - char localBuf[80]; - - cp = asctime_r(timeptr, localBuf); - if ((int) strlen(cp) >= bufsize) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - mprStrcpy(buf, bufsize, cp); - - return strlen(buf); -} - -/******************************************************************************/ - -#ifdef __cplusplus -} -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile b/source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile deleted file mode 100644 index 84e30ff8f1..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/WIN/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -# -# Makefile for the Mbedthis Portable Runtime (MPR) library for Windows -# -# Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. -# - -COMPILE := *.c -EXPORT_OBJECTS := yes -MAKE_IFLAGS := -I.. - -include make.dep - -## Local variables: -## tab-width: 4 -## End: -## vim: tw=78 sw=4 ts=4 diff --git a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c deleted file mode 100644 index 9ac1669f3d..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprFile.c +++ /dev/null @@ -1,123 +0,0 @@ -/** - * @file mprWinFile.c - * @brief File services for Windows - * @overview - * @remarks - */ - -/******************************************************************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/************************************ Code ************************************/ - -int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info) -{ - struct stat s; - - mprAssert(path); - mprAssert(info); - - if (stat(path, &s) < 0) { - return -1; - } - - info->size = s.st_size; - /* - * MOB -- these are time64_t. Loss of precision - */ - info->ctime = (uint) s.st_ctime; - info->mtime = (uint) s.st_mtime; - info->inode = s.st_ino; - info->isDir = (s.st_mode & S_IFDIR) != 0; - info->isReg = (s.st_mode & S_IFREG) != 0; - - /* - * Work hard on windows to determine if the file is a regular file. - * FUTURE -- OPT. Eliminate this CreateFile. - */ - if (info->isReg) { - long fileType, att; - - if ((att = GetFileAttributes(path)) == -1) { - return -1; - } - if (att & (FILE_ATTRIBUTE_REPARSE_POINT | - FILE_ATTRIBUTE_DIRECTORY | - FILE_ATTRIBUTE_ENCRYPTED | - FILE_ATTRIBUTE_SYSTEM | - FILE_ATTRIBUTE_OFFLINE)) { - /* - * Catch accesses to devices like CON, AUX, NUL, LPT etc - * att will be set to ENCRYPTED on Win9X and NT. - */ - info->isReg = 0; - } - if (info->isReg) { - HANDLE handle; - handle = CreateFile(path, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - 0, OPEN_EXISTING, 0, 0); - if (handle == INVALID_HANDLE_VALUE) { - info->isReg = 0; - } else { - fileType = GetFileType(handle); - if (fileType == FILE_TYPE_CHAR || fileType == FILE_TYPE_PIPE) { - info->isReg = 0; - } - CloseHandle(handle); - } - } - } - if (strcmp(path, "nul") == 0) { - info->isReg = 0; - } - return 0; -} - -/******************************************************************************/ - -int mprMakeDir(MprCtx ctx, const char *path, int perms) -{ - return mkdir(path, perms); -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c deleted file mode 100644 index 65718694b1..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprPlatform.c +++ /dev/null @@ -1,378 +0,0 @@ -/** - * @file mprPlatform.c - * @brief Cross platform routines - * @overview This module provides low level cross platform routines. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -#include "mpr.h" - -/**************************** Forward Declarations ****************************/ - -static const char *getHive(const char *keyPath, HKEY *hive); - -/************************************ Code ************************************/ - -char *mprInetToStr(char *buffer, int bufsize, const struct in_addr in) -{ -#if HAVE_NTOA_R - inet_ntoa_r(in, buffer, bufsize); -#else - uchar *cp; - cp = (uchar*) ∈ - mprSprintf(buffer, bufsize, "%d.%d.%d.%d", cp[0], cp[1], cp[2], cp[3]); -#endif - return buffer; -} - -/******************************************************************************/ - -void mprSetShell(MprCtx ctx, void *shell) -{ -} - -/******************************************************************************/ - -void *mprGetShell(MprCtx ctx) -{ - return 0; -} - -/******************************************************************************/ -/* - * Sleep. Period given in milliseconds. - */ - -void mprSleep(MprCtx ctx, int milliseconds) -{ - Sleep(milliseconds); -} - -/******************************************************************************/ -/* - * Make intervening directories - */ - -int mprMakeDirPath(MprCtx ctx, const char *path) -{ - char dir[MPR_MAX_PATH], buf[MPR_MAX_PATH]; - char *dirSep; - char *next, *tok; - - dir[0] = '\0'; - dirSep = "/\\"; - - if (path == 0 || *path == '\0') { - return MPR_ERR_BAD_ARGS; - } - - mprStrcpy(buf, sizeof(buf), path); - next = mprStrTok(buf, dirSep, &tok); - if (*buf == '/') { - dir[0] = '/'; - } - while (next != NULL) { - if (strcmp(next, ".") == 0 ) { - next = mprStrTok(NULL, dirSep, &tok); - continue; - } - strcat(dir, next); - if (access(dir, R_OK) != 0) { - if (_mkdir(dir) < 0) { - return MPR_ERR_CANT_CREATE; - } - } - strcat(dir, "/"); - next = mprStrTok(NULL, dirSep, &tok); - } - return 0; -} - -/******************************************************************************/ -/* - * Get a fully qualified file name for the given path. Return with forward - * slashes always - */ - -char *mprGetFullPathName(char *buf, int buflen, const char *path) -{ -#if (WIN || NW || OS2) && !BLD_FEATURE_ROMFS - char *junk, *cp; - int rc; - - --buflen; - rc = GetFullPathName(path, buflen, buf, &junk); - for (cp = buf; *cp; cp++) { - if (*cp == '\\') { - *cp = '/'; - } - } - buf[buflen] = '\0'; -#else - if (mprStrcpy(buf, buflen, path) < 0) { - mprAssert(0); - return 0; - } -#endif - return buf; -} - -/******************************************************************************/ -/* - * Replacement for gethostbyname that is multi-thread safe - */ - -struct hostent *mprGetHostByName(MprCtx ctx, const char *name) -{ - MprApp *app; - struct hostent *hp; - struct hostent *ip; - int count, i; - - hp = (struct hostent*) mprAlloc(ctx, sizeof(struct hostent)); - memset(hp, 0, sizeof(struct hostent)); - - app = mprGetApp(ctx); - - #undef gethostbyname - - mprGlobalLock(app); - ip = gethostbyname(name); - mprGlobalUnlock(app); - - if (ip == 0) { - return 0; - } - hp->h_addrtype = ip->h_addrtype; - hp->h_length = ip->h_length; - hp->h_name = mprStrdup(hp, ip->h_name); - hp->h_addr_list = 0; - hp->h_aliases = 0; - - for (count = 0; ip->h_addr_list[count] != 0; ) { - count++; - } - if (count > 0) { - count++; - hp->h_addr_list = mprAlloc(hp, count * sizeof(char*)); - for (i = 0; ip->h_addr_list[i] != 0; i++) { - memcpy(&hp->h_addr_list[i], &ip->h_addr_list[i], ip->h_length); - } - hp->h_addr_list[i] = 0; - } - - for (count = 0; ip->h_aliases[count] != 0; ) { - count++; - } - if (count > 0) { - count++; - hp->h_aliases = mprAlloc(hp, count * sizeof(char*)); - for (i = 0; ip->h_aliases[i] != 0; i++) { - hp->h_aliases[i] = mprStrdup(hp, ip->h_aliases[i]); - } - hp->h_aliases[i] = 0; - } - return hp; -} - -/******************************************************************************/ -/* - * Read a registry value. Returns allocated memory in buf. - */ - -int mprReadRegistry(MprCtx ctx, char **buf, int max, const char *key, - const char *name) -{ - HKEY top, h; - char *value; - ulong type, size; - - mprAssert(key && *key); - mprAssert(buf); - - /* - * Get the registry hive - */ - if ((key = getHive(key, &top)) == 0) { - return MPR_ERR_CANT_ACCESS; - } - - if (RegOpenKeyEx(top, key, 0, KEY_READ, &h) != ERROR_SUCCESS) { - return MPR_ERR_CANT_ACCESS; - } - - /* - * Get the type - */ - if (RegQueryValueEx(h, name, 0, &type, 0, &size) != ERROR_SUCCESS) { - RegCloseKey(h); - return MPR_ERR_CANT_READ; - } - if (type != REG_SZ && type != REG_EXPAND_SZ) { - RegCloseKey(h); - return MPR_ERR_BAD_TYPE; - } - - value = (char*) mprAlloc(ctx, size); - if ((int) size > max) { - RegCloseKey(h); - return MPR_ERR_WONT_FIT; - } - if (RegQueryValueEx(h, name, 0, &type, (uchar*) value, &size) != - ERROR_SUCCESS) { - mprFree(value); - RegCloseKey(h); - return MPR_ERR_CANT_READ; - } - - RegCloseKey(h); - *buf = value; - return 0; -} - -/******************************************************************************/ -/* - * Write a string registry value. Returns allocated memory in buf. - */ - -int mprWriteRegistry(MprCtx ctx, const char *key, const char *name, - const char *value) -{ - HKEY top, h, subHandle; - ulong disposition; - - mprAssert(key && *key); - mprAssert(name && *name); - mprAssert(value && *value); - - /* - * Get the registry hive - */ - if ((key = getHive(key, &top)) == 0) { - return MPR_ERR_CANT_ACCESS; - } - - if (name) { - /* - * Write a registry string value - */ - if (RegOpenKeyEx(top, key, 0, KEY_ALL_ACCESS, &h) != ERROR_SUCCESS) { - return MPR_ERR_CANT_ACCESS; - } - if (RegSetValueEx(h, name, 0, REG_SZ, value, strlen(value) + 1) - != ERROR_SUCCESS) { - RegCloseKey(h); - return MPR_ERR_CANT_READ; - } - - } else { - /* - * Create a new sub key - */ - if (RegOpenKeyEx(top, key, 0, KEY_CREATE_SUB_KEY, &h) != ERROR_SUCCESS){ - return MPR_ERR_CANT_ACCESS; - } - if (RegCreateKeyEx(h, name, 0, NULL, REG_OPTION_NON_VOLATILE, - KEY_ALL_ACCESS, NULL, &subHandle, &disposition) != ERROR_SUCCESS) { - return MPR_ERR_CANT_ACCESS; - } - RegCloseKey(subHandle); - } - RegCloseKey(h); - return 0; -} - -/******************************************************************************/ -/* - * Determine the registry hive by the first portion of the path. Return - * a pointer to the rest of key path after the hive portion. - */ - -static const char *getHive(const char *keyPath, HKEY *hive) -{ - char key[MPR_MAX_STRING], *cp; - int len; - - mprAssert(keyPath && *keyPath); - - *hive = 0; - - mprStrcpy(key, sizeof(key), keyPath); - key[sizeof(key) - 1] = '\0'; - - if (cp = strchr(key, '\\')) { - *cp++ = '\0'; - } - if (cp == 0 || *cp == '\0') { - return 0; - } - - if (!mprStrcmpAnyCase(key, "HKEY_LOCAL_MACHINE")) { - *hive = HKEY_LOCAL_MACHINE; - } else if (!mprStrcmpAnyCase(key, "HKEY_CURRENT_USER")) { - *hive = HKEY_CURRENT_USER; - } else if (!mprStrcmpAnyCase(key, "HKEY_USERS")) { - *hive = HKEY_USERS; - } else if (!mprStrcmpAnyCase(key, "HKEY_CLASSES_ROOT")) { - *hive = HKEY_CLASSES_ROOT; - } else { - return 0; - } - - if (*hive == 0) { - return 0; - } - len = strlen(key) + 1; - return keyPath + len; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c b/source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c deleted file mode 100644 index 74e59c9c73..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/WIN/mprTime.c +++ /dev/null @@ -1,192 +0,0 @@ -/** - * @file mprTime.c - * @brief Time handling for Windows - * @overview - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************* Includes ***********************************/ - -#include "mpr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/************************************ Code ************************************/ -/* - * Returns time in seconds and milliseconds. This is NOT time-of-day. - */ - -MprTime *mprGetTime(MprCtx ctx, MprTime *tp) -{ - FILETIME fileTime; - int64 now, base; - - GetSystemTimeAsFileTime(&fileTime); - - now = ((((int64) fileTime.dwHighDateTime) << BITS(uint)) + - ((int64) fileTime.dwLowDateTime)); - - /* - * Convert from 100-nanosec units to milliseconds - */ - now = (now / 10000); - - /* - * Adjust to be seconds since Jan 1 1970. Do this to be consistent with - * UNIX but not really required by the API definition. - */ - base = ((UINT64(365) * 86400 * (1970 - 1601)) * 1000); - now -= base; - tp->sec = (uint) (now / 1000); - tp->msec = (uint) (now % 1000); - -#if UNUSED -{ - static int64 start; - - if (start == 0) { - start = now; - } - if (now < start) { - mprLog(ctx, 0, "TIME WENT BACKWARDS"); - mprLog(ctx, 0, "start %Ld", start); - mprLog(ctx, 0, "now %Ld", now); - } - mprLog(ctx, 0, "getTime %Ld", now); - start = now; -} -#endif - - return tp; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of localtime - */ - -struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now) -{ - struct tm *tbuf; - mprGlobalLock(ctx); - tbuf = localtime(now); - *timep = *tbuf; - mprGlobalUnlock(ctx); - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of gmtime - */ - -struct tm *mprGmtime(MprCtx ctx, time_t *now, struct tm *timep) -{ - struct tm *tbuf; - tbuf = gmtime(now); - *timep = *tbuf; - - return timep; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of ctime - */ - -int mprCtime(MprCtx ctx, char *buf, int bufsize, const time_t *timer) -{ - char *cp; - int len; - - mprAssert(buf); - - mprGlobalLock(ctx); - - cp = ctime(timer); - if ((int) strlen(cp) >= bufsize) { - mprStrcpy(buf, bufsize, "WONT FIT"); - mprAssert(0); - mprGlobalUnlock(ctx); - return MPR_ERR_WONT_FIT; - } - - len = mprStrcpy(buf, bufsize, cp); - if (buf[len - 1] == '\n') { - buf[len - 1] = '\0'; - } - - mprGlobalUnlock(ctx); - - return 0; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of asctime - */ - -int mprAsctime(MprCtx ctx, char *buf, int bufsize, const struct tm *timeptr) -{ - char *cp; - - mprAssert(buf); - mprGlobalLock(ctx); - cp = asctime(timeptr); - if ((int) strlen(cp) >= bufsize) { - mprAssert(0); - mprGlobalUnlock(ctx); - return MPR_ERR_WONT_FIT; - } - mprStrcpy(buf, bufsize, cp); - mprGlobalUnlock(ctx); - - return strlen(buf); -} - -/******************************************************************************/ - -#ifdef __cplusplus -} -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/files b/source4/lib/appweb/ejs-2.0/mpr/files deleted file mode 100644 index 290c9ce790..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/files +++ /dev/null @@ -1,14 +0,0 @@ -${BLD_OBJ_DIR}/mpr${BLD_OBJ} -${BLD_OBJ_DIR}/mprAlloc${BLD_OBJ} -${BLD_OBJ_DIR}/mprArray${BLD_OBJ} -${BLD_OBJ_DIR}/mprBuf${BLD_OBJ} -${BLD_OBJ_DIR}/mprFile${BLD_OBJ} -${BLD_OBJ_DIR}/mprGenFile${BLD_OBJ} -${BLD_OBJ_DIR}/mprGenTime${BLD_OBJ} -${BLD_OBJ_DIR}/mprLock${BLD_OBJ} -${BLD_OBJ_DIR}/mprLog${BLD_OBJ} -${BLD_OBJ_DIR}/mprPlatform${BLD_OBJ} -${BLD_OBJ_DIR}/mprPrintf${BLD_OBJ} -${BLD_OBJ_DIR}/mprString${BLD_OBJ} -${BLD_OBJ_DIR}/mprSymbol${BLD_OBJ} -${BLD_OBJ_DIR}/mprTime${BLD_OBJ} diff --git a/source4/lib/appweb/ejs-2.0/mpr/mpr.c b/source4/lib/appweb/ejs-2.0/mpr/mpr.c deleted file mode 100644 index 163b51eccf..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mpr.c +++ /dev/null @@ -1,340 +0,0 @@ -/** - * @file mpr.c - * @brief Mpr initialization - * @overview - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -#include "mpr.h" - -/******************************************************************************/ -/* - * Initialize the MPR. Create the top level memory context. This routine is - * the first call an MPR application must do. If using MprServices, the - * creation of an Mpr object will call this routine. - */ - -MprApp *mprInit(MprAllocCback cback) -{ - return mprInitEx(cback, 0); -} - -/******************************************************************************/ -/* - * Add a shell parameter then do the regular init - */ - -MprApp *mprInitEx(MprAllocCback cback, void *shell) -{ - MprApp *app; - - app = (MprApp*) mprAllocInit(cback); - - mprAssert(app); - if (app == 0) { - return 0; - } - - app->name = mprStrdup(app, BLD_PRODUCT); - app->title = mprStrdup(app, BLD_NAME); - app->version = mprStrdup(app, BLD_VERSION); - - mprSetShell(app, shell); - - app->table = mprCreateSymbolTable(app, 0); - - if (mprStartFileServices(app) < 0) { - mprAllocTerm(app); - return 0; - } - -#if BLD_FEATURE_MULTITHREAD - mprInitThreads(app); -#endif - - /* - * See if any of the preceeding allocations failed - */ - if (mprGetAllocErrors(app) > 0) { - mprAllocTerm(app); - return 0; - } - - /* - * Mark all blocks allocated so far as required. They will then be - * omitted from leak reports. - */ - mprSetRequiredAlloc(app, 1); - - return app; -} - -/******************************************************************************/ -/* - * Terminate the MPR. If doStats is true, then output a memory allocation - * report. - */ - -void mprTerm(MprApp *app, bool doStats) -{ -#if BLD_FEATURE_ALLOC_STATS - if (doStats) { - mprPrintAllocReport(app, 1, "MPR Memory Allocation Report"); - } -#endif - -#if BLD_FEATURE_MULTITHREAD - mprTermThreads(app); -#endif - - mprStopFileServices(app); - -#if BLD_DEBUG - mprValidateAllocTree(app); -#endif - mprAllocTerm(app); -} - -/******************************************************************************/ - -bool mprIsExiting(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - if (app == 0) { - return 1; - } - return app->flags & MPR_APP_EXITING; -} - -/******************************************************************************/ - -int mprHasAllocError(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - if (app == 0) { - return 1; - } - - return app->flags & MPR_APP_ALLOC_ERROR; -} - -/******************************************************************************/ - -void mprSignalExit(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - app->flags |= MPR_APP_EXITING; -} - -/******************************************************************************/ - -void mprSignalAllocError(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - app->flags |= MPR_APP_ALLOC_ERROR; -} - -/******************************************************************************/ - -int mprSetAppName(MprCtx ctx, const char *name, const char *title, - const char *version) -{ - MprApp *app; - - app = mprGetApp(ctx); - - if (name) { - mprFree(app->name); - if ((app->name = mprStrdup(ctx, name)) == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - } - - if (title) { - mprFree(app->title); - if ((app->title = mprStrdup(ctx, title)) == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - } - - if (version) { - mprFree(app->version); - if ((app->version = mprStrdup(ctx, version)) == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - } - return 0; -} - -/******************************************************************************/ - -const char *mprGetAppName(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - return app->name; -} - -/******************************************************************************/ - -const char *mprGetAppTitle(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - return app->title; -} - -/******************************************************************************/ - -const char *mprGetAppVersion(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - return app->version; -} - -/******************************************************************************/ - -int mprSetKeyValue(MprCtx ctx, const char *key, void *ptr) -{ - MprApp *app; - - app = mprGetApp(ctx); - if (mprInsertSymbol(app->table, key, ptr) == 0) { - return MPR_ERR_CANT_WRITE; - } - return 0; -} - -/******************************************************************************/ - -int mprRemoveKeyValue(MprCtx ctx, const char *key) -{ - MprApp *app; - - app = mprGetApp(ctx); - return mprRemoveSymbol(app->table, key); -} - -/******************************************************************************/ - -void *mprGetKeyValue(MprCtx ctx, const char *key) -{ - MprApp *app; - - app = mprGetApp(ctx); - return mprLookupSymbol(app->table, key); -} - -/******************************************************************************/ - -bool mprGetDebugMode(MprCtx ctx) -{ - return mprGetApp(ctx)->debugMode; -} - -/******************************************************************************/ - -void mprSetDebugMode(MprCtx ctx, bool on) -{ - mprGetApp(ctx)->debugMode = on; -} - -/******************************************************************************/ - -void mprSetLogHandler(MprCtx ctx, MprLogHandler handler) -{ - mprGetApp(ctx)->logHandler = handler; -} - -/******************************************************************************/ - -MprLogHandler mprGetLogHandler(MprCtx ctx) -{ - return mprGetApp(ctx)->logHandler; -} - -#if UNUSED -/******************************************************************************/ - -void mprSetMprInstance(MprCtx ctx, void *mprInstance) -{ - mprGetApp(ctx)->mprInstance = mprInstance; -} - -/******************************************************************************/ - -void *mprGetMprInstance(MprCtx ctx) -{ - return mprGetApp(ctx)->mprInstance; -} - -#endif -/******************************************************************************/ - -const char *mprCopyright() -{ - return "Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved."; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mpr.h b/source4/lib/appweb/ejs-2.0/mpr/mpr.h deleted file mode 100644 index 67505a6e01..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mpr.h +++ /dev/null @@ -1,1027 +0,0 @@ -/* - * @file mpr.h - * @brief Header for the Mbedthis Portable Runtime (MPR) Base. - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/******************************* Documentation ********************************/ -/* - * See mpr.dox for additional documentation. - */ - -/******************************************************************************/ - -#ifndef _h_MPR -#define _h_MPR 1 - -/***********************************Includes **********************************/ - -#include "mprOs.h" - -/******************************************************************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************** Constants *********************************/ - -#if BLD_FEATURE_SQUEEZE -#if BREW || DOXYGEN -/* - * Maximum length of a file path name. Reduced from the system maximum to - * save memory space. - */ -#define MPR_MAX_FNAME 64 /**< Reasonable filename size */ -#define MPR_MAX_PATH 64 /**< Reasonable path name size */ -#define MPR_DEFAULT_STACK (16 * 1024) /**< Default stack size */ -#else -#define MPR_MAX_FNAME 128 /**< Reasonable filename size */ -#define MPR_MAX_PATH 256 /**< Reasonable path name size */ -#define MPR_DEFAULT_STACK (32 * 1024) /**< Default stack size */ -#endif -/* - * Reasonable length of a file name used by the product. Use where you know - * the expected file name and it is certain to be less than this limit. - */ -#define MPR_DEFAULT_ALLOC 64 /**< Default small alloc size */ -#define MPR_DEFAULT_HASH_SIZE 23 /**< Default size of hash table */ -#define MPR_MAX_ARGC 32 /**< Reasonable max of args */ -#define MPR_MAX_STRING 512 /**< Maximum (stack) string size */ -#define MPR_MAX_LOG_STRING 512 /**< Maximum log message */ -#define MPR_MAX_URL 256 /**< Reasonable size of a URL */ -#define MPR_BUFSIZE 512 /**< Reasonable size for buffers */ -#define MPR_SLAB_STR_MAX 32 /**< Size of string slab blocks */ -#define MPR_SLAB_STR_INC 32 /**< Pre-allocate increment */ -#define MPR_SLAB_DEFAULT_INC 8 /**< Default pre-allocate inc */ -#define MPR_ARRAY_INCR 8 /**< Default array growth inc */ -#define MPR_BUF_INCR 1024 /**< Default array growth inc */ -#define MPR_MAX_BUF (1024*4096) /**< Default array growth inc */ - -#define MPR_BLK_HDR_SIZE ((sizeof(struct MprBlk) + 3) & ~3) - -#else -#define MPR_MAX_FNAME 256 -#define MPR_MAX_PATH 1024 -#define MPR_DEFAULT_ALLOC 256 -#define MPR_DEFAULT_HASH_SIZE 43 -#define MPR_DEFAULT_STACK (64 * 1024) -#define MPR_MAX_ARGC 128 -#define MPR_MAX_STRING 4096 -#define MPR_MAX_LOG_STRING 8192 -#define MPR_MAX_URL 1024 -#define MPR_BUFSIZE 1024 -#define MPR_SLAB_STR_MAX 32 -#define MPR_SLAB_STR_INC 64 -#define MPR_SLAB_DEFAULT_INC 16 -#define MPR_ARRAY_INCR 16 -#define MPR_BUF_INCR 1024 -#define MPR_MAX_BUF (1024*4096) - -#define MPR_BLK_HDR_SIZE ((sizeof(struct MprBlk) + 15) & ~15) -#endif - -/** - * Maximum size of a host name string - */ -#define MPR_MAX_IP_NAME 64 - -/** - * Maximum size of an IP address - */ -#define MPR_MAX_IP_ADDR 16 - -/** - * Maximum size of an IP address including port number - */ -#define MPR_MAX_IP_ADDR_PORT 32 - -#define MPR_MAX_SLAB 16 /* Slabs from 32-512 bytes */ - -#define MPR_MAX_TIME_SYNC (10 * 1000) /* Time sync adjustments */ - -/** - * @overview Memory context type - * @description Blocks of memory are allocated using a memory context - * as the parent with the \ref MprApp structure being the root of the - * tree. Any allocated memory block may serve as the memory context for - * subsequent memory allocations. Freeing a block via \ref mprFree will - * release the allocated block and all child blocks. - * @stability Prototype. - * @library libmpr. - * @see mprInit, mprAlloc, mprFree - */ -typedef const void *MprCtx; - -/* - * Allocated memory destructor type - */ -typedef int (*MprDestructor)(void *); - -/******************************** Error Codes *********************************/ - -/* - * Standard MPR return and error codes - */ - -#define MPR_ERR_OK (0) -/**< Success */ - -#define MPR_ERR_BASE (-200) -/**< Base error code */ - -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) -/**< General error */ -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) -/**< Action aborted */ -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) -/**< Item already exists */ -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) -/**< Bad arguments or paramaeters */ -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) -/**< Bad input format */ -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) -/**< Module is in a bad state */ -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) -/**< Input has bad syntax */ -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) -/**< Can't access the file or resource */ -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) -/**< Can't create the file or resource */ -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) -/**< Can't open the file or resource */ -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) -/**< Can't read from the file or resource */ -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) -/**< Can't write to the file or resource */ -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) -/**< Module or resource is not initialized */ -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) -/**< The operation timed out */ -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) -// MOB -- rename NO_MEMORY -#define MPR_ERR_MEMORY (MPR_ERR_BASE - 30) -#define MPR_ERR_CANT_DELETE (MPR_ERR_BASE - 31) -#define MPR_ERR_MAX (MPR_ERR_BASE - 32) - -/* - * Standard logging trace levels are 0 to 9 with 0 being the most verbose. - * the These are ored with the error source and type flags. The MPR_LOG_MASK - * is used to extract the trace level from a flags word. We expect most apps - * to run with level 2 trace enabled. - */ -#define MPR_ERROR 1 /**< Hard error trace level */ -#define MPR_WARN 2 /**< Soft warning trace level */ -#define MPR_CONFIG 2 /**< Configuration settings trace level. */ -#define MPR_INFO 3 /**< Informational trace only */ -#define MPR_DEBUG 4 /**< Debug information trace level */ -#define MPR_VERBOSE 9 /**< Highest level of trace */ -#define MPR_LEVEL_MASK 0xf /**< Level mask */ - -/* - * Error source flags - */ -#define MPR_ERROR_SRC 0x10 /**< Originated from mprError */ -#define MPR_LOG_SRC 0x20 /**< Originated from mprLog */ -#define MPR_ASSERT_SRC 0x40 /**< Originated from mprAssert */ -#define MPR_FATAL_SRC 0x80 /**< Fatal error. Log and exit */ - -/* - * Log message type flags. Specify what kind of log / error message it is. - * Listener handlers examine this flag to determine if they should process - * the message.Assert messages are trapped when in DEV mode. Otherwise ignored. - */ -#define MPR_LOG_MSG 0x100 /**< Log trace message - not an error */ -#define MPR_ERROR_MSG 0x200 /**< General error */ -#define MPR_ASSERT_MSG 0x400 /**< Assert flags -- trap in debugger */ -#define MPR_USER_MSG 0x800 /**< User message */ - -/* - * Log output modifiers - */ -#define MPR_RAW 0x1000 /**< Raw trace output */ - -/* - * Error line number information. - */ -#define MPR_LINE(s) #s -#define MPR_LINE2(s) MPR_LINE(s) -#define MPR_LINE3 MPR_LINE2(__LINE__) -#define MPR_LOC __FILE__ ":" MPR_LINE3 - -/* - * Macros to pass file and line number information - * Use MPR_LOC_ARGS in normal user code. - * Use MPR_LOC_DEC in declarations. - * Use MPR_LOC_PASS in layered APIs to pass original line info down. - */ -#if BLD_FEATURE_ALLOC_LEAK_TRACK -#define MPR_LOC_ARGS(ctx) ctx, MPR_LOC -#define MPR_LOC_DEC(ctx, loc) MprCtx ctx, const char *loc -#define MPR_LOC_PASS(ctx, loc) ctx, loc -#else -#define MPR_LOC_ARGS(ctx) ctx -#define MPR_LOC_DEC(ctx, loc) MprCtx ctx -#define MPR_LOC_PASS(ctx, loc) ctx -#endif - -/******************************* Debug and Assert *****************************/ - -extern void mprBreakpoint(const char *loc, const char *msg); - -#if BLD_FEATURE_ASSERT - #define mprAssert(C) if (C) ; else mprStaticAssert(MPR_LOC, #C) -#else - #define mprAssert(C) if (1) ; else -#endif - -/********************************* Safe Strings *******************************/ -/* - * Unsafe functions that should not be used. Define UNSAFE_STRINGS_OK before - * including mpr.h if you really want to use these functions. A better approach - * is to undefine them just prior to using them in your C/C++ source file. - */ -#if BLD_FEATURE_SAFE_STRINGS - -#if BLD_FEATURE_PHP4_MODULE || BLD_FEATURE_PHP5_MODULE - #ifndef UNSAFE_FUNCTIONS_OK - #define UNSAFE_FUNCTIONS_OK 1 - #endif -#endif - -#ifndef UNSAFE_FUNCTIONS_OK - #define sprintf UseMprSprintfInstead - #define fprintf UseMprFprintfInstead - #define vsprintf UseMprVsprintfInstead - #define strtok UseMprStrTokInstead - #define gethostbyname UseMprGetHostByNameInstead - #define ctime UseMprCtimeInstead - #define asctime UseMprAsctimeInstead - #define localtime UseMprLocaltimeInstead - #define gmtime UseMprGmtimeInstead - #define malloc UseMprMallocInstead - #define free UseMprFreeInstead - #define realloc UseMprReallocInstead - #define strncpy UseMprStrcpyInstead - #define inet_ntoa UseMprInetToStrInstead - -#if !BREW - #define printf UseMprPrintfInstead -#endif - - #if FUTURE - #define strlen UseMprStrlenInstead - #define strcpy UseMprStrcpyInstead - #endif - -#endif /* UNSAFE_FUNCTIONS_OK */ -#endif /* BLD_FEATURE_SAFE_STRINGS */ - -/******************************************************************************/ - -struct MprBuf; -typedef int (*MprBufProc)(struct MprBuf* bp, void *arg); - -/** - * @overview Dynamic buffer structure - * @description MprBuf is a flexible, dynamic growable buffer structure. It - * utilizes a ring buffer mechanism and is suitable for high performance - * buffering in a variety of situations. - * @stability Prototype. - * @library libmpr. - * @see mprCreateBuf, mprFree, MprArray - */ -typedef struct MprBuf { - uchar *buf; /* Actual buffer for data */ - uchar *endbuf; /* Pointer one past the end of buffer */ - uchar *start; /* Pointer to next data char */ - uchar *end; /* Pointer one past the last data chr */ - int buflen; /* Current size of buffer */ - int maxsize; /* Max size the buffer can ever grow */ - int growBy; /* Next growth increment to use */ - MprBufProc refillProc; /* Auto-refill procedure */ - void *refillArg; /* Refill arg */ -} MprBuf; - -/** - * @overview File structure - * @description MprFile is the cross platform File I/O abstraction control - * structure. - * @stability Prototype. - * @library libmpr. - * @see mprOpen, mprClose, mprRead, mprWrite - */ -typedef struct MprFile -{ - MprBuf *buf; /* Buffer for I/O */ -#if BREW - IFile *fd; /* File handle */ -#else - int fd; -#endif -} MprFile; - -/** - * File information structure - * @overview File information structure - * @description MprFileInfo is the cross platform File information structure. - * @stability Prototype. - * @see mprGetFileInfo, mprOpen, mprClose, mprRead, mprWrite - */ -typedef struct MprFileInfo -{ - uint size; /* File length */ - uint ctime; /* Create time */ - uint mtime; /* Modified time */ - uint inode; /* Inode number */ - int isDir; /* Set if directory */ - int isReg; /* Set if a regular file */ -} MprFileInfo; - -/** - * @overview Mpr time structure. - * @description MprTime is the cross platform time abstraction structure. - * @stability Prototype. - * @library libmpr. - * @see mprGetTime - */ -typedef struct MprTime -{ - uint sec; /* Seconds */ - uint msec; /* Milliseconds */ -} MprTime; - - -/** - * @overview Generic array type - * @description The MprArray is a dynamic growable array suitable for storing - * pointers to arbitrary objects. - * @stability Prototype. - * @library libmpr. - * @see mprCreateItemArray, mprFree, MprBuf - */ -typedef struct MprArray -{ - int capacity; /* Current capacity of the array */ - int length; /* Count of used items */ - int incr; /* Growth increment */ - int maxSize; /* Maximum capacity */ - void **items; -} MprArray; - - -#if BLD_FEATURE_MULTITHREAD -/** - * @overview Multithreading lock control structure - * @description MprLock is used for multithread locking in multithreaded - * applications. - * @library libmpr. - * @see mprCreateLock, mprDestroyLock, mprLock, mprUnlock - */ -typedef struct -{ - #if WIN - CRITICAL_SECTION cs; /* O/S critical section */ - #endif - #if LINUX || MACOSX || SOLARIS - pthread_mutex_t cs; /* O/S critical section */ - #endif - #if VXWORKS - SEM_ID cs; /* Semaphore */ - #endif -} MprLock; -#endif - -/* - * Error and Logging callback - */ -typedef void (*MprLogHandler)(MPR_LOC_DEC(ctx, loc), int flags, - int level, const char *msg); - -/* - * Symbol table - * MOB -- rename hash - */ -typedef struct MprSymbol -{ - struct MprSymbol *next; /* Next symbol in hash chain */ - char *key; /* Symbol key */ - void *data; /* Pointer to symbol data */ - int bucket; /* Hash bucket index */ -} MprSymbol; - -typedef struct MprSymbolTable -{ - MprSymbol **buckets; - int hashSize; /* Size of the buckets array */ - int count; /* Number of symbols in the table */ -} MprSymbolTable; - - -/* - * Memory allocation error callback - */ -struct MprApp; -typedef int (*MprAllocCback)(struct MprApp *app, uint size, uint total, - bool granted); - - -/* - * Slab block pointer links - */ -typedef struct MprSlabBlock { - struct MprSlabBlock *next; -} MprSlabBlock; - - -#if BLD_FEATURE_ALLOC_STATS -/* - * Memory Slab Statistics - */ -typedef struct MprSlabStats { - uint allocCount; /* Number of allocated blocks */ - uint freeCount; /* Number of blocks on the slab freelist */ - uint peakAllocCount; /* Peak allocated */ - uint totalAllocCount; /* Total count of allocation calls */ - uint peakFreeCount; /* Peak on the free list */ - MprSlabBlock *next; -} MprSlabStats; -#endif - - -/* - * Slab control structure - */ -typedef struct MprSlab { - MprSlabBlock *next; - uint preAllocateIncr; /* Pre-allocation increment */ -#if BLD_FEATURE_ALLOC_STATS - MprSlabStats stats; -#endif -} MprSlab; - -/* - * Allocation stats (kept even in production code so we can detect memory - * allocation failures) - */ -typedef struct MprAllocStats -{ - uint bytesAllocated; /* Bytes currently allocated */ - uint peakAllocated; /* Peak bytes allocated */ - uint allocCount; /* Number of allocated blocks */ - uint redLine; /* Warn above this level */ - uint maxMemory; /* Max memory to allocate */ - uint errors; /* Allocation errors */ -} MprAllocStats; - -/* - * Memory allocation control - */ - -typedef struct MprAlloc { - MprSlab *slabs; /* Array[MPR_MAX_SLAB] of MprSlab */ - MprAllocCback cback; /* Memory allocation callback */ - MprAllocStats stats; /* Keep stats even in release */ - int inAllocException; /* Recursive protect */ -} MprAlloc; - - -/* - * MprApp State Flags - */ -#define MPR_APP_EXITING 0x1 /* App is exiting */ -#define MPR_APP_ALLOC_ERROR 0x2 /* App has allocation error */ - -/* MOB -- temporary */ -#define MPR_APP_NEED_GC 0x4 /* App needs GC */ - -/** - * @overview Primary MPR application control structure - * @description The MprApp structure stores critical application state - * information and is the root memory allocation context block. It is - * used as the MprCtx context for other memory allocations and is thus - * the ultimate parent of all allocated memory. - * \n\n - * The MprApp structure is allocated by the mprInit API. - */ -typedef struct MprApp -{ - uint magic; /* Corruption protection */ - MprFile *console; /* Stdout file */ - bool debugMode; /* Run in debug mode (no timers) */ - MprFile *error; /* Stderr file */ - int logLevel; /* Log trace level */ - MprFile *logFile; /* Log file */ - MprLogHandler logHandler; /* Current log handler callback */ - MprSymbolTable *table; - char *name; /* Product name */ - char *title; /* Product title */ - char *version; /* Product version */ - -#if BREW - uint classId; /* Brew class ID */ - IShell *shell; /* Brew shell object */ - IDisplay *display; /* Brew display object */ - IFileMgr *fileMgr; /* File manager */ - ITAPI *tapi; /* TAPI object */ - int displayHeight; /* Display height */ - int displayWidth; /* Display width */ - char *args; /* Command line args */ -#endif - - void *stackStart; /* Start of app stack */ - uint maxStack; /* Max stack size recorded */ - - MprAlloc alloc; /* Memory allocation data */ - int flags; /* App state flags */ - -#if BLD_FEATURE_MULTITHREAD - MprLock *globalLock; - MprLock *allocLock; -#endif -} MprApp; - - -/* - * String type. Minimum size is 8 words (32 bytes). - */ -#define MPR_MAX_INLINE_STR 24 - - -/* - * The block header structure for all allocated memory blocks (32 bytes) - * WARNING: Don't increase the size of this structure. It just fits into - * 32 bytes currently. Alignment requirements will double this size if you - * add one byte! - */ -typedef struct MprBlk -{ - MprApp *app; /* app is the top level alloc context */ - struct MprBlk *parent; /* Parent block */ - struct MprBlk *children; /* First child block */ - struct MprBlk *next; /* Next sibling */ - struct MprBlk *prev; /* Previous sibling */ - MprDestructor destructor; /* Destructor function (optional) */ - uint size; /* Size of block sans HDR_SIZE */ - uint flags; /* Allocation flags and magic number */ -#if BLD_FEATURE_ALLOC_LEAK_TRACK - const char *location; /* Allocating code (file + line) */ -#endif -} MprBlk; - -/******************************************************************************/ -/****************************** Internal Prototypes ***************************/ -/******************************************************************************/ - -extern void mprSignalAllocError(MprCtx ctx); - -/******************************************************************************/ -/********************************** Prototypes ********************************/ -/******************************************************************************/ - -extern MprApp *mprInit(MprAllocCback cback); -extern MprApp *mprInitEx(MprAllocCback cback, void *shell); -extern void mprTerm(MprApp *app, bool doStats); -extern void mprSignalExit(MprCtx ctx); -extern bool mprIsExiting(MprCtx ctx); -extern bool mprHasAllocError(MprCtx ctx); - -#if BLD_DEBUG && UNUSED -extern MprApp *mprGetApp(MprCtx ctx); -#else -#define mprGetApp(ctx) \ - (((MprBlk*) ((char*) ctx - MPR_BLK_HDR_SIZE))->app) -#endif - -/******************************************************************************/ - -extern int mprSetKeyValue(MprCtx ctx, const char *key, void *ptr); -/* MOB -- should this be delete or remove or unset */ -extern int mprRemoveKeyValue(MprCtx ctx, const char *key); -extern void *mprGetKeyValue(MprCtx ctx, const char *key); -/* MOB -- should be setAppName, getAppName */ -extern int mprSetAppName(MprCtx ctx, const char *name, const char *title, - const char *version); -extern const char *mprGetAppName(MprCtx ctx); -extern const char *mprGetAppTitle(MprCtx ctx); -extern const char *mprGetAppVersion(MprCtx ctx); - -/* - * File services - */ -extern void mprStopFileServices(MprCtx ctx); -extern int mprStartFileServices(MprCtx ctx); - -/* - * Item Array - */ -#define mprCreateItemArray(ctx, initialSize, maxSize) \ - mprCreateItemArrayInternal(MPR_LOC_ARGS(ctx), initialSize, \ - maxSize) - -extern MprArray *mprCreateItemArrayInternal(MPR_LOC_DEC(ctx, loc), - int initialSize, int maxSize); -/* MOB -- should be insert not add/delete or insert / remove */ -extern int mprAddItem(MprArray *array, void *item); -extern void mprClearItems(MprArray *array); -extern void mprClearAndFreeItems(MprArray *array); -extern int mprFindItem(MprArray *array, void *item); -extern void *mprGetFirstItem(MprArray *array, int *lastIndex); -extern void *mprGetItem(MprArray *array, int index); -extern int mprGetItemCapacity(MprArray *array); -extern int mprGetItemCount(MprArray *array); -extern void *mprGetNextItem(MprArray *array, int *lastIndex); -extern void *mprGetPrevItem(MprArray *array, int *lastIndex); -extern int mprRemoveItem(MprArray *array, void *item); -extern int mprRemoveItemByIndex(MprArray *array, int index); -extern int mprRemoveRangeOfItems(MprArray *array, int start, int end); - - -/* - * Printf replacements - */ -extern int mprSprintf(char *buf, int maxSize, const char *fmt, ...) - PRINTF_ATTRIBUTE(3,4); -extern int mprVsprintf(char *buf, int maxSize, const char *fmt, - va_list arg) PRINTF_ATTRIBUTE(3,0); -extern char *mprItoa(char *buf, int size, int value); -extern int mprAtoi(const char *str, int radix); - -extern int mprPrintf(MprCtx ctx, const char *fmt, ...) - PRINTF_ATTRIBUTE(2,3); -/* MOB -- NEED DOC */ -extern int mprErrorPrintf(MprCtx ctx, const char *fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern int mprStaticPrintf(MprCtx ctx, const char *fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern int mprPrintfError(MprCtx ctx, const char *fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern int mprFprintf(MprFile *file, const char *fmt, ...) - PRINTF_ATTRIBUTE(2,3); - -/* - * Safe string routines - */ -extern char *mprGetWordTok(char *buf, int bufsize, const char *str, - const char *delim, const char **tok); -extern int mprMemcpy(char *dest, int destMax, const char *src, - int nbytes); -extern int mprStrcat(char *dest, int max, const char *delim, - const char *src, ...); -extern int mprStrcpy(char *dest, int destMax, const char *src); - -extern int mprStrcmpAnyCase(const char *str1, const char *str2); -extern int mprStrcmpAnyCaseCount(const char *str1, const char *str2, - int len); -extern int mprStrlen(const char *src, int max); - -extern char *mprStrLower(char *str); -extern char *mprStrUpper(char *str); -extern char *mprStrTrim(char *str, const char *set); -extern char *mprStrTok(char *str, const char *delim, char **last); - -/* - * Symbol table - */ -extern MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize); -extern MprSymbol *mprGetFirstSymbol(MprSymbolTable *table); -extern MprSymbol *mprGetNextSymbol(MprSymbolTable *table, MprSymbol *last); -extern int mprGetSymbolCount(MprSymbolTable *table); -extern MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key, - void *ptr); -extern void *mprLookupSymbol(MprSymbolTable *table, const char *key); -extern int mprRemoveSymbol(MprSymbolTable *table, const char *key); - -/* - * File I/O support - */ -extern void mprClose(MprFile *file); -extern int mprDelete(MprCtx ctx, const char *path); -extern int mprDeleteDir(MprCtx ctx, const char *path); -extern int mprGetFileInfo(MprCtx ctx, const char *path, MprFileInfo *info); -extern char *mprGets(MprFile *file, char *buf, uint size); -extern int mprMakeDir(MprCtx ctx, const char *path, int perms); -extern MprFile *mprOpen(MprCtx ctx, const char *path, int omode, int perms); -extern int mprPuts(MprFile *file, const char *buf, uint size); -extern int mprRead(MprFile *file, void *buf, uint size); -extern int mprSeek(MprFile *file, int seekType, long distance); -extern int mprWrite(MprFile *file, const void *buf, uint count); - -extern int mprMakeTempFileName(MprCtx ctx, char *buf, int bufsize, - const char *tmpDir); - - -/* - * Error handling and logging - */ -extern void mprSetLogHandler(MprCtx ctx, MprLogHandler handler); -extern MprLogHandler mprGetLogHandler(MprCtx ctx); - -extern void mprAssertError(MPR_LOC_DEC(ctx, loc), const char *msg); -extern void mprError(MPR_LOC_DEC(ctx, loc), - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern void mprFatalError(MPR_LOC_DEC(ctx, loc), - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern void mprLog(MprCtx ctx, int level, - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern void mprRawLog(MprCtx ctx, const char *fmt, ...); -extern void mprStaticAssert(const char *loc, const char *msg); -extern void mprStaticError(MPR_LOC_DEC(ctx, loc), - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern void mprUserError(MPR_LOC_DEC(ctx, loc), - const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); - -/* - * Dynamic Buffering routines - */ -extern MprBuf *mprCreateBuf(MprCtx ctx, int initialSize, int maxSize); -extern char *mprStealBuf(MprCtx ctx, MprBuf *bp); -extern void mprAddNullToBuf(MprBuf *bp); -extern void mprAdjustBufStart(MprBuf *bp, int size); -extern void mprAdjustBufEnd(MprBuf *bp, int size); -extern void mprCopyBufDown(MprBuf *bp); -extern void mprFlushBuf(MprBuf *bp); -extern int mprGetCharFromBuf(MprBuf *bp); -extern int mprGetBlockFromBuf(MprBuf *bp, uchar *buf, int len); -extern int mprGetBufLength(MprBuf *bp); -extern int mprGetBufLinearSpace(MprBuf *bp); -extern int mprGetBufLinearData(MprBuf *bp); -extern char *mprGetBufOrigin(MprBuf *bp); -extern int mprGetBufSize(MprBuf *bp); -extern int mprGetBufSpace(MprBuf *bp); -extern char *mprGetBufStart(MprBuf *bp); -extern char *mprGetBufEnd(MprBuf *bp); -extern int mprInsertCharToBuf(MprBuf *bp, int c); -extern int mprLookAtNextCharInBuf(MprBuf *bp); -extern int mprLookAtLastCharInBuf(MprBuf *bp); -extern int mprPutCharToBuf(MprBuf *bp, int c); -extern int mprPutBlockToBuf(MprBuf *bp, const char *str, int size); -extern int mprPutIntToBuf(MprBuf *bp, int i); -extern int mprPutStringToBuf(MprBuf *bp, const char *str); -extern int mprPutFmtStringToBuf(MprBuf *bp, const char *fmt, ...); -extern int mprRefillBuf(MprBuf *bp); -extern void mprResetBufIfEmpty(MprBuf *bp); -extern void mprSetBufSize(MprBuf *bp, int initialSize, int maxSize); -extern MprBufProc mprGetBufRefillProc(MprBuf *bp); -extern void mprSetBufRefillProc(MprBuf *bp, MprBufProc fn, void *arg); - -/* - * General other xPlatform routines - */ -extern const char *mprGetBaseName(const char *name); -extern bool mprGetDebugMode(MprCtx ctx); -extern char *mprGetDirName(char *buf, int bufsize, const char *path); -extern char *mprGetFullPathName(char *buf, int buflen, const char *path); -extern int mprGetLogLevel(MprCtx ctx); -extern int mprGetOsError(); - - -extern int mprMakeArgv(MprCtx ctx, const char *prog, const char *cmd, - char ***argv, int *argc); -extern int mprMakeDirPath(MprCtx ctx, const char *path); -extern void mprSetDebugMode(MprCtx ctx, bool on); -extern void mprSetLogLevel(MprCtx ctx, int level); -extern void mprSleep(MprCtx ctx, int msec); -extern void mprSetShell(MprCtx ctx, void *shell); -extern void *mprGetShell(MprCtx ctx); -extern void mprSetClassId(MprCtx ctx, uint classId); -extern uint mprGetClassId(MprCtx ctx); - -#if BREW -extern void mprSetDisplay(MprCtx ctx, void *display); -extern void *mprGetDisplay(MprCtx ctx); -extern void mprSetFileMgr(MprCtx ctx, void *fileMgr); -extern void *mprGetFileMgr(MprCtx ctx); -#else -extern char *mprInetToStr(char *buf, int size, const struct in_addr in); -#endif - -/* - * Memory allocation - */ -extern MprApp *mprAllocInit(MprAllocCback cback); -extern void mprAllocTerm(MprApp *app); -extern void mprAllocAbort(); - -extern void *mprAllocBlock(MPR_LOC_DEC(ctx, loc), uint size); -extern void *mprAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size); -extern void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size); -extern int mprFree(void *ptr); -extern int mprStealAllocBlock(MPR_LOC_DEC(ctx, loc), const void *ptr); -extern void *mprMemdupInternal(MPR_LOC_DEC(ctx, loc), const void *ptr, - uint size); -extern char *mprStrndupInternal(MPR_LOC_DEC(ctx, loc), const char *str, - uint size); -extern char *mprStrdupInternal(MPR_LOC_DEC(ctx, loc), const char *str); - -extern void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc); -extern void *mprSlabAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size, - uint inc); - -extern uint mprGetAllocBlockSize(MprCtx ctx); -extern uint mprGetAllocBlockCount(MprCtx ctx); -extern uint mprGetAllocBlockMemory(MprCtx ctx); -extern void *mprGetAllocParent(MprCtx ctx); -extern uint mprGetAllocatedMemory(MprCtx ctx); -extern uint mprGetPeakAllocatedMemory(MprCtx ctx); -extern uint mprGetAllocatedSlabMemory(MprCtx ctx); -extern int mprIsAllocBlockValid(MprCtx ctx); -extern int mprStackCheck(MprCtx ctx); -extern int mprStackSize(MprCtx ctx); -extern int mprGetAllocErrors(MprCtx ctx); -extern void mprClearAllocErrors(MprCtx ctx); - -extern MprDestructor mprSetDestructor(MprCtx ctx, MprDestructor destructor); -extern MprAllocCback mprSetAllocCallback(MprApp *app, MprAllocCback cback); -extern void mprSetAllocLimits(MprApp *app, uint redLine, uint maxMemory); - -#if BLD_FEATURE_ALLOC_STATS -extern MprSlabStats *mprGetSlabAllocStats(MprApp *app, int slabIndex); -extern MprAllocStats *mprGetAllocStats(MprApp *app); -extern void mprPrintAllocReport(MprApp *app, bool doBlocks, - const char *msg); -#endif - -#if BLD_DEBUG -extern int mprPrintAllocBlocks(MprCtx ctx, int indent); -extern const char *mprGetAllocLocation(MprCtx ptr); -#endif - -extern int mprValidateBlock(MprCtx ctx); -extern int mprValidateAllocTree(MprCtx ptr); -extern void mprSetRequiredAlloc(MprCtx ptr, bool recurse); - -/* - * Sprintf style allocators - */ -extern int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, - const char *fmt, ...) PRINTF_ATTRIBUTE(5,6); -extern int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, - const char *fmt, va_list arg) PRINTF_ATTRIBUTE(5,0); -extern int mprAllocMemcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax, - const void *src, int nbytes); -extern int mprAllocStrcat(MPR_LOC_DEC(ctx, loc), char **dest, int max, - const char *delim, const char *src, ...); -extern int mprAllocStrcpy(MPR_LOC_DEC(ctx, loc), char **dest, int max, - const char *src); -extern int mprReallocStrcat(MPR_LOC_DEC(ctx, loc), char **dest, int max, - int existingLen, const char *delim, const char *src, ...); - -/* - * MACROS: These are the convenience macros to automatically supply file - * names and line numbers when debugging. - */ -#define mprNew(ctx) new(MPR_LOC_ARGS(ctx)) - -#define mprAlloc(ctx, size) mprAllocBlock(MPR_LOC_ARGS(ctx), size) - -#define mprAllocZeroed(ctx, size) mprAllocZeroedBlock(MPR_LOC_ARGS(ctx), size) - -#define mprSlabAlloc(ctx, size, inc) \ - ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), size, inc)) - -#define mprSlabAllocZeroed(ctx, size, inc) \ - ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), size, inc)) - -#define mprRealloc(ctx, ptr, size) mprReallocBlock(MPR_LOC_ARGS(ctx), ptr, size) - -#define mprMemdup(ctx, ptr, size) \ - mprMemdupInternal(MPR_LOC_ARGS(ctx), ptr, size) - -#define mprStrdup(ctx, str) mprStrdupInternal(MPR_LOC_ARGS(ctx), str) - -#define mprStrndup(ctx, str, size) mprStrndupDebug(MPR_LOC_ARGS(ctx), str, size) - -/* - * Allocate type macros - */ -#define mprAllocType(ctx, type) \ - ((type*) mprAllocBlock(MPR_LOC_ARGS(ctx), sizeof(type))) - -#define mprAllocTypeZeroed(ctx, type) \ - ((type*) mprAllocZeroedBlock(MPR_LOC_ARGS(ctx), sizeof(type))) - -#define mprSlabAllocType(ctx, type, inc) \ - ((type*) mprSlabAllocBlock(MPR_LOC_ARGS(ctx), sizeof(type), inc)) - -#define mprSlabAllocTypeZeroed(ctx, type, inc) \ - ((type*) mprSlabAllocZeroedBlock(MPR_LOC_ARGS(ctx), sizeof(type), \ - inc)) - -/* - * Multithread locking - */ -#if BLD_FEATURE_MULTITHREAD -extern void mprInitThreads(MprApp *app); -extern void mprTermThreads(MprApp *app); -extern MprLock *mprCreateLock(MprCtx ctx); -extern void mprDestroyLock(MprLock *lock); -extern void mprLock(MprLock *lock); -extern int mprTryLock(MprLock *lock); -extern void mprUnlock(MprLock *lock); -extern void mprGlobalLock(MprCtx ctx); -extern void mprGlobalUnlock(MprCtx ctx); -extern int mprGetCurrentThreadID(); -#else -/* - * Disable multithreading - */ -#define mprInitThreads(ctx, app) -#define mprTermThreads(app) -#define mprCreateLock(ctx) -#define mprDestroyLock(lock) -#define mprLock(lock) -#define mprTryLock(lock) -#define mprUnlock(lock) -#define mprGlobalLock(app) -#define mprGlobalUnlock(app) -#define mprGetCurrentThreadID() -#endif - -/* - * Time - */ -extern MprTime *mprGetTime(MprCtx ctx, MprTime *tp); -extern int mprGetTimeRemaining(MprCtx ctx, MprTime mark, uint timeout); -extern int mprGetElapsedTime(MprCtx ctx, MprTime mark); -extern int mprCompareTime(MprTime *t1, MprTime *t2); -extern uint mprSubtractTime(MprTime *t1, MprTime *t2); -extern void mprAddElapsedToTime(MprTime *time, uint elapsed); - -#if !BREW -extern int mprAsctime(MprCtx ctx, char *buf, int bufsize, - const struct tm *timeptr); -extern int mprCtime(MprCtx ctx, char *buf, int bufsize, - const time_t *timer); -extern struct tm *mprLocaltime(MprCtx ctx, struct tm *timep, time_t *now); -extern struct tm *mprGmtime(MprCtx ctx, time_t* now, struct tm *timep); -extern int mprRfcTime(MprCtx ctx, char *buf, int bufsize, - const struct tm *timep); -#endif /* !BREW */ - -/* - * Host name - */ -extern struct hostent* mprGetHostByName(MprCtx ctx, const char *name); - -#if WIN -extern int mprReadRegistry(MprCtx ctx, char **buf, int max, - const char *key, const char *val); -extern int mprWriteRegistry(MprCtx ctx, const char *key, const char *name, - const char *value); -#endif - -#ifdef __cplusplus -} -#endif - -#endif /* _h_MPR */ - - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c b/source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c deleted file mode 100644 index 6fcaa63a6c..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprAlloc.c +++ /dev/null @@ -1,1775 +0,0 @@ -/** - * @file mprAlloc.c - * @brief Memory Allocation - * @overview - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************* Includes ***********************************/ - -#define UNSAFE_FUNCTIONS_OK 1 - -#include "mpr.h" - -/******************************* Local Defines ********************************/ -/* - * Set to 1 to disable slab based allocations - */ -#define NO_SLAB 0 - -/* - * Validation mode is quite slow - */ -#define VALIDATE_ALLOC 0 -#if VALIDATE_ALLOC -#define VALIDATE_BLOCK(ptr) mprValidateBlock(ptr) -#else -#define VALIDATE_BLOCK(ptr) -#endif - -/* - * Align on 4 bytes if squeeze, Otherwize on 16 bytes. - */ -#define HDR_SIZE MPR_BLK_HDR_SIZE - -#define APP_MAGIC 0xa571cb80 -#define ALLOC_MAGIC 0xe814ecc0 - -/* - * This must be at least one word to ensure that the smallest allocation is - * 4 bytes. Slab allocations need at least one word to store their next ptr. - */ -#define ALLOC_ALIGN(x) (((x)+3)&~3) -#define GET_HDR(ptr) ((MprBlk*) (((char*) (ptr)) - HDR_SIZE)) -#define GET_PTR(bp) ((void*) (((char*) (bp)) + HDR_SIZE)) -#define VALID_HDR(bp) (((bp)->flags & ~0x3F) == ALLOC_MAGIC) -#define VALID_BLK(ptr) (VALID_HDR(GET_HDR(ptr))) - -/* - * In production releases, mprAssert will compile out (not be included) - * but CHECK_HDR will remain even in production builds. - */ -#define CHECK_HDR(bp) \ - if (1) { if (! VALID_HDR(bp)) { mprAllocAbort(); } } else - -/* - * Chunk the slabs into 32 byte increments. - * This allows for allocations up to 512 bytes via slabs and maximizes - * sharing of slab allocations. - * - * Index map: - * 0 == 32 bytes - * 1 == 64 bytes - * 2 == 96 bytes - * 3 == 128 bytes - * 4 == 160 bytes - * 5 == 192 bytes - * 6 == 224 bytes - * 7 == 256 bytes - * 8 == 288 bytes - * 9 == 320 bytes - * 10 == 352 bytes - * 11 == 384 bytes - * 12 == 416 bytes - * 13 == 448 bytes - * 14 == 480 bytes - * 15 == 512 bytes - */ -#define SLAB_ALIGN(size) ((size + 31) & ~31) -#define GET_SLAB(size) (size >> 6) - -/* - * Block flags - */ -#define ALLOC_FLAGS_FREE 0x1 /* Block is free */ -#define ALLOC_FLAGS_FREEING 0x2 /* Block is being freed */ -#define ALLOC_FLAGS_SLAB_BLOCK 0x4 /* Block was allocated from slab */ -#define ALLOC_FLAGS_REQUIRED 0x8 /* Block is required by alloc */ -#define ALLOC_FLAGS_KEEP 0x10 /* Keep block - don't mprFree */ -#define ALLOC_FLAGS_DONT_OS_FREE 0x20 /* Don't return mem to O/S */ -#define ALLOC_FLAGS_IS_SLAB 0x40 /* Block is a slab */ - -#if BLD_DEBUG && !BREW -/* - * Set this address to break when this address is allocated or freed. This is - * a block address (not a user ptr). - */ -static MprBlk *stopAlloc; -#endif - -#if !BREW -static MprCtx rootCtx; /* Root context if none supplied */ -#endif - -/***************************** Forward Declarations ***************************/ - -static int mprAllocException(MPR_LOC_DEC(ptr, loc), uint size, bool granted); -static void slabFree(MprBlk *bp); -static int growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc); - -/******************************************************************************/ -/* - * Put first in file so it is easy to locate in a debugger - */ - -void mprBreakpoint(const char *loc, const char *msg) -{ -} - -/******************************************************************************/ -#if (WIN || BREW_SIMULATOR) && BLD_DEBUG - -int crtReportHook(int type, char *msg, int *retval) -{ - printf("%s\n", msg); - *retval = 0; - return TRUE; -} - -#endif -/******************************************************************************/ -/* - * Initialize the memory subsystem - */ - -MprApp *mprAllocInit(MprAllocCback cback) -{ - MprAllocStats *stats; - MprApp *app; - MprSlab *slab; - MprBlk *bp, *sp; - int i; - - bp = malloc(sizeof(MprApp) + HDR_SIZE); - mprAssert(bp); - if (bp == 0) { - if (cback) { - (*cback)(0, sizeof(MprApp), 0, 0); - } - return 0; - } - memset(bp, 0, sizeof(MprApp) + HDR_SIZE); - - bp->parent = bp; - bp->size = sizeof(MprApp); - bp->flags = ALLOC_MAGIC; - bp->next = bp->prev = bp; - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - bp->location = MPR_LOC; -#endif - - app = (MprApp*) GET_PTR(bp); - app->magic = APP_MAGIC; - - app->alloc.cback = cback; - app->stackStart = (void*) &app; - - bp->app = app; - - app->alloc.slabs = mprAllocZeroedBlock(MPR_LOC_PASS(app, MPR_LOC), - sizeof(MprSlab) * MPR_MAX_SLAB); - if (app->alloc.slabs == 0) { - mprFree(app); - return 0; - } - - /* - * The slab control structures must not be freed. Set keep to safeguard - * against accidents. - */ - sp = GET_HDR(app->alloc.slabs); - sp->flags |= ALLOC_FLAGS_KEEP; - - for (i = 0; i < MPR_MAX_SLAB; i++) { - /* - * This is overriden by requestors calling slabAlloc - */ - slab = &app->alloc.slabs[i]; - slab->preAllocateIncr = MPR_SLAB_DEFAULT_INC; - } - - /* - * Keep aggregated stats even in production code - */ - stats = &app->alloc.stats; - stats->bytesAllocated += sizeof(MprApp); - if (stats->bytesAllocated > stats->peakAllocated) { - stats->peakAllocated = stats->bytesAllocated; - } - stats->allocCount++; - -#if !BREW - rootCtx = app; -#endif -#if (WIN || BREW_SIMULATOR) && BLD_DEBUG - _CrtSetReportHook(crtReportHook); -#endif - return app; -} - -/******************************************************************************/ -/* - * Terminate the alloc module - */ - -void mprAllocTerm(MprApp *app) -{ - MprSlab *slabs; - MprBlk *appBlk, *slabBlk; - - /* - * Must do a carefully ordered cleanup. Need to free all children blocks - * before freeing the slab memory. Save a local pointer to the slabs. - */ - slabs = app->alloc.slabs; - - /* - * Free the app and all children. Set DONT_OS_FREE to prevent free() being - * called on app itself. We need that so we can free the slabs below. - */ - appBlk = GET_HDR(app); - appBlk->flags |= ALLOC_FLAGS_DONT_OS_FREE; - mprFree(app); - - /* - * Slabs are initially marked don't free. We must preserve them while all - * other blocks are freed. Then we clear the don't free flag and free. - * Now we don't have an app structure which is used by mprFree. We must - * fake it. - */ - slabBlk = GET_HDR(slabs); - slabBlk->flags &= ~ALLOC_FLAGS_KEEP; - mprFree(slabs); - - /* - * Now we can finally free the memory for the app structure - */ - free(appBlk); -} - -/******************************************************************************/ -/* - * Allocate a block - */ - -void *mprAllocBlock(MPR_LOC_DEC(ctx, loc), uint size) -{ - MprAllocStats *stats; - MprBlk *bp, *parent; - MprApp *app; - int diff; - - mprAssert(size > 0); - - if (ctx == 0) { -#if BREW - mprAssert(ctx); - return 0; -#else - ctx = rootCtx; -#endif - } - if (size == 0) { - size = 1; - } - - mprAssert(VALID_BLK(ctx)); - parent = GET_HDR(ctx); - mprAssert(VALID_HDR(parent)); - - CHECK_HDR(parent); - - size = ALLOC_ALIGN(size); - - app = parent->app; - - stats = &app->alloc.stats; - - mprLock(app->allocLock); - - stats->bytesAllocated += size + HDR_SIZE; - if (stats->bytesAllocated > stats->peakAllocated) { - stats->peakAllocated = stats->bytesAllocated; - } - - /* - * Prevent allocation if over the maximum - */ - if (stats->maxMemory && stats->bytesAllocated > stats->maxMemory) { - stats->bytesAllocated -= (size + HDR_SIZE); - mprUnlock(app->allocLock); - if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0) < 0) { - return 0; - } - mprLock(app->allocLock); - } - - if ((bp = malloc(size + HDR_SIZE)) == 0) { - mprAssert(bp); - stats->errors++; - mprUnlock(app->allocLock); - mprAllocException(MPR_LOC_PASS(ctx, loc), size, 0); - return 0; - } - -#if BLD_DEBUG - memset(bp, 0xf7, size + HDR_SIZE); -#endif - -#if BLD_DEBUG && !BREW - if (bp == stopAlloc) { - mprBreakpoint(MPR_LOC, "breakOnAddr"); - } -#endif - - /* - * Warn if allocation puts us over the red line - */ - if (stats->redLine && stats->bytesAllocated > stats->redLine) { - mprUnlock(app->allocLock); - if (mprAllocException(MPR_LOC_PASS(ctx, loc), size, 1) < 0) { - return 0; - } - mprLock(app->allocLock); - } - - bp->size = size; - bp->flags = ALLOC_MAGIC; - bp->destructor = 0; - - bp->parent = parent; - - if (parent->children == 0) { - parent->children = bp; - bp->next = bp->prev = bp; - - } else { - /* - * Append to the end of the list. Preserve alloc order - */ - bp->next = parent->children; - bp->prev = parent->children->prev; - parent->children->prev->next = bp; - parent->children->prev = bp; - } - - bp->children = 0; - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - bp->location = loc; -#endif - - bp->app = parent->app; - - VALIDATE_BLOCK(GET_PTR(bp)); - - stats->allocCount++; - - /* - * Monitor stack usage - */ - diff = (int) bp->app->stackStart - (int) &stats; - if (diff < 0) { - app->maxStack -= diff; - app->stackStart = (void*) &stats; - diff = 0; - } - - if ((uint) diff > app->maxStack) { - app->maxStack = diff; - } - mprUnlock(app->allocLock); - - return GET_PTR(bp); -} - -/******************************************************************************/ -/* - * Allocate and zero a block - */ - -void *mprAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size) -{ - void *newBlock; - - MprBlk *bp; - - bp = GET_HDR(ctx); - mprAssert(VALID_BLK(ctx)); - - newBlock = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); - if (newBlock) { - memset(newBlock, 0, size); - } - return newBlock; -} - -/******************************************************************************/ -/* - * Free a block of memory. Free all children recursively. - */ - -int mprFree(void *ptr) -{ - MprAllocStats *stats; - MprBlk *bp, *parent, *cp, *firstChild, *prev; - MprApp *app; - - if (ptr == 0) { - return 0; - } - - mprAssert(VALID_BLK(ptr)); - VALIDATE_BLOCK(ptr); - - bp = GET_HDR(ptr); - -#if BLD_DEBUG && !BREW - if (bp == stopAlloc) { - mprBreakpoint(MPR_LOC, "breakOnAddr"); - } -#endif - - mprAssert(bp); - mprAssert(VALID_HDR(bp)); - - CHECK_HDR(bp); - - /* - * Test if already freed - */ - mprAssert(! (bp->flags & ALLOC_FLAGS_FREE)); - if (bp->flags & ALLOC_FLAGS_FREE) { - return 0; - } - - /* - * Return if recursive freeing or this is a permanent block - */ - app = bp->app; - mprLock(app->allocLock); - if (bp->flags & (ALLOC_FLAGS_FREEING | ALLOC_FLAGS_KEEP)) { - mprUnlock(app->allocLock); - return 0; - } - bp->flags |= ALLOC_FLAGS_FREEING; - - - /* - * Call any destructors - */ - if (bp->destructor) { - mprUnlock(app->allocLock); - if ((bp->destructor)(ptr) < 0) { - return -1; - } - mprLock(app->allocLock); - bp->destructor = 0; - } - - /* - * Free the children. Free in reverse order so firstChild is preserved - * during the list scan as an end of list marker. - */ - if ((firstChild = bp->children) != 0) { - cp = firstChild->prev; - while (cp != firstChild) { - - mprAssert(VALID_HDR(cp)); - VALIDATE_BLOCK(GET_PTR(cp)); - - prev = cp->prev; - - /* - * FUTURE - OPT. Make this inline - */ - mprFree(GET_PTR(cp)); - - cp = prev; - } - - mprFree(GET_PTR(firstChild)); - - /* - * Just for clarity - */ - bp->children = 0; - } - - parent = bp->parent; - - mprAssert(VALID_HDR(parent)); - - /* - * Unlink from the parent - */ - if (parent->children == bp) { - if (bp->next == bp) { - parent->children = 0; - } else { - parent->children = bp->next; - } - } - - /* - * Remove from the sibling chain - */ - bp->prev->next = bp->next; - bp->next->prev = bp->prev; - - bp->flags |= ALLOC_FLAGS_FREE; - - /* - * Release the memory. If from a slab, return to the slab. Otherwise, - * return to the O/S. - */ - if (bp->flags & ALLOC_FLAGS_SLAB_BLOCK) { - slabFree(bp); - - } else { - mprAssert(bp); - - /* - * Update the stats - */ - stats = &bp->app->alloc.stats; - stats->bytesAllocated -= (bp->size + HDR_SIZE); - mprAssert(stats->bytesAllocated >= 0); - - stats->allocCount--; - mprAssert(stats->allocCount >= 0); - -#if BLD_DEBUG && !BREW - if (bp == stopAlloc) { - mprBreakpoint(MPR_LOC, "breakOnAddr"); - } -#endif - - /* - * Return to the O/S - */ - if (! (bp->flags & ALLOC_FLAGS_DONT_OS_FREE)) { - free(bp); - } - } - /* OPT */ - if (app != ptr) { - mprUnlock(app->allocLock); - } - - return 0; -} - -/******************************************************************************/ -/* - * Rallocate a block - */ - -void *mprReallocBlock(MPR_LOC_DEC(ctx, loc), void *ptr, uint size) -{ - MprBlk *bp, *newbp, *firstChild, *cp; - MprApp *app; - void *newPtr; - - mprAssert(VALID_BLK(ctx)); - mprAssert(size > 0); - - if (ptr == 0) { - return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); - } - - mprAssert(VALID_BLK(ptr)); - bp = GET_HDR(ptr); - mprAssert(bp); - mprAssert(VALID_HDR(bp)); - - CHECK_HDR(bp); - - if (size < bp->size) { - return ptr; - } - - newPtr = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); - if (newPtr == 0) { - bp->flags &= ~ALLOC_FLAGS_FREE; - free(bp); - return 0; - } - - newbp = GET_HDR(newPtr); - mprAssert(newbp->size >= size); - memcpy((char*) newbp + HDR_SIZE, (char*) bp + HDR_SIZE, bp->size); - mprAssert(newbp->size >= size); - - /* - * Fix the next / prev pointers - */ - app = bp->app; - mprLock(app->allocLock); - newbp->next->prev = newbp; - newbp->prev->next = newbp; - - /* - * Need to fix the parent pointer of all children - */ - if ((firstChild = newbp->children) != 0) { - cp = firstChild; - do { - cp->parent = newbp; - cp = cp->next; - } while (cp != firstChild); - } - - /* - * May need to set the children pointer of our parent - */ - if (newbp->parent->children == bp) { - newbp->parent->children = newbp; - } - - /* - * Free the original block - */ - mprFree(ptr); - - mprUnlock(app->allocLock); - - return GET_PTR(newbp); -} - -/******************************************************************************/ -/* - * Allocate a block from a slab - */ - -void *mprSlabAllocBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc) -{ - -#if NO_SLAB - return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); -#else - - MprBlk *parent, *bp; - MprSlabBlock *sb; - MprApp *app; - MprSlab *slab; - int slabIndex; - - if (ctx == 0) { - mprAssert(ctx); - return 0; - } - - mprAssert(size > 0); - mprAssert(VALID_BLK(ctx)); - - parent = GET_HDR(ctx); - mprAssert(VALID_HDR(parent)); - - CHECK_HDR(parent); - - size = SLAB_ALIGN(size); - - app = parent->app; - mprAssert(app); - - slabIndex = GET_SLAB(size); - - if (slabIndex < 0 || slabIndex >= MPR_MAX_SLAB) { - return mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); - } - - /* - * Dequeue a block from the slab. "sb" will point to the user data - * portion of the block (i.e. after the MprBlk header). Slabs must be - * allocated off the "slabs" context to ensure they don't get freed - * until after all other blocks are freed. - */ - mprLock(app->allocLock); - slab = &app->alloc.slabs[slabIndex]; - if ((sb = slab->next) == 0) { - if (growSlab(MPR_LOC_ARGS(parent->app->alloc.slabs), - slab, size, inc) < 0) { - mprUnlock(app->allocLock); - return 0; - } - sb = slab->next; - } - mprAssert(sb); - - /* - * Dequeue the block - */ - slab->next = sb->next; - -#if BLD_FEATURE_ALLOC_STATS -{ - MprSlabStats *slabStats; - /* - * Update the slab stats - */ - slabStats = &slab->stats; - slabStats->totalAllocCount++; - slabStats->freeCount--; - slabStats->allocCount++; - if (slabStats->allocCount > slabStats->peakAllocCount) { - slabStats->peakAllocCount = slabStats->allocCount; - } -} -#endif /* BLD_FEATURE_ALLOC_STATS */ - - bp = GET_HDR(sb); - -#if BLD_DEBUG && !BREW - if (bp == stopAlloc) { - mprBreakpoint(MPR_LOC, "breakOnAddr"); - } -#endif - - bp->size = size; - bp->flags = ALLOC_MAGIC | ALLOC_FLAGS_SLAB_BLOCK; - bp->destructor = 0; - - bp->parent = parent; - - if (parent->children == 0) { - parent->children = bp; - bp->next = bp->prev = bp; - - } else { - /* - * Append to the end of the list. Preserve alloc order - */ - bp->next = parent->children; - bp->prev = parent->children->prev; - parent->children->prev->next = bp; - parent->children->prev = bp; - } - - bp->children = 0; - - bp->app = app; - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - bp->location = loc; -#endif - mprUnlock(app->allocLock); - - return GET_PTR(bp); -#endif -} - -/******************************************************************************/ -/* - * Return a block back to its slab - */ - -static void slabFree(MprBlk *bp) -{ - MprSlab *slab; - MprApp *app; - void *ptr; - int slabIndex; - - mprAssert(VALID_HDR(bp)); - - slabIndex = GET_SLAB(bp->size); - mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB); - - if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) { - mprLock(bp->app->allocLock); - slab = &bp->app->alloc.slabs[slabIndex]; - app = bp->app; - -#if BLD_DEBUG - memset(bp, 0xfc, bp->size + HDR_SIZE); -#endif - - ptr = GET_PTR(bp); - ((MprSlabBlock*) ptr)->next = slab->next; - slab->next = ((MprSlabBlock*) ptr); - -#if BLD_FEATURE_ALLOC_STATS -{ - MprSlabStats *slabStats; - slabStats = &slab->stats; - - slabStats->freeCount++; - slabStats->allocCount--; - - if (slabStats->freeCount >= slabStats->peakFreeCount) { - slabStats->peakFreeCount = slabStats->freeCount; - } -} -#endif - mprUnlock(app->allocLock); - } -} - -/******************************************************************************/ -/* - * Grow the slab and return the next free block - * Must be called locked. - */ - -static int growSlab(MPR_LOC_DEC(ctx, loc), MprSlab *slab, uint size, uint inc) -{ - MprBlk *bp; - MprSlabBlock *sb; - int i, chunkSize, len; - - mprAssert(VALID_BLK(ctx)); - mprAssert(slab); - mprAssert(size > 0); - - /* - * Take the maximum requested by anyone - */ - slab->preAllocateIncr = max(slab->preAllocateIncr, inc); - - /* - * We allocate an array of blocks each of user "size" bytes. - */ - chunkSize = HDR_SIZE + size; - len = chunkSize * slab->preAllocateIncr; - bp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); - -#if BLD_DEBUG - memset(bp, 0xf1, len); -#endif - - if (bp == 0) { - mprAssert(0); - return MPR_ERR_MEMORY; - } - bp->flags |= ALLOC_FLAGS_IS_SLAB; - - /* - * We store the slab information in the user data portion - */ - sb = (MprSlabBlock*) GET_PTR(bp); - - - sb = (MprSlabBlock*) ((char*) sb + len - chunkSize); - for (i = slab->preAllocateIncr - 1; i >= 0; i--) { - sb->next = slab->next; - slab->next = sb; - sb = (MprSlabBlock*) ((char*) sb - chunkSize); - } - -#if BLD_FEATURE_ALLOC_STATS -{ - MprSlabStats *stats; - stats = &slab->stats; - stats->freeCount += slab->preAllocateIncr; - if (stats->freeCount > stats->peakFreeCount) { - stats->peakFreeCount = stats->freeCount; - } -} -#endif - - return 0; -} - -/******************************************************************************/ -/* - * Set the pre-allocate amount - */ - -int mprSetSlabPreAllocate(MprCtx ctx, int slabIndex, int preAllocateIncr) -{ - MprApp *app; - MprSlab *slab; - - mprAssert(VALID_BLK(ctx)); - mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB); - mprAssert(preAllocateIncr > 0); - - if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) { - app = mprGetApp(ctx); - slab = &app->alloc.slabs[slabIndex]; - slab->preAllocateIncr = preAllocateIncr; - } else { - return MPR_ERR_BAD_ARGS; - } - return 0; -} - -/******************************************************************************/ - -void *mprSlabAllocZeroedBlock(MPR_LOC_DEC(ctx, loc), uint size, uint inc) -{ - void *newBlock; - - mprAssert(VALID_BLK(ctx)); - mprAssert(size > 0); - - newBlock = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), size, inc); - if (newBlock) { - memset(newBlock, 0, size); - } - return newBlock; -} - -/******************************************************************************/ -/* - * Internal strdup function. Will use the slab allocator for small strings - */ - -char *mprStrdupInternal(MPR_LOC_DEC(ctx, loc), const char *str) -{ - char *newp; - int len; - - mprAssert(VALID_BLK(ctx)); - - if (str == 0) { - str = ""; - } - - len = strlen(str) + 1; - - if (len < MPR_SLAB_STR_MAX) { - newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, - MPR_SLAB_STR_INC); - } else { - newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); - } - - if (newp) { - memcpy(newp, str, len); - } - - return newp; -} - -/******************************************************************************/ -/* - * Internal strndup function. Will use the slab allocator for small strings - */ - -char *mprStrndupInternal(MPR_LOC_DEC(ctx, loc), const char *str, uint size) -{ - char *newp; - uint len; - - mprAssert(VALID_BLK(ctx)); - - if (str == 0) { - str = ""; - } - len = strlen(str) + 1; - len = min(len, size); - - if (len < MPR_SLAB_STR_MAX) { - newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, - MPR_SLAB_STR_INC); - } else { - newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); - } - - if (newp) { - memcpy(newp, str, len); - } - - return newp; -} - -/******************************************************************************/ -/* - * Internal memcpy function. Will use the slab allocator for small strings - */ - -void *mprMemdupInternal(MPR_LOC_DEC(ctx, loc), const void *ptr, uint size) -{ - char *newp; - - mprAssert(VALID_BLK(ctx)); - - if (size < MPR_SLAB_STR_MAX) { - newp = mprSlabAllocBlock(MPR_LOC_PASS(ctx, loc), MPR_SLAB_STR_MAX, - MPR_SLAB_STR_INC); - } else { - newp = mprAllocBlock(MPR_LOC_PASS(ctx, loc), size); - } - - if (newp) { - memcpy(newp, ptr, size); - } - - return newp; -} - -/******************************************************************************/ -/* - * Steal a block from one context and insert in another - */ - -int mprStealAllocBlock(MPR_LOC_DEC(ctx, loc), const void *ptr) -{ - MprBlk *bp, *parent; - - if (ptr == 0) { - return 0; - } - - mprAssert(VALID_BLK(ctx)); - mprAssert(VALID_BLK(ptr)); - - bp = GET_HDR(ptr); - -#if BLD_DEBUG && !BREW - if (bp == stopAlloc) { - mprBreakpoint(MPR_LOC, "breakOnAddr"); - } -#endif - - mprAssert(bp); - mprAssert(VALID_HDR(bp)); - mprAssert(ptr != mprGetAllocParent(ptr)); - - CHECK_HDR(bp); - - mprAssert(bp->prev); - mprAssert(bp->prev->next); - mprAssert(bp->next); - mprAssert(bp->next->prev); - - parent = bp->parent; - mprAssert(VALID_HDR(parent)); - - mprLock(bp->app->allocLock); - if (parent->children == bp) { - if (bp->next == bp) { - parent->children = 0; - } else { - parent->children = bp->next; - } - } - - bp->prev->next = bp->next; - bp->next->prev = bp->prev; - - parent = GET_HDR(ctx); - mprAssert(VALID_HDR(parent)); - bp->parent = parent; - - if (parent->children == 0) { - parent->children = bp; - bp->next = bp->prev = bp; - - } else { - bp->next = parent->children; - bp->prev = parent->children->prev; - parent->children->prev->next = bp; - parent->children->prev = bp; - } - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - bp->location = loc; -#endif - - VALIDATE_BLOCK(GET_PTR(bp)); - - mprUnlock(bp->app->allocLock); - - return 0; -} - -/******************************************************************************/ - -void mprSetRequiredAlloc(MprCtx ptr, bool recurse) -{ - MprBlk *bp, *firstChild, *cp; - - bp = GET_HDR(ptr); - - bp->flags |= ALLOC_FLAGS_REQUIRED; - - if (recurse && (firstChild = bp->children) != 0) { - cp = firstChild; - do { - mprSetRequiredAlloc(GET_PTR(cp), recurse); - cp = cp->next; - } while (cp != firstChild); - } -} - -/******************************************************************************/ -/* - * Monitor stack usage. Return true if the stack has grown - */ - -int mprStackCheck(MprCtx ptr) -{ - MprApp *app; - int size; - - mprAssert(VALID_BLK(ptr)); - - app = mprGetApp(ptr); - - size = (int) app->stackStart - (int) &app; - if (size < 0) { - app->maxStack -= size; - app->stackStart = (void*) &app; - size = 0; - } - if ((uint) size > app->maxStack) { - app->maxStack = size; - return 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Return the stack size - */ - -int mprStackSize(MprCtx ptr) -{ - MprApp *app; - - mprAssert(VALID_BLK(ptr)); - - app = mprGetApp(ptr); - return app->maxStack; -} - -/******************************************************************************/ - -static int mprAllocException(MPR_LOC_DEC(ctx, loc), uint size, bool granted) -{ - MprApp *app; - MprAlloc *alloc; - int rc; - - mprAssert(VALID_BLK(ctx)); - - app = mprGetApp(ctx); - alloc = &app->alloc; - - if (alloc->cback == 0) { - return 0; - } - - mprLock(app->allocLock); - if (alloc->inAllocException == 0) { - alloc->inAllocException = 1; - mprUnlock(app->allocLock); - - rc = (alloc->cback)(app, size, alloc->stats.bytesAllocated, granted); - - mprLock(app->allocLock); - app->alloc.inAllocException = 0; - mprUnlock(app->allocLock); - - return rc; - } - return 0; -} - -/******************************************************************************/ - -void mprSetAllocLimits(MprApp *app, uint redLine, uint maxMemory) -{ - app->alloc.stats.redLine = redLine; - app->alloc.stats.maxMemory = maxMemory; -} - -/******************************************************************************/ - -MprAllocCback mprSetAllocCallback(MprApp *app, MprAllocCback cback) -{ - MprAllocCback old; - - mprAssert(app); - mprAssert(VALID_BLK(app)); - - old = app->alloc.cback; - app->alloc.cback = cback; - return old; -} - -/******************************************************************************/ - -uint mprGetAllocBlockSize(MprCtx ptr) -{ - MprBlk *bp; - - mprAssert(VALID_BLK(ptr)); - - if (ptr == 0) { - return 0; - } - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - - CHECK_HDR(bp); - - return bp->size; -} - -/******************************************************************************/ -/* - * Return the total block count used by a block including all children - */ - -uint mprGetAllocBlockCount(MprCtx ptr) -{ - MprBlk *bp, *firstChild, *cp; - uint count; - - mprAssert(VALID_BLK(ptr)); - - if (ptr == 0) { - return 0; - } - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - - /* - * Add one for itself - */ - count = 1; - if ((firstChild = bp->children) != 0) { - cp = firstChild; - do { - count += mprGetAllocBlockCount(GET_PTR(cp)); - cp = cp->next; - } while (cp != firstChild); - } - return count; -} - -/******************************************************************************/ -/* - * Return the total of all memory allocated including slabs - */ - -uint mprGetAllocBlockMemory(MprCtx ptr) -{ - MprBlk *bp, *firstChild, *cp; - uint count; - - mprAssert(VALID_BLK(ptr)); - - if (ptr == 0) { - return 0; - } - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - - count = bp->size + HDR_SIZE; - if ((firstChild = bp->children) != 0) { - cp = firstChild; - do { - count += mprGetAllocBlockMemory(GET_PTR(cp)); - cp = cp->next; - } while (cp != firstChild); - } - return count; -} - -/******************************************************************************/ -#if BLD_FEATURE_ALLOC_LEAK_TRACK - -const char *mprGetAllocLocation(MprCtx ptr) -{ - MprBlk *bp; - - if (ptr == 0) { - return 0; - } - mprAssert(VALID_BLK(ptr)); - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - return bp->location; -} - -#endif -/******************************************************************************/ - -void *mprGetAllocParent(MprCtx ptr) -{ - MprBlk *bp; - - mprAssert(VALID_BLK(ptr)); - - if (ptr == 0) { - return 0; - } - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - - CHECK_HDR(bp); - - return GET_PTR(bp->parent); -} - -/******************************************************************************/ - -MprAllocStats *mprGetAllocStats(MprApp *app) -{ - mprAssert(VALID_BLK(app)); - - return &app->alloc.stats; -} - -/******************************************************************************/ -#if BLD_FEATURE_ALLOC_STATS - -MprSlabStats *mprGetSlabAllocStats(MprApp *app, int slabIndex) -{ - MprSlab *slab; - - mprAssert(VALID_BLK(app)); - - if (0 <= slabIndex && slabIndex < MPR_MAX_SLAB) { - slab = &app->alloc.slabs[slabIndex]; - return &slab->stats; - } - - mprAssert(0 <= slabIndex && slabIndex < MPR_MAX_SLAB); - return 0; -} - -#endif /* BLD_FEATURE_ALLOC_STATS */ -/******************************************************************************/ -#if BLD_DEBUG - -int mprPrintAllocBlocks(MprCtx ptr, int indent) -{ - MprBlk *bp, *firstChild, *cp; - const char *location; - int subTotal, size, indentSpaces, code; - - subTotal = 0; - - bp = GET_HDR(ptr); - - if (! (bp->flags & ALLOC_FLAGS_REQUIRED)) { - size = bp->size + HDR_SIZE; - - /* - * Take one level off because we don't trace app - */ - indentSpaces = indent; - - if (bp->flags & ALLOC_FLAGS_REQUIRED) { - code = 'R'; - } else if (bp->flags & ALLOC_FLAGS_IS_SLAB) { - code = 'S'; - } else { - code = ' '; - } - -#if BLD_FEATURE_ALLOC_LEAK_TRACK - location = bp->location; -#else - location = ""; -#endif - mprLog(bp->app, 0, - "%c %.*s %-16s %.*s size %5d has %3d deps, total %6d", code, - indentSpaces, " ", - mprGetBaseName(location), - 8 - indent, " ", - size, - mprGetAllocBlockCount(GET_PTR(bp)), - mprGetAllocBlockMemory(GET_PTR(bp)) - /* (uint) bp */ - ); - - subTotal += size; - } - - if ((firstChild = bp->children) != 0) { - cp = firstChild; - do { - subTotal += mprPrintAllocBlocks(GET_PTR(cp), indent + 2); - cp = cp->next; - } while (cp != firstChild); - } - - return subTotal; -} - -#endif -/******************************************************************************/ -#if BLD_FEATURE_ALLOC_STATS -/* - * Print a memory allocation report that includes a list of allocated blocks - * and a statistics summary - */ - -void mprPrintAllocReport(MprApp *app, bool printBlocks, const char *msg) -{ - MprSlabStats *stats; - uint total; - int i, size; - - mprAssert(VALID_BLK(app)); - - if (msg) { - mprLog(app, 0, " "); - mprLog(app, 0, "%s", msg); - } - -#if BLD_DEBUG - /* - * Do block stats - */ - if (printBlocks) { - int sum; - mprLog(app, 0, " "); - sum = mprPrintAllocBlocks(app, 0); - if (sum) { - mprLog(app, 0, " Sum of blocks %d", sum); - } else { - mprLog(app, 0, " None"); - } - } -#endif - - /* - * Do Slab stats - */ - mprLog(app, 0, " "); - mprLog(app, 0, "MPR Slab Memory Stats"); - mprLog(app, 0, " "); - - mprLog(app, 0, - " Index Size Total Allocated Free PeakAlloc PeakFree TotalAlloc"); - - total = 0; - for (i = 0; i < MPR_MAX_SLAB; i++) { - stats = &app->alloc.slabs[i].stats; - size = 1 << (i + 5); - if (stats->totalAllocCount > 0) { - mprLog(app, 0, " %2d %6d %8d %9d %6d %9d %8d %10d", - i, size, size * (stats->allocCount + stats->freeCount), - stats->allocCount, stats->freeCount, - stats->peakAllocCount, stats->peakFreeCount, - stats->totalAllocCount); - total += size * (stats->allocCount + stats->freeCount); - } - } - mprLog(app, 0, " "); - mprLog(app, 0, "MPR Total Allocated Slab RAM: %10d", total); - mprLog(app, 0, "MPR Total Allocated RAM: %10d", - mprGetAllocatedMemory(app)); - mprLog(app, 0, "MPR Peak Allocated RAM: %10d", - mprGetPeakAllocatedMemory(app)); - mprLog(app, 0, " "); -} - -/******************************************************************************/ -/* - * Return the total memory allocated. - */ - -uint mprGetAllocatedMemory(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - - return app->alloc.stats.bytesAllocated; -} - -/******************************************************************************/ -/* - * Return the peak memory allocated. - */ - -uint mprGetPeakAllocatedMemory(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - - return app->alloc.stats.peakAllocated; -} - -/******************************************************************************/ -/* - * Return memory in the MPR slab. This excludes the EJS slabs - */ - -uint mprGetAllocatedSlabMemory(MprCtx ctx) -{ - MprApp *app; - MprSlabStats *stats; - uint total; - int i, size; - - app = mprGetApp(ctx); - - total = 0; - for (i = 0; i < MPR_MAX_SLAB; i++) { - stats = &app->alloc.slabs[i].stats; - size = 1 << (i + 5); - if (stats->totalAllocCount > 0) { - total += size * (stats->allocCount + stats->freeCount); - } - } - return total; -} - -#endif /* BLD_FEATURE_ALLOC_STATS */ -/******************************************************************************/ - -MprDestructor mprSetDestructor(MprCtx ptr, MprDestructor destructor) -{ - MprDestructor old; - MprBlk *bp; - - mprAssert(VALID_BLK(ptr)); - - if (ptr == 0) { - return 0; - } - - bp = GET_HDR(ptr); - - mprAssert(bp); - mprAssert(VALID_HDR(bp)); - mprAssert(ptr != mprGetAllocParent(ptr)); - - CHECK_HDR(bp); - - old = bp->destructor; - bp->destructor = destructor; - - return old; -} - -/******************************************************************************/ - -int mprIsAllocBlockValid(MprCtx ptr) -{ - MprBlk *bp; - - bp = GET_HDR(ptr); - return (bp && VALID_HDR(bp)); -} - -/******************************************************************************/ -#if VALIDATE_ALLOC -/* - * Exhaustive validation of the block and its children. Does not go recursive - * as it would be too slow. - */ - -int mprValidateBlock(MprCtx ptr) -{ - MprBlk *bp, *parent, *cp, *firstChild; - int count; - - mprAssert(ptr); - mprAssert(VALID_BLK(ptr)); - - bp = GET_HDR(ptr); - - mprAssert(bp); - mprAssert(VALID_HDR(bp)); - mprAssert(VALID_HDR(bp->parent)); - - if (ptr != bp->app) { - mprAssert(bp != bp->parent); - } - mprAssert(! (bp->flags & ALLOC_FLAGS_FREE)); - mprAssert(! (bp->flags & ALLOC_FLAGS_FREEING)); - - /* - * - */ - count = 0; - parent = bp->parent; - - if ((firstChild = bp->children) != 0) { - cp = firstChild; - mprAssert((int) cp != 0xfeefee); - do { - mprAssert(bp->next->prev == bp); - mprAssert(bp->prev->next == bp); - mprAssert(bp->prev->parent == parent); - mprAssert(bp->next->parent == parent); - - count++; - cp = cp->next; - - if (bp->next == bp) { - mprAssert(bp->prev == bp); - if (ptr != bp->app) { - mprAssert(parent->children == bp); - } - } - if (bp->prev == bp) { - mprAssert(bp->next == bp); - if (ptr != bp->app) { - mprAssert(parent->children == bp); - } - } - } while (cp != firstChild); - } - - return 0; -} - -#endif -/******************************************************************************/ -/* - * Validate a block and all children - */ - -int mprValidateAllocTree(MprCtx ptr) -{ -#if VALIDATE_ALLOC - MprBlk *bp, *cp, *firstChild; - - mprAssert(ptr); - mprAssert(VALID_BLK(ptr)); - - bp = GET_HDR(ptr); - - mprValidateBlock(GET_PTR(bp)); - - if ((firstChild = bp->children) != 0) { - cp = firstChild; - do { - mprValidateAllocTree(GET_PTR(cp)); - cp = cp->next; - } while (cp != firstChild); - } - -#endif - return 0; -} - -/******************************************************************************/ -#if UNUSED && FUTURE -/* - * Exhaustive validation of the block and its children. Does not go recursive - * as it would be too slow. - */ - -int mprValidateSlabs(MprApp *app) -{ - MprSlab *slab; - MprSlabStats *slabStats; - MprSlabBlock *sp; - int count, i; - - for (i = 0; i < MPR_MAX_SLAB; i++) { - slab = &app->alloc.slabs[i]; - slabStats = &slab->stats; - - count = 0; - for (sp = slab->next; sp; sp = sp->next) { - count++; - } - mprAssert(count == (int) slabStats->freeCount); - } - return 0; -} - -#endif -/******************************************************************************/ - -void mprAllocAbort() -{ -#if BREW - printf("Bad block header"); -#else - exit(255); -#endif -} - -/******************************************************************************/ -#undef mprGetApp -/* - * Get the root parent from any block (which is the MprApp structure) - */ - -MprApp *mprGetApp(MprCtx ptr) -{ - MprBlk *bp; - - mprAssert(ptr); - - bp = GET_HDR(ptr); - mprAssert(VALID_HDR(bp)); - - CHECK_HDR(bp); - - mprAssert(bp->app->magic == APP_MAGIC); - - return bp->app; -} - -/******************************************************************************/ - -int mprGetAllocErrors(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - return app->alloc.stats.errors; -} - -/******************************************************************************/ - -void mprClearAllocErrors(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - app->alloc.stats.errors = 0; -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprArray.c b/source4/lib/appweb/ejs-2.0/mpr/mprArray.c deleted file mode 100644 index 95b0a14450..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprArray.c +++ /dev/null @@ -1,385 +0,0 @@ -/** - * @file mprArray.c - * @brief Growable array structure - * @overview Simple growable array structure. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/******************************************************************************/ -/* - * Create a general growable array structure. Use mprFree to destroy. - */ - -MprArray *mprCreateItemArrayInternal(MPR_LOC_DEC(ctx, loc), int initialSize, - int maxSize) -{ - MprArray *array; - int size; - - mprAssert(initialSize <= maxSize); - - array = (MprArray*) mprSlabAllocZeroedBlock(MPR_LOC_PASS(ctx, loc), - sizeof(MprArray), 0); - if (array == 0) { - return 0; - } - - if (initialSize == 0) { - initialSize = MPR_ARRAY_INCR; - } - if (maxSize == 0) { - maxSize = MAXINT; - } - size = initialSize * sizeof(void*); - - array->items = (void**) mprSlabAllocBlock(MPR_LOC_PASS(array, loc), - size, 0); - - if (array->items == 0) { - mprFree(array); - return 0; - } - - array->capacity = initialSize; - array->maxSize = maxSize; - array->incr = min(initialSize * 2, (array->maxSize - array->length)); - array->length = 0; - - return array; -} - -/******************************************************************************/ -/* - * Add an item to the array - */ - -int mprAddItem(MprArray *array, void *item) -{ - int memsize, index, len; - - mprAssert(array); - mprAssert(array->capacity >= 0); - mprAssert(array->length >= 0); - - if (array->length < array->capacity) { - /* - * Room to fit in the current capacity - */ - index = array->length++; - array->items[index] = item; - return index; - } - mprAssert(array->length == array->capacity); - - /* - * Need to grow the array - */ - if (array->capacity >= array->maxSize) { - mprAssert(array->capacity < array->maxSize); - return MPR_ERR_TOO_MANY; - } - - len = array->capacity + array->incr; - memsize = len * sizeof(void*); - - /* - * Grow the array of items - */ - - array->items = (void**) mprRealloc(array, array->items, memsize); - - /* - * Zero the new portion - */ - memset(&array->items[array->capacity], 0, sizeof(void*) * array->incr); - array->capacity = len; - - array->incr = min(array->incr * 2, (array->maxSize - array->length)); - - index = array->length++; - array->items[index] = item; - - return index; -} - -/******************************************************************************/ -/* - * Remove an item from the array - */ - -int mprRemoveItem(MprArray *array, void *item) -{ - int index; - - mprAssert(array); - mprAssert(array->capacity > 0); - mprAssert(array->length > 0); - - index = mprFindItem(array, item); - if (index < 0) { - return index; - } - - return mprRemoveItemByIndex(array, index); -} - -/******************************************************************************/ -/* - * Remove an index from the array - */ - -int mprRemoveItemByIndex(MprArray *array, int index) -{ - void **items; - int i; - - mprAssert(array); - mprAssert(array->capacity > 0); - mprAssert(index >= 0 && index < array->capacity); - mprAssert(array->items[index] != 0); - mprAssert(array->length > 0); - - if (index < 0 || index >= array->length) { - return MPR_ERR_NOT_FOUND; - } - - /* - * Copy down to compress - */ - items = array->items; - for (i = index; i < (array->length - 1); i++) { - items[i] = items[i + 1]; - } - array->length--; - -#if BLD_DEBUG - if (array->length < array->capacity) { - items[array->length] = 0; - } -#endif - return 0; -} - -/******************************************************************************/ - -int mprRemoveRangeOfItems(MprArray *array, int start, int end) -{ - void **items; - int i, count; - - mprAssert(array); - mprAssert(array->capacity > 0); - mprAssert(array->length > 0); - mprAssert(start > end); - - if (start < 0 || start >= array->length) { - return MPR_ERR_NOT_FOUND; - } - if (end < 0 || end >= array->length) { - return MPR_ERR_NOT_FOUND; - } - if (start > end) { - return MPR_ERR_BAD_ARGS; - } - - /* - * Copy down to compress - */ - items = array->items; - count = end - start; - for (i = start; i < (array->length - count); i++) { - items[i] = items[i + count]; - } - array->length -= count; - -#if BLD_DEBUG - if (array->length < array->capacity) { - for (i = array->length; i < array->capacity; i++) { - items[i] = 0; - } - } -#endif - return 0; -} - -/******************************************************************************/ - -void *mprGetItem(MprArray *array, int index) -{ - mprAssert(array); - - if (index < 0 || index >= array->length) { - return 0; - } - return array->items[index]; -} - -/******************************************************************************/ - -void *mprGetFirstItem(MprArray *array, int *last) -{ - mprAssert(array); - mprAssert(last); - - if (array == 0) { - return 0; - } - - *last = 0; - - if (array->length == 0) { - return 0; - } - return array->items[0]; -} - -/******************************************************************************/ - -void *mprGetNextItem(MprArray *array, int *last) -{ - int index; - - mprAssert(array); - mprAssert(last); - mprAssert(*last >= 0); - - index = *last; - - if (++index < array->length) { - *last = index; - return array->items[index]; - } - return 0; -} - -/******************************************************************************/ - -void *mprGetPrevItem(MprArray *array, int *last) -{ - int index; - - mprAssert(array); - mprAssert(last); - mprAssert(*last >= 0); - - if (array == 0) { - return 0; - } - - index = *last; - - if (--index < array->length && index >= 0) { - *last = index; - return array->items[index]; - } - return 0; -} - -/******************************************************************************/ - -int mprGetItemCount(MprArray *array) -{ - mprAssert(array); - - if (array == 0) { - return 0; - } - - return array->length; -} - -/******************************************************************************/ - -int mprGetItemCapacity(MprArray *array) -{ - mprAssert(array); - - if (array == 0) { - return 0; - } - - return array->capacity; -} - -/******************************************************************************/ - -void mprClearAndFreeItems(MprArray *array) -{ - int i; - - mprAssert(array); - - for (i = 0; i < array->length; i++) { - mprFree(array->items[i]); - } -} - -/******************************************************************************/ - -void mprClearItems(MprArray *array) -{ - mprAssert(array); - - array->length = 0; -} - -/******************************************************************************/ - -int mprFindItem(MprArray *array, void *item) -{ - int i; - - mprAssert(array); - - for (i = 0; i < array->length; i++) { - if (array->items[i] == item) { - return i; - } - } - return MPR_ERR_NOT_FOUND; -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c b/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c deleted file mode 100644 index ba9888a9fc..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprBuf.c +++ /dev/null @@ -1,535 +0,0 @@ -/** - * @file mprBuf.c - * @brief Dynamic buffer module - * @overview - * @remarks - */ - -/******************************************************************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/**************************** Forward Declarations ****************************/ - -static int grow(MprBuf *bp); - -/*********************************** Code *************************************/ -/* - * Create a new buffer. "maxsize" is the limit to which the buffer can - * ever grow. -1 means no limit. The buffer can ever only fix maxsize-1 bytes. - * "initialSize" is used to define the amount to increase the size of the - * buffer each time if it becomes full. (Note: grow() will exponentially - * increase this number for performance.) - */ - -MprBuf *mprCreateBuf(MprCtx ctx, int initialSize, int maxSize) -{ - MprBuf *bp; - - if (initialSize <= 0) { - initialSize = MPR_DEFAULT_ALLOC; - } - bp = mprAllocTypeZeroed(ctx, MprBuf); - bp->growBy = MPR_BUFSIZE; - bp->maxsize = 0; - mprSetBufSize(bp, initialSize, maxSize); - return bp; -} - -/******************************************************************************/ -/* - * Set the initial buffer parameters and create the first buffer - */ - -void mprSetBufSize(MprBuf *bp, int initialSize, int max) -{ - mprAssert(initialSize > 0); - - if (max > 0 && initialSize > max) { - initialSize = max; - } - - if (bp->buf && bp->growBy > 0) { - mprFree(bp->buf); - } - - bp->buf = (uchar*) mprAlloc(bp, initialSize); - bp->growBy = initialSize; - bp->maxsize = max; - bp->buflen = initialSize; - bp->endbuf = &bp->buf[bp->buflen]; - bp->start = bp->buf; - bp->end = bp->buf; - *bp->start = '\0'; -} - -/******************************************************************************/ - -char *mprStealBuf(MprCtx ctx, MprBuf *bp) -{ - char *str; - - str = (char*) bp->start; - - mprStealAllocBlock(MPR_LOC_ARGS(ctx), bp->start); - - bp->start = bp->end = bp->buf = bp->endbuf = 0; - bp->buflen = 0; - - return str; -} - -/******************************************************************************/ - -void mprAddNullToBuf(MprBuf *bp) -{ - *((char*) bp->end) = (char) '\0'; -} - -/******************************************************************************/ - -void mprAdjustBufEnd(MprBuf *bp, int size) -{ - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - mprAssert(size < bp->buflen); - - bp->end += size; - if (bp->end >= bp->endbuf) { - bp->end -= bp->buflen; - } - if (bp->end < bp->buf) { - bp->end += bp->buflen; - } - - if (bp->end >= bp->endbuf) { - mprAssert(bp->end < bp->endbuf); - mprFlushBuf(bp); - } -} - -/******************************************************************************/ -/* - * Adjust the start pointer after a user copy - */ - -void mprAdjustBufStart(MprBuf *bp, int size) -{ - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - mprAssert(size < bp->buflen); - - bp->start += size; - while (bp->start >= bp->endbuf) { - bp->start -= bp->buflen; - } - while (bp->start < bp->buf) { - bp->start += bp->buflen; - } - - /* - * Flush the buffer if the start pointer is corrupted via a bad size - */ - if (bp->start >= bp->endbuf) { - mprAssert(bp->start < bp->endbuf); - mprFlushBuf(bp); - } -} - - -/******************************************************************************/ - -void mprFlushBuf(MprBuf *bp) -{ - bp->start = bp->buf; - bp->end = bp->buf; -} - -/******************************************************************************/ - -int mprGetCharFromBuf(MprBuf *bp) -{ - int c; - - if (bp->start == bp->end) { - return -1; - } - c = (uchar) *bp->start++; - if (bp->start >= bp->endbuf) { - bp->start = bp->buf; - } - return c; -} - -/******************************************************************************/ - -int mprGetBlockFromBuf(MprBuf *bp, uchar *buf, int size) -{ - int thisLen, bytesRead; - - mprAssert(buf); - mprAssert(size > 0); - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - - /* - * Get the max bytes in a straight copy - */ - bytesRead = 0; - while (size > 0) { - thisLen = mprGetBufLinearData(bp); - thisLen = min(thisLen, size); - if (thisLen <= 0) { - break; - } - - memcpy(buf, bp->start, thisLen); - buf += thisLen; - bp->start += thisLen; - size -= thisLen; - bytesRead += thisLen; - - if (bp->start >= bp->endbuf) { - bp->start = bp->buf; - } - } - return bytesRead; -} - -/******************************************************************************/ - -int mprGetBufLength(MprBuf *bp) -{ - if (bp->start > bp->end) { - return (bp->buflen + (bp->end - bp->start)); - } else { - return (bp->end - bp->start); - } -} - -/******************************************************************************/ - -int mprGetBufLinearData(MprBuf *bp) -{ - return min(mprGetBufLength(bp), (bp->endbuf - bp->start)); -} - -/******************************************************************************/ - -int mprGetBufLinearSpace(MprBuf *bp) -{ - int len = mprGetBufLength(bp); - int space = bp->buflen - len - 1; - return min((bp->endbuf - bp->end), space); -} - -/******************************************************************************/ - -int mprGetBufSize(MprBuf *bp) -{ - return bp->buflen; -} - -/******************************************************************************/ - -int mprGetBufSpace(MprBuf *bp) -{ - return bp->buflen - mprGetBufLength(bp) - 1; -} - -/******************************************************************************/ - -char *mprGetBufOrigin(MprBuf *bp) -{ - return (char*) bp->buf; -} - -/******************************************************************************/ - -char *mprGetBufStart(MprBuf *bp) -{ - return (char*) bp->start; -} - -/******************************************************************************/ - -char *mprGetBufEnd(MprBuf *bp) -{ - return (char*) bp->end; -} - -/******************************************************************************/ - -int mprInsertCharToBuf(MprBuf *bp, int c) -{ - char *cp; - int space; - - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - - space = bp->buflen - mprGetBufLength(bp) - 1; - if (space < (int) sizeof(char)) { - if (!grow(bp)) { - return -1; - } - } - if (bp->start <= bp->buf) { - bp->start = bp->endbuf; - } - cp = (char*) bp->start; - *--cp = (char) c; - bp->start = (uchar *) cp; - return 0; -} - -/******************************************************************************/ - -int mprLookAtNextCharInBuf(MprBuf *bp) -{ - if (bp->start == bp->end) { - return -1; - } - return *bp->start; -} - -/******************************************************************************/ - -int mprLookAtLastCharInBuf(MprBuf *bp) -{ - if (bp->start == bp->end) { - return -1; - } - return (bp->end == bp->buf) ? bp->endbuf[-1] : bp->end[-1]; -} - -/******************************************************************************/ - -int mprPutCharToBuf(MprBuf *bp, int c) -{ - char *cp; - int space; - - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - - space = bp->buflen - mprGetBufLength(bp) - 1; - if (space < (int) sizeof(char)) { - if (! grow(bp)) { - return -1; - } - } - - cp = (char*) bp->end; - *cp++ = (char) c; - bp->end = (uchar *) cp; - if (bp->end >= bp->endbuf) { - bp->end = bp->buf; - } - *((char*) bp->end) = (char) '\0'; - return 0; -} - -/******************************************************************************/ - -int mprPutBlockToBuf(MprBuf *bp, const char *str, int size) -{ - int thisLen, bytes, space; - - mprAssert(str); - mprAssert(size >= 0); - mprAssert(bp->buflen == (bp->endbuf - bp->buf)); - - /* - * Add the max we can in one copy - */ - bytes = 0; - while (size > 0) { - space = mprGetBufLinearSpace(bp); - thisLen = min(space, size); - if (thisLen <= 0) { - if (! grow(bp)) { - break; - } - space = mprGetBufLinearSpace(bp); - thisLen = min(space, size); - } - - memcpy(bp->end, str, thisLen); - str += thisLen; - bp->end += thisLen; - size -= thisLen; - bytes += thisLen; - - if (bp->end >= bp->endbuf) { - bp->end = bp->buf; - } - } - *((char*) bp->end) = (char) '\0'; - return bytes; -} - -/******************************************************************************/ - -int mprPutStringToBuf(MprBuf *bp, const char *str) -{ - return mprPutBlockToBuf(bp, str, strlen(str)); -} - -/******************************************************************************/ - -int mprPutFmtStringToBuf(MprBuf *bp, const char *fmt, ...) -{ - va_list ap; - char *buf; - int rc, len, space; - - va_start(ap, fmt); - space = mprGetBufLinearSpace(bp); - - /* - * Add max that the buffer can grow - */ - space += (bp->maxsize - bp->buflen - 1); - - len = mprAllocVsprintf(MPR_LOC_ARGS(bp), &buf, space, fmt, ap); - rc = mprPutBlockToBuf(bp, buf, len); - - mprFree(buf); - va_end(ap); - return rc; -} - -/******************************************************************************/ -/* - * Grow the buffer to fit new data. Return 1 if the buffer can grow. - * Grow using the growBy size specified when creating the buffer. - */ - -static int grow(MprBuf *bp) -{ - uchar *newbuf; - - if (bp->maxsize > 0 && bp->buflen >= bp->maxsize) { - return 0; - } - - newbuf = (uchar*) mprAlloc(bp, bp->buflen + bp->growBy); - if (bp->buf) { - memcpy(newbuf, bp->buf, bp->buflen); - mprFree(bp->buf); - } - - bp->buflen += bp->growBy; - bp->end = newbuf + (bp->end - bp->buf); - bp->start = newbuf + (bp->start - bp->buf); - bp->buf = newbuf; - bp->endbuf = &bp->buf[bp->buflen]; - - /* - * Increase growBy to reduce overhead - */ - bp->growBy *= 2; - if (bp->maxsize > 0 && (bp->buflen + bp->growBy) > bp->maxsize) { - bp->growBy = bp->maxsize - bp->buflen; - } - return 1; -} - -/******************************************************************************/ -/* - * Add a number to the buffer (always null terminated). - */ - -int mprPutIntToBuf(MprBuf *bp, int i) -{ - char numBuf[16]; - int rc; - - mprItoa(numBuf, sizeof(numBuf), i); - rc = mprPutStringToBuf(bp, numBuf); - *((char*) bp->end) = (char) '\0'; - - return rc; -} - -/******************************************************************************/ - -void mprCopyBufDown(MprBuf *bp) -{ - if (mprGetBufLength(bp) == 0) { - mprFlushBuf(bp); - return; - } - memmove(bp->buf, bp->start, (bp->end - bp->start)); - bp->end -= (bp->start - bp->buf); - bp->start = bp->buf; -} - -/******************************************************************************/ - -MprBufProc mprGetBufRefillProc(MprBuf *bp) -{ - return bp->refillProc; -} - -/******************************************************************************/ - -void mprSetBufRefillProc(MprBuf *bp, MprBufProc fn, void *arg) -{ - bp->refillProc = fn; - bp->refillArg = arg; -} - -/******************************************************************************/ - -int mprRefillBuf(MprBuf *bp) -{ - return (bp->refillProc) ? (bp->refillProc)(bp, bp->refillArg) : 0; -} - -/******************************************************************************/ - -void mprResetBufIfEmpty(MprBuf *bp) -{ - if (mprGetBufLength(bp) == 0) { - mprFlushBuf(bp); - } -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c b/source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c deleted file mode 100644 index 517e43853f..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprGenFile.c +++ /dev/null @@ -1,336 +0,0 @@ -/** - * @file mprGenFile.c - * @brief Generic File services - * @overview - * @remarks - * See OS/mprFile.c for the per O/S portions - */ - -/******************************************************************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "mpr.h" - -/****************************** Forward Declarations **************************/ -#if !BREW - -static int closeDestructor(void *data); - -/************************************ Code ************************************/ - -int mprStartFileServices(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - app->console = mprAllocTypeZeroed(ctx, MprFile); - app->error = mprAllocTypeZeroed(ctx, MprFile); - - /* - * We assume that STDOUT is 1 and STDERR is 2 - */ - app->console->fd = 1; - app->error->fd = 2; - - return 0; -} - -/******************************************************************************/ - -void mprStopFileServices(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - - mprFree(app->console); - app->console = 0; - mprFree(app->error); - app->error = 0; -} - -/******************************************************************************/ - -MprFile *mprOpen(MprCtx ctx, const char *path, int omode, int perms) -{ - MprFile *file; - - mprAssert(path && *path); - - file = mprAllocTypeZeroed(ctx, MprFile); - - file->fd = open(path, omode, perms); - if (file->fd < 0) { - mprFree(file); - return 0; - } - - mprSetDestructor(file, closeDestructor); - return file; -} - -/******************************************************************************/ - -static int closeDestructor(void *data) -{ - MprFile *file = (MprFile*) data; - - mprAssert(file); - - mprClose(file); - return 0; -} - -/******************************************************************************/ - -void mprClose(MprFile *file) -{ - mprAssert(file); - - if (file < 0) { - return; - } - - mprAssert(file->fd >= 0); - close(file->fd); - - mprSetDestructor(file, 0); - mprFree(file); -} - -/******************************************************************************/ - -int mprRead(MprFile *file, void *buf, uint size) -{ - mprAssert(file); - - if (file == 0) { - return MPR_ERR_BAD_HANDLE; - } - - return read(file->fd, buf, size); -} - -/******************************************************************************/ - -int mprWrite(MprFile *file, const void *buf, uint count) -{ - mprAssert(file); - - if (file == 0) { - return MPR_ERR_BAD_HANDLE; - } - - return write(file->fd, buf, count); -} - -/******************************************************************************/ - -int mprSeek(MprFile *file, int seekType, long distance) -{ - mprAssert(file); - - if (file == 0) { - return MPR_ERR_BAD_HANDLE; - } - - return lseek(file->fd, seekType, distance); -} - -/******************************************************************************/ - -int mprDelete(MprCtx ctx, const char *path) -{ - return unlink(path); -} - -/******************************************************************************/ - -int mprDeleteDir(MprCtx ctx, const char *path) -{ - return rmdir(path); -} - -#endif /* !BREW */ -/******************************************************************************/ - -char *mprGets(MprFile *file, char *buf, uint size) -{ - MprBuf *bp; - int count, len, c; - - mprAssert(file); - - if (file == 0) { - return 0; - } - - if (file->buf == 0) { - file->buf = mprCreateBuf(file, MPR_DEFAULT_ALLOC, MPR_MAX_STRING); - } - bp = file->buf; - - /* - * Must leave room for null - */ - count = 0; - while (--size > 0) { - if (mprGetBufLength(bp) == 0) { - mprFlushBuf(bp); - len = mprRead(file, mprGetBufEnd(bp), - mprGetBufLinearSpace(bp)); - if (len <= 0) { - return 0; - } - mprAdjustBufEnd(bp, len); - mprAddNullToBuf(bp); - } - if ((c = mprGetCharFromBuf(bp)) == '\n') { - buf[count] = '\0'; - return buf; - } - buf[count++] = c; - } - buf[count] = '\0'; - return buf; -} - -/******************************************************************************/ - -int mprPuts(MprFile *file, const char *writeBuf, uint count) -{ - MprBuf *bp; - char *buf; - int total, bytes, len; - - mprAssert(file); - - /* - * Buffer output and flush when full. - */ - if (file->buf == 0) { - file->buf = mprCreateBuf(file, MPR_BUFSIZE, 0); - if (file->buf == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - } - bp = file->buf; - - if (mprGetBufLength(bp) > 0 && mprGetBufSpace(bp) < (int) count) { - len = mprGetBufLength(bp); - if (mprWrite(file, mprGetBufStart(bp), len) != len) { - return MPR_ERR_CANT_WRITE; - } - mprFlushBuf(bp); - } - - total = 0; - buf = (char*) writeBuf; - - while (count > 0) { - bytes = mprPutBlockToBuf(bp, buf, count); - if (bytes <= 0) { - return MPR_ERR_CANT_ALLOCATE; - } - count -= bytes; - buf += bytes; - total += bytes; - mprAddNullToBuf(bp); - - if (count > 0) { - len = mprGetBufLength(bp); - if (mprWrite(file, mprGetBufStart(bp), len) != len) { - return MPR_ERR_CANT_WRITE; - } - mprFlushBuf(bp); - } - } - return total; -} - -/******************************************************************************/ - -int mprMakeTempFileName(MprCtx ctx, char *buf, int bufsize, const char *tempDir) -{ - MprFile *file; - MprTime now; - char *dir; - int seed, i; - - if (tempDir == 0) { -#if WIN - char *cp; - dir = mprStrdup(ctx, getenv("TEMP")); - for (cp = dir; *cp; cp++) { - if (*cp == '\\') { - *cp = '/'; - } - } -#else - dir = mprStrdup(ctx, "/tmp"); -#endif - } else { - dir = mprStrdup(ctx, tempDir); - } - - mprGetTime(ctx, &now); - seed = now.msec % 64000; - file = 0; - - for (i = 0; i < 128; i++) { - mprSprintf(buf, bufsize, "%s/MPR_%d_%d.tmp", dir, getpid(), seed++); - file = mprOpen(ctx, buf, O_CREAT | O_EXCL | O_BINARY, 0664); - if (file) { - break; - } - } - - if (file == 0) { - return MPR_ERR_CANT_CREATE; - } - - mprClose(file); - mprFree(dir); - - return 0; -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c b/source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c deleted file mode 100644 index 6b0ed97bbc..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprGenTime.c +++ /dev/null @@ -1,195 +0,0 @@ -/** - * @file mprGenTime.c - * @brief Generic Time handling - * @overview - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************* Includes ***********************************/ - -#include "mpr.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/******************************************************************************/ -/* - * Return the number of milliseconds until the given timeout has expired. - */ - -int mprGetTimeRemaining(MprCtx ctx, MprTime mark, uint timeout) -{ - MprTime now; - uint diff; - - mprGetTime(ctx, &now); - diff = ((now.sec - mark.sec) * 1000) + (now.msec - mark.msec); - - if (diff < 0) { - /* - * Detect time going backwards - */ - mprAssert(diff >= 0); - diff = 0; - } - return (int) (timeout - diff); -} - -/******************************************************************************/ -/* - * Return the number of milliseconds until the given timeout has expired. - */ - -int mprGetElapsedTime(MprCtx ctx, MprTime mark) -{ - MprTime now; - - mprGetTime(ctx, &now); - return ((now.sec - mark.sec) * 1000) + (now.msec - mark.msec); -} - -/******************************************************************************/ - -void mprAddElapsedToTime(MprTime *time, uint elapsed) -{ - time->sec += elapsed / 1000; - time->msec += elapsed % 1000; - if (time->msec > 1000) { - time->msec -= 1000; - time->sec++; - } -} - -/******************************************************************************/ - -int mprCompareTime(MprTime *t1, MprTime *t2) -{ - if (t1->sec < t2->sec) { - return -1; - } else if (t1->sec == t2->sec) { - if (t1->msec < t2->msec) { - return -1; - } else if (t1->msec == t2->msec) { - return 0; - } - } - return 1; -} - -/******************************************************************************/ - -uint mprSubtractTime(MprTime *t1, MprTime *t2) -{ - return ((t1->sec - t2->sec) * 1000) + (t1->msec - t2->msec); -} - -/******************************************************************************/ -#if !BREW -/* - * Thread-safe RFC822 dates (Eg: "Fri, 07 Jan 2003 12:12:21 GMT") - */ - -int mprRfcTime(MprCtx ctx, char *buf, int bufsize, const struct tm *timep) -{ - char months[12][4] = { - "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", - "Oct", "Nov", "Dec" - }; - - char days[7][4] = { - "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" - }; - - char *dayp, *monthp; - int year; - - if (bufsize < 30) { - return MPR_ERR_WONT_FIT; - } - dayp = &days[timep->tm_wday][0]; - *buf++ = *dayp++; - *buf++ = *dayp++; - *buf++ = *dayp++; - *buf++ = ','; - *buf++ = ' '; - - *buf++ = timep->tm_mday / 10 + '0'; - *buf++ = timep->tm_mday % 10 + '0'; - *buf++ = ' '; - - monthp = &months[timep->tm_mon][0]; - *buf++ = *monthp++; - *buf++ = *monthp++; - *buf++ = *monthp++; - *buf++ = ' '; - - year = 1900 + timep->tm_year; - /* This routine isn't y10k ready. */ - *buf++ = year / 1000 + '0'; - *buf++ = year % 1000 / 100 + '0'; - *buf++ = year % 100 / 10 + '0'; - *buf++ = year % 10 + '0'; - *buf++ = ' '; - - *buf++ = timep->tm_hour / 10 + '0'; - *buf++ = timep->tm_hour % 10 + '0'; - *buf++ = ':'; - *buf++ = timep->tm_min / 10 + '0'; - *buf++ = timep->tm_min % 10 + '0'; - *buf++ = ':'; - *buf++ = timep->tm_sec / 10 + '0'; - *buf++ = timep->tm_sec % 10 + '0'; - *buf++ = ' '; - - *buf++ = 'G'; - *buf++ = 'M'; - *buf++ = 'T'; - *buf++ = 0; - return 0; -} - -#endif -/******************************************************************************/ - -#ifdef __cplusplus -} -#endif - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprLock.c b/source4/lib/appweb/ejs-2.0/mpr/mprLock.c deleted file mode 100644 index df9ce276d4..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprLock.c +++ /dev/null @@ -1,266 +0,0 @@ -/** - * @file mprThread.c - * @brief Mbedthis Portable Runtime Base Thread Locking Support - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "mpr.h" - -#if BLD_FEATURE_MULTITHREAD -/************************************ Code ************************************/ - -void mprInitThreads(MprApp *app) -{ - mprAssert(app); - - if (app->globalLock == 0) { - app->globalLock = mprCreateLock(app); - app->allocLock = mprCreateLock(app); - } -} - -/******************************************************************************/ - -void mprTermThreads(MprApp *app) -{ - mprAssert(app); - - if (app->globalLock) { - mprDestroyLock(app->globalLock); - app->globalLock = 0; - } - if (app->allocLock) { - MprLock *lock = app->allocLock; - app->allocLock = 0; - mprDestroyLock(lock); - } -} - -/******************************************************************************/ - -MprLock *mprCreateLock(MprCtx ctx) -{ - MprLock *lock; - - mprAssert(ctx); - - lock = mprAllocType(ctx, MprLock); - -#if BLD_HOST_UNIX - pthread_mutexattr_t attr; - - pthread_mutexattr_init(&attr); - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); - pthread_mutex_init(&lock->cs, &attr); - pthread_mutexattr_destroy(&attr); -#elif WIN - InitializeCriticalSectionAndSpinCount(&lock->cs, 5000); -#elif VXWORKS - lock->cs = semMCreate(SEM_Q_PRIORITY | SEM_DELETE_SAFE | - SEM_INVERSION_SAFE); - if (lock->cs == 0) { - mprAssert(0); - mprFree(lock); - return 0; - } -#endif - return lock; -} - -/******************************************************************************/ -/* - * Destroy a lock. Must be locked on entrance. - */ - -void mprDestroyLock(MprLock *lock) -{ - mprAssert(lock); - if (lock == 0) { - return; - } - -#if BLD_HOST_UNIX - pthread_mutex_unlock(&lock->cs); - pthread_mutex_destroy(&lock->cs); -#elif WIN - DeleteCriticalSection(&lock->cs); -#elif VXWORKS - semDelete(lock->cs); -#endif - mprFree(lock); -} - -/******************************************************************************/ -/* - * Lock a mutex - */ - -void mprLock(MprLock *lock) -{ - /* - * OPT -- Do this just so we can allocate MprApp before we have created its - * lock. Should remove this test here and in mprUnlock. - */ - if (lock == 0) { - return; - } - -#if BLD_HOST_UNIX - pthread_mutex_lock(&lock->cs); -#elif WIN - EnterCriticalSection(&lock->cs); -#elif VXWORKS - semTake(lock->cs, WAIT_FOREVER); -#endif -} - -/******************************************************************************/ -/* - * Try to attain a lock. Do not block! - */ - -int mprTryLock(MprLock *lock) -{ - mprAssert(lock); - -#if BLD_HOST_UNIX - { - int err; - - if ((err = pthread_mutex_trylock(&lock->cs)) != 0) { - if (err == EBUSY) { - return MPR_ERR_BUSY; - } else { - return MPR_ERR_CANT_ACCESS; - } - } - return 0; - } -#elif WIN - if (TryEnterCriticalSection(&lock->cs) == 0) { - return MPR_ERR_BUSY; - } -#elif VXWORKS - { - int rc; - - rc = semTake(cs, NO_WAIT); - if (rc == -1) { - mprAssert(0); - } - if (rc == S_objLib_OBJ_UNAVAILABLE) { - return MPR_ERR_BUSY; - } else { - return MPR_ERR_CANT_ACCESS; - } - /* Success */ - return 0; - } -#endif - return 0; -} - -/******************************************************************************/ -/* - * Unlock. - */ - -void mprUnlock(MprLock *lock) -{ - if (lock == 0) { - return; - } - -#if BLD_HOST_UNIX - pthread_mutex_unlock(&lock->cs); -#elif WIN - LeaveCriticalSection(&lock->cs); -#elif VXWORKS - semGive(lock->cs); -#endif -} - -/******************************************************************************/ -/* - * Big global lock. Avoid using this. - */ - -void mprGlobalLock(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - mprAssert(app); - - if (app && app->globalLock) { - mprLock(app->globalLock); - } -} - -/******************************************************************************/ - -void mprGlobalUnlock(MprCtx ctx) -{ - MprApp *app; - - app = mprGetApp(ctx); - mprAssert(app); - - if (app && app->globalLock) { - mprUnlock(app->globalLock); - } -} - -/******************************************************************************/ - -int mprGetCurrentThreadID() -{ -#if BLD_HOST_UNIX - return (int) pthread_self(); -#elif WIN - return GetCurrentThreadId(); -#elif VXWORKS - return (int) pthread_self(); -#endif -} - -/******************************************************************************/ -#endif /* BLD_FEATURE_MULTITHREAD */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprLog.c b/source4/lib/appweb/ejs-2.0/mpr/mprLog.c deleted file mode 100644 index 1eb175ed95..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprLog.c +++ /dev/null @@ -1,602 +0,0 @@ -/** - * @file mprLog.c - * @brief Mbedthis Portable Runtime (MPR) Logging and error reporting. - * @remarks We always provide these routines. - */ - -/*********************************** License **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "mpr.h" - -/****************************** Forward Declarations **************************/ - -static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags, - int level, const char *msg); -static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level, - const char *msg); - -/************************************ Code ************************************/ - -void mprLog(MprCtx ctx, int level, const char *fmt, ...) -{ - va_list args; - char *buf; - - if (level > mprGetLogLevel(ctx)) { - return; - } - - va_start(args, fmt); - mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args); - va_end(args); - - logOutput(MPR_LOC_ARGS(ctx), MPR_LOG_SRC, level, buf); - - va_end(args); - mprFree(buf); -} - -/*****************************************************************************/ -/* - * Do raw output - */ - -void mprRawLog(MprCtx ctx, const char *fmt, ...) -{ - va_list args; - char *buf; - int len; - - va_start(args, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args); - va_end(args); - - logOutput(MPR_LOC_ARGS(ctx), MPR_RAW, 0, buf); - mprFree(buf); -} - -/*****************************************************************************/ -/* - * Handle an error - */ - -void mprError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...) -{ - va_list args; - char *buf; - int len; - - va_start(args, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args); - va_end(args); - - logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf); - - mprFree(buf); -} - -/*****************************************************************************/ -/* - * Handle an error that should be displayed to the user - */ - -void mprUserError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...) -{ - va_list args; - char *buf; - int len; - - va_start(args, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args); - va_end(args); - - logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_ERROR_SRC, 0, buf); - - mprFree(buf); -} - -/*****************************************************************************/ -/* - * Handle a fatal error. Forcibly shutdown the application. - */ - -void mprFatalError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...) -{ - va_list args; - char *buf; - int len; - - va_start(args, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, args); - va_end(args); - - logOutput(MPR_LOC_PASS(ctx, loc), MPR_USER_MSG | MPR_FATAL_SRC, 0, buf); - - mprFree(buf); - -#if BREW - mprSignalExit(ctx); -#else - exit(2); -#endif -} - -/*****************************************************************************/ -/* - * Handle a program assertion - */ - -void mprAssertError(MPR_LOC_DEC(ctx, loc), const char *msg) -{ - logOutput(MPR_LOC_PASS(ctx, loc), MPR_ASSERT_MSG | MPR_ASSERT_SRC, 0, msg); -} - -/*****************************************************************************/ -/* - * Handle an error - */ - -void mprStaticError(MPR_LOC_DEC(ctx, loc), const char *fmt, ...) -{ - va_list args; - int len; - char buf[MPR_MAX_STRING]; - - va_start(args, fmt); - len = mprVsprintf(buf, sizeof(buf), fmt, args); - va_end(args); - - logOutput(MPR_LOC_PASS(ctx, loc), MPR_ERROR_MSG | MPR_ERROR_SRC, 0, buf); -} - -/*****************************************************************************/ -/* - * Direct output to the standard output. Does not hook into the logging - * system and does not allocate memory. - */ - -void mprStaticAssert(const char *loc, const char *msg) -{ -#if BLD_DEBUG - char buf[MPR_MAX_STRING]; - int len; - - len = mprSprintf(buf, sizeof(buf), "Assertion %s, failed at %s\n", - msg, loc); - mprBreakpoint(loc, buf); - -#if BLD_HOST_UNIX - /* - * MOB -- but is stdout always okay to use - */ - write(1, buf, len); -#elif BREW || WIN - /* - * Only time we use printf. We can't get an alloc context so we have - * to use real print - */ -#if BREW && !BREW_SIMULATOR - printf(" MP: %s\n", buf); -#else - printf("%s\n", buf); -#endif - -#endif -#endif -} - -/*****************************************************************************/ - -int mprGetLogLevel(MprCtx ctx) -{ - return mprGetApp(ctx)->logLevel; -} - -/******************************************************************************/ - -void mprSetLogLevel(MprCtx ctx, int level) -{ - mprGetApp(ctx)->logLevel = level; -} - -/*****************************************************************************/ -/* - * Output a log message to the log handler - */ - -static void logOutput(MPR_LOC_DEC(ctx, loc), int flags, int level, - const char *msg) -{ - MprLogHandler handler; - - if (flags & (MPR_ERROR_SRC | MPR_FATAL_SRC | MPR_ASSERT_SRC)) { - mprBreakpoint(MPR_LOC, 0); - } - - mprAssert(ctx != 0); - handler = mprGetApp(ctx)->logHandler; - if (handler != 0) { - (handler)(MPR_LOC_PASS(ctx, loc), flags, level, msg); - return; - } - defaultLogHandler(MPR_LOC_PASS(ctx, loc), flags, level, msg); -} - -/*****************************************************************************/ -/* - * Default log output is just to the console - */ - -static void defaultLogHandler(MPR_LOC_DEC(ctx, loc), int flags, - int level, const char *msg) -{ - MprApp *app; - char *prefix; - - app = mprGetApp(ctx); - prefix = app->name; - - while (*msg == '\n') { - mprPrintf(ctx, "\n"); - msg++; - } - - if (flags & MPR_LOG_SRC) { -#if BREW && !BREW_SIMULATOR - mprPrintf(ctx, "%s\n", msg); -#else - mprPrintf(ctx, "%s: %d: %s\n", prefix, level, msg); -#endif - - } else if (flags & MPR_ERROR_SRC) { - /* - * Use static printing to avoid malloc when the messages are small. - * This is important for memory allocation errors. - */ - if (strlen(msg) < (MPR_MAX_STRING - 32)) { - mprStaticPrintf(ctx, "%s: Error: %s\n", prefix, msg); - } else { - mprPrintf(ctx, "%s: Error: %s\n", prefix, msg); - } - - } else if (flags & MPR_FATAL_SRC) { - mprPrintf(ctx, "%s: Fatal: %s\n", prefix, msg); - - } else if (flags & MPR_ASSERT_SRC) { -#if BLD_FEATURE_ALLOC_LEAK_TRACK - mprPrintf(ctx, "%s: Assertion %s, failed at %s\n", prefix, msg, loc); -#else - mprPrintf(ctx, "%s: Assertion %s, failed\n", prefix, msg); -#endif - - } else if (flags & MPR_RAW) { - mprPrintf(ctx, "%s", msg); - - } else { - return; - } -} - -/*****************************************************************************/ -/* - * Map the O/S error code to portable error codes. - */ - -int mprGetOsError() -{ -#if WIN - int rc; - rc = GetLastError(); - - /* - * Client has closed the pipe - */ - if (rc == ERROR_NO_DATA) { - return EPIPE; - } - return rc; -#endif -#if LINUX || VXWORKS || SOLARIS - return errno; -#endif -#if BREW - /* - * No such thing on Brew. Errors are per class - */ - return 0; -#endif -} - -/******************************************************************************/ -#if UNUSED - -const char *mprGetErrorMsg(int err) -{ - /* - * MPR error messages. Declare here so we don't have any globals. - */ - char *mprErrMessages[] = { - /* 0 MPR_ERR_OK */ "Success", - /* -201 MPR_ERR_GENERAL */ "General error", - /* -202 MPR_ERR_ABORTED */ "Aborted", - /* -203 MPR_ERR_ALREADY_EXISTS */ "Already exists", - /* -204 MPR_ERR_BAD_ARGS */ "Bad args", - /* -205 MPR_ERR_BAD_FORMAT */ "Bad format", - /* -206 MPR_ERR_BAD_HANDLE */ "Bad handle", - /* -207 MPR_ERR_BAD_STATE */ "Bad state", - /* -208 MPR_ERR_BAD_SYNTAX */ "Bad syntax", - /* -209 MPR_ERR_BAD_TYPE */ "Bad type", - /* -210 MPR_ERR_BAD_VALUE */ "Bad value", - /* -211 MPR_ERR_BUSY */ "Busy", - /* -212 MPR_ERR_CANT_ACCESS */ "Can't access", - /* -213 MPR_ERR_CANT_COMPLETE */ "Can't complete", - /* -214 MPR_ERR_CANT_CREATE */ "Can't create", - /* -215 MPR_ERR_CANT_INITIALIZE */ "Can't initialize", - /* -216 MPR_ERR_CANT_OPEN */ "Can't open", - /* -217 MPR_ERR_CANT_READ */ "Can't read", - /* -218 MPR_ERR_CANT_WRITE */ "Can't write", - /* -219 MPR_ERR_DELETED */ "Already deleted", - /* -220 MPR_ERR_NETWORK */ "Network error", - /* -221 MPR_ERR_NOT_FOUND */ "Not found", - /* -222 MPR_ERR_NOT_INITIALIZED */ "Not initialized", - /* -223 MPR_ERR_NOT_READY */ "Not ready", - /* -224 MPR_ERR_READ_ONLY */ "Read only", - /* -225 MPR_ERR_TIMEOUT */ "Timeout", - /* -226 MPR_ERR_TOO_MANY */ "Too many", - /* -227 MPR_ERR_WONT_FIT */ "Won't fit", - /* -228 MPR_ERR_WOULD_BLOCK */ "Would block", - /* -229 MPR_ERR_CANT_ALLOCATE */ "Can't allocate", - }; - int mprNumErr = sizeof(mprErrMessages) / sizeof(char*); - -/* - * Operating system error messages - */ -#if WIN -char *osErrMessages[] = -{ - /* 0 */ "No error", - /* 1 EPERM */ "Operation not permitted", - /* 2 ENOENT */ "No such file or directory", - /* 3 ESRCH */ "No such process", - /* 4 EINTR */ "Interrupted function call", - /* 5 EIO */ "I/O error", - /* 6 ENXIO */ "No such device or address", - /* 7 E2BIG */ "Arg list too long", - /* 8 ENOEXEC */ "Exec format error", - /* 9 EBADF */ "Bad file number", - /* 10 ECHILD */ "No child processes", - /* 11 EAGAIN */ "Try again", - /* 12 ENOMEM */ "Out of memory", - /* 13 EACCES */ "Permission denied", - /* 14 EFAULT */ "Bad address", - /* 15 ENOTBLK */ "Unknown error", - /* 16 EBUSY */ "Resource busy", - /* 17 EEXIST */ "File exists", - /* 18 EXDEV */ "Improper link", - /* 19 ENODEV */ "No such device", - /* 20 ENOTDIR */ "Not a directory", - /* 21 EISDIR */ "Is a directory", - /* 22 EINVAL */ "Invalid argument", - /* 23 ENFILE */ "Too many open files in system", - /* 24 EMFILE */ "Too many open files", - /* 25 ENOTTY */ "Inappropriate I/O control operation", - /* 26 ETXTBSY */ "Unknown error", - /* 27 EFBIG */ "File too large", - /* 28 ENOSPC */ "No space left on device", - /* 29 ESPIPE */ "Invalid seek", - /* 30 EROFS */ "Read-only file system", - /* 31 EMLINK */ "Too many links", - /* 32 EPIPE */ "Broken pipe", - /* 33 EDOM */ "Domain error", - /* 34 ERANGE */ "Result too large", - /* 35 EUCLEAN */ "Unknown error", - /* 36 EDEADLK */ "Resource deadlock would occur", - /* 37 UNKNOWN */ "Unknown error", - /* 38 ENAMETOOLONG */ "Filename too long", - /* 39 ENOLCK */ "No locks available", - /* 40 ENOSYS */ "Function not implemented", - /* 41 ENOTEMPTY */ "Directory not empty", - /* 42 EILSEQ */ "Illegal byte sequence", - /* 43 ENETDOWN */ "Network is down", - /* 44 ECONNRESET */ "Connection reset", - /* 45 ECONNREFUSED */ "Connection refused", - /* 46 EADDRINUSE */ "Address already in use" - -}; - -#else /* WIN */ - -char *osErrMessages[] = -{ - /* 0 */ "Success" - /* 1 EPERM */ "Operation not permitted" - /* 2 ENOENT */ "No such file or directory" - /* 3 ESRCH */ "No such process" - /* 4 EINTR */ "Interrupted system call" - /* 5 EIO */ "I/O error" - /* 6 ENXIO */ "No such device or address" - /* 7 E2BIG */ "Arg list too long" - /* 8 ENOEXEC */ "Exec format error" - /* 9 EBADF */ "Bad file number" - /* 10 ECHILD */ "No child processes" - /* 11 EAGAIN */ "Try again" - /* 12 ENOMEM */ "Out of memory" - /* 13 EACCES */ "Permission denied" - /* 14 EFAULT */ "Bad address" - /* 15 ENOTBLK */ "Block device required" - /* 16 EBUSY */ "Device or resource busy" - /* 17 EEXIST */ "File exists" - /* 18 EXDEV */ "Cross-device link" - /* 19 ENODEV */ "No such device" - /* 20 ENOTDIR */ "Not a directory" - /* 21 EISDIR */ "Is a directory" - /* 22 EINVAL */ "Invalid argument" - /* 23 ENFILE */ "File table overflow" - /* 24 EMFILE */ "Too many open files" - /* 25 ENOTTY */ "Not a typewriter" - /* 26 ETXTBSY */ "Text file busy" - /* 27 EFBIG */ "File too large" - /* 28 ENOSPC */ "No space left on device" - /* 29 ESPIPE */ "Illegal seek" - /* 30 EROFS */ "Read-only file system" - /* 31 EMLINK */ "Too many links" - /* 32 EPIPE */ "Broken pipe" - /* 33 EDOM */ "Math argument out of domain of func" - /* 34 ERANGE */ "Math result not representable" - /* 35 EDEADLK */ "Resource deadlock would occur" - /* 36 ENAMETOOLONG */ "File name too long" - /* 37 ENOLCK */ "No record locks available" - /* 38 ENOSYS */ "Function not implemented" - /* 39 ENOTEMPTY */ "Directory not empty" - /* 40 ELOOP */ "Too many symbolic links encountered" - /* 41 EWOULDBLOCK EAGAIN */"Operation would block" - /* 42 ENOMSG */ "No message of desired type" - /* 43 EIDRM */ "Identifier removed" - -#if !BLD_FEATURE_SQUEEZE - /* 44 ECHRNG */ "Channel number out of range" - /* 45 EL2NSYNC */ "Level 2 not synchronized" - /* 46 EL3HLT */ "Level 3 halted" - /* 47 EL3RST */ "Level 3 reset" - /* 48 ELNRNG */ "Link number out of range" - /* 49 EUNATCH */ "Protocol driver not attached" - /* 50 ENOCSI */ "No CSI structure available" - /* 51 EL2HLT */ "Level 2 halted" - /* 52 EBADE */ "Invalid exchange" - /* 53 EBADR */ "Invalid request descriptor" - /* 54 EXFULL */ "Exchange full" - /* 55 ENOANO */ "No anode" - /* 56 EBADRQC */ "Invalid request code" - /* 57 EBADSLT */ "Invalid slot" - /* 59 EBFONT */ "Bad font file format" - /* 60 ENOSTR */ "Device not a stream" - /* 61 ENODATA */ "No data available" - /* 62 ETIME */ "Timer expired" - /* 63 ENOSR */ "Out of streams resources" - /* 64 ENONET */ "Machine is not on the network" - /* 65 ENOPKG */ "Package not installed" - /* 66 EREMOTE */ "Object is remote" - /* 67 ENOLINK */ "Link has been severed" - /* 68 EADV */ "Advertise error" - /* 69 ESRMNT */ "Srmount error" - /* 70 ECOMM */ "Communication error on send" - /* 71 EPROTO */ "Protocol error" - /* 72 EMULTIHOP */ "Multihop attempted" - /* 73 EDOTDOT */ "RFS specific error" - /* 74 EBADMSG */ "Not a data message" - /* 75 EOVERFLOW */ "Value too large for defined data type" - /* 76 ENOTUNIQ */ "Name not unique on network" - /* 77 EBADFD */ "File descriptor in bad state" - /* 78 EREMCHG */ "Remote address changed" - /* 79 ELIBACC */ "Can not access a needed shared library" - /* 80 ELIBBAD */ "Accessing a corrupted shared library" - /* 81 ELIBSCN */ ".lib section in a.out corrupted" - /* 82 ELIBMAX */ "Linking in too many shared libraries" - /* 83 ELIBEXEC */ "Cannot exec a shared library directly" - /* 84 EILSEQ */ "Illegal byte sequence" - /* 85 ERESTART */ "Interrupted system call should be restarted" - /* 86 ESTRPIPE */ "Streams pipe error" - /* 87 EUSERS */ "Too many users" - /* 88 ENOTSOCK */ "Socket operation on non-socket" - /* 89 EDESTADDRREQ */ "Destination address required" - /* 90 EMSGSIZE */ "Message too long" - /* 91 EPROTOTYPE */ "Protocol wrong type for socket" - /* 92 ENOPROTOOPT */ "Protocol not available" - /* 93 EPROTONOSUPPORT */ "Protocol not supported" - /* 94 ESOCKTNOSUPPORT */ "Socket type not supported" - /* 95 EOPNOTSUPP */ "Operation not supported on transport endpoint" - /* 96 EPFNOSUPPORT */ "Protocol family not supported" - /* 97 EAFNOSUPPORT */ "Address family not supported by protocol" - /* 98 EADDRINUSE */ "Address already in use" - /* 99 EADDRNOTAVAIL */ "Cannot assign requested address" - /* 100 ENETDOWN */ "Network is down" - /* 101 ENETUNREACH */ "Network is unreachable" - /* 102 ENETRESET */ "Network dropped connection because of reset" - /* 103 ECONNABORTED */ "Software caused connection abort" - /* 104 ECONNRESET */ "Connection reset by peer" - /* 105 ENOBUFS */ "No buffer space available" - /* 106 EISCONN */ "Transport endpoint is already connected" - /* 107 ENOTCONN */ "Transport endpoint is not connected" - /* 108 ESHUTDOWN */ "Cannot send after transport endpoint shutdown" - /* 109 ETOOMANYREFS */ "Too many references: cannot splice" - /* 110 ETIMEDOUT */ "Connection timed out" - /* 111 ECONNREFUSED */ "Connection refused" - /* 112 EHOSTDOWN */ "Host is down" - /* 113 EHOSTUNREACH */ "No route to host" - /* 114 EALREADY */ "Operation already in progress" - /* 115 EINPROGRESS */ "Operation now in progress" - /* 116 ESTALE */ "Stale NFS file handle" - /* 117 EUCLEAN */ "Structure needs cleaning" - /* 118 ENOTNAM */ "Not a XENIX named type file" - /* 119 ENAVAIL */ "No XENIX semaphores available" - /* 120 EISNAM */ "Is a named type file" - /* 121 EREMOTEIO */ "Remote I/O error" - /* 122 EDQUOT */ "Quota exceeded" - /* 123 ENOMEDIUM */ "No medium found" - /* 124 EMEDIUMTYPE */ "Wrong medium type" -}; -#endif /* BLD_FEATURE_SQUEEZE */ -#endif /* WIN */ - - int osNumErr = sizeof(osErrMessages) / sizeof(char*); - - if (err < MPR_ERR_BASE) { - err = MPR_ERR_BASE - err; - if (err < 0 || err >= mprNumErr) { - return "Bad error code"; - } - return mprErrMessages[err]; - - } else { - /* - * Negative O/S error code. Map to a positive standard Posix error. - */ - err = -err; - if (err < 0 || err >= osNumErr) { - return "Bad O/S error code"; - } - return osErrMessages[err]; - } -} - -#endif -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprOs.h b/source4/lib/appweb/ejs-2.0/mpr/mprOs.h deleted file mode 100644 index bed4ca5979..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprOs.h +++ /dev/null @@ -1,707 +0,0 @@ -/* - * @file mprOs.h - * @brief Include O/S headers and smooth out per-O/S differences - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This header is part of the Mbedthis Portable Runtime and aims to include - * all necessary O/S headers and to unify the constants and declarations - * required by Mbedthis products. It can be included by C or C++ programs. - */ - -/******************************************************************************/ - -#ifndef _h_MPR_OS_HDRS -#define _h_MPR_OS_HDRS 1 - -#include "buildConfig.h" - -/********************************* CPU Families *******************************/ -/* - * Porters, add your CPU families here and update configure code. - */ -#define MPR_CPU_UNKNOWN 0 -#define MPR_CPU_IX86 1 -#define MPR_CPU_PPC 2 -#define MPR_CPU_SPARC 3 -#define MPR_CPU_XSCALE 4 -#define MPR_CPU_ARM 5 -#define MPR_CPU_MIPS 6 -#define MPR_CPU_68K 7 -#define MPR_CPU_SIMNT 8 /* VxWorks NT simulator */ -#define MPR_CPU_SIMSPARC 9 /* VxWorks sparc simulator */ - -/********************************* O/S Includes *******************************/ - -#if LINUX || SOLARIS - #include <sys/types.h> - #include <time.h> - #include <arpa/inet.h> - #include <ctype.h> - #include <dirent.h> - #include <dlfcn.h> - #include <fcntl.h> - #include <grp.h> - #include <errno.h> - #include <libgen.h> - #include <limits.h> - #include <netdb.h> - #include <net/if.h> - #include <netinet/in.h> - #include <netinet/tcp.h> - #include <netinet/ip.h> - #include <pthread.h> - #include <pwd.h> - #include <resolv.h> - #include <signal.h> - #include <stdarg.h> - #include <stdio.h> - #include <stdlib.h> - #include <string.h> - #include <syslog.h> - #include <sys/ioctl.h> - #include <sys/stat.h> - #include <sys/param.h> - #include <sys/resource.h> - #include <sys/sem.h> - #include <sys/shm.h> - #include <sys/socket.h> - #include <sys/select.h> - #include <sys/time.h> - #include <sys/times.h> - #include <sys/utsname.h> - #include <sys/wait.h> - #include <unistd.h> - -#if LINUX - #include <stdint.h> -#endif - -#if SOLARIS - #include <netinet/in_systm.h> -#endif - -#if BLD_FEATURE_FLOATING_POINT - #define __USE_ISOC99 1 - #include <math.h> - #include <values.h> -#endif - -#endif /* LINUX || SOLARIS */ - -#if VXWORKS - #include <vxWorks.h> - #include <envLib.h> - #include <sys/types.h> - #include <time.h> - #include <arpa/inet.h> - #include <ctype.h> - #include <dirent.h> - #include <fcntl.h> - #include <errno.h> - #include <limits.h> - #include <loadLib.h> - #include <netdb.h> - #include <net/if.h> - #include <netinet/tcp.h> - #include <netinet/in.h> - #include <netinet/ip.h> - #include <signal.h> - #include <stdarg.h> - #include <stdio.h> - #include <stdlib.h> - #include <string.h> - #include <sysSymTbl.h> - #include <sys/fcntlcom.h> - #include <sys/ioctl.h> - #include <sys/stat.h> - #include <sys/socket.h> - #include <sys/times.h> - #include <sys/wait.h> - #include <unistd.h> - #include <unldLib.h> - - #if BLD_FEATURE_FLOATING_POINT - #include <float.h> - #define __USE_ISOC99 1 - #include <math.h> - #endif - - #include <sockLib.h> - #include <inetLib.h> - #include <ioLib.h> - #include <pipeDrv.h> - #include <hostLib.h> - #include <netdb.h> - #include <tickLib.h> - #include <taskHookLib.h> - -#endif /* VXWORKS */ - -#if MACOSX - #include <time.h> - #include <arpa/inet.h> - #include <ctype.h> - #include <fcntl.h> - #include <grp.h> - #include <errno.h> - #include <libgen.h> - #include <limits.h> - #include <mach-o/dyld.h> - #include <netdb.h> - #include <net/if.h> - #include <netinet/in_systm.h> - #include <netinet/in.h> - #include <netinet/tcp.h> - #include <netinet/ip.h> - #include <pthread.h> - #include <pwd.h> - #include <resolv.h> - #include <signal.h> - #include <stdarg.h> - #include <stdio.h> - #include <stdlib.h> - #include <stdint.h> - #include <string.h> - #include <syslog.h> - #include <sys/ioctl.h> - #include <sys/types.h> - #include <sys/stat.h> - #include <sys/param.h> - #include <sys/resource.h> - #include <sys/sem.h> - #include <sys/shm.h> - #include <sys/socket.h> - #include <sys/select.h> - #include <sys/time.h> - #include <sys/times.h> - #include <sys/types.h> - #include <sys/utsname.h> - #include <sys/wait.h> - #include <unistd.h> -#endif /* MACOSX */ - -#if WIN - /* - * We replace insecure functions with Mbedthis replacements - */ - #define _CRT_SECURE_NO_DEPRECATE 1 - - #include <ctype.h> - #include <conio.h> - #include <direct.h> - #include <errno.h> - #include <fcntl.h> - #include <io.h> - #include <limits.h> - #include <malloc.h> - #include <process.h> - #include <sys/stat.h> - #include <sys/types.h> - #include <stddef.h> - #include <stdio.h> - #include <stdlib.h> - #include <string.h> - #include <stdarg.h> - #include <time.h> - #define WIN32_LEAN_AND_MEAN - #include <winsock2.h> - #include <windows.h> - #include <winbase.h> - #if BLD_FEATURE_FLOATING_POINT - #include <float.h> - #endif - #include <shlobj.h> - #include <shellapi.h> - #include <wincrypt.h> - -#if BLD_DEBUG - #include <crtdbg.h> -#endif - #include "mprUnix.h" -#endif /* WIN */ - -#if BREW - #if BLD_FEATURE_FLOATING_POINT - #warning "Floating point is not supported on Brew" - #endif - #if BLD_FEATURE_MULTITHREAD - #warning "Multithreading is not supported on Brew" - #endif - - #include "AEEModGen.h" - #include "AEEAppGen.h" - #include "BREWVersion.h" - - #if BREW_MAJ_VER == 2 - /* - * Fix for BREW 2.X - */ - #ifdef __GNUC__ - #define __inline extern __inline__ - #endif - #include "AEENet.h" - #undef __inline - #endif - - #include "AEE.h" - #include "AEEBitmap.h" - #include "AEEDisp.h" - #include "AEEFile.h" - #include "AEEHeap.h" - #include "AEEImageCtl.h" - #include "AEEMedia.h" - #include "AEEMediaUtil.h" - #include "AEEMimeTypes.h" - #include "AEEStdLib.h" - #include "AEEShell.h" - #include "AEESoundPlayer.h" - #include "AEEText.h" - #include "AEETransform.h" - #include "AEEWeb.h" - #if BREW_MAJ_VER >= 3 - #include "AEESMS.h" - #endif - #include "AEETAPI.h" - -#if 0 - #include "AEESound.h" - #include "AEEDb.h" - #include "AEEMenu.h" -#endif - -#endif /* BREW */ - -/******************************************************************************/ -/******************************* General Defines ******************************/ -/******************************************************************************/ - -#ifndef MAXINT -#if INT_MAX - #define MAXINT INT_MAX -#else - #define MAXINT 0x7fffffff -#endif -#endif - -#ifndef BITSPERBYTE -#define BITSPERBYTE (8 * sizeof(char)) -#endif - -#define BITS(type) (BITSPERBYTE * (int) sizeof(type)) - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -#ifndef min -#define min(a,b) (((a) < (b)) ? (a) : (b)) -#endif - -#define MPR_ARRAY_SIZE(type) (sizeof(type) / sizeof(type[0])) - -#ifndef PRINTF_ATTRIBUTE -#if (__GNUC__ >= 3) && !DOXYGEN && BLD_FEATURE_ALLOC_LEAK_TRACK -/** Use gcc attribute to check printf fns. a1 is the 1-based index of - * the parameter containing the format, and a2 the index of the first - * argument. Note that some gcc 2.x versions don't handle this - * properly **/ -#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2))) -#else -#define PRINTF_ATTRIBUTE(a1, a2) -#endif -#endif - -typedef char *MprStr; /* Used for dynamic strings */ - -#ifdef __cplusplus -extern "C" { -#else -typedef int bool; -#endif - -/******************************************************************************/ -/******************************** Linux Defines *******************************/ -/******************************************************************************/ - -#if LINUX - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; - #define INT64(x) (x##LL) - #define UINT64(x) (x##ULL) -#endif - - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - -/* - * For some reason it is removed from fedora pthreads.h and only - * comes in for UNIX96 - */ -extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict - __attr, int *__restrict __kind) __THROW; -/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL, - PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or - PTHREAD_MUTEX_DEFAULT). */ -extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind) - __THROW; - -#endif /* LINUX */ - -/******************************************************************************/ -/******************************* VxWorks Defines ******************************/ -/******************************************************************************/ - -#if VXWORKS - - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - - #define HAVE_SOCKLEN_T - typedef int socklen_t; - -#if BLD_FEATURE_INT64 - typedef long long int int64; - typedef unsigned long long int uint64; - #define INT64(x) (x##LL) - #define UINT64(x) (x##ULL) -#endif - - #define closesocket(x) close(x) - #define getpid() taskIdSelf() - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT FLT_MAX -#endif - - #undef R_OK - #define R_OK 4 - #undef W_OK - #define W_OK 2 - #undef X_OK - #define X_OK 1 - #undef F_OK - #define F_OK 0 - - #define MSG_NOSIGNAL 0 - - extern int access(char *path, int mode); - extern int sysClkRateGet(); - -#endif /* VXWORKS */ - -/******************************************************************************/ -/******************************** MacOsx Defines ******************************/ -/******************************************************************************/ -#if MACOSX - typedef unsigned long ulong; - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - __extension__ typedef long long int int64; - __extension__ typedef unsigned long long int uint64; - #define INT64(x) (x##LL) - #define UINT64(x) (x##ULL) -#endif - - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".dylib" - #define MSG_NOSIGNAL 0 - #define __WALL 0x40000000 - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - -#endif /* MACOSX */ - -/******************************************************************************/ -/******************************* Windows Defines ******************************/ -/******************************************************************************/ - -#if WIN - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - typedef unsigned short ushort; - -/* - * We always define INT64 types on windows - */ -#if BLD_FEATURE_INT64 || 1 - typedef __int64 int64; - typedef unsigned __int64 uint64; - #define INT64(x) (x##i64) - #define UINT64(x) (x##Ui64) -#endif - - typedef int uid_t; - typedef void *handle; - typedef char *caddr_t; - typedef long pid_t; - typedef int gid_t; - typedef ushort mode_t; - typedef void *siginfo_t; - - #define HAVE_SOCKLEN_T - typedef int socklen_t; - - #undef R_OK - #define R_OK 4 - #undef W_OK - #define W_OK 2 - - /* - * On windows map X_OK to R_OK - */ - #undef X_OK - #define X_OK 4 - #undef F_OK - #define F_OK 0 - - #ifndef EADDRINUSE - #define EADDRINUSE 46 - #endif - #ifndef EWOULDBLOCK - #define EWOULDBLOCK EAGAIN - #endif - #ifndef ENETDOWN - #define ENETDOWN 43 - #endif - #ifndef ECONNRESET - #define ECONNRESET 44 - #endif - #ifndef ECONNREFUSED - #define ECONNREFUSED 45 - #endif - - #define MSG_NOSIGNAL 0 - #define MPR_BINARY "b" - #define MPR_TEXT "t" - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT DBL_MAX -#endif - -#ifndef FILE_FLAG_FIRST_PIPE_INSTANCE -#define FILE_FLAG_FIRST_PIPE_INSTANCE 0x00080000 -#endif - - #define MPR_DLL_EXT ".dll" -#endif /* WIN */ - -/******************************************************************************/ -/****************************** Solaris Defines *******************************/ -/******************************************************************************/ - -#if SOLARIS - typedef unsigned char uchar; - -#if BLD_FEATURE_INT64 - typedef long long int int64; - typedef unsigned long long int uint64; - #define INT64(x) (x##LL) - #define UINT64(x) (x##ULL) -#endif - - #define closesocket(x) close(x) - #define MPR_BINARY "" - #define MPR_TEXT "" - #define O_BINARY 0 - #define O_TEXT 0 - #define SOCKET_ERROR -1 - #define MPR_DLL_EXT ".so" - #define MSG_NOSIGNAL 0 - #define INADDR_NONE ((in_addr_t) 0xffffffff) - #define __WALL 0 - #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE - -#if BLD_FEATURE_FLOATING_POINT - #define MAX_FLOAT MAXFLOAT -#endif - -#endif /* SOLARIS */ - -/******************************************************************************/ -/********************************* BREW Defines *******************************/ -/******************************************************************************/ - -#if BREW - typedef unsigned char uchar; - typedef unsigned int uint; - typedef unsigned long ulong; - typedef unsigned short ushort; - - typedef uint off_t; - typedef long pid_t; - -#if UNUSED - typedef int uid_t; - typedef void *handle; - typedef char *caddr_t; - typedef int gid_t; - typedef ushort mode_t; - typedef void *siginfo_t; - - #define HAVE_SOCKLEN_T - typedef int socklen_t; - - #ifndef EADDRINUSE - #define EADDRINUSE 46 - #endif - #ifndef EWOULDBLOCK - #define EWOULDBLOCK EAGAIN - #endif - #ifndef ENETDOWN - #define ENETDOWN 43 - #endif - #ifndef ECONNRESET - #define ECONNRESET 44 - #endif - #ifndef ECONNREFUSED - #define ECONNREFUSED 45 - #endif - - #define MSG_NOSIGNAL 0 - #define MPR_BINARY "b" - #define MPR_TEXT "t" - - #define MPR_DLL_EXT ".dll" -#endif - - #define O_RDONLY 0 - #define O_WRONLY 1 - #define O_RDWR 2 - #define O_CREAT 0x200 - #define O_TRUNC 0x400 - #define O_BINARY 0 - #define O_TEXT 0x20000 - #define O_EXCL 0x40000 - #define O_APPEND 0x80000 - - #define R_OK 4 - #define W_OK 2 - #define X_OK 1 - #define F_OK 0 - - #define SEEK_SET 0 - #define SEEK_CUR 1 - #define SEEK_END 2 - -#if UNUSED -struct stat { - uint st_size; -}; -#endif - -extern int getpid(); -extern int isalnum(int c); -extern int isalpha(int c); -extern int isdigit(int c); -extern int islower(int c); -extern int isupper(int c); -extern int isspace(int c); -extern int isxdigit(int c); - -extern uint strlen(const char *str); -extern char *strstr(const char *string, const char *strSet); -extern void *memset(const void *dest, int c, uint count); -extern void exit(int status); -extern char *strpbrk(const char *str, const char *set); -extern uint strspn(const char *str, const char *set); -extern int tolower(int c); -extern int toupper(int c); -extern void *memcpy(void *dest, const void *src, uint count); -extern void *memmove(void *dest, const void *src, uint count); - -extern int atoi(const char *str); -extern void free(void *ptr); -extern void *malloc(uint size); -extern void *realloc(void *ptr, uint size); -extern char *strcat(char *dest, const char *src); -extern char *strchr(const char *str, int c); -extern int strcmp(const char *s1, const char *s2); -extern int strncmp(const char *s1, const char *s2, uint count); -extern char *strcpy(char *dest, const char *src); -extern char *strncpy(char *dest, const char *src, uint count); -extern char *strrchr(const char *str, int c); - -#undef printf -#define printf DBGPRINTF - -#if BREW_SIMULATOR && BLD_DEBUG -extern _CRTIMP int __cdecl _CrtCheckMemory(void); -extern _CRTIMP int __cdecl _CrtSetReportHook(); -#endif - -#endif /* BREW */ - -/******************************************************************************/ -#ifdef __cplusplus -} -#endif - -#endif /* _h_MPR_OS_HDRS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c b/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c deleted file mode 100644 index 2d0951acfa..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprPrintf.c +++ /dev/null @@ -1,924 +0,0 @@ -/** - * @file mprPrintf.c - * @brief Printf routines safe for embedded programming - * @overview This module provides safe replacements for the standard - * printf formatting routines. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -#include "mpr.h" - -/*********************************** Defines **********************************/ -/* - * Class definitions - */ -#define CLASS_NORMAL 0 /* [All other] Normal characters */ -#define CLASS_PERCENT 1 /* [%] Begin format */ -#define CLASS_MODIFIER 2 /* [-+ #,] Modifiers */ -#define CLASS_ZERO 3 /* [0] Special modifier */ -#define CLASS_STAR 4 /* [*] Width supplied by arg */ -#define CLASS_DIGIT 5 /* [1-9] Field widths */ -#define CLASS_DOT 6 /* [.] Introduce precision */ -#define CLASS_BITS 7 /* [hlL] Length bits */ -#define CLASS_TYPE 8 /* [cdfinopsSuxX] Type specifiers */ - -#define STATE_NORMAL 0 /* Normal chars in format string */ -#define STATE_PERCENT 1 /* "%" */ -#define STATE_MODIFIER 2 /* Read flag */ -#define STATE_WIDTH 3 /* Width spec */ -#define STATE_DOT 4 /* "." */ -#define STATE_PRECISION 5 /* Precision spec */ -#define STATE_BITS 6 /* Size spec */ -#define STATE_TYPE 7 /* Data type */ -#define STATE_COUNT 8 - -/* - * Format: %[modifier][width][precision][bits][type] - * - * #define CLASS_MODIFIER 2 [-+ #,] Modifiers - * #define CLASS_BITS 7 [hlL] Length bits - */ - - -/* - * Flags - */ -#define SPRINTF_LEFT 0x1 /* Left align */ -#define SPRINTF_SIGN 0x2 /* Always sign the result */ -#define SPRINTF_LEAD_SPACE 0x4 /* put leading space for +ve numbers */ -#define SPRINTF_ALTERNATE 0x8 /* Alternate format */ -#define SPRINTF_LEAD_ZERO 0x10 /* Zero pad */ -#define SPRINTF_SHORT 0x20 /* 16-bit */ -#define SPRINTF_LONG 0x40 /* 32-bit */ -#if BLD_FEATURE_INT64 -#define SPRINTF_LONGLONG 0x80 /* 64-bit */ -#endif -#define SPRINTF_COMMA 0x100 /* Thousand comma separators */ -#define SPRINTF_UPPER_CASE 0x200 /* As the name says for numbers */ - -typedef struct Format { - uchar *buf; - uchar *endbuf; - uchar *start; - uchar *end; - int growBy; - int maxsize; - - int precision; - int radix; - int width; - int flags; - int len; -} Format; - -static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt); - -#define BPUT(ctx, loc, fmt, c) \ - if (1) { \ - /* Less one to allow room for the null */ \ - if ((fmt)->end >= ((fmt)->endbuf - sizeof(char))) { \ - if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \ - *(fmt)->end++ = (c); \ - } \ - } else { \ - *(fmt)->end++ = (c); \ - } \ - } else - -#define BPUTNULL(ctx, loc, fmt) \ - if (1) { \ - if ((fmt)->end > (fmt)->endbuf) { \ - if (growBuf(MPR_LOC_PASS(ctx, loc), fmt)) { \ - *(fmt)->end = '\0'; \ - } \ - } else { \ - *(fmt)->end = '\0'; \ - } \ - } else - -/******************************************************************************/ - -#if BLD_FEATURE_INT64 -#define unum uint64 -#define num int64 -#else -#define unum uint -#define num int -#endif - -/***************************** Forward Declarations ***************************/ -#ifdef __cplusplus -extern "C" { -#endif - -static int getState(char c, int state); -static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **s, - int maxsize, const char *fmt, va_list arg); -static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix, - unum val); - -#if BLD_FEATURE_FLOATING_POINT -static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar, - double value); -#endif - -/******************************************************************************/ - -int mprPrintf(MprCtx ctx, const char *fmt, ...) -{ - va_list ap; - char *buf; - int len; - MprApp *app; - - /* No asserts here as this is used as part of assert reporting */ - - app = mprGetApp(ctx); - - va_start(ap, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap); - va_end(ap); - if (len >= 0 && app->console) { - len = mprWrite(app->console, buf, len); - } - mprFree(buf); - - return len; -} - -/******************************************************************************/ - -int mprErrorPrintf(MprCtx ctx, const char *fmt, ...) -{ - va_list ap; - char *buf; - int len; - MprApp *app; - - /* No asserts here as this is used as part of assert reporting */ - - app = mprGetApp(ctx); - - va_start(ap, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(ctx), &buf, 0, fmt, ap); - va_end(ap); - if (len >= 0 && app->error) { - len = mprWrite(app->error, buf, len); - } - mprFree(buf); - - return len; -} - -/******************************************************************************/ - -int mprFprintf(MprFile *file, const char *fmt, ...) -{ - va_list ap; - char *buf; - int len; - - if (file == 0) { - return MPR_ERR_BAD_HANDLE; - } - - va_start(ap, fmt); - len = mprAllocVsprintf(MPR_LOC_ARGS(file), &buf, 0, fmt, ap); - va_end(ap); - - if (len >= 0) { - len = mprWrite(file, buf, len); - } - mprFree(buf); - return len; -} - -/******************************************************************************/ -/* - * Printf with a static buffer. Used internally only. WILL NOT MALLOC. - */ - -int mprStaticPrintf(MprCtx ctx, const char *fmt, ...) -{ - va_list ap; - char buf[MPR_MAX_STRING]; - char *bufp; - int len; - MprApp *app; - - app = mprGetApp(ctx); - - va_start(ap, fmt); - bufp = buf; - len = mprSprintfCore(MPR_LOC_ARGS(0), &bufp, MPR_MAX_STRING, fmt, ap); - va_end(ap); - if (len >= 0) { - len = mprWrite(app->console, buf, len); - } - return len; -} - -/******************************************************************************/ - -int mprSprintf(char *buf, int n, const char *fmt, ...) -{ - va_list ap; - int result; - - mprAssert(buf); - mprAssert(fmt); - mprAssert(n > 0); - - va_start(ap, fmt); - result = mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, ap); - va_end(ap); - return result; -} - -/******************************************************************************/ - -int mprVsprintf(char *buf, int n, const char *fmt, va_list arg) -{ - mprAssert(buf); - mprAssert(fmt); - mprAssert(n > 0); - - return mprSprintfCore(MPR_LOC_ARGS(0), &buf, n, fmt, arg); -} - -/******************************************************************************/ - -int mprAllocSprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, - const char *fmt, ...) -{ - va_list ap; - int result; - - mprAssert(buf); - mprAssert(fmt); - - *buf = 0; - va_start(ap, fmt); - result = mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, ap); - va_end(ap); - return result; -} - -/******************************************************************************/ - -int mprAllocVsprintf(MPR_LOC_DEC(ctx, loc), char **buf, int maxSize, - const char *fmt, va_list arg) -{ - mprAssert(buf); - mprAssert(fmt); - - *buf = 0; - return mprSprintfCore(MPR_LOC_PASS(ctx, loc), buf, maxSize, fmt, arg); -} - -/******************************************************************************/ - -static int getState(char c, int state) -{ - /* - * Declared here to remove all static / globals - * FUTURE OPT -- need to measure this. Could be slow on BREW. - */ - - char stateMap[] = { - /* STATES: Normal Percent Modifier Width Dot Prec Bits Type */ - /* CLASS 0 1 2 3 4 5 6 7 */ - /* Normal 0 */ 0, 0, 0, 0, 0, 0, 0, 0, - /* Percent 1 */ 1, 0, 1, 1, 1, 1, 1, 1, - /* Modifier 2 */ 0, 2, 2, 0, 0, 0, 0, 0, - /* Zero 3 */ 0, 2, 2, 3, 0, 5, 0, 0, - /* Star 4 */ 0, 3, 3, 0, 5, 0, 0, 0, - /* Digit 5 */ 0, 3, 3, 3, 5, 5, 0, 0, - /* Dot 6 */ 0, 4, 4, 4, 0, 0, 0, 0, - /* Bits 7 */ 0, 6, 6, 6, 6, 6, 6, 0, - /* Types 8 */ 0, 7, 7, 7, 7, 7, 7, 0, - }; - - /* - * Format: %[modifier][width][precision][bits][type] - */ - char classMap[] = { - /* 0 ' ' ! " # $ % & ' */ - 2, 0, 0, 2, 0, 1, 0, 0, - /* 07 ( ) * + , - . / */ - 0, 0, 4, 2, 2, 2, 6, 0, - /* 10 0 1 2 3 4 5 6 7 */ - 3, 5, 5, 5, 5, 5, 5, 5, - /* 17 8 9 : ; < = > ? */ - 5, 5, 0, 0, 0, 0, 0, 0, - /* 20 @ A B C D E F G */ - 0, 0, 0, 0, 0, 0, 0, 0, - /* 27 H I J K L M N O */ - 0, 0, 0, 0, 7, 0, 0, 0, - /* 30 P Q R S T U V W */ - 0, 0, 0, 8, 0, 0, 0, 0, - /* 37 X Y Z [ \ ] ^ _ */ - 8, 0, 0, 0, 0, 0, 0, 0, - /* 40 ' a b c d e f g */ - 0, 0, 0, 8, 8, 0, 8, 0, - /* 47 h i j k l m n o */ - 7, 8, 0, 0, 7, 0, 8, 8, - /* 50 p q r s t u v w */ - 8, 0, 0, 8, 0, 8, 0, 0, - /* 57 x y z */ - 8, 0, 0, - }; - - int chrClass; - - if (c < ' ' || c > 'z') { - chrClass = CLASS_NORMAL; - } else { - mprAssert((c - ' ') < (int) sizeof(classMap)); - chrClass = classMap[(c - ' ')]; - } - mprAssert((chrClass * STATE_COUNT + state) < (int) sizeof(stateMap)); - state = stateMap[chrClass * STATE_COUNT + state]; - return state; -} - -/******************************************************************************/ - -static int mprSprintfCore(MPR_LOC_DEC(ctx, loc), char **bufPtr, - int maxsize, const char *spec, va_list arg) -{ - Format fmt; - char *cp; - char c; - char *sValue; - num iValue; - unum uValue; - int count, i, len, state; - - mprAssert(bufPtr); - mprAssert(spec); - - if (*bufPtr != 0) { - mprAssert(maxsize > 0); - fmt.buf = (uchar*) *bufPtr; - fmt.endbuf = &fmt.buf[maxsize]; - fmt.growBy = 0; - } else { - if (maxsize <= 0) { - maxsize = MAXINT; - } - - len = min(MPR_DEFAULT_ALLOC, maxsize); - fmt.buf = (uchar*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); - fmt.endbuf = &fmt.buf[len]; - fmt.growBy = MPR_DEFAULT_ALLOC * 2; - } - - fmt.maxsize = maxsize; - fmt.start = fmt.buf; - fmt.end = fmt.buf; - fmt.len = 0; - *fmt.start = '\0'; - - state = STATE_NORMAL; - - while ((c = *spec++) != '\0') { - state = getState(c, state); - - switch (state) { - case STATE_NORMAL: - BPUT(ctx, loc, &fmt, c); - break; - - case STATE_PERCENT: - fmt.precision = -1; - fmt.width = 0; - fmt.flags = 0; - break; - - case STATE_MODIFIER: - switch (c) { - case '+': - fmt.flags |= SPRINTF_SIGN; - break; - case '-': - fmt.flags |= SPRINTF_LEFT; - break; - case '#': - fmt.flags |= SPRINTF_ALTERNATE; - break; - case '0': - fmt.flags |= SPRINTF_LEAD_ZERO; - break; - case ' ': - fmt.flags |= SPRINTF_LEAD_SPACE; - break; - case ',': - fmt.flags |= SPRINTF_COMMA; - break; - } - break; - - case STATE_WIDTH: - if (c == '*') { - fmt.width = va_arg(arg, int); - if (fmt.width < 0) { - fmt.width = -fmt.width; - fmt.flags |= SPRINTF_LEFT; - } - } else { - while (isdigit((int)c)) { - fmt.width = fmt.width * 10 + (c - '0'); - c = *spec++; - } - spec--; - } - break; - - case STATE_DOT: - fmt.precision = 0; - fmt.flags &= ~SPRINTF_LEAD_ZERO; - break; - - case STATE_PRECISION: - if (c == '*') { - fmt.precision = va_arg(arg, int); - } else { - while (isdigit((int) c)) { - fmt.precision = fmt.precision * 10 + (c - '0'); - c = *spec++; - } - spec--; - } - break; - - case STATE_BITS: - switch (c) { -#if BLD_FEATURE_INT64 - case 'L': - fmt.flags |= SPRINTF_LONGLONG; /* 64 bit */ - break; -#endif - - case 'l': - fmt.flags |= SPRINTF_LONG; - break; - - case 'h': - fmt.flags |= SPRINTF_SHORT; - break; - } - break; - - case STATE_TYPE: - switch (c) { -#if BLD_FEATURE_FLOATING_POINT - case 'e': - case 'g': - case 'f': - fmt.radix = 10; - outFloat(MPR_LOC_PASS(ctx, loc), &fmt, c, - (double) va_arg(arg, double)); - break; -#endif - case 'c': - BPUT(ctx, loc, &fmt, (char) va_arg(arg, int)); - break; - - case 's': - case 'S': - sValue = va_arg(arg, char*); - if (sValue == 0) { - sValue = "null"; - len = strlen(sValue); - } else if (fmt.flags & SPRINTF_ALTERNATE) { - sValue++; - len = (int) *sValue; - } else if (fmt.precision >= 0) { - /* - * Can't use strlen(), the string may not have a null - */ - cp = sValue; - for (len = 0; len < fmt.precision; len++) { - if (*cp++ == '\0') { - break; - } - } - } else { - len = strlen(sValue); - } - if (!(fmt.flags & SPRINTF_LEFT)) { - for (i = len; i < fmt.width; i++) { - BPUT(ctx, loc, &fmt, (char) ' '); - } - } - for (i = 0; i < len && *sValue; i++) { - BPUT(ctx, loc, &fmt, *sValue++); - } - if (fmt.flags & SPRINTF_LEFT) { - for (i = len; i < fmt.width; i++) { - BPUT(ctx, loc, &fmt, (char) ' '); - } - } - break; - - case 'i': - ; - case 'd': - fmt.radix = 10; - if (fmt.flags & SPRINTF_SHORT) { - iValue = (short) va_arg(arg, int); - } else if (fmt.flags & SPRINTF_LONG) { - iValue = va_arg(arg, long); -#if BLD_FEATURE_INT64 - } else if (fmt.flags & SPRINTF_LONGLONG) { - iValue = va_arg(arg, num); -#endif - } else { - iValue = va_arg(arg, int); - } - if (iValue >= 0) { - if (fmt.flags & SPRINTF_LEAD_SPACE) { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, " ", iValue); - } else if (fmt.flags & SPRINTF_SIGN) { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "+", iValue); - } else { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, iValue); - } - } else { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "-", -iValue); - } - break; - - case 'X': - fmt.flags |= SPRINTF_UPPER_CASE; - /* Fall through */ - case 'o': - case 'x': - case 'u': - if (fmt.flags & SPRINTF_SHORT) { - uValue = (ushort) va_arg(arg, uint); - } else if (fmt.flags & SPRINTF_LONG) { - uValue = va_arg(arg, ulong); -#if BLD_FEATURE_INT64 - } else if (fmt.flags & SPRINTF_LONGLONG) { - uValue = va_arg(arg, unum); -#endif - } else { - uValue = va_arg(arg, uint); - } - if (c == 'u') { - fmt.radix = 10; - outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); - } else if (c == 'o') { - fmt.radix = 8; - if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0", uValue); - } else { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); - } - } else { - fmt.radix = 16; - if (fmt.flags & SPRINTF_ALTERNATE && uValue != 0) { - if (c == 'X') { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0X", uValue); - } else { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue); - } - } else { - outNum(MPR_LOC_PASS(ctx, loc), &fmt, 0, uValue); - } - } - break; - - case 'n': /* Count of chars seen thus far */ - if (fmt.flags & SPRINTF_SHORT) { - short *count = va_arg(arg, short*); - *count = fmt.end - fmt.start; - } else if (fmt.flags & SPRINTF_LONG) { - long *count = va_arg(arg, long*); - *count = fmt.end - fmt.start; - } else { - int *count = va_arg(arg, int *); - *count = fmt.end - fmt.start; - } - break; - - case 'p': /* Pointer */ -#if __WORDSIZE == 64 && BLD_FEATURE_INT64 - uValue = (unum) va_arg(arg, void*); -#else - uValue = (uint) (int) va_arg(arg, void*); -#endif - fmt.radix = 16; - outNum(MPR_LOC_PASS(ctx, loc), &fmt, "0x", uValue); - break; - - default: - BPUT(ctx, loc, &fmt, c); - } - } - } - BPUTNULL(ctx, loc, &fmt); - - count = fmt.end - fmt.start; - if (*bufPtr == 0) { - *bufPtr = (char*) fmt.buf; - } - return count; -} - -/******************************************************************************/ -/* - * Output a number according to the given format. If BLD_FEATURE_INT64 is - * defined, then uses 64 bits universally. Slower but smaller code. - */ - -static void outNum(MPR_LOC_DEC(ctx, loc), Format *fmt, const char *prefix, - unum value) -{ - char numBuf[64]; - char *cp; - char *endp; - char c; - int letter, len, leadingZeros, i, fill; - - endp = &numBuf[sizeof(numBuf) - 1]; - *endp = '\0'; - cp = endp; - - /* - * Convert to ascii - */ - if (fmt->radix == 16) { - do { - letter = (int) (value % fmt->radix); - if (letter > 9) { - if (fmt->flags & SPRINTF_UPPER_CASE) { - letter = 'A' + letter - 10; - } else { - letter = 'a' + letter - 10; - } - } else { - letter += '0'; - } - *--cp = letter; - value /= fmt->radix; - } while (value > 0); - - } else if (fmt->flags & SPRINTF_COMMA) { - i = 1; - do { - *--cp = '0' + (int) (value % fmt->radix); - value /= fmt->radix; - if ((i++ % 3) == 0 && value > 0) { - *--cp = ','; - } - } while (value > 0); - } else { - do { - *--cp = '0' + (int) (value % fmt->radix); - value /= fmt->radix; - } while (value > 0); - } - - len = endp - cp; - fill = fmt->width - len; - - if (prefix != 0) { - fill -= strlen(prefix); - } - leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0; - fill -= leadingZeros; - - if (!(fmt->flags & SPRINTF_LEFT)) { - c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' '; - for (i = 0; i < fill; i++) { - BPUT(ctx, loc, fmt, c); - } - } - if (prefix != 0) { - while (*prefix) { - BPUT(ctx, loc, fmt, *prefix++); - } - } - for (i = 0; i < leadingZeros; i++) { - BPUT(ctx, loc, fmt, '0'); - } - while (*cp) { - BPUT(ctx, loc, fmt, *cp); - cp++; - } - if (fmt->flags & SPRINTF_LEFT) { - for (i = 0; i < fill; i++) { - BPUT(ctx, loc, fmt, ' '); - } - } -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Output a floating point number - */ - -static void outFloat(MPR_LOC_DEC(ctx, loc), Format *fmt, char specChar, - double value) -{ - char *cp; -#if FUTURE - char numBuf[64]; - char *endp; - char c; - int letter, len, leadingZeros, i, fill, width, precision; - - endp = &numBuf[sizeof(numBuf) - 1]; - *endp = '\0'; - - precision = fmt->precision; - if (precision < 0) { - precision = 6; - } else if (precision > (sizeof(numBuf) - 1)) { - precision = (sizeof(numBuf) - 1); - } - width = min(fmt->width, sizeof(numBuf) - 1); - - if (__isnanl(value)) { - "nan" - } else if (__isinfl(value)) { - "infinity" - } else if (value < 0) { - prefix = "-"; - } else if (fmt.flags & SPRINTF_LEAD_SPACE) { - prefix = " "; - } else if (fmt.flags & SPRINTF_SIGN) { - prefix = "+"; - } - - - /* - * Do the exponent part - */ - cp = &numBuf[sizeof(numBuf) - precision]; - for (i = 0; i < precision; i++) { - *cp++ = '0' + (int) (value % fmt->radix); - value /= fmt->radix; - } - - /* - * Do the decimal part - */ - if (fmt->flags & SPRINTF_COMMA) { - i = 1; - do { - *--cp = '0' + (int) (value % fmt->radix); - value /= fmt->radix; - if ((i++ % 3) == 0 && value > 0) { - *--cp = ','; - } - } while (value >= 1.0); - - } else { - do { - *--cp = '0' + (int) (value % fmt->radix); - value /= fmt->radix; - } while (value > 1.0); - } - - len = endp - cp; - fill = fmt->width - len; - - if (prefix != 0) { - fill -= strlen(prefix); - } - - leadingZeros = (fmt->precision > len) ? fmt->precision - len : 0; - fill -= leadingZeros; - - if (!(fmt->flags & SPRINTF_LEFT)) { - c = (fmt->flags & SPRINTF_LEAD_ZERO) ? '0': ' '; - for (i = 0; i < fill; i++) { - BPUT(ctx, loc, fmt, c); - } - } - if (prefix != 0) { - BPUT(ctx, loc, fmt, prefix); - } - for (i = 0; i < leadingZeros; i++) { - BPUT(ctx, loc, fmt, '0'); - } - BPUT(ctx, loc, fmt, cp); - if (fmt->flags & SPRINTF_LEFT) { - for (i = 0; i < fill; i++) { - BPUT(ctx, loc, fmt, ' '); - } - } -#else - char numBuf[64]; - if (specChar == 'f') { - sprintf(numBuf, "%*.*f", fmt->width, fmt->precision, value); - } else if (specChar == 'g') { - sprintf(numBuf, "%*.*g", fmt->width, fmt->precision, value); - } else if (specChar == 'e') { - sprintf(numBuf, "%*.*e", fmt->width, fmt->precision, value); - } - for (cp = numBuf; *cp; cp++) { - BPUT(ctx, loc, fmt, *cp); - } -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ -/* - * Grow the buffer to fit new data. Return 1 if the buffer can grow. - * Grow using the growBy size specified when creating the buffer. - */ - -static int growBuf(MPR_LOC_DEC(ctx, loc), Format *fmt) -{ - uchar *newbuf; - int buflen; - - buflen = fmt->endbuf - fmt->buf; - if (fmt->maxsize >= 0 && buflen >= fmt->maxsize) { - return 0; - } - if (fmt->growBy < 0) { - /* - * User supplied buffer - */ - return 0; - } - - newbuf = (uchar*) mprAlloc(ctx, buflen + fmt->growBy); - if (fmt->buf) { - memcpy(newbuf, fmt->buf, buflen); - mprFree(fmt->buf); - } - - buflen += fmt->growBy; - fmt->end = newbuf + (fmt->end - fmt->buf); - fmt->start = newbuf + (fmt->start - fmt->buf); - fmt->buf = newbuf; - fmt->endbuf = &fmt->buf[buflen]; - - /* - * Increase growBy to reduce overhead - */ - if ((buflen + (fmt->growBy * 2)) < fmt->maxsize) { - fmt->growBy *= 2; - } - return 1; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprString.c b/source4/lib/appweb/ejs-2.0/mpr/mprString.c deleted file mode 100644 index d39fc8b746..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprString.c +++ /dev/null @@ -1,733 +0,0 @@ -/** - * @file mprString.c - * @brief String routines safe for embedded programming - * @overview This module provides safe replacements for the standard - * string library. - * @remarks Most routines in this file are not thread-safe. It is the callers - * responsibility to perform all thread synchronization. - */ - -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "mpr.h" - -/********************************** Includes **********************************/ -/* - * We need to use the underlying str(cpy) routines to implement our safe - * alternatives - */ -#if !DOXYGEN -#define UNSAFE_FUNCTIONS_OK 1 -#endif - -/******************************************************************************/ -/**************************** Safe String Handling ****************************/ -/******************************************************************************/ - -int mprStrcpy(char *dest, int destMax, const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax >= 0); - mprAssert(src); - - len = strlen(src); - if (destMax > 0 && len >= destMax && len > 0) { - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - memcpy(dest, src, len); - dest[len] = '\0'; - } else { - *dest = '\0'; - len = 0; - } - return len; -} - -/******************************************************************************/ - -int mprAllocStrcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax, - const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax >= 0); - mprAssert(src); - - len = strlen(src); - if (destMax > 0 && len >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - *dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), len); - memcpy(*dest, src, len); - (*dest)[len] = '\0'; - } else { - *dest = (char*) mprAlloc(ctx, 1); - *dest = '\0'; - len = 0; - } - return len; -} - -/******************************************************************************/ - -int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) -{ - mprAssert(dest); - mprAssert(destMax <= 0 || destMax >= nbytes); - mprAssert(src); - mprAssert(nbytes >= 0); - - if (destMax > 0 && nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - memcpy(dest, src, nbytes); - return nbytes; - } else { - return 0; - } -} - -/******************************************************************************/ - -int mprAllocMemcpy(MPR_LOC_DEC(ctx, loc), char **dest, int destMax, - const void *src, int nbytes) -{ - mprAssert(dest); - mprAssert(src); - mprAssert(nbytes > 0); - mprAssert(destMax <= 0 || destMax >= nbytes); - - if (destMax > 0 && nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - *dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx,loc), nbytes); - if (*dest == 0) { - return MPR_ERR_MEMORY; - } - memcpy(*dest, src, nbytes); - } else { - *dest = (char*) mprAlloc(ctx, 1); - } - return nbytes; -} - -/******************************************************************************/ - -static int mprCoreStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax, - int existingLen, const char *delim, const char *src, va_list args) -{ - va_list ap; - char *dest, *str, *dp; - int sepLen, addBytes, required; - - mprAssert(destp); - mprAssert(destMax >= 0); - mprAssert(src); - - dest = *destp; - sepLen = (delim) ? strlen(delim) : 0; - -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - addBytes = 0; - if (existingLen > 0) { - addBytes += sepLen; - } - str = (char*) src; - - while (str) { - addBytes += strlen(str); - str = va_arg(ap, char*); - if (str) { - addBytes += sepLen; - } - } - - required = existingLen + addBytes + 1; - if (destMax > 0 && required >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - - if (ctx != 0) { - if (dest == 0) { - dest = (char*) mprAllocBlock(MPR_LOC_PASS(ctx, loc), required); - } else { - dest = (char*) mprReallocBlock(MPR_LOC_PASS(ctx, loc), dest, - required); - } - } else { - dest = (char*) *destp; - } - - dp = &dest[existingLen]; - if (delim && existingLen > 0) { - strcpy(dp, delim); - dp += sepLen; - } - - if (addBytes > 0) { -#ifdef __va_copy - __va_copy(ap, args); -#else - ap = args; -#endif - str = (char*) src; - while (str) { - strcpy(dp, str); - dp += strlen(str); - str = va_arg(ap, char*); - if (delim && str) { - strcpy(dp, delim); - dp += sepLen; - } - } - } else if (dest == 0) { - dest = (char*) mprAlloc(ctx, 1); - } - *dp = '\0'; - - *destp = dest; - mprAssert(dp < &dest[required]); - return required - 1; -} - -/***************************************************************************** - Note that this VARARGS function must be NULL (not 0, this must be a - pointer) terminated -*/ -int mprStrcat(char *dest, int destMax, const char *delim, const char *src, ...) -{ - va_list ap; - int rc; - - mprAssert(dest); - mprAssert(src); - - va_start(ap, src); - rc = mprCoreStrcat(MPR_LOC_ARGS(0), &dest, destMax, strlen(dest), - delim, src, ap); - va_end(ap); - return rc; -} - -/***************************************************************************** - Note that this VARARGS function must be NULL (not 0, this must be a - pointer) terminated -*/ -int mprAllocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax, - const char *delim, const char *src, ...) -{ - va_list ap; - int rc; - - mprAssert(destp); - mprAssert(src); - - *destp = 0; - va_start(ap, src); - rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, 0, delim, - src, ap); - va_end(ap); - return rc; -} - -/***************************************************************************** - Note that this VARARGS function must be NULL (not 0, this must be a - pointer) terminated -*/ -int mprReallocStrcat(MPR_LOC_DEC(ctx, loc), char **destp, int destMax, - int existingLen, const char *delim, const char *src,...) -{ - va_list ap; - int rc; - - va_start(ap, src); - rc = mprCoreStrcat(MPR_LOC_PASS(ctx, loc), destp, destMax, existingLen, - delim, src, ap); - va_end(ap); - return rc; -} - -/******************************************************************************/ - -int mprStrlen(const char *src, int max) -{ - int len; - - len = strlen(src); - if (len >= max) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - return len; -} - -/******************************************************************************/ - -char *mprStrTrim(char *str, const char *set) -{ - int len, i; - - if (str == 0 || set == 0) { - return str; - } - - i = strspn(str, set); - str += i; - - len = strlen(str); - while (strspn(&str[len - 1], set) > 0) { - str[len - 1] = '\0'; - len--; - } - return str; -} - -/******************************************************************************/ -/* - * Map a string to lower case (overwrites original string) - */ - -char *mprStrLower(char *str) -{ - char *cp; - - mprAssert(str); - - if (str == 0) { - return 0; - } - - for (cp = str; *cp; cp++) { - if (isupper(*cp)) { - *cp = (char) tolower(*cp); - } - } - return str; -} - -/******************************************************************************/ -/* - * Map a string to upper case (overwrites buffer) - */ - -char *mprStrUpper(char *str) -{ - char *cp; - - mprAssert(str); - if (str == 0) { - return 0; - } - - for (cp = str; *cp; cp++) { - if (islower(*cp)) { - *cp = (char) toupper(*cp); - } - } - return str; -} - -/******************************************************************************/ -/* - * Case insensitive string comparison. Stop at the end of str1. - */ - -int mprStrcmpAnyCase(const char *str1, const char *str2) -{ - int rc; - - if (str1 == 0 || str2 == 0) { - return -1; - } - if (str1 == str2) { - return 0; - } - - for (rc = 0; *str1 && rc == 0; str1++, str2++) { - rc = tolower(*str1) - tolower(*str2); - } - if (*str2) { - return -1; - } - return rc; -} - -/******************************************************************************/ -/* - * Case insensitive string comparison. Limited by length - */ - -int mprStrcmpAnyCaseCount(const char *str1, const char *str2, int len) -{ - int rc; - - if (str1 == 0 || str2 == 0) { - return -1; - } - if (str1 == str2) { - return 0; - } - - for (rc = 0; len-- > 0 && *str1 && rc == 0; str1++, str2++) { - rc = tolower(*str1) - tolower(*str2); - } - return rc; -} - -/******************************************************************************/ -/* - * Return the last portion of a pathname - */ - -const char *mprGetBaseName(const char *name) -{ - char *cp; - - cp = strrchr(name, '/'); - - if (cp == 0) { - cp = strrchr(name, '\\'); - if (cp == 0) { - return name; - } - } - if (cp == name) { - if (cp[1] == '\0') { - return name; - } - } else { - if (cp[1] == '\0') { - return ""; - } - } - return &cp[1]; -} - -/******************************************************************************/ -/* - * Return the directory portion of a pathname into the users buffer. - */ - -char *mprGetDirName(char *buf, int bufsize, const char *path) -{ - char *cp; - int dlen; - - mprAssert(path); - mprAssert(buf); - mprAssert(bufsize > 0); - - cp = strrchr(path, '/'); - if (cp == 0) { -#if WIN - cp = strrchr(path, '\\'); - if (cp == 0) -#endif - { - buf[0] = '\0'; - return buf; - } - } - - if (cp == path && cp[1] == '\0') { - strcpy(buf, "."); - return buf; - } - - dlen = cp - path; - if (dlen < bufsize) { - if (dlen == 0) { - dlen++; - } - mprMemcpy(buf, bufsize, path, dlen); - buf[dlen] = '\0'; - return buf; - } - return 0; -} - -/******************************************************************************/ -/* - * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() - */ - -char *mprStrTok(char *str, const char *delim, char **last) -{ - char *start, *end; - int i; - - start = str ? str : *last; - - if (start == 0) { - return 0; - } - - i = strspn(start, delim); - start += i; - if (*start == '\0') { - *last = 0; - return 0; - } - end = strpbrk(start, delim); - if (end) { - *end++ = '\0'; - i = strspn(end, delim); - end += i; - } - *last = end; - return start; -} - -/******************************************************************************/ -/* - * Split the buffer into word tokens - */ - -char *mprGetWordTok(char *buf, int bufsize, const char *str, const char *delim, - const char **tok) -{ - const char *start, *end; - int i, len; - - start = str ? str : *tok; - - if (start == 0) { - return 0; - } - - i = strspn(start, delim); - start += i; - if (*start =='\0') { - *tok = 0; - return 0; - } - end = strpbrk(start, delim); - if (end) { - len = min(end - start, bufsize - 1); - mprMemcpy(buf, bufsize, start, len); - buf[len] = '\0'; - } else { - if (mprStrcpy(buf, bufsize, start) < 0) { - buf[bufsize - 1] = '\0'; - return 0; - } - buf[bufsize - 1] = '\0'; - } - *tok = end; - return buf; -} - -/******************************************************************************/ -/* - * Format a number as a string. - */ - -char *mprItoa(char *buf, int size, int value) -{ - char numBuf[16]; - char *cp, *dp, *endp; - int negative; - - cp = &numBuf[sizeof(numBuf)]; - *--cp = '\0'; - - if (value < 0) { - negative = 1; - value = -value; - size--; - } else { - negative = 0; - } - - do { - *--cp = '0' + (value % 10); - value /= 10; - } while (value > 0); - - if (negative) { - *--cp = '-'; - } - - dp = buf; - endp = &buf[size]; - while (dp < endp && *cp) { - *dp++ = *cp++; - } - *dp++ = '\0'; - return buf; -} - -/******************************************************************************/ -/* - * Parse an ascii number. Supports radix 10 or 16. - */ - -int mprAtoi(const char *str, int radix) -{ - int c, val, negative; - - mprAssert(radix == 10 || radix == 16); - - if (str == 0) { - return 0; - } - - val = 0; - if (radix == 10 && *str == '-') { - negative = 1; - str++; - } else { - negative = 0; - } - - if (radix == 10) { - while (*str && isdigit(*str)) { - val = (val * radix) + *str - '0'; - str++; - } - } else if (radix == 16) { - if (*str == '0' && tolower(str[1]) == 'x') { - str += 2; - } - while (*str) { - c = tolower(*str); - if (isdigit(c)) { - val = (val * radix) + c - '0'; - } else if (c >= 'a' && c <= 'f') { - val = (val * radix) + c - 'a' + 10; - } else { - break; - } - str++; - } - } - - return (negative) ? -val: val; -} - -/******************************************************************************/ -/* - * Make an argv array. Caller must free by calling mprFree(argv) to free - * everything. - */ - -int mprMakeArgv(MprCtx ctx, const char *program, const char *cmd, - char ***argvp, int *argcp) -{ - char *cp, **argv, *buf, *args; - int size, argc; - - /* - * Allocate one buffer for argv and the actual args themselves - */ - size = strlen(cmd) + 1; - - buf = (char*) mprAlloc(ctx, (MPR_MAX_ARGC * sizeof(char*)) + size); - if (buf == 0) { - return MPR_ERR_MEMORY; - } - - args = &buf[MPR_MAX_ARGC * sizeof(char*)]; - strcpy(args, cmd); - argv = (char**) buf; - - argc = 0; - if (program) { - argv[argc++] = (char*) mprStrdup(ctx, program); - } - - for (cp = args; cp && *cp != '\0'; argc++) { - if (argc >= MPR_MAX_ARGC) { - mprAssert(argc < MPR_MAX_ARGC); - mprFree(buf); - *argvp = 0; - if (argcp) { - *argcp = 0; - } - return MPR_ERR_TOO_MANY; - } - while (isspace(*cp)) { - cp++; - } - if (*cp == '\0') { - break; - } - if (*cp == '"') { - cp++; - argv[argc] = cp; - while ((*cp != '\0') && (*cp != '"')) { - cp++; - } - } else { - argv[argc] = cp; - while (*cp != '\0' && !isspace(*cp)) { - cp++; - } - } - if (*cp != '\0') { - *cp++ = '\0'; - } - } - argv[argc] = 0; - - if (argcp) { - *argcp = argc; - } - *argvp = argv; - - return argc; -} - -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c b/source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c deleted file mode 100644 index 11ac278db4..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprSymbol.c +++ /dev/null @@ -1,279 +0,0 @@ -/* - * @file mprSym.cpp - * @brief Fast hashing symbol table lookup module - * @overview This symbol table uses a fast key lookup mechanism. Keys are - * strings and the value entries are arbitrary pointers. The keys are - * hashed into a series of buckets which then have a chain of hash - * entries using the standard doubly linked list classes (List/Link). - * The chain in in collating sequence so search time through the chain - * is on average (N/hashSize)/2. - * @remarks This module is not thread-safe. It is the callers responsibility - * to perform all thread synchronization. - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http: *www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http: *www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "mpr.h" - -/**************************** Forward Declarations ****************************/ - -static int hashIndex(const char *key, int size); -static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp, - MprSymbolTable *table, const char *key); - -/*********************************** Code *************************************/ -/* - * Create a new symbol table of a given size. Caller should provide a size - * that is a prime number for the greatest efficiency. Caller should use - * mprFree to free the symbol table. - */ - -MprSymbolTable *mprCreateSymbolTable(MprCtx ctx, int hashSize) -{ - MprSymbolTable *table; - - table = mprAllocTypeZeroed(ctx, MprSymbolTable); - if (table == 0) { - return 0; - } - - if (hashSize < MPR_DEFAULT_HASH_SIZE) { - hashSize = MPR_DEFAULT_HASH_SIZE; - } - table->hashSize = hashSize; - - table->count = 0; - table->hashSize = hashSize; - table->buckets = mprAllocZeroedBlock(MPR_LOC_ARGS(table), - sizeof(MprSymbol*) * hashSize); - - if (table->buckets == 0) { - mprFree(table); - return 0; - } - - return table; -} - -/******************************************************************************/ -/* - * Insert an entry into the symbol table. If the entry already exists, update - * its value. Order of insertion is not preserved. - */ - -MprSymbol *mprInsertSymbol(MprSymbolTable *table, const char *key, void *ptr) -{ - MprSymbol *sp, *prevSp; - int index; - - sp = lookupInner(&index, &prevSp, table, key); - - if (sp != 0) { - /* - * Already exists. Just update the data. - */ - sp->data = ptr; - return sp; - } - - /* - * New entry - */ - sp = mprAllocTypeZeroed(table, MprSymbol); - if (sp == 0) { - return 0; - } - - sp->data = ptr; - sp->key = mprStrdup(sp, key); - sp->bucket = index; - - sp->next = table->buckets[index]; - table->buckets[index] = sp; - - table->count++; - return sp; -} - -/******************************************************************************/ -/* - * Remove an entry from the table - */ - -int mprRemoveSymbol(MprSymbolTable *table, const char *key) -{ - MprSymbol *sp, *prevSp; - int index; - - if ((sp = lookupInner(&index, &prevSp, table, key)) == 0) { - return MPR_ERR_NOT_FOUND; - } - - if (prevSp) { - prevSp->next = sp->next; - } else { - table->buckets[index] = sp->next; - } - table->count--; - - mprFree(sp); - return 0; -} - -/******************************************************************************/ -/* - * Lookup a key and return the hash entry - */ - -void *mprLookupSymbol(MprSymbolTable *table, const char *key) -{ - MprSymbol *sp; - - mprAssert(key); - - sp = lookupInner(0, 0, table, key); - if (sp == 0) { - return 0; - } - return sp->data; -} - -/******************************************************************************/ - -static MprSymbol *lookupInner(int *bucketIndex, MprSymbol **prevSp, - MprSymbolTable *table, const char *key) -{ - MprSymbol *sp, *prev; - int index, rc; - - mprAssert(key); - - index = hashIndex(key, table->hashSize); - if (bucketIndex) { - *bucketIndex = index; - } - - sp = table->buckets[index]; - prev = 0; - - while (sp) { - rc = strcmp(sp->key, key); - if (rc == 0) { - if (prevSp) { - *prevSp = prev; - } - return sp; - } - prev = sp; - mprAssert(sp != sp->next); - sp = sp->next; - } - return 0; -} - -/******************************************************************************/ - -int mprGetSymbolCount(MprSymbolTable *table) -{ - return table->count; -} - -/******************************************************************************/ -/* - * Return the first entry in the table. - */ - -MprSymbol *mprGetFirstSymTab(MprSymbolTable *table) -{ - MprSymbol *sp; - int i; - - mprAssert(table); - - for (i = 0; i < table->hashSize; i++) { - if ((sp = (MprSymbol*) table->buckets[i]) != 0) { - return sp; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Return the next entry in the table - */ - -MprSymbol *mprGetNextSymTab(MprSymbolTable *table, MprSymbol *last) -{ - MprSymbol *sp; - int i; - - mprAssert(table); - - if (last->next) { - return last->next; - } - - for (i = last->bucket + 1; i < table->hashSize; i++) { - if ((sp = (MprSymbol*) table->buckets[i]) != 0) { - return sp; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Hash the key to produce a hash index. - */ - -static int hashIndex(const char *key, int size) -{ - uint sum; - - sum = 0; - while (*key) { - sum += (sum * 33) + *key++; - } - - return sum % size; -} - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs-2.0/mpr/mprUnix.h b/source4/lib/appweb/ejs-2.0/mpr/mprUnix.h deleted file mode 100644 index fbbe29ae9c..0000000000 --- a/source4/lib/appweb/ejs-2.0/mpr/mprUnix.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * @file mprUnix.h - * @brief Make windows a bit more unix like - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2006. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This header is part of the Mbedthis Portable Runtime and aims to include - * all necessary O/S headers and to unify the constants and declarations - * required by Mbedthis products. It can be included by C or C++ programs. - */ - -/******************************************************************************/ - -#ifndef _h_MPR_UNIX -#define _h_MPR_UNIX 1 - -/******************************************************************************/ -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Define BLD_NO_POSIX_REMAP if these defines mess with your app - */ -#if WIN && !BLD_NO_POSIX_REMAP -/* - * MOB -- clashes with ATL - */ -#define access _access -#define close _close -#define fileno _fileno -#define fstat _fstat -#define getpid _getpid -#define open _open -#define putenv _putenv -#define read _read -#define stat _stat -#define umask _umask -#define unlink _unlink -#define write _write -#define strdup _strdup -#define lseek _lseek -#define getcwd _getcwd -#define chdir _chdir - -#define mkdir(a,b) _mkdir(a) -#define rmdir(a) _rmdir(a) - -#define R_OK 4 -#define W_OK 2 -#define MPR_TEXT "t" - -extern void srand48(long); -extern long lrand48(void); -extern long ulimit(int, ...); -extern long nap(long); -extern int getuid(void); -extern int geteuid(void); -#endif - - -/******************************************************************************/ -#ifdef __cplusplus -} -#endif - -#endif /* _h_MPR_UNIX */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/config.h b/source4/lib/appweb/ejs/config.h deleted file mode 100644 index 8c06d28147..0000000000 --- a/source4/lib/appweb/ejs/config.h +++ /dev/null @@ -1,141 +0,0 @@ -#define BLD_PRODUCT "Samba4" -#define BLD_NAME "Samba4 WEB Applications" -#define BLD_VERSION "4" -#define BLD_NUMBER "1" -#define BLD_TYPE "DEBUG" -#define BLD_DEFAULTS "normal" -#define BLD_PACKAGES "" -#define BLD_APPWEB_CONFIG "normal.conf" -#define BLD_APPWEB 0 -#define BLD_COMPANY "Mbedthis" -#define BLD_DEBUG 0 -#define BLD_DIRS "bootstrap include obj bin mpr ejs esp http doc appWeb appWebSamples images" -#define BLD_HTTP_PORT 7777 -#define BLD_LIB_VERSION "1.0.0" -#define BLD_SSL_PORT 4443 -#define BLD_CLEAN_INSTALL "0" -#define BLD_LICENSE "gpl" -#define BLD_HOST_SYSTEM "i686-pc-linux-gnu" -#define BLD_BUILD_SYSTEM "i686-pc-linux-gnu" -#define BLD_HOST_OS "LINUX" -#define BLD_HOST_CPU_ARCH MPR_CPU_IX86 -#define BLD_HOST_CPU "i686" -#define BLD_HOST_UNIX 1 -#define BLD_BUILD_OS "LINUX" -#define BLD_BUILD_CPU_ARCH MPR_CPU_IX86 -#define BLD_BUILD_CPU i686 -#define BLD_BUILD_UNIX 1 -#define BLD_ROOT_PREFIX "/" -#define BLD_FEATURE_ACCESS_LOG 0 -#define BLD_FEATURE_ADMIN_MODULE 0 -#define BLD_FEATURE_ASPNET_MODULE 0 -#define BLD_FEATURE_ASSERT 1 -#define BLD_FEATURE_AUTH_MODULE 0 -#define BLD_FEATURE_C_API_MODULE 1 -#define BLD_FEATURE_C_API_CLIENT 0 -#define BLD_FEATURE_CGI_MODULE 0 -#define BLD_FEATURE_COMPAT_MODULE 0 -#define BLD_FEATURE_CONFIG_PARSE 0 -#define BLD_FEATURE_CONFIG_SAVE 0 -#define BLD_FEATURE_COOKIE 0 -#define BLD_FEATURE_COPY_MODULE 0 -#define BLD_FEATURE_DIGEST 0 -#define BLD_FEATURE_DLL 0 -#define BLD_FEATURE_EGI_MODULE 0 -#define BLD_FEATURE_EJS 1 -#define BLD_FEATURE_ESP_MODULE 1 -#define BLD_FEATURE_EVAL_PERIOD 30 -#define BLD_FEATURE_FLOATING_POINT 1 -#define BLD_FEATURE_IF_MODIFIED 0 -#define BLD_FEATURE_INT64 1 -#define BLD_FEATURE_KEEP_ALIVE 0 -#define BLD_FEATURE_LEGACY_API 0 -#define BLD_FEATURE_LIB_STDCPP 0 -#define BLD_FEATURE_LICENSE 0 -#define BLD_FEATURE_LOG 0 -#define BLD_FEATURE_MULTITHREAD 0 -#define BLD_FEATURE_MALLOC 0 -#define BLD_FEATURE_MALLOC_STATS 0 -#define BLD_FEATURE_MALLOC_LEAK 0 -#define BLD_FEATURE_MALLOC_HOOK 0 -#define BLD_FEATURE_NUM_TYPE int64_t -#define BLD_FEATURE_NUM_TYPE_ID MPR_TYPE_INT64 -#define BLD_FEATURE_ROMFS 0 -#define BLD_FEATURE_RUN_AS_SERVICE 0 -#define BLD_FEATURE_SAFE_STRINGS 0 -#define BLD_FEATURE_SAMPLES 0 -#define BLD_FEATURE_SESSION 1 -#define BLD_FEATURE_SHARED 0 -#define BLD_FEATURE_SQUEEZE 0 -#define BLD_FEATURE_SSL_MODULE 0 -#define BLD_FEATURE_STATIC 1 -#define BLD_FEATURE_STATIC_LINK_LIBC 0 -#define BLD_FEATURE_TEST 0 -#define BLD_FEATURE_UPLOAD_MODULE 0 -#define BLD_FEATURE_XDB_MODULE 0 -#define BLD_FEATURE_ADMIN_MODULE_BUILTIN 0 -#define BLD_FEATURE_ASPNET_MODULE_BUILTIN 0 -#define BLD_FEATURE_AUTH_MODULE_BUILTIN 0 -#define BLD_FEATURE_C_API_MODULE_BUILTIN 0 -#define BLD_FEATURE_CGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_COMPAT_MODULE_BUILTIN 0 -#define BLD_FEATURE_COPY_MODULE_BUILTIN 0 -#define BLD_FEATURE_EGI_MODULE_BUILTIN 0 -#define BLD_FEATURE_ESP_MODULE_BUILTIN 0 -#define BLD_FEATURE_SSL_MODULE_BUILTIN 0 -#define BLD_FEATURE_UPLOAD_MODULE_BUILTIN 0 -#define BLD_FEATURE_XDB_MODULE_BUILTIN 0 -#define BLD_FEATURE_ADMIN_MODULE_LOADABLE 0 -#define BLD_FEATURE_ASPNET_MODULE_LOADABLE 0 -#define BLD_FEATURE_AUTH_MODULE_LOADABLE 0 -#define BLD_FEATURE_C_API_MODULE_LOADABLE 0 -#define BLD_FEATURE_CGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_COMPAT_MODULE_LOADABLE 0 -#define BLD_FEATURE_COPY_MODULE_LOADABLE 0 -#define BLD_FEATURE_EGI_MODULE_LOADABLE 0 -#define BLD_FEATURE_ESP_MODULE_LOADABLE 0 -#define BLD_FEATURE_SSL_MODULE_LOADABLE 0 -#define BLD_FEATURE_UPLOAD_MODULE_LOADABLE 0 -#define BLD_FEATURE_XDB_MODULE_LOADABLE 0 -#define BLD_AR_FOR_BUILD "ar" -#define BLD_CC_FOR_BUILD "cc" -#define BLD_CSC_FOR_BUILD "" -#define BLD_JAVAC_FOR_BUILD "" -#define BLD_LD_FOR_BUILD "ld" -#define BLD_RANLIB_FOR_BUILD "" -#define BLD_NM_FOR_BUILD "nm" -#define BLD_CFLAGS_FOR_BUILD "" -#define BLD_IFLAGS_FOR_BUILD "" -#define BLD_LDFLAGS_FOR_BUILD "" -#define BLD_ARCHIVE_FOR_BUILD ".a" -#define BLD_EXE_FOR_BUILD "" -#define BLD_OBJ_FOR_BUILD ".o" -#define BLD_PIOBJ_FOR_BUILD ".lo" -#define BLD_CLASS_FOR_BUILD ".class" -#define BLD_SHLIB_FOR_BUILD "" -#define BLD_SHOBJ_FOR_BUILD ".so" -#define BLD_AR_FOR_HOST "ar" -#define BLD_CC_FOR_HOST "cc" -#define BLD_CSC_FOR_HOST "csc" -#define BLD_JAVAC_FOR_HOST "javac" -#define BLD_LD_FOR_HOST "ld" -#define BLD_RANLIB_FOR_HOST "true" -#define BLD_NM_FOR_HOST "nm" -#define BLD_CFLAGS_FOR_HOST "" -#define BLD_IFLAGS_FOR_HOST "" -#define BLD_LDFLAGS_FOR_HOST "" -#define BLD_ARCHIVE_FOR_HOST ".a" -#define BLD_EXE_FOR_HOST "" -#define BLD_OBJ_FOR_HOST ".o" -#define BLD_PIOBJ_FOR_HOST ".lo" -#define BLD_CLASS_FOR_HOST ".class" -#define BLD_SHLIB_FOR_HOST "" -#define BLD_SHOBJ_FOR_HOST ".so" -#define BLD_TOOLS_DIR "${BLD_TOP}/bin" -#define BLD_BIN_DIR "${BLD_TOP}/bin" -#define BLD_INC_DIR "/usr/include/${BLD_PRODUCT}" -#define BLD_EXP_OBJ_DIR "${BLD_TOP}/obj" - -#ifndef MAX_FLOAT -#define MAX_FLOAT 3.40282347e+38F -#endif diff --git a/source4/lib/appweb/ejs/ejs.h b/source4/lib/appweb/ejs/ejs.h deleted file mode 100644 index c7b0c54d8e..0000000000 --- a/source4/lib/appweb/ejs/ejs.h +++ /dev/null @@ -1,136 +0,0 @@ -/* - * @file ejs.h - * @brief Primary Embedded Javascript (ECMAScript) header. - * @overview This Embedded Javascript (EJS) header defines the - * public API. This API should only be used by those directly - * using EJS without using Embedded Server Pages (ESP). ESP - * wraps all relevant APIs to expose a single consistent API. - * \n\n - * This API requires the mpr/var.h facilities to create and - * manage objects and properties. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#ifndef _h_EJS -#define _h_EJS 1 - -#include "lib/appweb/mpr/miniMpr.h" -#include "lib/appweb/mpr/var.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/********************************* Prototypes *********************************/ - -typedef MprVarHandle EjsId; -typedef MprVarHandle EjsHandle; - -/* - * Multithreaded lock routines - */ -typedef void (*EjsLock)(void *lockData); -typedef void (*EjsUnlock)(void *lockData); - -/********************************* Prototypes *********************************/ -/* - * Module management - */ -extern int ejsOpen(EjsLock lock, EjsUnlock unlock, void *lockData); -extern void ejsClose(void); -extern EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle); -extern void ejsCloseEngine(EjsId eid); - -void *ejs_save_state(void); -void ejs_restore_state(void *ptr); - -/* - * Evaluation functions - */ -extern int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg); -extern int ejsEvalScript(EjsId eid, char *script, MprVar *result, - char **emsg); -extern int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args); - -/* - * Composite variable get / set routines. Can also use the MPR property - * routines on an object variable. - */ -extern MprVar ejsCreateObj(const char *name, int hashSize); -extern MprVar ejsCreateArray(const char *name, int hashSize); -extern bool ejsDestroyVar(MprVar *obj); -extern int ejsCopyVar(EjsId eid, const char *var, MprVar *value, - bool copyRef); -extern int ejsReadVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVar(EjsId eid, const char *var, MprVar *value); -extern int ejsWriteVarValue(EjsId eid, const char *var, MprVar value); -extern int ejsDeleteVar(EjsId eid, const char *var); - -extern MprVar *ejsGetLocalObject(EjsId eid); -extern MprVar *ejsGetGlobalObject(EjsId eid); - -/* - * Function routines - */ -extern void ejsDefineFunction(EjsId eid, const char *functionName, - char *args, char *body); -extern void ejsDefineCFunction(EjsId eid, const char *functionName, - MprCFunction fn, void *thisPtr, int flags); -extern void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags); -extern void *ejsGetThisPtr(EjsId eid); -extern MprVar *ejsGetReturnValue(EjsId eid); -extern int ejsGetLineNumber(EjsId eid); -extern int ejsParseArgs(int argc, char **argv, char *fmt, ...); -extern void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) - PRINTF_ATTRIBUTE(2,3); -extern void ejsSetReturnValue(EjsId eid, MprVar value); -extern void ejsSetReturnString(EjsId eid, const char *str); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsInternal.h b/source4/lib/appweb/ejs/ejsInternal.h deleted file mode 100644 index 8b66dafdca..0000000000 --- a/source4/lib/appweb/ejs/ejsInternal.h +++ /dev/null @@ -1,295 +0,0 @@ -/* - * @file ejsInternal.h - * @brief Private header for Embedded Javascript (ECMAScript) - * @overview This Embedded Javascript header defines the private Embedded - * Javascript internal structures. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************* Includes ***********************************/ - -#ifndef _h_EJS_INTERNAL -#define _h_EJS_INTERNAL 1 - -#include "ejs.h" - -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Constants - */ - -#if BLD_FEATURE_SQUEEZE - #define EJS_PARSE_INCR 256 /* Growth factor */ - #define EJS_MAX_RECURSE 25 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 128 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 13 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 8 /* Growth increment for lists */ -#else - #define EJS_PARSE_INCR 1024 /* Growth factor */ - #define EJS_MAX_RECURSE 100 /* Sanity for maximum recursion */ - #define EJS_MAX_ID 256 /* Maximum ID length */ - #define EJS_OBJ_HASH_SIZE 29 /* Object hash table size */ - #define EJS_SMALL_OBJ_HASH_SIZE 11 /* Small object hash size */ - #define EJS_LIST_INCR 16 /* Growth increment for lists */ -#endif -#define EJS_TOKEN_STACK 4 /* Put back token stack */ - -/* - * Lexical analyser tokens - */ -#define EJS_TOK_ERR -1 /* Any error */ -#define EJS_TOK_LPAREN 1 /* ( */ -#define EJS_TOK_RPAREN 2 /* ) */ -#define EJS_TOK_IF 3 /* if */ -#define EJS_TOK_ELSE 4 /* else */ -#define EJS_TOK_LBRACE 5 /* { */ -#define EJS_TOK_RBRACE 6 /* } */ -#define EJS_TOK_LOGICAL 7 /* ||, &&, ! */ -#define EJS_TOK_EXPR 8 /* +, -, /, % */ -#define EJS_TOK_SEMI 9 /* ; */ -#define EJS_TOK_LITERAL 10 /* literal string */ -#define EJS_TOK_FUNCTION_NAME 11 /* functionName */ -#define EJS_TOK_NEWLINE 12 /* newline white space */ -#define EJS_TOK_ID 13 /* Identifier */ -#define EJS_TOK_EOF 14 /* End of script */ -#define EJS_TOK_COMMA 15 /* Comma */ -#define EJS_TOK_VAR 16 /* var */ -#define EJS_TOK_ASSIGNMENT 17 /* = */ -#define EJS_TOK_FOR 18 /* for */ -#define EJS_TOK_INC_DEC 19 /* ++, -- */ -#define EJS_TOK_RETURN 20 /* return */ -#define EJS_TOK_PERIOD 21 /* . */ -#define EJS_TOK_LBRACKET 22 /* [ */ -#define EJS_TOK_RBRACKET 23 /* ] */ -#define EJS_TOK_NEW 24 /* new */ -#define EJS_TOK_DELETE 25 /* delete */ -#define EJS_TOK_IN 26 /* in */ -#define EJS_TOK_FUNCTION 27 /* function */ -#define EJS_TOK_NUMBER 28 /* Number */ - -/* - * Expression operators - */ -#define EJS_EXPR_LESS 1 /* < */ -#define EJS_EXPR_LESSEQ 2 /* <= */ -#define EJS_EXPR_GREATER 3 /* > */ -#define EJS_EXPR_GREATEREQ 4 /* >= */ -#define EJS_EXPR_EQ 5 /* == */ -#define EJS_EXPR_NOTEQ 6 /* != */ -#define EJS_EXPR_PLUS 7 /* + */ -#define EJS_EXPR_MINUS 8 /* - */ -#define EJS_EXPR_DIV 9 /* / */ -#define EJS_EXPR_MOD 10 /* % */ -#define EJS_EXPR_LSHIFT 11 /* << */ -#define EJS_EXPR_RSHIFT 12 /* >> */ -#define EJS_EXPR_MUL 13 /* * */ -#define EJS_EXPR_ASSIGNMENT 14 /* = */ -#define EJS_EXPR_INC 15 /* ++ */ -#define EJS_EXPR_DEC 16 /* -- */ -#define EJS_EXPR_BOOL_COMP 17 /* ! */ - -/* - * Conditional operators - */ -#define EJS_COND_AND 1 /* && */ -#define EJS_COND_OR 2 /* || */ -#define EJS_COND_NOT 3 /* ! */ - -/* - * States - */ -#define EJS_STATE_ERR -1 /* Error state */ -#define EJS_STATE_EOF 1 /* End of file */ -#define EJS_STATE_COND 2 /* Parsing a "(conditional)" stmt */ -#define EJS_STATE_COND_DONE 3 -#define EJS_STATE_RELEXP 4 /* Parsing a relational expr */ -#define EJS_STATE_RELEXP_DONE 5 -#define EJS_STATE_EXPR 6 /* Parsing an expression */ -#define EJS_STATE_EXPR_DONE 7 -#define EJS_STATE_STMT 8 /* Parsing General statement */ -#define EJS_STATE_STMT_DONE 9 -#define EJS_STATE_STMT_BLOCK_DONE 10 /* End of block "}" */ -#define EJS_STATE_ARG_LIST 11 /* Function arg list */ -#define EJS_STATE_ARG_LIST_DONE 12 -#define EJS_STATE_DEC_LIST 16 /* Declaration list */ -#define EJS_STATE_DEC_LIST_DONE 17 -#define EJS_STATE_DEC 18 /* Declaration statement */ -#define EJS_STATE_DEC_DONE 19 -#define EJS_STATE_RET 20 /* Return statement */ - -#define EJS_STATE_BEGIN EJS_STATE_STMT - -/* - * General parsing flags. - */ -#define EJS_FLAGS_EXE 0x1 /* Execute statements */ -#define EJS_FLAGS_LOCAL 0x2 /* Get local vars only */ -#define EJS_FLAGS_GLOBAL 0x4 /* Get global vars only */ -#define EJS_FLAGS_CREATE 0x8 /* Create var */ -#define EJS_FLAGS_ASSIGNMENT 0x10 /* In assignment stmt */ -#define EJS_FLAGS_DELETE 0x20 /* Deleting a variable */ -#define EJS_FLAGS_FOREACH 0x40 /* In foreach */ -#define EJS_FLAGS_NEW 0x80 /* In a new stmt() */ -#define EJS_FLAGS_EXIT 0x100 /* Must exit */ - -/* - * Putback token - */ - -typedef struct EjsToken { - char *token; /* Token string */ - int id; /* Token ID */ -} EjsToken; - -/* - * EJ evaluation block structure - */ -typedef struct ejEval { - EjsToken putBack[EJS_TOKEN_STACK]; /* Put back token stack */ - int putBackIndex; /* Top of stack index */ - MprStr line; /* Current line */ - int lineLength; /* Current line length */ - int lineNumber; /* Parse line number */ - int lineColumn; /* Column in line */ - MprStr script; /* Input script for parsing */ - char *scriptServp; /* Next token in the script */ - int scriptSize; /* Length of script */ - MprStr tokbuf; /* Current token */ - char *tokEndp; /* Pointer past end of token */ - char *tokServp; /* Pointer to next token char */ - int tokSize; /* Size of token buffer */ - struct ejEval *next; /* used for backtraces */ - const char *procName; /* gives name in backtrace */ -} EjsInput; - -/* - * Function call structure - */ -typedef struct { - MprArray *args; /* Args for function */ - MprVar *fn; /* Function definition */ - char *procName; /* Function name */ -} EjsProc; - -/* - * Per EJS structure - */ -typedef struct ej { - EjsHandle altHandle; /* alternate callback handle */ - MprVar *currentObj; /* Ptr to current object */ - MprVar *currentProperty; /* Ptr to current property */ - EjsId eid; /* Halloc handle */ - char *error; /* Error message */ - int exitStatus; /* Status to exit() */ - int flags; /* Flags */ - MprArray *frames; /* List of variable frames */ - MprVar *global; /* Global object */ - EjsInput *input; /* Input evaluation block */ - MprVar *local; /* Local object */ - EjsHandle primaryHandle; /* primary callback handle */ - EjsProc *proc; /* Current function */ - MprVar result; /* Variable result */ - void *thisPtr; /* C++ ptr for functions */ - int tid; /* Current token id */ - char *token; /* Pointer to token string */ - MprVar tokenNumber; /* Parsed number */ -} Ejs; - -typedef int EjsBlock; /* Scope block id */ - -/* - * Function callback when using Alternate handles. - */ -typedef int (*EjsAltStringCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, char **argv); -typedef int (*EjsAltCFunction)(EjsHandle userHandle, EjsHandle altHandle, - int argc, MprVar **argv); - -/******************************** Prototypes **********************************/ -/* - * Ejs Lex - */ -extern int ejsLexOpenScript(Ejs* ep, char *script); -extern void ejsLexCloseScript(Ejs* ep); -extern int ejsInitInputState(EjsInput *ip); -extern void ejsLexSaveInputState(Ejs* ep, EjsInput* state); -extern void ejsLexFreeInputState(Ejs* ep, EjsInput* state); -extern void ejsLexRestoreInputState(Ejs* ep, EjsInput* state); -extern int ejsLexGetToken(Ejs* ep, int state); -extern void ejsLexPutbackToken(Ejs* ep, int tid, char *string); - -/* - * Parsing - */ -extern MprVar *ejsFindObj(Ejs *ep, int state, const char *property, - int flags); -extern MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, - char *property, int flags); -extern int ejsGetVarCore(Ejs *ep, const char *var, MprVar **obj, - MprVar **varValue, int flags); -extern int ejsParse(Ejs *ep, int state, int flags); -extern Ejs *ejsPtr(EjsId eid); -extern void ejsSetExitStatus(int eid, int status); -extern void ejsSetFlags(int orFlags, int andFlags); - -/* - * Create variable scope blocks - */ -extern EjsBlock ejsOpenBlock(EjsId eid); -extern int ejsCloseBlock(EjsId eid, EjsBlock vid); -extern int ejsEvalBlock(EjsId eid, char *script, MprVar *v, char **err); -extern int ejsDefineStandardProperties(MprVar *objVar); - -/* - * Error handling - */ -extern void ejsError(Ejs *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -#ifdef __cplusplus -} -#endif -#endif /* _h_EJS_INTERNAL */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsLex.c b/source4/lib/appweb/ejs/ejsLex.c deleted file mode 100644 index b9a363cfc9..0000000000 --- a/source4/lib/appweb/ejs/ejsLex.c +++ /dev/null @@ -1,923 +0,0 @@ -/* - * @file ejsLex.c - * @brief EJS Lexical Analyser - * @overview EJS lexical analyser. This implementes a lexical analyser - * for a subset of the JavaScript language. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static int getLexicalToken(Ejs *ep, int state); -static int tokenAddChar(Ejs *ep, int c); -static int inputGetc(Ejs *ep); -static void inputPutback(Ejs *ep, int c); -static int charConvert(Ejs *ep, int base, int maxDig); - -/************************************* Code ***********************************/ -/* - * Open a new input script - */ - -int ejsLexOpenScript(Ejs *ep, char *script) -{ - EjsInput *ip; - - mprAssert(ep); - mprAssert(script); - - if ((ip = mprMalloc(sizeof(EjsInput))) == NULL) { - return -1; - } - memset(ip, 0, sizeof(*ip)); - ip->next = ep->input; - ep->input = ip; - ip->procName = ep->proc?ep->proc->procName:NULL; - -/* - * Create the parse token buffer and script buffer - */ - ip->tokbuf = mprMalloc(EJS_PARSE_INCR); - ip->tokSize = EJS_PARSE_INCR; - ip->tokServp = ip->tokbuf; - ip->tokEndp = ip->tokbuf; - - ip->script = mprStrdup(script); - ip->scriptSize = strlen(script); - ip->scriptServp = ip->script; - - ip->lineNumber = 1; - ip->lineLength = 0; - ip->lineColumn = 0; - ip->line = NULL; - - ip->putBackIndex = -1; - - return 0; -} - -/******************************************************************************/ -/* - * Close the input script - */ - -void ejsLexCloseScript(Ejs *ep) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - ep->input = ip->next; - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].token = 0; - } - - mprFree(ip->line); - mprFree(ip->tokbuf); - mprFree(ip->script); - - mprFree(ip); -} - -/******************************************************************************/ -/* - * Initialize an input state structure - */ - -int ejsInitInputState(EjsInput *ip) -{ - mprAssert(ip); - - memset(ip, 0, sizeof(*ip)); - ip->putBackIndex = -1; - - return 0; -} -/******************************************************************************/ -/* - * Save the input state - */ - -void ejsLexSaveInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - - ip = ep->input; - mprAssert(ip); - - *state = *ip; - - for (i = 0; i < ip->putBackIndex; i++) { - state->putBack[i].token = mprStrdup(ip->putBack[i].token); - state->putBack[i].id = ip->putBack[i].id; - } - for (; i < EJS_TOKEN_STACK; i++) { - state->putBack[i].token = 0; - } - - state->line = mprMalloc(ip->lineLength); - mprStrcpy(state->line, ip->lineLength, ip->line); - - state->lineColumn = ip->lineColumn; - state->lineNumber = ip->lineNumber; - state->lineLength = ip->lineLength; -} - -/******************************************************************************/ -/* - * Restore the input state - */ - -void ejsLexRestoreInputState(Ejs *ep, EjsInput *state) -{ - EjsInput *ip; - int i; - - mprAssert(ep); - mprAssert(state); - - ip = ep->input; - mprAssert(ip); - - ip->tokbuf = state->tokbuf; - ip->tokServp = state->tokServp; - ip->tokEndp = state->tokEndp; - ip->tokSize = state->tokSize; - - ip->script = state->script; - ip->scriptServp = state->scriptServp; - ip->scriptSize = state->scriptSize; - - ip->putBackIndex = state->putBackIndex; - for (i = 0; i < ip->putBackIndex; i++) { - mprFree(ip->putBack[i].token); - ip->putBack[i].id = state->putBack[i].id; - ip->putBack[i].token = mprStrdup(state->putBack[i].token); - } - - mprFree(ip->line); - ip->line = mprMalloc(state->lineLength); - mprStrcpy(ip->line, state->lineLength, state->line); - - ip->lineColumn = state->lineColumn; - ip->lineNumber = state->lineNumber; - ip->lineLength = state->lineLength; -} - -/******************************************************************************/ -/* - * Free a saved input state - */ - -void ejsLexFreeInputState(Ejs *ep, EjsInput *state) -{ - int i; - - mprAssert(ep); - mprAssert(state); - - for (i = 0; i < EJS_TOKEN_STACK; i++) { - mprFree(state->putBack[i].token); - } - state->putBackIndex = -1; - mprFree(state->line); - state->lineLength = 0; - state->lineColumn = 0; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -int ejsLexGetToken(Ejs *ep, int state) -{ - mprAssert(ep); - - ep->tid = getLexicalToken(ep, state); - return ep->tid; -} - -/******************************************************************************/ - -/* - * Check for reserved words "if", "else", "var", "for", "foreach", - * "delete", "function", and "return". "new", "in" and "function" - * done below. "true", "false", "null", "undefined" are handled - * as global objects. - * - * Other reserved words not supported: - * "break", "case", "catch", "continue", "default", "do", - * "finally", "instanceof", "switch", "this", "throw", "try", - * "typeof", "while", "with" - * - * ECMA extensions reserved words (not supported): - * "abstract", "boolean", "byte", "char", "class", "const", - * "debugger", "double", "enum", "export", "extends", - * "final", "float", "goto", "implements", "import", "int", - * "interface", "long", "native", "package", "private", - * "protected", "public", "short", "static", "super", - * "synchronized", "throws", "transient", "volatile" - */ - -static int checkReservedWord(Ejs *ep, int state, int c, int tid) -{ - if (state == EJS_STATE_STMT) { - if (strcmp(ep->token, "if") == 0) { - inputPutback(ep, c); - return EJS_TOK_IF; - } else if (strcmp(ep->token, "else") == 0) { - inputPutback(ep, c); - return EJS_TOK_ELSE; - } else if (strcmp(ep->token, "var") == 0) { - inputPutback(ep, c); - return EJS_TOK_VAR; - } else if (strcmp(ep->token, "for") == 0) { - inputPutback(ep, c); - return EJS_TOK_FOR; - } else if (strcmp(ep->token, "delete") == 0) { - inputPutback(ep, c); - return EJS_TOK_DELETE; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } else if (strcmp(ep->token, "return") == 0) { - if ((c == ';') || (c == '(')) { - inputPutback(ep, c); - } - return EJS_TOK_RETURN; - } - } else if (state == EJS_STATE_EXPR) { - if (strcmp(ep->token, "new") == 0) { - inputPutback(ep, c); - return EJS_TOK_NEW; - } else if (strcmp(ep->token, "in") == 0) { - inputPutback(ep, c); - return EJS_TOK_IN; - } else if (strcmp(ep->token, "function") == 0) { - inputPutback(ep, c); - return EJS_TOK_FUNCTION; - } - } - return tid; -} - -/******************************************************************************/ -/* - * Get the next EJS token - */ - -static int getLexicalToken(Ejs *ep, int state) -{ - MprType type; - EjsInput *ip; - int done, tid, c, quote, style, idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ep->tid = -1; - tid = -1; - type = BLD_FEATURE_NUM_TYPE_ID; - - /* - * Use a putback tokens first. Don't free strings as caller needs access. - */ - if (ip->putBackIndex >= 0) { - idx = ip->putBackIndex; - tid = ip->putBack[idx].id; - ep->token = (char*) ip->putBack[idx].token; - tid = checkReservedWord(ep, state, 0, tid); - ip->putBackIndex--; - return tid; - } - ep->token = ip->tokServp = ip->tokEndp = ip->tokbuf; - *ip->tokServp = '\0'; - - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - - /* - * Main lexical analyser - */ - for (done = 0; !done; ) { - switch (c) { - case -1: - return EJS_TOK_EOF; - - case ' ': - case '\t': - case '\r': - do { - if ((c = inputGetc(ep)) < 0) - break; - } while (c == ' ' || c == '\t' || c == '\r'); - break; - - case '\n': - return EJS_TOK_NEWLINE; - - case '(': - tokenAddChar(ep, c); - return EJS_TOK_LPAREN; - - case ')': - tokenAddChar(ep, c); - return EJS_TOK_RPAREN; - - case '[': - tokenAddChar(ep, c); - return EJS_TOK_LBRACKET; - - case ']': - tokenAddChar(ep, c); - return EJS_TOK_RBRACKET; - - case '.': - tokenAddChar(ep, c); - return EJS_TOK_PERIOD; - - case '{': - tokenAddChar(ep, c); - return EJS_TOK_LBRACE; - - case '}': - tokenAddChar(ep, c); - return EJS_TOK_RBRACE; - - case '+': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '+' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_PLUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_INC); - return EJS_TOK_INC_DEC; - - case '-': - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '-' ) { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_MINUS); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_DEC); - return EJS_TOK_INC_DEC; - - case '*': - tokenAddChar(ep, EJS_EXPR_MUL); - return EJS_TOK_EXPR; - - case '%': - tokenAddChar(ep, EJS_EXPR_MOD); - return EJS_TOK_EXPR; - - case '/': - /* - * Handle the division operator and comments - */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c != '*' && c != '/') { - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_DIV); - return EJS_TOK_EXPR; - } - style = c; - /* - * Eat comments. Both C and C++ comment styles are supported. - */ - while (1) { - if ((c = inputGetc(ep)) < 0) { - if (style == '/') { - return EJS_TOK_EOF; - } - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '\n' && style == '/') { - break; - } else if (c == '*') { - c = inputGetc(ep); - if (style == '/') { - if (c == '\n') { - break; - } - } else { - if (c == '/') { - break; - } - } - } - } - /* - * Continue looking for a token, so get the next character - */ - if ((c = inputGetc(ep)) < 0) { - return EJS_TOK_EOF; - } - break; - - case '<': /* < and <= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '<') { - tokenAddChar(ep, EJS_EXPR_LSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_LESSEQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_LESS); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '>': /* > and >= */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '>') { - tokenAddChar(ep, EJS_EXPR_RSHIFT); - return EJS_TOK_EXPR; - } else if (c == '=') { - tokenAddChar(ep, EJS_EXPR_GREATEREQ); - return EJS_TOK_EXPR; - } - tokenAddChar(ep, EJS_EXPR_GREATER); - inputPutback(ep, c); - return EJS_TOK_EXPR; - - case '=': /* "==" */ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_EQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - return EJS_TOK_ASSIGNMENT; - - case '!': /* "!=" or "!"*/ - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - if (c == '=') { - tokenAddChar(ep, EJS_EXPR_NOTEQ); - return EJS_TOK_EXPR; - } - inputPutback(ep, c); - tokenAddChar(ep, EJS_EXPR_BOOL_COMP); - return EJS_TOK_EXPR; - - case ';': - tokenAddChar(ep, c); - return EJS_TOK_SEMI; - - case ',': - tokenAddChar(ep, c); - return EJS_TOK_COMMA; - - case '|': /* "||" */ - if ((c = inputGetc(ep)) < 0 || c != '|') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_OR); - return EJS_TOK_LOGICAL; - - case '&': /* "&&" */ - if ((c = inputGetc(ep)) < 0 || c != '&') { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - tokenAddChar(ep, EJS_COND_AND); - return EJS_TOK_LOGICAL; - - case '\"': /* String quote */ - case '\'': - quote = c; - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Syntax Error"); - return EJS_TOK_ERR; - } - - while (c != quote) { - /* - * Check for escape sequence characters - */ - if (c == '\\') { - c = inputGetc(ep); - - if (isdigit(c)) { - /* - * Octal support, \101 maps to 65 = 'A'. Put first - * char back so converter will work properly. - */ - inputPutback(ep, c); - c = charConvert(ep, 8, 3); - - } else { - switch (c) { - case 'n': - c = '\n'; break; - case 'b': - c = '\b'; break; - case 'f': - c = '\f'; break; - case 'r': - c = '\r'; break; - case 't': - c = '\t'; break; - case 'x': - /* - * Hex support, \x41 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - break; - case 'u': - /* - * Unicode support, \x0401 maps to 65 = 'A' - */ - c = charConvert(ep, 16, 2); - c = c*16 + charConvert(ep, 16, 2); - - break; - case '\'': - case '\"': - case '\\': - break; - default: - ejsError(ep, "Invalid Escape Sequence"); - return EJS_TOK_ERR; - } - } - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } else { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - } - if ((c = inputGetc(ep)) < 0) { - ejsError(ep, "Unmatched Quote"); - return EJS_TOK_ERR; - } - } - return EJS_TOK_LITERAL; - - case '0': - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (tolower(c) == 'x') { - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - } while (isdigit(c) || (tolower(c) >= 'a' && tolower(c) <= 'f')); - - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - if (! isdigit(c)) { -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || c == '+' || c == '-') { - /* Fall through */ - type = MPR_TYPE_FLOAT; - } else -#endif - { - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - } - } - /* Fall through to get more digits */ - - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - do { - if (tokenAddChar(ep, c) < 0) { - return EJS_TOK_ERR; - } - if ((c = inputGetc(ep)) < 0) { - break; - } -#if BLD_FEATURE_FLOATING_POINT - if (c == '.' || tolower(c) == 'e' || tolower(c) == 'f') { - type = MPR_TYPE_FLOAT; - } - } while (isdigit(c) || c == '.' || tolower(c) == 'e' || tolower(c) == 'f' || - ((type == MPR_TYPE_FLOAT) && (c == '+' || c == '-'))); -#else - } while (isdigit(c)); -#endif - - mprDestroyVar(&ep->tokenNumber); - ep->tokenNumber = mprParseVar(ep->token, type); - inputPutback(ep, c); - return EJS_TOK_NUMBER; - - default: - /* - * Identifiers or a function names - */ - while (1) { - if (c == '\\') { - if ((c = inputGetc(ep)) < 0) { - break; - } - if (c == '\n' || c == '\r') { - break; - } - } else if (tokenAddChar(ep, c) < 0) { - break; - } - if ((c = inputGetc(ep)) < 0) { - break; - } - if (!isalnum(c) && c != '$' && c != '_' && c != '\\') { - break; - } - } - if (*ep->token == '\0') { - c = inputGetc(ep); - break; - } - if (! isalpha((int) *ep->token) && *ep->token != '$' && - *ep->token != '_') { - ejsError(ep, "Invalid identifier %s", ep->token); - return EJS_TOK_ERR; - } - - tid = checkReservedWord(ep, state, c, EJS_TOK_ID); - if (tid != EJS_TOK_ID) { - return tid; - } - - /* - * Skip white space after token to find out whether this is - * a function or not. - */ - while (c == ' ' || c == '\t' || c == '\r' || c == '\n') { - if ((c = inputGetc(ep)) < 0) - break; - } - - tid = EJS_TOK_ID; - done++; - } - } - - /* - * Putback the last extra character for next time - */ - inputPutback(ep, c); - return tid; -} - -/******************************************************************************/ -/* - * Convert a hex or octal character back to binary, return original char if - * not a hex digit - */ - -static int charConvert(Ejs *ep, int base, int maxDig) -{ - int i, c, lval, convChar; - - lval = 0; - for (i = 0; i < maxDig; i++) { - if ((c = inputGetc(ep)) < 0) { - break; - } - /* - * Initialize to out of range value - */ - convChar = base; - if (isdigit(c)) { - convChar = c - '0'; - } else if (c >= 'a' && c <= 'f') { - convChar = c - 'a' + 10; - } else if (c >= 'A' && c <= 'F') { - convChar = c - 'A' + 10; - } - /* - * If unexpected character then return it to buffer. - */ - if (convChar >= base) { - inputPutback(ep, c); - break; - } - lval = (lval * base) + convChar; - } - return lval; -} - -/******************************************************************************/ -/* - * Putback the last token read. Accept at most one push back token. - */ - -void ejsLexPutbackToken(Ejs *ep, int tid, char *string) -{ - EjsInput *ip; - int idx; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - ip->putBackIndex += 1; - idx = ip->putBackIndex; - ip->putBack[idx].id = tid; - - if (ip->putBack[idx].token) { - if (ip->putBack[idx].token == string) { - return; - } - mprFree(ip->putBack[idx].token); - } - ip->putBack[idx].token = mprStrdup(string); -} - -/******************************************************************************/ -/* - * Add a character to the token buffer - */ - -static int tokenAddChar(Ejs *ep, int c) -{ - EjsInput *ip; - uchar *oldbuf; - - mprAssert(ep); - ip = ep->input; - mprAssert(ip); - - if (ip->tokEndp >= &ip->tokbuf[ip->tokSize - 1]) { - ip->tokSize += EJS_PARSE_INCR; - oldbuf = ip->tokbuf; - ip->tokbuf = mprRealloc(ip->tokbuf, ip->tokSize); - if (ip->tokbuf == 0) { - ejsError(ep, "Token too big"); - return -1; - } - ip->tokEndp += (int) ((uchar*) ip->tokbuf - oldbuf); - ip->tokServp += (int) ((uchar*) ip->tokbuf - oldbuf); - ep->token += (int) ((uchar*) ip->tokbuf - oldbuf); - } - *ip->tokEndp++ = c; - *ip->tokEndp = '\0'; - - return 0; -} - -/******************************************************************************/ -/* - * Get another input character - */ - -static int inputGetc(Ejs *ep) -{ - EjsInput *ip; - int c; - - mprAssert(ep); - ip = ep->input; - - if (ip->scriptSize <= 0) { - return -1; - } - - c = (uchar) (*ip->scriptServp++); - ip->scriptSize--; - - /* - * For debugging, accumulate the line number and the currenly parsed line - */ - if (c == '\n') { -#if BLD_DEBUG && 0 - if (ip->lineColumn > 0) { - printf("PARSED: %s\n", ip->line); - } -#endif - ip->lineNumber++; - ip->lineColumn = 0; - } else { - if ((ip->lineColumn + 2) >= ip->lineLength) { - ip->lineLength += 80; - ip->line = mprRealloc(ip->line, ip->lineLength * sizeof(char)); - } - ip->line[ip->lineColumn++] = c; - ip->line[ip->lineColumn] = '\0'; - } - return c; -} - -/******************************************************************************/ -/* - * Putback a character onto the input queue - */ - -static void inputPutback(Ejs *ep, int c) -{ - EjsInput *ip; - - mprAssert(ep); - - if (c != 0) { - ip = ep->input; - *--ip->scriptServp = c; - ip->scriptSize++; - ip->lineColumn--; - ip->line[ip->lineColumn] = '\0'; - } -} - -/******************************************************************************/ - -#else -void ejsLexDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsLib.c b/source4/lib/appweb/ejs/ejsLib.c deleted file mode 100644 index 67d0a4e760..0000000000 --- a/source4/lib/appweb/ejs/ejsLib.c +++ /dev/null @@ -1,1090 +0,0 @@ -/* - * @file ejs.c - * @brief Embedded JavaScript (EJS) - * @overview Main module interface logic. - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/********************************** Local Data ********************************/ - -/* - * These fields must be locked before any access when multithreaded - */ -static MprVar master; /* Master object */ -static MprArray *ejsList; /* List of ej handles */ - -#if BLD_FEATURE_MULTITHREAD -static EjsLock lock; -static EjsUnlock unlock; -static void *lockData; -#define ejsLock() if (lock) { (lock)(lockData); } else -#define ejsUnlock() if (unlock) { (unlock)(lockData); } else -#else -#define ejsLock() -#define ejsUnlock() -#endif - - -/* - save/restore global ejs state - used to cope with simultaneous ejs requests - this is a workaround for the use of global variables in ejs -*/ -struct ejs_state_ctx { - MprVar master; - MprArray *ejsList; -}; - -void *ejs_save_state(void) -{ - struct ejs_state_ctx *ctx = talloc(talloc_autofree_context(), struct ejs_state_ctx); - ctx->master = master; - ctx->ejsList = ejsList; - return ctx; -} - -void ejs_restore_state(void *ptr) -{ - struct ejs_state_ctx *ctx = talloc_get_type(ptr, struct ejs_state_ctx); - master = ctx->master; - ejsList = ctx->ejsList; - talloc_free(ctx); -} - - -/****************************** Forward Declarations **************************/ - -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen); - -/************************************* Code ***********************************/ -/* - * Initialize the EJ subsystem - */ - -int ejsOpen(EjsLock lockFn, EjsUnlock unlockFn, void *data) -{ - MprVar *np; - -#if BLD_FEATURE_MULTITHREAD - if (lockFn) { - lock = lockFn; - unlock = unlockFn; - lockData = data; - } -#endif - ejsLock(); - - /* - * Master is the top level object (above global). It is used to clone its - * contents into the global scope for each. This is never visible to the - * user, so don't use ejsCreateObj(). - */ - master = mprCreateObjVar("master", EJS_SMALL_OBJ_HASH_SIZE); - if (master.type == MPR_TYPE_UNDEFINED) { - ejsUnlock(); - return MPR_ERR_CANT_ALLOCATE; - } - - ejsList = mprCreateArray(); - ejsDefineStandardProperties(&master); - - /* - * Make these objects immutable - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprSetVarReadonly(np, 1); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - ejsUnlock(); - return 0; -} - -/******************************************************************************/ - -void ejsClose() -{ - ejsLock(); - mprDestroyArray(ejsList); - mprDestroyVar(&master); - ejsUnlock(); -} - -/******************************************************************************/ -/* - * Create and initialize an EJS engine - */ - -EjsId ejsOpenEngine(EjsHandle primaryHandle, EjsHandle altHandle) -{ - MprVar *np; - Ejs *ep; - - ep = (Ejs *)mprMalloc(sizeof(Ejs)); - if (ep == 0) { - return (EjsId) -1; - } - memset(ep, 0, sizeof(Ejs)); - - ejsLock(); - ep->eid = (EjsId) mprAddToArray(ejsList, ep); - ejsUnlock(); - - /* - * Create array of local variable frames - */ - ep->frames = mprCreateArray(); - if (ep->frames == 0) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - ep->primaryHandle = primaryHandle; - ep->altHandle = altHandle; - - /* - * Create first frame: global variables - */ - ep->global = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->global = ejsCreateObj("global", EJS_OBJ_HASH_SIZE); - if (ep->global->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->global); - - /* - * Create first local variable frame - */ - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("local", EJS_OBJ_HASH_SIZE); - if (ep->local->type == MPR_TYPE_UNDEFINED) { - ejsCloseEngine(ep->eid); - return (EjsId) -1; - } - mprAddToArray(ep->frames, ep->local); - - /* - * Clone all master variables into the global frame. This does a - * reference copy. - * - * ejsDefineStandardProperties(ep->global); - */ - np = mprGetFirstProperty(&master, MPR_ENUM_FUNCTIONS | MPR_ENUM_DATA); - while (np) { - mprCreateProperty(ep->global, np->name, np); - np = mprGetNextProperty(&master, np, MPR_ENUM_FUNCTIONS | - MPR_ENUM_DATA); - } - - mprCreateProperty(ep->global, "global", ep->global); - mprCreateProperty(ep->global, "this", ep->global); - mprCreateProperty(ep->local, "local", ep->local); - - return ep->eid; -} - -/******************************************************************************/ -/* - * Close an EJS instance - */ - -void ejsCloseEngine(EjsId eid) -{ - Ejs *ep; - MprVar *vp; - void **handles; - int i; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - - mprFree(ep->error); - mprDestroyVar(&ep->result); - mprDestroyVar(&ep->tokenNumber); - - if (ep->local) { - mprDeleteProperty(ep->local, "local"); - } - mprDeleteProperty(ep->global, "this"); - mprDeleteProperty(ep->global, "global"); - - handles = ep->frames->handles; - for (i = 0; i < ep->frames->max; i++) { - vp = handles[i]; - if (vp) { -#if BLD_DEBUG - if (vp->type == MPR_TYPE_OBJECT && vp->properties->refCount > 1) { - mprLog(7, "ejsCloseEngine: %s has ref count %d\n", - vp->name, vp->properties->refCount); - } -#endif - mprDestroyVar(vp); - mprFree(vp); - mprRemoveFromArray(ep->frames, i); - } - } - mprDestroyArray(ep->frames); - - ejsLock(); - mprRemoveFromArray(ejsList, (int) ep->eid); - ejsUnlock(); - - mprFree(ep); -} - -/******************************************************************************/ -/* - * Evaluate an EJS script file - */ - -int ejsEvalFile(EjsId eid, char *path, MprVar *result, char **emsg) -{ - struct stat sbuf; - Ejs *ep; - char *script; - int rc, fd; - - mprAssert(path && *path); - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - goto error; - } - - if ((fd = open(path, O_RDONLY | O_BINARY, 0666)) < 0) { - ejsError(ep, "Can't open %s\n", path); - goto error; - } - - if (stat(path, &sbuf) < 0) { - close(fd); - ejsError(ep, "Cant stat %s", path); - goto error; - } - - if ((script = (char*) mprMalloc(sbuf.st_size + 1)) == NULL) { - close(fd); - ejsError(ep, "Cant malloc %d", (int) sbuf.st_size); - goto error; - } - - if (read(fd, script, sbuf.st_size) != (int) sbuf.st_size) { - close(fd); - mprFree(script); - ejsError(ep, "Error reading %s", path); - goto error; - } - - script[sbuf.st_size] = '\0'; - close(fd); - - rc = ejsEvalBlock(eid, script, result, emsg); - mprFree(script); - - return rc; - -/* - * Error return - */ -error: - if(emsg) - *emsg = mprStrdup(ep->error); - return -1; -} - -/******************************************************************************/ -/* - * Create a new variable scope block. This pushes the old local frame down - * the stack and creates a new local variables frame. - */ - -int ejsOpenBlock(EjsId eid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - ep->local = (MprVar*) mprMalloc(sizeof(MprVar)); - *ep->local = ejsCreateObj("localBlock", EJS_OBJ_HASH_SIZE); - - mprCreateProperty(ep->local, "local", ep->local); - - return mprAddToArray(ep->frames, ep->local); -} - -/******************************************************************************/ -/* - * Close a variable scope block opened via ejsOpenBlock. Pop back the old - * local variables frame. - */ - -int ejsCloseBlock(EjsId eid, int fid) -{ - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - /* - * Must remove self-references before destroying "local" - */ - mprDeleteProperty(ep->local, "local"); - - mprDestroyVar(ep->local); - mprFree(ep->local); - - mprRemoveFromArray(ep->frames, fid); - ep->local = (MprVar*) ep->frames->handles[ep->frames->used - 1]; - - return 0; -} - -/******************************************************************************/ -/* - * Create a new variable scope block and evaluate a script. All frames - * created during this context will be automatically deleted when complete. - * vp and emsg are optional. i.e. created local variables will be discarded - * when this routine returns. - */ - -int ejsEvalBlock(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - int rc, fid; - - mprAssert(script); - - fid = ejsOpenBlock(eid); - rc = ejsEvalScript(eid, script, vp, emsg); - ejsCloseBlock(eid, fid); - - return rc; -} - -/******************************************************************************/ -/* - * Parse and evaluate a EJS. Return the result in *vp. The result is "owned" - * by EJ and the caller must not free it. Returns -1 on errors and zero - * for success. On errors, emsg will be set to the reason. The caller must - * free emsg. - */ - -int ejsEvalScript(EjsId eid, char *script, MprVar *vp, char **emsg) -{ - Ejs *ep; - int state; - void *endlessLoopTest; - int loopCounter; - - if (emsg) { - *emsg = NULL; - } - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - mprDestroyVar(&ep->result); - - if (script == 0) { - return 0; - } - - /* - * Allocate a new evaluation block, and save the old one - */ - ejsLexOpenScript(ep, script); - - /* - * Do the actual parsing and evaluation - */ - loopCounter = 0; - endlessLoopTest = NULL; - ep->exitStatus = 0; - - do { - state = ejsParse(ep, EJS_STATE_BEGIN, EJS_FLAGS_EXE); - - if (state == EJS_STATE_RET) { - state = EJS_STATE_EOF; - } - /* - * Stuck parser and endless recursion protection. - */ - if (endlessLoopTest == ep->input->scriptServp) { - if (loopCounter++ > 10) { - state = EJS_STATE_ERR; - ejsError(ep, "Syntax error"); - } - } else { - endlessLoopTest = ep->input->scriptServp; - loopCounter = 0; - } - } while (state != EJS_STATE_EOF && state != EJS_STATE_ERR); - - ejsLexCloseScript(ep); - - /* - * Return any error string to the user - */ - if (state == EJS_STATE_ERR && emsg) { - *emsg = mprStrdup(ep->error); - } - - if (state == EJS_STATE_ERR) { - return -1; - } - - if (vp) { - *vp = ep->result; - } - - return ep->exitStatus; -} - -/******************************************************************************/ -/* - * Core error handling - */ - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) - PRINTF_ATTRIBUTE(2, 0); - -static void ejsErrorCore(Ejs* ep, const char *fmt, va_list args) -{ - EjsInput *ip; - char *errbuf, *msgbuf; - int frame = 0; - - mprAssert(ep); - - msgbuf = NULL; - mprAllocVsprintf(&msgbuf, MPR_MAX_STRING, fmt, args); - - ip = ep->input; - mprAllocSprintf(&errbuf, MPR_MAX_STRING, "%s\nBacktrace:\n", msgbuf); - - /* form a backtrace */ - while (ip) { - char *msg2, *ebuf2; - mprAllocSprintf(&msg2, MPR_MAX_STRING, - "\t[%2d] %20s:%-4d -> %s\n", - frame++, ip->procName?ip->procName:"", ip->lineNumber, ip->line); - ebuf2 = mprRealloc(errbuf, strlen(errbuf) + strlen(msg2) + 1); - if (ebuf2 == NULL) break; - errbuf = ebuf2; - memcpy(errbuf+strlen(errbuf), msg2, strlen(msg2)+1); - mprFree(msg2); - ip = ip->next; - } - mprFree(ep->error); - ep->error = errbuf; - mprFree(msgbuf); -} - -/******************************************************************************/ -/* - * Internal use function to set the error message - */ - -void ejsError(Ejs* ep, const char* fmt, ...) -{ - va_list args; - - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Public routine to set the error message - */ - -void ejsSetErrorMsg(EjsId eid, const char* fmt, ...) -{ - va_list args; - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - va_start(args, fmt); - ejsErrorCore(ep, fmt, args); - va_end(args); -} - -/******************************************************************************/ -/* - * Get the current line number - */ - -int ejsGetLineNumber(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - return ep->input->lineNumber; -} - -/******************************************************************************/ -/* - * Return the local object - */ - -MprVar *ejsGetLocalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->local; -} - -/******************************************************************************/ -/* - * Return the global object - */ - -MprVar *ejsGetGlobalObject(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->global; -} - -/******************************************************************************/ -/* - * Copy the value of an object property. Return value is in "value". - * If deepCopy is true, copy all object/strings. Otherwise, object reference - * counts are incremented. Callers must always call mprDestroyVar on the - * return value to prevent leaks. - * - * Returns: -1 on errors or if the variable is not found. - */ - -int ejsCopyVar(EjsId eid, const char *var, MprVar *value, bool deepCopy) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprCopyProperty(value, vp, deepCopy); -} - -/******************************************************************************/ -/* - * Return the value of an object property. Return value is in "value". - * Objects and strings are not copied and reference counts are not modified. - * Callers should NOT call mprDestroyVar. Returns: -1 on errors or if the - * variable is not found. - */ - -int ejsReadVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - mprAssert(value); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, 0) < 0) { - return -1; - } - - return mprReadProperty(vp, value); -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVar(EjsId eid, const char *var, MprVar *value) -{ - Ejs *ep; - MprVar *vp; - - mprAssert(var && *var); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - - if (ejsGetVarCore(ep, var, 0, &vp, EJS_FLAGS_CREATE) < 0) { - return -1; - } - mprAssert(vp); - - /* - * Only copy the value. Don't overwrite the object's name - */ - mprWriteProperty(vp, value); - - return 0; -} - -/******************************************************************************/ -/* - * Set a variable that may be an arbitrarily complex object or array reference. - * Will always define in the top most variable frame. - */ - -int ejsWriteVarValue(EjsId eid, const char *var, MprVar value) -{ - return ejsWriteVar(eid, var, &value); -} - -/******************************************************************************/ -/* - * Delete a variable - */ - -int ejsDeleteVar(EjsId eid, const char *var) -{ - Ejs *ep; - MprVar *vp; - MprVar *obj; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return -1; - } - if (ejsGetVarCore(ep, var, &obj, &vp, 0) < 0) { - return -1; - } - mprDeleteProperty(obj, vp->name); - return 0; -} - -/******************************************************************************/ -/* - * Set the expression return value - */ - -void ejsSetReturnValue(EjsId eid, MprVar value) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVar(&ep->result, &value, MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Set the expression return value to a string value - */ - -void ejsSetReturnString(EjsId eid, const char *str) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - mprCopyVarValue(&ep->result, mprCreateStringVar(str, 0), MPR_SHALLOW_COPY); -} - -/******************************************************************************/ -/* - * Get the expression return value - */ - -MprVar *ejsGetReturnValue(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return &ep->result; -} - -/******************************************************************************/ -/* - * Define a C function. If eid < 0, then update the master object with this - * function. NOTE: in this case, functionName must be simple without any "." or - * "[]" elements. If eid >= 0, add to the specified script engine. In this - * case, functionName can be an arbitrary object reference and can contain "." - * or "[]". - */ - -void ejsDefineCFunction(EjsId eid, const char *functionName, MprCFunction fn, - void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a C function with String arguments - */ - -void ejsDefineStringCFunction(EjsId eid, const char *functionName, - MprStringCFunction fn, void *thisPtr, int flags) -{ - if (eid < 0) { - ejsLock(); - mprCreatePropertyValue(&master, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - ejsUnlock(); - } else { - ejsWriteVarValue(eid, functionName, - mprCreateStringCFunctionVar(fn, thisPtr, flags)); - } -} - -/******************************************************************************/ -/* - * Define a JavaScript function. Args should be comma separated. - * Body should not contain braces. - */ - -void ejsDefineFunction(EjsId eid, const char *functionName, char *args, - char *body) -{ - MprVar v; - - v = mprCreateFunctionVar(args, body, 0); - if (eid < 0) { - ejsLock(); - mprCreateProperty(&master, functionName, &v); - ejsUnlock(); - } else { - ejsWriteVar(eid, functionName, &v); - } - mprDestroyVar(&v); -} - -/******************************************************************************/ - -void *ejsGetThisPtr(EjsId eid) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return 0; - } - return ep->thisPtr; -} - -/******************************************************************************/ -/* - * Find a variable given a variable name and return the parent object and - * the variable itself, the variable . This routine supports variable names - * that may be objects or arrays but may NOT have expressions in the array - * indicies. Returns -1 on errors or if the variable is not found. - */ - -int ejsGetVarCore(Ejs *ep, const char *vname, MprVar **obj, - MprVar **varValue, int flags) -{ - MprVar *currentObj; - MprVar *currentVar; - char tokBuf[EJS_MAX_ID]; - char *propertyName, *token, *next, *cp, *varName; - - if (obj) { - *obj = 0; - } - if (varValue) { - *varValue = 0; - } - currentObj = ejsFindObj(ep, 0, vname, flags); - currentVar = 0; - propertyName = 0; - - next = varName = mprStrdup(vname); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - while (currentObj != 0 && token != 0 && *token) { - - if (*token == '[') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - - propertyName = token; - if (*propertyName == '\"') { - propertyName++; - if ((cp = strchr(propertyName, '\"')) != 0) { - *cp = '\0'; - } - } else if (*propertyName == '\'') { - propertyName++; - if ((cp = strchr(propertyName, '\'')) != 0) { - *cp = '\0'; - } - } - - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, propertyName, 0); - - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (*token != ']') { - mprFree(varName); - return -1; - } - - } else if (*token == '.') { - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - if (!isalpha((int) token[0]) && - token[0] != '_' && token[0] != '$') { - mprFree(varName); - return -1; - } - - propertyName = token; - currentObj = currentVar; - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - - } else { - currentVar = ejsFindProperty(ep, 0, currentObj, token, 0); - } - token = getNextVarToken(&next, tokBuf, sizeof(tokBuf)); - } - mprFree(varName); - - if (currentVar == 0 && currentObj >= 0 && flags & EJS_FLAGS_CREATE) { - currentVar = mprCreatePropertyValue(currentObj, propertyName, - mprCreateUndefinedVar()); - } - if (obj) { - *obj = currentObj; - } - - /* - * Don't use mprCopyVar as it will copy the data - */ - if (varValue) { - *varValue = currentVar; - } - return currentVar ? 0 : -1; -} - -/******************************************************************************/ -/* - * Get the next token as part of a variable specification. This will return - * a pointer to the next token and will return a pointer to the next token - * (after this one) in "next". The tokBuf holds the parsed token. - */ -static char *getNextVarToken(char **next, char *tokBuf, int tokBufLen) -{ - char *start, *cp; - int len; - - start = *next; - while (isspace((int) *start) || *start == '\n' || *start == '\r') { - start++; - } - cp = start; - - if (*cp == '.' || *cp == '[' || *cp == ']') { - cp++; - } else { - while (*cp && *cp != '.' && *cp != '[' && *cp != ']' && - !isspace((int) *cp) && *cp != '\n' && *cp != '\r') { - cp++; - } - } - len = mprMemcpy(tokBuf, tokBufLen - 1, start, cp - start); - tokBuf[len] = '\0'; - - *next = cp; - return tokBuf; -} - -/******************************************************************************/ -/* - * Get the EJS structure pointer - */ - -Ejs *ejsPtr(EjsId eid) -{ - Ejs *handle; - int intId; - - intId = (int) eid; - - ejsLock(); - mprAssert(0 <= intId && intId < ejsList->max); - - if (intId < 0 || intId >= ejsList->max || ejsList->handles[intId] == NULL) { - mprAssert(0); - ejsUnlock(); - return NULL; - } - handle = ejsList->handles[intId]; - ejsUnlock(); - return handle; -} - -/******************************************************************************/ -/* - * Utility routine to crack JavaScript arguments. Return the number of args - * seen. This routine only supports %s and %d type args. - * - * Typical usage: - * - * if (ejsParseArgs(argc, argv, "%s %d", &name, &age) < 2) { - * mprError("Insufficient args\n"); - * return -1; - * } - */ - -int ejsParseArgs(int argc, char **argv, char *fmt, ...) -{ - va_list vargs; - bool *bp; - char *cp, **sp, *s; - int *ip, argn; - - va_start(vargs, fmt); - - if (argv == 0) { - return 0; - } - - for (argn = 0, cp = fmt; cp && *cp && argn < argc && argv[argn]; ) { - if (*cp++ != '%') { - continue; - } - - s = argv[argn]; - switch (*cp) { - case 'b': - bp = va_arg(vargs, bool*); - if (bp) { - if (strcmp(s, "true") == 0 || s[0] == '1') { - *bp = 1; - } else { - *bp = 0; - } - } else { - *bp = 0; - } - break; - - case 'd': - ip = va_arg(vargs, int*); - *ip = atoi(s); - break; - - case 's': - sp = va_arg(vargs, char**); - *sp = s; - break; - - default: - mprAssert(0); - } - argn++; - } - - va_end(vargs); - return argn; -} - -/******************************************************************************/ - -#else -void ejsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/******************************************************************************/ -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsParser.c b/source4/lib/appweb/ejs/ejsParser.c deleted file mode 100644 index da922a5728..0000000000 --- a/source4/lib/appweb/ejs/ejsParser.c +++ /dev/null @@ -1,2436 +0,0 @@ -/* - * @file ejsParser.c - * @brief EJS Parser and Execution - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ - -static void appendValue(MprVar *v1, MprVar *v2); -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -#if BLD_FEATURE_FLOATING_POINT -static int evalFloatExpr(Ejs *ep, double l, int rel, double r); -#endif -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r); -static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r); -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r); -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs); -static int evalFunction(Ejs *ep, MprVar *obj, int flags); -static void freeProc(EjsProc *proc); -static int parseArgs(Ejs *ep, int state, int flags); -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName); -static int parseCond(Ejs *ep, int state, int flags); -static int parseDeclaration(Ejs *ep, int state, int flags); -static int parseExpr(Ejs *ep, int state, int flags); -static int parseFor(Ejs *ep, int state, int flags); -static int parseForIn(Ejs *ep, int state, int flags); -static int parseFunctionDec(Ejs *ep, int state, int flags); -static int parseFunction(Ejs *ep, int state, int flags, char *id); -static int parseId(Ejs *ep, int state, int flags, char **id, - char **fullName, int *fullNameLen, int *done); -static int parseInc(Ejs *ep, int state, int flags); -static int parseIf(Ejs *ep, int state, int flags, int *done); -static int parseStmt(Ejs *ep, int state, int flags); -static void removeNewlines(Ejs *ep, int state); -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp); - -/************************************* Code ***********************************/ -/* - * Recursive descent parser for EJS - */ - -int ejsParse(Ejs *ep, int state, int flags) -{ - mprAssert(ep); - - switch (state) { - /* - * Any statement, function arguments or conditional expressions - */ - case EJS_STATE_STMT: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_STMT_DONE && - state != EJS_STATE_EOF && state != EJS_STATE_STMT_BLOCK_DONE && - state != EJS_STATE_RET) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_DEC: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_DEC_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - case EJS_STATE_EXPR: - if ((state = parseStmt(ep, state, flags)) != EJS_STATE_EXPR_DONE && - state != EJS_STATE_EOF) { - state = EJS_STATE_ERR; - } - break; - - /* - * Variable declaration list - */ - case EJS_STATE_DEC_LIST: - state = parseDeclaration(ep, state, flags); - break; - - /* - * Function argument string - */ - case EJS_STATE_ARG_LIST: - state = parseArgs(ep, state, flags); - break; - - /* - * Logical condition list (relational operations separated by &&, ||) - */ - case EJS_STATE_COND: - state = parseCond(ep, state, flags); - break; - - /* - * Expression list - */ - case EJS_STATE_RELEXP: - state = parseExpr(ep, state, flags); - break; - } - - if (state == EJS_STATE_ERR && ep->error == NULL) { - ejsError(ep, "Syntax error"); - } - return state; -} - -/******************************************************************************/ -/* - * Parse any statement including functions and simple relational operations - */ - -static int parseStmt(Ejs *ep, int state, int flags) -{ - EjsProc *saveProc; - MprVar *vp, *saveObj; - char *id, *fullName, *initToken; - int done, expectSemi, tid, fullNameLen, rel; - int initId; - - mprAssert(ep); - - expectSemi = 0; - saveProc = NULL; - id = 0; - fullName = 0; - fullNameLen = 0; - - ep->currentObj = 0; - ep->currentProperty = 0; - - for (done = 0; !done && state != EJS_STATE_ERR; ) { - tid = ejsLexGetToken(ep, state); - - switch (tid) { - default: - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - done++; - break; - - case EJS_TOK_EXPR: - rel = (int) *ep->token; - if (state == EJS_STATE_EXPR) { - ejsLexPutbackToken(ep, EJS_TOK_EXPR, ep->token); - } - done++; - break; - - case EJS_TOK_LOGICAL: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_ERR: - state = EJS_STATE_ERR; - done++; - break; - - case EJS_TOK_EOF: - state = EJS_STATE_EOF; - done++; - break; - - case EJS_TOK_NEWLINE: - break; - - case EJS_TOK_SEMI: - /* - * This case is when we discover no statement and just a lone ';' - */ - if (state != EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - } - done++; - break; - - case EJS_TOK_PERIOD: - if (flags & EJS_FLAGS_EXE) { - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined object \"%s\"\n", id); - goto error; - } - } - ep->currentObj = ep->currentProperty; - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - ejsError(ep, "Bad property after '.': %s\n", ep->token); - goto error; - } - mprFree(id); - id = mprStrdup(ep->token); - - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - updateResult(ep, state, flags, vp); - -#if BLD_DEBUG - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, fullNameLen, - 0, ".", NULL); -#endif - - ep->currentProperty = vp; - ejsLexPutbackToken(ep, tid, ep->token); - break; - - case EJS_TOK_LBRACKET: - ep->currentObj = ep->currentProperty; - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_RELEXP, flags) != EJS_STATE_RELEXP_DONE){ - goto error; - } - ep->currentObj = saveObj; - - mprFree(id); - mprVarToString(&id, MPR_MAX_STRING, 0, &ep->result); - - if (id[0] == '\0') { - if (flags & EJS_FLAGS_EXE) { - ejsError(ep, - "[] expression evaluates to the empty string\n"); - goto error; - } - } else { - vp = ejsFindProperty(ep, state, ep->currentObj, id, flags); - ep->currentProperty = vp; - updateResult(ep, state, flags, vp); - } - -#if BLD_DEBUG - if (id[0] && strlen(id) < (MPR_MAX_VAR / 2)) { - /* - * If not executing yet, id may not be known - */ - fullNameLen = mprReallocStrcat(&fullName, MPR_MAX_VAR, - fullNameLen, 0, "[", id, "]", NULL); - } -#endif - - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_RBRACKET) { - ejsError(ep, "Missing ']'\n"); - goto error; - } - break; - - case EJS_TOK_ID: - state = parseId(ep, state, flags, &id, &fullName, &fullNameLen, - &done); - if (done && state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_ASSIGNMENT: - state = parseAssignment(ep, state, flags, id, fullName); - if (state == EJS_STATE_STMT) { - expectSemi++; - done++; - } - break; - - case EJS_TOK_INC_DEC: - state = parseInc(ep, state, flags); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - break; - - case EJS_TOK_NEW: - if (ejsParse(ep, EJS_STATE_EXPR, flags | EJS_FLAGS_NEW) - != EJS_STATE_EXPR_DONE) { - goto error; - } - break; - - case EJS_TOK_DELETE: - if (ejsParse(ep, EJS_STATE_EXPR, - flags | EJS_FLAGS_DELETE) != EJS_STATE_EXPR_DONE) { - goto error; - } - if (flags & EJS_FLAGS_EXE) { - mprDeleteProperty(ep->currentObj, ep->currentProperty->name); - } - done++; - break; - - case EJS_TOK_FUNCTION: - state = parseFunctionDec(ep, state, flags); - done++; - break; - - case EJS_TOK_LITERAL: - /* - * Set the result to the string literal - */ - mprCopyVarValue(&ep->result, mprCreateStringVar(ep->token, 0), - MPR_SHALLOW_COPY); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_NUMBER: - /* - * Set the result to the parsed number - */ - mprCopyVar(&ep->result, &ep->tokenNumber, 0); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - done++; - break; - - case EJS_TOK_FUNCTION_NAME: - state = parseFunction(ep, state, flags, id); - if (state == EJS_STATE_STMT) { - expectSemi++; - } - if (ep->flags & EJS_FLAGS_EXIT) { - state = EJS_STATE_RET; - } - done++; - break; - - case EJS_TOK_IF: - state = parseIf(ep, state, flags, &done); - if (state == EJS_STATE_RET) { - goto doneParse; - } - break; - - case EJS_TOK_FOR: - if (state != EJS_STATE_STMT) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - goto error; - } - /* - * Need to peek 2-3 tokens ahead and see if this is a - * for ([var] x in set) - * or - * for (init ; whileCond; incr) - */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - if (initId == EJS_TOK_ID && strcmp(ep->token, "var") == 0) { - /* Simply eat var tokens */ - initId = ejsLexGetToken(ep, EJS_STATE_EXPR); - } - initToken = mprStrdup(ep->token); - - tid = ejsLexGetToken(ep, EJS_STATE_EXPR); - - ejsLexPutbackToken(ep, tid, ep->token); - ejsLexPutbackToken(ep, initId, initToken); - mprFree(initToken); - - if (tid == EJS_TOK_IN) { - if ((state = parseForIn(ep, state, flags)) < 0) { - goto error; - } - } else { - if ((state = parseFor(ep, state, flags)) < 0) { - goto error; - } - } - done++; - break; - - case EJS_TOK_VAR: - if (ejsParse(ep, EJS_STATE_DEC_LIST, flags) - != EJS_STATE_DEC_LIST_DONE) { - goto error; - } - done++; - break; - - case EJS_TOK_COMMA: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LPAREN: - if (state == EJS_STATE_EXPR) { - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - } - done++; - break; - - case EJS_TOK_RPAREN: - ejsLexPutbackToken(ep, tid, ep->token); - done++; - break; - - case EJS_TOK_LBRACE: - /* - * This handles any code in braces except "if () {} else {}" - */ - if (state != EJS_STATE_STMT) { - goto error; - } - - /* - * Parse will return EJS_STATE_STMT_BLOCK_DONE when the RBRACE - * is seen. - */ - do { - state = ejsParse(ep, EJS_STATE_STMT, flags); - } while (state == EJS_STATE_STMT_DONE); - - if (state != EJS_STATE_RET) { - if (ejsLexGetToken(ep, state) != EJS_TOK_RBRACE) { - goto error; - } - state = EJS_STATE_STMT_DONE; - } - done++; - break; - - case EJS_TOK_RBRACE: - if (state == EJS_STATE_STMT) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_STMT_BLOCK_DONE; - done++; - break; - } - goto error; - - case EJS_TOK_RETURN: - if (ejsParse(ep, EJS_STATE_RELEXP, flags) - != EJS_STATE_RELEXP_DONE) { - goto error; - } - if (flags & EJS_FLAGS_EXE) { - while (ejsLexGetToken(ep, state) != EJS_TOK_EOF) { - ; - } - state = EJS_STATE_RET; - done++; - } - break; - } - } - - if (expectSemi) { - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_SEMI && tid != EJS_TOK_NEWLINE && - tid != EJS_TOK_EOF) { - goto error; - } - - /* - * Skip newline after semi-colon - */ - removeNewlines(ep, state); - } - -/* - * Free resources and return the correct status - */ -doneParse: - mprFree(id); - mprFree(fullName); - - /* - * Advance the state - */ - switch (state) { - case EJS_STATE_STMT: - return EJS_STATE_STMT_DONE; - - case EJS_STATE_DEC: - return EJS_STATE_DEC_DONE; - - case EJS_STATE_EXPR: - return EJS_STATE_EXPR_DONE; - - case EJS_STATE_STMT_DONE: - case EJS_STATE_STMT_BLOCK_DONE: - case EJS_STATE_EOF: - case EJS_STATE_RET: - return state; - - default: - return EJS_STATE_ERR; - } - -/* - * Common error exit - */ -error: - state = EJS_STATE_ERR; - goto doneParse; -} - -/******************************************************************************/ -/* - * Parse function arguments - */ - -static int parseArgs(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - /* - * Peek and see if there are no args - */ - tid = ejsLexGetToken(ep, state); - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RPAREN) { - break; - } - - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state == EJS_STATE_EOF || state == EJS_STATE_ERR) { - return state; - } - if (state == EJS_STATE_RELEXP_DONE) { - if (flags & EJS_FLAGS_EXE) { - mprAssert(ep->proc->args); - mprAddToArray(ep->proc->args, - mprDupVar(&ep->result, MPR_SHALLOW_COPY)); - } - } - /* - * Peek at the next token, continue if more args (ie. comma seen) - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_COMMA) { - ejsLexPutbackToken(ep, tid, ep->token); - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_RPAREN && state != EJS_STATE_RELEXP_DONE) { - return EJS_STATE_ERR; - } - return EJS_STATE_ARG_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse an assignment statement - */ - -static int parseAssignment(Ejs *ep, int state, int flags, char *id, - char *fullName) -{ - MprVar *vp, *saveProperty, *saveObj; - - if (id == 0) { - return -1; - } - - saveObj = ep->currentObj; - saveProperty = ep->currentProperty; - if (ejsParse(ep, EJS_STATE_RELEXP, flags | EJS_FLAGS_ASSIGNMENT) - != EJS_STATE_RELEXP_DONE) { - return -1; - } - ep->currentObj = saveObj; - ep->currentProperty = saveProperty; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty) { - /* - * Update the variable. Update the property name if not - * yet defined. - */ - if (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0') { - mprSetVarName(ep->currentProperty, id); - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0){ - ejsError(ep, "Can't write to variable\n"); - return -1; - } - - } else { - /* - * Create the variable - */ - if (ep->currentObj) { - if (ep->currentObj->type != MPR_TYPE_OBJECT) { - if (strcmp(ep->currentObj->name, "session") == 0) { - ejsError(ep, "Variable \"%s\" is not an array or object." - "If using ESP, you need useSession(); in your page.", - ep->currentObj->name); - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - ep->currentObj->name); - } - return -1; - } - vp = mprCreateProperty(ep->currentObj, id, &ep->result); - - } else { - /* - * Standard says: "var x" means declare locally. - * "x = 2" means declare globally if x is undefined. - */ - if (state == EJS_STATE_DEC) { - vp = mprCreateProperty(ep->local, id, &ep->result); - } else { - vp = mprCreateProperty(ep->global, id, &ep->result); - } - } -#if BLD_DEBUG - mprSetVarFullName(vp, fullName); -#endif - } - return state; -} - -/******************************************************************************/ -/* - * Parse conditional expression (relational ops separated by ||, &&) - */ - -static int parseCond(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int tid, operator; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - operator = 0; - - do { - /* - * Recurse to handle one side of a conditional. Accumulate the - * left hand side and the final result in ep->result. - */ - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - - if (operator > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (evalCond(ep, &lhs, operator, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LOGICAL) { - operator = (int) *ep->token; - - } else if (tid == EJS_TOK_RPAREN || tid == EJS_TOK_SEMI) { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_COND_DONE; - break; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - tid = (state == EJS_STATE_RELEXP_DONE); - - } while (state == EJS_STATE_RELEXP_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - return state; -} - -/******************************************************************************/ -/* - * Parse variable declaration list. Declarations can be of the following forms: - * var x; - * var x, y, z; - * var x = 1 + 2 / 3, y = 2 + 4; - * - * We set the variable to NULL if there is no associated assignment. - */ - -static int parseDeclaration(Ejs *ep, int state, int flags) -{ - int tid; - - mprAssert(ep); - - do { - if ((tid = ejsLexGetToken(ep, state)) != EJS_TOK_ID) { - return EJS_STATE_ERR; - } - ejsLexPutbackToken(ep, tid, ep->token); - - /* - * Parse the entire assignment or simple identifier declaration - */ - if (ejsParse(ep, EJS_STATE_DEC, flags) != EJS_STATE_DEC_DONE) { - return EJS_STATE_ERR; - } - - /* - * Peek at the next token, continue if comma seen - */ - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_SEMI) { - return EJS_STATE_DEC_LIST_DONE; - } else if (tid != EJS_TOK_COMMA) { - return EJS_STATE_ERR; - } - } while (tid == EJS_TOK_COMMA); - - if (tid != EJS_TOK_SEMI) { - return EJS_STATE_ERR; - } - return EJS_STATE_DEC_LIST_DONE; -} - -/******************************************************************************/ -/* - * Parse expression (leftHandSide operator rightHandSide) - */ - -static int parseExpr(Ejs *ep, int state, int flags) -{ - MprVar lhs, rhs; - int rel, tid; - - mprAssert(ep); - - mprDestroyVar(&ep->result); - rhs = lhs = mprCreateUndefinedVar(); - rel = 0; - tid = 0; - - do { - /* - * This loop will handle an entire expression list. We call parse - * to evalutate each term which returns the result in ep->result. - */ - if (tid == EJS_TOK_LOGICAL) { - state = ejsParse(ep, EJS_STATE_RELEXP, flags); - if (state != EJS_STATE_RELEXP_DONE) { - state = EJS_STATE_ERR; - break; - } - } else { - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_EXPR && (int) *ep->token == EJS_EXPR_MINUS) { - lhs = mprCreateIntegerVar(0); - rel = (int) *ep->token; - } else { - ejsLexPutbackToken(ep, tid, ep->token); - } - - state = ejsParse(ep, EJS_STATE_EXPR, flags); - if (state != EJS_STATE_EXPR_DONE) { - state = EJS_STATE_ERR; - break; - } - } - - if (rel > 0) { - mprCopyVar(&rhs, &ep->result, MPR_SHALLOW_COPY); - if (tid == EJS_TOK_LOGICAL) { - if (evalCond(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } else { - if (evalExpr(ep, &lhs, rel, &rhs) < 0) { - state = EJS_STATE_ERR; - break; - } - } - } - mprCopyVar(&lhs, &ep->result, MPR_SHALLOW_COPY); - - if ((tid = ejsLexGetToken(ep, state)) == EJS_TOK_EXPR || - tid == EJS_TOK_INC_DEC || tid == EJS_TOK_LOGICAL) { - rel = (int) *ep->token; - - } else { - ejsLexPutbackToken(ep, tid, ep->token); - state = EJS_STATE_RELEXP_DONE; - } - - } while (state == EJS_STATE_EXPR_DONE); - - mprDestroyVar(&lhs); - mprDestroyVar(&rhs); - - return state; -} - -/******************************************************************************/ -/* - * Parse the "for ... in" statement. Format for the statement is: - * - * for (var in expr) { - * body; - * } - */ - -static int parseForIn(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar *iteratorVar, *setVar, *vp, v; - int forFlags, tid; - - mprAssert(ep); - - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, EJS_FLAGS_FOREACH | EJS_FLAGS_EXE) - != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0) { - return -1; - } - iteratorVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_IN) { - return -1; - } - - /* - * Get the set - */ - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ID) { - return -1; - } - ejsLexPutbackToken(ep, tid, ep->token); - - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ep->currentProperty == 0 && flags & EJS_FLAGS_EXE) { - return -1; - } - setVar = ep->currentProperty; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * Parse the body and remember the end of the body script - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - ejsInitInputState(&endScript); - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. - */ - if (flags & EJS_FLAGS_EXE) { - if (setVar->type == MPR_TYPE_OBJECT) { - vp = mprGetFirstProperty(setVar, MPR_ENUM_DATA); - while (vp) { - if (strcmp(vp->name, "length") != 0) { - v = mprCreateStringVar(vp->name, 0); - if (mprWriteProperty(iteratorVar, &v) < 0) { - ejsError(ep, "Can't write to variable\n"); - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - return -1; - } - - ejsLexRestoreInputState(ep, &bodyScript); - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - vp = mprGetNextProperty(setVar, vp, MPR_ENUM_DATA); - } - } else { - ejsError(ep, "Variable \"%s\" is not an array or object", - setVar->name); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return -1; - } - } - ejsLexRestoreInputState(ep, &endScript); - - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - - return state; -} - -/******************************************************************************/ -/* - * Parse the for statement. Format for the expression is: - * - * for (initial; condition; incr) { - * body; - * } - */ - -static int parseFor(Ejs *ep, int state, int flags) -{ - EjsInput condScript, endScript, bodyScript, incrScript; - int forFlags, cond; - - ejsInitInputState(&endScript); - ejsInitInputState(&bodyScript); - ejsInitInputState(&incrScript); - ejsInitInputState(&condScript); - - mprAssert(ep); - - /* - * Evaluate the for loop initialization statement - */ - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - return -1; - } - - /* - * The first time through, we save the current input context just prior - * to each step: prior to the conditional, the loop increment and - * the loop body. - */ - ejsLexSaveInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - cond = (ep->result.boolean != 0); - - if (ejsLexGetToken(ep, state) != EJS_TOK_SEMI) { - goto error; - } - - /* - * Don't execute the loop increment statement or the body - * first time. - */ - forFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, forFlags) != EJS_STATE_EXPR_DONE) { - goto error; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - goto error; - } - - /* - * Parse the body and remember the end of the body script - */ - ejsLexSaveInputState(ep, &bodyScript); - if (ejsParse(ep, EJS_STATE_STMT, forFlags) != EJS_STATE_STMT_DONE) { - goto error; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Now actually do the for loop. Note loop has been rotated - */ - while (cond && (flags & EJS_FLAGS_EXE)) { - /* - * Evaluate the body - */ - ejsLexRestoreInputState(ep, &bodyScript); - - switch (ejsParse(ep, EJS_STATE_STMT, flags)) { - case EJS_STATE_RET: - return EJS_STATE_RET; - case EJS_STATE_STMT_DONE: - break; - default: - goto error; - } - /* - * Evaluate the increment script - */ - ejsLexRestoreInputState(ep, &incrScript); - if (ejsParse(ep, EJS_STATE_EXPR, flags) != EJS_STATE_EXPR_DONE){ - goto error; - } - /* - * Evaluate the condition - */ - ejsLexRestoreInputState(ep, &condScript); - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - goto error; - } - mprAssert(ep->result.type == MPR_TYPE_BOOL); - cond = (ep->result.boolean != 0); - } - - ejsLexRestoreInputState(ep, &endScript); - -done: - ejsLexFreeInputState(ep, &condScript); - ejsLexFreeInputState(ep, &incrScript); - ejsLexFreeInputState(ep, &endScript); - ejsLexFreeInputState(ep, &bodyScript); - return state; - -error: - state = EJS_STATE_ERR; - goto done; -} - -/******************************************************************************/ -/* - * Parse a function declaration - */ - -static int parseFunctionDec(Ejs *ep, int state, int flags) -{ - EjsInput endScript, bodyScript; - MprVar v, *currentObj, *vp; - char *procName; - int len, tid, bodyFlags; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - /* - * function <name>(arg, arg, arg) { body }; - * function name(arg, arg, arg) { body }; - */ - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_ID) { - procName = mprStrdup(ep->token); - tid = ejsLexGetToken(ep, state); - } else { - procName = 0; - } - if (tid != EJS_TOK_LPAREN) { - mprFree(procName); - return EJS_STATE_ERR; - } - - /* - * Hand craft the function value structure. - */ - v = mprCreateFunctionVar(0, 0, 0); - tid = ejsLexGetToken(ep, state); - while (tid == EJS_TOK_ID) { - mprAddToArray(v.function.args, mprStrdup(ep->token)); - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_RPAREN || tid != EJS_TOK_COMMA) { - break; - } - tid = ejsLexGetToken(ep, state); - } - if (tid != EJS_TOK_RPAREN) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* Allow new lines before opening brace */ - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - if (tid != EJS_TOK_LBRACE) { - mprFree(procName); - mprDestroyVar(&v); - return EJS_STATE_ERR; - } - - /* - * Register the function name early to allow for recursive - * function calls (see note in ECMA standard, page 71) - */ - if (!(flags & EJS_FLAGS_ASSIGNMENT)) { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - /* - * Parse the function body. Turn execute off. - */ - bodyFlags = flags & ~EJS_FLAGS_EXE; - ejsLexSaveInputState(ep, &bodyScript); - - do { - state = ejsParse(ep, EJS_STATE_STMT, bodyFlags); - } while (state == EJS_STATE_STMT_DONE); - - tid = ejsLexGetToken(ep, state); - if (state != EJS_STATE_STMT_BLOCK_DONE || tid != EJS_TOK_RBRACE) { - mprFree(procName); - mprDestroyVar(&v); - ejsLexFreeInputState(ep, &bodyScript); - return EJS_STATE_ERR; - } - ejsLexSaveInputState(ep, &endScript); - - /* - * Save the function body between the starting and ending parse positions. - * Overwrite the trailing '}' with a null. - */ - len = endScript.scriptServp - bodyScript.scriptServp; - v.function.body = mprMalloc(len + 1); - memcpy(v.function.body, bodyScript.scriptServp, len); - - if (len <= 0) { - v.function.body[0] = '\0'; - } else { - v.function.body[len - 1] = '\0'; - } - ejsLexFreeInputState(ep, &bodyScript); - ejsLexFreeInputState(ep, &endScript); - - /* - * If we are in an assignment, don't register the function name, rather - * return the function structure in the parser result. - */ - if (flags & EJS_FLAGS_ASSIGNMENT) { - mprCopyVar(&ep->result, &v, MPR_SHALLOW_COPY); - } else { - currentObj = ejsFindObj(ep, 0, procName, flags); - vp = mprSetProperty(currentObj, procName, &v); - } - - mprFree(procName); - mprDestroyVar(&v); - - return EJS_STATE_STMT; -} - -/******************************************************************************/ -/* - * Parse a function name and invoke the function - */ - -static int parseFunction(Ejs *ep, int state, int flags, char *id) -{ - EjsProc proc, *saveProc; - MprVar *saveObj; - - /* - * Must save any current ep->proc value for the current stack frame - * to allow for recursive function calls. - */ - saveProc = (ep->proc) ? ep->proc: 0; - - memset(&proc, 0, sizeof(EjsProc)); - proc.procName = mprStrdup(id); - proc.fn = ep->currentProperty; - proc.args = mprCreateArray(); - ep->proc = &proc; - - mprDestroyVar(&ep->result); - - saveObj = ep->currentObj; - if (ejsParse(ep, EJS_STATE_ARG_LIST, flags) != EJS_STATE_ARG_LIST_DONE) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - ep->currentObj = saveObj; - - /* - * Evaluate the function if required - */ - if (flags & EJS_FLAGS_EXE) { - if (evalFunction(ep, ep->currentObj, flags) < 0) { - freeProc(&proc); - ep->proc = saveProc; - return -1; - } - } - - freeProc(&proc); - ep->proc = saveProc; - - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an identifier. This is a segment of a fully qualified variable. - * May come here for an initial identifier or for property names - * after a "." or "[...]". - */ - -static int parseId(Ejs *ep, int state, int flags, char **id, char **fullName, - int *fullNameLen, int *done) -{ - int tid; - - mprFree(*id); - *id = mprStrdup(ep->token); -#if BLD_DEBUG - *fullNameLen = mprReallocStrcat(fullName, MPR_MAX_VAR, *fullNameLen, - 0, *id, NULL); -#endif - if (ep->currentObj == 0) { - ep->currentObj = ejsFindObj(ep, state, *id, flags); - } - - /* - * Find the referenced variable and store it in currentProperty. - */ - ep->currentProperty = ejsFindProperty(ep, state, ep->currentObj, - *id, flags); - updateResult(ep, state, flags, ep->currentProperty); - -#if BLD_DEBUG - if (ep->currentProperty && (ep->currentProperty->name == 0 || - ep->currentProperty->name[0] == '\0')) { - mprSetVarName(ep->currentProperty, *id); - } -#endif - - tid = ejsLexGetToken(ep, state); - if (tid == EJS_TOK_LPAREN) { - if (ep->currentProperty == 0 && (flags & EJS_FLAGS_EXE)) { - ejsError(ep, "Function name not defined \"%s\"\n", *id); - return -1; - } - ejsLexPutbackToken(ep, EJS_TOK_FUNCTION_NAME, ep->token); - return state; - } - - if (tid == EJS_TOK_PERIOD || tid == EJS_TOK_LBRACKET || - tid == EJS_TOK_ASSIGNMENT || tid == EJS_TOK_INC_DEC) { - ejsLexPutbackToken(ep, tid, ep->token); - return state; - } - - /* - * Only come here for variable access and declarations. - * Assignment handled elsewhere. - */ - if (flags & EJS_FLAGS_EXE) { - if (state == EJS_STATE_DEC) { - /* - * Declare a variable. Standard allows: var x ; var x ; - */ -#if DISABLED - if (ep->currentProperty != 0) { - ejsError(ep, "Variable already defined \"%s\"\n", *id); - return -1; - } -#endif - /* - * Create or overwrite if it already exists - */ - mprSetPropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - ep->currentProperty = 0; - mprDestroyVar(&ep->result); - - } else if (flags & EJS_FLAGS_FOREACH) { - if (ep->currentProperty == 0) { - ep->currentProperty = - mprCreatePropertyValue(ep->currentObj, *id, - mprCreateUndefinedVar()); - } - - } else { - if (ep->currentProperty == 0) { - if (ep->currentObj == ep->global || - ep->currentObj == ep->local) { - ejsError(ep, "Undefined variable \"%s\"\n", *id); - return -1; - } - ep->currentProperty = mprCreatePropertyValue(ep->currentObj, - *id, mprCreateUndefinedVar()); - } - } - } - ejsLexPutbackToken(ep, tid, ep->token); - if (tid == EJS_TOK_RBRACKET || tid == EJS_TOK_COMMA || - tid == EJS_TOK_IN) { - *done = 1; - } - return state; -} - -/******************************************************************************/ -/* - * Parse an "if" statement - */ - -static int parseIf(Ejs *ep, int state, int flags, int *done) -{ - bool ifResult; - int thenFlags, elseFlags, tid; - - if (state != EJS_STATE_STMT) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_LPAREN) { - return -1; - } - - /* - * Evaluate the entire condition list "(condition)" - */ - if (ejsParse(ep, EJS_STATE_COND, flags) != EJS_STATE_COND_DONE) { - return -1; - } - if (ejsLexGetToken(ep, state) != EJS_TOK_RPAREN) { - return -1; - } - - /* - * This is the "then" case. We need to always parse both cases and - * execute only the relevant case. - */ - ifResult = mprVarToBool(&ep->result); - if (ifResult) { - thenFlags = flags; - elseFlags = flags & ~EJS_FLAGS_EXE; - } else { - thenFlags = flags & ~EJS_FLAGS_EXE; - elseFlags = flags; - } - - /* - * Process the "then" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, thenFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - - /* - * Check to see if there is an "else" case - */ - removeNewlines(ep, state); - tid = ejsLexGetToken(ep, state); - if (tid != EJS_TOK_ELSE) { - ejsLexPutbackToken(ep, tid, ep->token); - *done = 1; - return state; - } - - /* - * Process the "else" case. - */ - switch (ejsParse(ep, EJS_STATE_STMT, elseFlags)) { - case EJS_STATE_RET: - state = EJS_STATE_RET; - return state; - case EJS_STATE_STMT_DONE: - break; - default: - return -1; - } - *done = 1; - return state; -} - -/******************************************************************************/ -/* - * Parse an "++" or "--" statement - */ - -static int parseInc(Ejs *ep, int state, int flags) -{ - MprVar one; - - if (! (flags & EJS_FLAGS_EXE)) { - return state; - } - - if (ep->currentProperty == 0) { - ejsError(ep, "Undefined variable \"%s\"\n", ep->token); - return -1; - } - one = mprCreateIntegerVar(1); - if (evalExpr(ep, ep->currentProperty, (int) *ep->token, - &one) < 0) { - return -1; - } - if (mprWriteProperty(ep->currentProperty, &ep->result) < 0) { - ejsError(ep, "Can't write to variable\n"); - return -1; - } - return state; -} - -/******************************************************************************/ -/* - * Evaluate a condition. Implements &&, ||, !. Returns with a boolean result - * in ep->result. Returns -1 on errors, zero if successful. - */ - -static int evalCond(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - bool l, r, lval; - - mprAssert(rel > 0); - - l = mprVarToBool(lhs); - r = mprVarToBool(rhs); - - switch (rel) { - case EJS_COND_AND: - lval = l && r; - break; - case EJS_COND_OR: - lval = l || r; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - - -/* - return true if this string is a valid number -*/ -static int string_is_number(const char *s) -{ - char *endptr = NULL; - if (s == NULL || *s == 0) { - return 0; - } - strtod(s, &endptr); - if (endptr != NULL && *endptr == 0) { - return 1; - } - return 0; -} - -/******************************************************************************/ -/* - * Evaluate an operation. Returns with the result in ep->result. Returns -1 - * on errors, otherwise zero is returned. - */ - -static int evalExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - char *str; - MprNum lval, num; - int rc; - - mprAssert(rel > 0); - str = 0; - lval = 0; - - /* - * Type conversion. This is tricky and must be according to the standard. - * Only numbers (including floats) and strings can be compared. All other - * types are first converted to numbers by preference and if that fails, - * to strings. - * - * First convert objects to comparable types. The "===" operator will - * test the sameness of object references. Here, we coerce to comparable - * types first. - */ - if (lhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, lhs, "toValue", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, lhs, "toString", 0) == 0) { - mprCopyVar(lhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - if (rhs->type == MPR_TYPE_OBJECT) { - if (ejsRunFunction(ep->eid, rhs, "toValue", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } else { - if (ejsRunFunction(ep->eid, rhs, "toString", 0) == 0) { - mprCopyVar(rhs, &ep->result, MPR_SHALLOW_COPY); - } - } - /* Nothing more can be done */ - } - - /* undefined and null are special, in that they don't get promoted when - comparing */ - if (rel == EJS_EXPR_EQ || rel == EJS_EXPR_NOTEQ) { - if (lhs->type == MPR_TYPE_UNDEFINED || rhs->type == MPR_TYPE_UNDEFINED) { - return evalBoolExpr(ep, - lhs->type == MPR_TYPE_UNDEFINED, - rel, - rhs->type == MPR_TYPE_UNDEFINED); - } - - if (lhs->type == MPR_TYPE_NULL || rhs->type == MPR_TYPE_NULL) { - return evalBoolExpr(ep, - lhs->type == MPR_TYPE_NULL, - rel, - rhs->type == MPR_TYPE_NULL); - } - } - - /* - * From here on, lhs and rhs may contain allocated data (strings), so - * we must always destroy before overwriting. - */ - - /* - * Only allow a few bool operations. Otherwise convert to number. - */ - if (lhs->type == MPR_TYPE_BOOL && rhs->type == MPR_TYPE_BOOL && - (rel != EJS_EXPR_EQ && rel != EJS_EXPR_NOTEQ && - rel != EJS_EXPR_BOOL_COMP)) { - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - } - - /* - * Types do not match, so try to coerce the right operand to match the left - * But first, try to convert a left operand that is a numeric stored as a - * string, into a numeric. - */ - if (lhs->type != rhs->type) { - if (lhs->type == MPR_TYPE_STRING) { - if (string_is_number(lhs->string)) { - num = mprVarToNumber(lhs); - lhs->allocatedVar = 0; - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - /* Examine further below */ - - } else { - /* - * Convert the RHS to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, rhs); - rhs->allocatedVar = 0; - mprDestroyVar(rhs); - *rhs = mprCreateStringVar(str, 1); - mprFree(str); - } - -#if BLD_FEATURE_FLOATING_POINT - } else if (lhs->type == MPR_TYPE_FLOAT) { - /* - * Convert rhs to floating - */ - double f = mprVarToFloat(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateFloatVar(f); - -#endif -#if BLD_FEATURE_INT64 - } else if (lhs->type == MPR_TYPE_INT64) { - /* - * Convert the rhs to 64 bit - */ - int64 n = mprVarToInteger64(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateInteger64Var(n); -#endif - } else if (lhs->type == MPR_TYPE_BOOL || lhs->type == MPR_TYPE_INT) { - - if (rhs->type == MPR_TYPE_STRING) { - /* - * Convert to lhs to a string - */ - mprVarToString(&str, MPR_MAX_STRING, 0, lhs); - mprDestroyVar(lhs); - *lhs = mprCreateStringVar(str, 1); - mprFree(str); - -#if BLD_FEATURE_FLOATING_POINT - } else if (rhs->type == MPR_TYPE_FLOAT) { - /* - * Convert lhs to floating - */ - double f = mprVarToFloat(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateFloatVar(f); -#endif - - } else { - /* - * Convert both operands to numbers - */ - num = mprVarToNumber(lhs); - mprDestroyVar(lhs); - *lhs = mprCreateNumberVar(num); - - num = mprVarToNumber(rhs); - mprDestroyVar(rhs); - *rhs = mprCreateNumberVar(num); - } - } - } - - /* - * We have failed to coerce the types to be the same. Special case here - * for undefined and null. We need to allow comparisions against these - * special values. - */ - if (lhs->type == MPR_TYPE_UNDEFINED || lhs->type == MPR_TYPE_NULL) { - switch (rel) { - case EJS_EXPR_EQ: - lval = lhs->type == rhs->type; - break; - case EJS_EXPR_NOTEQ: - lval = lhs->type != rhs->type; - break; - case EJS_EXPR_BOOL_COMP: - lval = ! mprVarToBool(rhs); - break; - default: - lval = 0; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar((bool) lval), 0); - return 0; - } - - /* - * Types are the same here - */ - switch (lhs->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - /* Should be handled above */ - mprAssert(0); - return 0; - - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - mprCopyVarValue(&ep->result, mprCreateBoolVar(0), 0); - return 0; - - case MPR_TYPE_PTR: - rc = evalPtrExpr(ep, lhs->ptr, rel, rhs->ptr); - break; - - case MPR_TYPE_BOOL: - rc = evalBoolExpr(ep, lhs->boolean, rel, rhs->boolean); - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - rc = evalFloatExpr(ep, lhs->floating, rel, rhs->floating); - break; -#endif - - case MPR_TYPE_INT: - rc = evalNumericExpr(ep, (MprNum) lhs->integer, rel, - (MprNum) rhs->integer); - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - rc = evalNumericExpr(ep, (MprNum) lhs->integer64, rel, - (MprNum) rhs->integer64); - break; -#endif - - case MPR_TYPE_STRING: - rc = evalStringExpr(ep, lhs, rel, rhs); - } - return rc; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Expressions with floating operands - */ - -static int evalFloatExpr(Ejs *ep, double l, int rel, double r) -{ - double lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - lval = l / r; - break; - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateFloatVar(lval), 0); - } - return 0; -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ -/* - * Expressions with boolean operands - */ - -static int evalBoolExpr(Ejs *ep, bool l, int rel, bool r) -{ - bool lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -static int evalPtrExpr(Ejs *ep, void *l, int rel, void *r) -{ - bool lval; - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == NULL) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Expressions with numeric operands - */ - -static int evalNumericExpr(Ejs *ep, MprNum l, int rel, MprNum r) -{ - MprNum lval; - bool logical; - - lval = 0; - logical = 0; - - switch (rel) { - case EJS_EXPR_PLUS: - lval = l + r; - break; - case EJS_EXPR_INC: - lval = l + 1; - break; - case EJS_EXPR_MINUS: - lval = l - r; - break; - case EJS_EXPR_DEC: - lval = l - 1; - break; - case EJS_EXPR_MUL: - lval = l * r; - break; - case EJS_EXPR_DIV: - if (r != 0) { - lval = l / r; - } else { - ejsError(ep, "Divide by zero"); - return -1; - } - break; - case EJS_EXPR_MOD: - if (r != 0) { - lval = l % r; - } else { - ejsError(ep, "Modulo zero"); - return -1; - } - break; - case EJS_EXPR_LSHIFT: - lval = l << r; - break; - case EJS_EXPR_RSHIFT: - lval = l >> r; - break; - - default: - logical++; - break; - } - - /* - * Logical operators - */ - if (logical) { - - switch (rel) { - case EJS_EXPR_EQ: - lval = l == r; - break; - case EJS_EXPR_NOTEQ: - lval = l != r; - break; - case EJS_EXPR_LESS: - lval = (l < r) ? 1 : 0; - break; - case EJS_EXPR_LESSEQ: - lval = (l <= r) ? 1 : 0; - break; - case EJS_EXPR_GREATER: - lval = (l > r) ? 1 : 0; - break; - case EJS_EXPR_GREATEREQ: - lval = (l >= r) ? 1 : 0; - break; - case EJS_EXPR_BOOL_COMP: - lval = (r == 0) ? 1 : 0; - break; - default: - ejsError(ep, "Bad operator %d", rel); - return -1; - } - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval != 0), 0); - - } else { - mprCopyVarValue(&ep->result, mprCreateNumberVar(lval), 0); - } - return 0; -} - -/******************************************************************************/ -/* - * Expressions with string operands - */ - -static int evalStringExpr(Ejs *ep, MprVar *lhs, int rel, MprVar *rhs) -{ - int lval; - - mprAssert(ep); - mprAssert(lhs); - mprAssert(rhs); - - switch (rel) { - case EJS_EXPR_LESS: - lval = strcmp(lhs->string, rhs->string) < 0; - break; - case EJS_EXPR_LESSEQ: - lval = strcmp(lhs->string, rhs->string) <= 0; - break; - case EJS_EXPR_GREATER: - lval = strcmp(lhs->string, rhs->string) > 0; - break; - case EJS_EXPR_GREATEREQ: - lval = strcmp(lhs->string, rhs->string) >= 0; - break; - case EJS_EXPR_EQ: - lval = strcmp(lhs->string, rhs->string) == 0; - break; - case EJS_EXPR_NOTEQ: - lval = strcmp(lhs->string, rhs->string) != 0; - break; - case EJS_EXPR_PLUS: - /* - * This differs from all the above operations. We append rhs to lhs. - */ - mprDestroyVar(&ep->result); - appendValue(&ep->result, lhs); - appendValue(&ep->result, rhs); - return 0; - - case EJS_EXPR_INC: - case EJS_EXPR_DEC: - case EJS_EXPR_MINUS: - case EJS_EXPR_DIV: - case EJS_EXPR_MOD: - case EJS_EXPR_LSHIFT: - case EJS_EXPR_RSHIFT: - default: - ejsError(ep, "Bad operator"); - return -1; - } - - mprCopyVarValue(&ep->result, mprCreateBoolVar(lval), 0); - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a function. obj is set to the current object if a function is being - * run. - */ - -static int evalFunction(Ejs *ep, MprVar *obj, int flags) -{ - EjsProc *proc; - MprVar arguments, callee, thisObject, *prototype, **argValues; - MprArray *formalArgs, *actualArgs; - char buf[16], **argNames, **argBuf; - int i, rc, fid; - - mprAssert(ep); - mprAssert(ejsPtr(ep->eid)); - - rc = -1; - proc = ep->proc; - prototype = proc->fn; - actualArgs = proc->args; - argValues = (MprVar**) actualArgs->handles; - - /* - * Create a new variable stack frame. ie. new local variables. - */ - fid = ejsOpenBlock(ep->eid); - - if (flags & EJS_FLAGS_NEW) { - /* - * Create a new bare object and pass it into the constructor as the - * "this" local variable. - */ - thisObject = ejsCreateObj("this", EJS_OBJ_HASH_SIZE); - mprCreatePropertyValue(ep->local, "this", thisObject); - - } else if (obj) { - mprCreateProperty(ep->local, "this", obj); - } - - switch (prototype->type) { - default: - mprAssert(0); - break; - - case MPR_TYPE_STRING_CFUNCTION: - if (actualArgs->used > 0) { - argBuf = mprMalloc((1+actualArgs->used) * sizeof(char*)); - for (i = 0; i < actualArgs->used; i++) { - mprVarToString(&argBuf[i], MPR_MAX_STRING, 0, argValues[i]); - } - argBuf[i] = NULL; - } else { - argBuf = 0; - } - - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunctionWithStrings.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltStringCFunction) prototype->cFunctionWithStrings.fn) - (ep->eid, ep->altHandle, actualArgs->used, argBuf); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunctionWithStrings.fn)(ep->eid, - actualArgs->used, argBuf); - } else { - rc = (prototype->cFunctionWithStrings.fn)(ep->primaryHandle, - actualArgs->used, argBuf); - } - - if (actualArgs->used > 0) { - for (i = 0; i < actualArgs->used; i++) { - mprFree(argBuf[i]); - } - mprFree(argBuf); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_CFUNCTION: - /* - * Call the function depending on the various handle flags - */ - ep->thisPtr = prototype->cFunction.thisPtr; - if (prototype->flags & MPR_VAR_ALT_HANDLE) { - rc = ((EjsAltCFunction) prototype->cFunction.fn) - (ep->eid, ep->altHandle, actualArgs->used, argValues); - } else if (prototype->flags & MPR_VAR_SCRIPT_HANDLE) { - rc = (prototype->cFunction.fn)(ep->eid, actualArgs->used, - argValues); - } else { - rc = (prototype->cFunction.fn)(ep->primaryHandle, - actualArgs->used, argValues); - } - ep->thisPtr = 0; - break; - - case MPR_TYPE_FUNCTION: - - formalArgs = prototype->function.args; - argNames = (char**) formalArgs->handles; - - if (formalArgs->used > actualArgs->used) { - ejsError(ep, "Bad number of args. Should be %d", - formalArgs->used); - return -1; - } - - /* - * Create the arguments and callee variables - */ - arguments = ejsCreateObj("arguments", EJS_SMALL_OBJ_HASH_SIZE); - callee = ejsCreateObj("callee", EJS_SMALL_OBJ_HASH_SIZE); - - /* - * Overwrite the length property - */ - mprCreatePropertyValue(&arguments, "length", - mprCreateIntegerVar(actualArgs->used)); - mprCreatePropertyValue(&callee, "length", - mprCreateIntegerVar(formalArgs->used)); - - /* - * Define all the agruments to be set to the actual parameters - */ - for (i = 0; i < formalArgs->used; i++) { - mprCreateProperty(ep->local, argNames[i], argValues[i]); - } - for (i = 0; i < actualArgs->used; i++) { - mprItoa(i, buf, sizeof(buf)); - mprCreateProperty(&arguments, buf, argValues[i]); - } - - mprCreateProperty(&arguments, "callee", &callee); - mprCreateProperty(ep->local, "arguments", &arguments); - - /* - * Can destroy our variables here as they are now referenced via - * "local" - */ - mprDestroyVar(&callee); - mprDestroyVar(&arguments); - - /* - * Actually run the function - */ - rc = ejsEvalScript(ep->eid, prototype->function.body, 0, 0); - break; - } - - ejsCloseBlock(ep->eid, fid); - - /* - * New statements return the newly created object as the result of the - * command - */ - if (flags & EJS_FLAGS_NEW) { - mprDestroyVar(&ep->result); - /* - * Don't copy, we want to assign the actual object into result. - * (mprCopyVar would inc the refCount to 2). - */ - ep->result = thisObject; - } - return rc; -} - -/******************************************************************************/ -/* - * Run a function - */ - -int ejsRunFunction(int eid, MprVar *obj, const char *functionName, - MprArray *args) -{ - EjsProc proc, *saveProc; - Ejs *ep; - int rc; - - mprAssert(obj); - mprAssert(functionName && *functionName); - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return MPR_ERR_NOT_FOUND; - } - saveProc = ep->proc; - ep->proc = &proc; - - memset(&proc, 0, sizeof(EjsProc)); - mprDestroyVar(&ep->result); - - proc.fn = mprGetProperty(obj, functionName, 0); - if (proc.fn == 0 || proc.fn->type == MPR_TYPE_UNDEFINED) { - ep->proc = saveProc; - return MPR_ERR_NOT_FOUND; - } - proc.procName = mprStrdup(functionName); - if (args == 0) { - proc.args = mprCreateArray(); - rc = evalFunction(ep, obj, 0); - } else { - proc.args = args; - rc = evalFunction(ep, obj, 0); - proc.args = 0; - } - - freeProc(&proc); - ep->proc = saveProc; - - return rc; -} - -/******************************************************************************/ -/* - * Find which object contains the property given the current context. - * Only used for top level properties. - */ - -MprVar *ejsFindObj(Ejs *ep, int state, const char *property, int flags) -{ - MprVar *obj; - - mprAssert(ep); - mprAssert(property && *property); - - if (flags & EJS_FLAGS_GLOBAL) { - obj = ep->global; - - } else if (state == EJS_STATE_DEC || flags & EJS_FLAGS_LOCAL) { - obj = ep->local; - - } else { - /* First look local, then look global */ - if (mprGetProperty(ep->local, property, 0)) { - obj = ep->local; - } else { - obj = ep->global; - } - } - return obj; -} - -/******************************************************************************/ -/* - * Find an object property given a object and a property name. We - * intelligently look in the local and global namespaces depending on - * our state. If not found in local or global, try base classes for function - * names only. Returns the property or NULL. - */ - -MprVar *ejsFindProperty(Ejs *ep, int state, MprVar *obj, char *property, - int flags) -{ - MprVar *vp; - - mprAssert(ep); - if (flags & EJS_FLAGS_EXE) { - mprAssert(property && *property); - } - - if (obj != 0) { -#if FUTURE && MB - op = obj; - do { - vp = mprGetProperty(op, property, 0); - if (vp != 0) { - if (op != obj && mprVarIsFunction(vp->type)) { - } - break; - } - op = op->baseObj; - } while (op); -#endif - vp = mprGetProperty(obj, property, 0); - - } else { - if (state == EJS_STATE_DEC) { - vp = mprGetProperty(ep->local, property, 0); - - } else { - /* Look local first, then global */ - vp = mprGetProperty(ep->local, property, 0); - if (vp == NULL) { - vp = mprGetProperty(ep->global, property, 0); - } - } - } - return vp; -} - -/******************************************************************************/ -/* - * Update result - */ - -static void updateResult(Ejs *ep, int state, int flags, MprVar *vp) -{ - if (flags & EJS_FLAGS_EXE && state != EJS_STATE_DEC) { - mprDestroyVar(&ep->result); - if (vp) { - mprCopyProperty(&ep->result, vp, MPR_SHALLOW_COPY); - } - } -} - -/******************************************************************************/ -/* - * Append to the pointer value - */ - -static void appendValue(MprVar *dest, MprVar *src) -{ - char *value, *oldBuf, *buf; - int len, oldLen; - - mprAssert(dest); - - mprVarToString(&value, MPR_MAX_STRING, 0, src); - - if (mprVarIsValid(dest)) { - len = strlen(value); - oldBuf = dest->string; - oldLen = strlen(oldBuf); - buf = mprRealloc(oldBuf, (len + oldLen + 1) * sizeof(char)); - dest->string = buf; - strcpy(&buf[oldLen], value); - - } else { - *dest = mprCreateStringVar(value, 1); - } - mprFree(value); -} - -/******************************************************************************/ -/* - * Exit with status - */ - -void ejsSetExitStatus(int eid, int status) -{ - Ejs *ep; - - if ((ep = ejsPtr(eid)) == NULL) { - mprAssert(ep); - return; - } - ep->exitStatus = status; - ep->flags |= EJS_FLAGS_EXIT; -} - -/******************************************************************************/ -/* - * Free an argument list - */ - -static void freeProc(EjsProc *proc) -{ - MprVar **argValues; - int i; - - if (proc->args) { - argValues = (MprVar**) proc->args->handles; - - for (i = 0; i < proc->args->max; i++) { - if (argValues[i]) { - mprDestroyVar(argValues[i]); - mprFree(argValues[i]); - mprRemoveFromArray(proc->args, i); - } - } - - mprDestroyArray(proc->args); - } - - if (proc->procName) { - mprFree(proc->procName); - proc->procName = NULL; - } -} - -/******************************************************************************/ -/* - * This function removes any new lines. Used for else cases, etc. - */ - -static void removeNewlines(Ejs *ep, int state) -{ - int tid; - - do { - tid = ejsLexGetToken(ep, state); - } while (tid == EJS_TOK_NEWLINE); - - ejsLexPutbackToken(ep, tid, ep->token); -} - -/******************************************************************************/ - -#else -void ejsParserDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/ejs/ejsProcs.c b/source4/lib/appweb/ejs/ejsProcs.c deleted file mode 100644 index 43fff4a40b..0000000000 --- a/source4/lib/appweb/ejs/ejsProcs.c +++ /dev/null @@ -1,704 +0,0 @@ -/* - * @file ejsProc.c - * @brief EJS support functions - */ -/********************************* Copyright **********************************/ -/* - * @copy default.g - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Portions Copyright (c) GoAhead Software, 1995-2000. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "ejsInternal.h" - -#if BLD_FEATURE_EJS - -/****************************** Forward Declarations **************************/ -/* - * Object constructors - */ -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv); -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv); -static int booleanConsProc(EjsHandle eid, int argc, MprVar **agv); -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv); -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Core functions - */ -static int toStringProc(EjsHandle eid, int argc, MprVar **argv); -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv); - -/* - * Triggers - */ -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - int copyRef); - -/******************************************************************************/ -/* - * Routine to create the base common to all object types - */ - -MprVar ejsCreateObj(const char *name, int hashSize) -{ - MprVar o; - - o = mprCreateObjVar(name, hashSize); - if (o.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return o; - } - - mprCreatePropertyValue(&o, "toString", - mprCreateCFunctionVar(toStringProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(&o, "valueOf", - mprCreateCFunctionVar(valueOfProc, 0, MPR_VAR_SCRIPT_HANDLE)); - return o; -} - -/******************************************************************************/ -/* - * Routine to destroy a variable - */ - -bool ejsDestroyVar(MprVar *obj) -{ - return mprDestroyVar(obj); -} - -/******************************************************************************/ -/* - * Routine to create the base array type - */ - -MprVar ejsCreateArray(const char *name, int size) -{ - MprVar obj, *lp, undef; - char idx[16]; - int i; - - /* Sanity limit for size of hash table */ - - obj = ejsCreateObj(name, max(size, 503)); - if (obj.type == MPR_TYPE_UNDEFINED) { - mprAssert(0); - return obj; - } - - undef = mprCreateUndefinedVar(); - for (i = 0; i < size; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(&obj, idx, &undef); - } - - lp = mprCreatePropertyValue(&obj, "length", mprCreateIntegerVar(size)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return obj; -} - -/******************************************************************************/ -/******************************** Constructors ********************************/ -/******************************************************************************/ -/* - * Object constructor. Nothing really done here. For future expansion. - */ - -static int objectConsProc(EjsHandle eid, int argc, MprVar **argv) -{ -#if XX_UNUSED_XX - MprVar *obj; - Ejs *ep; - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); -#endif - return 0; -} - -/******************************************************************************/ -/* - * Array constructor - */ - -static int arrayConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj, *lp, undef; - Ejs *ep; - char idx[16]; - int i, max; - - objectConsProc(eid, argc, argv); - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - - if (argc == 1 && mprVarIsNumber(argv[0]->type)) { - /* - * x = new Array(size); - */ - undef = mprCreateUndefinedVar(); - max = (int) mprVarToInteger(argv[0]); - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, &undef); - } - } else { - /* - * x = new Array(element0, element1, ..., elementN): - */ - max = argc; - for (i = 0; i < max; i++) { - mprItoa(i, idx, sizeof(idx)); - mprCreateProperty(obj, idx, argv[i]); - } - } - - lp = mprCreatePropertyValue(obj, "length", mprCreateIntegerVar(max)); - mprAssert(lp); - - mprSetVarReadonly(lp, 1); - mprAddVarTrigger(lp, lengthTrigger); - - return 0; -} - -/******************************************************************************/ -/* - * Boolean constructor - */ - -static int booleanConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -#if FUTURE -/* - * Date constructor - */ - -static int dateConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -#endif -/******************************************************************************/ -/* - * Number constructor - */ - -static int numberConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/* - * String constructor - */ - -static int stringConsProc(EjsHandle eid, int argc, MprVar **argv) -{ - objectConsProc(eid, argc, argv); - return 0; -} - -/******************************************************************************/ -/********************************** Functions *********************************/ -/******************************************************************************/ - -static int toStringProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - char *buf; - int radix; - - if (argc == 0) { - radix = 10; - - } else if (argc == 1) { - radix = (int) mprVarToInteger(argv[0]); - - } else { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - mprVarToString(&buf, MPR_MAX_STRING, 0, obj); - mprCopyVarValue(&ep->result, mprCreateStringVar(buf, 0), MPR_SHALLOW_COPY); - mprFree(buf); - - return 0; -} - -/******************************************************************************/ - -static int valueOfProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *obj; - Ejs *ep; - - if (argc != 0) { - mprAssert(0); - return -1; - } - - if((ep = ejsPtr(eid)) == NULL) { - return -1; - } - - obj = mprGetProperty(ep->local, "this", 0); - mprAssert(obj); - - switch (obj->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_PTR: - mprCopyVar(&ep->result, obj, MPR_SHALLOW_COPY); - break; - - case MPR_TYPE_STRING: - mprCopyVarValue(&ep->result, mprCreateIntegerVar(atoi(obj->string)), 0); - break; - - case MPR_TYPE_BOOL: - case MPR_TYPE_INT: -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: -#endif -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: -#endif - mprCopyVar(&ep->result, obj, 0); - break; - } - return 0; -} - -/******************************************************************************/ -/* - * Var access trigger on the Array.length property. Return the count of - * enumerable properties (don't count functions). - */ - -static MprVarTriggerStatus lengthTrigger(MprVarTriggerOp op, - MprProperties *parentProperties, MprVar *prop, MprVar *newValue, - int copyRef) -{ - switch (op) { - case MPR_VAR_READ: - /* - * Subtract one for the length property - * FUTURE -- need an API to access parentProperties - * FUTURE -- contradiction to be read-only yet allow USE_NEW_VALUE. - * API needs finer control. - */ - *newValue = mprCreateIntegerVar(parentProperties->numDataItems - 1); - return MPR_TRIGGER_USE_NEW_VALUE; - - case MPR_VAR_WRITE: - return MPR_TRIGGER_ABORT; - - case MPR_VAR_CREATE_PROPERTY: - case MPR_VAR_DELETE_PROPERTY: - case MPR_VAR_DELETE: - default: - break; - } - return MPR_TRIGGER_PROCEED; -} - -/******************************************************************************/ -/**************************** Extension Functions *****************************/ -/******************************************************************************/ -/* - * Assert - */ - -static int assertProc(EjsHandle eid, int argc, MprVar **argv) -{ - bool b; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: assert(condition)\n"); - return -1; - } - b = mprVarToBool(argv[0]); - if (b == 0) { - ejsSetErrorMsg(eid, "Assertion failure\n"); - return -1; - } - ejsSetReturnValue(eid, mprCreateBoolVar(b)); - return 0; -} - -/******************************************************************************/ -/* - * Exit - */ - -static int exitProc(EjsHandle eid, int argc, MprVar **argv) -{ - int status; - - if (argc < 1) { - ejsSetErrorMsg(eid, "usage: exit(status)\n"); - return -1; - } - status = (int) mprVarToInteger(argv[0]); - ejsSetExitStatus(eid, status); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ - -static void printVar(MprVar *vp, int recurseCount, int indent) -{ - MprVar *np; - char *buf; - int i; - - if (recurseCount > 5) { - write(1, "Skipping - recursion too deep\n", 29); - return; - } - - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - - if (vp->type == MPR_TYPE_OBJECT) { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": {\n", 4); - np = mprGetFirstProperty(vp, MPR_ENUM_DATA); - while (np) { - if (strcmp(np->name, "local") == 0 || - strcmp(np->name, "global") == 0 || - strcmp(np->name, "this") == 0) { - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - continue; - } - printVar(np, recurseCount + 1, indent + 1); - np = mprGetNextProperty(vp, np, MPR_ENUM_DATA); - if (np) { - write(1, ",\n", 2); - } - } - write(1, "\n", 1); - for (i = 0; i < indent; i++) { - write(1, " ", 2); - } - write(1, "}", 1); - - } else { - if (vp->name) { - write(1, vp->name, strlen(vp->name)); - } else { - write(1, "unknown", 7); - } - write(1, ": ", 2); - - /* FUTURE -- other types ? */ - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - write(1, buf, strlen(buf)); - if (vp->type == MPR_TYPE_STRING) { - write(1, "\"", 1); - } - mprFree(buf); - } -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printVarsProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - char *buf; - int i; - - for (i = 0; i < argc; i++) { - vp = argv[i]; - switch (vp->type) { - case MPR_TYPE_OBJECT: - printVar(vp, 0, 0); - break; - default: - mprVarToString(&buf, MPR_MAX_STRING, 0, vp); - write(1, buf, strlen(buf)); - mprFree(buf); - break; - } - } - write(1, "\n", 1); - - ejsSetReturnValue(eid, mprCreateStringVar("", 0)); - return 0; -} - -/******************************************************************************/ -/* - * Print the args to stdout - */ - -static int printProc(EjsHandle eid, int argc, MprVar **argv) -{ - char *buf; - int i; - - for (i = 0; i < argc; i++) { - mprVarToString(&buf, MPR_MAX_STRING, 0, argv[i]); - write(1, buf, strlen(buf)); - mprFree(buf); - } - return 0; -} - -/******************************************************************************/ -/* - * println - */ - -static int printlnProc(EjsHandle eid, int argc, MprVar **argv) -{ - printProc(eid, argc, argv); - write(1, "\n", 1); - return 0; -} - -/******************************************************************************/ -/* - * Trace - */ - -static int traceProc(EjsHandle eid, int argc, char **argv) -{ - if (argc == 1) { - mprLog(0, "%s", argv[0]); - - } else if (argc == 2) { - mprLog(atoi(argv[0]), "%s", argv[1]); - - } else { - ejsSetErrorMsg(eid, "Usage: trace([level], message)"); - return -1; - } - ejsSetReturnString(eid, ""); - return 0; -} - -/******************************************************************************/ -/* - * Return the object reference count - */ - -static int refCountProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *vp; - int count; - - vp = argv[0]; - if (vp->type == MPR_TYPE_OBJECT) { - count = mprGetVarRefCount(vp); - ejsSetReturnValue(eid, mprCreateIntegerVar(count)); - } else { - ejsSetReturnValue(eid, mprCreateIntegerVar(0)); - } - - return 0; -} - -/******************************************************************************/ -/* - * Evaluate a sub-script. It is evaluated in the same variable scope as - * the calling script / function. - */ - -static int evalScriptProc(EjsHandle eid, int argc, MprVar **argv) -{ - MprVar *arg; - char *emsg; - int i; - - ejsSetReturnValue(eid, mprCreateUndefinedVar()); - - for (i = 0; i < argc; i++) { - arg = argv[i]; - if (arg->type != MPR_TYPE_STRING) { - continue; - } - if (ejsEvalScript(eid, arg->string, 0, &emsg) < 0) { - ejsSetErrorMsg(eid, "%s", emsg); - mprFree(emsg); - return -1; - } - } - /* - * Return with the value of the last expression - */ - return 0; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* - * Define the standard properties and functions inherited by all script engines. - */ - -int ejsDefineStandardProperties(MprVar *obj) -{ -#if BLD_FEATURE_FLOATING_POINT - double d = 0.0; - - /* FUTURE - this generates warnings on some systems. This is okay. */ - - mprCreatePropertyValue(obj, "NaN", mprCreateFloatVar(0.0 / d)); - d = MAX_FLOAT; - mprCreatePropertyValue(obj, "Infinity", mprCreateFloatVar(d * d)); -#endif - mprCreatePropertyValue(obj, "null", mprCreateNullVar()); - mprCreatePropertyValue(obj, "undefined", mprCreateUndefinedVar()); - mprCreatePropertyValue(obj, "true", mprCreateBoolVar(1)); - mprCreatePropertyValue(obj, "false", mprCreateBoolVar(0)); - mprCreatePropertyValue(obj, "NULL", mprCreatePtrVar(NULL)); - -#if BLD_FEATURE_LEGACY_API - /* - * DEPRECATED: 2.0. - * So that ESP/ASP can ignore "language=javascript" statements - */ - mprCreatePropertyValue(obj, "javascript", mprCreateIntegerVar(0)); -#endif - - /* - * Extension functions - */ - mprCreatePropertyValue(obj, "assert", - mprCreateCFunctionVar(assertProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "eval", - mprCreateCFunctionVar(evalScriptProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "exit", - mprCreateCFunctionVar(exitProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "refCount", - mprCreateCFunctionVar(refCountProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "print", - mprCreateCFunctionVar(printProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "println", - mprCreateCFunctionVar(printlnProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "printVars", - mprCreateCFunctionVar(printVarsProc,0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "trace", - mprCreateStringCFunctionVar(traceProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* - * Constructors - */ - mprCreatePropertyValue(obj, "Array", - mprCreateCFunctionVar(arrayConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Boolean", - mprCreateCFunctionVar(booleanConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Object", - mprCreateCFunctionVar(objectConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "Number", - mprCreateCFunctionVar(numberConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - mprCreatePropertyValue(obj, "String", - mprCreateCFunctionVar(stringConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - - /* mprCreatePropertyValue(obj, "Date", - * mprCreateCFunctionVar(dateConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - * mprCreatePropertyValue(obj, "Regexp", - * mprCreateCFunctionVar(regexpConsProc, 0, MPR_VAR_SCRIPT_HANDLE)); - */ - - /* - * Can we use on var x = "string text"; - */ - return 0; -} - -/******************************************************************************/ - -#else -void ejsProcsDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_EJS */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/esp/esp.c b/source4/lib/appweb/esp/esp.c deleted file mode 100644 index 3e47503edf..0000000000 --- a/source4/lib/appweb/esp/esp.c +++ /dev/null @@ -1,1042 +0,0 @@ -/* - * @file esp.c - * @brief Embedded Server Pages (ESP) core processing. - * @overview Embedded Server Pages provides an efficient way to generate - * dynamic pages using server-side Javascript. This code provides - * core processing, and should be called by an associated web - * server URL handler. - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "esp.h" - -#if BLD_FEATURE_ESP_MODULE - -/*********************************** Locals ***********************************/ -/* - * Master ESP control interface with the web server - */ - -static const Esp *esp; - -/***************************** Forward Declarations ***************************/ - -static int buildScript(EspRequest *ep, char **jsBuf, char *input, char - **errMsg); - -/************************************ Code ************************************/ -/* - * Called at server initialization - */ - -int espOpen(const Esp *control) -{ - mprAssert(control); - -#if BLD_FEATURE_MULTITHREAD - ejsOpen(control->lock, control->unlock, control->lockData); -#else - ejsOpen(0, 0, 0); -#endif - - /* - * Register the standard procedures - */ - espRegisterProcs(); - - /* - * Just for brain dead systems that don't zero global memory - */ - esp = control; - return 0; -} - -/******************************************************************************/ -/* - * Called at server termination - */ - -void espClose() -{ - ejsClose(); -} - -/******************************************************************************/ -/* - * Create for new ESP request. Assumed that this is called after all the - * HTTP headers have been read but before POST data has been read. It is - * expected that any session cookies have been read and that "variables" - * contains references to all the environment objects including "session". - * requestHandle is the web server request handle. - */ - -EspRequest *espCreateRequest(EspHandle webServerRequestHandle, char *uri, - MprVar *variables) -{ - EspRequest *ep; - MprVar *global; -#if BLD_FEATURE_LEGACY_API - MprVar *np; - char keyBuf[ESP_MAX_HEADER]; - int i; -#endif - - mprAssert(variables); - - ep = mprMalloc(sizeof(EspRequest)); - if (ep == 0) { - return 0; - } - memset(ep, 0, sizeof(EspRequest)); - ep->requestHandle = webServerRequestHandle; - ep->esp = esp; - ep->uri = mprStrdup(uri); - ep->docPath = 0; - ep->variables = variables; - - /* - * The handle passed to ejsOpenEngine is passed to every C function - * called by JavaScript. - */ - ep->eid = ejsOpenEngine((EjsHandle) ep, (EjsHandle) webServerRequestHandle); - if (ep->eid < 0) { - mprFree(ep); - return 0; - } - - /* - * All these copies and SetProperties will only copy references - * They will increments the object ref counts. - */ - mprCopyVar(&variables[ESP_GLOBAL_OBJ], ejsGetGlobalObject(ep->eid), - MPR_SHALLOW_COPY); - mprCopyVar(&variables[ESP_LOCAL_OBJ], ejsGetLocalObject(ep->eid), - MPR_SHALLOW_COPY); - - global = &variables[ESP_GLOBAL_OBJ]; - mprCreateProperty(global, "application", &variables[ESP_APPLICATION_OBJ]); - mprCreateProperty(global, "cookies", &variables[ESP_COOKIES_OBJ]); - mprCreateProperty(global, "files", &variables[ESP_FILES_OBJ]); - mprCreateProperty(global, "form", &variables[ESP_FORM_OBJ]); - mprCreateProperty(global, "headers", &variables[ESP_HEADERS_OBJ]); - mprCreateProperty(global, "request", &variables[ESP_REQUEST_OBJ]); - - /* - * FUTURE -- could server be shared across all requests for a given host - * and be made read-only. - */ - mprCreateProperty(global, "server", &variables[ESP_SERVER_OBJ]); - -#if BLD_FEATURE_SESSION - mprCreateProperty(global, "session", &variables[ESP_SESSION_OBJ]); -#endif - -#if BLD_FEATURE_LEGACY_API - /* - * DEPRECATED: 2.0 - * Define variables as globals. headers[] are prefixed with "HTTP_". - * NOTE: MaRequest::setVar does not copy into globals, whereas espSetVar - * does if legacy_api is defined. So variables pre-defined by MaRequest - * must be copied here into globals[]. - * - * NOTE: if a variable is in session[] and in form[], the form[] will - * override being later in the variables[] list. Use mprSetProperty - * instead of mprCreateProperty to cover for this case. - */ - for (i = 0; i < ESP_OBJ_MAX; i++) { - if (i == ESP_GLOBAL_OBJ || i == ESP_LOCAL_OBJ) { - continue; - } - if (variables[i].type != MPR_TYPE_OBJECT) { - continue; - } - np = mprGetFirstProperty(&variables[i], MPR_ENUM_DATA); - while (np) { - if (i == ESP_HEADERS_OBJ) { - mprSprintf(keyBuf, sizeof(keyBuf) - 1, "HTTP_%s", np->name); - mprSetProperty(global, keyBuf, np); - } else { - mprSetProperty(global, np->name, np); - } - np = mprGetNextProperty(&variables[i], np, MPR_ENUM_DATA); - } - } -#endif - return ep; -} - -/******************************************************************************/ - -void espDestroyRequest(EspRequest *ep) -{ - mprAssert(ep); - mprAssert(ep->eid >= 0); - - mprFree(ep->uri); - mprFree(ep->docPath); - ejsCloseEngine(ep->eid); - mprFree(ep); -} - -/******************************************************************************/ -/* - * The callback function will be called: - * - * (fn)(EjsId eid, EspRequest *ep, argc, argv); - * - * Callers can get their web server handle by calling: - * - * rq = (requiredCast) espGetHandle(ep); - */ - -void espDefineCFunction(EspRequest *ep, const char *functionName, EspCFunction fn, - void *thisPtr) -{ - mprAssert(functionName && *functionName); - mprAssert(fn); - - if (ep) { - ejsDefineCFunction(ep->eid, functionName, (MprCFunction) fn, - thisPtr, 0); - } else { - ejsDefineCFunction(-1, functionName, (MprCFunction) fn, thisPtr, 0); - } -} - -/******************************************************************************/ - -void espDefineStringCFunction(EspRequest *ep, const char *functionName, - EspStringCFunction fn, void *thisPtr) -{ - mprAssert(functionName && *functionName); - mprAssert(fn); - - if (ep) { - ejsDefineStringCFunction(ep->eid, functionName, (MprStringCFunction) fn, - thisPtr, 0); - } else { - ejsDefineStringCFunction(-1, functionName, (MprStringCFunction) fn, - thisPtr, 0); - } -} - -/******************************************************************************/ - -void *espGetRequestHandle(EspRequest *ep) -{ - return ep->requestHandle; -} - -/******************************************************************************/ - -EjsId espGetScriptHandle(EspRequest *ep) -{ - return ep->eid; -} - -/******************************************************************************/ - -char *espGetStringVar(EspRequest *ep, EspEnvType oType, char *var, - char *defaultValue) -{ - MprVar value; - - if (espGetVar(ep, oType, var, &value) < 0 || - value.type != MPR_TYPE_STRING) { - return defaultValue; - } - return value.string; -} - -/******************************************************************************/ - -int espGetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar *value) -{ - MprVar *vp; - - mprAssert(ep); - mprAssert(var); - - vp = mprGetProperty(&ep->variables[oType], var, 0); - if (vp == 0) { - return -1; - } - *value = *vp; - return 0; -} - -/******************************************************************************/ -/* - * Process the ESP page. docBuf holds the page already. We expect that - * ep->variables holds all the pertinent environment variables. - */ - -int espProcessRequest(EspRequest *ep, const char *docPath, char *docBuf, - char **errMsg) -{ - char *jsBuf; - - mprAssert(ep); - - ep->docPath = mprStrdup(docPath); - - jsBuf = 0; - if (buildScript(ep, &jsBuf, docBuf, errMsg) < 0) { - return MPR_ERR_CANT_COMPLETE; - } - - if (jsBuf) { - mprLog(7, "esp: script is:\n%s\n", jsBuf); - - /* - * Now evaluate the entire escript - * MOB could cache the script - */ - if (ejsEvalScript(ep->eid, jsBuf, 0, errMsg) < 0) { - return MPR_ERR_ABORTED; - } - - mprFree(jsBuf); - } - return 0; -} - -/******************************************************************************/ - -void espRedirect(EspRequest *ep, int code, char *url) -{ - mprAssert(ep); - mprAssert(url); - - ep->esp->redirect(ep->requestHandle, code, url); -} - -/******************************************************************************/ - -void espError(EspRequest *ep, const char *fmt, ...) -{ - va_list args; - char *buf; - - mprAssert(ep); - mprAssert(fmt); - - va_start(args, fmt); - mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args); - ejsSetErrorMsg(ep->eid, "%s", buf); - mprFree(buf); - va_end(args); -} - -/******************************************************************************/ - -void espSetHeader(EspRequest *ep, char *header, bool allowMultiple) -{ - mprAssert(ep); - - ep->esp->setHeader(ep->requestHandle, header, allowMultiple); -} - -/******************************************************************************/ -/* - * Caller does not need to destroy the var - */ - -MprVar *espGetResult(EspRequest *ep) -{ - mprAssert(ep); - - return ejsGetReturnValue(ep->eid); -} - -/******************************************************************************/ - -void espSetReturn(EspRequest *ep, MprVar value) -{ - mprAssert(ep); - - ejsSetReturnValue(ep->eid, value); -} - -/******************************************************************************/ - -void espSetReturnString(EspRequest *ep, const char *str) -{ - mprAssert(ep); - - ejsSetReturnValue(ep->eid, mprCreateStringVar(str, 0)); -} - -/******************************************************************************/ - -void espSetResponseCode(EspRequest *ep, int code) -{ - mprAssert(ep); - - ep->esp->setResponseCode(ep->requestHandle, code); -} - -/******************************************************************************/ - -void espSetVar(EspRequest *ep, EspEnvType oType, char *var, MprVar value) -{ - mprCreatePropertyValue(&ep->variables[oType], var, value); -} - -/******************************************************************************/ - -void espSetStringVar(EspRequest *ep, EspEnvType oType, - const char *var, const char *value) -{ - /* - * Will create or update if already existing - */ - mprCreatePropertyValue(&ep->variables[oType], var, - mprCreateStringVar(value, 0)); -} - -/******************************************************************************/ - -int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var) -{ - return mprDeleteProperty(&ep->variables[oType], var); -} - -/******************************************************************************/ - -int espWrite(EspRequest *ep, char *buf, int size) -{ - mprAssert(ep); - mprAssert(buf); - mprAssert(size >= 0); - - return ep->esp->writeBlock(ep->requestHandle, buf, size); -} - -/******************************************************************************/ - -int espWriteString(EspRequest *ep, char *buf) -{ - mprAssert(ep); - mprAssert(buf); - - return ep->esp->writeBlock(ep->requestHandle, buf, strlen(buf)); -} - -/******************************************************************************/ - -int espWriteFmt(EspRequest *ep, char *fmt, ...) -{ - va_list args; - char *buf; - int rc, len; - - mprAssert(ep); - mprAssert(fmt); - - va_start(args, fmt); - len = mprAllocVsprintf(&buf, MPR_MAX_HEAP_SIZE, fmt, args); - rc = ep->esp->writeBlock(ep->requestHandle, buf, len); - mprFree(buf); - va_end(args); - return rc; -} - -/******************************************************************************/ -/******************************************************************************/ -/******************************************************************************/ -/* - * Get a javascript identifier. Must allow x.y['abc'] or x.y["abc"]. - * Must be careful about quoting and only allow quotes inside []. - */ - -static int getIdentifier(EspParse *parse) -{ - int atQuote, prevC, c; - - mprAssert(parse); - - atQuote = 0; - prevC = 0; - c = *parse->inp++; - - while (isalnum(c) || c == '_' || c == '.' || c == '[' || - c == ']' || c == '\'' || c == '\"') { - if (c == '\'' || c == '\"') { - if (c == atQuote) { - atQuote = 0; - } else if (prevC == '[') { - atQuote = c; - } else { - break; - } - } - if (parse->tokp >= parse->endp) { - parse->token = (char*) mprRealloc(parse->token, - parse->tokLen + ESP_TOK_INCR); - if (parse->token == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - parse->token[parse->tokLen] = '\0'; - parse->tokLen += ESP_TOK_INCR; - parse->endp = &parse->token[parse->tokLen - 1]; - } - *parse->tokp++ = c; - prevC = c; - c = *parse->inp++; - } - - parse->inp--; - *parse->tokp = '\0'; - - return 0; -} - -/******************************************************************************/ -/* - * Get the next ESP input token. input points to the next input token. - * parse->token will hold the parsed token. The function returns the token id. - */ - -static int getEspToken(int state, EspParse *parse) -{ - char *cp; - int tid, done, c, quoted; - - tid = ESP_TOK_LITERAL; - parse->tokp = parse->token; - parse->tokp[0] = '\0'; - quoted = 0; - - c = *parse->inp++; - for (done = 0; !done; c = *parse->inp++) { - - /* - * Get room for more characters in the token buffer - */ - if (parse->tokp >= parse->endp) { - parse->token = (char*) mprRealloc(parse->token, - parse->tokLen + ESP_TOK_INCR); - if (parse->token == 0) { - return ESP_TOK_ERR; - } - parse->token[parse->tokLen] = '\0'; - parse->tokp = &parse->token[parse->tokLen - 1]; - parse->tokLen += ESP_TOK_INCR; - parse->endp = &parse->token[parse->tokLen - 1]; - } - - switch (c) { - case 0: - if (*parse->token) { - done++; - parse->inp--; - break; - } - return ESP_TOK_EOF; - - default: - if (c == '\"' && state != ESP_STATE_IN_ESP_TAG) { - *parse->tokp++ = '\\'; - } - *parse->tokp++ = c; - quoted = 0; - break; - - case '\\': - quoted = 1; - *parse->tokp++ = c; - break; - - case '@': - if (*parse->inp == '@' && state != ESP_STATE_IN_ESP_TAG) { - if (quoted) { - parse->tokp--; - quoted = 0; - } else { - if (*parse->token) { - parse->inp--; - } else { - parse->inp++; - tid = ESP_TOK_ATAT; - if (getIdentifier(parse) < 0) { - return ESP_TOK_ERR; - } - } - done++; - break; - } - } - *parse->tokp++ = c; - break; - - case '<': - if (*parse->inp == '%' && state != ESP_STATE_IN_ESP_TAG) { - if (quoted) { - parse->tokp--; - quoted = 0; - *parse->tokp++ = c; - break; - } - if (*parse->token) { - parse->inp--; - done++; - break; - } - parse->inp++; - while (isspace((int) *parse->inp)) { - parse->inp++; - } - if (*parse->inp == '=') { - parse->inp++; - while (isspace((int) *parse->inp)) { - parse->inp++; - } - tid = ESP_TOK_EQUALS; - if (getIdentifier(parse) < 0) { - return ESP_TOK_ERR; - } - done++; - break; - } - if (*parse->inp == 'i' && - strncmp(parse->inp, "include", 7) == 0 && - isspace((int) parse->inp[7])) { - tid = ESP_TOK_INCLUDE; - parse->inp += 7; - while (isspace((int) *parse->inp)) { - parse->inp++; - } - while (*parse->inp && !isspace((int) *parse->inp) && - *parse->inp != '%' && parse->tokp < parse->endp) { - *parse->tokp++ = *parse->inp++; - } - *parse->tokp = '\0'; - if (parse->token[0] == '"') { - parse->tokp = parse->token; - for (cp = &parse->token[1]; *cp; ) { - *parse->tokp++ = *cp++; - } - if (cp[-1] == '"') { - parse->tokp--; - } - *parse->tokp = '\0'; - } - - } else { - tid = ESP_TOK_START_ESP; - } - done++; - break; - } - *parse->tokp++ = c; - break; - - case '%': - if (*parse->inp == '>' && state == ESP_STATE_IN_ESP_TAG) { - if (quoted) { - parse->tokp--; - quoted = 0; - } else { - if (*parse->token) { - parse->inp--; - } else { - tid = ESP_TOK_END_ESP; - parse->inp++; - } - done++; - break; - } - } - *parse->tokp++ = c; - break; - } - } - - *parse->tokp = '\0'; - parse->inp--; - return tid; -} - -/******************************************************************************/ -/* - * Convert an ESP page into a JavaScript. We also expand include files. - */ - -static int buildScript(EspRequest *ep, char **jsBuf, char *input, char **errMsg) -{ - EspParse parse; - char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME], incPath[MPR_MAX_FNAME]; - char *incBuf, *incText; - int state, tid, len, rc, maxScriptSize, incSize; - - mprAssert(ep); - mprAssert(jsBuf); - mprAssert(input); - - rc = 0; - len = 0; - state = ESP_STATE_BEGIN; - if (errMsg) { - *errMsg = 0; - } - - memset(&parse, 0, sizeof(parse)); - parse.token = (char*) mprMalloc(ESP_TOK_INCR); - if (parse.token == 0) { - return MPR_ERR_CANT_ALLOCATE; - } - parse.token[0] = '\0'; - parse.tokLen = ESP_TOK_INCR; - parse.endp = &parse.token[parse.tokLen - 1]; - parse.tokp = parse.token; - parse.inBuf = input; - parse.inp = parse.inBuf; - - maxScriptSize = esp->maxScriptSize; - - tid = getEspToken(state, &parse); - while (tid != ESP_TOK_EOF && len >= 0) { - - switch (tid) { - default: - case ESP_TOK_ERR: - mprFree(parse.token); - return MPR_ERR_BAD_SYNTAX; - - case ESP_TOK_LITERAL: - len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, - "write(\"", parse.token, "\");\n", NULL); - break; - - case ESP_TOK_ATAT: - /* - * Trick to get undefined variables to evaluate to "". - * Catenate with "" to cause toString to run. - */ - len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, - "write(\"\" + ", parse.token, ");\n", NULL); - break; - - case ESP_TOK_EQUALS: - len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, - "write(\"\" + ", parse.token, ");\n", NULL); - state = ESP_STATE_IN_ESP_TAG; - break; - - case ESP_TOK_START_ESP: - state = ESP_STATE_IN_ESP_TAG; - tid = getEspToken(state, &parse); - while (tid != ESP_TOK_EOF && tid != ESP_TOK_EOF && - tid != ESP_TOK_END_ESP && len >= 0) { - len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, - parse.token, NULL); - tid = getEspToken(state, &parse); - } - state = ESP_STATE_BEGIN; - break; - - case ESP_TOK_END_ESP: - state = ESP_STATE_BEGIN; - break; - - case ESP_TOK_INCLUDE: - if (parse.token[0] == '/') { - mprStrcpy(incPath, sizeof(incPath), parse.token); - } else { - mprGetDirName(dir, sizeof(dir), ep->uri); - mprSprintf(incPath, sizeof(incPath), "%s/%s", - dir, parse.token); - } - if (esp->mapToStorage(ep->requestHandle, path, sizeof(path), - incPath, 0) < 0) { - mprAllocSprintf(errMsg, MPR_MAX_STRING, - "Can't find include file: %s", path); - rc = MPR_ERR_CANT_OPEN; - break; - } - if (esp->readFile(ep->requestHandle, &incText, &incSize, path) < 0){ - mprAllocSprintf(errMsg, MPR_MAX_STRING, - "Can't read include file: %s", path); - rc = MPR_ERR_CANT_READ; - break; - } - incText[incSize] = '\0'; - - /* - * Recurse and process the include script - */ - incBuf = 0; - if ((rc = buildScript(ep, &incBuf, incText, errMsg)) < 0) { - mprFree(incText); - mprFree(parse.token); - return rc; - } - - len = mprReallocStrcat(jsBuf, maxScriptSize, len, 0, incBuf, NULL); - mprFree(incText); - mprFree(incBuf); - state = ESP_STATE_IN_ESP_TAG; - break; - } - tid = getEspToken(state, &parse); - } - mprFree(parse.token); - if (len < 0) { - mprAllocSprintf(errMsg, MPR_MAX_STRING, - "Script token is too big in %s.\nConfigured maximum is %d.", - path, maxScriptSize); - return MPR_ERR_WONT_FIT; - } - return rc; -} - -/******************************************************************************/ -/******************************* Wrapped Routines *****************************/ -/******************************************************************************/ - -int espCopyVar(EspRequest *ep, char *var, MprVar *value, int copyDepth) -{ - return ejsCopyVar(ep->eid, var, value, copyDepth); -} - -/******************************************************************************/ - -MprVar espCreateObjVar(char *name, int hashSize) -{ - return ejsCreateObj(name, hashSize); -} - -/******************************************************************************/ - -MprVar espCreateArrayVar(char *name, int size) -{ - return ejsCreateArray(name, size); -} - -/******************************************************************************/ - -bool espDestroyVar(MprVar *obj) -{ - return ejsDestroyVar(obj); -} - -/******************************************************************************/ - -MprVar *espCreateProperty(MprVar *obj, char *property, MprVar *newValue) -{ - return mprCreateProperty(obj, property, newValue); -} - -/******************************************************************************/ - -MprVar *espCreatePropertyValue(MprVar *obj, char *property, MprVar newValue) -{ - return mprCreatePropertyValue(obj, property, newValue); -} - -/******************************************************************************/ - -void espDefineFunction(EspRequest *ep, const char *functionName, char *args, char *body) -{ - ejsDefineFunction(ep->eid, functionName, args, body); -} - -/******************************************************************************/ - -int espDeleteProperty(MprVar *obj, char *property) -{ - return mprDeleteProperty(obj, property); -} - -/******************************************************************************/ - -int espDeleteVar(EspRequest *ep, char *var) -{ - return ejsDeleteVar(ep->eid, var); -} - -/******************************************************************************/ -int espEvalFile(EspRequest *ep, char *path, MprVar *result, char **emsg) -{ - return ejsEvalFile(ep->eid, path, result, emsg); -} - -/******************************************************************************/ - -int espEvalScript(EspRequest *ep, char *script, MprVar *result, char **emsg) -{ - return ejsEvalScript(ep->eid, script, result, emsg); -} - -/******************************************************************************/ - -int espGetPropertyCount(MprVar *obj, int includeFlags) -{ - if (obj->type != MPR_TYPE_OBJECT) { - return MPR_ERR_BAD_STATE; - } - return mprGetPropertyCount(obj, includeFlags); -} - -/******************************************************************************/ - -MprVar *espGetFirstProperty(MprVar *obj, int includeFlags) -{ - return mprGetFirstProperty(obj, includeFlags); -} - -/******************************************************************************/ - -MprVar *espGetGlobalObject(EspRequest *ep) -{ - return ejsGetGlobalObject(ep->eid); -} - -/******************************************************************************/ - -MprVar *espGetLocalObject(EspRequest *ep) -{ - return ejsGetLocalObject(ep->eid); -} - -/******************************************************************************/ - -MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags) -{ - return mprGetNextProperty(obj, currentProperty, includeFlags); -} - -/******************************************************************************/ - -MprVar *espGetProperty(MprVar *obj, char *property, MprVar *value) -{ - return mprGetProperty(obj, property, value); -} - -/******************************************************************************/ - -void *espGetThisPtr(EspRequest *ep) -{ - return ejsGetThisPtr(ep->eid); -} - -/******************************************************************************/ -#if XX_UNUSED_XX - -int espReadProperty(MprVar *dest, MprVar *prop) -{ - mprAssert(prop); - mprAssert(dest); - - *dest = *prop; - return 0; -} - -#endif -/******************************************************************************/ - -int espReadVar(EspRequest *ep, char *var, MprVar *value) -{ - return ejsReadVar(ep->eid, var, value); -} - -/******************************************************************************/ - -int espRunFunction(EspRequest *ep, MprVar *obj, char *functionName, - MprArray *args) -{ - return ejsRunFunction(ep->eid, obj, functionName, args); -} - -/******************************************************************************/ - -MprVar *espSetProperty(MprVar *obj, char *property, MprVar *newValue) -{ - return mprSetProperty(obj, property, newValue); -} - -/******************************************************************************/ - -MprVar *espSetPropertyValue(MprVar *obj, char *property, MprVar newValue) -{ - return mprSetPropertyValue(obj, property, newValue); -} - -/******************************************************************************/ - -int espWriteVar(EspRequest *ep, char *var, MprVar *value) -{ - return ejsWriteVar(ep->eid, var, value); -} - -/******************************************************************************/ - -int espWriteVarValue(EspRequest *ep, char *var, MprVar value) -{ - return ejsWriteVarValue(ep->eid, var, value); -} - -/******************************************************************************/ -#if XX_UNUSED_XX - -int espWriteProperty(MprVar *prop, MprVar *newValue) -{ - return mprWriteProperty(prop, newValue); -} - -/******************************************************************************/ - -int espWritePropertyValue(MprVar *prop, MprVar newValue) -{ - return mprWritePropertyValue(prop, newValue); -} - -#endif -/******************************************************************************/ - -#else /* !BLD_FEATURE_ESP_MODULE */ -void espDummy() {} - -/******************************************************************************/ -#endif /* BLD_FEATURE_ESP_MODULE */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/esp/esp.h b/source4/lib/appweb/esp/esp.h deleted file mode 100644 index 3d9b7bf8dc..0000000000 --- a/source4/lib/appweb/esp/esp.h +++ /dev/null @@ -1,277 +0,0 @@ -/** - * @file esp.h - * @brief Header for Embedded Server Pages (ESP) - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#ifndef _h_ESP_h -#define _h_ESP_h 1 - -#include "lib/appweb/ejs/ejs.h" -#include "lib/appweb/esp/espEnv.h" -#include "lib/appweb/mpr/var.h" -#include "lib/appweb/mpr/miniMpr.h" - -/*********************************** Defines **********************************/ - -#if BLD_FEATURE_SQUEEZE -#define ESP_TOK_INCR 1024 -#define ESP_MAX_HEADER 1024 -#else -#define ESP_TOK_INCR 4096 -#define ESP_MAX_HEADER 4096 -#endif - -/* - * ESP lexical analyser tokens - */ -#define ESP_TOK_ERR -1 /* Any input error */ -#define ESP_TOK_EOF 0 /* End of file */ -#define ESP_TOK_START_ESP 1 /* <% */ -#define ESP_TOK_END_ESP 2 /* %> */ -#define ESP_TOK_ATAT 3 /* @@var */ -#define ESP_TOK_LITERAL 4 /* literal HTML */ -#define ESP_TOK_INCLUDE 5 /* include file.esp */ -#define ESP_TOK_EQUALS 6 /* = var */ - -/* - * ESP parser states - */ -#define ESP_STATE_BEGIN 1 /* Starting state */ -#define ESP_STATE_IN_ESP_TAG 2 /* Inside a <% %> group */ - -/*********************************** Types ************************************/ - -typedef void* EspHandle; /* Opaque Web server handle type */ - -/* - * Per request control block - */ -typedef struct EspRequest { - MprStr docPath; /* Physical path for ESP page */ - EjsId eid; /* EJS instance handle */ - const struct Esp *esp; /* Pointer to ESP control block */ - EspHandle requestHandle; /* Per request web server handle */ - MprStr uri; /* Request URI */ - MprVar *variables; /* Pointer to variables */ -} EspRequest; - -/* - * Master ESP control block. This defines the function callbacks for a - * web server handler to implement. ESP will call these functions as - * required. - */ -typedef struct Esp { - int maxScriptSize; - void (*createSession)(EspHandle handle, int timeout); - void (*destroySession)(EspHandle handle); - const char *(*getSessionId)(EspHandle handle); - int (*mapToStorage)(EspHandle handle, char *path, int len, const char *uri, - int flags); - int (*readFile)(EspHandle handle, char **buf, int *len, const char *path); - void (*redirect)(EspHandle handle, int code, char *url); - void (*setCookie)(EspHandle handle, const char *name, const char *value, - int lifetime, const char *path, bool secure); - void (*setHeader)(EspHandle handle, const char *value, bool allowMultiple); - void (*setResponseCode)(EspHandle handle, int code); - int (*writeBlock)(EspHandle handle, const char *buf, int size); - int (*writeFmt)(EspHandle handle, char *fmt, ...); -#if BLD_FEATURE_MULTITHREAD - void (*lock)(void *lockData); - void (*unlock)(void *lockData); - void *lockData; -#endif -} Esp; - - -/* - * ESP parse context - */ -typedef struct { - char *inBuf; /* Input data to parse */ - char *inp; /* Next character for input */ - char *endp; /* End of storage (allow for null) */ - char *tokp; /* Pointer to current parsed token */ - char *token; /* Storage buffer for token */ - int tokLen; /* Length of buffer */ -} EspParse; - - -/******************************** Private APIs ********************************/ - -extern void espRegisterProcs(void); - -/******************************** Published API *******************************/ -#ifdef __cplusplus -extern "C" { -#endif - -/* - * Function callback signatures - */ -typedef int (*EspCFunction)(EspRequest *ep, int argc, - struct MprVar **argv); -typedef int (*EspStringCFunction)(EspRequest *ep, int argc, - char **argv); - -/* - * APIs for those hosting the ESP module - */ -extern int espOpen(const Esp *control); -extern void espClose(void); -extern EspRequest *espCreateRequest(EspHandle webServerRequestHandle, - char *uri, MprVar *envObj); -extern void espDestroyRequest(EspRequest *ep); -extern int espProcessRequest(EspRequest *ep, const char *docPath, - char *docBuf, char **errMsg); - -/* - * Method invocation - */ -extern void espDefineCFunction(EspRequest *ep, const char *functionName, - EspCFunction fn, void *thisPtr); -extern void espDefineFunction(EspRequest *ep, const char *functionName, - char *args, char *body); -extern void espDefineStringCFunction(EspRequest *ep, - const char *functionName, EspStringCFunction fn, - void *thisPtr); -extern int espRunFunction(EspRequest *ep, MprVar *obj, - char *functionName, MprArray *args); -extern void espSetResponseCode(EspRequest *ep, int code); -extern void espSetReturn(EspRequest *ep, MprVar value); -extern void *espGetThisPtr(EspRequest *ep); - -/* - * Utility routines to use in C methods - */ -extern void espError(EspRequest *ep, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -extern int espEvalFile(EspRequest *ep, char *path, MprVar *result, - char **emsg); -extern int espEvalScript(EspRequest *ep, char *script, MprVar *result, - char **emsg); -extern MprVar *espGetLocalObject(EspRequest *ep); -extern MprVar *espGetGlobalObject(EspRequest *ep); -extern EspHandle espGetRequestHandle(EspRequest *ep); -extern MprVar *espGetResult(EspRequest *ep); -extern EjsId espGetScriptHandle(EspRequest *ep); -extern void espRedirect(EspRequest *ep, int code, char *url); -extern void espSetHeader(EspRequest *ep, char *header, - bool allowMultiple); -extern void espSetReturnString(EspRequest *ep, const char *str); -extern int espWrite(EspRequest *ep, char *buf, int size); -extern int espWriteString(EspRequest *ep, char *buf); -extern int espWriteFmt(EspRequest *ep, char *fmt, ...) PRINTF_ATTRIBUTE(2,3); - -/* - * ESP array[] variable access (set will update/create) - */ -extern int espGetVar(EspRequest *ep, EspEnvType oType, char *var, - MprVar *value); -extern char *espGetStringVar(EspRequest *ep, EspEnvType oType, - char *var, char *defaultValue); -extern void espSetVar(EspRequest *ep, EspEnvType oType, char *var, - MprVar value); -extern void espSetStringVar(EspRequest *ep, EspEnvType oType, - const char *var, const char *value); -extern int espUnsetVar(EspRequest *ep, EspEnvType oType, char *var); - -/* - * Object creation and management - */ -extern MprVar espCreateObjVar(char *name, int hashSize); -extern MprVar espCreateArrayVar(char *name, int size); -extern bool espDestroyVar(MprVar *var); -extern MprVar *espCreateProperty(MprVar *obj, char *property, - MprVar *newValue); -extern MprVar *espCreatePropertyValue(MprVar *obj, char *property, - MprVar newValue); -extern int espDeleteProperty(MprVar *obj, char *property); - -/* - * JavaScript variable management. Set will create/update a property. - * All return a property reference. GetProperty will optionally return the - * property in value. - */ -extern MprVar *espGetProperty(MprVar *obj, char *property, - MprVar *value); -extern MprVar *espSetProperty(MprVar *obj, char *property, - MprVar *newValue); -extern MprVar *espSetPropertyValue(MprVar *obj, char *property, - MprVar newValue); - -#if 0 -/* - * Low-level direct read and write of properties. - * FUTURE: -- Read is not (dest, src). MUST WARN IN DOC ABOUT COPY/READ - * Will still cause triggers to run. - */ -extern int espReadProperty(MprVar *dest, MprVar *prop); -extern int espWriteProperty(MprVar *prop, MprVar *newValue); -extern int espWritePropertyValue(MprVar *prop, MprVar newValue); -#endif - - -/* - * Access JavaScript variables by their full name. Can use "." or "[]". For - * example: "global.request['REQUEST_URI']" - * For Read/write, the variables must exist. - */ -extern int espCopyVar(EspRequest *ep, char *var, MprVar *value, - int copyDepth); -extern int espDeleteVar(EspRequest *ep, char *var); -extern int espReadVar(EspRequest *ep, char *var, MprVar *value); -extern int espWriteVar(EspRequest *ep, char *var, MprVar *value); -extern int espWriteVarValue(EspRequest *ep, char *var, MprVar value); - -/* - * Object property enumeration - */ -extern MprVar *espGetFirstProperty(MprVar *obj, int includeFlags); -extern MprVar *espGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags); -extern int espGetPropertyCount(MprVar *obj, int includeFlags); - -#ifdef __cplusplus -} -#endif -/******************************************************************************/ -#endif /* _h_ESP_h */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/esp/espEnv.h b/source4/lib/appweb/esp/espEnv.h deleted file mode 100644 index a3c9d9f5c7..0000000000 --- a/source4/lib/appweb/esp/espEnv.h +++ /dev/null @@ -1,128 +0,0 @@ -/* - * @file espEnv.h - * @brief ESP Environment Variables - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************************************************************/ - -#ifndef _h_ESP_ENV_h -#define _h_ESP_ENV_h 1 - -/* - * @brief Scripting environment variable array types - */ -typedef enum EspEnvType { - ESP_UNDEFINED_OBJ = -1, - - /** - * Elements for server[]: - * DOCUMENT_ROOT GATEWAY_INTERFACE SERVER_ADDR SERVER_PORT SERVER_NAME - * SERVER_PROTOCOL SERVER_SOFTWARE SERVER_URL UPLOAD_DIR - * FUTURE: SERVER_ADMIN - * FUTURE: this could be shared across all hosts and be made read-only. - */ - ESP_SERVER_OBJ = 0, /*! server[] data */ - - /** - * Elements for session[]: are user defined - */ - ESP_SESSION_OBJ = 1, /*! session[] data */ - - /** - * Elements for request[]: - * AUTH_TYPE CONTENT_LENGTH CONTENT_TYPE QUERY_STRING PATH_INFO - * PATH_TRANSLATED REMOTE_ADDR REMOTE_HOST REMOTE_USER REQUEST_METHOD - * REQUEST_URI SCRIPT_FILENAME SCRIPT_NAME - * FUTURE: FILEPATH_INFO REDIRECT_URL SELF REMOTE_PORT AUTH_USER - * AUTH_GROUP AUTH_ACL - */ - ESP_REQUEST_OBJ = 2, /*! request[] data */ - - /** - * Elements for headers[]: - * HTTP_ACCEPT HTTP_ACCEPT_CHARSET HTTP_CONNECTION HTTP_HOST - * HTTP_REFERER HTTP_USER_AGENT and any other custom headers - */ - ESP_HEADERS_OBJ = 3, /*! header [] data */ - - /** - * Elements for cookies[]: are defined by the HTTP request - */ - ESP_COOKIES_OBJ = 4, /*! cookies[] data */ - - /** - * Elements for files[]: are defined by the HTTP request - * CLIENT_FILENAME CONTENT_TYPE FILENAME SIZE - */ - ESP_FILES_OBJ = 5, /*! files[] data */ - - /** - * Elements for form[]: are defined by the HTTP request - */ - ESP_FORM_OBJ = 6, /*! form[] data */ - - /** - * Elements for application[]: are user defined - */ - ESP_APPLICATION_OBJ = 7, /*! application[] data */ - - /** - * Elements for global[]: are defined by ESP/EJS - */ - ESP_GLOBAL_OBJ = 8, /*! global [] data */ - - /* - * Elements for local[]: are defined by ESP/EJS - */ - ESP_LOCAL_OBJ = 9, /*! local [] data */ -} EspEnvType; - -#define ESP_OBJ_MAX 10 /* Total objects */ - -#if BLD_SQUEEZE -#define ESP_HASH_SIZE 19 /* Size of hash tables */ -#else -#define ESP_HASH_SIZE 37 -#endif - -/******************************************************************************/ -#endif /* _h_ESP_ENV_h */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/esp/espProcs.c b/source4/lib/appweb/esp/espProcs.c deleted file mode 100644 index 7b5dfe680e..0000000000 --- a/source4/lib/appweb/esp/espProcs.c +++ /dev/null @@ -1,249 +0,0 @@ -/* - * @file espProcs.c - * @brief Embedded Server Pages (ESP) Procedures. - * @overview These ESP procedures can be used in ESP pages for common tasks. - */ -/********************************* Copyright **********************************/ -/* - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -/********************************** Includes **********************************/ - -#include "esp.h" - -/************************************ Code ************************************/ -#if BLD_FEATURE_ESP_MODULE -#if BLD_FEATURE_SESSION -/* - * destroySession - */ - -static int destroySessionProc(EspRequest *ep, int argc, char **argv) -{ - ep->esp->destroySession(ep->requestHandle); - return 0; -} - -#endif /* BLD_FEATURE_SESSION */ - -/******************************************************************************/ -/* - * include - * - * This includes javascript libraries. For example: - * - * <% include("file", ...); %> - * - * Don't confuse with ESP includes: - * - * <% include file.esp %> - * - * Filenames are relative to the base document including the file. - * FUTURE -- move back to EJS. Only here now because we need ep->readFile. - */ - -static int includeProc(EspRequest *ep, int argc, char **argv) -{ - const Esp *esp; - char path[MPR_MAX_FNAME], dir[MPR_MAX_FNAME]; - char *emsg=NULL, *buf; - int size, i; - - esp = ep->esp; - mprAssert(argv); - for (i = 0; i < argc; i++) { - const char *extension; - - if (argv[i][0] != '/') { - mprGetDirName(dir, sizeof(dir), ep->docPath); - mprSprintf(path, sizeof(path), "%s/%s", dir, argv[i]); - } else { - mprSprintf(path, sizeof(path), "%s", argv[i]); - } - - if (esp->readFile(ep->requestHandle, &buf, &size, path) < 0) { - espError(ep, "Can't read include file: %s", path); - return MPR_ERR_CANT_ACCESS; - } - buf[size] = '\0'; - - extension = strrchr(argv[i], '.'); - - /* - * Allow nested inclusion of ESP requests - */ - if (extension && mprStrCmpAnyCase(extension, ".esp") == 0) { - if (espProcessRequest(ep, path, buf, &emsg) != 0) { - espError(ep, "Cant evaluate script - %s", emsg?emsg:""); - mprFree(buf); - return -1; - } - } else { - if (ejsEvalScript(espGetScriptHandle(ep), buf, 0, &emsg) < 0) { - espError(ep, "Cant evaluate script - %s", emsg?emsg:""); - mprFree(buf); - return -1; - } - } - mprFree(buf); - } - return 0; -} - -/******************************************************************************/ -/* - * redirect - * - * This implemements <% redirect(url, code); %> command. The redirection - * code is optional. - */ - -static int redirectProc(EspRequest *ep, int argc, char **argv) -{ - char *url; - int code; - - if (argc < 1) { - espError(ep, "Bad args"); - return MPR_ERR_BAD_ARGS; - } - url = argv[0]; - if (argc == 2) { - code = atoi(argv[1]); - } else { - code = 302; - } - espRedirect(ep, code, url); - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_SESSION -/* - * useSession - */ - -static int useSessionProc(EspRequest *ep, int argc, char **argv) -{ - int timeout; - - if (argc > 1) { - espError(ep, "Bad args"); - return MPR_ERR_BAD_ARGS; - - } else if (argc == 1) { - timeout = atoi(argv[0]); - } else { - timeout = 0; - } - - ep->esp->createSession(ep->requestHandle, timeout); - espSetReturnString(ep, ep->esp->getSessionId(ep->requestHandle)); - return 0; -} - -#endif /* BLD_FEATURE_SESSION */ -/******************************************************************************/ -/* - * setHeader - * - * This implemements <% setHeader("key: value", allowMultiple); %> command. - */ - -static int setHeaderProc(EspRequest *ep, int argc, char **argv) -{ - mprAssert(argv); - if (argc != 2) { - espError(ep, "Bad args"); - return MPR_ERR_BAD_ARGS; - } - ep->esp->setHeader(ep->requestHandle, argv[0], atoi(argv[1])); - return 0; -} - -/******************************************************************************/ -/* - * write - * - * This implemements <% write("text"); %> command. - */ - -static int writeProc(EspRequest *ep, int argc, char **argv) -{ - char *s; - int i, len; - - mprAssert(argv); - for (i = 0; i < argc; i++) { - s = argv[i]; - len = strlen(s); - if (len > 0) { - if (espWrite(ep, s, len) != len) { - espError(ep, "Can't write to client"); - return -1; - } - } - } - return 0; -} - -/******************************************************************************/ - -void espRegisterProcs() -{ - espDefineStringCFunction(0, "write", writeProc, 0); - espDefineStringCFunction(0, "setHeader", setHeaderProc, 0); - espDefineStringCFunction(0, "redirect", redirectProc, 0); - espDefineStringCFunction(0, "include", includeProc, 0); - -#if BLD_FEATURE_SESSION - /* - * Create and use are synonomous - */ - espDefineStringCFunction(0, "useSession", useSessionProc, 0); - espDefineStringCFunction(0, "createSession", useSessionProc, 0); - espDefineStringCFunction(0, "destroySession", destroySessionProc, 0); -#endif -} - -/******************************************************************************/ - -#else -void mprEspControlsDummy() {} - -#endif /* BLD_FEATURE_ESP_MODULE */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/mpr/miniMpr.c b/source4/lib/appweb/mpr/miniMpr.c deleted file mode 100644 index 381815eb23..0000000000 --- a/source4/lib/appweb/mpr/miniMpr.c +++ /dev/null @@ -1,522 +0,0 @@ -/* - * @file miniMpr.cpp - * @brief Mini Mbedthis Portable Runtime (MPR) - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -#include "miniMpr.h" -#include "param/param.h" -#include "lib/events/events.h" - -/************************************ Code ************************************/ -#if !BLD_APPWEB -#if !BLD_GOAHEAD_WEBSERVER - -static void *mpr_ctx; - -/* set the memory context to be used for all ejs variables */ -void mprSetCtx(TALLOC_CTX *ctx) -{ - mpr_ctx = ctx; -} - -/* return the memory context being used for all ejs variables */ -void *mprMemCtx(void) -{ - return mpr_ctx; -} - -struct event_context *mprEventCtx(void) -{ - return event_context_find(mprMemCtx()); -} - -/* return the loadparm context being used for all ejs variables */ -struct loadparm_context *mprLpCtx(void) -{ - return global_loadparm; -} - -void mprFree(void *ptr) -{ - talloc_free(ptr); -} - -void *mprMalloc(uint size) -{ - return talloc_size(mpr_ctx, size); -} - -/******************************************************************************/ - -void *mprRealloc(void *ptr, uint size) -{ - return talloc_realloc_size(mpr_ctx, ptr, size); -} - -/******************************************************************************/ - -char *mprStrdup(const char *str) -{ - if (str == 0) { - str = ""; - } - return talloc_strdup(mpr_ctx, str); -} - -/*****************************************************************************/ - -int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) -{ - va_list args; - char *buf; - int count; - - va_start(args, fmt); - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - va_end(args); - return count; -} - -/*****************************************************************************/ - -int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, va_list args) -{ - char *buf; - int count; - - buf = mprMalloc(maxSize + 1); - count = mtVsprintf(buf, maxSize, fmt, args); - *msgbuf = buf; - return count; -} - - -/*****************************************************************************/ -/* - * Format a number as a string. FUTURE -- reverse args to be standard. - * ie. mprItoa(char *userBuf, int bufsize, int value); - */ - -char *mprItoa(int value, char *buf, int width) -{ - char numBuf[16]; - char *cp, *dp, *endp; - int negative; - - cp = &numBuf[sizeof(numBuf)]; - *--cp = '\0'; - - if (value < 0) { - negative = 1; - value = -value; - width--; - } else { - negative = 0; - } - - do { - *--cp = '0' + (value % 10); - value /= 10; - } while (value > 0); - - if (negative) { - *--cp = '-'; - } - - dp = buf; - endp = &buf[width]; - while (dp < endp && *cp) { - *dp++ = *cp++; - } - *dp++ = '\0'; - return buf; -} - -/*****************************************************************************/ - -void mprLog(int level, const char *fmt, ...) -{ - va_list args; - char *buf; - - if (DEBUGLVL(level)) { - va_start(args, fmt); - mprAllocVsprintf(&buf, MPR_MAX_STRING, fmt, args); - va_end(args); - DEBUG(level, ("mprLog: %s", buf)); - mprFree(buf); - } -} - -/*****************************************************************************/ - -void mprBreakpoint(const char *file, int line, const char *cond) -{ - char *buf; - mprAllocSprintf(&buf, MPR_MAX_STRING, "esp exception - ASSERT at %s:%d, %s\n", - file, line, cond); - ejs_exception(buf); -} - -#endif /* !BLD_GOAHEAD_WEBSERVER */ -/*****************************************************************************/ -/* - * Create a general growable array structure - */ - -MprArray *mprCreateArray() -{ - MprArray *array; - int size; - - array = (MprArray*) mprMalloc(sizeof(MprArray)); - if (array == 0) { - return 0; - } - memset(array, 0, sizeof(MprArray)); - - size = MPR_ARRAY_INCR * sizeof(void*); - array->handles = (void**) mprMalloc(size); - if (array->handles == 0) { - mprFree(array); - return 0; - } - memset(array->handles, 0, size); - array->max = MPR_ARRAY_INCR; - array->used = 0; - return array; -} - -/*****************************************************************************/ -/* - * Dispose of the array. Callers responsibility to dispose of handle entries. - */ - -void mprDestroyArray(MprArray *array) -{ - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - mprFree(array->handles); - mprFree(array); -} - -/*****************************************************************************/ -/* - * Add an item to the array - */ - -int mprAddToArray(MprArray *array, void *item) -{ - int memsize, idx, len; - - mprAssert(array); - mprAssert(array->max >= 0); - mprAssert(array->used >= 0); - - if (array->used < array->max) { - idx = array->used++; - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - - for (idx = array->used; idx < array->max; idx++) { - if (array->handles[idx] == 0) { - array->used++; - mprAssert(array->handles[idx] == 0); - array->handles[idx] = item; - return idx; - } - } - - len = array->max + MPR_ARRAY_INCR; - memsize = len * sizeof(void*); - array->handles = (void**) mprRealloc((void*) array->handles, memsize); - if (array->handles == NULL) { - return -1; - } - memset(&array->handles[array->max], 0, sizeof(void*) * MPR_ARRAY_INCR); - array->max = len; - array->used++; - - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] == 0); - - array->handles[idx] = item; - return idx; -} - -/*****************************************************************************/ -/* - * Remove from the array - */ - -int mprRemoveFromArray(MprArray *array, int idx) -{ - mprAssert(array); - mprAssert(array->max > 0); - mprAssert(idx >= 0 && idx < array->max); - mprAssert(array->handles[idx] != 0); - mprAssert(array->used > 0); - - array->handles[idx] = 0; - return --array->used; -} - -/*****************************************************************************/ -/* - * Thread-safe wrapping of strtok. Note "str" is modifed as per strtok() - */ - -char *mprStrTok(char *str, const char *delim, char **tok) -{ - char *start, *end; - int i; - - start = str ? str : *tok; - - if (start == 0) { - return 0; - } - - i = strspn(start, delim); - start += i; - if (*start == '\0') { - *tok = 0; - return 0; - } - end = strpbrk(start, delim); - if (end) { - *end++ = '\0'; - i = strspn(end, delim); - end += i; - } - *tok = end; - return start; -} - -/*****************************************************************************/ - -static int mprCoreStrcat(int alloc, char **destp, int destMax, int existingLen, - const char *delim, const char *src, va_list args) -{ - va_list ap; - char *dest, *dp; - const char *str; - int sepLen, addBytes, required; - - mprAssert(destp); - mprAssert(destMax > 0); - mprAssert(src); - - dest = *destp; - sepLen = (delim) ? strlen(delim) : 0; - - va_copy(ap, args); - addBytes = 0; - str = src; - while (str) { - addBytes += strlen(str) + sepLen; - str = va_arg(ap, const char*); - } - va_end(ap); - - if (existingLen > 0) { - addBytes += sepLen; - } - required = existingLen + addBytes + 1; - if (required >= destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - - if (alloc) { - if (dest == 0) { - dest = (char*) mprMalloc(required); - } else { - dest = (char*) mprRealloc(dest, required); - } - } else { - dest = (char*) *destp; - } - - dp = &dest[existingLen]; - if (delim) { - strcpy(dp, delim); - dp += sepLen; - } - - if (addBytes > 0) { - va_copy(ap, args); - str = src; - while (str) { - strcpy(dp, str); - dp += strlen(str); - str = va_arg(ap, char*); - if (delim && str) { - strcpy(dp, delim); - dp += sepLen; - } - } - va_end(ap); - } else if (dest == 0) { - dest = (char*) mprMalloc(1); - } - *dp = '\0'; - - *destp = dest; - mprAssert(dp < &dest[required]); - return required - 1; -} - -/***************************************************************************** - Note that this VARARGS function must be NULL (not 0, this must be a - pointer) terminated -*/ - -int mprReallocStrcat(char **destp, int destMax, int existingLen, - const char *delim, const char *src,...) -{ - va_list ap; - int rc; - - va_start(ap, src); - rc = mprCoreStrcat(1, destp, destMax, existingLen, delim, src, ap); - va_end(ap); - return rc; -} - -/*****************************************************************************/ -/* - * Return the directory portion of a pathname into the users buffer. - */ - -int mprGetDirName(char *buf, int bufsize, char *path) -{ - char *cp; - int dlen; - - mprAssert(path); - mprAssert(buf); - mprAssert(bufsize > 0); - - cp = strrchr(path, '/'); - if (cp == 0) { -#if WIN - cp = strrchr(path, '\\'); - if (cp == 0) -#endif - { - buf[0] = '\0'; - return 0; - } - } - - if (cp == path && cp[1] == '\0') { - strcpy(buf, "."); - return 0; - } - - dlen = cp - path; - if (dlen < bufsize) { - if (dlen == 0) { - dlen++; - } - mprMemcpy(buf, bufsize, path, dlen); - buf[dlen] = '\0'; - return 0; - } - return MPR_ERR_WONT_FIT; -} - -/*****************************************************************************/ - -int mprStrcpy(char *dest, int destMax, const char *src) -{ - int len; - - mprAssert(dest); - mprAssert(destMax > 0); - mprAssert(src); - - len = strlen(src); - if (len >= destMax && len > 0) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (len > 0) { - memcpy(dest, src, len); - dest[len] = '\0'; - } else { - *dest = '\0'; - len = 0; - } - return len; -} - -/*****************************************************************************/ - -int mprMemcpy(char *dest, int destMax, const char *src, int nbytes) -{ - mprAssert(dest); - mprAssert(destMax > nbytes); - mprAssert(src); - mprAssert(nbytes > 0); - - if (nbytes > destMax) { - mprAssert(0); - return MPR_ERR_WONT_FIT; - } - if (nbytes > 0) { - memcpy(dest, src, nbytes); - return nbytes; - } else { - return 0; - } -} - -/*****************************************************************************/ -#else -void miniMprDummy() {} -#endif // !BLD_APPWEB && !BLD_GOAHEAD_WEBSERVER - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/mpr/miniMpr.h b/source4/lib/appweb/mpr/miniMpr.h deleted file mode 100644 index 2b8ff0af6a..0000000000 --- a/source4/lib/appweb/mpr/miniMpr.h +++ /dev/null @@ -1,301 +0,0 @@ -/* - * @file miniMpr.h - * @brief Mini Mbedthis Portable Runtime (MPR) Environment. - * @copy default - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ -#ifndef _h_MINI_MPR -#define _h_MINI_MPR 1 - -/********************************** Includes **********************************/ -/* - * Find out about our configuration - */ -#ifndef _INCLUDES_H - #include "includes.h" -#endif - -/* allow this library to use strcpy() */ -#undef strcpy - #include "lib/appweb/ejs/config.h" - -#if BLD_APPWEB - /* - * If building within AppWeb, use the full MPR - */ - #include "mpr.h" -#else - - #include <ctype.h> - #include <fcntl.h> - #include <stdarg.h> - #include <stdlib.h> - #include <stdio.h> - #include <string.h> - #include <sys/stat.h> - -#if !WIN - #include <unistd.h> -#endif - -#if CE - #include <io.h> - #include "CE/wincompat.h" -#endif - -#if LYNX - #include <unistd.h> -#endif - -#if QNX4 - #include <dirent.h> -#endif -#ifdef HAVE_MATH_H - #include <math.h> -#endif -/********************************** Defines ***********************************/ - -#ifdef __cplusplus -extern "C" { -#endif - -#if BLD_FEATURE_SQUEEZE -/* - * Reasonable length of a file path name to use in most cases where you know - * the expected file name and it is certain to be less than this limit. - */ -#define MPR_MAX_FNAME 128 -#define MPR_MAX_STRING 512 -#define MPR_DEFAULT_HASH_SIZE 23 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (32 * 1024) -#else -#define MPR_MAX_FNAME 256 -#define MPR_MAX_STRING 4096 -#define MPR_DEFAULT_HASH_SIZE 43 /* Default size of hash table index */ -#define MPR_MAX_HEAP_SIZE (64 * 1024) -#endif - -/* - * Useful for debugging - */ -#define MPR_L __FILE__, __LINE__ - -#if BLD_FEATURE_ASSERT -#define mprAssert(C) \ - if (C) ; else mprBreakpoint(__FILE__, __LINE__, #C) -#else - #define mprAssert(C) if (1) ; else -#endif - -/* - * Standard MPR return and error codes - */ -#define MPR_ERR_BASE (-200) /* Error code */ -#define MPR_ERR_GENERAL (MPR_ERR_BASE - 1) /* Error code */ -#define MPR_ERR_ABORTED (MPR_ERR_BASE - 2) /* Error code */ -#define MPR_ERR_ALREADY_EXISTS (MPR_ERR_BASE - 3) /* Error code */ -#define MPR_ERR_BAD_ARGS (MPR_ERR_BASE - 4) /* Error code */ -#define MPR_ERR_BAD_FORMAT (MPR_ERR_BASE - 5) /* Error code */ -#define MPR_ERR_BAD_HANDLE (MPR_ERR_BASE - 6) /* Error code */ -#define MPR_ERR_BAD_STATE (MPR_ERR_BASE - 7) /* Error code */ -#define MPR_ERR_BAD_SYNTAX (MPR_ERR_BASE - 8) /* Error code */ -#define MPR_ERR_BAD_TYPE (MPR_ERR_BASE - 9) /* Error code */ -#define MPR_ERR_BAD_VALUE (MPR_ERR_BASE - 10) /* Error code */ -#define MPR_ERR_BUSY (MPR_ERR_BASE - 11) /* Error code */ -#define MPR_ERR_CANT_ACCESS (MPR_ERR_BASE - 12) /* Error code */ -#define MPR_ERR_CANT_COMPLETE (MPR_ERR_BASE - 13) /* Error code */ -#define MPR_ERR_CANT_CREATE (MPR_ERR_BASE - 14) /* Error code */ -#define MPR_ERR_CANT_INITIALIZE (MPR_ERR_BASE - 15) /* Error code */ -#define MPR_ERR_CANT_OPEN (MPR_ERR_BASE - 16) /* Error code */ -#define MPR_ERR_CANT_READ (MPR_ERR_BASE - 17) /* Error code */ -#define MPR_ERR_CANT_WRITE (MPR_ERR_BASE - 18) /* Error code */ -#define MPR_ERR_DELETED (MPR_ERR_BASE - 19) /* Error code */ -#define MPR_ERR_NETWORK (MPR_ERR_BASE - 20) /* Error code */ -#define MPR_ERR_NOT_FOUND (MPR_ERR_BASE - 21) /* Error code */ -#define MPR_ERR_NOT_INITIALIZED (MPR_ERR_BASE - 22) /* Error code */ -#define MPR_ERR_NOT_READY (MPR_ERR_BASE - 23) /* Error code */ -#define MPR_ERR_READ_ONLY (MPR_ERR_BASE - 24) /* Error code */ -#define MPR_ERR_TIMEOUT (MPR_ERR_BASE - 25) /* Error code */ -#define MPR_ERR_TOO_MANY (MPR_ERR_BASE - 26) /* Error code */ -#define MPR_ERR_WONT_FIT (MPR_ERR_BASE - 27) /* Error code */ -#define MPR_ERR_WOULD_BLOCK (MPR_ERR_BASE - 28) /* Error code */ -#define MPR_ERR_CANT_ALLOCATE (MPR_ERR_BASE - 29) /* Error code */ -#define MPR_ERR_MAX (MPR_ERR_BASE - 30) /* Error code */ - -/* - * Standard error severity and trace levels. These are ored with the error - * severities below. The MPR_LOG_MASK is used to extract the trace level - * from a flags word. We expect most apps to run with level 2 trace. - */ -#define MPR_FATAL 0 /* Fatal error. Cant continue. */ -#define MPR_ERROR 1 /* Hard error */ -#define MPR_WARN 2 /* Soft warning */ -#define MPR_CONFIG 2 /* Essential configuration settings */ -#define MPR_INFO 3 /* Informational only */ -#define MPR_DEBUG 4 /* Debug information */ -#define MPR_VERBOSE 9 /* Highest level of trace */ -#define MPR_LOG_MASK 0xf /* Level mask */ - -/* - * Error flags. Specify where the error should be sent to. Note that the - * product.xml setting "headless" will modify how errors are reported. - * Assert errors are trapped when in DEV mode. Otherwise ignored. - */ -#define MPR_TRAP 0x10 /* Assert error -- trap in debugger */ -#define MPR_LOG 0x20 /* Log the error in the O/S event log */ -#define MPR_USER 0x40 /* Display to the user */ -#define MPR_ALERT 0x80 /* Send a management alert */ -#define MPR_TRACE 0x100 /* Trace */ - -/* - * Error format flags - */ -#define MPR_RAW 0x200 /* Raw trace output */ - -/* - * Error line number information - */ -#define MPR_L __FILE__, __LINE__ - -typedef char* MprStr; - -#ifndef __cplusplus -typedef unsigned char uchar; -#endif - -/* - * Porters: put other operating system type defines here - */ -#if WIN - typedef unsigned int uint; - typedef __int64 int64; - typedef unsigned __int64 uint64; -#else -#define O_BINARY 0 -#ifndef uint - #define uint unsigned -#endif - #define int64 int64_t - #define uint64 uint64_t -#endif - -/* - * Flexible array data type - */ -typedef struct { - int max; /* Size of the handles array */ - int used; /* Count of used entries in handles */ - void **handles; -} MprArray; - -#if BLD_FEATURE_SQUEEZE -#define MPR_ARRAY_INCR 8 -#else -#define MPR_ARRAY_INCR 16 -#endif - -#ifndef max -#define max(a,b) (((a) > (b)) ? (a) : (b)) -#endif - -/********************************* Prototypes *********************************/ -/* - * If running in the GoAhead WebServer, map some MPR routines to WebServer - * equivalents. - */ - -#if BLD_GOAHEAD_WEBSERVER -#include "uemf.h" -#define mprMalloc(size) balloc(B_L, size) -#define mprFree(ptr) bfreeSafe(B_L, ptr) -#define mprRealloc(ptr, size) brealloc(B_L, ptr, size) -#define mprStrdup(ptr) bstrdup(B_L, ptr) -#define mprAllocSprintf fmtAlloc -#define mprAllocVsprintf fmtValloc -#define mprSprintf fmtStatic -#define mprItoa stritoa -#define mprLog trace -#define mprBreakpoint(file, line, cond) \ - error(file, line, E_BLD_FEATURE_ASSERT, T("%s"), cond) - -#else /* !BLD_GOAHEAD_WEBSERVER */ -/* #define mprMalloc malloc */ -#define mprSprintf snprintf -#define mtVsprintf vsnprintf -extern void *mprMalloc(uint size); -extern void *mprRealloc(void *ptr, uint size); -extern void mprFree(void *ptr); -extern char *mprStrdup(const char *str); -extern int mprAllocVsprintf(char **msgbuf, int maxSize, const char *fmt, - va_list args) PRINTF_ATTRIBUTE(3,0); -extern int mprAllocSprintf(char **msgbuf, int maxSize, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4); -extern char *mprItoa(int num, char *buf, int width); -extern void mprLog(int level, const char *fmt, ...) PRINTF_ATTRIBUTE(2,3); -extern void mprBreakpoint(const char *file, int line, const char *msg) _NORETURN_; -#endif /* BLD_GOAHEAD_WEBSERVER */ - -extern MprArray *mprCreateArray(void); -extern void mprDestroyArray(MprArray *array); -extern int mprAddToArray(MprArray *array, void *item); -extern int mprRemoveFromArray(MprArray *array, int idx); -extern char *mprStrTok(char *str, const char *delim, char **tok); - -extern int mprGetDirName(char *buf, int bufsize, char *path); -extern int mprReallocStrcat(char **dest, int max, int existingLen, - const char *delim, const char *src, ...); -extern int mprStrcpy(char *dest, int destMax, const char *src); -extern int mprMemcpy(char *dest, int destMax, const char *src, int nbytes); - -extern void mprSetCtx(void *ctx); -extern void *mprMemCtx(void); -struct loadparm_context; -extern struct loadparm_context *mprLpCtx(void); -struct event_context; -extern struct event_context *mprEventCtx(void); - -/* This function needs to be provided by anyone using ejs */ -void ejs_exception(const char *reason); - -#define mprStrCmpAnyCase(s1, s2) strcasecmp_m(s1, s2) - -#ifdef __cplusplus -} -#endif -#endif /* !BLD_APPWEB */ -#endif /* _h_MINI_MPR */ - -/*****************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/mpr/var.c b/source4/lib/appweb/mpr/var.c deleted file mode 100644 index e73da773ea..0000000000 --- a/source4/lib/appweb/mpr/var.c +++ /dev/null @@ -1,2215 +0,0 @@ -/* - * @file var.c - * @brief MPR Universal Variable Type - * @overview - * - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ - -/* - * This module is NOT multithreaded. - * - * Properties are variables that are stored in an object type variable. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. - */ - -/********************************** Includes **********************************/ - -#include "var.h" - -/*********************************** Locals ***********************************/ -#if VAR_DEBUG - -static MprProperties objectList; /* Dummy head of objects list */ -static int objectCount = -1; /* Count of objects */ - -#endif -/***************************** Forward Declarations ***************************/ - -static int adjustRefCount(MprProperties *pp, int adj); -static int adjustVarRefCount(MprVar *vp, int adj); -static MprVar *allocProperty(const char *propertyName); -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth); -static MprProperties - *createProperties(const char *name, int hashSize); -static bool freeVar(MprVar *vp, int force); -static bool freeVarStorage(MprVar *vp, int force); -static MprVar *getObjChain(MprProperties *pp, const char *property); -static int hash(MprProperties *pp, const char *property); -static bool releaseProperties(MprProperties *pp, int force); - -/*********************************** Code *************************************/ -/* - * Destroy a variable and all referenced variables. Release any referenced - * object regardless of whether other users still have references. Be VERY - * careful using this routine. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyAllVars(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all vars. - */ - return freeVar(vp, 1); -} - -/******************************************************************************/ -/* - * Destroy a variable. Release any referenced object (destroy if no other - * users are referencing). - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -bool mprDestroyVar(MprVar *vp) -{ - mprAssert(vp); - - if (vp->trigger) { - if ((vp->trigger)(MPR_VAR_DELETE, vp->parentProperties, vp, 0, 0) - == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Free the actual value. If this var refers to an object, we will - * recurse through all the properties freeing all that have no other - * references. - */ - return freeVar(vp, 0); -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVar(MprVar *vp, int force) -{ - bool freed; - - mprAssert(vp); - - freed = freeVarStorage(vp, force); - - mprFree(vp->name); - mprFree(vp->fullName); - - if (vp->allocatedVar) { - mprFree(vp); - } else { - vp->name = 0; - vp->fullName = 0; - vp->type = MPR_TYPE_UNDEFINED; - } - return freed; -} - -/******************************************************************************/ -/* - * Free the value in a variable for primitive types. Release objects. - * - * Return TRUE if the underlying data is freed. Objects may not be freed if - * there are other users of the object. - */ - -static bool freeVarStorage(MprVar *vp, int force) -{ - MprArray *argList; - bool freed; - int i; - - freed = 1; - mprAssert(vp); - - switch (vp->type) { - default: - break; - - case MPR_TYPE_STRING: - if (vp->allocatedData && vp->string != 0) { - mprFree(vp->string); - vp->string = 0; - vp->allocatedData = 0; - } - break; - - case MPR_TYPE_PTR: - if (vp->allocatedData) { - vp->allocatedData = 0; - mprFree(vp->ptr); - } - break; - - case MPR_TYPE_OBJECT: -#if VAR_DEBUG - /* - * Recurse through all properties and release / delete. Release the - * properties hash table. - */ - if (vp->properties->refCount > 1) { - mprLog(7, "freeVar: ACT \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } else { - mprLog(7, "freeVar: DEL \"%s\", 0x%x, ref %d, force %d\n", - vp->name, vp->properties, vp->properties->refCount, force); - } -#endif - if (vp->allocatedData) { - freed = releaseProperties(vp->properties, force); - } - vp->properties = 0; - break; - - case MPR_TYPE_FUNCTION: - if (vp->allocatedData) { - argList = vp->function.args; - for (i = 0; i < argList->max; i++) { - if (argList->handles[i] != 0) { - mprFree(argList->handles[i]); - } - } - mprDestroyArray(argList); - vp->function.args = 0; - mprFree(vp->function.body); - vp->function.body = 0; - } - break; - } - - vp->type = MPR_TYPE_UNDEFINED; - return freed; -} - -/******************************************************************************/ -/* - * Adjust the object reference count and return the currrent count of - * users. - */ - -static int adjustVarRefCount(MprVar *vp, int adj) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, adj); -} - -/******************************************************************************/ -/* - * Get the object reference count - */ - -int mprGetVarRefCount(MprVar *vp) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - mprAssert(vp->type == MPR_TYPE_OBJECT); - return 0; - } - return adjustRefCount(vp->properties, 0); -} - -/******************************************************************************/ -/* - * Update the variable's name - */ - -void mprSetVarName(MprVar *vp, char *name) -{ - mprAssert(vp); - - mprFree(vp->name); - vp->name = mprStrdup(name); -} - -/******************************************************************************/ -/* - * Append to the variable's full name - */ - -void mprSetVarFullName(MprVar *vp, char *name) -{ -#if VAR_DEBUG - mprAssert(vp); - - mprFree(vp->fullName); - vp->fullName = mprStrdup(name); - if (vp->type == MPR_TYPE_OBJECT) { - if (strcmp(vp->properties->name, "this") == 0) { - mprStrcpy(vp->properties->name, sizeof(vp->properties->name), name); - } - } -#endif -} - -/******************************************************************************/ -/* - * Make a var impervious to recursive forced deletes. - */ - -void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect) -{ - mprAssert(vp); - - if (vp->type == MPR_TYPE_OBJECT && vp->properties) { - vp->properties->deleteProtect = deleteProtect; - } -} - -/******************************************************************************/ -/* - * Make a variable readonly. Can still be deleted. - */ - -void mprSetVarReadonly(MprVar *vp, int readonly) -{ - mprAssert(vp); - - vp->readonly = readonly; -} - -/******************************************************************************/ - -MprVarTrigger mprAddVarTrigger(MprVar *vp, MprVarTrigger fn) -{ - MprVarTrigger oldTrigger; - - mprAssert(vp); - mprAssert(fn); - - oldTrigger = vp->trigger; - vp->trigger = fn; - return oldTrigger; -} - -/******************************************************************************/ - -MprType mprGetVarType(MprVar *vp) -{ - mprAssert(vp); - - return vp->type; -} - -/******************************************************************************/ -/********************************** Properties ********************************/ -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. - */ - -MprVar *mprCreateProperty(MprVar *obj, const char *propertyName, - MprVar *newValue) -{ - MprVar *prop, *last; - int bucketIndex; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - /* - * See if property already exists and locate the bucket to hold the - * property reference. - */ - last = 0; - bucketIndex = hash(obj->properties, propertyName); - prop = obj->properties->buckets[bucketIndex]; - - /* - * Find the property in the hash chain if it exists - */ - for (last = 0; prop; last = prop, prop = prop->forw) { - if (prop->name[0] == propertyName[0] && - strcmp(prop->name, propertyName) == 0) { - break; - } - } - - if (prop) { - /* FUTURE -- remove. Just for debug. */ - mprAssert(prop == 0); - mprLog(0, "Attempting to create property %s in object %s\n", - propertyName, obj->name); - return 0; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_CREATE_PROPERTY, obj->properties, prop, - newValue, 0) == MPR_TRIGGER_ABORT) { - return 0; - } - } - - /* - * Create a new property - */ - prop = allocProperty(propertyName); - if (prop == 0) { - mprAssert(prop); - return 0; - } - - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - - prop->bucketIndex = bucketIndex; - if (last) { - last->forw = prop; - } else { - obj->properties->buckets[bucketIndex] = prop; - } - prop->parentProperties = obj->properties; - - /* - * Update the item counts - */ - obj->properties->numItems++; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems++; - } - - return prop; -} - -/******************************************************************************/ -/* - * Create a property in an object with a defined value. If the property - * already exists in the object, then just write its value. Same as - * mprCreateProperty except that the new value is passed by value rather than - * by pointer. - */ - -MprVar *mprCreatePropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprCreateProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Create a new property - */ - -static MprVar *allocProperty(const char *propertyName) -{ - MprVar *prop; - - prop = (MprVar*) mprMalloc(sizeof(MprVar)); - if (prop == 0) { - mprAssert(prop); - return 0; - } - memset(prop, 0, sizeof(MprVar)); - prop->allocatedVar = 1; - prop->name = mprStrdup(propertyName); - prop->forw = (MprVar*) 0; - - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it doesn not already exist. - */ - -MprVar *mprSetProperty(MprVar *obj, const char *propertyName, MprVar *newValue) -{ - MprVar *prop, triggerValue; - int rc; - - mprAssert(obj); - mprAssert(propertyName && *propertyName); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(0); - return 0; - } - - prop = mprGetProperty(obj, propertyName, 0); - if (prop == 0) { - return mprCreateProperty(obj, propertyName, newValue); - } - - if (obj->trigger) { - /* - * Call the trigger before the update and pass it the new value. - */ - triggerValue = *newValue; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (obj->trigger)(MPR_VAR_WRITE, obj->properties, obj, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - /* - * Trigger must copy to triggerValue a variable that is not - * a structure copy of the existing data. - */ - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return prop; - } - } - copyVarCore(prop, newValue, MPR_SHALLOW_COPY); - return prop; -} - -/******************************************************************************/ -/* - * Update a property in an object with a defined value. Create the property - * if it does not already exist. Same as mprSetProperty except that the - * new value is passed by value rather than by pointer. - */ - -MprVar *mprSetPropertyValue(MprVar *obj, const char *propertyName, - MprVar newValue) -{ - return mprSetProperty(obj, propertyName, &newValue); -} - -/******************************************************************************/ -/* - * Delete a property from this object - */ - -int mprDeleteProperty(MprVar *obj, const char *property) -{ - MprVar *prop, *last; - char *cp; - int bucketIndex; - - mprAssert(obj); - mprAssert(property && *property); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - last = 0; - bucketIndex = hash(obj->properties, property); - if ((prop = obj->properties->buckets[bucketIndex]) != 0) { - for ( ; prop; prop = prop->forw) { - cp = prop->name; - if (cp[0] == property[0] && strcmp(cp, property) == 0) { - break; - } - last = prop; - } - } - if (prop == (MprVar*) 0) { - mprAssert(prop); - return MPR_ERR_NOT_FOUND; - } - if (prop->readonly) { - mprAssert(! prop->readonly); - return MPR_ERR_READ_ONLY; - } - - if (obj->trigger) { - if ((obj->trigger)(MPR_VAR_DELETE_PROPERTY, obj->properties, prop, 0, 0) - == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - } - } - - if (last) { - last->forw = prop->forw; - } else { - obj->properties->buckets[bucketIndex] = prop->forw; - } - - obj->properties->numItems--; - if (! mprVarIsFunction(prop->type)) { - obj->properties->numDataItems--; - } - - mprDestroyVar(prop); - - return 0; -} - -/******************************************************************************/ -/* - * Find a property in an object and return a pointer to it. If a value arg - * is supplied, then copy the data into the var. - */ - -MprVar *mprGetProperty(MprVar *obj, const char *property, MprVar *value) -{ - MprVar *prop, triggerValue; - int rc; - - if (obj == 0 || obj->type != MPR_TYPE_OBJECT || property == 0 || - *property == '\0') { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - - for (prop = getObjChain(obj->properties, property); prop; - prop = prop->forw) { - if (prop->name && - prop->name[0] == property[0] && strcmp(prop->name, property) == 0) { - break; - } - } - if (prop == 0) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - } - if (value) { - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - /* - * Pass the trigger the current read value and may receive - * a new value. - */ - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - if (rc == MPR_TRIGGER_ABORT) { - if (value) { - value->type = MPR_TYPE_UNDEFINED; - } - return 0; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - } - } - /* - * Clone. No copy. - */ - *value = *prop; - } - return prop; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns the property's value. It does not - * copy object/string data but returns a pointer directly into the variable. - * The caller does not and should not call mprDestroy on the returned value. - * If value is null, just read the property and run triggers. - */ - -int mprReadProperty(MprVar *prop, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(prop, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - if (value) { - *value = *prop; - - /* - * Just so that if the user calls mprDestroyVar on value, it will do no - * harm. - */ - value->allocatedVar = 0; - value->allocatedData = 0; - } - return 0; -} - -/******************************************************************************/ -/* - * Read a properties value. This returns a copy of the property variable. - * However, if the property is an object or string, it returns a copy of the - * reference to the underlying data. If copyDepth is set to MPR_DEEP_COPY, - * then the underlying objects and strings data will be copied as well. If - * copyDepth is set to MPR_SHALLOW_COPY, then only strings will be copied. If - * it is set to MPR_NO_COPY, then no data will be copied. In all cases, the - * user must call mprDestroyVar to free resources. This routine will run any - * registered triggers which may modify the value the user receives (without - * updating the properties real value). - * - * WARNING: the args are reversed to most other APIs. This conforms to the - * strcpy(dest, src) standard instead. - */ - -int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth) -{ - MprVar triggerValue; - int rc; - - mprAssert(prop); - mprAssert(dest); - - if (prop->trigger) { - triggerValue = *prop; - triggerValue.allocatedVar = 0; - triggerValue.allocatedData = 0; - rc = (prop->trigger)(MPR_VAR_READ, prop->parentProperties, prop, - &triggerValue, copyDepth); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(dest, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - } - mprCopyVar(dest, prop, copyDepth); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWriteProperty(MprVar *vp, MprVar *value) -{ - MprVar triggerValue; - int rc; - - mprAssert(vp); - mprAssert(value); - - if (vp->readonly) { - return MPR_ERR_READ_ONLY; - } - - if (vp->trigger) { - triggerValue = *value; - - rc = (vp->trigger)(MPR_VAR_WRITE, vp->parentProperties, vp, - &triggerValue, 0); - - if (rc == MPR_TRIGGER_ABORT) { - return MPR_ERR_ABORTED; - - } else if (rc == MPR_TRIGGER_USE_NEW_VALUE) { - copyVarCore(vp, &triggerValue, MPR_SHALLOW_COPY); - mprDestroyVar(&triggerValue); - return 0; - } - /* Fall through */ - } - - copyVarCore(vp, value, MPR_SHALLOW_COPY); - return 0; -} - -/******************************************************************************/ -/* - * Write a new value into an existing property in an object. - */ - -int mprWritePropertyValue(MprVar *vp, MprVar value) -{ - mprAssert(vp); - - return mprWriteProperty(vp, &value); -} - -/******************************************************************************/ -/* - * Get the count of properties. - */ - -int mprGetPropertyCount(MprVar *vp, int includeFlags) -{ - mprAssert(vp); - - if (vp->type != MPR_TYPE_OBJECT) { - return 0; - } - if (includeFlags == MPR_ENUM_DATA) { - return vp->properties->numDataItems; - } else { - return vp->properties->numItems; - } -} - -/******************************************************************************/ -/* - * Get the first property in an object. Used for walking all properties in an - * object. - */ - -MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags) -{ - MprVar *prop; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - - for (i = 0; i < (int) obj->properties->hashSize; i++) { - for (prop = obj->properties->buckets[i]; prop; prop = prop->forw) { - if (prop) { - if (mprVarIsFunction(prop->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return prop; - } - break; - } - } - return 0; -} - -/******************************************************************************/ -/* - * Get the next property in sequence. - */ - -MprVar *mprGetNextProperty(MprVar *obj, MprVar *last, int includeFlags) -{ - MprProperties *properties; - int i; - - mprAssert(obj); - mprAssert(obj->type == MPR_TYPE_OBJECT); - - if (obj->type != MPR_TYPE_OBJECT) { - mprAssert(obj->type == MPR_TYPE_OBJECT); - return 0; - } - properties = obj->properties; - - if (last->forw) { - return last->forw; - } - - for (i = last->bucketIndex + 1; i < (int) properties->hashSize; i++) { - for (last = properties->buckets[i]; last; last = last->forw) { - if (mprVarIsFunction(last->type)) { - if (!(includeFlags & MPR_ENUM_FUNCTIONS)) { - continue; - } - } else { - if (!(includeFlags & MPR_ENUM_DATA)) { - continue; - } - } - return last; - } - } - return 0; -} - -/******************************************************************************/ -/************************** Internal Support Routines *************************/ -/******************************************************************************/ -/* - * Create an hash table to hold and index properties. Properties are just - * variables which may contain primitive data types, functions or other - * objects. The hash table is the essence of an object. HashSize specifies - * the size of the hash table to use and should be a prime number. - */ - -static MprProperties *createProperties(const char *name, int hashSize) -{ - MprProperties *pp; - - if (hashSize < 7) { - hashSize = 7; - } - if ((pp = (MprProperties*) mprMalloc(sizeof(MprProperties))) == NULL) { - mprAssert(0); - return 0; - } - mprAssert(pp); - memset(pp, 0, sizeof(MprProperties)); - - pp->numItems = 0; - pp->numDataItems = 0; - pp->hashSize = hashSize; - pp->buckets = (MprVar**) mprMalloc(pp->hashSize * sizeof(MprVar*)); - mprAssert(pp->buckets); - memset(pp->buckets, 0, pp->hashSize * sizeof(MprVar*)); - pp->refCount = 1; - -#if VAR_DEBUG - if (objectCount == -1) { - objectCount = 0; - objectList.next = objectList.prev = &objectList; - } - - mprStrcpy(pp->name, sizeof(pp->name), name); - pp->next = &objectList; - pp->prev = objectList.prev; - objectList.prev->next = pp; - objectList.prev = pp; - objectCount++; -#endif - return pp; -} - -/******************************************************************************/ -/* - * Release an object's properties hash table. If this is the last person - * using it, free it. Return TRUE if the object is released. - */ - -static bool releaseProperties(MprProperties *obj, int force) -{ - MprProperties *pp; - MprVar *prop, *forw; - int i; - - mprAssert(obj); - mprAssert(obj->refCount > 0); - -#if VAR_DEBUG - /* - * Debug sanity check - */ - mprAssert(obj->refCount < 20); -#endif - - if (--obj->refCount > 0 && !force) { - return 0; - } - -#if VAR_DEBUG - mprAssert(obj->prev); - mprAssert(obj->next); - mprAssert(obj->next->prev); - mprAssert(obj->prev->next); - obj->next->prev = obj->prev; - obj->prev->next = obj->next; - objectCount--; -#endif - - for (i = 0; i < (int) obj->hashSize; i++) { - for (prop = obj->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->type == MPR_TYPE_OBJECT) { - - if (prop->properties == obj) { - /* Self reference */ - continue; - } - pp = prop->properties; - if (pp->visited) { - continue; - } - - pp->visited = 1; - if (! freeVar(prop, pp->deleteProtect ? 0 : force)) { - pp->visited = 0; - } - - } else { - freeVar(prop, force); - } - } - } - - mprFree((void*) obj->buckets); - mprFree((void*) obj); - - return 1; -} - -/******************************************************************************/ -/* - * Adjust the reference count - */ - -static int adjustRefCount(MprProperties *pp, int adj) -{ - mprAssert(pp); - - /* - * Debug sanity check - */ - mprAssert(pp->refCount < 20); - - return pp->refCount += adj; -} - -/******************************************************************************/ -#if VAR_DEBUG -/* - * Print objects held - */ - -void mprPrintObjects(char *msg) -{ - MprProperties *pp, *np; - MprVar *prop, *forw; - char *buf; - int i; - - mprLog(7, "%s: Object Store. %d objects.\n", msg, objectCount); - pp = objectList.next; - while (pp != &objectList) { - mprLog(7, "%s: 0x%x, refCount %d, properties %d\n", - pp->name, pp, pp->refCount, pp->numItems); - for (i = 0; i < (int) pp->hashSize; i++) { - for (prop = pp->buckets[i]; prop; prop = forw) { - forw = prop->forw; - if (prop->properties == pp) { - /* Self reference */ - continue; - } - mprVarToString(&buf, MPR_MAX_STRING, 0, prop); - if (prop->type == MPR_TYPE_OBJECT) { - np = objectList.next; - while (np != &objectList) { - if (prop->properties == np) { - break; - } - np = np->next; - } - if (prop->properties == np) { - mprLog(7, " %s: OBJECT 0x%x, <%s>\n", - prop->name, prop->properties, prop->fullName); - } else { - mprLog(7, " %s: OBJECT NOT FOUND, %s <%s>\n", - prop->name, buf, prop->fullName); - } - } else { - mprLog(7, " %s: <%s> = %s\n", prop->name, - prop->fullName, buf); - } - mprFree(buf); - } - } - pp = pp->next; - } -} - -/******************************************************************************/ - -void mprPrintObjRefCount(MprVar *vp) -{ - mprLog(7, "OBJECT 0x%x, refCount %d\n", vp->properties, - vp->properties->refCount); -} - -#endif -/******************************************************************************/ -/* - * Get the bucket chain containing a property. - */ - -static MprVar *getObjChain(MprProperties *obj, const char *property) -{ - mprAssert(obj); - - return obj->buckets[hash(obj, property)]; -} - -/******************************************************************************/ -/* - * Fast hash. The history of this algorithm is part of lost computer science - * folk lore. - */ - -static int hash(MprProperties *pp, const char *property) -{ - uint sum; - - mprAssert(pp); - mprAssert(property); - - sum = 0; - while (*property) { - sum += (sum * 33) + *property++; - } - - return sum % pp->hashSize; -} - -/******************************************************************************/ -/*********************************** Constructors *****************************/ -/******************************************************************************/ -/* - * Initialize an undefined value. - */ - -MprVar mprCreateUndefinedVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_UNDEFINED; - return v; -} - -/******************************************************************************/ -/* - * Initialize an null value. - */ - -MprVar mprCreateNullVar() -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_NULL; - return v; -} - -/******************************************************************************/ - -MprVar mprCreateBoolVar(bool value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_BOOL; - v.boolean = value; - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_CFUNCTION; - v.cFunction.fn = fn; - v.cFunction.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize a C function. - */ - -MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, void *thisPtr, - int flags) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING_CFUNCTION; - v.cFunctionWithStrings.fn = fn; - v.cFunctionWithStrings.thisPtr = thisPtr; - v.flags = flags; - - return v; -} - -/******************************************************************************/ -/* - * Initialize an opaque pointer. - */ - -MprVar mprCreatePtrVar(void *ptr) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_PTR; - v.ptr = ptr; - - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Initialize a floating value. - */ - -MprVar mprCreateFloatVar(double value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FLOAT; - v.floating = value; - return v; -} - -#endif -/******************************************************************************/ -/* - * Initialize an integer value. - */ - -MprVar mprCreateIntegerVar(int value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT; - v.integer = value; - return v; -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Initialize a 64-bit integer value. - */ - -MprVar mprCreateInteger64Var(int64 value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_INT64; - v.integer64 = value; - return v; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Initialize an number variable. Type is defined by configure. - */ - -MprVar mprCreateNumberVar(MprNum value) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = BLD_FEATURE_NUM_TYPE_ID; -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - v.integer64 = value; -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - v.float = value; -#else - v.integer = value; -#endif - return v; -} - -/******************************************************************************/ -/* - * Initialize a (bare) JavaScript function. args and body can be null. - */ - -MprVar mprCreateFunctionVar(char *args, char *body, int flags) -{ - MprVar v; - char *cp, *arg, *last; - int aid; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_FUNCTION; - v.flags = flags; - - v.function.args = mprCreateArray(); - - if (args) { - args = mprStrdup(args); - arg = mprStrTok(args, ",", &last); - while (arg) { - while (isspace((int) *arg)) - arg++; - for (cp = &arg[strlen(arg) - 1]; cp > arg; cp--) { - if (!isspace((int) *cp)) { - break; - } - } - cp[1] = '\0'; - - aid = mprAddToArray(v.function.args, mprStrdup(arg)); - arg = mprStrTok(0, ",", &last); - } - mprFree(args); - } - - if (body) { - v.function.body = mprStrdup(body); - } - v.allocatedData = 1; - return v; -} - -/******************************************************************************/ -/* - * Initialize an object variable. Return type == MPR_TYPE_UNDEFINED if the - * memory allocation for the properties table failed. - */ - -MprVar mprCreateObjVar(const char *name, int hashSize) -{ - MprVar v; - - mprAssert(name && *name); - - memset(&v, 0x0, sizeof(MprVar)); - v.type = MPR_TYPE_OBJECT; - if (hashSize <= 0) { - hashSize = MPR_DEFAULT_HASH_SIZE; - } - v.properties = createProperties(name, hashSize); - if (v.properties == 0) { - /* Indicate failed memory allocation */ - v.type = MPR_TYPE_UNDEFINED; - } - v.allocatedData = 1; - v.name = mprStrdup(name); - mprLog(7, "mprCreateObjVar %s, 0x%p\n", name, v.properties); - return v; -} - -/******************************************************************************/ -/* - * Initialize a string value. - */ - -MprVar mprCreateStringVar(const char *value, bool allocate) -{ - MprVar v; - - memset(&v, 0x0, sizeof(v)); - v.type = MPR_TYPE_STRING; - if (value == 0) { - v.string = (char*) ""; - } else if (allocate) { - v.string = mprStrdup(value); - v.allocatedData = 1; - } else { - v.string = (char*) value; - } - return v; -} - -/******************************************************************************/ -/* - * Copy an objects core value (only). This preserves the destination object's - * name. This implements copy by reference for objects and copy by value for - * strings and other types. Caller must free dest prior to calling. - */ - -static void copyVarCore(MprVar *dest, MprVar *src, int copyDepth) -{ - MprVarTrigger saveTrigger; - MprVar *srcProp, *destProp, *last; - char **srcArgs; - int i; - - mprAssert(dest); - mprAssert(src); - - if (dest == src) { - return; - } - - /* - * FUTURE: we should allow read-only triggers where the value is never - * stored in the object. Currently, triggers override the readonly - * status. - */ - - if (dest->type != MPR_TYPE_UNDEFINED && dest->readonly && !dest->trigger) { - mprAssert(0); - return; - } - - if (dest->type != MPR_TYPE_UNDEFINED) { - saveTrigger = dest->trigger; - freeVarStorage(dest, 0); - } else { - saveTrigger = 0; - } - - switch (src->type) { - default: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - break; - - case MPR_TYPE_BOOL: - dest->boolean = src->boolean; - break; - - case MPR_TYPE_PTR: - /* we have to reference here so talloc structures survive a - copy */ - if (src->allocatedData) { - dest->ptr = talloc_reference(mprMemCtx(), src->ptr); - dest->allocatedData = 1; - } else { - dest->ptr = src->ptr; - } - break; - - case MPR_TYPE_STRING_CFUNCTION: - dest->cFunctionWithStrings = src->cFunctionWithStrings; - break; - - case MPR_TYPE_CFUNCTION: - dest->cFunction = src->cFunction; - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - dest->floating = src->floating; - break; -#endif - - case MPR_TYPE_INT: - dest->integer = src->integer; - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - dest->integer64 = src->integer64; - break; -#endif - - case MPR_TYPE_OBJECT: - if (copyDepth == MPR_DEEP_COPY) { - - dest->properties = createProperties(src->name, - src->properties->hashSize); - dest->allocatedData = 1; - - for (i = 0; i < (int) src->properties->hashSize; i++) { - last = 0; - for (srcProp = src->properties->buckets[i]; srcProp; - srcProp = srcProp->forw) { - if (srcProp->visited) { - continue; - } - destProp = allocProperty(srcProp->name); - if (destProp == 0) { - mprAssert(destProp); - return; - } - - destProp->bucketIndex = i; - if (last) { - last->forw = destProp; - } else { - dest->properties->buckets[i] = destProp; - } - destProp->parentProperties = dest->properties; - - /* - * Recursively copy the object - */ - srcProp->visited = 1; - copyVarCore(destProp, srcProp, copyDepth); - srcProp->visited = 0; - last = destProp; - } - } - dest->properties->numItems = src->properties->numItems; - dest->properties->numDataItems = src->properties->numDataItems; - dest->allocatedData = 1; - - } else if (copyDepth == MPR_SHALLOW_COPY) { - dest->properties = src->properties; - adjustVarRefCount(src, 1); - dest->allocatedData = 1; - - } else { - dest->properties = src->properties; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_FUNCTION: - if (copyDepth != MPR_NO_COPY) { - dest->function.args = mprCreateArray(); - srcArgs = (char**) src->function.args->handles; - for (i = 0; i < src->function.args->max; i++) { - if (srcArgs[i]) { - mprAddToArray(dest->function.args, mprStrdup(srcArgs[i])); - } - } - dest->function.body = mprStrdup(src->function.body); - dest->allocatedData = 1; - } else { - dest->function.args = src->function.args; - dest->function.body = src->function.body; - dest->allocatedData = 0; - } - break; - - case MPR_TYPE_STRING: - if (src->string && copyDepth != MPR_NO_COPY) { - dest->string = mprStrdup(src->string); - dest->allocatedData = 1; - } else { - dest->string = src->string; - dest->allocatedData = 0; - } - break; - } - - dest->type = src->type; - dest->flags = src->flags; - dest->trigger = saveTrigger; - - /* - * Just for safety - */ - dest->spare = 0; -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth) -{ - mprAssert(dest); - mprAssert(src); - - copyVarCore(dest, src, copyDepth); - - mprFree(dest->name); - dest->name = mprStrdup(src->name); - -#if VAR_DEBUG - if (src->type == MPR_TYPE_OBJECT) { - - mprFree(dest->fullName); - dest->fullName = mprStrdup(src->fullName); - - mprLog(7, "mprCopyVar: object \"%s\", FDQ \"%s\" 0x%x, refCount %d\n", - dest->name, dest->fullName, dest->properties, - dest->properties->refCount); - } -#endif -} - -/******************************************************************************/ -/* - * Copy an entire object including name. - */ - -void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth) -{ - mprAssert(dest); - - mprCopyVar(dest, &src, copyDepth); -} - -/******************************************************************************/ -/* - * Copy an object. This implements copy by reference for objects and copy by - * value for strings and other types. Caller must free dest prior to calling. - */ - -MprVar *mprDupVar(MprVar *src, int copyDepth) -{ - MprVar *dest; - - mprAssert(src); - - dest = (MprVar*) mprMalloc(sizeof(MprVar)); - memset(dest, 0, sizeof(MprVar)); - - mprCopyVar(dest, src, copyDepth); - return dest; -} - -/******************************************************************************/ -/* - * Convert a value to a text based representation of its value - * FUTURE -- conver this to use the format string in all cases. Allow - * arbitrary format strings. - */ - -void mprVarToString(char** out, int size, char *fmt, MprVar *obj) -{ - char *src; - - mprAssert(out); - - *out = NULL; - - if (obj->trigger) { - mprReadProperty(obj, 0); - } - - switch (obj->type) { - case MPR_TYPE_UNDEFINED: - /* FUTURE -- spec says convert to "undefined" */ - *out = mprStrdup(""); - break; - - case MPR_TYPE_NULL: - *out = mprStrdup("null"); - break; - - case MPR_TYPE_PTR: - mprAllocSprintf(out, size, "[Opaque Pointer %p]", obj->ptr); - break; - - case MPR_TYPE_BOOL: - if (obj->boolean) { - *out = mprStrdup("true"); - } else { - *out = mprStrdup("false"); - } - break; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%f", obj->floating); - } else { - mprAllocSprintf(out, size, fmt, obj->floating); - } - break; -#endif - - case MPR_TYPE_INT: - if (fmt == NULL || *fmt == '\0') { - mprAllocSprintf(out, size, "%d", obj->integer); - } else { - mprAllocSprintf(out, size, fmt, obj->integer); - } - break; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - if (fmt == NULL || *fmt == '\0') { -#if BLD_GOAHEAD_WEBSERVER - mprAllocSprintf(out, size, "%d", (int) obj->integer64); -#else - mprAllocSprintf(out, size, "%lld", (long long)obj->integer64); -#endif - } else { - mprAllocSprintf(out, size, fmt, obj->integer64); - } - break; -#endif - - case MPR_TYPE_CFUNCTION: - mprAllocSprintf(out, size, "[C Function]"); - break; - - case MPR_TYPE_STRING_CFUNCTION: - mprAllocSprintf(out, size, "[C StringFunction]"); - break; - - case MPR_TYPE_FUNCTION: - mprAllocSprintf(out, size, "[JavaScript Function]"); - break; - - case MPR_TYPE_OBJECT: - /* FUTURE -- really want: [object class: name] */ - mprAllocSprintf(out, size, "[object %s]", obj->name); - break; - - case MPR_TYPE_STRING: - src = obj->string; - - mprAssert(src); - if (fmt && *fmt) { - mprAllocSprintf(out, size, fmt, src); - - } else if (src == NULL) { - *out = mprStrdup("null"); - - } else { - *out = mprStrdup(src); - } - break; - - default: - mprAssert(0); - } -} - -/******************************************************************************/ -/* - * Parse a string based on formatting instructions and intelligently - * create a variable. - */ - -MprVar mprParseVar(char *buf, MprType preferredType) -{ - MprType type; - char *cp; - - mprAssert(buf); - - type = preferredType; - - if (preferredType == MPR_TYPE_UNDEFINED) { - if (*buf == '-') { - type = MPR_NUM_VAR; - - } else if (!isdigit((int) *buf)) { - if (strcmp(buf, "true") == 0 || strcmp(buf, "false") == 0) { - type = MPR_TYPE_BOOL; - } else { - type = MPR_TYPE_STRING; - } - - } else if (isdigit((int) *buf)) { - type = MPR_NUM_VAR; - cp = buf; - if (*cp && tolower(cp[1]) == 'x') { - cp = &cp[2]; - } - for (cp = buf; *cp; cp++) { - if (! isdigit((int) *cp)) { - break; - } - } - - if (*cp != '\0') { -#if BLD_FEATURE_FLOATING_POINT - if (*cp == '.' || tolower(*cp) == 'e') { - type = MPR_TYPE_FLOAT; - } else -#endif - { - type = MPR_NUM_VAR; - } - } - } - } - - switch (type) { - case MPR_TYPE_OBJECT: - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_PTR: - default: - break; - - case MPR_TYPE_BOOL: - return mprCreateBoolVar(buf[0] == 't' ? 1 : 0); - - case MPR_TYPE_INT: - return mprCreateIntegerVar(mprParseInteger(buf)); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return mprCreateInteger64Var(mprParseInteger64(buf)); -#endif - - case MPR_TYPE_STRING: - if (strcmp(buf, "null") == 0) { - return mprCreateNullVar(); - } else if (strcmp(buf, "undefined") == 0) { - return mprCreateUndefinedVar(); - } - - return mprCreateStringVar(buf, 1); - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return mprCreateFloatVar(atof(buf)); -#endif - - } - return mprCreateUndefinedVar(); -} - -/******************************************************************************/ -/* - * Convert the variable to a boolean. Only for primitive types. - */ - -bool mprVarToBool(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - return 0; - - case MPR_TYPE_PTR: - return (vp->ptr != NULL); - - case MPR_TYPE_BOOL: - return vp->boolean; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - return (vp->floating != 0 && !mprIsNan(vp->floating)); -#endif - - case MPR_TYPE_INT: - return (vp->integer != 0); - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (vp->integer64 != 0); -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return (vp->string[0] != '\0'); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the variable to a floating point number. Only for primitive types. - */ - -double mprVarToFloat(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1.0 : 0.0; - - case MPR_TYPE_FLOAT: - return vp->floating; - - case MPR_TYPE_INT: - return (double) vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (double) vp->integer64; -#endif - - case MPR_TYPE_STRING: - mprAssert(vp->string); - return atof(vp->string); - } - - /* Not reached */ - return 0; -} - -#endif -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprVarToNumber(const MprVar *vp) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprVarToInteger64(vp); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprVarToFloat(vp); -#else - return mprVarToInteger(vp); -#endif -} - -/******************************************************************************/ -/* - * Convert the variable to a number type. Only works for primitive types. - */ - -MprNum mprParseNumber(char *s) -{ -#if BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_INT64 - return mprParseInteger64(s); -#elif BLD_FEATURE_NUM_TYPE_ID == MPR_TYPE_FLOAT - return mprParseFloat(s); -#else - return mprParseInteger(s); -#endif -} - -/******************************************************************************/ -#if BLD_FEATURE_INT64 -/* - * Convert the variable to an Integer64 type. Only works for primitive types. - */ - -int64 mprVarToInteger64(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int64) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - - case MPR_TYPE_INT64: - return vp->integer64; - - case MPR_TYPE_STRING: - return mprParseInteger64(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer64. - */ - -int64 mprParseInteger64(char *str) -{ - char *cp; - int64 num64; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num64 = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num64 = (*cp - '0') + (num64 * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num64 = (c - '0') + (num64 * radix); - } else if (c >= 'a' && c <= 'f') { - num64 = (c - ('a' - 10)) + (num64 * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num64 = (c - '0') + (num64 * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num64; - } - return num64; -} - -#endif /* BLD_FEATURE_INT64 */ -/******************************************************************************/ -/* - * Convert the variable to an Integer type. Only works for primitive types. - */ - -int mprVarToInteger(const MprVar *vp) -{ - mprAssert(vp); - - switch (vp->type) { - case MPR_TYPE_UNDEFINED: - case MPR_TYPE_NULL: - case MPR_TYPE_STRING_CFUNCTION: - case MPR_TYPE_CFUNCTION: - case MPR_TYPE_FUNCTION: - case MPR_TYPE_OBJECT: - case MPR_TYPE_PTR: - return 0; - - case MPR_TYPE_BOOL: - return (vp->boolean) ? 1 : 0; - -#if BLD_FEATURE_FLOATING_POINT - case MPR_TYPE_FLOAT: - if (mprIsNan(vp->floating)) { - return 0; - } - return (int) vp->floating; -#endif - - case MPR_TYPE_INT: - return vp->integer; - -#if BLD_FEATURE_INT64 - case MPR_TYPE_INT64: - return (int) vp->integer64; -#endif - - case MPR_TYPE_STRING: - return mprParseInteger(vp->string); - } - - /* Not reached */ - return 0; -} - -/******************************************************************************/ -/* - * Convert the string buffer to an Integer. - */ - -int mprParseInteger(char *str) -{ - char *cp; - int num; - int radix, c, negative; - - mprAssert(str); - - cp = str; - num = 0; - negative = 0; - - if (*cp == '-') { - cp++; - negative = 1; - } - - /* - * Parse a number. Observe hex and octal prefixes (0x, 0) - */ - if (*cp != '0') { - /* - * Normal numbers (Radix 10) - */ - while (isdigit((int) *cp)) { - num = (*cp - '0') + (num * 10); - cp++; - } - } else { - cp++; - if (tolower(*cp) == 'x') { - cp++; - radix = 16; - while (*cp) { - c = tolower(*cp); - if (isdigit(c)) { - num = (c - '0') + (num * radix); - } else if (c >= 'a' && c <= 'f') { - num = (c - ('a' - 10)) + (num * radix); - } else { - break; - } - cp++; - } - - } else{ - radix = 8; - while (*cp) { - c = tolower(*cp); - if (isdigit(c) && c < '8') { - num = (c - '0') + (num * radix); - } else { - break; - } - cp++; - } - } - } - - if (negative) { - return 0 - num; - } - return num; -} - -/******************************************************************************/ -#if BLD_FEATURE_FLOATING_POINT -/* - * Convert the string buffer to an Floating. - */ - -double mprParseFloat(char *str) -{ - return atof(str); -} - -/******************************************************************************/ - -bool mprIsNan(double f) -{ -#if WIN - return _isnan(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#elif defined(FP_NAN) - return (f == FP_NAN); -#else - return 0; -#endif -} -/******************************************************************************/ - -bool mprIsInfinite(double f) -{ -#if WIN - return !_finite(f); -#elif VXWORKS - /* FUTURE */ - return (0); -#elif defined(FP_INFINITE) - return (f == FP_INFINITE); -#else - return 0; -#endif -} - -#endif /* BLD_FEATURE_FLOATING_POINT */ -/******************************************************************************/ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/appweb/mpr/var.h b/source4/lib/appweb/mpr/var.h deleted file mode 100644 index 98313c0476..0000000000 --- a/source4/lib/appweb/mpr/var.h +++ /dev/null @@ -1,487 +0,0 @@ -/* - * @file var.h - * @brief MPR Universal Variable Type - * @copy default.m - * - * Copyright (c) Mbedthis Software LLC, 2003-2005. All Rights Reserved. - * Copyright (c) Michael O'Brien, 1994-1995. All Rights Reserved. - * - * This software is distributed under commercial and open source licenses. - * You may use the GPL open source license described below or you may acquire - * a commercial license from Mbedthis Software. You agree to be fully bound - * by the terms of either license. Consult the LICENSE.TXT distributed with - * this software for full details. - * - * This software is open source; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. See the GNU General Public License for more - * details at: http://www.mbedthis.com/downloads/gplLicense.html - * - * This program is distributed WITHOUT ANY WARRANTY; without even the - * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * This GPL license does NOT permit incorporating this software into - * proprietary programs. If you are unable to comply with the GPL, you must - * acquire a commercial license to use this software. Commercial licenses - * for this software and support services are available from Mbedthis - * Software at http://www.mbedthis.com - * - * @end - */ - -/******************************* Documentation ********************************/ -/* - * Variables can efficiently store primitive types and can hold references to - * objects. Objects can store properties which are themselves variables. - * Properties can be primitive data types, other objects or functions. - * Properties are indexed by a character name. A variable may store one of - * the following types: - * - * string, integer, integer-64bit, C function, C function with string args, - * Javascript function, Floating point number, boolean value, Undefined - * value and the Null value. - * - * Variables have names while objects may be referenced by multiple variables. - * Objects use reference counting for garbage collection. - * - * This module is not thread safe for performance and compactness. It relies - * on upper modules to provide thread synchronization as required. The API - * provides primitives to get variable/object references or to get copies of - * variables which will help minimize required lock times. - */ - -#ifndef _h_MPR_VAR -#define _h_MPR_VAR 1 - -/********************************* Includes ***********************************/ - -#include "miniMpr.h" - -/********************************** Defines ***********************************/ - -/* - * Define VAR_DEBUG if you want to track objects. However, this code is not - * thread safe and you need to run the server single threaded. - * - * #define VAR_DEBUG 1 - */ - -#ifdef __cplusplus -extern "C" { -#endif -/* - * Forward declare types - */ -struct MprProperties; -struct MprVar; - -/* - * Possible variable types. Don't use enum because we need to be able to - * do compile time conditional compilation on BLD_FEATURE_NUM_TYPE_ID. - */ -typedef int MprType; -#define MPR_TYPE_UNDEFINED 0 /* Undefined. No value has been set. */ -#define MPR_TYPE_NULL 1 /* Value defined to be null. */ -#define MPR_TYPE_BOOL 2 /* Boolean type. */ -#define MPR_TYPE_CFUNCTION 3 /* C function or C++ method */ -#define MPR_TYPE_FLOAT 4 /* Floating point number */ -#define MPR_TYPE_INT 5 /* Integer number */ -#define MPR_TYPE_INT64 6 /* 64-bit Integer number */ -#define MPR_TYPE_OBJECT 7 /* Object reference */ -#define MPR_TYPE_FUNCTION 8 /* JavaScript function */ -#define MPR_TYPE_STRING 9 /* String (immutable) */ -#define MPR_TYPE_STRING_CFUNCTION 10 /* C/C++ function with string args */ -#define MPR_TYPE_PTR 11 /* Opaque pointer */ - -/* - * Create a type for the default number type - * Config.h will define the default number type. For example: - * - * BLD_FEATURE_NUM_TYPE=int - * BLD_FEATURE_NUM_TYPE_ID=MPR_TYPE_INT - */ - -/** - * Set to the type used for MPR numeric variables. Will equate to int, int64 - * or double. - */ -typedef BLD_FEATURE_NUM_TYPE MprNum; - -/** - * Set to the MPR_TYPE used for MPR numeric variables. Will equate to - * MPR_TYPE_INT, MPR_TYPE_INT64 or MPR_TYPE_FLOAT. - */ -#define MPR_NUM_VAR BLD_FEATURE_NUM_TYPE_ID -#define MPR_TYPE_NUM BLD_FEATURE_NUM_TYPE_ID - -/* - * Return TRUE if a variable is a function type - */ -#define mprVarIsFunction(type) \ - (type == MPR_TYPE_FUNCTION || type == MPR_TYPE_STRING_CFUNCTION || \ - type == MPR_TYPE_CFUNCTION) - -/* - * Return TRUE if a variable is a numeric type - */ -#define mprVarIsNumber(type) \ - (type == MPR_TYPE_INT || type == MPR_TYPE_INT64 || type == MPR_TYPE_FLOAT) - -/* - * Return TRUE if a variable is a boolean - */ -#define mprVarIsBoolean(type) \ - (type == MPR_TYPE_BOOL) -#define mprVarIsString(type) \ - (type == MPR_TYPE_STRING) -#define mprVarIsObject(type) \ - (type == MPR_TYPE_OBJECT) -#define mprVarIsFloating(type) \ - (type == MPR_TYPE_FLOAT) -#define mprVarIsPtr(type) \ - (type == MPR_TYPE_PTR) -#define mprVarIsUndefined(var) \ - ((var)->type == MPR_TYPE_UNDEFINED) -#define mprVarIsNull(var) \ - ((var)->type == MPR_TYPE_NULL) -#define mprVarIsValid(var) \ - (((var)->type != MPR_TYPE_NULL) && ((var)->type != MPR_TYPE_UNDEFINED)) - -#define MPR_VAR_MAX_RECURSE 5 /* Max object loops */ - -#if BLD_FEATURE_SQUEEZE -#define MPR_MAX_VAR 64 /* Max var full name */ -#else -#define MPR_MAX_VAR 512 -#endif - -/* - * Function signatures - */ -typedef int MprVarHandle; -typedef int (*MprCFunction)(MprVarHandle userHandle, int argc, - struct MprVar **argv); -typedef int (*MprStringCFunction)(MprVarHandle userHandle, int argc, - char **argv); - -/* - * Triggers - */ -typedef enum { - MPR_VAR_WRITE, /* This property is being updated */ - MPR_VAR_READ, /* This property is being read */ - MPR_VAR_CREATE_PROPERTY, /* A property is being created */ - MPR_VAR_DELETE_PROPERTY, /* A property is being deleted */ - MPR_VAR_DELETE /* This object is being deleted */ -} MprVarTriggerOp; - -/* - * Trigger function return codes. - */ -typedef enum { - MPR_TRIGGER_ABORT, /* Abort the current operation */ - MPR_TRIGGER_USE_NEW_VALUE, /* Proceed and use the newValue */ - MPR_TRIGGER_PROCEED /* Proceed with the operation */ -} MprVarTriggerStatus; - -/* - * The MprVarTrigger arguments have the following meaning: - * - * op The operation being performed. See MprVarTriggerOp. - * parentProperties Pointer to the MprProperties structure. - * vp Pointer to the property that registered the trigger. - * newValue New value (see below for more details). - * copyDepth Specify what data items to copy. - * - * For VAR_READ, newVar is set to a temporary variable that the trigger - * function may assign a value to be returned instead of the actual - * property value. - * For VAR_WRITE, newValue holds the new value. The old existing value may be - * accessed via vp. - * For DELETE_PROPERTY, vp is the property being deleted. newValue is null. - * For ADD_PROPERTY, vp is set to the property being added and newValue holds - * the new value. - */ -typedef MprVarTriggerStatus (*MprVarTrigger)(MprVarTriggerOp op, - struct MprProperties *parentProperties, struct MprVar *vp, - struct MprVar *newValue, int copyDepth); - -/* - * mprCreateFunctionVar flags - */ -/** Use the alternate handle on function callbacks */ -#define MPR_VAR_ALT_HANDLE 0x1 - -/** Use the script handle on function callbacks */ -#define MPR_VAR_SCRIPT_HANDLE 0x2 - -/* - * Useful define for the copyDepth argument - */ -/** Don't copy any data. Copy only the variable name */ -#define MPR_NO_COPY 0 - -/** Copy strings. Increment object reference counts. */ -#define MPR_SHALLOW_COPY 1 - -/** Copy strings and do complete object copies. */ -#define MPR_DEEP_COPY 2 - -/* - * GetFirst / GetNext flags - */ -/** Step into data properties. */ -#define MPR_ENUM_DATA 0x1 - -/** Step into functions properties. */ -#define MPR_ENUM_FUNCTIONS 0x2 - -/* - * Collection type to hold properties in an object - */ -typedef struct MprProperties { /* Collection of properties */ -#if VAR_DEBUG - struct MprProperties *next; /* Linked list */ - struct MprProperties *prev; /* Linked list */ - char name[32]; /* Debug name */ -#endif - struct MprVar **buckets; /* Hash chains */ - int numItems; /* Total count of items */ - /* FUTURE - Better way of doing this */ - int numDataItems; /* Enumerable data items */ - uint hashSize : 8; /* Size of the hash table */ - /* FUTURE -- increase size of refCount */ - uint refCount : 8; /* References to this property*/ - /* FUTURE - make these flags */ - uint deleteProtect : 8; /* Don't recursively delete */ - uint visited : 8; /* Node has been processed */ -} MprProperties; - -/* - * Universal Variable Type - */ -typedef struct MprVar { - /* FUTURE - remove name to outside reference */ - MprStr name; /* Property name */ - /* FUTURE - remove */ - MprStr fullName; /* Full object name */ - /* FUTURE - make part of the union */ - MprProperties *properties; /* Pointer to properties */ - - /* - * Packed bit field - */ - MprType type : 8; /* Selector into union */ - uint bucketIndex : 8; /* Copy of bucket index */ - - uint flags : 5; /* Type specific flags */ - uint allocatedData : 1; /* Data needs freeing */ - uint readonly : 1; /* Unmodifiable */ - uint deleteProtect : 1; /* Don't recursively delete */ - - uint visited : 1; /* Node has been processed */ - uint allocatedVar : 1; /* Var needs freeing */ - uint spare : 6; /* Unused */ - - struct MprVar *forw; /* Hash table linkage */ - MprVarTrigger trigger; /* Trigger function */ - -#if UNUSED && KEEP - struct MprVar *baseClass; /* Pointer to class object */ -#endif - MprProperties *parentProperties; /* Pointer to parent object */ - - /* - * Union of primitive types. When debugging on Linux, don't use unions - * as the gdb debugger can't display them. - */ -#if 0 && !BLD_DEBUG && !LINUX && !VXWORKS - union { -#endif - bool boolean; -#if BLD_FEATURE_FLOATING_POINT - double floating; -#endif - int integer; -#if BLD_FEATURE_INT64 - int64 integer64; -#endif - struct { /* Javascript functions */ - MprArray *args; /* Null terminated */ - char *body; - } function; - struct { /* Function with MprVar args */ - MprCFunction fn; - void *thisPtr; - } cFunction; - struct { /* Function with string args */ - MprStringCFunction fn; - void *thisPtr; - } cFunctionWithStrings; - MprStr string; /* Allocated string */ - void *ptr; /* Opaque pointer */ -#if 0 && !BLD_DEBUG && !LINUX && !VXWORKS - }; -#endif -} MprVar; - -/* - * Define a field macro so code an use numbers in a "generic" fashion. - */ -#if MPR_NUM_VAR == MPR_TYPE_INT || DOXYGEN -/* Default numeric type */ -#define mprNumber integer -#endif -#if MPR_NUM_VAR == MPR_TYPE_INT64 -/* Default numeric type */ -#define mprNumber integer64 -#endif -#if MPR_NUM_VAR == MPR_TYPE_FLOAT -/* Default numeric type */ -#define mprNumber floating -#endif - -typedef BLD_FEATURE_NUM_TYPE MprNumber; - -/********************************* Prototypes *********************************/ -/* - * Variable constructors and destructors - */ -extern MprVar mprCreateObjVar(const char *name, int hashSize); -extern MprVar mprCreateBoolVar(bool value); -extern MprVar mprCreateCFunctionVar(MprCFunction fn, void *thisPtr, - int flags); -#if BLD_FEATURE_FLOATING_POINT -extern MprVar mprCreateFloatVar(double value); -#endif -extern MprVar mprCreateIntegerVar(int value); -#if BLD_FEATURE_INT64 -extern MprVar mprCreateInteger64Var(int64 value); -#endif -extern MprVar mprCreateFunctionVar(char *args, char *body, int flags); -extern MprVar mprCreateNullVar(void); -extern MprVar mprCreateNumberVar(MprNumber value); -extern MprVar mprCreateStringCFunctionVar(MprStringCFunction fn, - void *thisPtr, int flags); -extern MprVar mprCreateStringVar(const char *value, bool allocate); -extern MprVar mprCreateUndefinedVar(void); -extern MprVar mprCreatePtrVar(void *ptr); -extern bool mprDestroyVar(MprVar *vp); -extern bool mprDestroyAllVars(MprVar* vp); -extern MprType mprGetVarType(MprVar *vp); - -/* - * Copy - */ -extern void mprCopyVar(MprVar *dest, MprVar *src, int copyDepth); -extern void mprCopyVarValue(MprVar *dest, MprVar src, int copyDepth); -extern MprVar *mprDupVar(MprVar *src, int copyDepth); - -/* - * Manage vars - */ -extern MprVarTrigger - mprAddVarTrigger(MprVar *vp, MprVarTrigger fn); -extern int mprGetVarRefCount(MprVar *vp); -extern void mprSetVarDeleteProtect(MprVar *vp, int deleteProtect); -extern void mprSetVarFullName(MprVar *vp, char *name); -extern void mprSetVarReadonly(MprVar *vp, int readonly); -extern void mprSetVarName(MprVar *vp, char *name); - -/* - * Create properties and return a reference to the property. - */ -extern MprVar *mprCreateProperty(MprVar *obj, const char *property, - MprVar *newValue); -extern MprVar *mprCreatePropertyValue(MprVar *obj, const char *property, - MprVar newValue); -extern int mprDeleteProperty(MprVar *obj, const char *property); - -/* - * Get/Set properties. Set will update/create. - */ -extern MprVar *mprGetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetProperty(MprVar *obj, const char *property, - MprVar *value); -extern MprVar *mprSetPropertyValue(MprVar *obj, const char *property, - MprVar value); - -/* - * Directly read/write property values (the property must already exist) - * For mprCopyProperty, mprDestroyVar must always called on the var. - */ -extern int mprReadProperty(MprVar *prop, MprVar *value); -extern int mprWriteProperty(MprVar *prop, MprVar *newValue); -extern int mprWritePropertyValue(MprVar *prop, MprVar newValue); - -/* - * Copy a property. NOTE: reverse of most other args: (dest, src) - */ -extern int mprCopyProperty(MprVar *dest, MprVar *prop, int copyDepth); - -/* - * Enumerate properties - */ -extern MprVar *mprGetFirstProperty(MprVar *obj, int includeFlags); -extern MprVar *mprGetNextProperty(MprVar *obj, MprVar *currentProperty, - int includeFlags); - -/* - * Query properties characteristics - */ -extern int mprGetPropertyCount(MprVar *obj, int includeFlags); - -/* - * Conversion routines - */ -extern MprVar mprParseVar(char *str, MprType prefType); -extern MprNum mprVarToNumber(const MprVar *vp); -extern int mprVarToInteger(const MprVar *vp); -#if BLD_FEATURE_INT64 -extern int64 mprVarToInteger64(const MprVar *vp); -#endif -extern bool mprVarToBool(const MprVar *vp); -#if BLD_FEATURE_FLOATING_POINT -extern double mprVarToFloat(const MprVar *vp); -#endif -extern void mprVarToString(char** buf, int size, char *fmt, MprVar *vp); - -/* - * Parsing and utility routines - */ -extern MprNum mprParseNumber(char *str); -extern int mprParseInteger(char *str); - -#if BLD_FEATURE_INT64 -extern int64 mprParseInteger64(char *str); -#endif - -#if BLD_FEATURE_FLOATING_POINT -extern double mprParseFloat(char *str); -extern bool mprIsInfinite(double f); -extern bool mprIsNan(double f); -#endif - -#if VAR_DEBUG -extern void mprPrintObjects(char *msg); -extern void mprPrintObjRefCount(MprVar *vp); -#endif - -#ifdef __cplusplus -} -#endif - -/*****************************************************************************/ -#endif /* _h_MPR_VAR */ - -/* - * Local variables: - * tab-width: 4 - * c-basic-offset: 4 - * End: - * vim:tw=78 - * vim600: sw=4 ts=4 fdm=marker - * vim<600: sw=4 ts=4 - */ diff --git a/source4/lib/charset/util_unistr.c b/source4/lib/charset/util_unistr.c index 09ec7b0471..a8ff88423a 100644 --- a/source4/lib/charset/util_unistr.c +++ b/source4/lib/charset/util_unistr.c @@ -570,7 +570,13 @@ _PUBLIC_ char *strupper_talloc(TALLOC_CTX *ctx, const char *src) return strupper_talloc_n(ctx, src, src?strlen(src):0); } - +/** + talloc_strdup() a unix string to upper case. +**/ +_PUBLIC_ char *talloc_strdup_upper(TALLOC_CTX *ctx, const char *src) +{ + return strupper_talloc(ctx, src); +} /** Convert a string to lower case. diff --git a/source4/lib/com/config.mk b/source4/lib/com/config.mk index c5c5a35003..73836ef5f8 100644 --- a/source4/lib/com/config.mk +++ b/source4/lib/com/config.mk @@ -1,22 +1,22 @@ [SUBSYSTEM::COM] PRIVATE_DEPENDENCIES = LIBSAMBA-UTIL LIBSAMBA-HOSTCONFIG LIBEVENTS LIBNDR -COM_OBJ_FILES = $(addprefix lib/com/, tables.o rot.o main.o) +COM_OBJ_FILES = $(addprefix $(comsrcdir)/, tables.o rot.o main.o) [SUBSYSTEM::DCOM] PUBLIC_DEPENDENCIES = COM DCOM_PROXY_DCOM RPC_NDR_REMACT \ RPC_NDR_OXIDRESOLVER -DCOM_OBJ_FILES = $(addprefix lib/com/dcom/, main.o tables.o) +DCOM_OBJ_FILES = $(addprefix $(comsrcdir)/dcom/, main.o tables.o) [MODULE::com_simple] SUBSYSTEM = COM INIT_FUNCTION = com_simple_init -com_simple_OBJ_FILES = lib/com/classes/simple.o +com_simple_OBJ_FILES = $(comsrcdir)/classes/simple.o [PYTHON::pycom] LIBRARY_REALNAME = samba/com.$(SHLIBEXT) PRIVATE_DEPENDENCIES = COM -pycom_OBJ_FILES = lib/com/pycom.o +pycom_OBJ_FILES = $(comsrcdir)/pycom.o diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i index 8cd39b5690..e9496b503b 100644 --- a/source4/lib/ldb/ldb.i +++ b/source4/lib/ldb/ldb.i @@ -153,17 +153,21 @@ PyObject *ldb_val_to_py_object(struct ldb_context *ldb_ctx, * Wrap struct ldb_result */ -%typemap(in,noblock=1,numinputs=0) struct ldb_result **OUT (struct ldb_result *temp_ldb_result) { +%typemap(in,noblock=1,numinputs=0) struct ldb_result ** (struct ldb_result *temp_ldb_result) { $1 = &temp_ldb_result; } #ifdef SWIGPYTHON %typemap(argout,noblock=1) struct ldb_result ** (int i) { - $result = PyList_New((*$1)->count); - for (i = 0; i < (*$1)->count; i++) { - PyList_SetItem($result, i, - SWIG_NewPointerObj((*$1)->msgs[i], SWIGTYPE_p_ldb_message, 0) - ); + if ($1 == NULL) { + $result = Py_None; + } else { + $result = PyList_New((*$1)->count); + for (i = 0; i < (*$1)->count; i++) { + PyList_SetItem($result, i, + SWIG_NewPointerObj((*$1)->msgs[i], SWIGTYPE_p_ldb_message, 0) + ); + } } } @@ -944,20 +948,55 @@ typedef struct ldb_module { return ret; } #endif - int search(struct ldb_request *req) { - return $self->ops->search($self, req); + int search(struct ldb_dn *base, enum ldb_scope scope, struct ldb_parse_tree *tree, const char * const * attrs, struct ldb_result **res) { + int ret; + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + + req->operation = LDB_SEARCH; + req->op.search.base = base; + req->op.search.scope = scope; + req->op.search.tree = tree; + req->op.search.attrs = attrs; + + req->op.search.res = talloc_zero(NULL, struct ldb_result); + + ret = $self->ops->search($self, req); + + *res = req->op.search.res; + + talloc_free(req); + + return ret; } - ldb_error add(struct ldb_request *req) { - return $self->ops->add($self, req); + ldb_error add(struct ldb_message *message) { + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_ADD; + req->op.add.message = message; + + return $self->ops->add($self, &req); } - ldb_error modify(struct ldb_request *req) { - return $self->ops->modify($self, req); + ldb_error modify(struct ldb_message *message) { + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_MODIFY; + req->op.mod.message = message; + + return $self->ops->modify($self, &req); } - ldb_error delete(struct ldb_request *req) { - return $self->ops->del($self, req); + ldb_error delete(struct ldb_dn *dn) { + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_DELETE; + req->op.del.dn = dn; + + return $self->ops->del($self, &req); + } - ldb_error rename(struct ldb_request *req) { - return $self->ops->rename($self, req); + ldb_error rename(struct ldb_dn *olddn, struct ldb_dn *newdn) { + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_RENAME; + req->op.rename.olddn = olddn; + req->op.rename.olddn = newdn; + + return $self->ops->rename($self, &req); } ldb_error start_transaction() { return $self->ops->start_transaction($self); diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c index 7a6d4517ce..84e68d460e 100644 --- a/source4/lib/ldb/ldb_wrap.c +++ b/source4/lib/ldb/ldb_wrap.c @@ -2495,23 +2495,22 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) #define SWIGTYPE_p_ldb_module swig_types[9] #define SWIGTYPE_p_ldb_module_ops swig_types[10] #define SWIGTYPE_p_ldb_parse_tree swig_types[11] -#define SWIGTYPE_p_ldb_request swig_types[12] -#define SWIGTYPE_p_ldb_result swig_types[13] -#define SWIGTYPE_p_ldb_val swig_types[14] -#define SWIGTYPE_p_long_long swig_types[15] -#define SWIGTYPE_p_p_char swig_types[16] -#define SWIGTYPE_p_p_ldb_control swig_types[17] -#define SWIGTYPE_p_p_ldb_result swig_types[18] -#define SWIGTYPE_p_short swig_types[19] -#define SWIGTYPE_p_signed_char swig_types[20] -#define SWIGTYPE_p_unsigned_char swig_types[21] -#define SWIGTYPE_p_unsigned_int swig_types[22] -#define SWIGTYPE_p_unsigned_long swig_types[23] -#define SWIGTYPE_p_unsigned_long_long swig_types[24] -#define SWIGTYPE_p_unsigned_short swig_types[25] -#define SWIGTYPE_p_void swig_types[26] -static swig_type_info *swig_types[28]; -static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; +#define SWIGTYPE_p_ldb_result swig_types[12] +#define SWIGTYPE_p_ldb_val swig_types[13] +#define SWIGTYPE_p_long_long swig_types[14] +#define SWIGTYPE_p_p_char swig_types[15] +#define SWIGTYPE_p_p_ldb_control swig_types[16] +#define SWIGTYPE_p_p_ldb_result swig_types[17] +#define SWIGTYPE_p_short swig_types[18] +#define SWIGTYPE_p_signed_char swig_types[19] +#define SWIGTYPE_p_unsigned_char swig_types[20] +#define SWIGTYPE_p_unsigned_int swig_types[21] +#define SWIGTYPE_p_unsigned_long swig_types[22] +#define SWIGTYPE_p_unsigned_long_long swig_types[23] +#define SWIGTYPE_p_unsigned_short swig_types[24] +#define SWIGTYPE_p_void swig_types[25] +static swig_type_info *swig_types[27]; +static swig_module_info swig_module = {swig_types, 26, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -3238,20 +3237,55 @@ SWIGINTERN char *ldb_module___repr__(ldb_module *self){ asprintf(&ret, "<ldb module '%s'>", self->ops->name); return ret; } -SWIGINTERN int ldb_module_search(ldb_module *self,struct ldb_request *req){ - return self->ops->search(self, req); +SWIGINTERN int ldb_module_search(ldb_module *self,struct ldb_dn *base,enum ldb_scope scope,struct ldb_parse_tree *tree,char const *const *attrs,struct ldb_result **res){ + int ret; + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + + req->operation = LDB_SEARCH; + req->op.search.base = base; + req->op.search.scope = scope; + req->op.search.tree = tree; + req->op.search.attrs = attrs; + + req->op.search.res = talloc_zero(NULL, struct ldb_result); + + ret = self->ops->search(self, req); + + *res = req->op.search.res; + + talloc_free(req); + + return ret; } -SWIGINTERN ldb_error ldb_module_add(ldb_module *self,struct ldb_request *req){ - return self->ops->add(self, req); +SWIGINTERN ldb_error ldb_module_add(ldb_module *self,struct ldb_message *message){ + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_ADD; + req->op.add.message = message; + + return self->ops->add(self, &req); } -SWIGINTERN ldb_error ldb_module_modify(ldb_module *self,struct ldb_request *req){ - return self->ops->modify(self, req); +SWIGINTERN ldb_error ldb_module_modify(ldb_module *self,struct ldb_message *message){ + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_MODIFY; + req->op.mod.message = message; + + return self->ops->modify(self, &req); } -SWIGINTERN ldb_error ldb_module_delete(ldb_module *self,struct ldb_request *req){ - return self->ops->del(self, req); +SWIGINTERN ldb_error ldb_module_delete(ldb_module *self,struct ldb_dn *dn){ + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_DELETE; + req->op.del.dn = dn; + + return self->ops->del(self, &req); + } -SWIGINTERN ldb_error ldb_module_rename(ldb_module *self,struct ldb_request *req){ - return self->ops->rename(self, req); +SWIGINTERN ldb_error ldb_module_rename(ldb_module *self,struct ldb_dn *olddn,struct ldb_dn *newdn){ + struct ldb_request *req = talloc_zero(NULL, struct ldb_request); + req->operation = LDB_RENAME; + req->op.rename.olddn = olddn; + req->op.rename.olddn = newdn; + + return self->ops->rename(self, &req); } SWIGINTERN ldb_error ldb_module_start_transaction(ldb_module *self){ return self->ops->start_transaction(self); @@ -5000,11 +5034,15 @@ SWIGINTERN PyObject *_wrap_Ldb_search_ex(PyObject *SWIGUNUSEDPARM(self), PyObjec SWIG_fail; } resultobj = Py_None; - resultobj = PyList_New((*arg8)->count); - for (i8 = 0; i8 < (*arg8)->count; i8++) { - PyList_SetItem(resultobj, i8, - SWIG_NewPointerObj((*arg8)->msgs[i8], SWIGTYPE_p_ldb_message, 0) - ); + if (arg8 == NULL) { + resultobj = Py_None; + } else { + resultobj = PyList_New((*arg8)->count); + for (i8 = 0; i8 < (*arg8)->count; i8++) { + PyList_SetItem(resultobj, i8, + SWIG_NewPointerObj((*arg8)->msgs[i8], SWIGTYPE_p_ldb_message, 0) + ); + } } talloc_free(arg3); if (alloc5 == SWIG_NEWOBJ) free((char*)buf5); @@ -6235,33 +6273,80 @@ fail: SWIGINTERN PyObject *_wrap_ldb_module_search(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; ldb_module *arg1 = (ldb_module *) 0 ; - struct ldb_request *arg2 = (struct ldb_request *) 0 ; + struct ldb_dn *arg2 = (struct ldb_dn *) 0 ; + enum ldb_scope arg3 ; + struct ldb_parse_tree *arg4 = (struct ldb_parse_tree *) 0 ; + char **arg5 = (char **) 0 ; + struct ldb_result **arg6 = (struct ldb_result **) 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; int res2 = 0 ; + int val3 ; + int ecode3 = 0 ; + void *argp4 = 0 ; + int res4 = 0 ; + struct ldb_result *temp_ldb_result6 ; + int i6 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; + PyObject * obj3 = 0 ; + PyObject * obj4 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "req", NULL + (char *) "self",(char *) "base",(char *) "scope",(char *) "tree",(char *) "attrs", NULL }; int result; - if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:ldb_module_search",kwnames,&obj0,&obj1)) SWIG_fail; + arg6 = &temp_ldb_result6; + if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOOOO:ldb_module_search",kwnames,&obj0,&obj1,&obj2,&obj3,&obj4)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_module, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_module_search" "', argument " "1"" of type '" "ldb_module *""'"); } arg1 = (ldb_module *)(argp1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_request, 0 | 0 ); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_dn, 0 | 0 ); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_search" "', argument " "2"" of type '" "struct ldb_request *""'"); + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_search" "', argument " "2"" of type '" "struct ldb_dn *""'"); } - arg2 = (struct ldb_request *)(argp2); - result = (int)ldb_module_search(arg1,arg2); + arg2 = (struct ldb_dn *)(argp2); + ecode3 = SWIG_AsVal_int(obj2, &val3); + if (!SWIG_IsOK(ecode3)) { + SWIG_exception_fail(SWIG_ArgError(ecode3), "in method '" "ldb_module_search" "', argument " "3"" of type '" "enum ldb_scope""'"); + } + arg3 = (enum ldb_scope)(val3); + res4 = SWIG_ConvertPtr(obj3, &argp4,SWIGTYPE_p_ldb_parse_tree, 0 | 0 ); + if (!SWIG_IsOK(res4)) { + SWIG_exception_fail(SWIG_ArgError(res4), "in method '" "ldb_module_search" "', argument " "4"" of type '" "struct ldb_parse_tree *""'"); + } + arg4 = (struct ldb_parse_tree *)(argp4); + if (obj4 == Py_None) { + arg5 = NULL; + } else if (PySequence_Check(obj4)) { + int i; + arg5 = talloc_array(NULL, char *, PySequence_Size(obj4)+1); + for(i = 0; i < PySequence_Size(obj4); i++) + arg5[i] = PyString_AsString(PySequence_GetItem(obj4, i)); + arg5[i] = NULL; + } else { + SWIG_exception(SWIG_TypeError, "expected sequence"); + } + result = (int)ldb_module_search(arg1,arg2,arg3,arg4,(char const *const *)arg5,arg6); resultobj = SWIG_From_int((int)(result)); + if (arg6 == NULL) { + resultobj = Py_None; + } else { + resultobj = PyList_New((*arg6)->count); + for (i6 = 0; i6 < (*arg6)->count; i6++) { + PyList_SetItem(resultobj, i6, + SWIG_NewPointerObj((*arg6)->msgs[i6], SWIGTYPE_p_ldb_message, 0) + ); + } + } + talloc_free(arg5); return resultobj; fail: + talloc_free(arg5); return NULL; } @@ -6269,7 +6354,7 @@ fail: SWIGINTERN PyObject *_wrap_ldb_module_add(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; ldb_module *arg1 = (ldb_module *) 0 ; - struct ldb_request *arg2 = (struct ldb_request *) 0 ; + struct ldb_message *arg2 = (struct ldb_message *) 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; @@ -6277,7 +6362,7 @@ SWIGINTERN PyObject *_wrap_ldb_module_add(PyObject *SWIGUNUSEDPARM(self), PyObje PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "req", NULL + (char *) "self",(char *) "message", NULL }; ldb_error result; @@ -6287,11 +6372,11 @@ SWIGINTERN PyObject *_wrap_ldb_module_add(PyObject *SWIGUNUSEDPARM(self), PyObje SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_module_add" "', argument " "1"" of type '" "ldb_module *""'"); } arg1 = (ldb_module *)(argp1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_request, 0 | 0 ); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_message, 0 | 0 ); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_add" "', argument " "2"" of type '" "struct ldb_request *""'"); + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_add" "', argument " "2"" of type '" "struct ldb_message *""'"); } - arg2 = (struct ldb_request *)(argp2); + arg2 = (struct ldb_message *)(argp2); result = ldb_module_add(arg1,arg2); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_errstring(arg1))); @@ -6307,7 +6392,7 @@ fail: SWIGINTERN PyObject *_wrap_ldb_module_modify(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; ldb_module *arg1 = (ldb_module *) 0 ; - struct ldb_request *arg2 = (struct ldb_request *) 0 ; + struct ldb_message *arg2 = (struct ldb_message *) 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; @@ -6315,7 +6400,7 @@ SWIGINTERN PyObject *_wrap_ldb_module_modify(PyObject *SWIGUNUSEDPARM(self), PyO PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "req", NULL + (char *) "self",(char *) "message", NULL }; ldb_error result; @@ -6325,11 +6410,11 @@ SWIGINTERN PyObject *_wrap_ldb_module_modify(PyObject *SWIGUNUSEDPARM(self), PyO SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_module_modify" "', argument " "1"" of type '" "ldb_module *""'"); } arg1 = (ldb_module *)(argp1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_request, 0 | 0 ); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_message, 0 | 0 ); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_modify" "', argument " "2"" of type '" "struct ldb_request *""'"); + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_modify" "', argument " "2"" of type '" "struct ldb_message *""'"); } - arg2 = (struct ldb_request *)(argp2); + arg2 = (struct ldb_message *)(argp2); result = ldb_module_modify(arg1,arg2); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_errstring(arg1))); @@ -6345,7 +6430,7 @@ fail: SWIGINTERN PyObject *_wrap_ldb_module_delete(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; ldb_module *arg1 = (ldb_module *) 0 ; - struct ldb_request *arg2 = (struct ldb_request *) 0 ; + struct ldb_dn *arg2 = (struct ldb_dn *) 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; @@ -6353,7 +6438,7 @@ SWIGINTERN PyObject *_wrap_ldb_module_delete(PyObject *SWIGUNUSEDPARM(self), PyO PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "req", NULL + (char *) "self",(char *) "dn", NULL }; ldb_error result; @@ -6363,11 +6448,11 @@ SWIGINTERN PyObject *_wrap_ldb_module_delete(PyObject *SWIGUNUSEDPARM(self), PyO SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_module_delete" "', argument " "1"" of type '" "ldb_module *""'"); } arg1 = (ldb_module *)(argp1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_request, 0 | 0 ); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_dn, 0 | 0 ); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_delete" "', argument " "2"" of type '" "struct ldb_request *""'"); + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_delete" "', argument " "2"" of type '" "struct ldb_dn *""'"); } - arg2 = (struct ldb_request *)(argp2); + arg2 = (struct ldb_dn *)(argp2); result = ldb_module_delete(arg1,arg2); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_errstring(arg1))); @@ -6383,30 +6468,39 @@ fail: SWIGINTERN PyObject *_wrap_ldb_module_rename(PyObject *SWIGUNUSEDPARM(self), PyObject *args, PyObject *kwargs) { PyObject *resultobj = 0; ldb_module *arg1 = (ldb_module *) 0 ; - struct ldb_request *arg2 = (struct ldb_request *) 0 ; + struct ldb_dn *arg2 = (struct ldb_dn *) 0 ; + struct ldb_dn *arg3 = (struct ldb_dn *) 0 ; void *argp1 = 0 ; int res1 = 0 ; void *argp2 = 0 ; int res2 = 0 ; + void *argp3 = 0 ; + int res3 = 0 ; PyObject * obj0 = 0 ; PyObject * obj1 = 0 ; + PyObject * obj2 = 0 ; char * kwnames[] = { - (char *) "self",(char *) "req", NULL + (char *) "self",(char *) "olddn",(char *) "newdn", NULL }; ldb_error result; - if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OO:ldb_module_rename",kwnames,&obj0,&obj1)) SWIG_fail; + if (!PyArg_ParseTupleAndKeywords(args,kwargs,(char *)"OOO:ldb_module_rename",kwnames,&obj0,&obj1,&obj2)) SWIG_fail; res1 = SWIG_ConvertPtr(obj0, &argp1,SWIGTYPE_p_ldb_module, 0 | 0 ); if (!SWIG_IsOK(res1)) { SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "ldb_module_rename" "', argument " "1"" of type '" "ldb_module *""'"); } arg1 = (ldb_module *)(argp1); - res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_request, 0 | 0 ); + res2 = SWIG_ConvertPtr(obj1, &argp2,SWIGTYPE_p_ldb_dn, 0 | 0 ); if (!SWIG_IsOK(res2)) { - SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_rename" "', argument " "2"" of type '" "struct ldb_request *""'"); + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "ldb_module_rename" "', argument " "2"" of type '" "struct ldb_dn *""'"); + } + arg2 = (struct ldb_dn *)(argp2); + res3 = SWIG_ConvertPtr(obj2, &argp3,SWIGTYPE_p_ldb_dn, 0 | 0 ); + if (!SWIG_IsOK(res3)) { + SWIG_exception_fail(SWIG_ArgError(res3), "in method '" "ldb_module_rename" "', argument " "3"" of type '" "struct ldb_dn *""'"); } - arg2 = (struct ldb_request *)(argp2); - result = ldb_module_rename(arg1,arg2); + arg3 = (struct ldb_dn *)(argp3); + result = ldb_module_rename(arg1,arg2,arg3); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_errstring(arg1))); SWIG_fail; @@ -6788,7 +6882,6 @@ static swig_type_info _swigt__p_ldb_message_element = {"_p_ldb_message_element", static swig_type_info _swigt__p_ldb_module = {"_p_ldb_module", "struct ldb_module *|ldb_module *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_module_ops = {"_p_ldb_module_ops", "struct ldb_module_ops *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_parse_tree = {"_p_ldb_parse_tree", "struct ldb_parse_tree *", 0, 0, (void*)0, 0}; -static swig_type_info _swigt__p_ldb_request = {"_p_ldb_request", "struct ldb_request *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_result = {"_p_ldb_result", "struct ldb_result *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_val = {"_p_ldb_val", "struct ldb_val *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0}; @@ -6817,7 +6910,6 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_ldb_module, &_swigt__p_ldb_module_ops, &_swigt__p_ldb_parse_tree, - &_swigt__p_ldb_request, &_swigt__p_ldb_result, &_swigt__p_ldb_val, &_swigt__p_long_long, @@ -6846,7 +6938,6 @@ static swig_cast_info _swigc__p_ldb_message_element[] = { {&_swigt__p_ldb_messa static swig_cast_info _swigc__p_ldb_module[] = { {&_swigt__p_ldb_module, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_module_ops[] = { {&_swigt__p_ldb_module_ops, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_parse_tree[] = { {&_swigt__p_ldb_parse_tree, 0, 0, 0},{0, 0, 0, 0}}; -static swig_cast_info _swigc__p_ldb_request[] = { {&_swigt__p_ldb_request, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_result[] = { {&_swigt__p_ldb_result, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_val[] = { {&_swigt__p_ldb_val, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_long_long[] = { {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}}; @@ -6875,7 +6966,6 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_ldb_module, _swigc__p_ldb_module_ops, _swigc__p_ldb_parse_tree, - _swigc__p_ldb_request, _swigc__p_ldb_result, _swigc__p_ldb_val, _swigc__p_long_long, diff --git a/source4/lib/ldb/tests/python/api.py b/source4/lib/ldb/tests/python/api.py index bc3bbc1c8c..4b3501839f 100755 --- a/source4/lib/ldb/tests/python/api.py +++ b/source4/lib/ldb/tests/python/api.py @@ -2,7 +2,7 @@ # Simple tests for the ldb python bindings. # Copyright (C) 2007 Jelmer Vernooij <jelmer@samba.org> -import sys +import os, sys import unittest # Required for the standalone LDB build @@ -472,11 +472,16 @@ class ModuleTests(unittest.TestCase): def __init__(self, ldb, next): ops.append("init") + self.next = next + + def search(self, *args, **kwargs): + return self.next.search(*args, **kwargs) ldb.register_module(ExampleModule) + if os.path.exists("usemodule.ldb"): + os.unlink("usemodule.ldb") l = ldb.Ldb("usemodule.ldb") - l.add({"dn": "@MODULES", - "@LIST": "bla"}) + l.add({"dn": "@MODULES", "@LIST": "bla"}) self.assertEquals([], ops) l = ldb.Ldb("usemodule.ldb") self.assertEquals(["init"], ops) diff --git a/source4/lib/registry/patchfile.c b/source4/lib/registry/patchfile.c index 0ede3106f0..d49d46250d 100644 --- a/source4/lib/registry/patchfile.c +++ b/source4/lib/registry/patchfile.c @@ -4,6 +4,7 @@ Copyright (C) Jelmer Vernooij 2004-2007 Copyright (C) Wilco Baan Hofman 2006 + Copyright (C) Matthias Dieter Wallnöfer 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -58,8 +59,9 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, &old_num_subkeys, &old_num_values, NULL, NULL, NULL, NULL); if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error occured while getting key info: %s\n", + DEBUG(0, ("Error occurred while getting key info: %s\n", win_errstr(error))); + talloc_free(mem_ctx); return error; } } else { @@ -70,11 +72,10 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, /* Subkeys that were deleted */ for (i = 0; i < old_num_subkeys; i++) { error1 = reg_key_get_subkey_by_index(mem_ctx, oldkey, i, - &keyname1, - NULL, NULL); + &keyname1, NULL, NULL); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Error occured while getting subkey by index: %s\n", - win_errstr(error2))); + DEBUG(0, ("Error occurred while getting subkey by index: %s\n", + win_errstr(error1))); continue; } @@ -98,6 +99,17 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, /* newkey didn't have such a subkey, add del diff */ tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); callbacks->del_key(callback_data, tmppath); + + /* perform here also the recursive invocation */ + error1 = reg_open_key(mem_ctx, oldkey, keyname1, &t1); + if (!W_ERROR_IS_OK(error1)) { + DEBUG(0, ("Error occured while getting subkey by name: %s\n", + win_errstr(error1))); + talloc_free(mem_ctx); + return error1; + } + reg_generate_diff_key(t1, t2, tmppath, callbacks, callback_data); + talloc_free(tmppath); } @@ -106,8 +118,9 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, &new_num_subkeys, &new_num_values, NULL, NULL, NULL, NULL); if (!W_ERROR_IS_OK(error)) { - DEBUG(0, ("Error occured while getting key info: %s\n", + DEBUG(0, ("Error occurred while getting key info: %s\n", win_errstr(error))); + talloc_free(mem_ctx); return error; } } else { @@ -117,11 +130,10 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, /* Subkeys that were added */ for(i = 0; i < new_num_subkeys; i++) { - error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, - i, &keyname1, - NULL, NULL); + error1 = reg_key_get_subkey_by_index(mem_ctx, newkey, i, + &keyname1, NULL, NULL); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Error occured while getting subkey by index: %s\n", + DEBUG(0, ("Error occurred while getting subkey by index: %s\n", win_errstr(error1))); talloc_free(mem_ctx); return error1; @@ -133,12 +145,12 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, if (W_ERROR_IS_OK(error2)) continue; } else { + error2 = WERR_BADFILE; t1 = NULL; - error2 = WERR_BADFILE; } if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { - DEBUG(0, ("Error occured while getting subkey by name: %s\n", + DEBUG(0, ("Error occurred while getting subkey by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); return error2; @@ -148,15 +160,20 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, tmppath = talloc_asprintf(mem_ctx, "%s\\%s", path, keyname1); callbacks->add_key(callback_data, tmppath); - W_ERROR_NOT_OK_RETURN( - reg_open_key(mem_ctx, newkey, keyname1, &t2)); + /* perform here also the recursive invocation */ + error1 = reg_open_key(mem_ctx, newkey, keyname1, &t2); + if (!W_ERROR_IS_OK(error1)) { + DEBUG(0, ("Error occured while getting subkey by name: %s\n", + win_errstr(error1))); + talloc_free(mem_ctx); + return error1; + } + reg_generate_diff_key(t1, t2, tmppath, callbacks, callback_data); - reg_generate_diff_key(t1, t2, tmppath, - callbacks, callback_data); talloc_free(tmppath); } - /* Values that were changed */ + /* Values that were added or changed */ for(i = 0; i < new_num_values; i++) { const char *name; uint32_t type1, type2; @@ -165,7 +182,7 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, error1 = reg_key_get_value_by_index(mem_ctx, newkey, i, &name, &type1, &contents1); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Unable to get key by index: %s\n", + DEBUG(0, ("Unable to get value by index: %s\n", win_errstr(error1))); talloc_free(mem_ctx); return error1; @@ -178,16 +195,17 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, } else error2 = WERR_BADFILE; - if(!W_ERROR_IS_OK(error2) && - !W_ERROR_EQUAL(error2, WERR_BADFILE)) { - DEBUG(0, ("Error occured while getting value by name: %s\n", + if (!W_ERROR_IS_OK(error2) + && !W_ERROR_EQUAL(error2, WERR_BADFILE)) { + DEBUG(0, ("Error occurred while getting value by name: %s\n", win_errstr(error2))); talloc_free(mem_ctx); return error2; } - if (W_ERROR_IS_OK(error2) && - data_blob_cmp(&contents1, &contents2) == 0) + if (W_ERROR_IS_OK(error2) + && (data_blob_cmp(&contents1, &contents2) == 0) + && (type1 == type2)) continue; callbacks->set_value(callback_data, path, name, @@ -197,24 +215,31 @@ WERROR reg_generate_diff_key(struct registry_key *oldkey, /* Values that were deleted */ for (i = 0; i < old_num_values; i++) { const char *name; + uint32_t type; + DATA_BLOB contents; + error1 = reg_key_get_value_by_index(mem_ctx, oldkey, i, &name, - NULL, NULL); + &type, &contents); if (!W_ERROR_IS_OK(error1)) { - DEBUG(0, ("Error ocurred getting value by index: %s\n", + DEBUG(0, ("Unable to get value by index: %s\n", win_errstr(error1))); talloc_free(mem_ctx); return error1; } - error2 = reg_key_get_value_by_name(mem_ctx, newkey, name, NULL, - NULL); + if (newkey != NULL) + error2 = reg_key_get_value_by_name(mem_ctx, newkey, + name, &type, &contents); + else + error2 = WERR_BADFILE; if (W_ERROR_IS_OK(error2)) continue; if (!W_ERROR_EQUAL(error2, WERR_BADFILE)) { - DEBUG(0, ("Error occured while getting value by name: %s\n", + DEBUG(0, ("Error occurred while getting value by name: %s\n", win_errstr(error2))); + talloc_free(mem_ctx); return error2; } @@ -236,27 +261,30 @@ _PUBLIC_ WERROR reg_generate_diff(struct registry_context *ctx1, int i; WERROR error; - for(i = HKEY_FIRST; i <= HKEY_LAST; i++) { + for (i = 0; reg_predefined_keys[i].name; i++) { struct registry_key *r1 = NULL, *r2 = NULL; - error = reg_get_predefined_key(ctx1, i, &r1); + + error = reg_get_predefined_key(ctx1, + reg_predefined_keys[i].handle, &r1); if (!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_BADFILE)) { DEBUG(0, ("Unable to open hive %s for backend 1\n", - reg_get_predef_name(i))); + reg_predefined_keys[i].name)); + continue; } - error = reg_get_predefined_key(ctx2, i, &r2); + error = reg_get_predefined_key(ctx2, + reg_predefined_keys[i].handle, &r2); if (!W_ERROR_IS_OK(error) && !W_ERROR_EQUAL(error, WERR_BADFILE)) { DEBUG(0, ("Unable to open hive %s for backend 2\n", - reg_get_predef_name(i))); - } - - if (r1 == NULL && r2 == NULL) + reg_predefined_keys[i].name)); continue; + } - error = reg_generate_diff_key(r1, r2, reg_get_predef_name(i), - callbacks, callback_data); + error = reg_generate_diff_key(r1, r2, + reg_predefined_keys[i].name, callbacks, + callback_data); if (!W_ERROR_IS_OK(error)) { DEBUG(0, ("Unable to determine diff: %s\n", win_errstr(error))); diff --git a/source4/lib/registry/rpc.c b/source4/lib/registry/rpc.c index 18b7607713..6429a390db 100644 --- a/source4/lib/registry/rpc.c +++ b/source4/lib/registry/rpc.c @@ -2,6 +2,7 @@ Samba Unix/Linux SMB implementation RPC backend for the registry library Copyright (C) 2003-2007 Jelmer Vernooij, jelmer@samba.org + Copyright (C) 2008 Matthias Dieter Wallnöfer, mwallnoefer@yahoo.de This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,16 +21,23 @@ #include "registry.h" #include "librpc/gen_ndr/ndr_winreg_c.h" +#define MAX_NAMESIZE 512 +#define MAX_VALSIZE 32768 + struct rpc_key { struct registry_key key; struct policy_handle pol; struct dcerpc_pipe *pipe; - uint32_t num_values; + const char* classname; uint32_t num_subkeys; + uint32_t max_subkeylen; + uint32_t max_subkeysize; + uint32_t num_values; uint32_t max_valnamelen; - uint32_t max_valdatalen; - uint32_t max_subkeynamelen; + uint32_t max_valbufsize; + uint32_t secdescsize; + NTTIME last_changed_time; }; struct rpc_registry_context { @@ -43,26 +51,22 @@ static struct registry_operations reg_backend_rpc; * This is the RPC backend for the registry library. */ -static void init_winreg_String(struct winreg_String *name, const char *s) -{ - name->name = s; -} - - #define openhive(u) static WERROR open_ ## u(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx, struct policy_handle *hnd) \ { \ struct winreg_Open ## u r; \ NTSTATUS status; \ - \ +\ + ZERO_STRUCT(r); \ r.in.system_name = NULL; \ r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; \ r.out.handle = hnd;\ - \ +\ status = dcerpc_winreg_Open ## u(p, mem_ctx, &r); \ - if (NT_STATUS_IS_ERR(status)) {\ - DEBUG(0,("Error executing open\n"));\ - return ntstatus_to_werror(status);\ - }\ +\ + if (!NT_STATUS_IS_OK(status)) { \ + DEBUG(1, ("OpenHive failed - %s\n", nt_errstr(status))); \ + return ntstatus_to_werror(status); \ + } \ \ return r.out.result;\ } @@ -90,7 +94,7 @@ static struct { { 0, NULL } }; -static WERROR rpc_query_key(const struct registry_key *k); +static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k); static WERROR rpc_get_predefined_key(struct registry_context *ctx, uint32_t hkey_type, @@ -127,15 +131,15 @@ static WERROR rpc_key_put_rpc_data(TALLOC_CTX *mem_ctx, struct registry_key *k) struct winreg_OpenKey r; struct rpc_key_data *mykeydata; - k->backend_data = mykeydata = talloc(mem_ctx, struct rpc_key_data); + k->backend_data = mykeydata = talloc_zero(mem_ctx, struct rpc_key_data); mykeydata->num_values = -1; mykeydata->num_subkeys = -1; /* Then, open the handle using the hive */ - memset(&r, 0, sizeof(struct winreg_OpenKey)); + ZERO_STRUCT(r); r.in.handle = &(((struct rpc_key_data *)k->hive->root->backend_data)->pol); - init_winreg_String(&r.in.keyname, k->path); + r.in.keyname.name = k->path; r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; @@ -155,8 +159,7 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, struct winreg_OpenKey r; NTSTATUS status; - mykeydata = talloc(mem_ctx, struct rpc_key); - + mykeydata = talloc_zero(mem_ctx, struct rpc_key); mykeydata->key.context = parentkeydata->key.context; mykeydata->pipe = talloc_reference(mykeydata, parentkeydata->pipe); mykeydata->num_values = -1; @@ -166,14 +169,15 @@ static WERROR rpc_open_key(TALLOC_CTX *mem_ctx, struct registry_key *h, /* Then, open the handle using the hive */ ZERO_STRUCT(r); r.in.parent_handle = &parentkeydata->pol; - init_winreg_String(&r.in.keyname, name); + r.in.keyname.name = name; r.in.unknown = 0x00000000; r.in.access_mask = 0x02000000; r.out.handle = &mykeydata->pol; status = dcerpc_winreg_OpenKey(mykeydata->pipe, mem_ctx, &r); - if (NT_STATUS_IS_ERR(status)) { - DEBUG(0,("Error executing openkey: %s\n", nt_errstr(status))); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("OpenKey failed - %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } @@ -188,47 +192,94 @@ static WERROR rpc_get_value_by_index(TALLOC_CTX *mem_ctx, DATA_BLOB *data) { struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); - WERROR error; struct winreg_EnumValue r; - uint32_t in_type = 0; - NTSTATUS status; struct winreg_StringBuf name; + uint8_t value; + uint32_t val_size = MAX_VALSIZE; uint32_t zero = 0; - - ZERO_STRUCT(r); + WERROR error; + NTSTATUS status; if (mykeydata->num_values == -1) { - error = rpc_query_key(parent); + error = rpc_query_key(mem_ctx, parent); if(!W_ERROR_IS_OK(error)) return error; } - name.length = 0; - name.size = mykeydata->max_valnamelen * 2; - name.name = NULL; + name.name = ""; + name.size = MAX_NAMESIZE; + ZERO_STRUCT(r); r.in.handle = &mykeydata->pol; r.in.enum_index = n; r.in.name = &name; - r.in.type = &in_type; - r.in.value = talloc_zero_array(mem_ctx, uint8_t, 0); + r.in.type = type; + r.in.value = &value; + r.in.size = &val_size; r.in.length = &zero; - r.in.size = &mykeydata->max_valdatalen; r.out.name = &name; r.out.type = type; + r.out.value = &value; + r.out.size = &val_size; + r.out.length = &zero; status = dcerpc_winreg_EnumValue(mykeydata->pipe, mem_ctx, &r); - if(NT_STATUS_IS_ERR(status)) { - DEBUG(0, ("Error in EnumValue: %s\n", nt_errstr(status))); - return WERR_GENERAL_FAILURE; + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("EnumValue failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); } - if(NT_STATUS_IS_OK(status) && - W_ERROR_IS_OK(r.out.result) && r.out.length) { - *value_name = talloc_strdup(mem_ctx, r.out.name->name); - *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length); - return WERR_OK; + *value_name = talloc_reference(mem_ctx, r.out.name->name); + *type = *(r.out.type); + *data = data_blob_talloc(mem_ctx, r.out.value, *r.out.length); + + return r.out.result; +} + +static WERROR rpc_get_value_by_name(TALLOC_CTX *mem_ctx, + const struct registry_key *parent, + const char *value_name, + uint32_t *type, + DATA_BLOB *data) +{ + struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); + struct winreg_QueryValue r; + struct winreg_String name; + uint8_t value; + uint32_t val_size = MAX_VALSIZE; + uint32_t zero = 0; + WERROR error; + NTSTATUS status; + + if (mykeydata->num_values == -1) { + error = rpc_query_key(mem_ctx, parent); + if(!W_ERROR_IS_OK(error)) return error; + } + + name.name = value_name; + + ZERO_STRUCT(r); + r.in.handle = &mykeydata->pol; + r.in.value_name = name; + r.in.type = type; + r.in.data = &value; + r.in.size = &val_size; + r.in.length = &zero; + r.out.type = type; + r.out.data = &value; + r.out.size = &val_size; + r.out.length = &zero; + + status = dcerpc_winreg_QueryValue(mykeydata->pipe, mem_ctx, &r); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("QueryValue failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); } + *type = *(r.out.type); + *data = data_blob_talloc(mem_ctx, r.out.data, *r.out.length); + return r.out.result; } @@ -241,34 +292,39 @@ static WERROR rpc_get_subkey_by_index(TALLOC_CTX *mem_ctx, { struct winreg_EnumKey r; struct rpc_key *mykeydata = talloc_get_type(parent, struct rpc_key); - NTSTATUS status; struct winreg_StringBuf namebuf, classbuf; NTTIME change_time = 0; + NTSTATUS status; - ZERO_STRUCT(r); - - namebuf.length = 0; - namebuf.size = 1024; - namebuf.name = NULL; - classbuf.length = 0; - classbuf.size = 0; - classbuf.name = NULL; + namebuf.name = ""; + namebuf.size = MAX_NAMESIZE; + classbuf.name = NULL; + classbuf.size = 0; + ZERO_STRUCT(r); r.in.handle = &mykeydata->pol; r.in.enum_index = n; r.in.name = &namebuf; r.in.keyclass = &classbuf; r.in.last_changed_time = &change_time; - r.out.name = &namebuf; + r.out.keyclass = &classbuf; + r.out.last_changed_time = &change_time; status = dcerpc_winreg_EnumKey(mykeydata->pipe, mem_ctx, &r); - if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(r.out.result)) { - *name = talloc_strdup(mem_ctx, r.out.name->name); - if (keyclass != NULL) - *keyclass = talloc_strdup(mem_ctx, r.out.keyclass->name); + + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("EnumKey failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); } + if (name != NULL) + *name = talloc_reference(mem_ctx, r.out.name->name); + if (keyclass != NULL) + *keyclass = talloc_reference(mem_ctx, r.out.keyclass->name); + if (last_changed_time != NULL) + *last_changed_time = *(r.out.last_changed_time); + return r.out.result; } @@ -278,19 +334,22 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, struct security_descriptor *sec, struct registry_key **key) { - NTSTATUS status; struct winreg_CreateKey r; struct rpc_key *parentkd = talloc_get_type(parent, struct rpc_key); struct rpc_key *rpck = talloc(mem_ctx, struct rpc_key); + + NTSTATUS status; - init_winreg_String(&r.in.name, name); - init_winreg_String(&r.in.keyclass, NULL); - + ZERO_STRUCT(r); r.in.handle = &parentkd->pol; - r.out.new_handle = &rpck->pol; + r.in.name.name = name; + r.in.keyclass.name = NULL; r.in.options = 0; - r.in.access_mask = SEC_STD_ALL; + r.in.access_mask = 0x02000000; r.in.secdesc = NULL; + r.in.action_taken = NULL; + r.out.new_handle = &rpck->pol; + r.out.action_taken = NULL; status = dcerpc_winreg_CreateKey(parentkd->pipe, mem_ctx, &r); @@ -300,49 +359,42 @@ static WERROR rpc_add_key(TALLOC_CTX *mem_ctx, return ntstatus_to_werror(status); } - if (W_ERROR_IS_OK(r.out.result)) { - rpck->pipe = talloc_reference(rpck, parentkd->pipe); - *key = (struct registry_key *)rpck; - } + rpck->pipe = talloc_reference(rpck, parentkd->pipe); + *key = (struct registry_key *)rpck; return r.out.result; } -static WERROR rpc_query_key(const struct registry_key *k) +static WERROR rpc_query_key(TALLOC_CTX *mem_ctx, const struct registry_key *k) { - NTSTATUS status; struct winreg_QueryInfoKey r; struct rpc_key *mykeydata = talloc_get_type(k, struct rpc_key); - TALLOC_CTX *mem_ctx = talloc_init("query_key"); - uint32_t max_subkeysize; - uint32_t secdescsize; - NTTIME last_changed_time; + struct winreg_String classname; + NTSTATUS status; - ZERO_STRUCT(r.out); + classname.name = NULL; + ZERO_STRUCT(r); + r.in.handle = &mykeydata->pol; + r.in.classname = &classname; + r.out.classname = &classname; r.out.num_subkeys = &mykeydata->num_subkeys; - r.out.max_subkeylen = &mykeydata->max_subkeynamelen; - r.out.max_valnamelen = &mykeydata->max_valnamelen; - r.out.max_valbufsize = &mykeydata->max_valdatalen; - r.out.max_subkeysize = &max_subkeysize; + r.out.max_subkeylen = &mykeydata->max_subkeylen; + r.out.max_subkeysize = &mykeydata->max_subkeysize; r.out.num_values = &mykeydata->num_values; - r.out.secdescsize = &secdescsize; - r.out.last_changed_time = &last_changed_time; - - r.out.classname = r.in.classname = talloc_zero(mem_ctx, struct winreg_String); - init_winreg_String(r.in.classname, NULL); - r.in.handle = &mykeydata->pol; + r.out.max_valnamelen = &mykeydata->max_valnamelen; + r.out.max_valbufsize = &mykeydata->max_valbufsize; + r.out.secdescsize = &mykeydata->secdescsize; + r.out.last_changed_time = &mykeydata->last_changed_time; status = dcerpc_winreg_QueryInfoKey(mykeydata->pipe, mem_ctx, &r); - talloc_free(mem_ctx); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("QueryInfoKey failed - %s\n", nt_errstr(status))); return ntstatus_to_werror(status); } - if (W_ERROR_IS_OK(r.out.result)) { - } + mykeydata->classname = talloc_reference(mem_ctx, r.out.classname->name); return r.out.result; } @@ -354,22 +406,28 @@ static WERROR rpc_del_key(struct registry_key *parent, const char *name) struct winreg_DeleteKey r; TALLOC_CTX *mem_ctx = talloc_init("del_key"); + ZERO_STRUCT(r); r.in.handle = &mykeydata->pol; - init_winreg_String(&r.in.key, name); + r.in.key.name = name; status = dcerpc_winreg_DeleteKey(mykeydata->pipe, mem_ctx, &r); talloc_free(mem_ctx); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1, ("DeleteKey failed - %s\n", nt_errstr(status))); + return ntstatus_to_werror(status); + } + return r.out.result; } static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key, const char **classname, - uint32_t *numsubkeys, - uint32_t *numvalue, + uint32_t *num_subkeys, + uint32_t *num_values, NTTIME *last_changed_time, - uint32_t *max_subkeynamelen, + uint32_t *max_subkeylen, uint32_t *max_valnamelen, uint32_t *max_valbufsize) { @@ -377,27 +435,30 @@ static WERROR rpc_get_info(TALLOC_CTX *mem_ctx, const struct registry_key *key, WERROR error; if (mykeydata->num_values == -1) { - error = rpc_query_key(key); + error = rpc_query_key(mem_ctx, key); if(!W_ERROR_IS_OK(error)) return error; } - /* FIXME: *classname = talloc_strdup(mem_ctx, mykeydata->classname); */ - /* FIXME: *last_changed_time = mykeydata->last_changed_time */ + if (classname != NULL) + *classname = mykeydata->classname; + + if (num_subkeys != NULL) + *num_subkeys = mykeydata->num_subkeys; - if (numvalue != NULL) - *numvalue = mykeydata->num_values; + if (num_values != NULL) + *num_values = mykeydata->num_values; - if (numsubkeys != NULL) - *numsubkeys = mykeydata->num_subkeys; + if (last_changed_time != NULL) + *last_changed_time = mykeydata->last_changed_time; + + if (max_subkeylen != NULL) + *max_subkeylen = mykeydata->max_subkeylen; if (max_valnamelen != NULL) *max_valnamelen = mykeydata->max_valnamelen; if (max_valbufsize != NULL) - *max_valbufsize = mykeydata->max_valdatalen; - - if (max_subkeynamelen != NULL) - *max_subkeynamelen = mykeydata->max_subkeynamelen; + *max_valbufsize = mykeydata->max_valbufsize; return WERR_OK; } @@ -408,6 +469,7 @@ static struct registry_operations reg_backend_rpc = { .get_predefined_key = rpc_get_predefined_key, .enum_key = rpc_get_subkey_by_index, .enum_value = rpc_get_value_by_index, + .get_value = rpc_get_value_by_name, .create_key = rpc_add_key, .delete_key = rpc_del_key, .get_key_info = rpc_get_info, diff --git a/source4/lib/registry/tools/regdiff.c b/source4/lib/registry/tools/regdiff.c index 240c582340..fcf7c26237 100644 --- a/source4/lib/registry/tools/regdiff.c +++ b/source4/lib/registry/tools/regdiff.c @@ -46,7 +46,7 @@ static struct registry_context *open_backend(poptContext pc, break; case REG_REMOTE: error = reg_open_remote(&ctx, NULL, cmdline_credentials, lp_ctx, - remote_host, NULL); + remote_host, ev_ctx); break; case REG_NULL: error = reg_open_local(NULL, &ctx); diff --git a/source4/lib/registry/tools/regshell.c b/source4/lib/registry/tools/regshell.c index 98f7f02c38..5c308bfbda 100644 --- a/source4/lib/registry/tools/regshell.c +++ b/source4/lib/registry/tools/regshell.c @@ -207,8 +207,8 @@ static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv) { int i; WERROR error; - uint32_t data_type; - DATA_BLOB data; + uint32_t valuetype; + DATA_BLOB valuedata; const char *name = NULL; for (i = 0; W_ERROR_IS_OK(error = reg_key_get_subkey_by_index(ctx, @@ -221,19 +221,15 @@ static WERROR cmd_ls(struct regshell_context *ctx, int argc, char **argv) } if (!W_ERROR_EQUAL(error, WERR_NO_MORE_ITEMS)) { - DEBUG(0, ("Error occured while browsing thru keys: %s\n", - win_errstr(error))); + fprintf(stderr, "Error occured while browsing thru keys: %s\n", + win_errstr(error)); + return error; } for (i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(ctx, - ctx->current, - i, - &name, - &data_type, - &data)); i++) { - printf("V \"%s\" %s %s\n", name, str_regtype(data_type), - reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), data_type, data)); - } + ctx->current, i, &name, &valuetype, &valuedata)); i++) + printf("V \"%s\" %s %s\n", name, str_regtype(valuetype), + reg_val_data_string(ctx, lp_iconv_convenience(cmdline_lp_ctx), valuetype, valuedata)); return WERR_OK; } @@ -250,7 +246,8 @@ static WERROR cmd_mkkey(struct regshell_context *ctx, int argc, char **argv) error = reg_key_add_name(ctx, ctx->current, argv[1], 0, NULL, &tmp); if (!W_ERROR_IS_OK(error)) { - fprintf(stderr, "Error adding new subkey '%s'\n", argv[1]); + fprintf(stderr, "Error adding new subkey '%s': %s\n", argv[1], + win_errstr(error)); return error; } @@ -438,7 +435,7 @@ static char **reg_complete_key(const char *text, int start, int end) len = strlen(text); for(i = 0; j < MAX_COMPLETIONS-1; i++) { status = reg_key_get_subkey_by_index(mem_ctx, base, i, - &subkeyname, NULL, NULL); + &subkeyname, NULL, NULL); if(W_ERROR_IS_OK(status)) { if(!strncmp(text, subkeyname, len)) { matches[j] = strdup(subkeyname); @@ -536,7 +533,8 @@ int main(int argc, char **argv) if (ctx->current == NULL) { int i; - for (i = 0; reg_predefined_keys[i].handle; i++) { + for (i = 0; (reg_predefined_keys[i].handle != 0) && + (ctx->current == NULL); i++) { WERROR err; err = reg_get_predefined_key(ctx->registry, reg_predefined_keys[i].handle, diff --git a/source4/lib/registry/tools/regtree.c b/source4/lib/registry/tools/regtree.c index 19e4a010b4..6d55a3eb84 100644 --- a/source4/lib/registry/tools/regtree.c +++ b/source4/lib/registry/tools/regtree.c @@ -38,10 +38,9 @@ static void print_tree(int level, struct registry_key *p, bool fullpath, bool novals) { struct registry_key *subkey; - const char *valuename; - const char *keyname; - uint32_t value_type; - DATA_BLOB value_data; + const char *valuename, *keyname; + uint32_t valuetype; + DATA_BLOB valuedata; struct security_descriptor *sec_desc; WERROR error; int i; @@ -73,18 +72,14 @@ static void print_tree(int level, struct registry_key *p, if (!novals) { mem_ctx = talloc_init("print_tree"); - for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index(mem_ctx, - p, - i, - &valuename, - &value_type, - &value_data)); i++) { + for(i = 0; W_ERROR_IS_OK(error = reg_key_get_value_by_index( + mem_ctx, p, i, &valuename, &valuetype, &valuedata)); + i++) { int j; - char *desc; for(j = 0; j < level+1; j++) putchar(' '); - desc = reg_val_description(mem_ctx, lp_iconv_convenience(cmdline_lp_ctx), valuename, - value_type, value_data); - printf("%s\n", desc); + printf("%s\n", reg_val_description(mem_ctx, + lp_iconv_convenience(cmdline_lp_ctx), valuename, + valuetype, valuedata)); } talloc_free(mem_ctx); diff --git a/source4/libcli/auth/smbencrypt.c b/source4/libcli/auth/smbencrypt.c index 7de9627302..b50f003b91 100644 --- a/source4/libcli/auth/smbencrypt.c +++ b/source4/libcli/auth/smbencrypt.c @@ -497,10 +497,10 @@ bool encode_pw_buffer(uint8_t buffer[516], const char *password, int string_flag returned password including termination. ************************************************************/ bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd, - int new_pwrd_size, uint32_t *new_pw_len, - int string_flags) + int new_pwrd_size, int string_flags) { int byte_len=0; + ssize_t converted_pw_len; /* the incoming buffer can be any alignment. */ string_flags |= STR_NOALIGN; @@ -526,13 +526,17 @@ bool decode_pw_buffer(uint8_t in_buffer[516], char *new_pwrd, } /* decode into the return buffer. Buffer length supplied */ - *new_pw_len = pull_string(lp_iconv_convenience(global_loadparm), new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, + converted_pw_len = pull_string(lp_iconv_convenience(global_loadparm), new_pwrd, &in_buffer[512 - byte_len], new_pwrd_size, byte_len, string_flags); + if (converted_pw_len == -1) { + return false; + } + #ifdef DEBUG_PASSWORD DEBUG(100,("decode_pw_buffer: new_pwrd: ")); - dump_data(100, (const uint8_t *)new_pwrd, *new_pw_len); - DEBUG(100,("multibyte len:%d\n", *new_pw_len)); + dump_data(100, (const uint8_t *)new_pwrd, converted_pw_len); + DEBUG(100,("multibyte len:%d\n", converted_pw_len)); DEBUG(100,("original char len:%d\n", byte_len/2)); #endif diff --git a/source4/libcli/composite/composite.c b/source4/libcli/composite/composite.c index 3e3f224f47..104397fa48 100644 --- a/source4/libcli/composite/composite.c +++ b/source4/libcli/composite/composite.c @@ -28,7 +28,7 @@ #include "libcli/composite/composite.h" #include "lib/messaging/irpc.h" #include "librpc/rpc/dcerpc.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" /* create a new composite_context structure @@ -214,5 +214,5 @@ _PUBLIC_ void composite_continue_nbt(struct composite_context *ctx, { if (composite_nomem(new_req, ctx)) return; new_req->async.fn = continuation; - new_req->async.private = private_data; + new_req->async.private_data = private_data; } diff --git a/source4/libcli/config.mk b/source4/libcli/config.mk index 262a2cfa22..cee51439ab 100644 --- a/source4/libcli/config.mk +++ b/source4/libcli/config.mk @@ -40,22 +40,22 @@ $(eval $(call proto_header_template,$(libclisrcdir)/smb_composite/proto.h,$(LIBC [SUBSYSTEM::NDR_NBT_BUF] -NDR_NBT_BUF_OBJ_FILES = $(libclisrcdir)/nbt/nbtname.o +NDR_NBT_BUF_OBJ_FILES = ../$(libclisrcdir)/nbt/nbtname.o -$(eval $(call proto_header_template,$(libclisrcdir)/nbt/nbtname.h,$(NDR_NBT_BUF_OBJ_FILES:.o=.c))) +$(eval $(call proto_header_template,../$(libclisrcdir)/nbt/nbtname.h,$(NDR_NBT_BUF_OBJ_FILES:.o=.c))) [SUBSYSTEM::LIBCLI_NBT] PUBLIC_DEPENDENCIES = LIBNDR NDR_NBT LIBCLI_COMPOSITE LIBEVENTS \ NDR_SECURITY samba-socket LIBSAMBA-UTIL -LIBCLI_NBT_OBJ_FILES = $(addprefix $(libclisrcdir)/nbt/, \ +LIBCLI_NBT_OBJ_FILES = $(addprefix ../$(libclisrcdir)/nbt/, \ nbtsocket.o \ namequery.o \ nameregister.o \ namerefresh.o \ namerelease.o) -$(eval $(call proto_header_template,$(libclisrcdir)/nbt/nbt_proto.h,$(LIBCLI_NBT_OBJ_FILES:.o=.c))) +$(eval $(call proto_header_template,../$(libclisrcdir)/nbt/nbt_proto.h,$(LIBCLI_NBT_OBJ_FILES:.o=.c))) [SUBSYSTEM::LIBCLI_NDR_NETLOGON] PUBLIC_DEPENDENCIES = LIBNDR \ @@ -85,7 +85,7 @@ $(eval $(call proto_header_template,$(libclisrcdir)/drsblobs_proto.h,$(LIBCLI_DR LIBRARY_REALNAME = samba/netbios.$(SHLIBEXT) PUBLIC_DEPENDENCIES = LIBCLI_NBT DYNCONFIG LIBSAMBA-HOSTCONFIG -python_netbios_OBJ_FILES = $(libclisrcdir)/nbt/pynbt.o +python_netbios_OBJ_FILES = ../$(libclisrcdir)/nbt/pynbt.o $(python_libcli_nbt_OBJ_FILES): CFLAGS+=$(CFLAG_NO_UNUSED_MACROS) $(CFLAG_NO_CAST_QUAL) diff --git a/source4/libcli/finddcs.c b/source4/libcli/finddcs.c index 56f931ce19..f12f1ac805 100644 --- a/source4/libcli/finddcs.c +++ b/source4/libcli/finddcs.c @@ -217,7 +217,7 @@ static void fallback_node_status(struct finddcs_state *state) static void fallback_node_status_replied(struct nbt_name_request *name_req) { int i; - struct finddcs_state *state = talloc_get_type(name_req->async.private, struct finddcs_state); + struct finddcs_state *state = talloc_get_type(name_req->async.private_data, struct finddcs_state); state->ctx->status = nbt_name_status_recv(name_req, state, &state->node_status); if (!composite_is_ok(state->ctx)) return; diff --git a/source4/libcli/nbt/libnbt.h b/source4/libcli/nbt/libnbt.h deleted file mode 100644 index 0b01365510..0000000000 --- a/source4/libcli/nbt/libnbt.h +++ /dev/null @@ -1,351 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - a raw async NBT library - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#ifndef __LIBNBT_H__ -#define __LIBNBT_H__ - -#include "librpc/gen_ndr/nbt.h" -#include "librpc/ndr/libndr.h" - -/* - possible states for pending requests -*/ -enum nbt_request_state {NBT_REQUEST_SEND, - NBT_REQUEST_WAIT, - NBT_REQUEST_DONE, - NBT_REQUEST_TIMEOUT, - NBT_REQUEST_ERROR}; - -/* - a nbt name request -*/ -struct nbt_name_request { - struct nbt_name_request *next, *prev; - - enum nbt_request_state state; - - NTSTATUS status; - - /* the socket this was on */ - struct nbt_name_socket *nbtsock; - - /* where to send the request */ - struct socket_address *dest; - - /* timeout between retries */ - int timeout; - - /* how many retries to send on timeout */ - int num_retries; - - /* whether we have received a WACK */ - bool received_wack; - - /* the timeout event */ - struct timed_event *te; - - /* the name transaction id */ - uint16_t name_trn_id; - - /* is it a reply? */ - bool is_reply; - - /* the encoded request */ - DATA_BLOB encoded; - - /* shall we allow multiple replies? */ - bool allow_multiple_replies; - - unsigned int num_replies; - struct nbt_name_reply { - struct nbt_name_packet *packet; - struct socket_address *dest; - } *replies; - - /* information on what to do on completion */ - struct { - void (*fn)(struct nbt_name_request *); - void *private; - } async; -}; - - - -/* - context structure for operations on name queries -*/ -struct nbt_name_socket { - struct socket_context *sock; - struct event_context *event_ctx; - struct smb_iconv_convenience *iconv_convenience; - - /* a queue of requests pending to be sent */ - struct nbt_name_request *send_queue; - - /* the fd event */ - struct fd_event *fde; - - /* mapping from name_trn_id to pending event */ - struct idr_context *idr; - - /* how many requests are waiting for a reply */ - uint16_t num_pending; - - /* what to do with incoming request packets */ - struct { - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *); - void *private; - } incoming; - - /* what to do with unexpected replies */ - struct { - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *); - void *private; - } unexpected; -}; - - -/* a simple name query */ -struct nbt_name_query { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - bool broadcast; - bool wins_lookup; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - int16_t num_addrs; - const char **reply_addrs; - } out; -}; - -/* a simple name status query */ -struct nbt_name_status { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - struct nbt_rdata_status status; - } out; -}; - -/* a name registration request */ -struct nbt_name_register { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - bool register_demand; - bool broadcast; - bool multi_homed; - uint32_t ttl; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - const char *reply_addr; - uint8_t rcode; - } out; -}; - -/* a send 3 times then demand name broadcast name registration */ -struct nbt_name_register_bcast { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - uint32_t ttl; - } in; -}; - - -/* wins name register with multiple wins servers to try and multiple - addresses to register */ -struct nbt_name_register_wins { - struct { - struct nbt_name name; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - uint16_t nb_flags; - uint32_t ttl; - } in; - struct { - const char *wins_server; - uint8_t rcode; - } out; -}; - - - -/* a name refresh request */ -struct nbt_name_refresh { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - bool broadcast; - uint32_t ttl; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - const char *reply_addr; - uint8_t rcode; - } out; -}; - -/* wins name refresh with multiple wins servers to try and multiple - addresses to register */ -struct nbt_name_refresh_wins { - struct { - struct nbt_name name; - const char **wins_servers; - uint16_t wins_port; - const char **addresses; - uint16_t nb_flags; - uint32_t ttl; - } in; - struct { - const char *wins_server; - uint8_t rcode; - } out; -}; - - -/* a name release request */ -struct nbt_name_release { - struct { - struct nbt_name name; - const char *dest_addr; - uint16_t dest_port; - const char *address; - uint16_t nb_flags; - bool broadcast; - int timeout; /* in seconds */ - int retries; - } in; - struct { - const char *reply_from; - struct nbt_name name; - const char *reply_addr; - uint8_t rcode; - } out; -}; - -struct nbt_name_socket *nbt_name_socket_init(TALLOC_CTX *mem_ctx, - struct event_context *event_ctx, - struct smb_iconv_convenience *iconv_convenience); -struct nbt_name_request *nbt_name_query_send(struct nbt_name_socket *nbtsock, - struct nbt_name_query *io); -NTSTATUS nbt_name_query_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io); -NTSTATUS nbt_name_query(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_query *io); -struct nbt_name_request *nbt_name_status_send(struct nbt_name_socket *nbtsock, - struct nbt_name_status *io); -NTSTATUS nbt_name_status_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io); -NTSTATUS nbt_name_status(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_status *io); - -NTSTATUS nbt_name_dup(TALLOC_CTX *mem_ctx, struct nbt_name *name, struct nbt_name *newname); -NTSTATUS nbt_name_to_blob(TALLOC_CTX *mem_ctx, struct smb_iconv_convenience *iconv_convenience, DATA_BLOB *blob, struct nbt_name *name); -NTSTATUS nbt_name_from_blob(TALLOC_CTX *mem_ctx, const DATA_BLOB *blob, struct nbt_name *name); -void nbt_choose_called_name(TALLOC_CTX *mem_ctx, struct nbt_name *n, const char *name, int type); -char *nbt_name_string(TALLOC_CTX *mem_ctx, const struct nbt_name *name); -NTSTATUS nbt_name_register(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_register *io); -NTSTATUS nbt_name_refresh(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io); -NTSTATUS nbt_name_release(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, struct nbt_name_release *io); -NTSTATUS nbt_name_register_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io); -NTSTATUS nbt_name_refresh_wins(struct nbt_name_socket *nbtsock, - TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io); -NTSTATUS nbt_name_register_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_register *io); -struct nbt_name_request *nbt_name_register_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register *io); -NTSTATUS nbt_name_release_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_release *io); - -struct nbt_name_request *nbt_name_release_send(struct nbt_name_socket *nbtsock, - struct nbt_name_release *io); - -NTSTATUS nbt_name_refresh_recv(struct nbt_name_request *req, - TALLOC_CTX *mem_ctx, struct nbt_name_refresh *io); - -NTSTATUS nbt_set_incoming_handler(struct nbt_name_socket *nbtsock, - void (*handler)(struct nbt_name_socket *, struct nbt_name_packet *, - struct socket_address *), - void *private); -NTSTATUS nbt_name_reply_send(struct nbt_name_socket *nbtsock, - struct socket_address *dest, - struct nbt_name_packet *request); - - -NDR_SCALAR_PROTO(wrepl_nbt_name, const struct nbt_name *) -NDR_SCALAR_PROTO(nbt_string, const char *) -NDR_BUFFER_PROTO(nbt_name, struct nbt_name) -NTSTATUS nbt_rcode_to_ntstatus(uint8_t rcode); - -struct composite_context; -struct composite_context *nbt_name_register_bcast_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_bcast *io); -NTSTATUS nbt_name_register_bcast_recv(struct composite_context *c); -struct composite_context *nbt_name_register_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_register_wins *io); -NTSTATUS nbt_name_refresh_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_refresh_wins *io); -struct composite_context *nbt_name_refresh_wins_send(struct nbt_name_socket *nbtsock, - struct nbt_name_refresh_wins *io); -NTSTATUS nbt_name_register_wins_recv(struct composite_context *c, TALLOC_CTX *mem_ctx, - struct nbt_name_register_wins *io); - - -#endif /* __LIBNBT_H__ */ diff --git a/source4/libcli/raw/clitransport.c b/source4/libcli/raw/clitransport.c index e95ae3271e..f8ef343e3a 100644 --- a/source4/libcli/raw/clitransport.c +++ b/source4/libcli/raw/clitransport.c @@ -28,7 +28,7 @@ #include "lib/stream/packet.h" #include "librpc/gen_ndr/ndr_nbt.h" #include "param/param.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" /* diff --git a/source4/libcli/raw/libcliraw.h b/source4/libcli/raw/libcliraw.h index d55b4cc42c..bd9bda0db1 100644 --- a/source4/libcli/raw/libcliraw.h +++ b/source4/libcli/raw/libcliraw.h @@ -261,6 +261,12 @@ struct smbcli_request { counter by one */ uint_t sign_single_increment:1; + /* the caller wants to do the signing check */ + bool sign_caller_checks; + + /* give the caller a chance to prevent the talloc_free() in the _recv() function */ + bool do_not_free; + /* the mid of this packet - used to match replies */ uint16_t mid; diff --git a/source4/libcli/raw/rawrequest.c b/source4/libcli/raw/rawrequest.c index a0e6452748..dd9b1f3e96 100644 --- a/source4/libcli/raw/rawrequest.c +++ b/source4/libcli/raw/rawrequest.c @@ -72,7 +72,11 @@ _PUBLIC_ NTSTATUS smbcli_request_destroy(struct smbcli_request *req) } status = req->status; - talloc_free(req); + + if (!req->do_not_free) { + talloc_free(req); + } + return status; } diff --git a/source4/libcli/raw/smb_signing.c b/source4/libcli/raw/smb_signing.c index 1d03686d9a..826d7dd56b 100644 --- a/source4/libcli/raw/smb_signing.c +++ b/source4/libcli/raw/smb_signing.c @@ -298,11 +298,20 @@ bool smbcli_request_check_sign_mac(struct smbcli_request *req) { bool good; + if (!req->transport->negotiate.sign_info.doing_signing && + req->sign_caller_checks) { + return true; + } + + req->sign_caller_checks = false; + switch (req->transport->negotiate.sign_info.signing_state) { case SMB_SIGNING_ENGINE_OFF: return true; case SMB_SIGNING_ENGINE_BSRSPYL: + return true; + case SMB_SIGNING_ENGINE_ON: { if (req->in.size < (HDR_SS_FIELD + 8)) { @@ -350,6 +359,7 @@ bool smbcli_simple_set_signing(TALLOC_CTX *mem_ctx, dump_data_pw("Started Signing with key:\n", sign_info->mac_key.data, sign_info->mac_key.length); sign_info->signing_state = SMB_SIGNING_ENGINE_ON; + sign_info->next_seq_num = 2; return true; } diff --git a/source4/libcli/resolve/nbtlist.c b/source4/libcli/resolve/nbtlist.c index 8f085c5404..7dafd130f8 100644 --- a/source4/libcli/resolve/nbtlist.c +++ b/source4/libcli/resolve/nbtlist.c @@ -28,7 +28,7 @@ #include "system/network.h" #include "lib/socket/netif.h" #include "librpc/gen_ndr/ndr_nbt.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "param/param.h" struct nbtlist_state { @@ -46,7 +46,7 @@ struct nbtlist_state { */ static void nbtlist_handler(struct nbt_name_request *req) { - struct composite_context *c = talloc_get_type(req->async.private, + struct composite_context *c = talloc_get_type(req->async.private_data, struct composite_context); struct nbtlist_state *state = talloc_get_type(c->private_data, struct nbtlist_state); struct nbt_name_query *q; @@ -169,7 +169,7 @@ struct composite_context *resolve_name_nbtlist_send(TALLOC_CTX *mem_ctx, if (composite_nomem(state->queries[i], c)) return c; state->queries[i]->async.fn = nbtlist_handler; - state->queries[i]->async.private = c; + state->queries[i]->async.private_data = c; } return c; diff --git a/source4/libcli/resolve/resolve.h b/source4/libcli/resolve/resolve.h index 79b91dc836..22de146c99 100644 --- a/source4/libcli/resolve/resolve.h +++ b/source4/libcli/resolve/resolve.h @@ -22,7 +22,7 @@ #ifndef __RESOLVE_H__ #define __RESOLVE_H__ -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" typedef struct composite_context *(*resolve_name_send_fn)(TALLOC_CTX *mem_ctx, struct event_context *, void *privdata, struct nbt_name *); typedef NTSTATUS (*resolve_name_recv_fn)(struct composite_context *, TALLOC_CTX *, const char **); #include "libcli/resolve/proto.h" diff --git a/source4/libcli/resolve/wins.c b/source4/libcli/resolve/wins.c index 3ec180f332..ebce9b98bd 100644 --- a/source4/libcli/resolve/wins.c +++ b/source4/libcli/resolve/wins.c @@ -20,7 +20,7 @@ */ #include "includes.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "libcli/resolve/resolve.h" #include "param/param.h" #include "lib/socket/netif.h" diff --git a/source4/libcli/smb_composite/sesssetup.c b/source4/libcli/smb_composite/sesssetup.c index 11ac37e257..92b49dc3d4 100644 --- a/source4/libcli/smb_composite/sesssetup.c +++ b/source4/libcli/smb_composite/sesssetup.c @@ -35,6 +35,7 @@ struct sesssetup_state { union smb_sesssetup setup; + NTSTATUS remote_status; NTSTATUS gensec_status; struct smb_composite_sesssetup *io; struct smbcli_request *req; @@ -85,8 +86,15 @@ static void request_handler(struct smbcli_request *req) DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB null_data_blob = data_blob(NULL, 0); NTSTATUS session_key_err, nt_status; + struct smbcli_request *check_req = NULL; - c->status = smb_raw_sesssetup_recv(req, state, &state->setup); + if (req->sign_caller_checks) { + req->do_not_free = true; + check_req = req; + } + + state->remote_status = smb_raw_sesssetup_recv(req, state, &state->setup); + c->status = state->remote_status; state->req = NULL; switch (state->setup.old.level) { @@ -102,6 +110,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -120,6 +129,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -138,6 +148,7 @@ static void request_handler(struct smbcli_request *req) state->io, &state->req); if (NT_STATUS_IS_OK(nt_status)) { + talloc_free(check_req); c->status = nt_status; composite_continue_smb(c, state->req, request_handler, c); return; @@ -169,12 +180,16 @@ static void request_handler(struct smbcli_request *req) state->setup.spnego.in.secblob = data_blob(NULL, 0); } - /* we need to do another round of session setup. We keep going until both sides - are happy */ - session_key_err = gensec_session_key(session->gensec, &session_key); - if (NT_STATUS_IS_OK(session_key_err)) { - set_user_session_key(session, &session_key); - smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); + if (NT_STATUS_IS_OK(state->remote_status)) { + if (state->setup.spnego.in.secblob.length) { + c->status = NT_STATUS_INTERNAL_ERROR; + break; + } + session_key_err = gensec_session_key(session->gensec, &session_key); + if (NT_STATUS_IS_OK(session_key_err)) { + set_user_session_key(session, &session_key); + smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); + } } if (state->setup.spnego.in.secblob.length) { @@ -186,6 +201,9 @@ static void request_handler(struct smbcli_request *req) session->vuid = state->io->out.vuid; state->req = smb_raw_sesssetup_send(session, &state->setup); session->vuid = vuid; + if (state->req) { + state->req->sign_caller_checks = true; + } composite_continue_smb(c, state->req, request_handler, c); return; } @@ -196,6 +214,15 @@ static void request_handler(struct smbcli_request *req) break; } + if (check_req) { + check_req->sign_caller_checks = false; + if (!smbcli_request_check_sign_mac(check_req)) { + c->status = NT_STATUS_ACCESS_DENIED; + } + talloc_free(check_req); + check_req = NULL; + } + /* enforce the local signing required flag */ if (NT_STATUS_IS_OK(c->status) && !cli_credentials_is_anonymous(state->io->in.credentials)) { if (!session->transport->negotiate.sign_info.doing_signing @@ -222,11 +249,14 @@ static NTSTATUS session_setup_nt1(struct composite_context *c, struct smb_composite_sesssetup *io, struct smbcli_request **req) { - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_INTERNAL_ERROR; struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); DATA_BLOB names_blob = NTLMv2_generate_names_blob(state, lp_iconv_convenience(global_loadparm), session->transport->socket->hostname, lp_workgroup(global_loadparm)); - DATA_BLOB session_key; + DATA_BLOB session_key = data_blob(NULL, 0); int flags = CLI_CRED_NTLM_AUTH; + + smbcli_temp_set_signing(session->transport); + if (session->options.lanman_auth) { flags |= CLI_CRED_LANMAN_AUTH; } @@ -258,12 +288,6 @@ static NTSTATUS session_setup_nt1(struct composite_context *c, &state->setup.nt1.in.password2, NULL, &session_key); NT_STATUS_NOT_OK_RETURN(nt_status); - - smbcli_transport_simple_set_signing(session->transport, session_key, - state->setup.nt1.in.password2); - set_user_session_key(session, &session_key); - - data_blob_free(&session_key); } else if (session->options.plaintext_auth) { const char *password = cli_credentials_get_password(io->in.credentials); state->setup.nt1.in.password1 = data_blob_talloc(state, password, strlen(password)); @@ -277,6 +301,15 @@ static NTSTATUS session_setup_nt1(struct composite_context *c, if (!*req) { return NT_STATUS_NO_MEMORY; } + + if (NT_STATUS_IS_OK(nt_status)) { + smbcli_transport_simple_set_signing(session->transport, session_key, + state->setup.nt1.in.password2); + set_user_session_key(session, &session_key); + + data_blob_free(&session_key); + } + return (*req)->status; } @@ -350,9 +383,7 @@ static NTSTATUS session_setup_spnego(struct composite_context *c, struct smbcli_request **req) { struct sesssetup_state *state = talloc_get_type(c->private_data, struct sesssetup_state); - NTSTATUS status, session_key_err; - DATA_BLOB session_key = data_blob(NULL, 0); - DATA_BLOB null_data_blob = data_blob(NULL, 0); + NTSTATUS status; const char *chosen_oid = NULL; state->setup.spnego.level = RAW_SESSSETUP_SPNEGO; @@ -440,15 +471,18 @@ static NTSTATUS session_setup_spnego(struct composite_context *c, } state->gensec_status = status; - session_key_err = gensec_session_key(session->gensec, &session_key); - if (NT_STATUS_IS_OK(session_key_err)) { - smbcli_transport_simple_set_signing(session->transport, session_key, null_data_blob); - } - *req = smb_raw_sesssetup_send(session, &state->setup); if (!*req) { return NT_STATUS_NO_MEMORY; } + + /* + * we need to check the signature ourself + * as the session key might be the acceptor subkey + * which comes within the response itself + */ + (*req)->sign_caller_checks = true; + return (*req)->status; } diff --git a/source4/librpc/config.mk b/source4/librpc/config.mk index 05848bc3a4..cf41f9884a 100644 --- a/source4/librpc/config.mk +++ b/source4/librpc/config.mk @@ -743,7 +743,6 @@ python_dcerpc_security_OBJ_FILES = $(gen_ndrsrcdir)/py_security.o $(IDL_HEADER_FILES) $(IDL_NDR_PARSE_H_FILES) $(IDL_NDR_PARSE_C_FILES) \ $(IDL_NDR_CLIENT_C_FILES) $(IDL_NDR_CLIENT_H_FILES) \ $(IDL_NDR_SERVER_C_FILES) $(IDL_SWIG_FILES) \ - $(IDL_NDR_EJS_C_FILES) $(IDL_NDR_EJS_H_FILES) \ $(IDL_NDR_PY_C_FILES) $(IDL_NDR_PY_H_FILES): idl idl_full:: $(pidldir)/lib/Parse/Pidl/IDL.pm $(pidldir)/lib/Parse/Pidl/Expr.pm diff --git a/source4/librpc/idl/nbt.idl b/source4/librpc/idl/nbt.idl index 63be489e0d..fad3a39e30 100644 --- a/source4/librpc/idl/nbt.idl +++ b/source4/librpc/idl/nbt.idl @@ -10,7 +10,7 @@ import "misc.idl", "security.idl", "svcctl.idl", "samr.idl"; [ - helper("libcli/netlogon.h", "libcli/nbt/libnbt.h") + helper("libcli/netlogon.h", "../libcli/nbt/libnbt.h") ] interface nbt { diff --git a/source4/main.mk b/source4/main.mk index ddeb4baf2e..0edfa1c144 100644 --- a/source4/main.mk +++ b/source4/main.mk @@ -18,7 +18,6 @@ mkinclude lib/events/config.mk mkinclude lib/cmdline/config.mk mkinclude ../lib/socket_wrapper/config.mk mkinclude ../lib/nss_wrapper/config.mk -mkinclude lib/appweb/config.mk mkinclude lib/stream/config.mk mkinclude lib/util/config.mk mkinclude lib/tdr/config.mk @@ -47,6 +46,5 @@ mkinclude torture/config.mk mkinclude librpc/config.mk mkinclude client/config.mk mkinclude libcli/config.mk -mkinclude scripting/ejs/config.mk mkinclude scripting/python/config.mk mkinclude kdc/config.mk diff --git a/source4/nbt_server/defense.c b/source4/nbt_server/defense.c index 2d7a126f5b..08eebe0c55 100644 --- a/source4/nbt_server/defense.c +++ b/source4/nbt_server/defense.c @@ -38,7 +38,7 @@ void nbtd_request_defense(struct nbt_name_socket *nbtsock, { struct nbtd_iface_name *iname; struct nbt_name *name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); /* diff --git a/source4/nbt_server/interfaces.c b/source4/nbt_server/interfaces.c index e59475051b..76bc145903 100644 --- a/source4/nbt_server/interfaces.c +++ b/source4/nbt_server/interfaces.c @@ -38,7 +38,7 @@ static void nbtd_request_handler(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; diff --git a/source4/nbt_server/nbt_server.h b/source4/nbt_server/nbt_server.h index 688b6a7a7d..00d8f31b2b 100644 --- a/source4/nbt_server/nbt_server.h +++ b/source4/nbt_server/nbt_server.h @@ -19,7 +19,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. */ -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "libcli/wrepl/winsrepl.h" #include "libcli/dgram/libdgram.h" #include "librpc/gen_ndr/irpc.h" diff --git a/source4/nbt_server/nodestatus.c b/source4/nbt_server/nodestatus.c index a7bf67ad51..a5f1426f37 100644 --- a/source4/nbt_server/nodestatus.c +++ b/source4/nbt_server/nodestatus.c @@ -104,7 +104,7 @@ void nbtd_query_status(struct nbt_name_socket *nbtsock, { struct nbt_name *name; struct nbtd_iface_name *iname; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); NBTD_ASSERT_PACKET(packet, src, packet->qdcount == 1); diff --git a/source4/nbt_server/packet.c b/source4/nbt_server/packet.c index 07a309b633..ff4e94fef9 100644 --- a/source4/nbt_server/packet.c +++ b/source4/nbt_server/packet.c @@ -47,7 +47,7 @@ bool nbtd_self_packet_and_bcast(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, const struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); /* if its not a broadcast then its not considered a self packet */ @@ -74,7 +74,7 @@ bool nbtd_self_packet(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, const struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; @@ -106,7 +106,7 @@ void nbtd_name_query_reply(struct nbt_name_socket *nbtsock, { struct nbt_name_packet *packet; size_t num_addresses = str_list_length(addresses); - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; int i; @@ -168,7 +168,7 @@ void nbtd_negative_name_query_reply(struct nbt_name_socket *nbtsock, { struct nbt_name_packet *packet; struct nbt_name *name = &request_packet->questions[0].name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; @@ -212,7 +212,7 @@ void nbtd_name_registration_reply(struct nbt_name_socket *nbtsock, { struct nbt_name_packet *packet; struct nbt_name *name = &request_packet->questions[0].name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; @@ -260,7 +260,7 @@ void nbtd_name_release_reply(struct nbt_name_socket *nbtsock, { struct nbt_name_packet *packet; struct nbt_name *name = &request_packet->questions[0].name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; @@ -306,7 +306,7 @@ void nbtd_wack_reply(struct nbt_name_socket *nbtsock, { struct nbt_name_packet *packet; struct nbt_name *name = &request_packet->questions[0].name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct nbtd_server *nbtsrv = iface->nbtsrv; diff --git a/source4/nbt_server/query.c b/source4/nbt_server/query.c index dfd742db5a..a8809e84a2 100644 --- a/source4/nbt_server/query.c +++ b/source4/nbt_server/query.c @@ -38,7 +38,7 @@ void nbtd_request_query(struct nbt_name_socket *nbtsock, { struct nbtd_iface_name *iname; struct nbt_name *name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); /* see if its a node status query */ diff --git a/source4/nbt_server/register.c b/source4/nbt_server/register.c index a17d503190..ebdb4dc0f8 100644 --- a/source4/nbt_server/register.c +++ b/source4/nbt_server/register.c @@ -38,7 +38,7 @@ static void nbtd_start_refresh_timer(struct nbtd_iface_name *iname); */ static void refresh_completion_handler(struct nbt_name_request *req) { - struct nbtd_iface_name *iname = talloc_get_type(req->async.private, + struct nbtd_iface_name *iname = talloc_get_type(req->async.private_data, struct nbtd_iface_name); NTSTATUS status; struct nbt_name_refresh io; @@ -108,7 +108,7 @@ static void name_refresh_handler(struct event_context *ev, struct timed_event *t if (req == NULL) return; req->async.fn = refresh_completion_handler; - req->async.private = iname; + req->async.private_data = iname; } diff --git a/source4/nbt_server/wins/wins_dns_proxy.c b/source4/nbt_server/wins/wins_dns_proxy.c index 3322ad55fd..cd605907a8 100644 --- a/source4/nbt_server/wins/wins_dns_proxy.c +++ b/source4/nbt_server/wins/wins_dns_proxy.c @@ -68,7 +68,7 @@ void nbtd_wins_dns_proxy_query(struct nbt_name_socket *nbtsock, struct socket_address *src) { struct nbt_name *name = &packet->questions[0].name; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_dns_proxy_state *s; struct composite_context *creq; diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c index f8901ce09d..399530b4cf 100644 --- a/source4/nbt_server/wins/winsserver.c +++ b/source4/nbt_server/wins/winsserver.c @@ -68,7 +68,7 @@ static uint8_t wins_register_new(struct nbt_name_socket *nbtsock, const struct socket_address *src, enum wrepl_name_type type) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; @@ -119,7 +119,7 @@ static uint8_t wins_update_ttl(struct nbt_name_socket *nbtsock, struct winsdb_addr *winsdb_addr, const struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; uint32_t ttl = wins_server_ttl(winssrv, packet->additional[0].ttl); @@ -158,7 +158,7 @@ static uint8_t wins_sgroup_merge(struct nbt_name_socket *nbtsock, const char *address, const struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; uint32_t ttl = wins_server_ttl(winssrv, packet->additional[0].ttl); @@ -357,7 +357,7 @@ static void wins_register_wack(struct nbt_name_socket *nbtsock, struct socket_address *src, enum wrepl_name_type new_type) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct wack_state *s; @@ -415,7 +415,7 @@ static void nbtd_winsserver_register(struct nbt_name_socket *nbtsock, struct socket_address *src) { NTSTATUS status; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; @@ -671,7 +671,7 @@ static void nbtd_winsserver_query(struct loadparm_context *lp_ctx, struct socket_address *src) { NTSTATUS status; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; @@ -813,7 +813,7 @@ static void nbtd_winsserver_release(struct nbt_name_socket *nbtsock, struct socket_address *src) { NTSTATUS status; - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; struct nbt_name *name = &packet->questions[0].name; @@ -928,7 +928,7 @@ void nbtd_winsserver_request(struct nbt_name_socket *nbtsock, struct nbt_name_packet *packet, struct socket_address *src) { - struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private, + struct nbtd_interface *iface = talloc_get_type(nbtsock->incoming.private_data, struct nbtd_interface); struct wins_server *winssrv = iface->nbtsrv->winssrv; if ((packet->operation & NBT_FLAG_BROADCAST) || winssrv == NULL) { diff --git a/source4/nbt_server/wins/winswack.c b/source4/nbt_server/wins/winswack.c index 43d2747ae7..7e0c73a810 100644 --- a/source4/nbt_server/wins/winswack.c +++ b/source4/nbt_server/wins/winswack.c @@ -37,7 +37,7 @@ struct wins_challenge_state { static void wins_challenge_handler(struct nbt_name_request *req) { - struct composite_context *ctx = talloc_get_type(req->async.private, struct composite_context); + struct composite_context *ctx = talloc_get_type(req->async.private_data, struct composite_context); struct wins_challenge_state *state = talloc_get_type(ctx->private_data, struct wins_challenge_state); ctx->status = nbt_name_query_recv(req, state, &state->query); @@ -123,7 +123,7 @@ struct composite_context *wins_challenge_send(TALLOC_CTX *mem_ctx, struct wins_c if (req == NULL) goto failed; req->async.fn = wins_challenge_handler; - req->async.private = result; + req->async.private_data = result; return result; failed: @@ -151,7 +151,7 @@ struct wins_release_demand_state { static void wins_release_demand_handler(struct nbt_name_request *req) { - struct composite_context *ctx = talloc_get_type(req->async.private, struct composite_context); + struct composite_context *ctx = talloc_get_type(req->async.private_data, struct composite_context); struct wins_release_demand_state *state = talloc_get_type(ctx->private_data, struct wins_release_demand_state); ctx->status = nbt_name_release_recv(req, state, &state->release); @@ -240,7 +240,7 @@ static struct composite_context *wins_release_demand_send(TALLOC_CTX *mem_ctx, s if (req == NULL) goto failed; req->async.fn = wins_release_demand_handler; - req->async.private = result; + req->async.private_data = result; return result; failed: diff --git a/source4/nsswitch/tests/test_wbinfo.sh b/source4/nsswitch/tests/test_wbinfo.sh index dfd633b656..a67fac9394 100755 --- a/source4/nsswitch/tests/test_wbinfo.sh +++ b/source4/nsswitch/tests/test_wbinfo.sh @@ -62,7 +62,7 @@ admin_sid=`$wbinfo -n "$DOMAIN/$USERNAME" | cut -d " " -f1` echo "$DOMAIN/$USERNAME resolved to $admin_sid" testit "wbinfo -s $admin_sid against $TARGET" $wbinfo -s $admin_sid || failed=`expr $failed + 1` -admin_name=`wbinfo -s $admin_sid | cut -d " " -f1| tr a-z A-Z` +admin_name=`$wbinfo -s $admin_sid | cut -d " " -f1| tr a-z A-Z` echo "$admin_sid resolved to $admin_name" tested_name=`echo $DOMAIN/$USERNAME | tr a-z A-Z` @@ -100,7 +100,7 @@ else echo "success: wbinfo -U check for sane mapping" fi -admin_uid=`wbinfo -U $admin_sid` +admin_uid=`$wbinfo -U $admin_sid` testit "wbinfo -G against $TARGET" $wbinfo -G 30000 || failed=`expr $failed + 1` @@ -149,7 +149,7 @@ testit "wbinfo --all-domains against $TARGET" $wbinfo --all-domains || failed=`e testit "wbinfo --own-domain against $TARGET" $wbinfo --own-domain || failed=`expr $failed + 1` echo "test: wbinfo --own-domain against $TARGET check output" -own_domain=`wbinfo --own-domain` +own_domain=`$wbinfo --own-domain` if test x$own_domain = x$DOMAIN; then echo "success: wbinfo --own-domain against $TARGET check output" else diff --git a/source4/ntp_signd/ntp_signd.c b/source4/ntp_signd/ntp_signd.c index 546743e4e6..8bcf258e5e 100644 --- a/source4/ntp_signd/ntp_signd.c +++ b/source4/ntp_signd/ntp_signd.c @@ -349,7 +349,7 @@ static void ntp_signd_task_init(struct task_server *task) /* within the ntp_signd task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) { DEBUG(0,("Can't find 'single' process model_ops\n")); return; diff --git a/source4/param/loadparm.c b/source4/param/loadparm.c index e63a7aa8a1..15edbd1f89 100644 --- a/source4/param/loadparm.c +++ b/source4/param/loadparm.c @@ -97,8 +97,6 @@ struct loadparm_global char *szWINS_CONFIG_URL; char *szWINS_URL; char *szPrivateDir; - const char **jsInclude; - char *jsonrpcServicesDir; const char **szPasswordServers; char *szSocketOptions; char *szRealm; @@ -469,7 +467,6 @@ static struct parm_struct parm_table[] = { {"lock directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szLockDir), NULL, NULL}, {"modules dir", P_STRING, P_GLOBAL, GLOBAL_VAR(szModulesDir), NULL, NULL}, {"pid directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szPidDir), NULL, NULL}, - {"js include", P_LIST, P_GLOBAL, GLOBAL_VAR(jsInclude), NULL, NULL}, {"setup directory", P_STRING, P_GLOBAL, GLOBAL_VAR(szSetupDir), NULL, NULL}, {"socket address", P_STRING, P_GLOBAL, GLOBAL_VAR(szSocketAddress), NULL, NULL}, @@ -702,7 +699,6 @@ _PUBLIC_ FN_GLOBAL_INTEGER(lp_cli_minprotocol, cli_minprotocol) _PUBLIC_ FN_GLOBAL_INTEGER(lp_security, security) _PUBLIC_ FN_GLOBAL_BOOL(lp_paranoid_server_security, paranoid_server_security) _PUBLIC_ FN_GLOBAL_INTEGER(lp_announce_as, announce_as) -_PUBLIC_ FN_GLOBAL_LIST(lp_js_include, jsInclude) const char *lp_servicename(const struct loadparm_service *service) { return lp_string((const char *)service->szService); @@ -2413,7 +2409,6 @@ struct loadparm_context *loadparm_init(TALLOC_CTX *mem_ctx) lp_do_global_parameter(lp_ctx, "tls keyfile", "tls/key.pem"); lp_do_global_parameter(lp_ctx, "tls certfile", "tls/cert.pem"); lp_do_global_parameter(lp_ctx, "tls cafile", "tls/ca.pem"); - lp_do_global_parameter_var(lp_ctx, "js include", "%s", dyn_JSDIR); lp_do_global_parameter_var(lp_ctx, "setup directory", "%s", dyn_SETUPDIR); diff --git a/source4/rpc_server/netlogon/dcerpc_netlogon.c b/source4/rpc_server/netlogon/dcerpc_netlogon.c index 6f4287f9d8..cceb2a62ac 100644 --- a/source4/rpc_server/netlogon/dcerpc_netlogon.c +++ b/source4/rpc_server/netlogon/dcerpc_netlogon.c @@ -337,7 +337,6 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal struct ldb_context *sam_ctx; NTSTATUS nt_status; char new_pass[512]; - uint32_t new_pass_len; bool ret; struct samr_CryptPassword password_buf; @@ -358,7 +357,7 @@ static NTSTATUS dcesrv_netr_ServerPasswordSet2(struct dcesrv_call_state *dce_cal creds_arcfour_crypt(creds, password_buf.data, 516); ret = decode_pw_buffer(password_buf.data, new_pass, sizeof(new_pass), - &new_pass_len, STR_UNICODE); + STR_UNICODE); if (!ret) { DEBUG(3,("netr_ServerPasswordSet2: failed to decode password buffer\n")); return NT_STATUS_ACCESS_DENIED; diff --git a/source4/rpc_server/samr/samr_password.c b/source4/rpc_server/samr/samr_password.c index b78a9ceaa7..5b8e92583b 100644 --- a/source4/rpc_server/samr/samr_password.c +++ b/source4/rpc_server/samr/samr_password.c @@ -243,7 +243,7 @@ NTSTATUS dcesrv_samr_OemChangePasswordUser2(struct dcesrv_call_state *dce_call, data_blob_free(&lm_pwd_blob); if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass), - &new_pass_len, STR_ASCII)) { + STR_ASCII)) { ldb_transaction_cancel(sam_ctx); DEBUG(3,("samr: failed to decode password buffer\n")); return NT_STATUS_WRONG_PASSWORD; @@ -321,7 +321,6 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, { NTSTATUS status; char new_pass[512]; - uint32_t new_pass_len; struct ldb_context *sam_ctx = NULL; struct ldb_dn *user_dn; int ret; @@ -386,7 +385,7 @@ NTSTATUS dcesrv_samr_ChangePasswordUser3(struct dcesrv_call_state *dce_call, data_blob_free(&nt_pwd_blob); if (!decode_pw_buffer(r->in.nt_password->data, new_pass, sizeof(new_pass), - &new_pass_len, STR_UNICODE)) { + STR_UNICODE)) { DEBUG(3,("samr: failed to decode password buffer\n")); status = NT_STATUS_WRONG_PASSWORD; goto failed; @@ -519,7 +518,6 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call, { NTSTATUS nt_status; char new_pass[512]; - uint32_t new_pass_len; DATA_BLOB session_key = data_blob(NULL, 0); nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key); @@ -530,7 +528,7 @@ NTSTATUS samr_set_password(struct dcesrv_call_state *dce_call, arcfour_crypt_blob(pwbuf->data, 516, &session_key); if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass), - &new_pass_len, STR_UNICODE)) { + STR_UNICODE)) { DEBUG(3,("samr: failed to decode password buffer\n")); return NT_STATUS_WRONG_PASSWORD; } @@ -583,7 +581,7 @@ NTSTATUS samr_set_password_ex(struct dcesrv_call_state *dce_call, arcfour_crypt_blob(pwbuf->data, 516, &co_session_key); if (!decode_pw_buffer(pwbuf->data, new_pass, sizeof(new_pass), - &new_pass_len, STR_UNICODE)) { + STR_UNICODE)) { DEBUG(3,("samr: failed to decode password buffer\n")); return NT_STATUS_WRONG_PASSWORD; } diff --git a/source4/samba4-quick b/source4/samba4-quick index 3627a87bbe..7bea619f18 100644 --- a/source4/samba4-quick +++ b/source4/samba4-quick @@ -35,3 +35,4 @@ rpc.altercontext rpc.join rpc.handles rpc.echo +smb.signing diff --git a/source4/samba4-skip b/source4/samba4-skip index b1313adea0..5fa40ee706 100644 --- a/source4/samba4-skip +++ b/source4/samba4-skip @@ -58,6 +58,5 @@ samba4.ntvfs.cifs.raw. ^samba4.net.domopen.*$ # Hangs for some reason ^samba4.net.api.become.dc.*$ # Fails nss.test # Fails -samba4.samba3sam.python # Conversion from EJS not yet finished raw.offline # Samba 4 doesn't have much offline support yet winreg* #Does not authenticate against the target server diff --git a/source4/script/find_unused_makefilevars.pl b/source4/script/find_unused_makefilevars.pl index 1bed1228ec..23fc36ef6a 100755 --- a/source4/script/find_unused_makefilevars.pl +++ b/source4/script/find_unused_makefilevars.pl @@ -13,17 +13,26 @@ my %defines; # First, make a list of defines in configure $in = shift; -open(IN, $in); -while(<IN>) { - my $line = $_; - while($line =~ /^\b([a-zA-Z0-9_][a-zA-Z0-9_]*)\b[ \t]*=.*/sgm) { - $defines{$1} = 1; - } - while($line =~ /\$\(([a-zA-Z0-9_][a-zA-Z0-9_]*)\)/sgm) { - $references{$1} = 1; +sub process_file($) +{ + my ($fn) = @_; + open(IN, $fn); + while(<IN>) { + my $line = $_; + while($line =~ /^\b([a-zA-Z0-9_][a-zA-Z0-9_]*)\b[ \t]*=.*/sgm) { + $defines{$1} = 1; + } + while($line =~ /\$\(([a-zA-Z0-9_][a-zA-Z0-9_]*)\)/sgm) { + $references{$1} = 1; + } + while ($line =~ /^include (.*)/sgm) { + process_file($1); + } } + close IN; } -close IN; + +process_file($in); print "##### DEFINED BUT UNUSED: #####\n"; foreach(%defines) { diff --git a/source4/script/installmisc.sh b/source4/script/installmisc.sh index 5f7e11f083..eb347307ba 100755 --- a/source4/script/installmisc.sh +++ b/source4/script/installmisc.sh @@ -2,16 +2,11 @@ # install miscellaneous files SRCDIR="$1" -JSDIR="$2" -SETUPDIR="$3" -BINDIR="$4" +SETUPDIR="$2" +BINDIR="$3" cd $SRCDIR || exit 1 -echo "Installing js libs" -mkdir -p $JSDIR || exit 1 -cp scripting/libjs/*.js $JSDIR || exit 1 - echo "Installing setup templates" mkdir -p $SETUPDIR || exit 1 cp setup/schema-map-* $SETUPDIR || exit 1 diff --git a/source4/script/installmodules.sh b/source4/script/installmodules.sh deleted file mode 100755 index fb0ad90c14..0000000000 --- a/source4/script/installmodules.sh +++ /dev/null @@ -1,33 +0,0 @@ -#!/bin/sh - -INSTALLPERMS=$1 -LIBDIR=$2 -shift -shift -shift - -if [ ! -d $LIBDIR ]; then -mkdir $LIBDIR -if [ ! -d $LIBDIR ]; then - echo Failed to make directory $LIBDIR - exit 1 -fi -fi - -for p in $*; do - p2=`basename $p` - echo Installing $p as $LIBDIR/$p2 - cp -f $p $LIBDIR/ - chmod $INSTALLPERMS $LIBDIR/$p2 -done - - -cat << EOF -====================================================================== -The modules are installed. You may uninstall the modules using the -command "make uninstallmodules" or "make uninstall" to uninstall -binaries, man pages, shell scripts and modules. -====================================================================== -EOF - -exit 0 diff --git a/source4/script/installscripts.sh b/source4/script/installscripts.sh deleted file mode 100755 index bff5423e7c..0000000000 --- a/source4/script/installscripts.sh +++ /dev/null @@ -1,47 +0,0 @@ -#!/bin/sh -# this script courtesy of James_K._Foote.PARC@xerox.com -# 5 July 96 Dan.Shearer@UniSA.Edu.Au Don't hardcode script names, get from Make - -INSTALLPERMS=$1 -BINDIR=$2 - -shift -shift - -echo Installing scripts in $BINDIR - -for d in $BINDIR; do - if [ ! -d $d ]; then - mkdir $d - if [ ! -d $d ]; then - echo Failed to make directory $d - echo Have you run installbin first? - exit 1 - fi - fi -done - -for p in $*; do - p2=`basename $p` - echo Installing $BINDIR/$p2 - if [ -f $BINDIR/$p2 ]; then - rm -f $BINDIR/$p2.old - mv $BINDIR/$p2 $BINDIR/$p2.old - fi - cp $p $BINDIR/ - chmod $INSTALLPERMS $BINDIR/$p2 - if [ ! -f $BINDIR/$p2 ]; then - echo Cannot copy $p2... does $USER have privileges? - fi -done - -cat << EOF -====================================================================== -The scripts have been installed. You may uninstall them using -the command "make uninstallscripts" or "make install" to install binaries, -man pages and shell scripts. You may recover the previous version (if any -by "make revert". -====================================================================== -EOF - -exit 0 diff --git a/source4/script/uninstallmodules.sh b/source4/script/uninstallmodules.sh deleted file mode 100755 index 30582a39fa..0000000000 --- a/source4/script/uninstallmodules.sh +++ /dev/null @@ -1,37 +0,0 @@ -#!/bin/sh -#4 July 96 Dan.Shearer@UniSA.edu.au - -INSTALLPERMS=$1 -BASEDIR=$2 -LIBDIR=$3 -shift -shift -shift - -if [ ! -d $LIBDIR ]; then - echo Directory $LIBDIR does not exist! - echo Do a "make installmodules" or "make install" first. - exit 1 -fi - -for p in $*; do - p2=`basename $p` - if [ -f $LIBDIR/$p2 ]; then - echo Removing $LIBDIR/$p2 - rm -f $LIBDIR/$p2 - if [ -f $LIBDIR/$p2 ]; then - echo Cannot remove $LIBDIR/$p2 ... does $USER have privileges? - fi - fi -done - - -cat << EOF -====================================================================== -The modules have been uninstalled. You may restore the modules using -the command "make installmodules" or "make install" to install -binaries, modules, man pages and shell scripts. -====================================================================== -EOF - -exit 0 diff --git a/source4/script/uninstallscripts.sh b/source4/script/uninstallscripts.sh deleted file mode 100755 index 13104acedd..0000000000 --- a/source4/script/uninstallscripts.sh +++ /dev/null @@ -1,36 +0,0 @@ -#!/bin/sh -# 5 July 96 Dan.Shearer@UniSA.Edu.Au - almost identical to uninstallbin.sh - -INSTALLPERMS=$1 -BINDIR=$2 - -shift -shift - -if [ ! -d $BINDIR ]; then - echo Directory $BINDIR does not exist! - echo Do a "make installscripts" or "make install" first. - exit 1 -fi - -for p in $*; do - p2=`basename $p` - if [ -f $BINDIR/$p2 ]; then - echo Removing $BINDIR/$p2 - rm -f $BINDIR/$p2 - if [ -f $BINDIR/$p2 ]; then - echo Cannot remove $BINDIR/$p2 ... does $USER have privileges? - fi - fi -done - -cat << EOF -====================================================================== -The scripts have been uninstalled. You may reinstall them using -the command "make installscripts" or "make install" to install binaries, -man pages and shell scripts. You may recover a previous version (if any -with "make revert". -====================================================================== -EOF - -exit 0 diff --git a/source4/scripting/bin/autoidl.py b/source4/scripting/bin/autoidl index eed4ba3a80..eed4ba3a80 100755 --- a/source4/scripting/bin/autoidl.py +++ b/source4/scripting/bin/autoidl diff --git a/source4/scripting/bin/epdump.py b/source4/scripting/bin/epdump index 15dee33774..15dee33774 100644..100755 --- a/source4/scripting/bin/epdump.py +++ b/source4/scripting/bin/epdump diff --git a/source4/scripting/bin/minschema.py b/source4/scripting/bin/minschema index 111557126d..111557126d 100755 --- a/source4/scripting/bin/minschema.py +++ b/source4/scripting/bin/minschema diff --git a/source4/scripting/bin/smbstatus b/source4/scripting/bin/smbstatus index bbd0e84826..a9265ead6a 100755 --- a/source4/scripting/bin/smbstatus +++ b/source4/scripting/bin/smbstatus @@ -22,7 +22,7 @@ def show_sessions(conn): sessions = conn.smbsrv_information(irpc.SMBSRV_INFO_SESSIONS).next() print "User Client Connected at" - print "-------------------------------------------------------------------------------" + print "-" * 79 for session in sessions: fulluser = "%s/%s" % (session.account_name, session.domain_name) print "%-30s %16s %s" % (fulluser, session.client_ip, sys.httptime(session.connect_time)) @@ -33,7 +33,7 @@ def show_tcons(open_connection): conn = open_connection("smb_server") tcons = conn.smbsrv_information(irpc.SMBSRV_INFO_TCONS).next() print "Share Client Connected at" - print "-------------------------------------------------------------------------------" + print "-" * 79 for tcon in tcons: print "%-30s %16s %s" % (tcon.share_name, tcon.client_ip, sys.httptime(tcon.connect_time)) @@ -76,7 +76,7 @@ else: try: conn = open_connection("smb_server") except RuntimeError, (num, msg): - if msg == 'NT_STATUS_OBJECT_NAME_NOT_FOUND': + if msg == 'NT_STATUS_OBJECT_NAME_NOT_FOUND': print "No active connections" else: show_sessions(conn) diff --git a/source4/scripting/ejs/config.mk b/source4/scripting/ejs/config.mk deleted file mode 100644 index 34c0a9678e..0000000000 --- a/source4/scripting/ejs/config.mk +++ /dev/null @@ -1,63 +0,0 @@ -[MODULE::smbcalls_config] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = smbcalls -INIT_FUNCTION = smb_setup_ejs_config - -smbcalls_config_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_config.o - -[MODULE::smbcalls_ldb] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = smbcalls -INIT_FUNCTION = smb_setup_ejs_ldb -PRIVATE_DEPENDENCIES = LIBLDB SAMDB LIBNDR - -smbcalls_ldb_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_ldb.o - -[MODULE::smbcalls_auth] -OUTPUT_TYPE = MERGED_OBJ -SUBSYSTEM = smbcalls -INIT_FUNCTION = smb_setup_ejs_auth -PRIVATE_DEPENDENCIES = service_auth - -smbcalls_auth_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_auth.o - -smbcalls_auth_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_auth.o - -[MODULE::smbcalls_string] -SUBSYSTEM = smbcalls -OUTPUT_TYPE = MERGED_OBJ -INIT_FUNCTION = smb_setup_ejs_string - -smbcalls_string_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_string.o - -[MODULE::smbcalls_sys] -SUBSYSTEM = smbcalls -OUTPUT_TYPE = MERGED_OBJ -INIT_FUNCTION = smb_setup_ejs_system - -smbcalls_sys_OBJ_FILES = $(ejsscriptsrcdir)/smbcalls_sys.o - -[SUBSYSTEM::smbcalls] -PRIVATE_DEPENDENCIES = \ - EJS LIBSAMBA-UTIL \ - MESSAGING \ - LIBSAMBA-NET LIBCLI_SMB LIBPOPT \ - CREDENTIALS POPT_CREDENTIALS POPT_SAMBA \ - NDR_TABLE - -smbcalls_OBJ_FILES = $(addprefix $(ejsscriptsrcdir)/, \ - smbcalls.o \ - smbcalls_options.o \ - smbcalls_creds.o \ - mprutil.o) - -$(eval $(call proto_header_template,$(ejsscriptsrcdir)/proto.h,$(smbcalls_OBJ_FILES:.o=.c))) - -####################### -# Start BINARY SMBSCRIPT -[BINARY::smbscript] -PRIVATE_DEPENDENCIES = EJS LIBSAMBA-UTIL smbcalls LIBSAMBA-HOSTCONFIG -# End BINARY SMBSCRIPT -####################### - -smbscript_OBJ_FILES = $(ejsscriptsrcdir)/smbscript.o diff --git a/source4/scripting/ejs/mprutil.c b/source4/scripting/ejs/mprutil.c deleted file mode 100644 index 9143947fb8..0000000000 --- a/source4/scripting/ejs/mprutil.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - utility functions for manipulating mpr variables in ejs calls - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/ldb/include/ldb.h" -#include "scripting/ejs/smbcalls.h" - -/* - return a default mpr object -*/ -struct MprVar mprObject(const char *name) -{ - return ejsCreateObj(name && *name?name:"(NULL)", MPR_DEFAULT_HASH_SIZE); -} - -/* - return a empty mpr array -*/ -struct MprVar mprArray(const char *name) -{ - return ejsCreateArray(name && *name?name:"(NULL)", 0); -} - -/* - find a mpr component, allowing for sub objects, using the '.' convention -*/ - NTSTATUS mprGetVar(struct MprVar **v, const char *name) -{ - const char *p = strchr(name, '.'); - char *objname; - NTSTATUS status; - if (p == NULL) { - *v = mprGetProperty(*v, name, NULL); - if (*v == NULL) { - DEBUG(1,("mprGetVar unable to find '%s'\n", name)); - return NT_STATUS_INVALID_PARAMETER; - } - return NT_STATUS_OK; - } - objname = talloc_strndup(mprMemCtx(), name, p-name); - NT_STATUS_HAVE_NO_MEMORY(objname); - *v = mprGetProperty(*v, objname, NULL); - NT_STATUS_HAVE_NO_MEMORY(*v); - status = mprGetVar(v, p+1); - talloc_free(objname); - return status; -} - - -/* - set a mpr component, allowing for sub objects, using the '.' convention - destroys 'val' after setting -*/ - NTSTATUS mprSetVar(struct MprVar *v, const char *name, struct MprVar val) -{ - const char *p = strchr(name, '.'); - char *objname; - struct MprVar *v2; - NTSTATUS status; - if (p == NULL) { - v2 = mprSetProperty(v, name, &val); - if (v2 == NULL) { - DEBUG(1,("mprSetVar unable to set '%s'\n", name)); - return NT_STATUS_INVALID_PARAMETER_MIX; - } - mprDestroyVar(&val); - return NT_STATUS_OK; - } - objname = talloc_strndup(mprMemCtx(), name, p-name); - if (objname == NULL) { - return NT_STATUS_NO_MEMORY; - } - v2 = mprGetProperty(v, objname, NULL); - if (v2 == NULL) { - mprSetVar(v, objname, mprObject(objname)); - v2 = mprGetProperty(v, objname, NULL); - } - status = mprSetVar(v2, p+1, val); - talloc_free(objname); - return status; -} - - - -/* - add an indexed array element to a property -*/ - void mprAddArray(struct MprVar *var, int i, struct MprVar v) -{ - char idx[16]; - mprItoa(i, idx, sizeof(idx)); - mprSetVar(var, idx, v); -} - -/* - construct a MprVar from a list -*/ -struct MprVar mprList(const char *name, const char **list) -{ - struct MprVar var; - int i; - - var = mprArray(name); - for (i=0;list && list[i];i++) { - mprAddArray(&var, i, mprString(list[i])); - } - return var; -} - -/* - construct a MprVar from a string, using NULL if needed -*/ -struct MprVar mprString(const char *s) -{ - if (s == NULL) { - return mprCreatePtrVar(NULL); - } - return mprCreateStringVar(s, true); -} - -/* - construct a string MprVar from a lump of data -*/ -struct MprVar mprData(const uint8_t *p, size_t length) -{ - struct MprVar var; - char *s = talloc_strndup(mprMemCtx(), (const char *)p, length); - if (s == NULL) { - return mprCreateUndefinedVar(); - } - var = mprString(s); - talloc_free(s); - return var; -} - -/* - turn a ldb_message into a ejs object variable -*/ -static struct MprVar mprLdbMessage(struct ldb_context *ldb, struct ldb_message *msg) -{ - struct MprVar var; - int i; - /* we force some attributes to always be an array in the - returned structure. This makes the scripting easier, as you don't - need a special case for the single value case */ - const char *multivalued[] = { "objectClass", "memberOf", "privilege", - "member", NULL }; - - var = mprObject(ldb_dn_alloc_linearized(msg, msg->dn)); - - for (i=0;i<msg->num_elements;i++) { - struct ldb_message_element *el = &msg->elements[i]; - struct MprVar val; - const struct ldb_schema_attribute *a; - struct ldb_val v; - - a = ldb_schema_attribute_by_name(ldb, el->name); - if (a == NULL) { - goto failed; - } - - if (el->num_values == 1 && - !str_list_check_ci(multivalued, el->name)) { - if (a->syntax->ldif_write_fn(ldb, msg, &el->values[0], &v) != 0) { - goto failed; - } - /* FIXME: nasty hack, remove me when ejs will support - * arbitrary string and does not truncate on \0 */ - if (strlen((char *)v.data) != v.length) { - val = mprDataBlob(v); - } else { - val = mprData(v.data, v.length); - } - } else { - int j; - val = mprArray(el->name); - for (j=0;j<el->num_values;j++) { - if (a->syntax->ldif_write_fn(ldb, msg, - &el->values[j], &v) != 0) { - goto failed; - } - /* FIXME: nasty hack, remove me when ejs will support - * arbitrary string and does not truncate on \0 */ - if (strlen((char *)v.data) != v.length) { - mprAddArray(&val, j, mprDataBlob(v)); - } else { - mprAddArray(&val, j, mprData(v.data, v.length)); - } - } - } - mprSetVar(&var, el->name, val); - } - - /* add the dn if it is not already specified */ - if (mprGetProperty(&var, "dn", 0) == 0) { - mprSetVar(&var, "dn", mprString(ldb_dn_alloc_linearized(msg, msg->dn))); - } - - return var; -failed: - return mprCreateUndefinedVar(); -} - - -/* - build a MprVar result object for ldb operations with lots of funky properties -*/ -struct MprVar mprLdbResult(struct ldb_context *ldb, int err, struct ldb_result *result) -{ - struct MprVar ret; - struct MprVar ary; - - ret = mprObject("ldbret"); - - mprSetVar(&ret, "error", mprCreateIntegerVar(err)); - mprSetVar(&ret, "errstr", mprString(ldb_errstring(ldb))); - - ary = mprArray("ldb_message"); - if (result) { - int i; - - for (i = 0; i < result->count; i++) { - mprAddArray(&ary, i, mprLdbMessage(ldb, result->msgs[i])); - } - } - - mprSetVar(&ret, "msgs", ary); - - /* TODO: add referrals, exteded ops, and controls */ - - return ret; -} - - -/* - turn a MprVar string variable into a const char * - */ -const char *mprToString(struct MprVar *v) -{ - if (v->trigger) { - mprReadProperty(v, 0); - } - if (!mprVarIsString(v->type)) return NULL; - return v->string; -} - -/* - turn a MprVar integer variable into an int - */ -int mprToInt(struct MprVar *v) -{ - if (v->trigger) { - mprReadProperty(v, 0); - } - if (!mprVarIsNumber(v->type)) return 0; - return mprVarToNumber(v); -} - -/* - turn a MprVar object variable into a string list - this assumes the object variable consists only of strings -*/ -const char **mprToList(TALLOC_CTX *mem_ctx, struct MprVar *v) -{ - const char **list = NULL; - struct MprVar *el; - - if (v->type != MPR_TYPE_OBJECT || - v->properties == NULL) { - return NULL; - } - for (el=mprGetFirstProperty(v, MPR_ENUM_DATA); - el; - el=mprGetNextProperty(v, el, MPR_ENUM_DATA)) { - const char *s = mprToString(el); - if (s) { - list = str_list_add(list, s); - } - } - talloc_steal(mem_ctx, list); - return list; -} - - -/* - turn a MprVar object variable into a string list - this assumes the object variable is an array of strings -*/ -const char **mprToArray(TALLOC_CTX *mem_ctx, struct MprVar *v) -{ - const char **list = NULL; - struct MprVar *len; - int length, i; - - len = mprGetProperty(v, "length", NULL); - if (len == NULL) { - return NULL; - } - length = mprToInt(len); - - for (i=0;i<length;i++) { - char idx[16]; - struct MprVar *vs; - mprItoa(i, idx, sizeof(idx)); - vs = mprGetProperty(v, idx, NULL); - if (vs == NULL || vs->type != MPR_TYPE_STRING) { - talloc_free(list); - return NULL; - } - list = str_list_add(list, mprToString(vs)); - } - talloc_steal(mem_ctx, list); - return list; -} - -/* - turn a NTSTATUS into a MprVar object with lots of funky properties -*/ -struct MprVar mprNTSTATUS(NTSTATUS status) -{ - struct MprVar res; - - res = mprObject("ntstatus"); - - mprSetVar(&res, "errstr", mprString(nt_errstr(status))); - mprSetVar(&res, "v", mprCreateIntegerVar(NT_STATUS_V(status))); - mprSetVar(&res, "is_ok", mprCreateBoolVar(NT_STATUS_IS_OK(status))); - mprSetVar(&res, "is_err", mprCreateBoolVar(NT_STATUS_IS_ERR(status))); - - return res; -} - -/* - create a data-blob in a mpr variable -*/ -struct MprVar mprDataBlob(DATA_BLOB blob) -{ - struct MprVar res; - struct datablob *pblob = talloc(mprMemCtx(), struct datablob); - *pblob = data_blob_talloc(pblob, blob.data, blob.length); - - res = mprObject("DATA_BLOB"); - - mprSetVar(&res, "size", mprCreateIntegerVar(blob.length)); - mprSetPtrChild(&res, "blob", pblob); - - return res; -} - -/* - return a data blob from a mpr var created using mprDataBlob -*/ -struct datablob *mprToDataBlob(struct MprVar *v) -{ - return talloc_get_type(mprGetPtr(v, "blob"), struct datablob); -} - -/* - turn a WERROR into a MprVar object with lots of funky properties -*/ -struct MprVar mprWERROR(WERROR status) -{ - struct MprVar res; - - res = mprObject("werror"); - - mprSetVar(&res, "errstr", mprString(win_errstr(status))); - mprSetVar(&res, "v", mprCreateIntegerVar(W_ERROR_V(status))); - mprSetVar(&res, "is_ok", mprCreateBoolVar(W_ERROR_IS_OK(status))); - mprSetVar(&res, "is_err", mprCreateBoolVar(!W_ERROR_IS_OK(status))); - - return res; -} - - -/* - set a pointer in a existing MprVar -*/ -void mprSetPtr(struct MprVar *v, const char *propname, const void *p) -{ - mprSetVar(v, propname, mprCreatePtrVar(discard_const(p))); -} - -/* - set a pointer in a existing MprVar, freeing it when the property goes away -*/ -void mprSetPtrChild(struct MprVar *v, const char *propname, const void *p) -{ - mprSetVar(v, propname, mprCreatePtrVar(discard_const(p))); - v = mprGetProperty(v, propname, NULL); - v->allocatedData = 1; - talloc_steal(mprMemCtx(), p); -} - -/* - get a pointer from a MprVar -*/ -void *mprGetPtr(struct MprVar *v, const char *propname) -{ - struct MprVar *val; - val = mprGetProperty(v, propname, NULL); - if (val == NULL) { - return NULL; - } - if (val->type != MPR_TYPE_PTR) { - return NULL; - } - return val->ptr; -} - -/* - set the return value then free the variable -*/ - void mpr_Return(int eid, struct MprVar v) -{ - ejsSetReturnValue(eid, v); - mprDestroyVar(&v); -} - -/* - set the return value then free the variable -*/ -void mpr_ReturnString(int eid, const char *s) -{ - mpr_Return(eid, mprString(s)); -} - - -/* - set a C function in a variable -*/ - void mprSetCFunction(struct MprVar *obj, const char *name, MprCFunction fn) -{ - mprSetVar(obj, name, mprCreateCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE)); -} - -/* - set a string C function in a variable -*/ - void mprSetStringCFunction(struct MprVar *obj, const char *name, MprStringCFunction fn) -{ - mprSetVar(obj, name, mprCreateStringCFunctionVar(fn, obj, MPR_VAR_SCRIPT_HANDLE)); -} - -/* - get a pointer in the current object -*/ -void *mprGetThisPtr(int eid, const char *name) -{ - struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0); - return mprGetPtr(this, name); -} - -/* - set a pointer as a child of the local object -*/ -void mprSetThisPtr(int eid, const char *name, void *ptr) -{ - struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0); - mprSetPtrChild(this, name, ptr); -} - -/* - used by object xxx_init() routines to allow for the caller - to supply a pre-existing object to add properties to, - or create a new object. This makes inheritance easy -*/ -struct MprVar *mprInitObject(int eid, const char *name, int argc, struct MprVar **argv) -{ - if (argc > 0 && mprVarIsObject(argv[0]->type)) { - return argv[0]; - } - mpr_Return(eid, mprObject(name)); - return ejsGetReturnValue(eid); -} diff --git a/source4/scripting/ejs/smbcalls.c b/source4/scripting/ejs/smbcalls.c deleted file mode 100644 index 4314b51455..0000000000 --- a/source4/scripting/ejs/smbcalls.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks into smbd C calls from ejs scripts - - Copyright (C) Andrew Tridgell 2005 - Copyright (C) Tim Potter 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "param/param.h" -#include "scripting/ejs/smbcalls.h" -#include "version.h" - -/* - return the type of a variable -*/ -static int ejs_typeof(MprVarHandle eid, int argc, struct MprVar **argv) -{ - const struct { - MprType type; - const char *name; - } types[] = { - { MPR_TYPE_UNDEFINED, "undefined" }, - { MPR_TYPE_NULL, "object" }, - { MPR_TYPE_BOOL, "boolean" }, - { MPR_TYPE_CFUNCTION, "function" }, - { MPR_TYPE_FLOAT, "number" }, - { MPR_TYPE_INT, "number" }, - { MPR_TYPE_INT64, "number" }, - { MPR_TYPE_OBJECT, "object" }, - { MPR_TYPE_FUNCTION, "function" }, - { MPR_TYPE_STRING, "string" }, - { MPR_TYPE_STRING_CFUNCTION, "function" }, - { MPR_TYPE_PTR, "pointer" } - }; - int i; - const char *type = NULL; - - if (argc != 1) return -1; - - for (i=0;i<ARRAY_SIZE(types);i++) { - if (argv[0]->type == types[i].type) { - type = types[i].name; - break; - } - } - if (type == NULL) return -1; - - mpr_ReturnString(eid, type); - return 0; -} - -/* - return the native type of a variable -*/ -static int ejs_typeof_native(MprVarHandle eid, int argc, struct MprVar **argv) -{ - const struct { - MprType type; - const char *name; - } types[] = { - { MPR_TYPE_UNDEFINED, "undefined" }, - { MPR_TYPE_NULL, "null" }, - { MPR_TYPE_BOOL, "boolean" }, - { MPR_TYPE_CFUNCTION, "c_function" }, - { MPR_TYPE_FLOAT, "float" }, - { MPR_TYPE_INT, "integer" }, - { MPR_TYPE_INT64, "integer64" }, - { MPR_TYPE_OBJECT, "object" }, - { MPR_TYPE_FUNCTION, "js_function" }, - { MPR_TYPE_STRING, "string" }, - { MPR_TYPE_STRING_CFUNCTION, "string_c_function" }, - { MPR_TYPE_PTR, "pointer" } - }; - int i; - const char *type = NULL; - - if (argc != 1) return -1; - - for (i=0;i<ARRAY_SIZE(types);i++) { - if (argv[0]->type == types[i].type) { - type = types[i].name; - break; - } - } - if (type == NULL) return -1; - - mpr_ReturnString(eid, type); - return 0; -} - -/* - libinclude() allows you to include js files using a search path specified - in "js include =" in smb.conf. -*/ -static int ejs_libinclude(int eid, int argc, char **argv) -{ - int i, j; - const char **js_include = lp_js_include(mprLpCtx()); - - if (js_include == NULL || js_include[0] == NULL) { - ejsSetErrorMsg(eid, "js include path not set"); - return -1; - } - - for (i = 0; i < argc; i++) { - const char *script = argv[i]; - struct MprVar result; - char *path, *emsg; - int ret; - - /* use specfied path to search for requested file */ - for (j=0;js_include[j];j++) { - path = talloc_asprintf(mprMemCtx(), "%s/%s", js_include[j], script); - if (path == NULL) { - return -1; - } - if (file_exist(path)) { - - ret = ejsEvalFile(eid, path, &result, &emsg); - talloc_free(path); - if (ret < 0) { - ejsSetErrorMsg(eid, "%s: %s", script, emsg); - return -1; - } - break; - } - talloc_free(path); - } - - if (js_include[j] == NULL) { - ejsSetErrorMsg(eid, "unable to include '%s'", script); - return -1; - } - } - return 0; -} - -/* - return the current version -*/ -static int ejs_version(MprVarHandle eid, int argc, struct MprVar **argv) -{ - mpr_ReturnString(eid, SAMBA_VERSION_STRING); - return 0; -} - - -static void (*ejs_exception_handler) (const char *) = NULL; - -_PUBLIC_ void ejs_exception(const char *reason) -{ - ejs_exception_handler(reason); -} - -/* - setup C functions that be called from ejs -*/ -void smb_setup_ejs_functions(void (*exception_handler)(const char *)) -{ - extern NTSTATUS ejs_init_security(void); - extern NTSTATUS ejs_init_initshutdown(void); - extern NTSTATUS smb_setup_ejs_reg(void); - extern NTSTATUS smb_setup_ejs_string(void); - extern NTSTATUS ejs_init_lsarpc(void); - extern NTSTATUS ejs_init_rpcecho(void); - extern NTSTATUS ejs_init_winreg(void); - extern NTSTATUS smb_setup_ejs_random(void); - extern NTSTATUS smb_setup_ejs_config(void); - extern NTSTATUS ejs_init_misc(void); - extern NTSTATUS ejs_init_netdfs(void); - extern NTSTATUS smb_setup_ejs_datablob(void); - extern NTSTATUS smb_setup_ejs_auth(void); - extern NTSTATUS smb_setup_ejs_nss(void); - extern NTSTATUS ejs_init_samr(void); - extern NTSTATUS ejs_init_wkssvc(void); - extern NTSTATUS smb_setup_ejs_system(void); - extern NTSTATUS smb_setup_ejs_ldb(void); - extern NTSTATUS ejs_init_svcctl(void); - extern NTSTATUS smb_setup_ejs_net(void); - extern NTSTATUS ejs_init_srvsvc(void); - extern NTSTATUS ejs_init_netlogon(void); - extern NTSTATUS ejs_init_drsuapi(void); - extern NTSTATUS ejs_init_irpc(void); - extern NTSTATUS ejs_init_eventlog(void); - init_module_fn static_init[] = { STATIC_smbcalls_MODULES }; - init_module_fn *shared_init; - - ejs_exception_handler = exception_handler; - - smb_setup_ejs_options(); - smb_setup_ejs_credentials(); - - shared_init = load_samba_modules(NULL, mprLpCtx(), "smbcalls"); - - run_init_functions(static_init); - run_init_functions(shared_init); - - talloc_free(shared_init); - - ejsDefineCFunction(-1, "typeof", ejs_typeof, NULL, MPR_VAR_SCRIPT_HANDLE); - ejsDefineCFunction(-1, "nativeTypeOf", ejs_typeof_native, NULL, MPR_VAR_SCRIPT_HANDLE); - ejsDefineStringCFunction(-1, "libinclude", ejs_libinclude, NULL, MPR_VAR_SCRIPT_HANDLE); - ejsDefineCFunction(-1, "version", ejs_version, NULL, MPR_VAR_SCRIPT_HANDLE); -} - diff --git a/source4/scripting/ejs/smbcalls.h b/source4/scripting/ejs/smbcalls.h deleted file mode 100644 index 3aaf324b6e..0000000000 --- a/source4/scripting/ejs/smbcalls.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks into smbd C calls from ejs scripts - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "lib/appweb/ejs/ejs.h" -#include "lib/ldb/include/ldb.h" - -void mpr_Return(int eid, struct MprVar); -NTSTATUS mprSetVar(struct MprVar *v, const char *name, struct MprVar val); -NTSTATUS mprGetVar(struct MprVar **v, const char *name); -void mprAddArray(struct MprVar *var, int i, struct MprVar v); -void mprSetCFunction(struct MprVar *obj, const char *name, MprCFunction fn); -void mprSetStringCFunction(struct MprVar *obj, const char *name, MprStringCFunction fn); - -struct smbcalls_context { - struct event_context *event_ctx; - struct messaging_context *msg_ctx; -}; - -struct ldb_context; -struct ldb_message; -struct cli_credentials; - -#include "param/param.h" -#include "scripting/ejs/proto.h" diff --git a/source4/scripting/ejs/smbcalls_auth.c b/source4/scripting/ejs/smbcalls_auth.c deleted file mode 100644 index b67bb7ed5b..0000000000 --- a/source4/scripting/ejs/smbcalls_auth.c +++ /dev/null @@ -1,243 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - ejs auth functions - - Copyright (C) Simo Sorce 2005 - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/appweb/ejs/ejs.h" -#include "auth/auth.h" -#include "auth/credentials/credentials.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/events/events.h" -#include "lib/messaging/irpc.h" -#include "libcli/security/security.h" - -static int ejs_doauth(MprVarHandle eid, - TALLOC_CTX *tmp_ctx, struct MprVar *auth, - const char *username, const char *password, - const char *domain, const char *workstation, - struct socket_address *remote_host, - const char **auth_types) -{ - struct auth_usersupplied_info *user_info = NULL; - struct auth_serversupplied_info *server_info = NULL; - struct auth_session_info *session_info = NULL; - struct auth_context *auth_context; - struct MprVar *session_info_obj; - NTSTATUS nt_status; - bool set; - - struct smbcalls_context *c; - struct event_context *ev; - struct messaging_context *msg; - - /* Hope we can find an smbcalls_context somewhere up there... */ - c = talloc_find_parent_bytype(tmp_ctx, struct smbcalls_context); - if (c) { - ev = c->event_ctx; - msg = c->msg_ctx; - } else { - /* Hope we can find the event context somewhere up there... */ - ev = mprEventCtx(); - msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, mprLpCtx()), - lp_iconv_convenience(mprLpCtx()), ev); - } - - if (auth_types) { - nt_status = auth_context_create_methods(tmp_ctx, auth_types, ev, msg, mprLpCtx(), &auth_context); - } else { - nt_status = auth_context_create(tmp_ctx, ev, msg, mprLpCtx(), &auth_context); - } - if (!NT_STATUS_IS_OK(nt_status)) { - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - mprSetPropertyValue(auth, "report", mprString("Auth System Failure")); - goto done; - } - - user_info = talloc(tmp_ctx, struct auth_usersupplied_info); - if (!user_info) { - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - mprSetPropertyValue(auth, "report", mprString("talloc failed")); - goto done; - } - - user_info->mapped_state = true; - user_info->client.account_name = username; - user_info->mapped.account_name = username; - user_info->client.domain_name = domain; - user_info->mapped.domain_name = domain; - - user_info->workstation_name = workstation; - - user_info->remote_host = remote_host; - - user_info->password_state = AUTH_PASSWORD_PLAIN; - user_info->password.plaintext = talloc_strdup(user_info, password); - - user_info->flags = USER_INFO_CASE_INSENSITIVE_USERNAME | - USER_INFO_DONT_CHECK_UNIX_ACCOUNT; - - user_info->logon_parameters = 0; - - nt_status = auth_check_password(auth_context, tmp_ctx, user_info, &server_info); - - /* Don't give the game away (any difference between no such - * user and wrong password) */ - nt_status = auth_nt_status_squash(nt_status); - - if (!NT_STATUS_IS_OK(nt_status)) { - mprSetPropertyValue(auth, "report", - mprString(talloc_strdup(mprMemCtx(), get_friendly_nt_error_msg(nt_status)))); - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - goto done; - } - - nt_status = auth_generate_session_info(tmp_ctx, mprEventCtx(), mprLpCtx(), server_info, &session_info); - if (!NT_STATUS_IS_OK(nt_status)) { - mprSetPropertyValue(auth, "report", mprString("Session Info generation failed")); - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - goto done; - } - - if (security_token_has_nt_authenticated_users(session_info->security_token)) { - mprSetPropertyValue(auth, "user_class", mprString("USER")); - set = true; - } - - if (security_token_has_builtin_administrators(session_info->security_token)) { - mprSetPropertyValue(auth, "user_class", mprString("ADMINISTRATOR")); - set = true; - } - - if (security_token_is_system(session_info->security_token)) { - mprSetPropertyValue(auth, "user_class", mprString("SYSTEM")); - set = true; - } - - if (security_token_is_anonymous(session_info->security_token)) { - mprSetPropertyValue(auth, "report", mprString("Anonymous login not permitted")); - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - goto done; - } - - if (!set) { - mprSetPropertyValue(auth, "report", mprString("Session Info generation failed")); - mprSetPropertyValue(auth, "result", mprCreateBoolVar(false)); - } - - session_info_obj = mprInitObject(eid, "session_info", 0, NULL); - - mprSetPtrChild(session_info_obj, "session_info", session_info); - talloc_steal(mprMemCtx(), session_info); - - mprSetProperty(auth, "session_info", session_info_obj); - mprSetPropertyValue(auth, "result", mprCreateBoolVar(server_info->authenticated)); - mprSetPropertyValue(auth, "username", mprString(server_info->account_name)); - mprSetPropertyValue(auth, "domain", mprString(server_info->domain_name)); - -done: - return 0; -} - -/* - perform user authentication, returning an array of results - -*/ -static int ejs_userAuth(MprVarHandle eid, int argc, struct MprVar **argv) -{ - TALLOC_CTX *tmp_ctx; - const char *username; - const char *password; - const char *domain; - const char *workstation; - struct MprVar auth; - struct cli_credentials *creds; - struct socket_address *remote_host; - const char *auth_types_unix[] = { "unix", NULL }; - - if (argc != 2 || argv[0]->type != MPR_TYPE_OBJECT || argv[1]->type != MPR_TYPE_OBJECT) { - ejsSetErrorMsg(eid, "userAuth invalid arguments, this function requires an object."); - return -1; - } - - /* get credential values from credentials object */ - creds = mprGetPtr(argv[0], "creds"); - if (creds == NULL) { - ejsSetErrorMsg(eid, "userAuth requires a 'creds' first parameter"); - return -1; - } - - remote_host = (struct socket_address *)mprGetPtr(argv[1], "socket_address"); - if (remote_host == NULL) { - ejsSetErrorMsg(eid, "userAuth requires a socket address second parameter"); - return -1; - } - - tmp_ctx = talloc_new(mprMemCtx()); - - username = cli_credentials_get_username(creds); - password = cli_credentials_get_password(creds); - domain = cli_credentials_get_domain(creds); - workstation = cli_credentials_get_workstation(creds); - - if (username == NULL || password == NULL || domain == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - talloc_free(tmp_ctx); - return 0; - } - - auth = mprObject("auth"); - - if (domain && (strcmp("SYSTEM USER", domain) == 0)) { - ejs_doauth(eid, tmp_ctx, &auth, username, password, domain, workstation, remote_host, auth_types_unix); - } else { - ejs_doauth(eid, tmp_ctx, &auth, username, password, domain, workstation, remote_host, NULL); - } - - mpr_Return(eid, auth); - talloc_free(tmp_ctx); - return 0; -} - -/* - initialise credentials ejs object -*/ -static int ejs_system_session(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *obj = mprInitObject(eid, "session_info", argc, argv); - struct auth_session_info *session_info = system_session(mprMemCtx(), mprLpCtx()); - - if (session_info == NULL) { - return -1; - } - - mprSetPtrChild(obj, "session_info", session_info); - return 0; -} - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_auth(void) -{ - ejsDefineCFunction(-1, "userAuth", ejs_userAuth, NULL, MPR_VAR_SCRIPT_HANDLE); - ejsDefineCFunction(-1, "system_session", ejs_system_session, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbcalls_config.c b/source4/scripting/ejs/smbcalls_config.c deleted file mode 100644 index eb673b3a23..0000000000 --- a/source4/scripting/ejs/smbcalls_config.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks into smbd C calls from ejs scripts - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" -#include "param/loadparm.h" -#include "system/network.h" -#include "lib/socket/netif.h" -#include "param/param.h" - -/* - return a list of defined services -*/ -static int ejs_lpServices(MprVarHandle eid, int argc, char **argv) -{ - int i; - const char **list = NULL; - if (argc != 0) return -1; - - for (i=0;i<lp_numservices(mprLpCtx());i++) { - list = str_list_add(list, lp_servicename(lp_servicebynum(mprLpCtx(), i))); - } - talloc_steal(mprMemCtx(), list); - mpr_Return(eid, mprList("services", list)); - return 0; -} - - -/* - allow access to loadparm variables from inside ejs scripts in web apps - - can be called in 4 ways: - - v = lp.get("type:parm"); gets a parametric variable - v = lp.get("share", "type:parm"); gets a parametric variable on a share - v = lp.get("parm"); gets a global variable - v = lp.get("share", "parm"); gets a share variable - - the returned variable is a ejs object. It is an array object for lists. -*/ -static int ejs_lpGet(MprVarHandle eid, int argc, char **argv) -{ - struct parm_struct *parm = NULL; - void *parm_ptr = NULL; - int i; - - if (argc < 1) return -1; - - if (argc == 2) { - struct loadparm_service *service; - /* its a share parameter */ - service = lp_service(mprLpCtx(), argv[0]); - if (service == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - if (strchr(argv[1], ':')) { - /* its a parametric option on a share */ - const char *type = talloc_strndup(mprMemCtx(), - argv[1], - strcspn(argv[1], ":")); - const char *option = strchr(argv[1], ':') + 1; - const char *value; - if (type == NULL || option == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - value = lp_get_parametric(mprLpCtx(), service, type, option); - if (value == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - mpr_ReturnString(eid, value); - return 0; - } - - parm = lp_parm_struct(argv[1]); - if (parm == NULL || parm->class == P_GLOBAL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - parm_ptr = lp_parm_ptr(mprLpCtx(), service, parm); - } else if (strchr(argv[0], ':')) { - /* its a global parametric option */ - const char *type = talloc_strndup(mprMemCtx(), - argv[0], strcspn(argv[0], ":")); - const char *option = strchr(argv[0], ':') + 1; - const char *value; - if (type == NULL || option == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - value = lp_get_parametric(mprLpCtx(), NULL, type, option); - if (value == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - mpr_ReturnString(eid, value); - return 0; - } else { - /* its a global parameter */ - parm = lp_parm_struct(argv[0]); - if (parm == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - parm_ptr = lp_parm_ptr(mprLpCtx(), NULL, parm); - } - - if (parm == NULL || parm_ptr == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - - /* construct and return the right type of ejs object */ - switch (parm->type) { - case P_STRING: - case P_USTRING: - mpr_ReturnString(eid, *(char **)parm_ptr); - break; - case P_BOOL: - mpr_Return(eid, mprCreateBoolVar(*(bool *)parm_ptr)); - break; - case P_INTEGER: - case P_OCTAL: - case P_BYTES: - mpr_Return(eid, mprCreateIntegerVar(*(int *)parm_ptr)); - break; - case P_ENUM: - for (i=0; parm->enum_list[i].name; i++) { - if (*(int *)parm_ptr == parm->enum_list[i].value) { - mpr_ReturnString(eid, parm->enum_list[i].name); - return 0; - } - } - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - case P_LIST: - mpr_Return(eid, mprList(parm->label, *(const char ***)parm_ptr)); - break; - } - return 0; -} - -/* - v = lp.filename(); obtain filename -*/ -static int ejs_lpFilename(MprVarHandle eid, int argc, char **argv) -{ - mpr_ReturnString(eid, lp_configfile(mprLpCtx())); - return 0; -} - -/* - set a smb.conf parameter. Only sets in memory, not permanent - - can be called in 4 ways: - - ok = lp.set("parm", "value"); -*/ -static int ejs_lpSet(MprVarHandle eid, int argc, char **argv) -{ - if (argc != 2) { - ejsSetErrorMsg(eid, "lp.set invalid arguments"); - return -1; - } - - mpr_Return(eid, mprCreateBoolVar(lp_set_cmdline(mprLpCtx(), argv[0], argv[1]))); - return 0; -} - -/* - reload smb.conf - - ok = lp.reload(); -*/ -static int ejs_lpReload(MprVarHandle eid, int argc, char **argv) -{ - bool ret; - const char *filename = lp_configfile(mprLpCtx()); - - ret = lp_load(mprLpCtx(), filename); - mpr_Return(eid, mprCreateBoolVar(ret)); - return 0; -} - -/* - initialise loadparm ejs subsystem -*/ -static int ejs_loadparm_init(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *obj = mprInitObject(eid, "loadparm", argc, argv); - - mprSetStringCFunction(obj, "get", ejs_lpGet); - mprSetStringCFunction(obj, "set", ejs_lpSet); - mprSetStringCFunction(obj, "reload", ejs_lpReload); - mprSetStringCFunction(obj, "services", ejs_lpServices); - mprSetStringCFunction(obj, "filename", ejs_lpFilename); - return 0; -} - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_config(void) -{ - ejsDefineCFunction(-1, "loadparm_init", ejs_loadparm_init, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbcalls_creds.c b/source4/scripting/ejs/smbcalls_creds.c deleted file mode 100644 index fd73f0751f..0000000000 --- a/source4/scripting/ejs/smbcalls_creds.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks credentials calls - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/cmdline/popt_common.h" -#include "auth/credentials/credentials.h" - -/* - helper function to get the local objects credentials ptr -*/ -static struct cli_credentials *ejs_creds_get_credentials(int eid) -{ - struct cli_credentials *creds = (struct cli_credentials *)mprGetThisPtr(eid, "creds"); - if (creds == NULL) { - ejsSetErrorMsg(eid, "NULL ejs credentials"); - } - return creds; -} - -/* - get a domain -*/ -static int ejs_creds_get_domain(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - - mpr_Return(eid, mprString(cli_credentials_get_domain(creds))); - return 0; -} - - -/* - set a domain -*/ -static int ejs_creds_set_domain(MprVarHandle eid, int argc, char **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 1) { - ejsSetErrorMsg(eid, "bad arguments to set_domain"); - return -1; - } - - cli_credentials_set_domain(creds, argv[0], CRED_SPECIFIED); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - get a username -*/ -static int ejs_creds_get_username(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - - mpr_Return(eid, mprString(cli_credentials_get_username(creds))); - return 0; -} - - -/* - set a username -*/ -static int ejs_creds_set_username(MprVarHandle eid, int argc, char **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 1) { - ejsSetErrorMsg(eid, "bad arguments to set_username"); - return -1; - } - - cli_credentials_set_username(creds, argv[0], CRED_SPECIFIED); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - get user password -*/ -static int ejs_creds_get_password(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - - mpr_Return(eid, mprString(cli_credentials_get_password(creds))); - return 0; -} - - -/* - set user password -*/ -static int ejs_creds_set_password(MprVarHandle eid, int argc, char **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 1) { - ejsSetErrorMsg(eid, "bad arguments to set_password"); - return -1; - } - - cli_credentials_set_password(creds, argv[0], CRED_SPECIFIED); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - set realm -*/ -static int ejs_creds_set_realm(MprVarHandle eid, int argc, char **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 1) { - ejsSetErrorMsg(eid, "bad arguments to set_realm"); - return -1; - } - - cli_credentials_set_realm(creds, argv[0], CRED_SPECIFIED); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - get realm -*/ -static int ejs_creds_get_realm(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - - mpr_Return(eid, mprString(cli_credentials_get_realm(creds))); - return 0; -} - - -/* - set workstation -*/ -static int ejs_creds_set_workstation(MprVarHandle eid, int argc, char **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 1) { - ejsSetErrorMsg(eid, "bad arguments to set_workstation"); - return -1; - } - - cli_credentials_set_workstation(creds, argv[0], CRED_SPECIFIED); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - get workstation -*/ -static int ejs_creds_get_workstation(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - - mpr_Return(eid, mprString(cli_credentials_get_workstation(creds))); - return 0; -} - -/* - set machine account -*/ -static int ejs_creds_set_machine_account(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds = ejs_creds_get_credentials(eid); - if (argc != 0) { - ejsSetErrorMsg(eid, "bad arguments to set_machine_account"); - return -1; - } - - if (NT_STATUS_IS_OK(cli_credentials_set_machine_account(creds, mprLpCtx()))) { - mpr_Return(eid, mprCreateBoolVar(true)); - } else { - mpr_Return(eid, mprCreateBoolVar(false)); - } - return 0; -} - - -/* - initialise credentials ejs object -*/ -static int ejs_credentials_obj(struct MprVar *obj, struct cli_credentials *creds) -{ - mprSetPtrChild(obj, "creds", creds); - - /* setup our object methods */ - mprSetCFunction(obj, "get_domain", ejs_creds_get_domain); - mprSetStringCFunction(obj, "set_domain", ejs_creds_set_domain); - mprSetCFunction(obj, "get_username", ejs_creds_get_username); - mprSetStringCFunction(obj, "set_username", ejs_creds_set_username); - mprSetCFunction(obj, "get_password", ejs_creds_get_password); - mprSetStringCFunction(obj, "set_password", ejs_creds_set_password); - mprSetCFunction(obj, "get_realm", ejs_creds_get_realm); - mprSetStringCFunction(obj, "set_realm", ejs_creds_set_realm); - mprSetCFunction(obj, "get_workstation", ejs_creds_get_workstation); - mprSetStringCFunction(obj, "set_workstation", ejs_creds_set_workstation); - mprSetCFunction(obj, "set_machine_account", ejs_creds_set_machine_account); - - return 0; -} - - -struct MprVar mprCredentials(struct cli_credentials *creds) -{ - struct MprVar mpv = mprObject("credentials"); - - ejs_credentials_obj(&mpv, creds); - - return mpv; -} - - -/* - initialise credentials ejs object -*/ -static int ejs_credentials_init(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct cli_credentials *creds; - struct MprVar *obj = mprInitObject(eid, "credentials", argc, argv); - - creds = cli_credentials_init(mprMemCtx()); - if (creds == NULL) { - return -1; - } - - cli_credentials_set_conf(creds, mprLpCtx()); - - return ejs_credentials_obj(obj, creds); -} - -/* - initialise cmdline credentials ejs object -*/ -int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv) -{ - struct MprVar *obj = mprInitObject(eid, "credentials", argc, argv); - if (talloc_reference(mprMemCtx(), cmdline_credentials) == NULL) { - return -1; - } - return ejs_credentials_obj(obj, cmdline_credentials); -} - -/* - setup C functions that be called from ejs -*/ -void smb_setup_ejs_credentials(void) -{ - ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE); -} - diff --git a/source4/scripting/ejs/smbcalls_ldb.c b/source4/scripting/ejs/smbcalls_ldb.c deleted file mode 100644 index 4a157945af..0000000000 --- a/source4/scripting/ejs/smbcalls_ldb.c +++ /dev/null @@ -1,772 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide hooks into smbd C calls from ejs scripts - - Copyright (C) Andrew Tridgell 2005 - Copyright (C) Jelmer Vernooij 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/ldb/include/ldb.h" -#include "lib/ldb/include/ldb_errors.h" -#include "ldb_wrap.h" -#include "dsdb/samdb/samdb.h" -#include "librpc/ndr/libndr.h" -#include "libcli/security/security.h" - -/* - get the connected db - */ -static struct ldb_context *ejs_get_ldb_context(int eid) -{ - struct ldb_context *ldb = (struct ldb_context *)mprGetThisPtr(eid, "db"); - if (ldb == NULL) { - ejsSetErrorMsg(eid, "invalid ldb connection"); - } - return ldb; -} - -/* - perform an ldb search, returning an array of results - - syntax: - res = ldb.search("expression"); - var attrs = new Array("attr1", "attr2", "attr3"); - ldb.search("expression", attrs); - var basedn = "cn=this,dc=is,dc=a,dc=test"; - ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs); - ldb.search("expression", basedn, ldb.SCOPE_SUBTREE, attrs, controls); -*/ -static int ejs_ldbSearch(MprVarHandle eid, int argc, struct MprVar **argv) -{ - const char **attrs = NULL; - const char *expression; - const char *base = NULL; - struct ldb_dn *basedn = NULL; - int scope = LDB_SCOPE_DEFAULT; - TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx()); - struct ldb_context *ldb; - int ret; - struct ldb_control **parsed_controls = NULL; - struct ldb_result *res=NULL; - struct ldb_request *req; - - /* validate arguments */ - if (argc < 1 || argc > 5) { - ejsSetErrorMsg(eid, "ldb.search invalid number of arguments"); - goto failed; - } - if (argc > 3 && argv[3]->type != MPR_TYPE_OBJECT) { - ejsSetErrorMsg(eid, "ldb.search attributes must be an object"); - goto failed; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - expression = mprToString(argv[0]); - if (argc > 1) { - base = mprToString(argv[1]); - /* a null basedn is valid */ - } - if (base != NULL) { - basedn = ldb_dn_new(tmp_ctx, ldb, base); - if ( ! ldb_dn_validate(basedn)) { - ejsSetErrorMsg(eid, "ldb.search malformed base dn"); - goto failed; - } - } else { - basedn = ldb_get_default_basedn(ldb); - } - if (argc > 2) { - scope = mprToInt(argv[2]); - switch (scope) { - case LDB_SCOPE_DEFAULT: - case LDB_SCOPE_BASE: - case LDB_SCOPE_ONELEVEL: - case LDB_SCOPE_SUBTREE: - break; /* ok */ - default: - ejsSetErrorMsg(eid, "ldb.search invalid scope"); - goto failed; - } - } - if (argc > 3) { - attrs = mprToList(tmp_ctx, argv[3]); - } - if (argc > 4) { - const char **controls; - controls = mprToList(tmp_ctx, argv[4]); - if (controls) { - parsed_controls = ldb_parse_control_strings(ldb, tmp_ctx, controls); - if (!parsed_controls) { - ejsSetErrorMsg(eid, "ldb.search cannot parse controls: %s", - ldb_errstring(ldb)); - goto failed; - } - } - } - - res = talloc_zero(tmp_ctx, struct ldb_result); - if (!res) { - return LDB_ERR_OPERATIONS_ERROR; - } - - ret = ldb_build_search_req(&req, ldb, tmp_ctx, - basedn, - scope, - expression, - attrs, - parsed_controls, - res, - ldb_search_default_callback); - - if (ret == LDB_SUCCESS) { - - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - ret = ldb_request(ldb, req); - - if (ret == LDB_SUCCESS) { - ret = ldb_wait(req->handle, LDB_WAIT_ALL); - } - } - - if (ret != LDB_SUCCESS) { - ejsSetErrorMsg(eid, "ldb.search failed - %s", ldb_errstring(ldb)); - mpr_Return(eid, mprLdbResult(ldb, ret, NULL)); - } else { - mpr_Return(eid, mprLdbResult(ldb, ret, res)); - } - - talloc_free(tmp_ctx); - return 0; - -failed: - talloc_free(tmp_ctx); - return -1; -} - - -/* - perform an ldb add or modify -*/ -static int ejs_ldbAddModify(MprVarHandle eid, int argc, struct MprVar **argv, - int fn(struct ldb_context *, const struct ldb_message *)) -{ - const char *ldifstring; - struct ldb_context *ldb; - struct ldb_ldif *ldif; - int ret = 0, count=0; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments"); - return -1; - } - - ldifstring = mprToString(argv[0]); - if (ldifstring == NULL) { - ejsSetErrorMsg(eid, "ldb.add/modify invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - while ((ldif = ldb_ldif_read_string(ldb, &ldifstring))) { - count++; - ret = fn(ldb, ldif->msg); - talloc_free(ldif); - if (ret != 0) break; - } - - if (count == 0) { - ejsSetErrorMsg(eid, "ldb.add/modify invalid ldif"); - return -1; - } - - mpr_Return(eid, mprLdbResult(ldb, ret, NULL)); - return 0; -} - - -/* - perform an ldb delete - usage: - ok = ldb.delete(dn); -*/ -static int ejs_ldbDelete(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_dn *dn; - struct ldb_context *ldb; - int ret; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.delete invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - dn = ldb_dn_new(ldb, ldb, mprToString(argv[0])); - if ( ! ldb_dn_validate(dn)) { - ejsSetErrorMsg(eid, "ldb.delete malformed dn"); - return -1; - } - - ret = ldb_delete(ldb, dn); - - talloc_free(dn); - - mpr_Return(eid, mprLdbResult(ldb, ret, NULL)); - return 0; -} - -/* - perform an ldb rename - usage: - ok = ldb.rename(dn1, dn2); -*/ -static int ejs_ldbRename(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_dn *dn1, *dn2; - struct ldb_context *ldb; - int ret; - - if (argc != 2) { - ejsSetErrorMsg(eid, "ldb.rename invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - dn1 = ldb_dn_new(ldb, ldb, mprToString(argv[0])); - dn2 = ldb_dn_new(ldb, ldb, mprToString(argv[1])); - if ( ! ldb_dn_validate(dn1) || ! ldb_dn_validate(dn2)) { - ejsSetErrorMsg(eid, "ldb.rename invalid or malformed arguments"); - return -1; - } - - ret = ldb_rename(ldb, dn1, dn2); - - talloc_free(dn1); - talloc_free(dn2); - - mpr_Return(eid, mprLdbResult(ldb, ret, NULL)); - return 0; -} - -/* - get last error message - usage: - ok = ldb.errstring(); -*/ -static int ejs_ldbErrstring(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_context *ldb; - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - mpr_Return(eid, mprString(ldb_errstring(ldb))); - return 0; -} - -/* - base64 encode - usage: - dataout = ldb.encode(datain) - */ -static int ejs_base64encode(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char *ret; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count"); - return -1; - } - - if (argv[0]->type == MPR_TYPE_STRING) { - const char *orig = mprToString(argv[0]); - ret = ldb_base64_encode(mprMemCtx(), orig, strlen(orig)); - } else { - DATA_BLOB *blob; - - blob = mprToDataBlob(argv[0]); - mprAssert(blob); - ret = ldb_base64_encode(mprMemCtx(), (char *)blob->data, blob->length); - } - - if (!ret) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - mpr_Return(eid, mprString(ret)); - } - - talloc_free(ret); - - return 0; -} - -/* - base64 decode - usage: - dataout = ldb.decode(datain) - */ -static int ejs_base64decode(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char *tmp; - int ret; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.base64encode invalid argument count"); - return -1; - } - - tmp = talloc_strdup(mprMemCtx(), mprToString(argv[0])); - ret = ldb_base64_decode(tmp); - if (ret == -1) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - DATA_BLOB blob; - blob.data = (uint8_t *)tmp; - blob.length = ret; - mpr_Return(eid, mprDataBlob(blob)); - } - - talloc_free(tmp); - - return 0; -} - -/* - escape a DN - usage: - dataout = ldb.dn_escape(datain) - */ -static int ejs_dn_escape(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char *ret; - struct ldb_val val; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.dn_escape invalid argument count"); - return -1; - } - - val = data_blob_string_const(mprToString(argv[0])); - - ret = ldb_dn_escape_value(mprMemCtx(), val); - if (ret == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - mpr_Return(eid, mprString(ret)); - talloc_free(ret); - } - - return 0; -} - -/* - perform an ldb add - - syntax: - ok = ldb.add(ldifstring); -*/ -static int ejs_ldbAdd(MprVarHandle eid, int argc, struct MprVar **argv) -{ - return ejs_ldbAddModify(eid, argc, argv, ldb_add); -} - -/* - perform an ldb modify - - syntax: - ok = ldb.modify(ldifstring); -*/ -static int ejs_ldbModify(MprVarHandle eid, int argc, struct MprVar **argv) -{ - return ejs_ldbAddModify(eid, argc, argv, ldb_modify); -} - -/* - connect to a database - usage: - ok = ldb.connect(dbfile); - ok = ldb.connect(dbfile, "modules:modlist"); - - ldb.credentials or ldb.session_info may be setup first - -*/ -static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv) -{ - struct ldb_context *ldb; - struct auth_session_info *session_info = NULL; - struct cli_credentials *creds = NULL; - struct MprVar *credentials, *session; - struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0); - - const char *dbfile; - - if (argc < 1) { - ejsSetErrorMsg(eid, "ldb.connect invalid arguments"); - return -1; - } - - credentials = mprGetProperty(this, "credentials", NULL); - if (credentials) { - creds = talloc_get_type(mprGetPtr(credentials, "creds"), struct cli_credentials); - } - - session = mprGetProperty(this, "session_info", NULL); - if (session) { - session_info = talloc_get_type(mprGetPtr(session, "session_info"), struct auth_session_info); - } - - dbfile = argv[0]; - - ldb = ldb_wrap_connect(mprMemCtx(), mprEventCtx(), mprLpCtx(), dbfile, - session_info, creds, - 0, (const char **)(argv+1)); - if (ldb == NULL) { - ejsSetErrorMsg(eid, "ldb.connect failed to open %s", dbfile); - } - - mprSetThisPtr(eid, "db", ldb); - mpr_Return(eid, mprCreateBoolVar(ldb != NULL)); - return 0; -} - - -/* - close a db connection -*/ -static int ejs_ldbClose(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_context *ldb; - - if (argc != 0) { - ejsSetErrorMsg(eid, "ldb.close invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - mprSetThisPtr(eid, "db", NULL); - mpr_Return(eid, mprCreateBoolVar(true)); - return 0; -} - - -/* - start a ldb transaction - usage: - ok = ldb.transaction_start(); -*/ -static int ejs_ldbTransactionStart(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_context *ldb; - int ret; - - if (argc != 0) { - ejsSetErrorMsg(eid, "ldb.transaction_start invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - ret = ldb_transaction_start(ldb); - - mpr_Return(eid, mprCreateBoolVar(ret == 0)); - return 0; -} - -/* - cancel a ldb transaction - usage: - ok = ldb.transaction_cancel(); -*/ -static int ejs_ldbTransactionCancel(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_context *ldb; - int ret; - - if (argc != 0) { - ejsSetErrorMsg(eid, "ldb.transaction_cancel invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - ret = ldb_transaction_cancel(ldb); - - mpr_Return(eid, mprCreateBoolVar(ret == 0)); - return 0; -} - -/* - commit a ldb transaction - usage: - ok = ldb.transaction_commit(); -*/ -static int ejs_ldbTransactionCommit(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct ldb_context *ldb; - int ret; - - if (argc != 0) { - ejsSetErrorMsg(eid, "ldb.transaction_commit invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - ret = ldb_transaction_commit(ldb); - - mpr_Return(eid, mprCreateBoolVar(ret == 0)); - return 0; -} - -/* - commit a ldb attach a dsdb_schema from ldif files - usage: - ok = ldb.attach_dsdb_schema_from_ldif("prefixMap ldif content", "definition ldif content") -*/ -static int ejs_ldb_attach_dsdb_schema_from_ldif(MprVarHandle eid, int argc, char **argv) -{ - struct ldb_context *ldb; - WERROR status; - const char *pf; - const char *df; - - if (argc != 2) { - ejsSetErrorMsg(eid, "ldb.attach_dsdb_schema_from_ldif invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - pf = argv[0]; - df = argv[1]; - - status = dsdb_attach_schema_from_ldif_file(ldb, pf, df); - - mpr_Return(eid, mprWERROR(status)); - return 0; -} - -/* - set a particular invocationId against the running LDB - usage: - ok = ldb.set_ntds_invocationId("7729aa4b-f990-41ad-b81a-8b6a14090f41"); -*/ -static int ejs_ldb_set_ntds_invocationId(MprVarHandle eid, int argc, char **argv) -{ - struct ldb_context *ldb; - NTSTATUS status; - struct GUID guid; - char *guid_str; - bool ok; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - guid_str = argv[0]; - - status = GUID_from_string(guid_str, &guid); - if (!NT_STATUS_IS_OK(status)) { - ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to parse GUID '%s' %s\n", - guid_str, nt_errstr(status)); - return -1; - } - - ok = samdb_set_ntds_invocation_id(ldb, &guid); - if (!ok) { - ejsSetErrorMsg(eid, "ldb.set_ntds_invocationId - failed to set cached ntds invocationId\n"); - return -1; - } - - mpr_Return(eid, mprCreateBoolVar(ok)); - return 0; -} - -/* - attach a particular ntds objectGUID against the current ldb - usage: - ok = ldb.set_ntds_objectGUID("7729aa4b-f990-41ad-b81a-8b6a14090f41"); -*/ -static int ejs_ldb_set_ntds_objectGUID(MprVarHandle eid, int argc, char **argv) -{ - struct ldb_context *ldb; - NTSTATUS status; - struct GUID guid; - char *guid_str; - bool ok; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - guid_str = argv[0]; - - status = GUID_from_string(guid_str, &guid); - if (!NT_STATUS_IS_OK(status)) { - ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to parse GUID '%s' %s\n", - guid_str, nt_errstr(status)); - return -1; - } - - ok = samdb_set_ntds_invocation_id(ldb, &guid); - if (!ok) { - ejsSetErrorMsg(eid, "ldb.set_ntds_objectGUID - failed to set cached ntds invocationId\n"); - return -1; - } - - mpr_Return(eid, mprCreateBoolVar(ok)); - return 0; -} - -/* - attach a particular domain SID against the current ldb - usage: - ok = ldb.set_domain_sid("S-S-1-5-21-3065342217-3567412576-2214182334"); -*/ -static int ejs_ldb_set_domain_sid(MprVarHandle eid, int argc, char **argv) -{ - struct ldb_context *ldb; - struct dom_sid *dom_sid; - char *dom_sid_str; - bool ok; - - if (argc != 1) { - ejsSetErrorMsg(eid, "ldb.set_domain_sid invalid arguments"); - return -1; - } - - ldb = ejs_get_ldb_context(eid); - if (ldb == NULL) { - return -1; - } - - dom_sid_str = argv[0]; - - dom_sid = dom_sid_parse_talloc(NULL, dom_sid_str); - if (!dom_sid) { - ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to parse domain sid '%s'\n", - dom_sid_str); - return -1; - } - - ok = samdb_set_domain_sid(ldb, dom_sid); - talloc_free(dom_sid); - if (!ok) { - ejsSetErrorMsg(eid, "ldb.set_domain_sid - failed to set cached ntds invocationId\n"); - return -1; - } - - mpr_Return(eid, mprCreateBoolVar(ok)); - return 0; -} - -/* - initialise ldb ejs subsystem -*/ -static int ejs_ldb_init(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *ldb = mprInitObject(eid, "ldb", argc, argv); - - mprSetStringCFunction(ldb, "connect", ejs_ldbConnect); - mprSetCFunction(ldb, "search", ejs_ldbSearch); - mprSetCFunction(ldb, "add", ejs_ldbAdd); - mprSetCFunction(ldb, "modify", ejs_ldbModify); - mprSetCFunction(ldb, "del", ejs_ldbDelete); - mprSetCFunction(ldb, "rename", ejs_ldbRename); - mprSetCFunction(ldb, "errstring", ejs_ldbErrstring); - mprSetCFunction(ldb, "encode", ejs_base64encode); - mprSetCFunction(ldb, "decode", ejs_base64decode); - mprSetCFunction(ldb, "dn_escape", ejs_dn_escape); - mprSetCFunction(ldb, "close", ejs_ldbClose); - mprSetCFunction(ldb, "transaction_start", ejs_ldbTransactionStart); - mprSetCFunction(ldb, "transaction_cancel", ejs_ldbTransactionCancel); - mprSetCFunction(ldb, "transaction_commit", ejs_ldbTransactionCommit); - mprSetStringCFunction(ldb, "attach_dsdb_schema_from_ldif", - ejs_ldb_attach_dsdb_schema_from_ldif); - mprSetStringCFunction(ldb, "set_ntds_invocationId", - ejs_ldb_set_ntds_invocationId); - mprSetStringCFunction(ldb, "set_ntds_objectGUID", - ejs_ldb_set_ntds_objectGUID); - mprSetStringCFunction(ldb, "set_domain_sid", - ejs_ldb_set_domain_sid); - mprSetVar(ldb, "SCOPE_BASE", mprCreateNumberVar(LDB_SCOPE_BASE)); - mprSetVar(ldb, "SCOPE_ONE", mprCreateNumberVar(LDB_SCOPE_ONELEVEL)); - mprSetVar(ldb, "SCOPE_SUBTREE", mprCreateNumberVar(LDB_SCOPE_SUBTREE)); - mprSetVar(ldb, "SCOPE_DEFAULT", mprCreateNumberVar(LDB_SCOPE_DEFAULT)); - - return 0; -} - - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_ldb(void) -{ - ejsDefineCFunction(-1, "ldb_init", ejs_ldb_init, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbcalls_options.c b/source4/scripting/ejs/smbcalls_options.c deleted file mode 100644 index 93872baa40..0000000000 --- a/source4/scripting/ejs/smbcalls_options.c +++ /dev/null @@ -1,193 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide a command line options parsing function for ejs - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/cmdline/popt_common.h" -#include "scripting/ejs/smbcalls.h" - - -/* - usage: - options = GetOptions(argv, - "realm=s", - "enablexx", - "myint=i"); - - the special options POPT_COMMON_* options are recognised and replaced - with the Samba internal options - - resulting parsed options are placed in the options object - - additional command line arguments are placed in options.ARGV -*/ - -static int ejs_GetOptions(MprVarHandle eid, int argc, struct MprVar **argv) -{ - poptContext pc; - int opt; - struct { - const char *name; - struct poptOption *table; - const char *description; - } tables[] = { - { "POPT_AUTOHELP", poptHelpOptions, "Help options:" }, - { "POPT_COMMON_SAMBA", popt_common_samba, "Common Samba options:" }, - { "POPT_COMMON_CONNECTION", popt_common_connection, "Connection options:" }, - { "POPT_COMMON_CREDENTIALS", popt_common_credentials, "Authentication options:" }, - { "POPT_COMMON_VERSION", popt_common_version, "Common Samba options:" } - }; - - struct MprVar *options = mprInitObject(eid, "options", 0, NULL); - - TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx()); - struct poptOption *long_options = NULL; - int i, num_options = 0; - int opt_argc; - const char **opt_argv; - const char **opt_names = NULL; - const int BASE_OPTNUM = 0x100000; - - /* validate arguments */ - if (argc < 1 || argv[0]->type != MPR_TYPE_OBJECT) { - ejsSetErrorMsg(eid, "GetOptions invalid arguments"); - return -1; - } - - opt_argv = mprToArray(tmp_ctx, argv[0]); - opt_argc = str_list_length(opt_argv); - - long_options = talloc_array(tmp_ctx, struct poptOption, 1); - if (long_options == NULL) { - return -1; - } - - /* create the long_options array */ - for (i=1;i<argc;i++) { - const char *optstr = mprToString(argv[i]); - int t, opt_type = POPT_ARG_NONE; - const char *s; - if (argv[i]->type != MPR_TYPE_STRING) { - ejsSetErrorMsg(eid, "GetOptions string argument"); - return -1; - } - - long_options = talloc_realloc(tmp_ctx, long_options, - struct poptOption, num_options+2); - if (long_options == NULL) { - return -1; - } - ZERO_STRUCT(long_options[num_options]); - - /* see if its one of the special samba option tables */ - for (t=0;t<ARRAY_SIZE(tables);t++) { - if (strcmp(tables[t].name, optstr) == 0) { - break; - } - } - if (t < ARRAY_SIZE(tables)) { - opt_names = str_list_add(opt_names, optstr); - talloc_steal(tmp_ctx, opt_names); - long_options[num_options].argInfo = POPT_ARG_INCLUDE_TABLE; - long_options[num_options].arg = tables[t].table; - long_options[num_options].descrip = tables[t].description; - num_options++; - continue; - } - - s = strchr(optstr, '='); - if (s) { - char *name = talloc_strndup(tmp_ctx, optstr, (int)(s-optstr)); - opt_names = str_list_add(opt_names, name); - if (s[1] == 's') { - opt_type = POPT_ARG_STRING; - } else if (s[1] == 'i') { - opt_type = POPT_ARG_INT; - } else { - ejsSetErrorMsg(eid, "GetOptions invalid option type"); - return -1; - } - talloc_free(name); - } else { - opt_names = str_list_add(opt_names, optstr); - } - talloc_steal(tmp_ctx, opt_names); - if (strlen(opt_names[num_options]) == 1) { - long_options[num_options].shortName = opt_names[num_options][0]; - } else { - long_options[num_options].longName = opt_names[num_options]; - } - long_options[num_options].argInfo = opt_type; - long_options[num_options].val = num_options + BASE_OPTNUM; - num_options++; - } - - ZERO_STRUCT(long_options[num_options]); - - pc = poptGetContext("smbscript", opt_argc, opt_argv, long_options, 0); - - /* parse the options */ - while((opt = poptGetNextOpt(pc)) != -1) { - const char *arg; - - if (opt < BASE_OPTNUM || opt >= num_options + BASE_OPTNUM) { - char *err; - err = talloc_asprintf(tmp_ctx, "%s: %s", - poptBadOption(pc, POPT_BADOPTION_NOALIAS), - poptStrerror(opt)); - mprSetVar(options, "ERROR", mprString(err)); - talloc_free(tmp_ctx); - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - opt -= BASE_OPTNUM; - arg = poptGetOptArg(pc); - if (arg == NULL) { - mprSetVar(options, opt_names[opt], mprCreateBoolVar(1)); - } else if (long_options[opt].argInfo == POPT_ARG_INT) { - int v = strtol(arg, NULL, 0); - mprSetVar(options, opt_names[opt], mprCreateIntegerVar(v)); - } else { - mprSetVar(options, opt_names[opt], mprString(arg)); - } - } - - /* setup options.argv list */ - mprSetVar(options, "ARGV", mprList("ARGV", poptGetArgs(pc))); - - poptFreeContext(pc); - - talloc_free(tmp_ctx); - - /* setup methods */ - mprSetCFunction(options, "get_credentials", ejs_credentials_cmdline); - - return 0; -} - - - -/* - setup C functions that be called from ejs -*/ -void smb_setup_ejs_options(void) -{ - ejsDefineCFunction(-1, "GetOptions", ejs_GetOptions, NULL, MPR_VAR_SCRIPT_HANDLE); -} diff --git a/source4/scripting/ejs/smbcalls_string.c b/source4/scripting/ejs/smbcalls_string.c deleted file mode 100644 index 541303ff2d..0000000000 --- a/source4/scripting/ejs/smbcalls_string.c +++ /dev/null @@ -1,529 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide access to string functions - - Copyright (C) Andrew Tridgell 2005 - Copyright (C) Jelmer Vernooij 2005 (substr) - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" - -/* - usage: - var len = strlen(str); -*/ -static int ejs_strlen(MprVarHandle eid, int argc, char **argv) -{ - if (argc != 1) { - ejsSetErrorMsg(eid, "strlen invalid arguments"); - return -1; - } - mpr_Return(eid, mprCreateIntegerVar(strlen_m(argv[0]))); - return 0; -} - -/* - usage: - var s = strlower("UPPER"); -*/ -static int ejs_strlower(MprVarHandle eid, int argc, char **argv) -{ - char *s; - if (argc != 1) { - ejsSetErrorMsg(eid, "strlower invalid arguments"); - return -1; - } - s = strlower_talloc(mprMemCtx(), argv[0]); - mpr_Return(eid, mprString(s)); - talloc_free(s); - return 0; -} - -/* - usage: - var s = strupper("lower"); -*/ -static int ejs_strupper(MprVarHandle eid, int argc, char **argv) -{ - char *s; - if (argc != 1) { - ejsSetErrorMsg(eid, "strupper invalid arguments"); - return -1; - } - s = strupper_talloc(mprMemCtx(), argv[0]); - mpr_Return(eid, mprString(s)); - talloc_free(s); - return 0; -} - -/* - usage: - var s = strstr(string, substring); -*/ -static int ejs_strstr(MprVarHandle eid, int argc, char **argv) -{ - char *s; - if (argc != 2) { - ejsSetErrorMsg(eid, "strstr invalid arguments"); - return -1; - } - s = strstr(argv[0], argv[1]); - mpr_Return(eid, mprString(s)); - return 0; -} - -/* - usage: - var s = strspn(string, legal_chars_string); -*/ -static int ejs_strspn(MprVarHandle eid, int argc, char **argv) -{ - int len; - if (argc != 2) { - ejsSetErrorMsg(eid, "strspn invalid arguments"); - return -1; - } - len = strspn(argv[0], argv[1]); - mpr_Return(eid, mprCreateIntegerVar(len)); - return 0; -} - -/* - usage: - list = split(".", "a.foo.bar"); - list = split(".", "a.foo.bar", count); - - count is an optional count of how many splits to make - - NOTE: does not take a regular expression, unlike perl split() -*/ -static int ejs_split(MprVarHandle eid, int argc, struct MprVar **argv) -{ - const char *separator, *s; - char *p; - struct MprVar ret; - int count = 0, maxcount=0; - TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx()); - if (argc < 2 || - argv[0]->type != MPR_TYPE_STRING || - argv[1]->type != MPR_TYPE_STRING) { - ejsSetErrorMsg(eid, "split invalid arguments"); - return -1; - } - separator = mprToString(argv[0]); - s = mprToString(argv[1]); - if (argc == 3) { - maxcount = mprToInt(argv[2]); - } - - ret = mprArray("list"); - - while ((p = strstr(s, separator))) { - char *s2 = talloc_strndup(tmp_ctx, s, (int)(p-s)); - mprAddArray(&ret, count++, mprString(s2)); - talloc_free(s2); - s = p + strlen(separator); - if (maxcount != 0 && count >= maxcount) { - break; - } - } - if (*s) { - mprAddArray(&ret, count++, mprString(s)); - } - talloc_free(tmp_ctx); - mpr_Return(eid, ret); - return 0; -} - -/* - usage: - str = substr(orig[, start_offset[, length]]); - - special cases: - if start_offset < 0 then start_offset+=strlen(orig) - if length < 0 then length+=strlen(orig)-start_offset - - (as found in many other languages) -*/ -static int ejs_substr(MprVarHandle eid, int argc, struct MprVar **argv) -{ - int start_offset = 0; - int length = 0; - const char *orig; - char *target; - - if (argc < 1 || argc > 3 || - argv[0]->type != MPR_TYPE_STRING) { - ejsSetErrorMsg(eid, "substr invalid arguments"); - return -1; - } - - if (argc == 1) { - mpr_Return(eid, *argv[0]); - return 0; - } - - orig = mprToString(argv[0]); - start_offset = mprToInt(argv[1]); - length = strlen(orig); - if (start_offset < 0) start_offset += strlen(orig); - if (start_offset < 0 || start_offset > strlen(orig)) { - ejsSetErrorMsg(eid, "substr arg 2 out of bounds ([%s], %d)", orig, start_offset); - return -1; - } - - if (argc == 3) { - length = mprToInt(argv[2]); - if (length < 0) length += strlen(orig) - start_offset; - if (length < 0 || length+start_offset > strlen(orig)) { - ejsSetErrorMsg(eid, "substr arg 3 out of bounds ([%s], %d, %d)", orig, start_offset, length); - return -1; - } - } - - target = talloc_strndup(mprMemCtx(), orig+start_offset, length); - - mpr_Return(eid, mprString(target)); - - talloc_free(target); - - return 0; -} - -/* - usage: - str = join("DC=", list); -*/ -static int ejs_join(MprVarHandle eid, int argc, struct MprVar **argv) -{ - int i; - const char *separator; - char *ret = NULL; - const char **list; - TALLOC_CTX *tmp_ctx = talloc_new(mprMemCtx()); - if (argc != 2 || - argv[0]->type != MPR_TYPE_STRING || - argv[1]->type != MPR_TYPE_OBJECT) { - ejsSetErrorMsg(eid, "join invalid arguments"); - return -1; - } - - separator = mprToString(argv[0]); - list = mprToArray(tmp_ctx, argv[1]); - - if (list == NULL || list[0] == NULL) { - talloc_free(tmp_ctx); - mpr_Return(eid, mprString(NULL)); - return 0; - } - - ret = talloc_strdup(tmp_ctx, list[0]); - if (ret == NULL) { - goto failed; - } - for (i=1;list[i];i++) { - ret = talloc_asprintf_append_buffer(ret, "%s%s", separator, list[i]); - if (ret == NULL) { - goto failed; - } - } - mpr_Return(eid, mprString(ret)); - talloc_free(tmp_ctx); - return 0; -failed: - ejsSetErrorMsg(eid, "out of memory"); - return -1; -} - - -/* - blergh, C certainly makes this hard! - usage: - str = sprintf("i=%d s=%7s", 7, "foo"); -*/ -typedef char *(*_asprintf_append_t)(char *, const char *, ...); -static int ejs_sprintf(MprVarHandle eid, int argc, struct MprVar **argv) -{ - const char *format; - const char *p; - char *ret; - int a = 1; - _asprintf_append_t _asprintf_append; - TALLOC_CTX *tmp_ctx; - if (argc < 1 || argv[0]->type != MPR_TYPE_STRING) { - ejsSetErrorMsg(eid, "sprintf invalid arguments"); - return -1; - } - format = mprToString(argv[0]); - tmp_ctx = talloc_new(mprMemCtx()); - ret = talloc_strdup(tmp_ctx, ""); - - /* avoid all the format string warnings */ - _asprintf_append = (_asprintf_append_t)talloc_asprintf_append_buffer; - - /* - hackity hack ... - */ - while ((p = strchr(format, '%'))) { - char *fmt2; - int len, len_count=0; - char *tstr; - ret = talloc_asprintf_append_buffer(ret, "%*.*s", - (int)(p-format), (int)(p-format), - format); - if (ret == NULL) goto failed; - format += (int)(p-format); - len = strcspn(p+1, "dxuiofgGpXeEFcs%") + 1; - fmt2 = talloc_strndup(tmp_ctx, p, len+1); - if (fmt2 == NULL) goto failed; - len_count = count_chars(fmt2, '*'); - /* find the type string */ - tstr = &fmt2[len]; - while (tstr > fmt2 && isalpha((unsigned char)tstr[-1])) { - tstr--; - } - if (strcmp(tstr, "%") == 0) { - ret = talloc_asprintf_append_buffer(ret, "%%"); - if (ret == NULL) { - goto failed; - } - format += len+1; - continue; - } - if (len_count > 2 || - argc < a + len_count + 1) { - ejsSetErrorMsg(eid, "sprintf: not enough arguments for format"); - goto failed; - } -#define FMT_ARG(fn, type) do { \ - switch (len_count) { \ - case 0: \ - ret = _asprintf_append(ret, fmt2, \ - (type)fn(argv[a])); \ - break; \ - case 1: \ - ret = _asprintf_append(ret, fmt2, \ - (int)mprVarToNumber(argv[a]), \ - (type)fn(argv[a+1])); \ - break; \ - case 2: \ - ret = _asprintf_append(ret, fmt2, \ - (int)mprVarToNumber(argv[a]), \ - (int)mprVarToNumber(argv[a+1]), \ - (type)fn(argv[a+2])); \ - break; \ - } \ - a += len_count + 1; \ - if (ret == NULL) { \ - goto failed; \ - } \ -} while (0) - - if (strcmp(tstr, "s")==0) FMT_ARG(mprToString, const char *); - else if (strcmp(tstr, "c")==0) FMT_ARG(*mprToString, char); - else if (strcmp(tstr, "d")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "ld")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "lld")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "x")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "lx")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "llx")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "X")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "lX")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "llX")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "u")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "lu")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "llu")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "i")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "li")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "lli")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "o")==0) FMT_ARG(mprVarToNumber, int); - else if (strcmp(tstr, "lo")==0) FMT_ARG(mprVarToNumber, long); - else if (strcmp(tstr, "llo")==0) FMT_ARG(mprVarToNumber, long long); - else if (strcmp(tstr, "f")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "lf")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "g")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "lg")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "e")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "le")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "E")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "lE")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "F")==0) FMT_ARG(mprVarToFloat, double); - else if (strcmp(tstr, "lF")==0) FMT_ARG(mprVarToFloat, double); - else { - ejsSetErrorMsg(eid, "sprintf: unknown format string '%s'", fmt2); - goto failed; - } - format += len+1; - } - - ret = talloc_asprintf_append_buffer(ret, "%s", format); - mpr_Return(eid, mprString(ret)); - talloc_free(tmp_ctx); - return 0; - -failed: - talloc_free(tmp_ctx); - return -1; -} - -/* - used to build your own print function - str = vsprintf(args); -*/ -static int ejs_vsprintf(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar **args, *len, *v; - int i, ret, length; - if (argc != 1 || argv[0]->type != MPR_TYPE_OBJECT) { - ejsSetErrorMsg(eid, "vsprintf invalid arguments"); - return -1; - } - v = argv[0]; - len = mprGetProperty(v, "length", NULL); - if (len == NULL) { - ejsSetErrorMsg(eid, "vsprintf takes an array"); - return -1; - } - length = mprToInt(len); - args = talloc_array(mprMemCtx(), struct MprVar *, length); - if (args == NULL) { - return -1; - } - - for (i=0;i<length;i++) { - char idx[16]; - mprItoa(i, idx, sizeof(idx)); - args[i] = mprGetProperty(v, idx, NULL); - } - - ret = ejs_sprintf(eid, length, args); - talloc_free(args); - return ret; -} - - -/* - encode a string, replacing all non-alpha with %02x form -*/ -static int ejs_encodeURIComponent(MprVarHandle eid, int argc, char **argv) -{ - int i, j, count=0; - const char *s; - char *ret; - if (argc != 1) { - ejsSetErrorMsg(eid, "encodeURIComponent invalid arguments"); - return -1; - } - - s = argv[0]; - - for (i=0;s[i];i++) { - if (!isalnum(s[i])) count++; - } - - ret = talloc_array(mprMemCtx(), char, i + count*2 + 1); - if (ret == NULL) { - return -1; - } - for (i=j=0;s[i];i++,j++) { - if (!isalnum(s[i])) { - snprintf(ret+j, 4, "%%%02X", (unsigned)s[i]); - j += 2; - } else { - ret[j] = s[i]; - } - } - ret[j] = 0; - mpr_Return(eid, mprString(ret)); - talloc_free(ret); - return 0; -} - -/* - encode a string, replacing all non-alpha of %02x form -*/ -static int ejs_decodeURIComponent(MprVarHandle eid, int argc, char **argv) -{ - int i, j, count=0; - const char *s; - char *ret; - if (argc != 1) { - ejsSetErrorMsg(eid, "decodeURIComponent invalid arguments"); - return -1; - } - - s = argv[0]; - - ret = talloc_array(mprMemCtx(), char, strlen(s) + 1); - if (ret == NULL) { - return -1; - } - - for (i=j=0;s[i];i++,j++) { - if (s[i] == '%') { - unsigned c; - if (sscanf(s+i+1, "%02X", &c) != 1) { - ejsSetErrorMsg(eid, "decodeURIComponent bad format"); - return -1; - } - ret[j] = c; - i += 2; - } else { - ret[j] = s[i]; - } - if (!isalnum(s[i])) count++; - } - - ret[j] = 0; - mpr_Return(eid, mprString(ret)); - talloc_free(ret); - return 0; -} - -/* - initialise string ejs subsystem -*/ -static int ejs_string_init(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *obj = mprInitObject(eid, "string", argc, argv); - - mprSetCFunction(obj, "substr", ejs_substr); - mprSetStringCFunction(obj, "strlen", ejs_strlen); - mprSetStringCFunction(obj, "strlower", ejs_strlower); - mprSetStringCFunction(obj, "strupper", ejs_strupper); - mprSetStringCFunction(obj, "strstr", ejs_strstr); - mprSetStringCFunction(obj, "strspn", ejs_strspn); - mprSetCFunction(obj, "split", ejs_split); - mprSetCFunction(obj, "join", ejs_join); - mprSetCFunction(obj, "sprintf", ejs_sprintf); - mprSetCFunction(obj, "vsprintf", ejs_vsprintf); - mprSetStringCFunction(obj, "encodeURIComponent", ejs_encodeURIComponent); - mprSetStringCFunction(obj, "decodeURIComponent", ejs_decodeURIComponent); - - return 0; -} - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_string(void) -{ - ejsDefineCFunction(-1, "string_init", ejs_string_init, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbcalls_sys.c b/source4/scripting/ejs/smbcalls_sys.c deleted file mode 100644 index 00599a55bc..0000000000 --- a/source4/scripting/ejs/smbcalls_sys.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - provide access to system functions - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "scripting/ejs/smbcalls.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/ldb/include/ldb.h" -#include "system/time.h" -#include "system/network.h" -#include "lib/socket/netif.h" - -/* - return the list of configured network interfaces -*/ -static int ejs_sys_interfaces(MprVarHandle eid, int argc, struct MprVar **argv) -{ - int i, count; - struct MprVar ret = mprArray("interfaces"); - struct interface *ifaces; - - load_interfaces(NULL, lp_interfaces(mprLpCtx()), &ifaces); - - count = iface_count(ifaces); - for (i=0;i<count;i++) { - mprAddArray(&ret, i, mprString(iface_n_ip(ifaces, i))); - } - - talloc_free(ifaces); - mpr_Return(eid, ret); - return 0; -} - -/* - return the hostname from gethostname() -*/ -static int ejs_sys_hostname(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char name[200]; - if (gethostname(name, sizeof(name)-1) == -1) { - ejsSetErrorMsg(eid, "gethostname failed - %s", strerror(errno)); - return -1; - } - mpr_Return(eid, mprString(name)); - return 0; -} - - -/* - return current time as seconds and microseconds -*/ -static int ejs_sys_gettimeofday(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct timeval tv = timeval_current(); - struct MprVar v = mprObject("timeval"); - struct MprVar sec = mprCreateIntegerVar(tv.tv_sec); - struct MprVar usec = mprCreateIntegerVar(tv.tv_usec); - - mprCreateProperty(&v, "sec", &sec); - mprCreateProperty(&v, "usec", &usec); - mpr_Return(eid, v); - return 0; -} - -/* - return current time as a 64 bit nttime value -*/ -static int ejs_sys_nttime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct timeval tv = timeval_current(); - struct MprVar v = mprCreateNumberVar(timeval_to_nttime(&tv)); - mpr_Return(eid, v); - return 0; -} - -/* - return time as a 64 bit nttime value from a 32 bit time_t value -*/ -static int ejs_sys_unix2nttime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - NTTIME nt; - struct MprVar v; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_unix2nttime invalid arguments"); - return -1; - } - unix_to_nt_time(&nt, mprVarToNumber(argv[0])); - v = mprCreateNumberVar(nt); - mpr_Return(eid, v); - return 0; -} - -/* - return the GMT time represented by the struct tm argument, as a time_t value -*/ -static int ejs_sys_gmmktime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *o; - struct tm tm; - if (argc != 1 || !mprVarIsObject(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_gmmktime invalid arguments"); - return -1; - } - - o = argv[0]; -#define TM_EL(n) tm.n = mprVarToNumber(mprGetProperty(o, #n, NULL)) - TM_EL(tm_sec); - TM_EL(tm_min); - TM_EL(tm_hour); - TM_EL(tm_mday); - TM_EL(tm_mon); - TM_EL(tm_year); - TM_EL(tm_wday); - TM_EL(tm_yday); - TM_EL(tm_isdst); -#undef TM_EL - - mpr_Return(eid, mprCreateIntegerVar(mktime(&tm))); - return 0; -} - -/* - return the given time as a gmtime structure -*/ -static int ejs_sys_gmtime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - time_t t; - struct MprVar ret; - struct tm *tm; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_gmtime invalid arguments"); - return -1; - } - t = (time_t) mprVarToNumber(argv[0]); - tm = gmtime(&t); - if (tm == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - ret = mprObject("gmtime"); -#define TM_EL(n) mprSetVar(&ret, #n, mprCreateIntegerVar(tm->n)) - TM_EL(tm_sec); - TM_EL(tm_min); - TM_EL(tm_hour); - TM_EL(tm_mday); - TM_EL(tm_mon); - TM_EL(tm_year); - TM_EL(tm_wday); - TM_EL(tm_yday); - TM_EL(tm_isdst); -#undef TM_EL - - mpr_Return(eid, ret); - return 0; -} - -/* - return the given NT time as a time_t value -*/ -static int ejs_sys_nttime2unix(MprVarHandle eid, int argc, struct MprVar **argv) -{ - time_t t; - struct MprVar v; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_ntgmtime invalid arguments"); - return -1; - } - t = nt_time_to_unix(mprVarToNumber(argv[0])); - v = mprCreateNumberVar(t); - mpr_Return(eid, v); - return 0; -} - -/* - return the given NT time as a gmtime structure -*/ -static int ejs_sys_ntgmtime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - time_t t; - struct MprVar ret; - struct tm *tm; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_ntgmtime invalid arguments"); - return -1; - } - t = nt_time_to_unix(mprVarToNumber(argv[0])); - tm = gmtime(&t); - if (tm == NULL) { - mpr_Return(eid, mprCreateUndefinedVar()); - return 0; - } - ret = mprObject("gmtime"); -#define TM_EL(n) mprSetVar(&ret, #n, mprCreateIntegerVar(tm->n)) - TM_EL(tm_sec); - TM_EL(tm_min); - TM_EL(tm_hour); - TM_EL(tm_mday); - TM_EL(tm_mon); - TM_EL(tm_year); - TM_EL(tm_wday); - TM_EL(tm_yday); - TM_EL(tm_isdst); -#undef TM_EL - - mpr_Return(eid, ret); - return 0; -} - -/* - return a ldap time string from a nttime -*/ -static int ejs_sys_ldaptime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char *s; - time_t t; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_ldaptime invalid arguments"); - return -1; - } - t = nt_time_to_unix(mprVarToNumber(argv[0])); - s = ldb_timestring(mprMemCtx(), t); - mpr_Return(eid, mprString(s)); - talloc_free(s); - return 0; -} - -/* - return a http time string from a nttime -*/ -static int ejs_sys_httptime(MprVarHandle eid, int argc, struct MprVar **argv) -{ - char *s; - time_t t; - if (argc != 1 || !mprVarIsNumber(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_httptime invalid arguments"); - return -1; - } - t = nt_time_to_unix(mprVarToNumber(argv[0])); - s = http_timestring(mprMemCtx(), t); - mpr_Return(eid, mprString(s)); - talloc_free(s); - return 0; -} - -/* - unlink a file - ok = sys.unlink(fname); -*/ -static int ejs_sys_unlink(MprVarHandle eid, int argc, char **argv) -{ - int ret; - if (argc != 1) { - ejsSetErrorMsg(eid, "sys_unlink invalid arguments"); - return -1; - } - ret = unlink(argv[0]); - mpr_Return(eid, mprCreateBoolVar(ret == 0)); - return 0; -} - -/* - load a file as a string - usage: - string = sys.file_load(filename); -*/ -static int ejs_sys_file_load(MprVarHandle eid, int argc, char **argv) -{ - char *s; - if (argc != 1) { - ejsSetErrorMsg(eid, "sys_file_load invalid arguments"); - return -1; - } - - s = file_load(argv[0], NULL, mprMemCtx()); - mpr_Return(eid, mprString(s)); - talloc_free(s); - return 0; -} - -/* - save a file from a string - usage: - ok = sys.file_save(filename, str); -*/ -static int ejs_sys_file_save(MprVarHandle eid, int argc, char **argv) -{ - bool ret; - if (argc != 2) { - ejsSetErrorMsg(eid, "sys_file_save invalid arguments"); - return -1; - } - ret = file_save(argv[0], argv[1], strlen(argv[1])); - mpr_Return(eid, mprCreateBoolVar(ret)); - return 0; -} - -/* - mkdir() - usage: - ok = sys.mkdir(dirname, mode); -*/ -static int ejs_sys_mkdir(MprVarHandle eid, int argc, struct MprVar **argv) -{ - bool ret; - char *name; - if (argc != 2) { - ejsSetErrorMsg(eid, "sys_mkdir invalid arguments, need mkdir(dirname, mode)"); - return -1; - } - if (!mprVarIsString(argv[0]->type)) { - ejsSetErrorMsg(eid, "sys_mkdir dirname not a string"); - return -1; - } - if (!mprVarIsNumber(argv[1]->type)) { - ejsSetErrorMsg(eid, "sys_mkdir mode not a number"); - return -1; - } - mprVarToString(&name, 0, NULL, argv[0]); - ret = mkdir(name, mprVarToNumber(argv[1])); - mpr_Return(eid, mprCreateBoolVar(ret == 0)); - return 0; -} - - -/* - return fields of a stat() call -*/ -static struct MprVar mpr_stat(struct stat *st) -{ - struct MprVar ret; - ret = mprObject("stat"); - -#define ST_EL(n) mprSetVar(&ret, #n, mprCreateNumberVar(st->n)) - ST_EL(st_dev); - ST_EL(st_ino); - ST_EL(st_mode); - ST_EL(st_nlink); - ST_EL(st_uid); - ST_EL(st_gid); - ST_EL(st_rdev); - ST_EL(st_size); - ST_EL(st_blksize); - ST_EL(st_blocks); - ST_EL(st_atime); - ST_EL(st_mtime); - ST_EL(st_ctime); - - return ret; -} - -/* - usage: - var st = sys.stat(filename); - returns an object containing struct stat elements -*/ -static int ejs_sys_stat(MprVarHandle eid, int argc, char **argv) -{ - struct stat st; - /* validate arguments */ - if (argc != 1) { - ejsSetErrorMsg(eid, "sys.stat invalid arguments"); - return -1; - } - if (stat(argv[0], &st) != 0) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - mpr_Return(eid, mpr_stat(&st)); - } - return 0; -} - -/* - usage: - var st = sys.lstat(filename); - returns an object containing struct stat elements -*/ -static int ejs_sys_lstat(MprVarHandle eid, int argc, char **argv) -{ - struct stat st; - /* validate arguments */ - if (argc != 1) { - ejsSetErrorMsg(eid, "sys.stat invalid arguments"); - return -1; - } - if (lstat(argv[0], &st) != 0) { - mpr_Return(eid, mprCreateUndefinedVar()); - } else { - mpr_Return(eid, mpr_stat(&st)); - } - return 0; -} - -/* - bitwise AND - usage: - var z = sys.bitAND(x, 0x70); -*/ -static int ejs_sys_bitAND(MprVarHandle eid, int argc, struct MprVar **argv) -{ - int x, y, z; - - if (argc != 2 || - !mprVarIsNumber(argv[0]->type) || - !mprVarIsNumber(argv[1]->type)) { - ejsSetErrorMsg(eid, "bitand invalid arguments"); - return -1; - } - x = mprToInt(argv[0]); - y = mprToInt(argv[1]); - z = x & y; - - mpr_Return(eid, mprCreateIntegerVar(z)); - return 0; -} - -/* - bitwise OR - usage: - var z = sys.bitOR(x, 0x70); -*/ -static int ejs_sys_bitOR(MprVarHandle eid, int argc, struct MprVar **argv) -{ - int x, y, z; - - if (argc != 2 || - !mprVarIsNumber(argv[0]->type) || - !mprVarIsNumber(argv[1]->type)) { - ejsSetErrorMsg(eid, "bitand invalid arguments"); - return -1; - } - x = mprToInt(argv[0]); - y = mprToInt(argv[1]); - z = x | y; - - mpr_Return(eid, mprCreateIntegerVar(z)); - return 0; -} - -/* - initialise sys ejs subsystem -*/ -static int ejs_sys_init(MprVarHandle eid, int argc, struct MprVar **argv) -{ - struct MprVar *obj = mprInitObject(eid, "sys", argc, argv); - - mprSetCFunction(obj, "interfaces", ejs_sys_interfaces); - mprSetCFunction(obj, "hostname", ejs_sys_hostname); - mprSetCFunction(obj, "nttime", ejs_sys_nttime); - mprSetCFunction(obj, "gettimeofday", ejs_sys_gettimeofday); - mprSetCFunction(obj, "unix2nttime", ejs_sys_unix2nttime); - mprSetCFunction(obj, "gmmktime", ejs_sys_gmmktime); - mprSetCFunction(obj, "gmtime", ejs_sys_gmtime); - mprSetCFunction(obj, "nttime2unix", ejs_sys_nttime2unix); - mprSetCFunction(obj, "ntgmtime", ejs_sys_ntgmtime); - mprSetCFunction(obj, "ldaptime", ejs_sys_ldaptime); - mprSetCFunction(obj, "httptime", ejs_sys_httptime); - mprSetCFunction(obj, "mkdir", ejs_sys_mkdir); - mprSetStringCFunction(obj, "unlink", ejs_sys_unlink); - mprSetStringCFunction(obj, "file_load", ejs_sys_file_load); - mprSetStringCFunction(obj, "file_save", ejs_sys_file_save); - mprSetStringCFunction(obj, "stat", ejs_sys_stat); - mprSetStringCFunction(obj, "lstat", ejs_sys_lstat); - mprSetCFunction(obj, "bitAND", ejs_sys_bitAND); - mprSetCFunction(obj, "bitOR", ejs_sys_bitOR); - - return 0; -} - - -/* - setup C functions that be called from ejs -*/ -NTSTATUS smb_setup_ejs_system(void) -{ - ejsDefineCFunction(-1, "sys_init", ejs_sys_init, NULL, MPR_VAR_SCRIPT_HANDLE); - return NT_STATUS_OK; -} diff --git a/source4/scripting/ejs/smbscript.c b/source4/scripting/ejs/smbscript.c deleted file mode 100644 index db9fc9affa..0000000000 --- a/source4/scripting/ejs/smbscript.c +++ /dev/null @@ -1,129 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - Standalone client for ejs scripting. - - Copyright (C) Tim Potter <tpot@samba.org> 2005 - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "lib/appweb/ejs/ejs.h" -#include "lib/appweb/ejs/ejsInternal.h" -#include "scripting/ejs/smbcalls.h" -#include "auth/gensec/gensec.h" -#include "ldb/include/ldb.h" -#include "dynconfig/dynconfig.h" - -static EjsId eid; - -_NORETURN_ static void smbscript_ejs_exception(const char *reason) -{ - Ejs *ep = ejsPtr(eid); - ejsSetErrorMsg(eid, "%s", reason); - fprintf(stderr, "%s", ep->error); - exit(127); -} - -int main(int argc, const char **argv) -{ - EjsHandle handle = 0; - MprVar result; - char *emsg, *script; - size_t script_size; - TALLOC_CTX *mem_ctx = talloc_new(NULL); - const char **argv_list = NULL; - const char *fname; - struct MprVar *return_var; - int exit_status, i; - struct loadparm_context *lp_ctx; - - fault_setup(argv[0]); - - global_loadparm = lp_ctx = loadparm_init(talloc_autofree_context()); - - if (getenv("SMB_CONF_PATH")) { - lp_load(lp_ctx, getenv("SMB_CONF_PATH")); - } else { - lp_load(lp_ctx, dyn_CONFIGFILE); - } - - gensec_init(lp_ctx); - mprSetCtx(mem_ctx); - - - if (argc < 2) { - fprintf(stderr, "You must supply a script name\n"); - exit(1); - } - - fname = argv[1]; - - if (ejsOpen(NULL, NULL, NULL) != 0) { - fprintf(stderr, "smbscript: ejsOpen(): unable to initialise " - "EJS subsystem\n"); - exit(127); - } - - smb_setup_ejs_functions(smbscript_ejs_exception); - - if ((eid = ejsOpenEngine(handle, 0)) == (EjsId)-1) { - fprintf(stderr, "smbscript: ejsOpenEngine(): unable to " - "initialise an EJS engine\n"); - exit(127); - } - - /* setup ARGV[] in the ejs environment */ - for (i=1;argv[i];i++) { - argv_list = str_list_add(argv_list, argv[i]); - } - talloc_steal(mem_ctx, argv_list); - mprSetVar(ejsGetGlobalObject(eid), "ARGV", mprList("ARGV", argv_list)); - - /* load the script and advance past interpreter line*/ - script = file_load(fname, &script_size, mem_ctx); - - if (!script) { - fprintf(stderr, "Unable to load script from '%s'\n", fname); - exit(1); - } - - /* allow scriptable js */ - if (strncmp(script, "#!", 2) == 0) { - script += strcspn(script, "\r\n"); - script += strspn(script, "\r\n"); - } - /* and this copes with the ugly exec hack */ - if (strncmp(script, "exec ", 5) == 0) { - script += strcspn(script, "\r\n"); - script += strspn(script, "\r\n"); - } - - /* run the script */ - if (ejsEvalScript(eid, script, &result, &emsg) == -1) { - fprintf(stderr, "smbscript: ejsEvalScript(): %s\n", emsg); - exit(127); - } - - return_var = ejsGetReturnValue(eid); - exit_status = mprVarToNumber(return_var); - - ejsClose(); - - talloc_free(mem_ctx); - - return exit_status; -} diff --git a/source4/scripting/libjs/base.js b/source4/scripting/libjs/base.js deleted file mode 100644 index 790dfeb3e0..0000000000 --- a/source4/scripting/libjs/base.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - base js library functions - Copyright Andrew Tridgell 2005 - released under the GNU GPL version 3 or later -*/ - -if (global["HAVE_BASE_JS"] != undefined) { - return; -} -HAVE_BASE_JS=1 - -/* bring the string functions into the global frame */ -string_init(global); - -/* - an essential function! -*/ -function printf() -{ - print(vsprintf(arguments)); -} - -/* - substitute strings of the form ${NAME} in str, replacing - with substitutions from subobj -*/ -function substitute_var(str, subobj) -{ - var list = split("${", str); - var i; - for (i=1;i<list.length;i++) { - var list2 = split("}", list[i], 1); - if ((list2.length < 2) && (list2[0] + "}" != list[i])) { - return undefined; - } - var key = list2[0]; - var val; - if (typeof(subobj[key]) == "undefined") { - val = "${" + key + "}"; - } else if (typeof(subobj[key]) == "string") { - val = subobj[key]; - } else { - var fn = subobj[key]; - val = fn(key); - } - list2[0] = "" + val; - list[i] = join("", list2); - } - return join("", list); -} diff --git a/source4/scripting/python/misc_wrap.c b/source4/scripting/python/misc_wrap.c index 3aee83f72c..b669f3e801 100644 --- a/source4/scripting/python/misc_wrap.c +++ b/source4/scripting/python/misc_wrap.c @@ -2494,24 +2494,26 @@ SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int argnum, int flags) #define SWIGTYPE_p_ldb_ldif swig_types[8] #define SWIGTYPE_p_ldb_message swig_types[9] #define SWIGTYPE_p_ldb_message_element swig_types[10] -#define SWIGTYPE_p_ldb_result swig_types[11] -#define SWIGTYPE_p_loadparm_context swig_types[12] -#define SWIGTYPE_p_loadparm_service swig_types[13] -#define SWIGTYPE_p_long_long swig_types[14] -#define SWIGTYPE_p_param_context swig_types[15] -#define SWIGTYPE_p_param_opt swig_types[16] -#define SWIGTYPE_p_param_section swig_types[17] -#define SWIGTYPE_p_security_descriptor swig_types[18] -#define SWIGTYPE_p_security_token swig_types[19] -#define SWIGTYPE_p_short swig_types[20] -#define SWIGTYPE_p_signed_char swig_types[21] -#define SWIGTYPE_p_unsigned_char swig_types[22] -#define SWIGTYPE_p_unsigned_int swig_types[23] -#define SWIGTYPE_p_unsigned_long swig_types[24] -#define SWIGTYPE_p_unsigned_long_long swig_types[25] -#define SWIGTYPE_p_unsigned_short swig_types[26] -static swig_type_info *swig_types[28]; -static swig_module_info swig_module = {swig_types, 27, 0, 0, 0, 0}; +#define SWIGTYPE_p_ldb_module swig_types[11] +#define SWIGTYPE_p_ldb_parse_tree swig_types[12] +#define SWIGTYPE_p_ldb_result swig_types[13] +#define SWIGTYPE_p_loadparm_context swig_types[14] +#define SWIGTYPE_p_loadparm_service swig_types[15] +#define SWIGTYPE_p_long_long swig_types[16] +#define SWIGTYPE_p_param_context swig_types[17] +#define SWIGTYPE_p_param_opt swig_types[18] +#define SWIGTYPE_p_param_section swig_types[19] +#define SWIGTYPE_p_security_descriptor swig_types[20] +#define SWIGTYPE_p_security_token swig_types[21] +#define SWIGTYPE_p_short swig_types[22] +#define SWIGTYPE_p_signed_char swig_types[23] +#define SWIGTYPE_p_unsigned_char swig_types[24] +#define SWIGTYPE_p_unsigned_int swig_types[25] +#define SWIGTYPE_p_unsigned_long swig_types[26] +#define SWIGTYPE_p_unsigned_long_long swig_types[27] +#define SWIGTYPE_p_unsigned_short swig_types[28] +static swig_type_info *swig_types[30]; +static swig_module_info swig_module = {swig_types, 29, 0, 0, 0, 0}; #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) @@ -3340,6 +3342,8 @@ static swig_type_info _swigt__p_ldb_dn = {"_p_ldb_dn", "struct ldb_dn *|ldb_dn * static swig_type_info _swigt__p_ldb_ldif = {"_p_ldb_ldif", "struct ldb_ldif *|ldb_ldif *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_message = {"_p_ldb_message", "ldb_msg *|struct ldb_message *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_message_element = {"_p_ldb_message_element", "struct ldb_message_element *|ldb_message_element *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_ldb_module = {"_p_ldb_module", "struct ldb_module *|ldb_module *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_ldb_parse_tree = {"_p_ldb_parse_tree", "struct ldb_parse_tree *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_ldb_result = {"_p_ldb_result", "struct ldb_result *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_loadparm_context = {"_p_loadparm_context", "struct loadparm_context *|loadparm_context *", 0, 0, (void*)0, 0}; static swig_type_info _swigt__p_loadparm_service = {"_p_loadparm_service", "struct loadparm_service *|loadparm_service *", 0, 0, (void*)0, 0}; @@ -3369,6 +3373,8 @@ static swig_type_info *swig_type_initial[] = { &_swigt__p_ldb_ldif, &_swigt__p_ldb_message, &_swigt__p_ldb_message_element, + &_swigt__p_ldb_module, + &_swigt__p_ldb_parse_tree, &_swigt__p_ldb_result, &_swigt__p_loadparm_context, &_swigt__p_loadparm_service, @@ -3398,6 +3404,8 @@ static swig_cast_info _swigc__p_ldb_dn[] = { {&_swigt__p_ldb_dn, 0, 0, 0},{0, 0 static swig_cast_info _swigc__p_ldb_ldif[] = { {&_swigt__p_ldb_ldif, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_message[] = { {&_swigt__p_ldb_message, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_message_element[] = { {&_swigt__p_ldb_message_element, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_ldb_module[] = { {&_swigt__p_ldb_module, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_ldb_parse_tree[] = { {&_swigt__p_ldb_parse_tree, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_ldb_result[] = { {&_swigt__p_ldb_result, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_loadparm_context[] = { {&_swigt__p_loadparm_context, 0, 0, 0},{0, 0, 0, 0}}; static swig_cast_info _swigc__p_loadparm_service[] = { {&_swigt__p_loadparm_service, 0, 0, 0},{0, 0, 0, 0}}; @@ -3427,6 +3435,8 @@ static swig_cast_info *swig_cast_initial[] = { _swigc__p_ldb_ldif, _swigc__p_ldb_message, _swigc__p_ldb_message_element, + _swigc__p_ldb_module, + _swigc__p_ldb_parse_tree, _swigc__p_ldb_result, _swigc__p_loadparm_context, _swigc__p_loadparm_service, diff --git a/source4/selftest/output/plain.pm b/source4/selftest/output/plain.pm index 4bec4e0fdc..4e1e290534 100644 --- a/source4/selftest/output/plain.pm +++ b/source4/selftest/output/plain.pm @@ -48,10 +48,7 @@ sub start_testsuite($$) if ($self->{immediate}) { print "$out\n"; } else { - require Term::ReadKey; - my ($wchar, $hchar, $wpixels, $hpixels) = Term::ReadKey::GetTerminalSize(); - foreach (1..$wchar) { $out.= " "; } - print "\r".substr($out, 0, $wchar); + print "$out: "; } } @@ -94,6 +91,13 @@ sub end_testsuite($$$$$) $out .= $self->{test_output}->{$name}; } + if (not $self->{immediate}) { + if (not $unexpected) { + $out .= " ok\n"; + } else { + $out .= " " . uc($result) . "\n"; + } + } print $out; } @@ -120,6 +124,12 @@ sub end_test($$$$$) unless ($unexpected) { $self->{test_output}->{$self->{NAME}} = ""; + if (not $self->{immediate}) { + if ($result eq "failure") { print "f"; } + elsif ($result eq "skip") { print "s"; } + elsif ($result eq "success") { print "."; } + else { print "?($result)"; } + } return; } @@ -133,6 +143,13 @@ sub end_test($$$$$) print $self->{test_output}->{$self->{NAME}}; $self->{test_output}->{$self->{NAME}} = ""; } + + if (not $self->{immediate}) { + if ($result eq "error") { print "E"; } + elsif ($result eq "failure") { print "F"; } + elsif ($result eq "success") { print "S"; } + else { print "?"; } + } } sub summary($) diff --git a/source4/selftest/samba4_tests.sh b/source4/selftest/samba4_tests.sh index a72024e9e1..36d52fff5a 100755 --- a/source4/selftest/samba4_tests.sh +++ b/source4/selftest/samba4_tests.sh @@ -60,12 +60,8 @@ $incdir/../bin/smbtorture -V samba4srcdir=$incdir/.. samba4bindir=$samba4srcdir/bin -SCRIPTDIR=$samba4srcdir/../testprogs/ejs smb4torture="$samba4bindir/smbtorture $TORTURE_OPTIONS" -plantest "js.base" dc "$SCRIPTDIR/base.js" $CONFIGURATION -plantest "js.ldb" none "$SCRIPTDIR/ldb.js" `pwd` $CONFIGURATION -d 10 - # Simple tests for LDAP and CLDAP for options in "" "--option=socket:testnonblock=true" "-U\$USERNAME%\$PASSWORD --option=socket:testnonblock=true" "-U\$USERNAME%\$PASSWORD"; do @@ -287,10 +283,6 @@ for t in "BASE-RW1"; do plantest "ntvfs.simple.`normalize_testname $t`" dc $VALGRIND $smb4torture $ADDARGS //\$SERVER/simple -U"\$USERNAME"%"\$PASSWORD" $t done -DATADIR=$samba4srcdir/../testdata - -plantest "js.samba3sam" none $samba4bindir/smbscript $SCRIPTDIR/samba3sam.js $CONFIGURATION `pwd` $DATADIR/samba3/ - # Domain Member Tests plantest "rpc.echo against member server with local creds" member $VALGRIND $smb4torture ncacn_np:"\$NETBIOSNAME" -U"\$NETBIOSNAME/\$USERNAME"%"\$PASSWORD" RPC-ECHO "$*" @@ -300,6 +292,46 @@ plantest "rpc.samr.users against member server with local creds" member $VALGRIN plantest "rpc.samr.passwords against member server with local creds" member $VALGRIND $smb4torture ncacn_np:"\$NETBIOSNAME" -U"\$NETBIOSNAME/\$USERNAME"%"\$PASSWORD" "RPC-SAMR-PASSWORDS" "$*" plantest "blackbox.smbclient against member server with local creds" member $samba4srcdir/client/tests/test_smbclient.sh "\$NETBIOSNAME" "\$USERNAME" "\$PASSWORD" "\$NETBIOSNAME" "$PREFIX" +# Tests SMB signing + +for mech in \ + "-k no" \ + "-k no --option=usespnego=no" \ + "-k no --option=gensec:spengo=no" \ + "-k yes" \ + "-k yes --option=gensec:fake_gssapi_krb5=yes --option=gensec:gssapi_krb5=no"; do + for signing in \ + "--signing=on" \ + "--signing=required"; do + + signoptions="$mech $signing" + name="smb.signing on with $signoptions" + plantest "$name" dc $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp $signoptions -U"\$USERNAME"%"\$PASSWORD" BASE-XCOPY "$*" + done +done + +for mech in \ + "-k no" \ + "-k no --option=usespnego=no" \ + "-k no --option=gensec:spengo=no" \ + "-k yes" \ + "-k yes --option=gensec:fake_gssapi_krb5=yes --option=gensec:gssapi_krb5=no"; do + signoptions="$mech --signing=off" + name="smb.signing on with $signoptions" + plantest "$name domain-creds" member $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp $signoptions -U"\$DC_USERNAME"%"\$DC_PASSWORD" BASE-XCOPY "$*" +done +for mech in \ + "-k no" \ + "-k no --option=usespnego=no" \ + "-k no --option=gensec:spengo=no"; do + signoptions="$mech --signing=off" + name="smb.signing on with $signoptions" + plantest "$name local-creds" member $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp $signoptions -U"\$NETBIOSNAME\\\\\$USERNAME"%"\$PASSWORD" BASE-XCOPY "$*" +done +plantest "--signing=yes anon" dc $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp -k no --signing=yes -U% BASE-XCOPY "$*" +plantest "--signing=required anon" dc $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp -k no --signing=required -U% BASE-XCOPY "$*" +plantest "--signing=no anon" member $VALGRIND $smb4torture //"\$NETBIOSNAME"/tmp -k no --signing=no -U% BASE-XCOPY "$*" + NBT_TESTS=`$smb4torture --list | grep "^NBT-" | xargs` for t in $NBT_TESTS; do diff --git a/source4/selftest/selftest.pl b/source4/selftest/selftest.pl index e86ccbe468..51a354c7a4 100755 --- a/source4/selftest/selftest.pl +++ b/source4/selftest/selftest.pl @@ -417,8 +417,6 @@ sub prefix_pathvar($$) } } prefix_pathvar("PKG_CONFIG_PATH", "$old_pwd/bin/pkgconfig"); -# Required for smbscript: -prefix_pathvar("PATH", "$old_pwd/bin"); prefix_pathvar("PYTHONPATH", "$old_pwd/bin/python"); if ($opt_socket_wrapper_keep_pcap) { @@ -576,7 +574,6 @@ sub write_clientconf($$) } print CF " private dir = $prefix_abs/client/private - js include = $srcdir_abs/scripting/libjs name resolve order = bcast panic action = $srcdir_abs/script/gdb_backtrace \%PID\% \%PROG\% max xmit = 32K diff --git a/source4/selftest/target/Samba4.pm b/source4/selftest/target/Samba4.pm index 8835f69c6c..992e251c35 100644 --- a/source4/selftest/target/Samba4.pm +++ b/source4/selftest/target/Samba4.pm @@ -555,7 +555,6 @@ sub provision($$$$$$) lock dir = $lockdir setup directory = $self->{setupdir} modules dir = $self->{bindir}/modules - js include = $srcdir/scripting/libjs winbindd socket directory = $winbindd_socket_dir winbindd privileged socket directory = $winbindd_privileged_socket_dir ntp signd socket directory = $ntp_signd_socket_dir diff --git a/source4/smb_server/config.mk b/source4/smb_server/config.mk index e11968a100..d1ec6d49e8 100644 --- a/source4/smb_server/config.mk +++ b/source4/smb_server/config.mk @@ -9,6 +9,14 @@ SERVICE_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_server.o $(eval $(call proto_header_template,$(smb_serversrcdir)/service_smb_proto.h,$(SERVICE_SMB_OBJ_FILES:.o=.c))) +# samba3 SMB server subsystem +# +[MODULE::SERVICE_SAMBA3_SMB] +INIT_FUNCTION = server_service_samba3_smb_init +SUBSYSTEM = smbd + +SERVICE_SAMBA3_SMB_OBJ_FILES = $(smb_serversrcdir)/smb_samba3.o + ####################### # Start SUBSYSTEM SMB [SUBSYSTEM::SMB_SERVER] diff --git a/source4/smb_server/smb/sesssetup.c b/source4/smb_server/smb/sesssetup.c index f45cbf1756..a12bbd5cec 100644 --- a/source4/smb_server/smb/sesssetup.c +++ b/source4/smb_server/smb/sesssetup.c @@ -193,16 +193,6 @@ static void sesssetup_nt1_send(struct auth_check_password_request *areq, goto done; } - /* Force check of the request packet, now we know the session key */ - smbsrv_signing_check_incoming(req); -/* TODO: why don't we check the result here? */ - - /* Unfortunetly win2k3 as a client doesn't sign the request - * packet here, so we have to force signing to start again */ - - smbsrv_signing_restart(req->smb_conn, &session_info->session_key, &sess->nt1.in.password2, - session_info->server_info->authenticated); - done: status = NT_STATUS_OK; failed: @@ -321,13 +311,8 @@ static void sesssetup_spnego_send(struct gensec_update_request *greq, void *priv if (!NT_STATUS_IS_OK(status)) goto failed; skey_status = gensec_session_key(smb_sess->gensec_ctx, &session_key); - if (NT_STATUS_IS_OK(skey_status) && - smbsrv_setup_signing(req->smb_conn, &session_key, NULL)) { - /* Force check of the request packet, now we know the session key */ - smbsrv_signing_check_incoming(req); - - smbsrv_signing_restart(req->smb_conn, &session_key, NULL, - session_info->server_info->authenticated); + if (NT_STATUS_IS_OK(skey_status)) { + smbsrv_setup_signing(req->smb_conn, &session_key, NULL); } /* Ensure this is marked as a 'real' vuid, not one diff --git a/source4/smb_server/smb/signing.c b/source4/smb_server/smb/signing.c index ee4531c8f6..0b5cf56fdb 100644 --- a/source4/smb_server/smb/signing.c +++ b/source4/smb_server/smb/signing.c @@ -75,30 +75,6 @@ bool smbsrv_setup_signing(struct smbsrv_connection *smb_conn, &smb_conn->signing, session_key, response); } -void smbsrv_signing_restart(struct smbsrv_connection *smb_conn, - DATA_BLOB *session_key, - DATA_BLOB *response, - bool authenticated_session) -{ - if (!smb_conn->signing.seen_valid) { - DEBUG(5, ("Client did not send a valid signature on " - "SPNEGO session setup - ignored, expect good next time\n")); - /* force things back on (most clients do not sign this packet)... */ - smbsrv_setup_signing(smb_conn, session_key, response); - smb_conn->signing.next_seq_num = 2; - - /* If mandetory_signing is set, and this was an authenticated logon, then force on */ - if (smb_conn->signing.mandatory_signing && authenticated_session) { - DEBUG(5, ("Configured for mandatory signing, 'good packet seen' forced on\n")); - /* if this is mandatory, then - * pretend we have seen a - * valid packet, so we don't - * turn it off */ - smb_conn->signing.seen_valid = true; - } - } -} - bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) { smb_conn->signing.mac_key = data_blob(NULL, 0); @@ -118,10 +94,19 @@ bool smbsrv_init_signing(struct smbsrv_connection *smb_conn) smb_conn->signing.mandatory_signing = true; break; case SMB_SIGNING_AUTO: + /* If we are a domain controller, SMB signing is + * really important, as it can prevent a number of + * attacks on communications between us and the + * clients */ + if (lp_server_role(smb_conn->lp_ctx) == ROLE_DOMAIN_CONTROLLER) { smb_conn->signing.allow_smb_signing = true; smb_conn->signing.mandatory_signing = true; } else { + /* However, it really sucks (no sendfile, CPU + * overhead) performance-wise when used on a + * file server, so disable it by default (auto + * is the default) on non-DCs */ smb_conn->signing.allow_smb_signing = false; } break; diff --git a/source4/smb_server/smb_samba3.c b/source4/smb_server/smb_samba3.c new file mode 100644 index 0000000000..7b3229892f --- /dev/null +++ b/source4/smb_server/smb_samba3.c @@ -0,0 +1,174 @@ +/* + Unix SMB/CIFS implementation. + + process incoming connections and fork a samba3 in inetd mode + + Copyright (C) Stefan Metzmacher 2008 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "smbd/service_task.h" +#include "smbd/service_stream.h" +#include "smbd/service.h" +#include "lib/messaging/irpc.h" +#include "lib/stream/packet.h" +#include "lib/socket/socket.h" +#include "libcli/smb2/smb2.h" +#include "smb_server/smb2/smb2_server.h" +#include "system/network.h" +#include "lib/socket/netif.h" +#include "param/share.h" +#include "dsdb/samdb/samdb.h" +#include "param/param.h" +#include "dynconfig/dynconfig.h" +#include "smbd/process_model.h" + +/* + initialise a server_context from a open socket and register a event handler + for reading from that socket +*/ +static void samba3_smb_accept(struct stream_connection *conn) +{ + int i; + int fd = socket_get_fd(conn->socket); + const char *prog; + char *argv[2]; + char *reason; + + close(0); + close(1); + dup2(fd, 0); + dup2(fd, 1); + for (i=2;i<256;i++) { + close(i); + } + + prog = lp_parm_string(conn->lp_ctx, NULL, "samba3", "smbd"); + + if (prog == NULL) { + argv[0] = talloc_asprintf(conn, "%s/%s", dyn_BINDIR, "smbd3"); + } + else { + argv[0] = talloc_strdup(conn, prog); + } + + if (argv[0] == NULL) { + stream_terminate_connection(conn, "out of memory"); + return; + } + argv[1] = NULL; + + execve(argv[0], argv, environ); + + /* + * Should never get here + */ + reason = talloc_asprintf(conn, "Could not execute %s", argv[0]); + if (reason == NULL) { + stream_terminate_connection(conn, "out of memory"); + return; + } + stream_terminate_connection(conn, reason); + talloc_free(reason); +} + +static const struct stream_server_ops samba3_smb_stream_ops = { + .name = "samba3", + .accept_connection = samba3_smb_accept, +}; + +/* + setup a listening socket on all the SMB ports for a particular address +*/ +static NTSTATUS samba3_add_socket(struct event_context *event_context, + struct loadparm_context *lp_ctx, + const struct model_ops *model_ops, + const char *address) +{ + const char **ports = lp_smb_ports(lp_ctx); + int i; + NTSTATUS status; + + for (i=0;ports[i];i++) { + uint16_t port = atoi(ports[i]); + if (port == 0) continue; + status = stream_setup_socket(event_context, lp_ctx, + model_ops, &samba3_smb_stream_ops, + "ip", address, &port, + lp_socket_options(lp_ctx), + NULL); + NT_STATUS_NOT_OK_RETURN(status); + } + + return NT_STATUS_OK; +} + + +/* + open the smb server sockets +*/ +static void samba3_smb_task_init(struct task_server *task) +{ + NTSTATUS status; + const struct model_ops *model_ops; + + model_ops = process_model_startup(task->event_ctx, "standard"); + + if (model_ops == NULL) { + goto failed; + } + + task_server_set_title(task, "task[samba3_smb]"); + + if (lp_interfaces(task->lp_ctx) + && lp_bind_interfaces_only(task->lp_ctx)) { + int num_interfaces; + int i; + struct interface *ifaces; + + load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces); + + num_interfaces = iface_count(ifaces); + + /* We have been given an interfaces line, and been + told to only bind to those interfaces. Create a + socket per interface and bind to only these. + */ + for(i = 0; i < num_interfaces; i++) { + const char *address = iface_n_ip(ifaces, i); + status = samba3_add_socket(task->event_ctx, + task->lp_ctx, + model_ops, address); + if (!NT_STATUS_IS_OK(status)) goto failed; + } + } else { + /* Just bind to lp_socket_address() (usually 0.0.0.0) */ + status = samba3_add_socket(task->event_ctx, task->lp_ctx, + model_ops, + lp_socket_address(task->lp_ctx)); + if (!NT_STATUS_IS_OK(status)) goto failed; + } + + return; +failed: + task_server_terminate(task, "Failed to startup samba3 smb task"); +} + +/* called at smbd startup - register ourselves as a server service */ +NTSTATUS server_service_samba3_smb_init(void) +{ + return register_server_service("samba3_smb", samba3_smb_task_init); +} diff --git a/source4/smbd/process_model.c b/source4/smbd/process_model.c index 704e6cc7a2..d99d517d9f 100644 --- a/source4/smbd/process_model.c +++ b/source4/smbd/process_model.c @@ -22,6 +22,8 @@ #include "smbd/process_model.h" #include "param/param.h" +static const struct model_ops *process_model_byname(const char *name); + /* setup the events for the chosen process model */ @@ -99,7 +101,7 @@ _PUBLIC_ NTSTATUS process_model_init(struct loadparm_context *lp_ctx) /* return the operations structure for a named backend of the specified type */ -_PUBLIC_ const struct model_ops *process_model_byname(const char *name) +static const struct model_ops *process_model_byname(const char *name) { int i; diff --git a/source4/smbd/process_model.h b/source4/smbd/process_model.h index b545212091..a9b33a4725 100644 --- a/source4/smbd/process_model.h +++ b/source4/smbd/process_model.h @@ -78,7 +78,6 @@ struct process_model_critical_sizes { extern const struct model_ops single_ops; const struct model_ops *process_model_startup(struct event_context *ev, const char *model); -const struct model_ops *process_model_byname(const char *name); NTSTATUS register_process_model(const void *_ops); NTSTATUS process_model_init(struct loadparm_context *lp_ctx); diff --git a/source4/smbd/server.c b/source4/smbd/server.c index 5bd5568913..cf25693fbe 100644 --- a/source4/smbd/server.c +++ b/source4/smbd/server.c @@ -199,6 +199,7 @@ static int binary_smbd_main(const char *binary_name, int argc, const char *argv[ extern NTSTATUS server_service_drepl_init(void); extern NTSTATUS server_service_rpc_init(void); extern NTSTATUS server_service_ntp_signd_init(void); + extern NTSTATUS server_service_samba3_smb_init(void); init_module_fn static_init[] = { STATIC_smbd_MODULES }; init_module_fn *shared_init; struct event_context *event_ctx; diff --git a/source4/torture/nbt/nbt.c b/source4/torture/nbt/nbt.c index 7d35fc856a..aee0c54358 100644 --- a/source4/torture/nbt/nbt.c +++ b/source4/torture/nbt/nbt.c @@ -18,7 +18,7 @@ */ #include "includes.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "torture/torture.h" #include "torture/nbt/proto.h" #include "torture/smbtorture.h" diff --git a/source4/torture/nbt/query.c b/source4/torture/nbt/query.c index 80027a1b68..b1b703a3c2 100644 --- a/source4/torture/nbt/query.c +++ b/source4/torture/nbt/query.c @@ -33,7 +33,7 @@ struct result_struct { static void increment_handler(struct nbt_name_request *req) { - struct result_struct *v = talloc_get_type(req->async.private, struct result_struct); + struct result_struct *v = talloc_get_type(req->async.private_data, struct result_struct); if (req->state != NBT_REQUEST_DONE) { v->num_fail++; } else { @@ -76,7 +76,7 @@ static bool bench_namequery(struct torture_context *tctx) req = nbt_name_query_send(nbtsock, &io); torture_assert(tctx, req != NULL, "Failed to setup request!"); req->async.fn = increment_handler; - req->async.private = result; + req->async.private_data = result; num_sent++; if (num_sent % 1000 == 0) { if (torture_setting_bool(tctx, "progress", true)) { diff --git a/source4/torture/nbt/winsbench.c b/source4/torture/nbt/winsbench.c index a0d90fb653..bea3d4f9cf 100644 --- a/source4/torture/nbt/winsbench.c +++ b/source4/torture/nbt/winsbench.c @@ -56,7 +56,7 @@ static struct nbt_name generate_name(TALLOC_CTX *tctx, int idx) static void register_handler(struct nbt_name_request *req) { - struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state); + struct idx_state *istate = talloc_get_type(req->async.private_data, struct idx_state); struct wins_state *state = istate->state; struct nbt_name_register io; NTSTATUS status; @@ -100,7 +100,7 @@ static void generate_register(struct nbt_name_socket *nbtsock, struct wins_state req = nbt_name_register_send(nbtsock, &io); req->async.fn = register_handler; - req->async.private = istate; + req->async.private_data = istate; talloc_free(tmp_ctx); } @@ -108,7 +108,7 @@ static void generate_register(struct nbt_name_socket *nbtsock, struct wins_state static void release_handler(struct nbt_name_request *req) { - struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state); + struct idx_state *istate = talloc_get_type(req->async.private_data, struct idx_state); struct wins_state *state = istate->state; struct nbt_name_release io; NTSTATUS status; @@ -150,7 +150,7 @@ static void generate_release(struct nbt_name_socket *nbtsock, struct wins_state req = nbt_name_release_send(nbtsock, &io); req->async.fn = release_handler; - req->async.private = istate; + req->async.private_data = istate; talloc_free(tmp_ctx); } @@ -158,7 +158,7 @@ static void generate_release(struct nbt_name_socket *nbtsock, struct wins_state static void query_handler(struct nbt_name_request *req) { - struct idx_state *istate = talloc_get_type(req->async.private, struct idx_state); + struct idx_state *istate = talloc_get_type(req->async.private_data, struct idx_state); struct wins_state *state = istate->state; struct nbt_name_query io; NTSTATUS status; @@ -197,7 +197,7 @@ static void generate_query(struct nbt_name_socket *nbtsock, struct wins_state *s req = nbt_name_query_send(nbtsock, &io); req->async.fn = query_handler; - req->async.private = istate; + req->async.private_data = istate; talloc_free(tmp_ctx); } diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c index 6b600bd7cd..b688f1fbfe 100644 --- a/source4/torture/nbt/winsreplication.c +++ b/source4/torture/nbt/winsreplication.c @@ -9457,7 +9457,7 @@ static void test_conflict_owned_active_vs_replica_handler_query(struct nbt_name_ struct nbt_name *name; struct nbt_name_packet *rep_packet; struct test_conflict_owned_active_vs_replica_struct *rec = - (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private; + (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private_data; _NBT_ASSERT(req_packet->qdcount, 1); _NBT_ASSERT(req_packet->questions[0].question_type, NBT_QTYPE_NETBIOS); @@ -9556,7 +9556,7 @@ static void test_conflict_owned_active_vs_replica_handler_release( struct nbt_name *name; struct nbt_name_packet *rep_packet; struct test_conflict_owned_active_vs_replica_struct *rec = - (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private; + (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private_data; _NBT_ASSERT(req_packet->qdcount, 1); _NBT_ASSERT(req_packet->questions[0].question_type, NBT_QTYPE_NETBIOS); @@ -9610,7 +9610,7 @@ static void test_conflict_owned_active_vs_replica_handler(struct nbt_name_socket struct socket_address *src) { struct test_conflict_owned_active_vs_replica_struct *rec = - (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private; + (struct test_conflict_owned_active_vs_replica_struct *)nbtsock->incoming.private_data; rec->defend.ret = false; diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c index 5ec2c29a20..2522062696 100644 --- a/source4/torture/rpc/netlogon.c +++ b/source4/torture/rpc/netlogon.c @@ -250,6 +250,10 @@ static bool test_SetupCredentials3(struct dcerpc_pipe *p, struct torture_context torture_assert(tctx, creds_client_check(creds, &credentials3), "Credential chaining failed"); torture_comment(tctx, "negotiate_flags=0x%08x\n", negotiate_flags); + + /* Prove that requesting a challenge again won't break it */ + status = dcerpc_netr_ServerReqChallenge(p, tctx, &r); + torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge"); *creds_out = creds; return true; diff --git a/source4/torture/rpc/remote_pac.c b/source4/torture/rpc/remote_pac.c index 6419e40014..a4111d1c3e 100644 --- a/source4/torture/rpc/remote_pac.c +++ b/source4/torture/rpc/remote_pac.c @@ -68,8 +68,6 @@ static bool test_PACVerify(struct torture_context *tctx, TALLOC_CTX *tmp_ctx = talloc_new(tctx); - int i; - torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed"); if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS, @@ -118,16 +116,12 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } - if (client_to_server.length == 0) { - break; - } - status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed"); } - if (server_to_client.length == 0) { + if (NT_STATUS_IS_OK(status)) { break; } } while (1); @@ -137,7 +131,6 @@ static bool test_PACVerify(struct torture_context *tctx, status = gensec_session_info(gensec_server_context, &session_info); torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed"); - pac_wrapped_struct.MessageType = 0x3; pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; @@ -207,51 +200,6 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); - /* This will break message type, check that however we still get NT_STATUS_OK */ - for (i=0; i < 256; i++) { - pac_wrapped_struct.MessageType = i; - pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; - pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; - pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; - pac_wrapped_struct.ChecksumAndSignature = payload - = data_blob_talloc(tmp_ctx, NULL, - pac_wrapped_struct.ChecksumLength - + pac_wrapped_struct.SignatureLength); - memcpy(&payload.data[0], - session_info->server_info->pac_srv_sig.signature.data, - pac_wrapped_struct.ChecksumLength); - memcpy(&payload.data[pac_wrapped_struct.ChecksumLength], - session_info->server_info->pac_kdc_sig.signature.data, - pac_wrapped_struct.SignatureLength); - - ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct, - (ndr_push_flags_fn_t)ndr_push_PAC_Validate); - torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed"); - - torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption"); - creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length); - - generic.length = pac_wrapped.length; - generic.data = pac_wrapped.data; - - ZERO_STRUCT(auth2); - creds_client_authenticator(creds, &auth); - r.in.credential = &auth; - r.in.return_authenticator = &auth2; - r.in.logon_level = NetlogonGenericInformation; - r.in.logon.generic = &generic; - r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p)); - r.in.computer_name = cli_credentials_get_workstation(credentials); - r.in.validation_level = NetlogonValidationGenericInfo2; - - status = dcerpc_netr_LogonSamLogon(p, tctx, &r); - - torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed"); - - torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), - "Credential chaining failed"); - } - /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */ generic.length--; @@ -272,7 +220,6 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); - pac_wrapped_struct.MessageType = 0x3; pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; @@ -318,8 +265,6 @@ static bool test_PACVerify(struct torture_context *tctx, torture_assert(tctx, creds_client_check(creds, &r.out.return_authenticator->cred), "Credential chaining failed"); - - pac_wrapped_struct.MessageType = 0x3; pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length; pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type; pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length; diff --git a/source4/torture/rpc/winreg.c b/source4/torture/rpc/winreg.c index 8b602ef652..898813f807 100644 --- a/source4/torture/rpc/winreg.c +++ b/source4/torture/rpc/winreg.c @@ -80,6 +80,7 @@ static bool test_NotifyChangeKeyValue(struct dcerpc_pipe *p, { struct winreg_NotifyChangeKeyValue r; + ZERO_STRUCT(r); r.in.handle = handle; r.in.watch_subtree = true; r.in.notify_filter = 0; @@ -109,6 +110,7 @@ static bool test_CreateKey(struct dcerpc_pipe *p, struct torture_context *tctx, struct policy_handle newhandle; enum winreg_CreateAction action_taken = 0; + ZERO_STRUCT(r); r.in.handle = handle; r.out.new_handle = &newhandle; init_winreg_String(&r.in.name, name); @@ -163,6 +165,7 @@ static bool test_CreateKey_sd(struct dcerpc_pipe *p, secbuf.length = sdblob.length-10; secbuf.inherit = 0; + ZERO_STRUCT(r); r.in.handle = handle; r.out.new_handle = newhandle; init_winreg_String(&r.in.name, name); @@ -317,6 +320,7 @@ static bool test_CloseKey(struct dcerpc_pipe *p, struct torture_context *tctx, { struct winreg_CloseKey r; + ZERO_STRUCT(r); r.in.handle = r.out.handle = handle; torture_assert_ntstatus_ok(tctx, dcerpc_winreg_CloseKey(p, tctx, &r), @@ -332,6 +336,7 @@ static bool test_FlushKey(struct dcerpc_pipe *p, struct torture_context *tctx, { struct winreg_FlushKey r; + ZERO_STRUCT(r); r.in.handle = handle; torture_assert_ntstatus_ok(tctx, dcerpc_winreg_FlushKey(p, tctx, &r), @@ -351,6 +356,7 @@ static bool _test_OpenKey(struct dcerpc_pipe *p, struct torture_context *tctx, { struct winreg_OpenKey r; + ZERO_STRUCT(r); r.in.parent_handle = hive_handle; init_winreg_String(&r.in.keyname, keyname); r.in.unknown = 0x00000000; @@ -384,6 +390,7 @@ static bool test_Cleanup(struct dcerpc_pipe *p, struct torture_context *tctx, { struct winreg_DeleteKey r; + ZERO_STRUCT(r); r.in.handle = handle; init_winreg_String(&r.in.key, key); @@ -1435,6 +1442,7 @@ static bool test_EnumKey(struct dcerpc_pipe *p, struct torture_context *tctx, class.name = ""; class.size = 1024; + ZERO_STRUCT(r); r.in.handle = handle; r.in.enum_index = 0; r.in.name = &name; @@ -1486,6 +1494,7 @@ static bool test_QueryMultipleValues(struct dcerpc_pipe *p, NTSTATUS status; uint32_t bufsize=0; + ZERO_STRUCT(r); r.in.key_handle = handle; r.in.values = r.out.values = talloc_array(tctx, struct QueryMultipleValue, 1); r.in.values[0].name = talloc(tctx, struct winreg_String); @@ -1527,6 +1536,7 @@ static bool test_QueryValue(struct dcerpc_pipe *p, uint32_t offered = 0xfff; uint32_t zero = 0; + ZERO_STRUCT(r); r.in.handle = handle; r.in.data = NULL; r.in.value_name.name = valuename; @@ -1558,6 +1568,7 @@ static bool test_EnumValue(struct dcerpc_pipe *p, struct torture_context *tctx, name.name = ""; name.size = 1024; + ZERO_STRUCT(r); r.in.handle = handle; r.in.enum_index = 0; r.in.name = &name; @@ -1594,6 +1605,7 @@ static bool test_AbortSystemShutdown(struct dcerpc_pipe *p, struct winreg_AbortSystemShutdown r; uint16_t server = 0x0; + ZERO_STRUCT(r); r.in.server = &server; torture_assert_ntstatus_ok(tctx, @@ -1612,6 +1624,7 @@ static bool test_InitiateSystemShutdown(struct torture_context *tctx, struct winreg_InitiateSystemShutdown r; uint16_t hostname = 0x0; + ZERO_STRUCT(r); r.in.hostname = &hostname; r.in.message = talloc(tctx, struct lsa_StringLarge); init_lsa_StringLarge(r.in.message, "spottyfood"); @@ -1636,6 +1649,7 @@ static bool test_InitiateSystemShutdownEx(struct torture_context *tctx, struct winreg_InitiateSystemShutdownEx r; uint16_t hostname = 0x0; + ZERO_STRUCT(r); r.in.hostname = &hostname; r.in.message = talloc(tctx, struct lsa_StringLarge); init_lsa_StringLarge(r.in.message, "spottyfood"); @@ -1694,6 +1708,7 @@ static bool test_Open_Security(struct torture_context *tctx, winreg_open_fn open_fn = userdata; + ZERO_STRUCT(r); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; @@ -1767,6 +1782,7 @@ static bool test_Open(struct torture_context *tctx, struct dcerpc_pipe *p, winreg_open_fn open_fn = userdata; + ZERO_STRUCT(r); r.in.system_name = 0; r.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED; r.out.handle = &handle; diff --git a/source4/utils/nmblookup.c b/source4/utils/nmblookup.c index a74ab5a42e..0d98cb99de 100644 --- a/source4/utils/nmblookup.c +++ b/source4/utils/nmblookup.c @@ -29,7 +29,7 @@ #include "system/locale.h" #include "lib/socket/netif.h" #include "librpc/gen_ndr/nbt.h" -#include "libcli/nbt/libnbt.h" +#include "../libcli/nbt/libnbt.h" #include "param/param.h" /* command line options */ diff --git a/source4/web_server/config.mk b/source4/web_server/config.mk index fe78687794..af3ac5f544 100644 --- a/source4/web_server/config.mk +++ b/source4/web_server/config.mk @@ -5,10 +5,10 @@ [MODULE::WEB] INIT_FUNCTION = server_service_web_init SUBSYSTEM = smbd -PRIVATE_DEPENDENCIES = ESP LIBTLS smbcalls process_model +PRIVATE_DEPENDENCIES = LIBTLS smbcalls process_model LIBPYTHON # End SUBSYSTEM WEB ####################### -WEB_OBJ_FILES = $(addprefix $(web_serversrcdir)/, web_server.o http.o) +WEB_OBJ_FILES = $(addprefix $(web_serversrcdir)/, web_server.o wsgi.o) $(eval $(call proto_header_template,$(web_serversrcdir)/proto.h,$(WEB_OBJ_FILES:.o=.c))) diff --git a/source4/web_server/http.c b/source4/web_server/http.c deleted file mode 100644 index bd6efa9262..0000000000 --- a/source4/web_server/http.c +++ /dev/null @@ -1,1030 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - http handling code - - Copyright (C) Andrew Tridgell 2005 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "smbd/service_task.h" -#include "web_server/web_server.h" -#include "smbd/service_stream.h" -#include "smbd/service.h" -#include "lib/events/events.h" -#include "system/time.h" -#include "system/wait.h" -#include "lib/appweb/esp/esp.h" -#include "lib/appweb/ejs/ejsInternal.h" -#include "lib/util/dlinklist.h" -#include "lib/tls/tls.h" -#include "scripting/ejs/smbcalls.h" -#include "param/param.h" - -#define SAMBA_SESSION_KEY "SambaSessionId" -#define HTTP_PREAUTH_URI "/scripting/preauth.esp" - -/* state of the esp subsystem for a specific request */ -struct esp_state { - struct websrv_context *web; - struct EspRequest *req; - struct MprVar variables[ESP_OBJ_MAX]; - struct session_data *session; -}; - -/* - output the http headers -*/ -static void http_output_headers(struct websrv_context *web) -{ - int i; - char *s; - DATA_BLOB b; - uint32_t content_length = 0; - const char *response_string = "Unknown Code"; - const struct { - unsigned code; - const char *response_string; - } codes[] = { - { 200, "OK" }, - { 301, "Moved" }, - { 302, "Found" }, - { 303, "Method" }, - { 304, "Not Modified" }, - { 400, "Bad request" }, - { 401, "Unauthorized" }, - { 403, "Forbidden" }, - { 404, "Not Found" }, - { 500, "Internal Server Error" }, - { 501, "Not implemented" } - }; - for (i=0;i<ARRAY_SIZE(codes);i++) { - if (codes[i].code == web->output.response_code) { - response_string = codes[i].response_string; - } - } - - if (web->output.headers == NULL) return; - s = talloc_asprintf(web, "HTTP/1.0 %u %s\r\n", - web->output.response_code, response_string); - if (s == NULL) return; - for (i=0;web->output.headers[i];i++) { - s = talloc_asprintf_append_buffer(s, "%s\r\n", web->output.headers[i]); - } - - /* work out the content length */ - content_length = web->output.content.length; - if (web->output.fd != -1) { - struct stat st; - fstat(web->output.fd, &st); - content_length += st.st_size; - } - s = talloc_asprintf_append_buffer(s, "Content-Length: %u\r\n\r\n", content_length); - if (s == NULL) return; - - b = web->output.content; - web->output.content = data_blob_string_const(s); - data_blob_append(web, &web->output.content, b.data, b.length); - data_blob_free(&b); -} - -/* - return the local path for a URL -*/ -static const char *http_local_path(struct websrv_context *web, - const char *url, - const char *base_dir) -{ - int i; - char *path; - - /* check that the url is OK */ - if (url[0] != '/') return NULL; - - for (i=0;url[i];i++) { - if ((!isalnum((unsigned char)url[i]) && !strchr("./_-", url[i])) || - (url[i] == '.' && strchr("/.", url[i+1]))) { - return NULL; - } - } - - path = talloc_asprintf(web, "%s/%s", base_dir, url+1); - if (path == NULL) return NULL; - - if (directory_exist(path)) { - path = talloc_asprintf_append_buffer(path, "/index.esp"); - } - return path; -} - -/* - called when esp wants to read a file to support include() calls -*/ -static int http_readFile(EspHandle handle, - char **buf, - int *len, - const char *path, - const char *base_dir) -{ - struct websrv_context *web = talloc_get_type(handle, - struct websrv_context); - int fd = -1; - struct stat st; - *buf = NULL; - - path = http_local_path(web, path, base_dir); - if (path == NULL) goto failed; - - fd = open(path, O_RDONLY); - if (fd == -1 || fstat(fd, &st) != 0 || !S_ISREG(st.st_mode)) goto failed; - - *buf = talloc_array(handle, char, st.st_size+1); - if (*buf == NULL) goto failed; - - if (read(fd, *buf, st.st_size) != st.st_size) goto failed; - - (*buf)[st.st_size] = 0; - - close(fd); - *len = st.st_size; - return 0; - -failed: - DEBUG(0,("Failed to read file %s - %s\n", path, strerror(errno))); - if (fd != -1) close(fd); - talloc_free(*buf); - *buf = NULL; - return -1; -} - -static int http_readFileFromSwatDir(EspHandle handle, char **buf, int *len, - const char *path) -{ - return http_readFile(handle, buf, len, path, - lp_swat_directory(global_loadparm)); -} - - - -/* - called when esp wants to find the real path of a file -*/ -static int http_mapToStorage(EspHandle handle, char *path, int len, const char *uri, int flags) -{ - if (uri == NULL || strlen(uri) >= len) return -1; - strncpy(path, uri, len); - return 0; -} - -/* - called when esp wants to output something -*/ -static int http_writeBlock(EspHandle handle, const char *buf, int size) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - if (!data_blob_append(web, &web->output.content, buf, size)) - return -1; - return size; -} - - -/* - set a http header -*/ -static void http_setHeader(EspHandle handle, const char *value, bool allowMultiple) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - char *p = strchr(value, ':'); - - if (p && !allowMultiple && web->output.headers) { - int i; - for (i=0;web->output.headers[i];i++) { - if (strncmp(web->output.headers[i], value, (p+1)-value) == 0) { - web->output.headers[i] = talloc_strdup(web, value); - return; - } - } - } - - web->output.headers = str_list_add(web->output.headers, value); - talloc_steal(web, web->output.headers); -} - -/* - set a http response code -*/ -static void http_setResponseCode(EspHandle handle, int code) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - web->output.response_code = code; -} - -/* - redirect to another web page - */ -static void http_redirect(EspHandle handle, int code, char *url) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - const char *host = web->input.host; - - /* form the full url, unless it already looks like a url */ - if (strchr(url, ':') == NULL) { - if (host == NULL) { - struct socket_address *socket_address = socket_get_my_addr(web->conn->socket, web); - if (socket_address == NULL) goto internal_error; - host = talloc_asprintf(web, "%s:%u", - socket_address->addr, socket_address->port); - } - if (host == NULL) goto internal_error; - if (url[0] != '/') { - char *p = strrchr(web->input.url, '/'); - if (p == web->input.url) { - url = talloc_asprintf(web, "http%s://%s/%s", - tls_enabled(web->conn->socket)?"s":"", - host, url); - } else { - int dirlen = p - web->input.url; - url = talloc_asprintf(web, "http%s://%s%*.*s/%s", - tls_enabled(web->conn->socket)?"s":"", - host, - dirlen, dirlen, web->input.url, - url); - } - if (url == NULL) goto internal_error; - } - } - - http_setHeader(handle, talloc_asprintf(web, "Location: %s", url), 0); - - /* make sure we give a valid redirect code */ - if (code >= 300 && code < 400) { - http_setResponseCode(handle, code); - } else { - http_setResponseCode(handle, 302); - } - return; - -internal_error: - http_error(web, 500, "Internal server error"); -} - - -/* - setup a cookie -*/ -static void http_setCookie(EspHandle handle, const char *name, const char *value, - int lifetime, const char *path, bool secure) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - char *buf; - - if (lifetime > 0) { - buf = talloc_asprintf(web, "Set-Cookie: %s=%s; path=%s; Expires=%s; %s", - name, value, path?path:"/", - http_timestring(web, time(NULL)+lifetime), - secure?"secure":""); - } else { - buf = talloc_asprintf(web, "Set-Cookie: %s=%s; path=%s; %s", - name, value, path?path:"/", - secure?"secure":""); - } - http_setHeader(handle, "Cache-control: no-cache=\"set-cookie\"", 0); - http_setHeader(handle, buf, 0); - talloc_free(buf); -} - -/* - return the session id -*/ -static const char *http_getSessionId(EspHandle handle) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - return web->session->id; -} - -/* - setup a session -*/ -static void http_createSession(EspHandle handle, int timeout) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - if (web->session) { - web->session->lifetime = timeout; - http_setCookie(web, SAMBA_SESSION_KEY, web->session->id, - web->session->lifetime, "/", 0); - } -} - -/* - destroy a session -*/ -static void http_destroySession(EspHandle handle) -{ - struct websrv_context *web = talloc_get_type(handle, struct websrv_context); - talloc_free(web->session); - web->session = NULL; -} - - -/* - setup for a raw http level error -*/ -void http_error(struct websrv_context *web, int code, const char *info) -{ - char *s; - s = talloc_asprintf(web,"<HTML><HEAD><TITLE>Error %u</TITLE></HEAD><BODY><H1>Error %u</H1><pre>%s</pre><p></BODY></HTML>\r\n\r\n", - code, code, info); - if (s == NULL) { - stream_terminate_connection(web->conn, "http_error: out of memory"); - return; - } - http_writeBlock(web, s, strlen(s)); - http_setResponseCode(web, code); - http_output_headers(web); - EVENT_FD_NOT_READABLE(web->conn->event.fde); - EVENT_FD_WRITEABLE(web->conn->event.fde); - web->output.output_pending = true; -} - -/* - map a unix error code to a http error -*/ -void http_error_unix(struct websrv_context *web, const char *info) -{ - int code = 500; - switch (errno) { - case ENOENT: - case EISDIR: - code = 404; - break; - case EACCES: - code = 403; - break; - } - info = talloc_asprintf(web, "%s<p>%s<p>\n", info, strerror(errno)); - http_error(web, code, info); -} - - -/* - a simple file request -*/ -static void http_simple_request(struct websrv_context *web) -{ - const char *url = web->input.url; - const char *path; - struct stat st; - - path = http_local_path(web, url, lp_swat_directory(web->task->lp_ctx)); - if (path == NULL) goto invalid; - - /* looks ok */ - web->output.fd = open(path, O_RDONLY); - if (web->output.fd == -1) { - DEBUG(0,("Failed to read file %s - %s\n", path, strerror(errno))); - http_error_unix(web, path); - return; - } - - if (fstat(web->output.fd, &st) != 0 || !S_ISREG(st.st_mode)) { - close(web->output.fd); - goto invalid; - } - - return; - -invalid: - http_error(web, 400, "Malformed URL"); -} - -/* - setup the standard ESP arrays -*/ -static void http_setup_arrays(struct esp_state *esp) -{ - struct websrv_context *web = esp->web; - struct esp_data *edata = talloc_get_type(web->task->private, struct esp_data); - struct EspRequest *req = esp->req; - struct socket_address *socket_address = socket_get_my_addr(web->conn->socket, esp); - struct socket_address *peer_address = socket_get_peer_addr(web->conn->socket, esp); - char *p; - -#define SETVAR(type, name, value) do { \ - const char *v = value; \ - if (v) espSetStringVar(req, type, name, v); \ -} while (0) - - SETVAR(ESP_REQUEST_OBJ, "CONTENT_LENGTH", - talloc_asprintf(esp, "%u", web->input.content_length)); - SETVAR(ESP_REQUEST_OBJ, "QUERY_STRING", web->input.query_string); - SETVAR(ESP_REQUEST_OBJ, "POST_DATA", - talloc_strndup(esp, - web->input.partial.data, - web->input.partial.length)); - SETVAR(ESP_REQUEST_OBJ, "REQUEST_METHOD", web->input.post_request?"POST":"GET"); - SETVAR(ESP_REQUEST_OBJ, "REQUEST_URI", web->input.url); - p = strrchr(web->input.url, '/'); - SETVAR(ESP_REQUEST_OBJ, "SCRIPT_NAME", p+1); - SETVAR(ESP_REQUEST_OBJ, "SCRIPT_FILENAME", web->input.url); - if (peer_address) { - struct MprVar mpv = mprObject("socket_address"); - mprSetPtrChild(&mpv, "socket_address", peer_address); - espSetVar(req, ESP_REQUEST_OBJ, "REMOTE_SOCKET_ADDRESS", mpv); - SETVAR(ESP_REQUEST_OBJ, "REMOTE_ADDR", peer_address->addr); - } - p = socket_get_peer_name(web->conn->socket, esp); - SETVAR(ESP_REQUEST_OBJ, "REMOTE_HOST", p); - SETVAR(ESP_REQUEST_OBJ, "REMOTE_USER", ""); - SETVAR(ESP_REQUEST_OBJ, "CONTENT_TYPE", web->input.content_type); - if (web->session) { - SETVAR(ESP_REQUEST_OBJ, "SESSION_ID", web->session->id); - } - SETVAR(ESP_REQUEST_OBJ, "COOKIE_SUPPORT", web->input.cookie?"true":"false"); - - SETVAR(ESP_HEADERS_OBJ, "HTTP_REFERER", web->input.referer); - SETVAR(ESP_HEADERS_OBJ, "HOST", web->input.host); - SETVAR(ESP_HEADERS_OBJ, "ACCEPT_ENCODING", web->input.accept_encoding); - SETVAR(ESP_HEADERS_OBJ, "ACCEPT_LANGUAGE", web->input.accept_language); - SETVAR(ESP_HEADERS_OBJ, "ACCEPT_CHARSET", web->input.accept_charset); - SETVAR(ESP_HEADERS_OBJ, "COOKIE", web->input.cookie); - SETVAR(ESP_HEADERS_OBJ, "USER_AGENT", web->input.user_agent); - - if (socket_address) { - SETVAR(ESP_SERVER_OBJ, "SERVER_ADDR", socket_address->addr); - SETVAR(ESP_SERVER_OBJ, "SERVER_NAME", socket_address->addr); - SETVAR(ESP_SERVER_OBJ, "SERVER_HOST", socket_address->addr); - SETVAR(ESP_SERVER_OBJ, "SERVER_PORT", - talloc_asprintf(esp, "%u", socket_address->port)); - } - - SETVAR(ESP_SERVER_OBJ, "DOCUMENT_ROOT", lp_swat_directory(esp->web->task->lp_ctx)); - SETVAR(ESP_SERVER_OBJ, "SERVER_PROTOCOL", tls_enabled(web->conn->socket)?"https":"http"); - SETVAR(ESP_SERVER_OBJ, "SERVER_SOFTWARE", "SAMBA"); - SETVAR(ESP_SERVER_OBJ, "GATEWAY_INTERFACE", "CGI/1.1"); - SETVAR(ESP_SERVER_OBJ, "TLS_SUPPORT", tls_support(edata->tls_params)?"true":"false"); -} - -#if HAVE_SETJMP_H -/* the esp scripting lirary generates exceptions when - it hits a major error. We need to catch these and - report a internal server error via http -*/ -static jmp_buf ejs_exception_buf; -static const char *exception_reason; - -static void web_server_ejs_exception(const char *reason) -{ - Ejs *ep = ejsPtr(0); - if (ep) { - ejsSetErrorMsg(0, "%s", reason); - exception_reason = ep->error; - } else { - exception_reason = reason; - } - DEBUG(0,("%s", exception_reason)); - longjmp(ejs_exception_buf, -1); -} -#else -static void web_server_ejs_exception(const char *reason) -{ - DEBUG(0,("%s", reason)); - smb_panic(reason); -} -#endif - -/* - process a esp request -*/ -static void esp_request(struct esp_state *esp, const char *url) -{ - struct websrv_context *web = esp->web; - int size; - int res; - char *emsg = NULL, *buf; - - if (http_readFile(web, &buf, &size, url, lp_swat_directory(esp->web->task->lp_ctx)) != 0) { - http_error_unix(web, url); - return; - } - -#if HAVE_SETJMP_H - if (setjmp(ejs_exception_buf) != 0) { - http_error(web, 500, exception_reason); - return; - } -#endif - - res = espProcessRequest(esp->req, url, buf, &emsg); - if (res != 0 && emsg) { - http_writeBlock(web, "<pre>", 5); - http_writeBlock(web, emsg, strlen(emsg)); - http_writeBlock(web, "</pre>", 6); - } - talloc_free(buf); -} - -/* - perform pre-authentication on every page if /scripting/preauth.esp - exists. If this script generates any non-whitepace output at all, - then we don't run the requested URL. - - note that the preauth is run even for static pages such as images -*/ -static bool http_preauth(struct esp_state *esp) -{ - const char *path = http_local_path(esp->web, - HTTP_PREAUTH_URI, - lp_swat_directory(esp->web->task->lp_ctx)); - int i; - if (path == NULL) { - http_error(esp->web, 500, "Internal server error"); - return false; - } - if (!file_exist(path)) { - /* if the preath script is not installed then allow access */ - return true; - } - esp_request(esp, HTTP_PREAUTH_URI); - for (i=0;i<esp->web->output.content.length;i++) { - if (!isspace(esp->web->output.content.data[i])) { - /* if the preauth has generated content, then force it - to be html, so that we can show the login page for - failed access to images */ - http_setHeader(esp->web, "Content-Type: text/html", 0); - return false; - } - } - data_blob_free(&esp->web->output.content); - return true; -} - - -/* - handling of + and % escapes in http variables -*/ -static const char *http_unescape(TALLOC_CTX *mem_ctx, const char *p) -{ - char *s0 = talloc_strdup(mem_ctx, p); - char *s = s0; - if (s == NULL) return NULL; - - while (*s) { - unsigned v; - if (*s == '+') *s = ' '; - if (*s == '%' && sscanf(s+1, "%02x", &v) == 1) { - *s = (char)v; - memmove(s+1, s+3, strlen(s+3)+1); - } - s++; - } - - return s0; -} - -/* - set a form or GET variable -*/ -static void esp_putvar(struct esp_state *esp, const char *var, const char *value) -{ - if (strcasecmp(var, SAMBA_SESSION_KEY) == 0) { - /* special case support for browsers without cookie - support */ - esp->web->input.session_key = talloc_strdup(esp, value); - } else { - mprSetPropertyValue(&esp->variables[ESP_FORM_OBJ], - http_unescape(esp, var), - mprCreateStringVar(http_unescape(esp, value), 0)); - } -} - - -/* - parse the variables in a POST style request -*/ -static NTSTATUS http_parse_post(struct esp_state *esp) -{ - DATA_BLOB b = esp->web->input.partial; - - while (b.length) { - char *p, *line; - size_t len; - - p = memchr(b.data, '&', b.length); - if (p == NULL) { - len = b.length; - } else { - len = p - (char *)b.data; - } - line = talloc_strndup(esp, (char *)b.data, len); - NT_STATUS_HAVE_NO_MEMORY(line); - - p = strchr(line,'='); - if (p) { - *p = 0; - esp_putvar(esp, line, p+1); - } - talloc_free(line); - b.length -= len; - b.data += len; - if (b.length > 0) { - b.length--; - b.data++; - } - } - - return NT_STATUS_OK; -} - -/* - parse the variables in a GET style request -*/ -static NTSTATUS http_parse_get(struct esp_state *esp) -{ - struct websrv_context *web = esp->web; - char *p, *s, *tok; - char *pp; - - p = strchr(web->input.url, '?'); - web->input.query_string = p+1; - *p = 0; - - s = talloc_strdup(esp, esp->web->input.query_string); - NT_STATUS_HAVE_NO_MEMORY(s); - - for (tok=strtok_r(s,"&;", &pp);tok;tok=strtok_r(NULL,"&;", &pp)) { - p = strchr(tok,'='); - if (p) { - *p = 0; - esp_putvar(esp, tok, p+1); - } - } - return NT_STATUS_OK; -} - -/* - called when a session times out -*/ -static void session_timeout(struct event_context *ev, struct timed_event *te, - struct timeval t, void *private) -{ - struct session_data *s = talloc_get_type(private, struct session_data); - talloc_free(s); -} - -/* - destroy a session - */ -static int session_destructor(struct session_data *s) -{ - DLIST_REMOVE(s->edata->sessions, s); - return 0; -} - -/* - setup the session for this request -*/ -static void http_setup_session(struct esp_state *esp) -{ - const char *session_key = SAMBA_SESSION_KEY; - char *p; - const char *cookie = esp->web->input.cookie; - const char *key = NULL; - struct esp_data *edata = talloc_get_type(esp->web->task->private, struct esp_data); - struct session_data *s; - bool generated_key = false; - - /* look for our session key */ - if (cookie && (p = strstr(cookie, session_key)) && - p[strlen(session_key)] == '=') { - p += strlen(session_key)+1; - key = talloc_strndup(esp, p, strcspn(p, ";")); - } - - if (key == NULL && esp->web->input.session_key) { - key = esp->web->input.session_key; - } else if (key == NULL) { - key = generate_random_str_list(esp, 16, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"); - generated_key = true; - } - - /* try to find this session in the existing session list */ - for (s=edata->sessions;s;s=s->next) { - if (strcmp(key, s->id) == 0) { - break; - } - } - - if (s == NULL) { - /* create a new session */ - s = talloc_zero(edata, struct session_data); - s->id = talloc_steal(s, key); - s->data = NULL; - s->te = NULL; - s->edata = edata; - s->lifetime = lp_parm_int(esp->web->task->lp_ctx, NULL, "web", "sessiontimeout", 900); - DLIST_ADD(edata->sessions, s); - talloc_set_destructor(s, session_destructor); - if (!generated_key) { - mprSetPropertyValue(&esp->variables[ESP_REQUEST_OBJ], - "SESSION_EXPIRED", mprCreateStringVar("true", 0)); - } - } - - http_setCookie(esp->web, session_key, key, s->lifetime, "/", 0); - - if (s->data) { - mprCopyVar(&esp->variables[ESP_SESSION_OBJ], s->data, MPR_DEEP_COPY); - } - - esp->web->session = s; -} - - -/* callbacks for esp processing */ -static const struct Esp esp_control = { - .maxScriptSize = 60000, - .writeBlock = http_writeBlock, - .setHeader = http_setHeader, - .redirect = http_redirect, - .setResponseCode = http_setResponseCode, - .readFile = http_readFileFromSwatDir, - .mapToStorage = http_mapToStorage, - .setCookie = http_setCookie, - .createSession = http_createSession, - .destroySession = http_destroySession, - .getSessionId = http_getSessionId -}; - -/* - process a complete http request -*/ -void http_process_input(struct websrv_context *web) -{ - NTSTATUS status; - struct esp_state *esp = NULL; - struct esp_data *edata = talloc_get_type(web->task->private, struct esp_data); - struct smbcalls_context *smbcalls_ctx; - char *p; - void *save_mpr_ctx = mprMemCtx(); - void *ejs_save = ejs_save_state(); - int i; - const char *file_type = NULL; - enum page_type { - page_type_simple, - page_type_esp - }; - enum page_type page_type; - const struct { - const char *extension; - const char *mime_type; - enum page_type page_type; - } mime_types[] = { - {"gif", "image/gif"}, - {"png", "image/png"}, - {"jpg", "image/jpeg"}, - {"txt", "text/plain"}, - {"ico", "image/x-icon"}, - {"css", "text/css"}, - {"esp", "text/html", true} - }; - - /* - * give the smbcalls a chance to find the event context - * and messaging context - */ - smbcalls_ctx = talloc(web, struct smbcalls_context); - if (smbcalls_ctx == NULL) goto internal_error; - smbcalls_ctx->event_ctx = web->conn->event.ctx; - smbcalls_ctx->msg_ctx = web->conn->msg_ctx; - - esp = talloc_zero(smbcalls_ctx, struct esp_state); - if (esp == NULL) goto internal_error; - - esp->web = web; - - mprSetCtx(esp); - - if (espOpen(&esp_control) != 0) goto internal_error; - - for (i=0;i<ARRAY_SIZE(esp->variables);i++) { - esp->variables[i] = mprCreateUndefinedVar(); - } - esp->variables[ESP_HEADERS_OBJ] = mprCreateObjVar("headers", ESP_HASH_SIZE); - esp->variables[ESP_FORM_OBJ] = mprCreateObjVar("form", ESP_HASH_SIZE); - esp->variables[ESP_APPLICATION_OBJ] = mprCreateObjVar("application", ESP_HASH_SIZE); - esp->variables[ESP_COOKIES_OBJ] = mprCreateObjVar("cookies", ESP_HASH_SIZE); - esp->variables[ESP_FILES_OBJ] = mprCreateObjVar("files", ESP_HASH_SIZE); - esp->variables[ESP_REQUEST_OBJ] = mprCreateObjVar("request", ESP_HASH_SIZE); - esp->variables[ESP_SERVER_OBJ] = mprCreateObjVar("server", ESP_HASH_SIZE); - esp->variables[ESP_SESSION_OBJ] = mprCreateObjVar("session", ESP_HASH_SIZE); - - if (edata->application_data) { - mprCopyVar(&esp->variables[ESP_APPLICATION_OBJ], - edata->application_data, MPR_DEEP_COPY); - } - - smb_setup_ejs_functions(web_server_ejs_exception); - - if (web->input.url == NULL) { - http_error(web, 400, "You must specify a GET or POST request"); - mprSetCtx(save_mpr_ctx); - ejs_restore_state(ejs_save); - return; - } - - /* parse any form or get variables */ - if (web->input.post_request) { - status = http_parse_post(esp); - if (!NT_STATUS_IS_OK(status)) { - http_error(web, 400, "Malformed POST data"); - mprSetCtx(save_mpr_ctx); - ejs_restore_state(ejs_save); - return; - } - } - if (strchr(web->input.url, '?')) { - status = http_parse_get(esp); - if (!NT_STATUS_IS_OK(status)) { - http_error(web, 400, "Malformed GET data"); - mprSetCtx(save_mpr_ctx); - ejs_restore_state(ejs_save); - return; - } - } - - http_setup_session(esp); - - esp->req = espCreateRequest(web, web->input.url, esp->variables); - if (esp->req == NULL) goto internal_error; - - p = strrchr(web->input.url, '.'); - if (p == NULL) { - page_type = page_type_esp; - file_type = "text/html"; - } - for (i=0;p && i<ARRAY_SIZE(mime_types);i++) { - if (strcmp(mime_types[i].extension, p+1) == 0) { - page_type = mime_types[i].page_type; - file_type = mime_types[i].mime_type; - } - } - if (file_type == NULL) { - page_type = page_type_simple; - file_type = "text/html"; - } - - /* setup basic headers */ - http_setResponseCode(web, 200); - http_setHeader(web, talloc_asprintf(esp, "Date: %s", - http_timestring(esp, time(NULL))), 0); - http_setHeader(web, "Server: Samba", 0); - http_setHeader(web, "Connection: close", 0); - http_setHeader(web, talloc_asprintf(esp, "Content-Type: %s", file_type), 0); - - http_setup_arrays(esp); - - /* - * Do pre-authentication. If pre-authentication succeeds, do - * page-type-specific processing. - */ - switch(page_type) - { - case page_type_simple: - if (http_preauth(esp)) { - http_simple_request(web); - } - break; - - case page_type_esp: - if (http_preauth(esp)) { - esp_request(esp, web->input.url); - } - break; - } - - if (web->conn == NULL) { - /* the connection has been terminated above us, probably - via a timeout */ - goto internal_error; - } - - if (!web->output.output_pending) { - http_output_headers(web); - EVENT_FD_WRITEABLE(web->conn->event.fde); - web->output.output_pending = true; - } - - /* copy any application data to long term storage in edata */ - talloc_free(edata->application_data); - edata->application_data = talloc_zero(edata, struct MprVar); - mprSetCtx(edata->application_data); - mprCopyVar(edata->application_data, &esp->variables[ESP_APPLICATION_OBJ], - MPR_DEEP_COPY); - mprSetCtx(esp); - - /* copy any session data */ - if (web->session) { - talloc_free(web->session->data); - web->session->data = talloc_zero(web->session, struct MprVar); - if (esp->variables[ESP_SESSION_OBJ].properties == NULL || - esp->variables[ESP_SESSION_OBJ].properties[0].numItems == 0) { - talloc_free(web->session); - web->session = NULL; - } else { - mprSetCtx(web->session->data); - mprCopyVar(web->session->data, &esp->variables[ESP_SESSION_OBJ], - MPR_DEEP_COPY); - /* setup the timeout for the session data */ - mprSetCtx(esp); - talloc_free(web->session->te); - web->session->te = event_add_timed(web->conn->event.ctx, web->session, - timeval_current_ofs(web->session->lifetime, 0), - session_timeout, web->session); - } - } - - talloc_free(esp); - mprSetCtx(save_mpr_ctx); - ejs_restore_state(ejs_save); - return; - -internal_error: - mprSetCtx(esp); - talloc_free(esp); - if (web->conn != NULL) { - http_error(web, 500, "Internal server error"); - } - mprSetCtx(save_mpr_ctx); - ejs_restore_state(ejs_save); -} - - -/* - parse one line of header input -*/ -NTSTATUS http_parse_header(struct websrv_context *web, const char *line) -{ - if (line[0] == 0) { - web->input.end_of_headers = true; - } else if (strncasecmp(line,"GET ", 4)==0) { - web->input.url = talloc_strndup(web, &line[4], strcspn(&line[4], " \t")); - } else if (strncasecmp(line,"POST ", 5)==0) { - web->input.post_request = true; - web->input.url = talloc_strndup(web, &line[5], strcspn(&line[5], " \t")); - } else if (strchr(line, ':') == NULL) { - http_error(web, 400, "This server only accepts GET and POST requests"); - return NT_STATUS_INVALID_PARAMETER; - } else if (strncasecmp(line,"Content-Length: ", 16)==0) { - web->input.content_length = strtoul(&line[16], NULL, 10); - } else { -#define PULL_HEADER(v, s) do { \ - if (strncmp(line, s, strlen(s)) == 0) { \ - web->input.v = talloc_strdup(web, &line[strlen(s)]); \ - return NT_STATUS_OK; \ - } \ -} while (0) - PULL_HEADER(content_type, "Content-Type: "); - PULL_HEADER(user_agent, "User-Agent: "); - PULL_HEADER(referer, "Referer: "); - PULL_HEADER(host, "Host: "); - PULL_HEADER(accept_encoding, "Accept-Encoding: "); - PULL_HEADER(accept_language, "Accept-Language: "); - PULL_HEADER(accept_charset, "Accept-Charset: "); - PULL_HEADER(cookie, "Cookie: "); - } - - /* ignore all other headers for now */ - return NT_STATUS_OK; -} - - -/* - setup the esp processor - called at task initialisation -*/ -NTSTATUS http_setup_esp(struct task_server *task) -{ - struct esp_data *edata; - - edata = talloc_zero(task, struct esp_data); - NT_STATUS_HAVE_NO_MEMORY(edata); - - task->private = edata; - - edata->tls_params = tls_initialise(edata, task->lp_ctx); - NT_STATUS_HAVE_NO_MEMORY(edata->tls_params); - - return NT_STATUS_OK; -} diff --git a/source4/web_server/swat/__init__.py b/source4/web_server/swat/__init__.py index e0d85dbe2c..d434bb260b 100644 --- a/source4/web_server/swat/__init__.py +++ b/source4/web_server/swat/__init__.py @@ -1,4 +1,5 @@ #!/usr/bin/python +# -*- coding: utf-8 -*- # Unix SMB/CIFS implementation. # Copyright © Jelmer Vernooij <jelmer@samba.org> 2008 @@ -19,9 +20,20 @@ # along with this program. If not, see <http://www.gnu.org/licenses/>. # -def SWAT(environ, start_response): +def __call__(environ, start_response): status = '200 OK' - response_headers = [('Content-type','text/plain')] + response_headers = [('Content-type','text/html')] start_response(status, response_headers) - return ['Hello world!\n'] + yield '<table>\n' + for key, value in environ.items(): + if isinstance(value, str): + yield '\t<tr><td><b>%s</b></td><td>%s</td></tr>\n' % (key, value) + + yield '</table>\n' + +if __name__ == '__main__': + from wsgiref import simple_server + httpd = simple_server.make_server('localhost', 8090, __call__) + print "Serving HTTP on port 8090..." + httpd.serve_forever() diff --git a/source4/web_server/web_server.c b/source4/web_server/web_server.c index ac83a3384d..d741992770 100644 --- a/source4/web_server/web_server.c +++ b/source4/web_server/web_server.c @@ -4,6 +4,7 @@ web server startup Copyright (C) Andrew Tridgell 2005 + Copyright (C) Jelmer Vernooij 2008 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -29,6 +30,7 @@ #include "system/network.h" #include "lib/socket/netif.h" #include "lib/tls/tls.h" +#include "lib/util/dlinklist.h" #include "param/param.h" /* don't allow connections to hang around forever */ @@ -39,9 +41,6 @@ */ static int websrv_destructor(struct websrv_context *web) { - if (web->output.fd != -1) { - close(web->output.fd); - } return 0; } @@ -62,10 +61,90 @@ static void websrv_timeout(struct event_context *event_context, } /* + setup for a raw http level error +*/ +void http_error(struct websrv_context *web, const char *status, const char *info) +{ + char *s; + s = talloc_asprintf(web,"<HTML><HEAD><TITLE>Error %s</TITLE></HEAD><BODY><H1>Error %s</H1><pre>%s</pre><p></BODY></HTML>\r\n\r\n", + status, status, info); + if (s == NULL) { + stream_terminate_connection(web->conn, "http_error: out of memory"); + return; + } + websrv_output_headers(web, status, NULL); + websrv_output(web, s, strlen(s)); +} + +void websrv_output_headers(struct websrv_context *web, const char *status, struct http_header *headers) +{ + char *s; + DATA_BLOB b; + struct http_header *hdr; + + s = talloc_asprintf(web, "HTTP/1.0 %s\r\n", status); + if (s == NULL) return; + for (hdr = headers; hdr; hdr = hdr->next) { + s = talloc_asprintf_append_buffer(s, "%s: %s\r\n", hdr->name, hdr->value); + } + + s = talloc_asprintf_append_buffer(s, "\r\n"); + + b = web->output.content; + web->output.content = data_blob_string_const(s); + websrv_output(web, b.data, b.length); + data_blob_free(&b); +} + +void websrv_output(struct websrv_context *web, void *data, size_t length) +{ + data_blob_append(web, &web->output.content, data, length); + EVENT_FD_NOT_READABLE(web->conn->event.fde); + EVENT_FD_WRITEABLE(web->conn->event.fde); + web->output.output_pending = true; +} + + +/* + parse one line of header input +*/ +NTSTATUS http_parse_header(struct websrv_context *web, const char *line) +{ + if (line[0] == 0) { + web->input.end_of_headers = true; + } else if (strncasecmp(line,"GET ", 4)==0) { + web->input.url = talloc_strndup(web, &line[4], strcspn(&line[4], " \t")); + } else if (strncasecmp(line,"POST ", 5)==0) { + web->input.post_request = true; + web->input.url = talloc_strndup(web, &line[5], strcspn(&line[5], " \t")); + } else if (strchr(line, ':') == NULL) { + http_error(web, "400 Bad request", "This server only accepts GET and POST requests"); + return NT_STATUS_INVALID_PARAMETER; + } else if (strncasecmp(line, "Content-Length: ", 16)==0) { + web->input.content_length = strtoul(&line[16], NULL, 10); + } else { + struct http_header *hdr = talloc_zero(web, struct http_header); + char *colon = strchr(line, ':'); + if (colon == NULL) { + http_error(web, "500 Internal Server Error", "invalidly formatted header"); + return NT_STATUS_INVALID_PARAMETER; + } + + hdr->name = talloc_strndup(hdr, line, colon-line); + hdr->value = talloc_strdup(hdr, colon+1); + DLIST_ADD(web->input.headers, hdr); + } + + /* ignore all other headers for now */ + return NT_STATUS_OK; +} + +/* called when a web connection becomes readable */ static void websrv_recv(struct stream_connection *conn, uint16_t flags) { + struct web_server_data *wdata; struct websrv_context *web = talloc_get_type(conn->private, struct websrv_context); NTSTATUS status; @@ -123,7 +202,9 @@ static void websrv_recv(struct stream_connection *conn, uint16_t flags) destroy the stack variables being used by that rendering process when we handle the timeout. */ if (!talloc_reference(web->task, web)) goto failed; - http_process_input(web); + wdata = talloc_get_type(web->task->private, struct web_server_data); + if (wdata == NULL) goto failed; + wdata->http_process_input(wdata, web); talloc_unlink(web->task, web); } return; @@ -133,6 +214,7 @@ failed: } + /* called when a web connection becomes writable */ @@ -159,29 +241,7 @@ static void websrv_send(struct stream_connection *conn, uint16_t flags) web->output.nsent += nsent; - /* possibly read some more raw data from a file */ - if (web->output.content.length == web->output.nsent && - web->output.fd != -1) { - uint8_t buf[2048]; - ssize_t nread; - - data_blob_free(&web->output.content); - web->output.nsent = 0; - - nread = read(web->output.fd, buf, sizeof(buf)); - if (nread == -1 && errno == EINTR) { - return; - } - if (nread <= 0) { - close(web->output.fd); - web->output.fd = -1; - nread = 0; - } - web->output.content = data_blob_talloc(web, buf, nread); - } - - if (web->output.content.length == web->output.nsent && - web->output.fd == -1) { + if (web->output.content.length == web->output.nsent) { stream_terminate_connection(web->conn, "websrv_send: finished sending"); } } @@ -192,7 +252,7 @@ static void websrv_send(struct stream_connection *conn, uint16_t flags) static void websrv_accept(struct stream_connection *conn) { struct task_server *task = talloc_get_type(conn->private, struct task_server); - struct esp_data *edata = talloc_get_type(task->private, struct esp_data); + struct web_server_data *wdata = talloc_get_type(task->private, struct web_server_data); struct websrv_context *web; struct socket_context *tls_socket; @@ -202,7 +262,6 @@ static void websrv_accept(struct stream_connection *conn) web->task = task; web->conn = conn; conn->private = web; - web->output.fd = -1; talloc_set_destructor(web, websrv_destructor); event_add_timed(conn->event.ctx, web, @@ -210,7 +269,7 @@ static void websrv_accept(struct stream_connection *conn) websrv_timeout, web); /* Overwrite the socket with a (possibly) TLS socket */ - tls_socket = tls_init_server(edata->tls_params, conn->socket, + tls_socket = tls_init_server(wdata->tls_params, conn->socket, conn->event.fde, "GPHO"); /* We might not have TLS, or it might not have initilised */ if (tls_socket) { @@ -243,11 +302,12 @@ static void websrv_task_init(struct task_server *task) NTSTATUS status; uint16_t port = lp_web_port(task->lp_ctx); const struct model_ops *model_ops; + struct web_server_data *wdata; task_server_set_title(task, "task[websrv]"); /* run the web server as a single process */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) goto failed; if (lp_interfaces(task->lp_ctx) && lp_bind_interfaces_only(task->lp_ctx)) { @@ -280,8 +340,15 @@ static void websrv_task_init(struct task_server *task) /* startup the esp processor - unfortunately we can't do this per connection as that wouldn't allow for session variables */ - status = http_setup_esp(task); - if (!NT_STATUS_IS_OK(status)) goto failed; + wdata = talloc_zero(task, struct web_server_data); + if (wdata == NULL)goto failed; + + task->private = wdata; + + wdata->tls_params = tls_initialise(wdata, task->lp_ctx); + if (wdata->tls_params == NULL) goto failed; + + if (!wsgi_initialize(wdata)) goto failed; return; diff --git a/source4/web_server/web_server.h b/source4/web_server/web_server.h index 52aff05dcc..f91c766494 100644 --- a/source4/web_server/web_server.h +++ b/source4/web_server/web_server.h @@ -19,13 +19,28 @@ #include "smbd/process_model.h" +struct websrv_context; + +struct web_server_data { + struct tls_params *tls_params; + void (*http_process_input)(struct web_server_data *wdata, + struct websrv_context *web); + void *private; +}; + +struct http_header { + char *name; + char *value; + struct http_header *prev, *next; +}; + /* context of one open web connection */ struct websrv_context { struct task_server *task; struct stream_connection *conn; - struct { + struct websrv_request_input { bool tls_detect; bool tls_first_char; uint8_t first_byte; @@ -34,45 +49,17 @@ struct websrv_context { char *url; unsigned content_length; bool post_request; - const char *content_type; - const char *query_string; - const char *user_agent; - const char *referer; - const char *host; - const char *accept_encoding; - const char *accept_language; - const char *accept_charset; - const char *cookie; - const char *session_key; + struct http_header *headers; } input; - struct { + struct websrv_request_output { bool output_pending; DATA_BLOB content; - int fd; + bool headers_sent; unsigned nsent; - int response_code; - const char **headers; } output; struct session_data *session; }; -/* - context for long term storage in the web server, to support session[] - and application[] data. Stored in task->private. -*/ -struct esp_data { - struct session_data { - struct session_data *next, *prev; - struct esp_data *edata; - const char *id; - struct MprVar *data; - struct timed_event *te; - int lifetime; - } *sessions; - struct MprVar *application_data; - struct tls_params *tls_params; -}; - #include "web_server/proto.h" diff --git a/source4/web_server/wsgi.c b/source4/web_server/wsgi.c new file mode 100644 index 0000000000..66697868e0 --- /dev/null +++ b/source4/web_server/wsgi.c @@ -0,0 +1,391 @@ +/* + Unix SMB/CIFS implementation. + Samba utility functions + Copyright © Jelmer Vernooij <jelmer@samba.org> 2008 + + Implementation of the WSGI interface described in PEP0333 + (http://www.python.org/dev/peps/pep-0333) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "includes.h" +#include "web_server/web_server.h" +#include "lib/util/dlinklist.h" +#include "lib/util/data_blob.h" +#include "lib/tls/tls.h" +#include <Python.h> + +typedef struct { + PyObject_HEAD + struct websrv_context *web; +} web_request_Object; + +static PyObject *start_response(PyObject *self, PyObject *args, PyObject *kwargs) +{ + PyObject *response_header, *exc_info = NULL; + char *status; + int i; + const char *kwnames[] = { + "status", "response_header", "exc_info", NULL + }; + web_request_Object *py_web = (web_request_Object *)self; + struct websrv_context *web = py_web->web; + struct http_header *headers = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "sO|O:start_response", discard_const_p(char *, kwnames), &status, &response_header, &exc_info)) { + return NULL; + } + + /* FIXME: exc_info */ + + if (!PyList_Check(response_header)) { + PyErr_SetString(PyExc_TypeError, "response_header should be list"); + return NULL; + } + + for (i = 0; i < PyList_Size(response_header); i++) { + struct http_header *hdr = talloc_zero(web, struct http_header); + PyObject *item = PyList_GetItem(response_header, i); + PyObject *py_name, *py_value; + + if (!PyTuple_Check(item)) { + PyErr_SetString(PyExc_TypeError, "Expected tuple"); + return NULL; + } + + if (PyTuple_Size(item) != 2) { + PyErr_SetString(PyExc_TypeError, "header tuple has invalid size, expected 2"); + return NULL; + } + + py_name = PyTuple_GetItem(item, 0); + + if (!PyString_Check(py_name)) { + PyErr_SetString(PyExc_TypeError, "header name should be string"); + return NULL; + } + + py_value = PyTuple_GetItem(item, 1); + if (!PyString_Check(py_value)) { + PyErr_SetString(PyExc_TypeError, "header value should be string"); + return NULL; + } + + hdr->name = talloc_strdup(hdr, PyString_AsString(py_name)); + hdr->value = talloc_strdup(hdr, PyString_AsString(py_value)); + DLIST_ADD(headers, hdr); + } + + websrv_output_headers(web, status, headers); + + return Py_None; +} + +static PyMethodDef web_request_methods[] = { + { "start_response", (PyCFunction)start_response, METH_VARARGS|METH_KEYWORDS, NULL }, + { NULL } +}; + + +PyTypeObject web_request_Type = { + PyObject_HEAD_INIT(NULL) 0, + .tp_name = "wsgi.Request", + .tp_methods = web_request_methods, + .tp_basicsize = sizeof(web_request_Object), + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +typedef struct { + PyObject_HEAD +} error_Stream_Object; + +static PyObject *py_error_flush(PyObject *self, PyObject *args, PyObject *kwargs) +{ + /* Nothing to do here */ + return Py_None; +} + +static PyObject *py_error_write(PyObject *self, PyObject *args, PyObject *kwargs) +{ + const char *kwnames[] = { "str", NULL }; + char *str = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:write", discard_const_p(char *, kwnames), &str)) { + return NULL; + } + + DEBUG(0, ("WSGI App: %s", str)); + + return Py_None; +} + +static PyObject *py_error_writelines(PyObject *self, PyObject *args, PyObject *kwargs) +{ + const char *kwnames[] = { "seq", NULL }; + PyObject *seq = NULL, *item; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:writelines", discard_const_p(char *, kwnames), &seq)) { + return NULL; + } + + while ((item = PyIter_Next(seq))) { + char *str = PyString_AsString(item); + + DEBUG(0, ("WSGI App: %s", str)); + } + + return Py_None; +} + +static PyMethodDef error_Stream_methods[] = { + { "flush", (PyCFunction)py_error_flush, METH_VARARGS|METH_KEYWORDS, NULL }, + { "write", (PyCFunction)py_error_write, METH_VARARGS|METH_KEYWORDS, NULL }, + { "writelines", (PyCFunction)py_error_writelines, METH_VARARGS|METH_KEYWORDS, NULL }, + { NULL, NULL, 0, NULL } +}; + +PyTypeObject error_Stream_Type = { + PyObject_HEAD_INIT(NULL) 0, + .tp_name = "wsgi.ErrorStream", + .tp_basicsize = sizeof(error_Stream_Object), + .tp_methods = error_Stream_methods, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +typedef struct { + PyObject_HEAD + struct websrv_context *web; + size_t offset; +} input_Stream_Object; + +static PyObject *py_input_read(PyObject *_self, PyObject *args, PyObject *kwargs) +{ + const char *kwnames[] = { "size", NULL }; + PyObject *ret; + input_Stream_Object *self = (input_Stream_Object *)_self; + int size = -1; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", discard_const_p(char *, kwnames), &size)) + return NULL; + + /* Don't read beyond buffer boundaries */ + if (size == -1) + size = self->web->input.partial.length-self->offset; + else + size = MIN(size, self->web->input.partial.length-self->offset); + + ret = PyString_FromStringAndSize((char *)self->web->input.partial.data+self->offset, size); + self->offset += size; + + return ret; +} + +static PyObject *py_input_readline(PyObject *_self) +{ + input_Stream_Object *self = (input_Stream_Object *)_self; + /* FIXME */ + PyErr_SetString(PyExc_NotImplementedError, + "readline() not yet implemented"); + return NULL; +} + +static PyObject *py_input_readlines(PyObject *_self, PyObject *args, PyObject *kwargs) +{ + const char *kwnames[] = { "hint", NULL }; + PyObject *ret; + int hint; + input_Stream_Object *self = (input_Stream_Object *)_self; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|i", discard_const_p(char *, kwnames), &hint)) + return NULL; + + /* FIXME */ + PyErr_SetString(PyExc_NotImplementedError, + "readlines() not yet implemented"); + return NULL; +} + +static PyObject *py_input___iter__(PyObject *_self) +{ + input_Stream_Object *self = (input_Stream_Object *)_self; + /* FIXME */ + PyErr_SetString(PyExc_NotImplementedError, + "__iter__() not yet implemented"); + return NULL; +} + +static PyMethodDef input_Stream_methods[] = { + { "read", (PyCFunction)py_input_read, METH_VARARGS|METH_KEYWORDS, NULL }, + { "readline", (PyCFunction)py_input_readline, METH_NOARGS, NULL }, + { "readlines", (PyCFunction)py_input_readlines, METH_VARARGS|METH_KEYWORDS, NULL }, + { "__iter__", (PyCFunction)py_input___iter__, METH_NOARGS, NULL }, + { NULL, NULL, 0, NULL } +}; + +PyTypeObject input_Stream_Type = { + PyObject_HEAD_INIT(NULL) 0, + .tp_name = "wsgi.InputStream", + .tp_basicsize = sizeof(input_Stream_Object), + .tp_methods = input_Stream_methods, + .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, +}; + +static PyObject *Py_InputHttpStream(struct websrv_context *web) +{ + input_Stream_Object *ret = PyObject_New(input_Stream_Object, &input_Stream_Type); + ret->web = web; + ret->offset = 0; + return (PyObject *)ret; +} + +static PyObject *Py_ErrorHttpStream(void) +{ + error_Stream_Object *ret = PyObject_New(error_Stream_Object, &error_Stream_Type); + return (PyObject *)ret; +} + +static PyObject *create_environ(bool tls, int content_length, struct http_header *headers, const char *request_method, const char *servername, int serverport, PyObject *inputstream, const char *request_string) +{ + PyObject *env; + PyObject *errorstream; + PyObject *py_scheme; + struct http_header *hdr; + char *questionmark; + + env = PyDict_New(); + if (env == NULL) { + return NULL; + } + + errorstream = Py_ErrorHttpStream(); + if (errorstream == NULL) { + Py_DECREF(env); + Py_DECREF(inputstream); + return NULL; + } + + PyDict_SetItemString(env, "wsgi.input", inputstream); + PyDict_SetItemString(env, "wsgi.errors", errorstream); + PyDict_SetItemString(env, "wsgi.version", Py_BuildValue("(i,i)", 1, 0)); + PyDict_SetItemString(env, "wsgi.multithread", Py_False); + PyDict_SetItemString(env, "wsgi.multiprocess", Py_True); + PyDict_SetItemString(env, "wsgi.run_once", Py_False); + PyDict_SetItemString(env, "SERVER_PROTOCOL", PyString_FromString("HTTP/1.0")); + if (content_length > 0) { + PyDict_SetItemString(env, "CONTENT_LENGTH", PyLong_FromLong(content_length)); + } + PyDict_SetItemString(env, "REQUEST_METHOD", PyString_FromString(request_method)); + + questionmark = strchr(request_string, '?'); + if (questionmark == NULL) { + PyDict_SetItemString(env, "SCRIPT_NAME", PyString_FromString(request_string)); + } else { + PyDict_SetItemString(env, "QUERY_STRING", PyString_FromString(questionmark+1)); + PyDict_SetItemString(env, "SCRIPT_NAME", PyString_FromStringAndSize(request_string, questionmark-request_string)); + } + + PyDict_SetItemString(env, "SERVER_NAME", PyString_FromString(servername)); + PyDict_SetItemString(env, "SERVER_PORT", PyInt_FromLong(serverport)); + for (hdr = headers; hdr; hdr = hdr->next) { + char *name; + if (!strcasecmp(hdr->name, "Content-Type")) { + PyDict_SetItemString(env, "CONTENT_TYPE", PyString_FromString(hdr->value)); + } else { + asprintf(&name, "HTTP_%s", hdr->name); + PyDict_SetItemString(env, name, PyString_FromString(hdr->value)); + free(name); + } + } + + if (tls) { + py_scheme = PyString_FromString("https"); + } else { + py_scheme = PyString_FromString("http"); + } + PyDict_SetItemString(env, "wsgi.url_scheme", py_scheme); + + return env; +} + +static void wsgi_process_http_input(struct web_server_data *wdata, + struct websrv_context *web) +{ + PyObject *py_environ, *result, *item, *iter; + PyObject *request_handler = wdata->private; + struct socket_address *socket_address; + + web_request_Object *py_web = PyObject_New(web_request_Object, &web_request_Type); + py_web->web = web; + + socket_address = socket_get_my_addr(web->conn->socket, web); + py_environ = create_environ(tls_enabled(web->conn->socket), + web->input.content_length, + web->input.headers, + web->input.post_request?"POST":"GET", + socket_address->addr, + socket_address->port, + Py_InputHttpStream(web), + web->input.url + ); + if (py_environ == NULL) { + DEBUG(0, ("Unable to create WSGI environment object\n")); + return; + } + + result = PyObject_CallMethod(request_handler, discard_const_p(char, "__call__"), discard_const_p(char, "OO"), + py_environ, PyObject_GetAttrString((PyObject *)py_web, "start_response")); + + if (result == NULL) { + DEBUG(0, ("error while running WSGI code\n")); + return; + } + + iter = PyObject_GetIter(result); + Py_DECREF(result); + + /* Now, iter over all the data returned */ + + while ((item = PyIter_Next(iter))) { + websrv_output(web, PyString_AsString(item), PyString_Size(item)); + Py_DECREF(item); + } + + Py_DECREF(iter); +} + +bool wsgi_initialize(struct web_server_data *wdata) +{ + PyObject *py_swat; + + Py_Initialize(); + + if (PyType_Ready(&web_request_Type) < 0) + return false; + + if (PyType_Ready(&input_Stream_Type) < 0) + return false; + + if (PyType_Ready(&error_Stream_Type) < 0) + return false; + + wdata->http_process_input = wsgi_process_http_input; + py_swat = PyImport_Import(PyString_FromString("swat")); + if (py_swat == NULL) { + DEBUG(0, ("Unable to find SWAT\n")); + return false; + } + wdata->private = py_swat; + return true; +} diff --git a/source4/winbind/wb_server.c b/source4/winbind/wb_server.c index d56a82ea18..638fac00a1 100644 --- a/source4/winbind/wb_server.c +++ b/source4/winbind/wb_server.c @@ -122,7 +122,7 @@ static void winbind_task_init(struct task_server *task) /* within the winbind task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) { task_server_terminate(task, "Can't find 'single' process model_ops"); diff --git a/source4/wrepl_server/wrepl_in_connection.c b/source4/wrepl_server/wrepl_in_connection.c index 25227481b8..ecc265e590 100644 --- a/source4/wrepl_server/wrepl_in_connection.c +++ b/source4/wrepl_server/wrepl_in_connection.c @@ -218,7 +218,7 @@ NTSTATUS wreplsrv_in_connection_merge(struct wreplsrv_partner *partner, /* within the wrepl task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(service->task->event_ctx, "single"); if (!model_ops) { DEBUG(0,("Can't find 'single' process model_ops")); return NT_STATUS_INTERNAL_ERROR; @@ -273,7 +273,7 @@ NTSTATUS wreplsrv_setup_sockets(struct wreplsrv_service *service, struct loadpar /* within the wrepl task we want to be a single process, so ask for the single process model ops and pass these to the stream_setup_socket() call. */ - model_ops = process_model_byname("single"); + model_ops = process_model_startup(task->event_ctx, "single"); if (!model_ops) { DEBUG(0,("Can't find 'single' process model_ops")); return NT_STATUS_INTERNAL_ERROR; diff --git a/testprogs/ejs/base.js b/testprogs/ejs/base.js deleted file mode 100755 index 3c998ee4f8..0000000000 --- a/testprogs/ejs/base.js +++ /dev/null @@ -1,23 +0,0 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} - -var options = GetOptions(ARGV, - "POPT_COMMON_SAMBA"); -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -libinclude("base.js"); - -var obj = new Object(); -obj.FOO = "foo"; -obj.BAR = "bar"; -var str1 = "${FOO}:${BAR}"; -var str2 = "${FOO}:${BAR} "; // note the space after the brace -var sub1 = substitute_var(str1, obj); -var sub2 = substitute_var(str2, obj); - -assert(str1 + " " == str2); -assert(sub1 + " " == sub2); -exit(0); diff --git a/testprogs/ejs/bugs.js b/testprogs/ejs/bugs.js deleted file mode 100644 index 0c1cecb486..0000000000 --- a/testprogs/ejs/bugs.js +++ /dev/null @@ -1,155 +0,0 @@ -/* - demonstrate some bugs in ejs - - tridge <appweb@tridgell.net> -*/ - - -/**************************************** -demo a bug in constructing arrays -fix at http://build.samba.org/build.pl?function=diff;tree=samba4;revision=7124 -status: FIXED -*****************************************/ -function arraybug() { - var a; - - println("First with 3 elements"); - a = new Array("one", "two", "three"); - printVars(a); - assert(a.length == 3); - assert(a[0] == "one"); - assert(a[1] == "two"); - assert(a[2] == "three"); - - println("with a array length"); - a = new Array(5); - printVars(a); - assert(a.length == 5); - - println("\nNow with 1 element"); - a = new Array("one"); - printVars(a); - assert(a.length == 1); - assert(a[0] == "one"); - - println("ALL OK"); -} - - -/**************************************** -demo a bug in variable arguments -fix at http://build.samba.org/build.pl?function=diff;tree=samba4;revision=7085 -status: FIXED -*****************************************/ -function argsbug() { - println("we should have been called with 3 arguments"); - assert(arguments.length == 3); - assert(arguments[0] == "one"); - assert(arguments[1] == "two"); - assert(arguments[2] == "three"); -} - - -/**************************************** -demo a bug in constructing objects -no fix available yet -status: SUBMITTED -*****************************************/ -function MyObj() { - var o = new Object(); - o.test = 42; - return o; -} - -function objbug() { - println("the docs say you should use 'new'"); - var o1 = new MyObj(); - var o2 = MyObj(); - printVars(o1); - printVars(o2); - assert(o1.test == 42); - assert(o2.test == 42); -} - -/* - demo a expression handling bug - status: FIXED -*/ -function exprbug() { - var a = new Array(10); - var i; - for (i=0;i<4;i++) { - a[1+(i*2)] = i; - a[2+(i*2)] = i*2; - } -} - -/**************************************** -demo lack of recursion -fix in http://build.samba.org/build.pl?function=diff;tree=samba4;revision=7127 -status: FIXED -*****************************************/ -function fibonacci(n) { - if (n < 3) { - return 1; - } - return fibonacci(n-1) + fibonacci(n-2); -} - -function recursebug() { - println("First 10 fibonacci numbers:"); - for (i=0;i<10;i++) { - println("fibonacci(" + i + ")=" + fibonacci(i)); - } -} - -/**************************************** -demo lack of function variables inside functions -status: FIXED IN SAMBA -*****************************************/ -function callback() -{ - return "testing"; -} - -function fnbug(c) -{ - s = c(); - assert(s == "testing"); -} - -/**************************************** -demo incorrect handling of reserved words in strings -status: SUBMITTED -*****************************************/ -function reservedbug() -{ - assert("funct" + "ion" == 'function'); -} - - -/**************************************** -demo incorrect handling of boolean functions -status: SUBMITTED -*****************************************/ -function no() -{ - return false; -} - -function boolbug() -{ - assert(false == no()); - assert(!no()); -} - - -/* run the tests */ -arraybug(); -argsbug("one", "two", "three"); -recursebug(); -exprbug(); -fnbug(callback); -reservedbug(); -boolbug(); -objbug(); diff --git a/testprogs/ejs/ldb.js b/testprogs/ejs/ldb.js deleted file mode 100755 index 8c71994805..0000000000 --- a/testprogs/ejs/ldb.js +++ /dev/null @@ -1,385 +0,0 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} -/* - demonstrate access to ldb databases from ejs -*/ - - -var ldb = ldb_init(); -var sys; -var options = GetOptions(ARGV, - "POPT_AUTOHELP", - "POPT_COMMON_SAMBA"); -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -libinclude("base.js"); - -if (options.ARGV.length != 1) { - println("Usage: ldb.js <prefix>"); - return -1; -} - -prefix = options.ARGV[0]; - -function basic_tests(ldb) -{ - println("Running basic tests"); - ok = ldb.add(" -dn: cn=x,cn=test -objectClass: foo -x: 3 -"); - assert(ok.error == 0); - - println("Testing ldb.search"); - var res = ldb.search("(objectClass=*)"); - assert(res.msgs[0].objectClass[0] == "foo"); - assert(res.msgs[0].dn == "cn=x,cn=test"); - assert(res.msgs[0].x == 3); - - ok = ldb.add(" -dn: cn=x2,cn=test -objectClass: foo -x: 4 -"); - assert(ok.error == 0); - var attrs = new Array("x"); - res = ldb.search("x=4", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.msgs[0].x == 4); - assert(res.msgs[0].objectClass == undefined); - assert(res.msgs[0].dn == "cn=x2,cn=test"); - - ok = ldb.del("cn=x,cn=test"); - assert(ok.error == 0); - - ok = ldb.rename("cn=x2,cn=test", "cn=x3,cn=test"); - assert(ok.error == 0); - res = ldb.search("x=4", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.msgs[0].dn == "cn=x3,cn=test"); - - ok = ldb.rename("cn=x3,cn=test", "cn=X3,cn=test"); - assert(ok.error == 0); - res = ldb.search("x=4", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.msgs[0].dn == "cn=X3,cn=test"); - - ok = ldb.modify(" -dn: cn=x3,cn=test -changetype: modify -add: x -x: 7 -"); - - res = ldb.search("x=7"); - assert(res.msgs.length == 1); - assert(res.msgs[0].x.length == 2); - - /* Check a few things before we add modules */ - assert(res.msgs[0].objectGUID == undefined); - assert(res.msgs[0].createTimestamp == undefined); - assert(res.msgs[0].whenCreated == undefined); - -} - -function setup_modules(ldb) -{ - ok = ldb.add(" -dn: @MODULES -@LIST: rootdse,operational,rdn_name,partition - -dn: @ROOTDSE -defaultNamingContext: cn=Test - -dn: @PARTITION -partition: cn=SideTest:" + prefix + "/" + "testside.ldb -partition: cn=Sub,cn=PartTest:" + prefix + "/" + "testsub.ldb -partition: cn=PartTest:" + prefix + "/" + "testpartition.ldb -partition: cn=Sub,cn=Sub,cn=PartTest:" + prefix + "/" + "testsubsub.ldb -replicateEntries: @ATTRIBUTES -replicateEntries: @INDEXLIST -modules: cn=PartTest:objectguid -"); -} - -/* Test the basic operation of the timestamps,objectguid and name_rdn - modules */ - -function modules_test(ldb, parttestldb) -{ - println("Running modules tests"); - - ok = ldb.add(" -dn: @ATTRIBUTES -cn: CASE_INSENSITIVE -caseattr: CASE_INSENSITIVE -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - /* Confirm that the attributes were replicated */ - var res_attrs = parttestldb.search("cn=*", "@ATTRIBUTES", parttestldb.SCOPE_BASE); - assert(res_attrs.msgs[0].cn == "CASE_INSENSITIVE"); - - ok = ldb.add(" -dn: cn=x8,cn=PartTest -objectClass: foo -x: 8 -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - ok = ldb.add(" -dn: cn=x9,cn=PartTest -objectClass: foo -x: 9 -cn: X9 -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - ok = ldb.add(" -dn: cn=X9,cn=PartTest -objectClass: foo -x: 9 -cn: X9 -"); - if (ok.error == 0) { - println("Should have failed to add cn=X9,cn=PartTest"); - assert(ok.error != 0); - } - - var res = ldb.search("x=8", "cn=PartTest", ldb.SCOPE_DEFAULT); - assert(res.msgs[0].objectGUID != undefined); - assert(res.msgs[0].uSNCreated != undefined); - assert(res.msgs[0].uSNChanged != undefined); - assert(res.msgs[0].createTimestamp == undefined); - assert(res.msgs[0].whenCreated != undefined); - assert(res.msgs[0].name == "x8"); - assert(res.msgs[0].cn == "x8"); - - /* Confirm that this ended up in the correct LDB */ - var res_otherldb = parttestldb.search("x=8", "cn=PartTest", parttestldb.SCOPE_DEFAULT); - assert(res_otherldb.msgs[0].objectGUID != undefined); - assert(res_otherldb.msgs[0].createTimestamp == undefined); - assert(res_otherldb.msgs[0].whenCreated != undefined); - assert(res_otherldb.msgs[0].name == "x8"); - assert(res_otherldb.msgs[0].cn == "x8"); - - var attrs = new Array("*", "createTimestamp"); - var res2 = ldb.search("x=9", "cn=PartTest", ldb.SCOPE_DEFAULT, attrs); - assert(res2.msgs[0].objectGUID != undefined); - assert(res2.msgs[0].createTimestamp != undefined); - assert(res2.msgs[0].whenCreated != undefined); - assert(res2.msgs[0].name == "x9"); - assert(res2.msgs[0].cn == "x9"); - - assert(res.msgs[0].objectGUID != res2.msgs[0].objectGUID); - - var attrs = new Array("*"); - var res3 = ldb.search("", "", ldb.SCOPE_BASE, attrs); - assert(res3.msgs[0].cn == undefined); - assert(res3.msgs[0].distinguishedName == undefined); - assert(res3.msgs[0].name == undefined); - assert(res3.msgs[0].currentTime != undefined); - assert(res3.msgs[0].highestCommittedUSN != undefined); - - assert(res3.msgs[0].namingContexts[0] == "cn=Sub,cn=Sub,cn=PartTest"); - assert(res3.msgs[0].namingContexts[1] == "cn=Sub,cn=PartTest"); - assert(res3.msgs[0].namingContexts[2] == "cn=PartTest"); - assert(res3.msgs[0].namingContexts[3] == "cn=SideTest"); - var usn = res3.msgs[0].highestCommittedUSN; - - /* Start a transaction. We are going to abort it later, to - * show we clean up all partitions */ - - ok = ldb.transaction_start() - if (!ok) { - println("Failed to start a transaction: " + ok.errstr); - assert(ok.error == 0); - } - - - ok = ldb.add(" -dn: cn=x10,cn=parttest -objectClass: foo -x: 10 -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - var attrs = new Array("highestCommittedUSN"); - var res4 = ldb.search("", "", ldb.SCOPE_BASE, attrs); - var usn2 = res4.msgs[0].highestCommittedUSN; - assert(usn < res4.msgs[0].highestCommittedUSN); - - ok = ldb.add(" -dn: cn=x11,cn=sub,cn=parttest -objectClass: foo -x: 11 -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - var attrs = new Array("highestCommittedUSN"); - var res5 = ldb.search("", "", ldb.SCOPE_BASE, attrs); - assert(usn2 < res5.msgs[0].highestCommittedUSN); - - var attrs = new Array("*", "createTimestamp"); - var res6 = ldb.search("x=11", "cn=parttest", ldb.SCOPE_SUB, attrs); - assert(res6.msgs.length == 0); - - var attrs = new Array("*", "createTimestamp"); - var res7 = ldb.search("x=10", "cn=sub,cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(res7.msgs.length == 0); - - var res8 = ldb.search("x=11", "cn=sub,cn=parttest", ldb.SCOPE_DEFAULT, attrs); - - assert(res8.msgs[0].objectGUID == undefined); /* The objectGUID module is not loaded here */ - assert(res8.msgs[0].uSNCreated == undefined); /* The objectGUID module is not loaded here */ - assert(res8.msgs[0].name == "x11"); - assert(res8.msgs[0].cn == "x11"); - - ok = ldb.add(" -dn: caseattr=XY,cn=PartTest -objectClass: foo -x: Y -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - ok = ldb.add(" -dn: caseattr=XZ,cn=PartTest -objectClass: foo -x: Z -caseattr: XZ -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - ok = ldb.add(" -dn: caseattr=xz,cn=PartTest -objectClass: foo -x: Z -caseattr: xz -"); - if (ok.error == 0) { - println("Should have failed to add caseattr=xz,cn=PartTest"); - assert(ok.error != 0); - } - - ok = ldb.add(" -dn: caseattr2=XZ,cn=PartTest -objectClass: foo -x: Z -caseattr2: XZ -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - ok = ldb.add(" -dn: caseattr2=Xz,cn=PartTest -objectClass: foo -x: Z -caseattr2: Xz -"); - if (ok.error != 0) { - println("Failed to add: " + ok.errstr); - assert(ok.error == 0); - } - - var resX = ldb.search("caseattr=xz", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(resX.msgs.length == 1); - assert(resX.msgs[0].objectGUID != undefined); - assert(resX.msgs[0].createTimestamp != undefined); - assert(resX.msgs[0].whenCreated != undefined); - assert(resX.msgs[0].name == "XZ"); - - var rescount = ldb.search("(|(caseattr=*)(cn=*))", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(rescount.msgs.length == 5); - - /* Check this attribute is *not* case sensitive */ - var resXcount = ldb.search("caseattr=x*", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(resXcount.msgs.length == 2); - - /* Check that this attribute *is* case sensitive */ - var resXcount2 = ldb.search("caseattr2=xz", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(resXcount2.msgs.length == 0); - - - /* Now abort the transaction to show that even with - * partitions, it is aborted everywhere */ - ok = ldb.transaction_cancel(); - if (!ok) { - println("Failed to cancel a transaction: " + ok.errstr); - assert(ok); - } - - /* now check it all went away */ - - var attrs = new Array("highestCommittedUSN"); - var res9 = ldb.search("", "", ldb.SCOPE_BASE, attrs); - assert(usn == res9.msgs[0].highestCommittedUSN); - - var attrs = new Array("*"); - var res10 = ldb.search("x=11", "cn=sub,cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(res10.msgs.length == 0); - - var attrs = new Array("*"); - var res11 = ldb.search("x=10", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(res11.msgs.length == 0); - - var attrs = new Array("*"); - var res12 = ldb.search("caseattr=*", "cn=parttest", ldb.SCOPE_DEFAULT, attrs); - assert(res12.msgs.length == 0); - -} - -sys = sys_init(); -var dbfile = "test.ldb"; - -sys.unlink(prefix + "/" + dbfile); -sys.unlink(prefix + "/" + "testpartition.ldb"); -sys.unlink(prefix + "/" + "testsub.ldb"); -sys.unlink(prefix + "/" + "testsubsub.ldb"); -sys.unlink(prefix + "/" + "testside.ldb"); - -var ok = ldb.connect("tdb://" + prefix + "/" + dbfile); -assert(ok); - -basic_tests(ldb); - -setup_modules(ldb); -ldb = ldb_init(); -var ok = ldb.connect("tdb://" + prefix + "/" + dbfile); -assert(ok); - -parttestldb = ldb_init(); -var ok = parttestldb.connect("tdb://" + prefix + "/" + "testpartition.ldb"); -assert(ok); - -modules_test(ldb, parttestldb); - -sys.unlink(prefix + "/" + dbfile); -sys.unlink(prefix + "/" + "testpartition.ldb"); -sys.unlink(prefix + "/" + "testsub.ldb"); -sys.unlink(prefix + "/" + "testsubsub.ldb"); -sys.unlink(prefix + "/" + "testside.ldb"); -return 0; diff --git a/testprogs/ejs/minschema.js b/testprogs/ejs/minschema.js deleted file mode 100755 index f088501c1d..0000000000 --- a/testprogs/ejs/minschema.js +++ /dev/null @@ -1,804 +0,0 @@ -#!/bin/sh -exec smbscript "$0" ${1+"$@"} -/* - work out the minimal schema for a set of objectclasses -*/ - -libinclude("base.js"); - -var ldb = ldb_init(); - -var options = GetOptions(ARGV, - "POPT_AUTOHELP", - "POPT_COMMON_SAMBA", - "POPT_COMMON_CREDENTIALS", - "verbose", - "classes", - "attributes"); -if (options == undefined) { - println("Failed to parse options"); - return -1; -} -verbose = options["verbose"]; -dump_all = "yes"; -dump_classes = options["classes"]; -dump_attributes = options["attributes"]; - -if (dump_classes != undefined) { - dump_all = undefined; -} -if (dump_attributes != undefined) { - dump_all = undefined; -} -if (dump_all != undefined) { - dump_classes = "yes"; - dump_attributes = "yes"; -} - -if (options.ARGV.length != 2) { - println("Usage: minschema.js <URL> <classfile>"); - return -1; -} - -var url = options.ARGV[0]; -var classfile = options.ARGV[1]; - -/* use command line creds if available */ -ldb.credentials = options.get_credentials(); - -var ok = ldb.connect(url); -assert(ok); - -objectclasses = new Object(); -attributes = new Object(); -rootDse = new Object(); - -objectclasses_expanded = new Object(); - -/* the attributes we need for objectclasses */ -class_attrs = new Array("objectClass", - "subClassOf", - "governsID", - "possSuperiors", - "possibleInferiors", - "mayContain", - "mustContain", - "auxiliaryClass", - "rDNAttID", - "showInAdvancedViewOnly", - "adminDisplayName", - "adminDescription", - "objectClassCategory", - "lDAPDisplayName", - "schemaIDGUID", - "systemOnly", - "systemPossSuperiors", - "systemMayContain", - "systemMustContain", - "systemAuxiliaryClass", - "defaultSecurityDescriptor", - "systemFlags", - "defaultHidingValue", - "defaultObjectCategory", - - /* this attributes are not used by w2k3 */ - "schemaFlagsEx", - "msDs-IntId", - "msDs-Schema-Extensions", - "classDisplayName", - "isDefunct"); - - -attrib_attrs = new Array("objectClass", - "attributeID", - "attributeSyntax", - "isSingleValued", - "rangeLower", - "rangeUpper", - "mAPIID", - "linkID", - "showInAdvancedViewOnly", - "adminDisplayName", - "oMObjectClass", - "adminDescription", - "oMSyntax", - "searchFlags", - "extendedCharsAllowed", - "lDAPDisplayName", - "schemaIDGUID", - "attributeSecurityGUID", - "systemOnly", - "systemFlags", - "isMemberOfPartialAttributeSet", - - /* this attributes are not used by w2k3 */ - "schemaFlagsEx", - "msDs-IntId", - "msDs-Schema-Extensions", - "classDisplayName", - "isEphemeral", - "isDefunct"); - -/* - notes: - - objectClassCategory - 1: structural - 2: abstract - 3: auxiliary -*/ - - -/* - print only if verbose is set -*/ -function dprintf() { - if (verbose != undefined) { - print(vsprintf(arguments)); - } -} - -function get_object_cn(ldb, name) { - var attrs = new Array("cn"); - - var res = ldb.search(sprintf("(ldapDisplayName=%s)", name), rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs); - assert(res != undefined); - assert(res.msgs.length == 1); - - var cn = res.msgs[0]["cn"]; - assert(cn != undefined); - if (typeof(cn) == "string") { - return cn; - } - return cn[0]; -} -/* - create an objectclass object -*/ -function obj_objectClass(ldb, name) { - var o = new Object(); - o.name = name; - o.cn = get_object_cn(ldb, name); - return o; -} - -/* - create an attribute object -*/ -function obj_attribute(ldb, name) { - var o = new Object(); - o.name = name; - o.cn = get_object_cn(ldb, name); - return o; -} - - -syntaxmap = new Object(); - -syntaxmap['2.5.5.1'] = '1.3.6.1.4.1.1466.115.121.1.12'; -syntaxmap['2.5.5.2'] = '1.3.6.1.4.1.1466.115.121.1.38'; -syntaxmap['2.5.5.3'] = '1.2.840.113556.1.4.1362'; -syntaxmap['2.5.5.4'] = '1.2.840.113556.1.4.905'; -syntaxmap['2.5.5.5'] = '1.3.6.1.4.1.1466.115.121.1.26'; -syntaxmap['2.5.5.6'] = '1.3.6.1.4.1.1466.115.121.1.36'; -syntaxmap['2.5.5.7'] = '1.2.840.113556.1.4.903'; -syntaxmap['2.5.5.8'] = '1.3.6.1.4.1.1466.115.121.1.7'; -syntaxmap['2.5.5.9'] = '1.3.6.1.4.1.1466.115.121.1.27'; -syntaxmap['2.5.5.10'] = '1.3.6.1.4.1.1466.115.121.1.40'; -syntaxmap['2.5.5.11'] = '1.3.6.1.4.1.1466.115.121.1.24'; -syntaxmap['2.5.5.12'] = '1.3.6.1.4.1.1466.115.121.1.15'; -syntaxmap['2.5.5.13'] = '1.3.6.1.4.1.1466.115.121.1.43'; -syntaxmap['2.5.5.14'] = '1.2.840.113556.1.4.904'; -syntaxmap['2.5.5.15'] = '1.2.840.113556.1.4.907'; -syntaxmap['2.5.5.16'] = '1.2.840.113556.1.4.906'; -syntaxmap['2.5.5.17'] = '1.3.6.1.4.1.1466.115.121.1.40'; - -/* - map some attribute syntaxes from some apparently MS specific - syntaxes to the standard syntaxes -*/ -function map_attribute_syntax(s) { - if (syntaxmap[s] != undefined) { - return syntaxmap[s]; - } - return s; -} - - -/* - fix a string DN to use ${SCHEMADN} -*/ -function fix_dn(dn) { - var s = strstr(dn, rootDse.schemaNamingContext); - if (s == NULL) { - return dn; - } - return substr(dn, 0, strlen(dn) - strlen(s)) + "${SCHEMADN}"; -} - -/* - dump an object as ldif -*/ -function write_ldif_one(o, attrs) { - var i; - printf("dn: CN=%s,${SCHEMADN}\n", o.cn); - for (i=0;i<attrs.length;i++) { - var a = attrs[i]; - if (o[a] == undefined) { - continue; - } - /* special case for oMObjectClass, which is a binary object */ - if (a == "oMObjectClass") { - printf("%s:: %s\n", a, o[a]); - continue; - } - var v = o[a]; - if (typeof(v) == "string") { - v = new Array(v); - } - var j; - for (j=0;j<v.length;j++) { - printf("%s: %s\n", a, fix_dn(v[j])); - } - } - printf("\n"); -} - -/* - dump an array of objects as ldif -*/ -function write_ldif(o, attrs) { - var i; - for (i in o) { - write_ldif_one(o[i], attrs); - } -} - - -/* - create a testDN based an an example DN - the idea is to ensure we obey any structural rules -*/ -function create_testdn(exampleDN) { - var a = split(",", exampleDN); - a[0] = "CN=TestDN"; - return join(",", a); -} - -/* - find the properties of an objectclass - */ -function find_objectclass_properties(ldb, o) { - var res = ldb.search( - sprintf("(ldapDisplayName=%s)", o.name), - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, class_attrs); - assert(res != undefined); - assert(res.msgs.length == 1); - var msg = res.msgs[0]; - var a; - for (a in msg) { - o[a] = msg[a]; - } -} - -/* - find the properties of an attribute - */ -function find_attribute_properties(ldb, o) { - var res = ldb.search( - sprintf("(ldapDisplayName=%s)", o.name), - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrib_attrs); - assert(res != undefined); - assert(res.msgs.length == 1); - var msg = res.msgs[0]; - var a; - for (a in msg) { - /* special case for oMObjectClass, which is a binary object */ - if (a == "oMObjectClass") { - o[a] = ldb.encode(msg[a]); - continue; - } - o[a] = msg[a]; - } -} - -/* - find the auto-created properties of an objectclass. Only works for classes - that can be created using just a DN and the objectclass - */ -function find_objectclass_auto(ldb, o) { - if (o["exampleDN"] == undefined) { - return; - } - var testdn = create_testdn(o.exampleDN); - var ok; - - dprintf("testdn is '%s'\n", testdn); - - var ldif = "dn: " + testdn; - ldif = ldif + "\nobjectClass: " + o.name; - ok = ldb.add(ldif); - if (ok.error != 0) { - dprintf("error adding %s: %s\n", o.name, ok.errstr); - dprintf("%s\n", ldif); - return; - } - - var res = ldb.search("", testdn, ldb.SCOPE_BASE); - ok = ldb.del(testdn); - assert(ok.error == 0); - - var a; - for (a in res.msgs[0]) { - attributes[a].autocreate = true; - } -} - - -/* - look at auxiliary information from a class to intuit the existance of more - classes needed for a minimal schema -*/ -function expand_objectclass(ldb, o) { - var attrs = new Array("auxiliaryClass", "systemAuxiliaryClass", - "possSuperiors", "systemPossSuperiors", - "subClassOf"); - var res = ldb.search( - sprintf("(&(objectClass=classSchema)(ldapDisplayName=%s))", o.name), - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs); - var a; - dprintf("Expanding class %s\n", o.name); - assert(res != undefined); - assert(res.msgs.length == 1); - var msg = res.msgs[0]; - for (a=0;a<attrs.length;a++) { - var aname = attrs[a]; - if (msg[aname] == undefined) { - continue; - } - var list = msg[aname]; - if (typeof(list) == "string") { - list = new Array(msg[aname]); - } - var i; - for (i=0;i<list.length;i++) { - var name = list[i]; - if (objectclasses[name] == undefined) { - dprintf("Found new objectclass '%s'\n", name); - objectclasses[name] = obj_objectClass(ldb, name); - } - } - } -} - - -/* - add the must and may attributes from an objectclass to the full list - of attributes -*/ -function add_objectclass_attributes(ldb, class) { - var attrs = new Array("mustContain", "systemMustContain", - "mayContain", "systemMayContain"); - var i; - for (i=0;i<attrs.length;i++) { - var aname = attrs[i]; - if (class[aname] == undefined) { - continue; - } - var alist = class[aname]; - if (typeof(alist) == "string") { - alist = new Array(alist); - } - var j; - var len = alist.length; - for (j=0;j<len;j++) { - var a = alist[j]; - if (attributes[a] == undefined) { - attributes[a] = obj_attribute(ldb, a); - } - } - } -} - - -/* - process an individual record, working out what attributes it has -*/ -function walk_dn(ldb, dn) { - /* get a list of all possible attributes for this object */ - var attrs = new Array("allowedAttributes"); - var res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, attrs); - if (res.error != 0) { - dprintf("Unable to fetch allowedAttributes for '%s' - %s\n", - dn, res.errstr); - return; - } - var allattrs = res.msgs[0].allowedAttributes; - res = ldb.search("objectClass=*", dn, ldb.SCOPE_BASE, allattrs); - if (res.error != 0) { - dprintf("Unable to fetch all attributes for '%s' - %s\n", - dn, res.errstr); - return; - } - var a; - var msg = res.msgs[0]; - for (a in msg) { - if (attributes[a] == undefined) { - attributes[a] = obj_attribute(ldb, a); - } - } -} - -/* - walk a naming context, looking for all records -*/ -function walk_naming_context(ldb, namingContext) { - var attrs = new Array("objectClass"); - var res = ldb.search("objectClass=*", namingContext, ldb.SCOPE_DEFAULT, attrs); - if (res.error != 0) { - dprintf("Unable to fetch objectClasses for '%s' - %s\n", - namingContext, res.errstr); - return; - } - var r; - for (r=0;r<res.msgs.length;r++) { - var msg = res.msgs[r].objectClass; - var c; - for (c=0;c<msg.length;c++) { - var objectClass = msg[c]; - if (objectclasses[objectClass] == undefined) { - objectclasses[objectClass] = obj_objectClass(ldb, objectClass); - objectclasses[objectClass].exampleDN = res.msgs[r].dn; - } - } - walk_dn(ldb, res.msgs[r].dn); - } -} - -/* - trim the may attributes for an objectClass -*/ -function trim_objectclass_attributes(ldb, class) { - var i,j,n; - - /* trim possibleInferiors, - * include only the classes we extracted */ - var possinf = class["possibleInferiors"]; - if (possinf != undefined) { - var newpossinf = new Array(); - if (typeof(possinf) == "string") { - possinf = new Array(possinf); - } - n = 0; - for (j = 0;j < possinf.length; j++) { - var x = possinf[j]; - if (objectclasses[x] != undefined) { - newpossinf[n] = x; - n++; - } - } - class["possibleInferiors"] = newpossinf; - } - - /* trim systemMayContain, - * remove duplicates */ - var sysmay = class["systemMayContain"]; - if (sysmay != undefined) { - var newsysmay = new Array(); - if (typeof(sysmay) == "string") { - sysmay = new Array(sysmay); - } - for (j = 0;j < sysmay.length; j++) { - var x = sysmay[j]; - var dup = false; - if (newsysmay[0] == undefined) { - newsysmay[0] = x; - } else { - for (n = 0; n < newsysmay.length; n++) { - if (newsysmay[n] == x) { - dup = true; - } - } - if (dup == false) { - newsysmay[n] = x; - } - } - } - class["systemMayContain"] = newsysmay; - } - - /* trim mayContain, - * remove duplicates */ - var may = class["mayContain"]; - if (may != undefined) { - var newmay = new Array(); - if (typeof(may) == "string") { - may = new Array(may); - } - for (j = 0;j < may.length; j++) { - var x = may[j]; - var dup = false; - if (newmay[0] == undefined) { - newmay[0] = x; - } else { - for (n = 0; n < newmay.length; n++) { - if (newmay[n] == x) { - dup = true; - } - } - if (dup == false) { - newmay[n] = x; - } - } - } - class["mayContain"] = newmay; - } -} - -/* - load the basic attributes of an objectClass -*/ -function build_objectclass(ldb, name) { - var attrs = new Array("name"); - var res = ldb.search( - sprintf("(&(objectClass=classSchema)(ldapDisplayName=%s))", name), - rootDse.schemaNamingContext, ldb.SCOPE_SUBTREE, attrs); - if (res.error != 0) { - dprintf("unknown class '%s'\n", name); - return undefined; - } - if (res.msgs.length == 0) { - dprintf("unknown class '%s'\n", name); - return undefined; - } - return obj_objectClass(ldb, name); -} - -/* - append 2 lists -*/ -function list_append(a1, a2) { - var i; - if (a1 == undefined) { - return a2; - } - if (a2 == undefined) { - return a1; - } - for (i=0;i<a2.length;i++) { - a1[a1.length] = a2[i]; - } - return a1; -} - -/* - form a coalesced attribute list -*/ -function attribute_list(class, attr1, attr2) { - var a1 = class[attr1]; - var a2 = class[attr2]; - if (typeof(a1) == "string") { - a1 = new Array(a1); - } - if (typeof(a2) == "string") { - a2 = new Array(a2); - } - return list_append(a1, a2); -} - -/* - write out a list in aggregate form -*/ -function aggregate_list(name, list) { - if (list == undefined) { - return; - } - var i; - printf("%s ( ", name); - for (i=0;i<list.length;i++) { - printf("%s ", list[i]); - if (i < (list.length - 1)) { - printf("$ "); - } - } - printf(") "); -} - -/* - write the aggregate record for an objectclass -*/ -function write_aggregate_objectclass(class) { - printf("objectClasses: ( %s NAME '%s' ", class.governsID, class.name); - if (class['subClassOf'] != undefined) { - printf("SUP %s ", class['subClassOf']); - } - if (class.objectClassCategory == 1) { - printf("STRUCTURAL "); - } else if (class.objectClassCategory == 2) { - printf("ABSTRACT "); - } else if (class.objectClassCategory == 3) { - printf("AUXILIARY "); - } - - var list; - - list = attribute_list(class, "systemMustContain", "mustContain"); - aggregate_list("MUST", list); - - list = attribute_list(class, "systemMayContain", "mayContain"); - aggregate_list("MAY", list); - - printf(")\n"); -} - - -/* - write the aggregate record for an ditcontentrule -*/ -function write_aggregate_ditcontentrule(class) { - var list = attribute_list(class, "auxiliaryClass", "systemAuxiliaryClass"); - var i; - if (list == undefined) { - return; - } - - printf("dITContentRules: ( %s NAME '%s' ", class.governsID, class.name); - - aggregate_list("AUX", list); - - var may_list = undefined; - var must_list = undefined; - - for (i=0;i<list.length;i++) { - var c = list[i]; - var list2; - list2 = attribute_list(objectclasses[c], - "mayContain", "systemMayContain"); - may_list = list_append(may_list, list2); - list2 = attribute_list(objectclasses[c], - "mustContain", "systemMustContain"); - must_list = list_append(must_list, list2); - } - - aggregate_list("MUST", must_list); - aggregate_list("MAY", may_list); - - printf(")\n"); -} - -/* - write the aggregate record for an attribute -*/ -function write_aggregate_attribute(attrib) { - printf("attributeTypes: ( %s NAME '%s' SYNTAX '%s' ", - attrib.attributeID, attrib.name, - map_attribute_syntax(attrib.attributeSyntax)); - if (attrib['isSingleValued'] == "TRUE") { - printf("SINGLE-VALUE "); - } - if (attrib['systemOnly'] == "TRUE") { - printf("NO-USER-MODIFICATION "); - } - - printf(")\n"); -} - - - -/* - load a list from a file -*/ -function load_list(file) { - var sys = sys_init(); - var s = sys.file_load(file); - var a = split("\n", s); - return a; -} - -/* get the rootDSE */ -var res = ldb.search("", "", ldb.SCOPE_BASE); -rootDse = res.msgs[0]; - -/* load the list of classes we are interested in */ -var classes = load_list(classfile); -var i; -for (i=0;i<classes.length;i++) { - var classname = classes[i]; - var class = build_objectclass(ldb, classname); - if (class != undefined) { - objectclasses[classname] = class; - } -} - - -/* - expand the objectclass list as needed -*/ -var num_classes = 0; -var expanded = 0; -/* calculate the actual number of classes */ -for (i in objectclasses) { - num_classes++; -} -/* so EJS do not have while nor the break statement - cannot find any other way than doing more loops - than necessary to recursively expand all classes - */ -var inf; -for (inf = 0;inf < 500; inf++) { - if (expanded < num_classes) { - for (i in objectclasses) { - var n = objectclasses[i]; - if (objectclasses_expanded[i] != "DONE") { - expand_objectclass(ldb, objectclasses[i]); - objectclasses_expanded[i] = "DONE"; - expanded++; - } - } - /* recalculate the actual number of classes */ - num_classes = 0; - for (i in objectclasses) { - num_classes++; - } - } -} - -/* - find objectclass properties -*/ -for (i in objectclasses) { - find_objectclass_properties(ldb, objectclasses[i]); -} - -/* - form the full list of attributes -*/ -for (i in objectclasses) { - add_objectclass_attributes(ldb, objectclasses[i]); -} - -/* and attribute properties */ -for (i in attributes) { - find_attribute_properties(ldb, attributes[i]); -} - -/* - trim the 'may' attribute lists to those really needed -*/ -for (i in objectclasses) { - trim_objectclass_attributes(ldb, objectclasses[i]); -} - -/* - dump an ldif form of the attributes and objectclasses -*/ -if (dump_attributes != undefined) { - write_ldif(attributes, attrib_attrs); -} -if (dump_classes != undefined) { - write_ldif(objectclasses, class_attrs); -} -if (verbose == undefined) { - exit(0); -} - -/* - dump list of objectclasses -*/ -printf("objectClasses:\n") -for (i in objectclasses) { - printf("\t%s\n", i); -} -printf("attributes:\n") -for (i in attributes) { - printf("\t%s\n", i); -} - -printf("autocreated attributes:\n"); -for (i in attributes) { - if (attributes[i].autocreate == true) { - printf("\t%s\n", i); - } -} - -return 0; diff --git a/testprogs/ejs/samba3sam.js b/testprogs/ejs/samba3sam.js deleted file mode 100644 index 244074743d..0000000000 --- a/testprogs/ejs/samba3sam.js +++ /dev/null @@ -1,1263 +0,0 @@ -#!/usr/bin/env smbscript -/* - (C) Jelmer Vernooij <jelmer@samba.org> 2005 - (C) Martin Kuehl <mkhl@samba.org> 2006 - Published under the GNU GPL - Sponsored by Google Summer of Code - */ - -var sys; -var options = GetOptions(ARGV, "POPT_AUTOHELP", "POPT_COMMON_SAMBA"); -if (options == undefined) { - println("Failed to parse options"); - return -1; -} - -libinclude("base.js"); - -if (options.ARGV.length != 2) { - println("Usage: samba3sam.js <TESTDIR> <DATADIR>"); - return -1; -} - -var prefix = options.ARGV[0]; -var datadir = options.ARGV[1]; - -function setup_data(obj, ldif) -{ - assert(ldif != undefined); - ldif = substitute_var(ldif, obj); - assert(ldif != undefined); - var ok = obj.db.add(ldif); - assert(ok.error == 0); -} - -function setup_modules(ldb, s3, s4, ldif) -{ - assert(ldif != undefined); - ldif = substitute_var(ldif, s4); - assert(ldif != undefined); - var ok = ldb.add(ldif); - assert(ok.error == 0); - - var ldif = " -dn: @MAP=samba3sam -@FROM: " + s4.BASEDN + " -@TO: sambaDomainName=TESTS," + s3.BASEDN + " - -dn: @MODULES -@LIST: rootdse,paged_results,server_sort,extended_dn,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition - -dn: @PARTITION -partition: " + s4.BASEDN + ":" + s4.url + " -partition: " + s3.BASEDN + ":" + s3.url + " -replicateEntries: @SUBCLASSES -replicateEntries: @ATTRIBUTES -replicateEntries: @INDEXLIST -"; - var ok = ldb.add(ldif); - assert(ok.error == 0); -} - -function test_s3sam_search(ldb) -{ - println("Looking up by non-mapped attribute"); - var msg = ldb.search("(cn=Administrator)"); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - assert(msg.msgs[0].cn == "Administrator"); - - println("Looking up by mapped attribute"); - var msg = ldb.search("(name=Backup Operators)"); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - assert(msg.msgs[0].name == "Backup Operators"); - - println("Looking up by old name of renamed attribute"); - var msg = ldb.search("(displayName=Backup Operators)"); - assert(msg.msgs.length == 0); - - println("Looking up mapped entry containing SID"); - var msg = ldb.search("(cn=Replicator)"); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - println(msg.msgs[0].dn); - assert(msg.msgs[0].dn == "cn=Replicator,ou=Groups,dc=vernstok,dc=nl"); - assert(msg.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552"); - - println("Checking mapping of objectClass"); - var oc = msg.msgs[0].objectClass; - assert(oc != undefined); - for (var i in oc) { - assert(oc[i] == "posixGroup" || oc[i] == "group"); - } - - println("Looking up by objectClass"); - var msg = ldb.search("(|(objectClass=user)(cn=Administrator))"); - assert(msg.error == 0); - assert(msg.msgs.length == 2); - for (var i = 0; i < msg.msgs.length; i++) { - assert((msg.msgs[i].dn == "unixName=Administrator,ou=Users,dc=vernstok,dc=nl") || - (msg.msgs[i].dn == "unixName=nobody,ou=Users,dc=vernstok,dc=nl")); - } -} - -function test_s3sam_modify(ldb, s3) -{ - var msg, ok; - println("Adding a record that will be fallbacked"); - ok = ldb.add(" -dn: cn=Foo -foo: bar -blah: Blie -cn: Foo -showInAdvancedViewOnly: TRUE -"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - - println("Checking for existence of record (local)"); - /* TODO: This record must be searched in the local database, which is currently only supported for base searches - * msg = ldb.search("(cn=Foo)", new Array('foo','blah','cn','showInAdvancedViewOnly')); - * TODO: Actually, this version should work as well but doesn't... - * - */ - var attrs = new Array('foo','blah','cn','showInAdvancedViewOnly'); - msg = ldb.search("(cn=Foo)", "cn=Foo", ldb.LDB_SCOPE_BASE, attrs); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - assert(msg.msgs[0].showInAdvancedViewOnly == "TRUE"); - assert(msg.msgs[0].foo == "bar"); - assert(msg.msgs[0].blah == "Blie"); - - println("Adding record that will be mapped"); - ok = ldb.add(" -dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl -objectClass: user -unixName: bin -sambaUnicodePwd: geheim -cn: Niemand -"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - assert(ok.error == 0); - - println("Checking for existence of record (remote)"); - msg = ldb.search("(unixName=bin)", new Array('unixName','cn','dn', 'sambaUnicodePwd')); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - assert(msg.msgs[0].cn == "Niemand"); - assert(msg.msgs[0].sambaUnicodePwd == "geheim"); - - println("Checking for existence of record (local && remote)"); - msg = ldb.search("(&(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd')); - assert(msg.error == 0); - assert(msg.msgs.length == 1); // TODO: should check with more records - assert(msg.msgs[0].cn == "Niemand"); - assert(msg.msgs[0].unixName == "bin"); - assert(msg.msgs[0].sambaUnicodePwd == "geheim"); - - println("Checking for existence of record (local || remote)"); - msg = ldb.search("(|(unixName=bin)(sambaUnicodePwd=geheim))", new Array('unixName','cn','dn', 'sambaUnicodePwd')); - println("got " + msg.msgs.length + " replies"); - assert(msg.error == 0); - assert(msg.msgs.length == 1); // TODO: should check with more records - assert(msg.msgs[0].cn == "Niemand"); - assert(msg.msgs[0].unixName == "bin" || msg.msgs[0].sambaUnicodePwd == "geheim"); - - println("Checking for data in destination database"); - msg = s3.db.search("(cn=Niemand)"); - assert(msg.error == 0); - assert(msg.msgs.length >= 1); - assert(msg.msgs[0].sambaSID == "S-1-5-21-4231626423-2410014848-2360679739-2001"); - assert(msg.msgs[0].displayName == "Niemand"); - - println("Adding attribute..."); - ok = ldb.modify(" -dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl -changetype: modify -add: description -description: Blah -"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - assert(ok.error == 0); - - println("Checking whether changes are still there..."); - msg = ldb.search("(cn=Niemand)"); - assert(msg.error == 0); - assert(msg.msgs.length >= 1); - assert(msg.msgs[0].cn == "Niemand"); - assert(msg.msgs[0].description == "Blah"); - - println("Modifying attribute..."); - ok = ldb.modify(" -dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl -changetype: modify -replace: description -description: Blie -"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - assert(ok.error == 0); - - println("Checking whether changes are still there..."); - msg = ldb.search("(cn=Niemand)"); - assert(msg.error == 0); - assert(msg.msgs.length >= 1); - assert(msg.msgs[0].description == "Blie"); - - println("Deleting attribute..."); - ok = ldb.modify(" -dn: cn=Niemand,cn=Users,dc=vernstok,dc=nl -changetype: modify -delete: description -"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - assert(ok.error == 0); - - println("Checking whether changes are no longer there..."); - msg = ldb.search("(cn=Niemand)"); - assert(msg.error == 0); - assert(msg.msgs.length >= 1); - assert(msg.msgs[0].description == undefined); - - println("Renaming record..."); - ok = ldb.rename("cn=Niemand,cn=Users,dc=vernstok,dc=nl", "cn=Niemand2,cn=Users,dc=vernstok,dc=nl"); - assert(ok.error == 0); - - println("Checking whether DN has changed..."); - msg = ldb.search("(cn=Niemand2)"); - assert(msg.error == 0); - assert(msg.msgs.length == 1); - assert(msg.msgs[0].dn == "cn=Niemand2,cn=Users,dc=vernstok,dc=nl"); - - println("Deleting record..."); - ok = ldb.del("cn=Niemand2,cn=Users,dc=vernstok,dc=nl"); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - - println("Checking whether record is gone..."); - msg = ldb.search("(cn=Niemand2)"); - assert(msg.error == 0); - assert(msg.msgs.length == 0); -} - -function test_map_search(ldb, s3, s4) -{ - println("Running search tests on mapped data"); - var res; - var dn; - var attrs; - - - var ldif = " -dn: " + "sambaDomainName=TESTS," + s3.BASEDN + " -objectclass: sambaDomain -objectclass: top -sambaSID: S-1-5-21-4231626423-2410014848-2360679739 -sambaNextRid: 2000 -sambaDomainName: TESTS" - ldif = substitute_var(ldif, s3); - assert(ldif != undefined); - var ok = s3.db.add(ldif); - assert(ok.error == 0); - - printf("Add a set of split records"); - var ldif = " -dn: " + s4.dn("cn=X") + " -objectClass: user -cn: X -codePage: x -revision: x -dnsHostName: x -nextRid: y -lastLogon: x -description: x -objectSid: S-1-5-21-4231626423-2410014848-2360679739-552 -primaryGroupID: 1-5-21-4231626423-2410014848-2360679739-512 - -dn: " + s4.dn("cn=Y") + " -objectClass: top -cn: Y -codePage: x -revision: x -dnsHostName: y -nextRid: y -lastLogon: y -description: x - -dn: " + s4.dn("cn=Z") + " -objectClass: top -cn: Z -codePage: x -revision: y -dnsHostName: z -nextRid: y -lastLogon: z -description: y -"; - - ldif = substitute_var(ldif, s4); - assert(ldif != undefined); - var ok = ldb.add(ldif); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - - println("Add a set of remote records"); - - var ldif = " -dn: " + s3.dn("cn=A") + " -objectClass: posixAccount -cn: A -sambaNextRid: x -sambaBadPasswordCount: x -sambaLogonTime: x -description: x -sambaSID: S-1-5-21-4231626423-2410014848-2360679739-552 -sambaPrimaryGroupSID: S-1-5-21-4231626423-2410014848-2360679739-512 - -dn: " + s3.dn("cn=B") + " -objectClass: top -cn:B -sambaNextRid: x -sambaBadPasswordCount: x -sambaLogonTime: y -description: x - -dn: " + s3.dn("cn=C") + " -objectClass: top -cn: C -sambaNextRid: x -sambaBadPasswordCount: y -sambaLogonTime: z -description: y -"; - ldif = substitute_var(ldif, s3); - assert(ldif != undefined); - var ok = s3.db.add(ldif); - assert(ok.error == 0); - - println("Testing search by DN"); - - /* Search remote record by local DN */ - dn = s4.dn("cn=A"); - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "x"); - - /* Search remote record by remote DN */ - dn = s3.dn("cn=A"); - attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime"); - res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == undefined); - assert(res.msgs[0].sambaLogonTime == "x"); - - /* Search split record by local DN */ - dn = s4.dn("cn=X"); - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].dnsHostName == "x"); - assert(res.msgs[0].lastLogon == "x"); - - /* Search split record by remote DN */ - dn = s3.dn("cn=X"); - attrs = new Array("dnsHostName", "lastLogon", "sambaLogonTime"); - res = s3.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == undefined); - assert(res.msgs[0].sambaLogonTime == "x"); - - println("Testing search by attribute"); - - /* Search by ignored attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(revision=x)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by kept attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(description=y)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=Z")); - assert(res.msgs[0].dnsHostName == "z"); - assert(res.msgs[0].lastLogon == "z"); - assert(res.msgs[1].dn == s4.dn("cn=C")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "z"); - - /* Search by renamed attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(badPwdCount=x)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by converted attribute */ - attrs = new Array("dnsHostName", "lastLogon", "objectSid"); - /* TODO: - Using the SID directly in the parse tree leads to conversion - errors, letting the search fail with no results. - res = ldb.search("(objectSid=S-1-5-21-4231626423-2410014848-2360679739-552)", NULL, ldb. SCOPE_DEFAULT, attrs); - */ - res = ldb.search("(objectSid=*)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 3); - assert(res.msgs[0].dn == s4.dn("cn=X")); - assert(res.msgs[0].dnsHostName == "x"); - assert(res.msgs[0].lastLogon == "x"); - assert(res.msgs[0].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[1].objectSid == "S-1-5-21-4231626423-2410014848-2360679739-552"); - - /* Search by generated attribute */ - /* In most cases, this even works when the mapping is missing - * a `convert_operator' by enumerating the remote db. */ - attrs = new Array("dnsHostName", "lastLogon", "primaryGroupID"); - res = ldb.search("(primaryGroupID=512)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == s4.dn("cn=A")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "x"); - assert(res.msgs[0].primaryGroupID == "512"); - - /* TODO: There should actually be two results, A and X. The - * primaryGroupID of X seems to get corrupted somewhere, and the - * objectSid isn't available during the generation of remote (!) data, - * which can be observed with the following search. Also note that Xs - * objectSid seems to be fine in the previous search for objectSid... */ - /* - res = ldb.search("(primaryGroupID=*)", NULL, ldb. SCOPE_DEFAULT, attrs); - println(res.msgs.length + " results found"); - for (i=0;i<res.msgs.length;i++) { - for (obj in res.msgs[i]) { - println(obj + ": " + res.msgs[i][obj]); - } - println("---"); - } - */ - - /* Search by remote name of renamed attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(sambaBadPasswordCount=*)", "", ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Search by objectClass */ - attrs = new Array("dnsHostName", "lastLogon", "objectClass"); - res = ldb.search("(objectClass=user)", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=X")); - assert(res.msgs[0].dnsHostName == "x"); - assert(res.msgs[0].lastLogon == "x"); - assert(res.msgs[0].objectClass != undefined); - assert(res.msgs[0].objectClass[0] == "user"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[1].objectClass != undefined); - assert(res.msgs[1].objectClass[0] == "user"); - - /* Prove that the objectClass is actually used for the search */ - res = ldb.search("(|(objectClass=user)(badPwdCount=x))", NULL, ldb. SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 3); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[0].objectClass != undefined); - for (i=0;i<res.msgs[0].objectClass.length;i++) { - assert(res.msgs[0].objectClass[i] != "user"); - } - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[1].objectClass != undefined); - assert(res.msgs[1].objectClass[0] == "user"); - assert(res.msgs[2].dn == s4.dn("cn=A")); - assert(res.msgs[2].dnsHostName == undefined); - assert(res.msgs[2].lastLogon == "x"); - assert(res.msgs[2].objectClass != undefined); - assert(res.msgs[2].objectClass[0] == "user"); - - println("Testing search by parse tree"); - - /* Search by conjunction of local attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(&(codePage=x)(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by conjunction of remote attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(&(lastLogon=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=X")); - assert(res.msgs[0].dnsHostName == "x"); - assert(res.msgs[0].lastLogon == "x"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by conjunction of local and remote attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(&(codePage=x)(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by conjunction of local and remote attribute w/o match */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(&(codePage=x)(nextRid=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - res = ldb.search("(&(revision=x)(lastLogon=z))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Search by disjunction of local attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(|(revision=x)(dnsHostName=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 2); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - - /* Search by disjunction of remote attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(|(badPwdCount=x)(lastLogon=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 3); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=A")); - assert(res.msgs[2].dnsHostName == undefined); - assert(res.msgs[2].lastLogon == "x"); - - /* Search by disjunction of local and remote attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(|(revision=x)(lastLogon=y))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 3); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=B")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "y"); - assert(res.msgs[2].dn == s4.dn("cn=X")); - assert(res.msgs[2].dnsHostName == "x"); - assert(res.msgs[2].lastLogon == "x"); - - /* Search by disjunction of local and remote attribute w/o match */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(|(codePage=y)(nextRid=z))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Search by negated local attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(revision=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 5); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=Z")); - assert(res.msgs[2].dnsHostName == "z"); - assert(res.msgs[2].lastLogon == "z"); - assert(res.msgs[3].dn == s4.dn("cn=C")); - assert(res.msgs[3].dnsHostName == undefined); - assert(res.msgs[3].lastLogon == "z"); - - /* Search by negated remote attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(description=x))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 3); - assert(res.msgs[0].dn == s4.dn("cn=Z")); - assert(res.msgs[0].dnsHostName == "z"); - assert(res.msgs[0].lastLogon == "z"); - assert(res.msgs[1].dn == s4.dn("cn=C")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "z"); - - /* Search by negated conjunction of local attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(&(codePage=x)(revision=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 5); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=Z")); - assert(res.msgs[2].dnsHostName == "z"); - assert(res.msgs[2].lastLogon == "z"); - assert(res.msgs[3].dn == s4.dn("cn=C")); - assert(res.msgs[3].dnsHostName == undefined); - assert(res.msgs[3].lastLogon == "z"); - - /* Search by negated conjunction of remote attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(&(lastLogon=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 5); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=B")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "y"); - assert(res.msgs[2].dn == s4.dn("cn=Z")); - assert(res.msgs[2].dnsHostName == "z"); - assert(res.msgs[2].lastLogon == "z"); - assert(res.msgs[3].dn == s4.dn("cn=C")); - assert(res.msgs[3].dnsHostName == undefined); - assert(res.msgs[3].lastLogon == "z"); - - /* Search by negated conjunction of local and remote attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(&(codePage=x)(description=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 5); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=Z")); - assert(res.msgs[2].dnsHostName == "z"); - assert(res.msgs[2].lastLogon == "z"); - assert(res.msgs[3].dn == s4.dn("cn=C")); - assert(res.msgs[3].dnsHostName == undefined); - assert(res.msgs[3].lastLogon == "z"); - - /* Search by negated disjunction of local attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(|(revision=x)(dnsHostName=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=A")); - assert(res.msgs[1].dnsHostName == undefined); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=Z")); - assert(res.msgs[2].dnsHostName == "z"); - assert(res.msgs[2].lastLogon == "z"); - assert(res.msgs[3].dn == s4.dn("cn=C")); - assert(res.msgs[3].dnsHostName == undefined); - assert(res.msgs[3].lastLogon == "z"); - - /* Search by negated disjunction of remote attributes */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(|(badPwdCount=x)(lastLogon=x)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 4); - assert(res.msgs[0].dn == s4.dn("cn=Y")); - assert(res.msgs[0].dnsHostName == "y"); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=Z")); - assert(res.msgs[1].dnsHostName == "z"); - assert(res.msgs[1].lastLogon == "z"); - assert(res.msgs[2].dn == s4.dn("cn=C")); - assert(res.msgs[2].dnsHostName == undefined); - assert(res.msgs[2].lastLogon == "z"); - - /* Search by negated disjunction of local and remote attribute */ - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(!(|(revision=x)(lastLogon=y)))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 4); - assert(res.msgs[0].dn == s4.dn("cn=A")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "x"); - assert(res.msgs[1].dn == s4.dn("cn=Z")); - assert(res.msgs[1].dnsHostName == "z"); - assert(res.msgs[1].lastLogon == "z"); - assert(res.msgs[2].dn == s4.dn("cn=C")); - assert(res.msgs[2].dnsHostName == undefined); - assert(res.msgs[2].lastLogon == "z"); - - println("Search by complex parse tree"); - attrs = new Array("dnsHostName", "lastLogon"); - res = ldb.search("(|(&(revision=x)(dnsHostName=x))(!(&(description=x)(nextRid=y)))(badPwdCount=y))", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 6); - assert(res.msgs[0].dn == s4.dn("cn=B")); - assert(res.msgs[0].dnsHostName == undefined); - assert(res.msgs[0].lastLogon == "y"); - assert(res.msgs[1].dn == s4.dn("cn=X")); - assert(res.msgs[1].dnsHostName == "x"); - assert(res.msgs[1].lastLogon == "x"); - assert(res.msgs[2].dn == s4.dn("cn=A")); - assert(res.msgs[2].dnsHostName == undefined); - assert(res.msgs[2].lastLogon == "x"); - assert(res.msgs[3].dn == s4.dn("cn=Z")); - assert(res.msgs[3].dnsHostName == "z"); - assert(res.msgs[3].lastLogon == "z"); - assert(res.msgs[4].dn == s4.dn("cn=C")); - assert(res.msgs[4].dnsHostName == undefined); - assert(res.msgs[4].lastLogon == "z"); - - /* Clean up */ - var dns = new Array(); - dns[0] = s4.dn("cn=A"); - dns[1] = s4.dn("cn=B"); - dns[2] = s4.dn("cn=C"); - dns[3] = s4.dn("cn=X"); - dns[4] = s4.dn("cn=Y"); - dns[5] = s4.dn("cn=Z"); - for (i=0;i<dns.length;i++) { - var ok = ldb.del(dns[i]); - assert(ok.error == 0); - } -} - -function test_map_modify(ldb, s3, s4) -{ - println("Running modification tests on mapped data"); - - var ldif; - var attrs; - var dn, dn2; - var res; - var ok; - - println("Testing modification of local records"); - - /* Add local record */ - dn = "cn=test,dc=idealx,dc=org"; - ldif = " -dn: " + dn + " -cn: test -foo: bar -revision: 1 -description: test -"; - ok = ldb.add(ldif); - assert(ok.error == 0); - /* Check it's there */ - attrs = new Array("foo", "revision", "description"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].foo == "bar"); - assert(res.msgs[0].revision == "1"); - assert(res.msgs[0].description == "test"); - /* Check it's not in the local db */ - res = s4.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - /* Check it's not in the remote db */ - res = s3.db.search("(cn=test)", NULL, ldb.SCOPE_DEFAULT, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Modify local record */ - ldif = " -dn: " + dn + " -replace: foo -foo: baz -replace: description -description: foo -"; - ok = ldb.modify(ldif); - assert(ok.error == 0); - /* Check in local db */ - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].foo == "baz"); - assert(res.msgs[0].revision == "1"); - assert(res.msgs[0].description == "foo"); - - /* Rename local record */ - dn2 = "cn=toast,dc=idealx,dc=org"; - ok = ldb.rename(dn, dn2); - assert(ok.error == 0); - /* Check in local db */ - res = ldb.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].foo == "baz"); - assert(res.msgs[0].revision == "1"); - assert(res.msgs[0].description == "foo"); - - /* Delete local record */ - ok = ldb.del(dn2); - assert(ok.error == 0); - /* Check it's gone */ - res = ldb.search("", dn2, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); - - println("Testing modification of remote records"); - - /* Add remote record */ - dn = s4.dn("cn=test"); - dn2 = s3.dn("cn=test"); - ldif = " -dn: " + dn2 + " -cn: test -description: foo -sambaBadPasswordCount: 3 -sambaNextRid: 1001 -"; - ok = s3.db.add(ldif); - assert(ok.error == 0); - /* Check it's there */ - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "foo"); - assert(res.msgs[0].sambaBadPasswordCount == "3"); - assert(res.msgs[0].sambaNextRid == "1001"); - /* Check in mapped db */ - attrs = new Array("description", "badPwdCount", "nextRid"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "foo"); - assert(res.msgs[0].badPwdCount == "3"); - assert(res.msgs[0].nextRid == "1001"); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Modify remote data of remote record */ - ldif = " -dn: " + dn + " -replace: description -description: test -replace: badPwdCount -badPwdCount: 4 -"; - ok = ldb.modify(ldif); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - /* Check in mapped db */ - attrs = new Array("description", "badPwdCount", "nextRid"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].badPwdCount == "4"); - assert(res.msgs[0].nextRid == "1001"); - /* Check in remote db */ - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].sambaBadPasswordCount == "4"); - assert(res.msgs[0].sambaNextRid == "1001"); - - /* Rename remote record */ - dn2 = s4.dn("cn=toast"); - ok = ldb.rename(dn, dn2); - assert(ok.error == 0); - /* Check in mapped db */ - dn = dn2; - attrs = new Array("description", "badPwdCount", "nextRid"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].badPwdCount == "4"); - assert(res.msgs[0].nextRid == "1001"); - /* Check in remote db */ - dn2 = s3.dn("cn=toast"); - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].sambaBadPasswordCount == "4"); - assert(res.msgs[0].sambaNextRid == "1001"); - - /* Delete remote record */ - ok = ldb.del(dn); - assert(ok.error == 0); - /* Check in mapped db */ - res = ldb.search("", dn, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); - /* Check in remote db */ - res = s3.db.search("", dn2, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); - - /* Add remote record (same as before) */ - dn = s4.dn("cn=test"); - dn2 = s3.dn("cn=test"); - ldif = " -dn: " + dn2 + " -cn: test -description: foo -sambaBadPasswordCount: 3 -sambaNextRid: 1001 -"; - ok = s3.db.add(ldif); - assert(ok.error == 0); - - /* Modify local data of remote record */ - ldif = " -dn: " + dn + " -add: revision -revision: 1 -replace: description -description: test -"; - ok = ldb.modify(ldif); - if (ok.error != 0) { - println(ok.errstr); - assert(ok.error == 0); - } - /* Check in mapped db */ - attrs = new Array("revision", "description"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].revision == "1"); - /* Check in remote db */ - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].revision == undefined); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == undefined); - assert(res.msgs[0].revision == "1"); - - /* Delete (newly) split record */ - ok = ldb.del(dn); - assert(ok.error == 0); - - println("Testing modification of split records"); - - /* Add split record */ - dn = s4.dn("cn=test"); - dn2 = s3.dn("cn=test"); - ldif = " -dn: " + dn + " -cn: test -description: foo -badPwdCount: 3 -nextRid: 1001 -revision: 1 -"; - ok = ldb.add(ldif); - assert(ok.error == 0); - /* Check it's there */ - attrs = new Array("description", "badPwdCount", "nextRid", "revision"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "foo"); - assert(res.msgs[0].badPwdCount == "3"); - assert(res.msgs[0].nextRid == "1001"); - assert(res.msgs[0].revision == "1"); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == undefined); - assert(res.msgs[0].badPwdCount == undefined); - assert(res.msgs[0].nextRid == undefined); - assert(res.msgs[0].revision == "1"); - /* Check in remote db */ - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "foo"); - assert(res.msgs[0].sambaBadPasswordCount == "3"); - assert(res.msgs[0].sambaNextRid == "1001"); - assert(res.msgs[0].revision == undefined); - - /* Modify of split record */ - ldif = " -dn: " + dn + " -replace: description -description: test -replace: badPwdCount -badPwdCount: 4 -replace: revision -revision: 2 -"; - ok = ldb.modify(ldif); - assert(ok.error == 0); - /* Check in mapped db */ - attrs = new Array("description", "badPwdCount", "nextRid", "revision"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].badPwdCount == "4"); - assert(res.msgs[0].nextRid == "1001"); - assert(res.msgs[0].revision == "2"); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == undefined); - assert(res.msgs[0].badPwdCount == undefined); - assert(res.msgs[0].nextRid == undefined); - assert(res.msgs[0].revision == "2"); - /* Check in remote db */ - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].sambaBadPasswordCount == "4"); - assert(res.msgs[0].sambaNextRid == "1001"); - assert(res.msgs[0].revision == undefined); - - /* Rename split record */ - dn2 = s4.dn("cn=toast"); - ok = ldb.rename(dn, dn2); - assert(ok.error == 0); - /* Check in mapped db */ - dn = dn2; - attrs = new Array("description", "badPwdCount", "nextRid", "revision"); - res = ldb.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].badPwdCount == "4"); - assert(res.msgs[0].nextRid == "1001"); - assert(res.msgs[0].revision == "2"); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn); - assert(res.msgs[0].description == undefined); - assert(res.msgs[0].badPwdCount == undefined); - assert(res.msgs[0].nextRid == undefined); - assert(res.msgs[0].revision == "2"); - /* Check in remote db */ - dn2 = s3.dn("cn=toast"); - attrs = new Array("description", "sambaBadPasswordCount", "sambaNextRid", "revision"); - res = s3.db.search("", dn2, ldb.SCOPE_BASE, attrs); - assert(res.error == 0); - assert(res.msgs.length == 1); - assert(res.msgs[0].dn == dn2); - assert(res.msgs[0].description == "test"); - assert(res.msgs[0].sambaBadPasswordCount == "4"); - assert(res.msgs[0].sambaNextRid == "1001"); - assert(res.msgs[0].revision == undefined); - - /* Delete split record */ - ok = ldb.del(dn); - assert(ok.error == 0); - /* Check in mapped db */ - res = ldb.search("", dn, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); - /* Check in local db */ - res = s4.db.search("", dn, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); - /* Check in remote db */ - res = s3.db.search("", dn2, ldb.SCOPE_BASE); - assert(res.error == 0); - assert(res.msgs.length == 0); -} - -function make_dn(rdn) -{ - return rdn + ",sambaDomainName=TESTS," + this.BASEDN; -} - -function make_s4dn(rdn) -{ - return rdn + "," + this.BASEDN; -} - -var ldb = ldb_init(); - -sys = sys_init(); -var ldbfile = prefix + "/" + "test.ldb"; -var ldburl = "tdb://" + ldbfile; - -var samba4 = new Object("samba4 partition info"); -samba4.file = prefix + "/" + "samba4.ldb"; -samba4.url = "tdb://" + samba4.file; -samba4.BASEDN = "dc=vernstok,dc=nl"; -samba4.db = ldb_init(); -samba4.dn = make_s4dn; - -var samba3 = new Object("samba3 partition info"); -samba3.file = prefix + "/" + "samba3.ldb"; -samba3.url = "tdb://" + samba3.file; -samba3.BASEDN = "cn=Samba3Sam"; -samba3.db = ldb_init(); -samba3.dn = make_dn; - -var templates = new Object("templates partition info"); -templates.file = prefix + "/" + "templates.ldb"; -templates.url = "tdb://" + templates.file; -templates.BASEDN = "cn=templates"; -templates.db = ldb_init(); - -sys.unlink(ldbfile); -sys.unlink(samba3.file); -sys.unlink(templates.file); -sys.unlink(samba4.file); - -var ok = ldb.connect(ldburl); -assert(ok); -var ok = samba3.db.connect(samba3.url); -assert(ok); -var ok = templates.db.connect(templates.url); -assert(ok); -var ok = samba4.db.connect(samba4.url); -assert(ok); - -setup_data(samba3, sys.file_load(datadir + "/" + "samba3.ldif")); -setup_data(templates, sys.file_load(datadir + "/" + "provision_samba3sam_templates.ldif")); -setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "/" + "provision_samba3sam.ldif")); - -ldb = ldb_init(); -var ok = ldb.connect(ldburl); -assert(ok); - -test_s3sam_search(ldb); -test_s3sam_modify(ldb, samba3); - -sys.unlink(ldbfile); -sys.unlink(samba3.file); -sys.unlink(templates.file); -sys.unlink(samba4.file); - -ldb = ldb_init(); -var ok = ldb.connect(ldburl); -assert(ok); -samba3.db = ldb_init(); -var ok = samba3.db.connect(samba3.url); -assert(ok); -templates.db = ldb_init(); -var ok = templates.db.connect(templates.url); -assert(ok); -samba4.db = ldb_init(); -var ok = samba4.db.connect(samba4.url); -assert(ok); - -setup_data(templates, sys.file_load(datadir + "/" + "provision_samba3sam_templates.ldif")); -setup_modules(ldb, samba3, samba4, sys.file_load(datadir + "provision_samba3sam.ldif")); - -ldb = ldb_init(); -var ok = ldb.connect(ldburl); -assert(ok); - -test_map_search(ldb, samba3, samba4); -test_map_modify(ldb, samba3, samba4); - -sys.unlink(ldbfile); -sys.unlink(samba3.file); -sys.unlink(samba4.file); - -return 0; diff --git a/testprogs/ejs/sprintf.js b/testprogs/ejs/sprintf.js deleted file mode 100755 index 6ae8605718..0000000000 --- a/testprogs/ejs/sprintf.js +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env smbscript -/* - test sprintf function -*/ - -string_init(local); - -function check_result(s, v) -{ - if (s != v) { - println("expected '" + v + "' but got '" + s + "'"); - } - assert(s == v); -} - -function xprintf() -{ - return "XX{" + vsprintf(arguments) + "}XX"; -} - -check_result(sprintf("%d", 7), "7"); -check_result(sprintf("%04d", 42), "0042"); -check_result(sprintf("my string=%7.2s", "foo%7"), "my string= fo"); -check_result(sprintf("blah=0x%*x", 4, 19), "blah=0x 13"); -check_result(sprintf("blah=0x%0*x", 4, 19), "blah=0x0013"); -check_result(sprintf("blah=%.0f", 1032), "blah=1032"); -check_result(sprintf("%4.2f%%", 72.32), "72.32%"); - -check_result(xprintf("%4.2f%% and %s", 72.32, "foo"),"XX{72.32% and foo}XX"); - -println("ALL OK"); |