summaryrefslogtreecommitdiffstats
path: root/lib/libadmin
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libadmin')
-rw-r--r--lib/libadmin/Makefile61
-rw-r--r--lib/libadmin/authdb.c2467
-rw-r--r--lib/libadmin/error.c109
-rw-r--r--lib/libadmin/strlist.c46
-rw-r--r--lib/libadmin/template.c820
-rw-r--r--lib/libadmin/util.c1340
6 files changed, 4843 insertions, 0 deletions
diff --git a/lib/libadmin/Makefile b/lib/libadmin/Makefile
new file mode 100644
index 00000000..68029ce2
--- /dev/null
+++ b/lib/libadmin/Makefile
@@ -0,0 +1,61 @@
+#
+# BEGIN COPYRIGHT BLOCK
+# Copyright 2001 Sun Microsystems, Inc.
+# Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+# All rights reserved.
+# END COPYRIGHT BLOCK
+#
+# The admin libraries
+
+MCOM_ROOT=../../..
+
+MODULE=LibAdmin
+MODULE_CFLAGS=-DENCRYPT_PASSWORDS -DUSE_ADMSERV
+
+include ../../nsdefs.mk
+
+OBJDEST=$(OBJDIR)/lib/libadmin
+
+ifeq ($(ARCH), WINNT)
+LIBS=$(OBJDIR)/lib/libadmin.lib
+else
+LIBS=$(OBJDIR)/lib/libadmin.a
+endif
+
+OBJS=$(addprefix $(OBJDEST)/, admconf.o form_get.o error.o admlog.o \
+ magconf.o ns-util.o objconf.o password.o \
+ referer.o template.o util.o \
+ hinstall.o admserv.o install.o nsnews.o \
+ commit.o pcontrol.o get_msg.o \
+ multconf.o httpcon.o authdb.o usrlists.o \
+ dstats.o backup.o cluster.o \
+ keyconf.o strlist.o $(OSOBJS))
+
+# moved files [to libadminutil] : form_post.o strlist.o distadm.o cron_conf.o
+# candidate for moing: admlog.o error.o admserv.o
+# replaced files: error.o [by libadminutil/errRpt.c]
+# removed for lack of ndbm support from binary release of libdbm.... userdb.o
+#!! nsnews.o does not work anymore.
+
+all: $(OBJDEST) $(LIBS)
+
+$(LIBS): $(addprefix $(MCOM_ROOT)/ldapserver/include/libadmin/, \
+ hadm_msgs.i la_msgs.i)
+
+include ../../nsconfig.mk
+
+MCC_INCLUDE += $(ADMINUTIL_INCLUDE)
+
+ifeq ($(ARCH), HPUX)
+CC=$(CCC)
+endif
+
+$(OBJDEST):
+ mkdir -p $(OBJDEST)
+
+$(LIBS): $(OBJS)
+ rm -f $@
+ $(AR) $(OBJS)
+ $(RANLIB) $@
+
+include $(INCLUDE_DEPENDS)
diff --git a/lib/libadmin/authdb.c b/lib/libadmin/authdb.c
new file mode 100644
index 00000000..8aff4ca8
--- /dev/null
+++ b/lib/libadmin/authdb.c
@@ -0,0 +1,2467 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * authdb.c: Functions to aid in user/group database admin
+ *
+ * These things leak memory like a sieve.
+ *
+ * Ben Polk
+ * (blame Mike McCool for functions with an MLM)
+ */
+
+#ifdef XP_UNIX
+#include <dirent.h>
+#endif /* WIN32? */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+#include <stdio.h>
+#include "base/shexp.h"
+#include "base/util.h"
+#include "libadminutil/admutil.h"
+#include "libadmin/libadmin.h"
+
+#include "libaccess/nsgmgmt.h"
+#include "libaccess/nsumgmt.h"
+/* XXX MLM - This shouldn't have to define itself as private. */
+#define __PRIVATE_NSADB
+#include "libaccess/nsadb.h"
+#include "libaccess/nsamgmt.h"
+#include "libaccess/aclerror.h"
+#include "libaccess/aclbuild.h"
+#include "libaccess/acladmin.h"
+#include "usrlists.h"
+
+#define BUF_SIZE 10
+
+void list_authdbs(char *fullpath, char *partialpath);
+
+static char **list;
+static int listsize;
+static int curentry;
+
+/*
+ * Rights we know about. This should be moved out to some
+ * external location. Perhaps obj.conf?
+ */
+NSAPI_PUBLIC char *acl_read_rights[] =
+{
+ "GET",
+ "HEAD",
+ "POST",
+ "INDEX",
+#ifdef MCC_PROXY
+ "CONNECT",
+#endif
+ NULL
+};
+
+NSAPI_PUBLIC char *acl_write_rights[] =
+{
+ "PUT",
+ "DELETE",
+ "MKDIR",
+ "RMDIR",
+ "MOVE",
+ NULL
+};
+
+
+/*
+ * passfilter - function returns non-zero if the regular expression
+ * passed in matches the string passed in.
+ */
+static int passfilter(char *str, char *regexp)
+{
+ if (!str)
+ return 0; /* NULL string never matches */
+ else if (!regexp)
+ return 1; /* NULL regexp matches everything */
+ else
+ return(!shexp_casecmp(str, regexp));
+}
+
+NSAPI_PUBLIC char **list_auth_dbs(char *fullpath)
+{
+ list = new_strlist(BUF_SIZE);
+ listsize = BUF_SIZE;
+ curentry = 0;
+ list_authdbs(fullpath, "");
+
+ return(list);
+}
+
+NSAPI_PUBLIC void output_authdb_selector(char *path, char *element, char *current) {
+ char **pathlist = list_auth_dbs(path);
+ int currentnum = -1;
+ int plen = path ? strlen(path) : 0;
+ register int x;
+
+ /*
+ * If the 'current' string begins with the 'path' string, remove the
+ * 'path' prefix.
+ */
+ if (!strncmp(current, path, plen)) {
+ current += plen;
+ if (*current == FILE_PATHSEP) ++current;
+ }
+
+ if (pathlist[0]) /* Is there at least one database? */
+ {
+ /* Find current selection in list of databases. */
+ for(x=0; pathlist[x]; x++) {
+ if(!strcmp(current, pathlist[x])) {
+ currentnum = x;
+ continue;
+ }
+ }
+
+/* BONEHEAD */
+ fprintf(stdout, "<SELECT name=\"%s\" %s>",
+ element, (x>SELECT_OVERFLOW) ? "size=5" : "");
+
+ /* If the current selection is in there, put it first. */
+ if(currentnum != -1) {
+ fprintf(stdout, "<OPTION value=\"%s\" SELECTED>%s\n",
+ pathlist[currentnum], pathlist[currentnum]);
+
+ }
+ for(x=0; pathlist[x]; x++) {
+ if (x == currentnum)
+ continue;
+
+ fprintf(stdout, "<OPTION value=\"%s\">%s\n",
+ pathlist[x], pathlist[x]);
+ }
+ fprintf(stdout, "</SELECT>");
+ } else {
+ fprintf(stdout, "<b>No databases found.</b>");
+ }
+}
+
+NSAPI_PUBLIC char *get_current_authdb()
+{
+ char **config = get_adm_config();
+ return(STRDUP(config[3]));
+}
+
+NSAPI_PUBLIC void set_current_authdb(char *current)
+{
+ char **config = get_adm_config();
+ config[3] = STRDUP(current);
+ write_adm_config(config);
+}
+
+void list_authdbs(char *fullpath, char *partialpath)
+{
+ int stat_good;
+ struct stat finfo;
+ char **dirlisting;
+ char *path = (char *)MALLOC(strlen(fullpath)+strlen(partialpath)+2);
+
+ sprintf(path, "%s%c%s", fullpath, FILE_PATHSEP, partialpath);
+ if( !(dirlisting = list_directory(path,0)))
+ return;
+ else {
+ register int x;
+ char *entry, *newppath;
+
+ for(x=0; dirlisting[x]; x++) {
+ entry = (char *)MALLOC(strlen(path)+strlen(dirlisting[x])+2);
+ sprintf(entry, "%s%s", path, dirlisting[x]);
+
+#ifdef XP_UNIX
+ stat_good = (lstat(entry, &finfo) == -1 ? 0 : 1);
+#else /* WIN32 */
+ stat_good = (stat(entry, &finfo) == -1 ? 0 : 1);
+#endif /* XP_UNIX */
+
+ if(!stat_good)
+ continue;
+ newppath = (char *)MALLOC(strlen(partialpath)+strlen(dirlisting[x])+3);
+
+ if(S_ISDIR(finfo.st_mode)) {
+ sprintf(newppath, "%s%s", partialpath, dirlisting[x]);
+ curentry++;
+
+ if(!(curentry < listsize)) {
+ listsize += BUF_SIZE;
+ list = grow_strlist(list, listsize);
+ }
+ list[curentry-1] = STRDUP(newppath);
+ list[curentry] = NULL;
+ }
+
+ FREE(entry);
+ FREE(newppath);
+ }
+ }
+}
+
+/* Get the userdb directory. (V1.x) */
+NSAPI_PUBLIC char *get_userdb_dir(void)
+{
+ char *userdb;
+ char line[BIG_LINE];
+
+#ifdef USE_ADMSERV
+ char *tmp = getenv("NETSITE_ROOT");
+
+ sprintf(line, "%s%cuserdb", tmp, FILE_PATHSEP);
+#else
+ char *tmp = get_mag_var("#ServerRoot");
+
+ sprintf(line, "%s%cadmin%cuserdb", tmp, FILE_PATHSEP, FILE_PATHSEP);
+#endif
+ userdb = STRDUP(line);
+ return userdb;
+}
+
+/* Get the httpacl directory. (V2.x) */
+NSAPI_PUBLIC char *get_httpacl_dir(void)
+{
+ char *httpacl;
+ char line[BIG_LINE];
+
+#ifdef USE_ADMSERV
+ char *tmp = getenv("NETSITE_ROOT");
+
+ sprintf(line, "%s%chttpacl", tmp, FILE_PATHSEP);
+#else
+ char *tmp = get_mag_var("#ServerRoot");
+
+ sprintf(line, "%s%cadmin%chttpacl", tmp, FILE_PATHSEP, FILE_PATHSEP);
+#endif
+ httpacl = STRDUP(line);
+ return httpacl;
+}
+
+/* Get the authdb directory. (V2.x) */
+NSAPI_PUBLIC char *get_authdb_dir(void)
+{
+ char *authdb;
+ char line[BIG_LINE];
+
+#ifdef USE_ADMSERV
+ char *tmp = getenv("NETSITE_ROOT");
+
+ sprintf(line, "%s%cauthdb", tmp, FILE_PATHSEP);
+#else
+ char *tmp = get_mag_var("#ServerRoot");
+
+ sprintf(line, "%s%cadmin%cauthdb", tmp, FILE_PATHSEP, FILE_PATHSEP);
+#endif
+ authdb = STRDUP(line);
+ return authdb;
+}
+/*
+ * groupOrUser - function sets its return variable flags
+ * based on whether the name passed in is
+ * a user or a group in the specified database.
+ * It could be both, although the entry form
+ * are intended to prohibit this.
+ * Returns: 0 if no error occurs, something else otherwise.
+ */
+NSAPI_PUBLIC int groupOrUser(char *db_path, char *name, int *is_user, int *is_group)
+{
+ int rv = 1;
+ UserObj_t *uoptr;
+ GroupObj_t *goptr;
+ void *padb;
+
+ if (name && is_user && is_group) {
+ *is_user = 0;
+ *is_group = 0;
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (!rv) {
+
+ rv = nsadbFindByName(NULL, padb, name, AIF_USER, (void **)&uoptr);
+ if (rv == AIF_USER) {
+ *is_user = 1;
+ }
+
+ rv = nsadbFindByName(NULL, padb, name, AIF_GROUP, (void **)&goptr);
+ if (rv == AIF_GROUP) {
+ *is_group = 1;
+ }
+
+ nsadbClose(padb, 0);
+ }
+ }
+
+ return rv;
+}
+
+/*
+ * getfullname - function to get the fullname of a user.
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int getfullname(char *db_path, char *user, char **fullname) {
+ int rv;
+ UserObj_t *uoptr;
+ void *padb;
+
+ if (db_path && user)
+ {
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv == 0) {
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (rv == AIF_USER) {
+ *fullname = (uoptr->uo_rname != 0) ? STRDUP((char *)uoptr->uo_rname)
+ : STRDUP("");
+ }
+ else
+ rv = 1;
+ nsadbClose(padb, 0);
+ }
+ }
+ else
+ rv = 1;
+
+ return rv;
+}
+
+/*
+ * setfullname - function to set the fullname for the specified user.
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int setfullname(char *db_path, char *user, char *fullname) {
+ int rv;
+ UserObj_t *uoptr;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to update "
+ "the user's fullname in the database.");
+ } else {
+ /* See if the user already exists, if so, update it. */
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (rv == AIF_USER) {
+ uoptr->uo_rname = (NTS_t)fullname;
+ } else {
+ /* User doesn't exist, so we've failed. */
+ report_error(SYSTEM_ERROR, user,
+ "Unable to change this user's fullname, "
+ "user was not found in the database.");
+ rv = 1;
+ }
+
+ if (uoptr) {
+ rv = nsadbModifyUser(NULL, padb, uoptr);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, user,
+ "A database error occurred while "
+ "trying to change the user fullname.");
+ }
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/* Set a user's login name MLM*/
+NSAPI_PUBLIC int setusername(char *db_path, char *user, char *newname) {
+ int rv;
+ UserObj_t *uoptr;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to update "
+ "the user's fullname in the database.");
+ } else {
+ /* See if the user already exists, if so, update it. */
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (rv != AIF_USER) {
+ /* User doesn't exist, so we've failed. */
+ report_error(SYSTEM_ERROR, user,
+ "Unable to change this user's fullname, "
+ "user was not found in the database.");
+ rv = 1;
+ }
+ if (uoptr) {
+ rv = userRename(NULL, ((AuthDB_t *)padb)->adb_userdb,
+ uoptr, (NTS_t)newname);
+
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, user,
+ "A database error occurred while "
+ "trying to change the login name.");
+ }
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * addusertogroup - function to add a user to a group
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int addusertogroup(char *db_path, char *user, char *group) {
+ int rv;
+ UserObj_t *uoptr;
+ GroupObj_t *goptr;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to add "
+ "user to a group.");
+ } else {
+ /* See if the user and group exist. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (goptr == 0) {
+ report_error(INCORRECT_USAGE, group,
+ "The group was not found.");
+ }
+ else if (uoptr == 0) {
+ report_error(INCORRECT_USAGE, user,
+ "The user was not found.");
+ }
+ else {
+ rv = nsadbAddUserToGroup(NULL, padb, goptr, uoptr);
+ }
+
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * addgrouptogroup - function to add a group to a group
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int addgrouptogroup(char *db_path, char *memgroup, char *group) {
+ int rv;
+ GroupObj_t *goptr;
+ GroupObj_t *mem_goptr;
+ void *padb;
+
+ if (!strcmp(memgroup, group)) {
+ report_error(INCORRECT_USAGE, group,
+ "You can't add a group to itself.");
+ }
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to add "
+ "group to a group.");
+ } else {
+ /* See if the groups exist. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ rv = nsadbFindByName(NULL,
+ padb, memgroup, AIF_GROUP, (void **)&mem_goptr);
+ if (goptr == 0) {
+ report_error(INCORRECT_USAGE, group,
+ "The target group was not found.");
+ }
+ else if (mem_goptr == 0) {
+ report_error(INCORRECT_USAGE, memgroup,
+ "The group to add was not found.");
+ }
+ else {
+ rv = nsadbAddGroupToGroup(NULL, padb, goptr, mem_goptr);
+ }
+
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * remuserfromgroup - function to remove a user from a group
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int remuserfromgroup(char *db_path, char *user, char *group) {
+ int rv;
+ UserObj_t *uoptr;
+ GroupObj_t *goptr;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to add "
+ "user to a group.");
+ } else {
+ /* See if the user and group exist. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (goptr == 0) {
+ report_error(SYSTEM_ERROR, group,
+ "The group was not found.");
+ }
+ else if (uoptr == 0) {
+ report_error(SYSTEM_ERROR, user,
+ "The user was not found.");
+ }
+ else {
+ rv = nsadbRemUserFromGroup(NULL, padb, goptr, uoptr);
+ if (rv)
+ report_error(SYSTEM_ERROR, "Error taking out user",
+ "An error occured trying to take "
+ "the user out of the group.");
+ }
+
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * remgroupfromgroup - function to remove a group to a group
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int remgroupfromgroup(char *db_path, char *memgroup, char *group) {
+ int rv;
+ GroupObj_t *goptr;
+ GroupObj_t *mem_goptr;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to remove "
+ "a group from a group.");
+ } else {
+ /* See if the groups exist. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ rv = nsadbFindByName(NULL,
+ padb, memgroup, AIF_GROUP, (void **)&mem_goptr);
+ if (goptr == 0) {
+ report_error(SYSTEM_ERROR, group,
+ "The target group was not found.");
+ }
+ else if (mem_goptr == 0) {
+ report_error(SYSTEM_ERROR, memgroup,
+ "The group to remove was not found.");
+ }
+ else {
+ rv = nsadbRemGroupFromGroup(NULL, padb, goptr, mem_goptr);
+ }
+
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * setpw - function to set the password for the specified user.
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int setpw(char *db_path, char *user, char *pwd) {
+ int rv;
+ UserObj_t *uoptr = 0;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to add "
+ "the password to the database.");
+ } else {
+ /* See if the user already exists, if so, update it. */
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (uoptr != 0) {
+ uoptr->uo_pwd = (NTS_t)STRDUP(pw_enc(pwd));
+ } else {
+ /* User doesn't exist, so we've failed. */
+ report_error(SYSTEM_ERROR, user,
+ "Unable to change this user's password, "
+ "user was not found in the database.");
+ rv = 1;
+ }
+
+ if (uoptr) {
+ rv = nsadbModifyUser(NULL, padb, uoptr);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, user,
+ "A database error occurred while "
+ "trying to change the user password.");
+ }
+ nsadbClose(padb, 0);
+ }
+ return rv;
+}
+
+/*
+ * setdbpw - function to set the password on the special user
+ * who's password is used as the database password.
+ * If the password passed in is NULL, the user is
+ * removed or not created.
+ * If the password is not NULL, then the user will
+ * be created if needed, and it's password set to
+ * the one passed in.
+ *
+ * Return: Returns 0 if it works, something else if it fails.
+ */
+NSAPI_PUBLIC int setdbpw(char *db_path, char *pwd)
+{
+ int rv;
+ UserObj_t *uoptr = 0;
+ void *padb;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Open Database",
+ "An error occurred while trying to add "
+ "the password to the database.");
+ }
+ /*
+ * If NULL pwd, remove the user if it exists.
+ */
+ else if (pwd == NULL) {
+ rv = nsadbRemoveUser(NULL, padb, DBPW_USER);
+ nsadbClose(padb, 0);
+
+ /*
+ * If we get success(0) or a no such user error(NSAERRNAME)
+ * we're happy.
+ */
+ if (rv != 0 && rv != NSAERRNAME) {
+ report_error(SYSTEM_ERROR, "Remove Password Failed",
+ "An error occurred while trying to remove "
+ "the password for the database.");
+ }
+ } else {
+ /* See if the user already exists, if so, just update it. */
+ rv = nsadbFindByName(NULL, padb, DBPW_USER, AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ /* User doesn't exist, so add it. */
+ uoptr = userCreate((NTS_t)DBPW_USER, (NTS_t)pw_enc(pwd), (NTS_t)DBPW_USER);
+ if (uoptr == 0) {
+ report_error(SYSTEM_ERROR, "Failed To Update Database",
+ "An error occurred while trying to add "
+ "the password to the database.");
+ rv = 1;
+ }
+ else {
+ rv = nsadbCreateUser(NULL, padb, uoptr);
+ }
+ } else {
+ uoptr->uo_pwd = (NTS_t)STRDUP(pw_enc(pwd));
+ rv = nsadbModifyUser(NULL, padb, uoptr);
+ }
+
+ nsadbClose(padb, 0);
+
+ if (uoptr) {
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, "Failed To Set Database Password",
+ "An error occurred while trying to save "
+ "the password in the database.");
+ rv = 1;
+ }
+ userFree(uoptr);
+ }
+ }
+ return rv;
+}
+
+/*
+ * checkdbpw - Return TRUE if the password is correct, or database
+ * doesn't have one, because the password user isn't there.
+ * Return FALSE if required password is not correct.
+ */
+NSAPI_PUBLIC int checkdbpw(char *db_path, char *pwd)
+{
+ int rv;
+ UserObj_t *uoptr = 0;
+ void *padb;
+ int fpwOK = 0;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv == 0) {
+ rv = nsadbFindByName(NULL, padb, DBPW_USER, AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ fpwOK = 1; /* Password userid isn't there, so none required. */
+ } else {
+ if (pwd == NULL)
+ fpwOK = 0; /* PW user exists, no pw passed in, return false. */
+ else {
+ if (pw_cmp(pwd, (char *)uoptr->uo_pwd))
+ fpwOK = 0; /* passwords are different, so return false. */
+ else
+ fpwOK = 1; /* passwords are the same, so return true. */
+ }
+ userFree(uoptr);
+ }
+ nsadbClose(padb, 0);
+ }
+ return fpwOK;
+}
+
+/*
+ * Create a link to another CGI:
+ * val - value text on the link
+ * targ - name of the CGI to start
+ * arg - argument to pass to the CGI
+ */
+void output_cgi_link(char *val, char *trg, char *arg)
+{
+ char line[BIG_LINE];
+ sprintf(line, "%s?%s", trg, arg);
+ printf("<a href=index?options+acss+%s target='options'>%s</a>",
+ util_uri_escape(NULL, line), val);
+}
+
+/*
+ * groupEnumCB - callback function from libaccess group enumerator
+ */
+static int groupEnumCB (NSErr_t * errp,
+ void * padb, void *parg, GroupObj_t *goptr)
+{
+ if (goptr && goptr->go_name && strlen((char *)goptr->go_name))
+ ulsAddToList(parg, goptr->go_gid, (char *)goptr->go_name);
+
+ return 0; /* 0: continue enumeration */
+}
+
+/*
+ * userEnumCB - callback function from libaccess group enumerator
+ */
+static int userEnumCB (NSErr_t * errp,
+ void * padb, void *parg, UserObj_t *uoptr)
+{
+ if (uoptr && uoptr->uo_name && strlen((char *)uoptr->uo_name))
+ ulsAddToList(parg, uoptr->uo_uid, (char *)uoptr->uo_name);
+
+ return 0; /* 0: continue enumeration */
+}
+
+/*
+ * idfound - horribly inefficient scan through the idlist table
+ * returning true if the specified id is found, false
+ * otherwise.
+ */
+int idfound(int id, int *idlist, int count)
+{
+ int i;
+ for (i = 0; i < count; ++i) {
+ if (id == idlist[i])
+ return 1;
+ }
+ return 0;
+}
+
+void output_groups_user_is_in(char *db_path, char *user)
+{
+ int rv;
+ UserObj_t *uoptr = 0;
+ GroupObj_t *goptr = 0;
+ void *padb;
+ USI_t *gidlist;
+ int i;
+ int id;
+ char *group;
+ char *gname;
+ int groupCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list group membership.");
+ } else {
+ /* See if the user exists. */
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ /* User doesn't exist, so we've failed. */
+ report_error(SYSTEM_ERROR, user,
+ "Unable to find user when trying to "
+ "list group membership.");
+ rv = 1;
+ } else {
+ groupCount = UILCOUNT(&uoptr->uo_groups);
+ if (groupCount > 0) {
+ void *DirectlyInList;
+ void *IndirectlyInList;
+ ulsAlloc(&DirectlyInList);
+ ulsAlloc(&IndirectlyInList);
+
+ gidlist = UILLIST(&uoptr->uo_groups);
+ for (i = 0; i < groupCount; ++i) {
+ rv = nsadbIdToName(NULL,
+ padb, gidlist[i], AIF_GROUP, &gname);
+ if (rv >= 0) {
+ rv = nsadbFindByName(NULL, padb, gname, AIF_GROUP,
+ (void **)&goptr);
+ }
+ if (goptr != 0) {
+ if (goptr->go_name && strlen((char *)goptr->go_name)) {
+ if (idfound(uoptr->uo_uid,
+ (int*)UILLIST(&goptr->go_users),
+ UILCOUNT(&goptr->go_users))) {
+ ulsAddToList(DirectlyInList, goptr->go_gid,
+ (char *)goptr->go_name);
+ }
+ else {
+ ulsAddToList(IndirectlyInList, goptr->go_gid,
+ (char *)goptr->go_name);
+ }
+ }
+ groupFree(goptr);
+ goptr = 0;
+ }
+ }
+ ulsSortName(DirectlyInList);
+ ulsGetCount(DirectlyInList, &groupCount);
+ for (i=0; i<groupCount; ++i) {
+ group = NULL;
+ ulsGetEntry(DirectlyInList, i, &id, &group);
+ if (group) {
+ printf("<tr><td>");
+ printf("Member of <b>%s</b></td><td>", group);
+ sprintf(line, "group=%s", group);
+ output_cgi_link("Edit Group", "grped", line);
+ printf("</td><td>");
+ sprintf(line, "remfromgrp_but=1&memuser=%s&group=%s",
+ user, group);
+ output_cgi_link("Remove from Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ ulsSortName(IndirectlyInList);
+ ulsGetCount(IndirectlyInList, &groupCount);
+ for (i=0; i<groupCount; ++i) {
+ group = NULL;
+ ulsGetEntry(IndirectlyInList, i, &id, &group);
+ if (group) {
+ printf("<tr><td>");
+ printf("Indirect member of <b>%s</b></td><td>", group);
+ sprintf(line, "group=%s", group);
+ output_cgi_link("Edit Group", "grped", group);
+ printf("</td><td>");
+ sprintf(line, "addtogrp_but=1&memuser=%s&group=%s",
+ user, group);
+ output_cgi_link("Add to Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ ulsFree(&DirectlyInList);
+ ulsFree(&IndirectlyInList);
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * output a table with the groups the user isn't a member of
+ */
+void output_nonmembership(char *db_path, char *user)
+{
+ int rv;
+ UserObj_t *uoptr = 0;
+ void *padb;
+ USI_t *gidlist;
+ int i;
+ int id;
+ char *group;
+ int groupCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list group membership.");
+ } else {
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ report_error(SYSTEM_ERROR, user,
+ "Unable to find user when trying to "
+ "list group membership.");
+ rv = 1;
+ } else {
+ void *sortList;
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateGroups(NULL, padb,
+ (void *)sortList, groupEnumCB);
+
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+
+ if (groupCount > 0) {
+ gidlist = UILLIST(&uoptr->uo_groups);
+ for (i=0; i<groupCount; ++i) {
+ group = NULL;
+ ulsGetEntry(sortList, i, &id, &group);
+ if (group && !idfound(id, (int*)gidlist, UILCOUNT(&uoptr->uo_groups))){
+ printf("<tr><td>");
+ printf("Not a member of <b>%s</b></td><td>", group);
+ sprintf(line, "group=%s", group);
+ output_cgi_link("Edit Group", "grped", line);
+ printf("</td><td>");
+ sprintf(line, "addtogrp_but=1&memuser=%s&group=%s",
+ user, group);
+ output_cgi_link("Add to Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ }
+ ulsFree(&sortList);
+ userFree(uoptr);
+ }
+ }
+ return;
+}
+
+/*
+ * output_group_membership - output a table showing which
+ * groups a user is in.
+ */
+void output_group_membership(char *db_path, char *user)
+{
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>%s group membership:</b>", user);
+ printf("</caption>\n");
+ output_groups_user_is_in(db_path, user);
+ output_nonmembership(db_path, user);
+ printf("</table>\n");
+}
+
+void output_grpgroup_membership(char *db_path, char *group, char *filter)
+{
+ int rv;
+ GroupObj_t *goptr = 0;
+ void *padb;
+ USI_t *gidlist;
+ int i;
+ int id;
+ char *gname;
+ char *memgroup;
+ int groupCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list group membership.");
+ } else {
+ /* See if the group exists. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ /* Group doesn't exist, so we've failed. */
+ report_error(SYSTEM_ERROR, group,
+ "Unable to find group when trying to "
+ "list group membership.");
+ rv = 1;
+ } else {
+ groupCount = UILCOUNT(&goptr->go_groups);
+ if (groupCount > 0) {
+ void *sortList;
+ ulsAlloc(&sortList);
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>%s has these group members:</b>", group);
+ printf("</caption>\n");
+ gidlist = UILLIST(&goptr->go_groups);
+ for (i = 0; i < groupCount; ++i) {
+ rv = nsadbIdToName(NULL,
+ padb, gidlist[i], AIF_GROUP, &gname);
+ if ((rv >= 0) && (gname != 0) && (strlen(gname) != 0)) {
+ ulsAddToList(sortList, gidlist[i], gname);
+ }
+ }
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+ for (i=0; i<groupCount; ++i) {
+ memgroup = NULL;
+ ulsGetEntry(sortList, i, &id, &memgroup);
+ if (memgroup && passfilter(memgroup, filter)) {
+ printf("<tr><td>");
+ printf("<b>%s</b></td><td>", memgroup);
+ sprintf(line, "group=%s", memgroup);
+ output_cgi_link("Edit Group", "grped", line);
+ printf("</td><td>");
+ sprintf(line, "remfromgrp_but=1&memgroup=%s&group=%s",
+ memgroup, group);
+ output_cgi_link("Remove from Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ ulsFree(&sortList);
+ } else {
+ printf("<b>This group has no group members.</b>");
+ }
+ groupFree(goptr);
+ }
+ nsadbClose(padb, 0);
+ }
+ return;
+}
+
+/*
+ * Output a table showing the user members of a group.
+ */
+NSAPI_PUBLIC void output_user_membership(char *db_path, char *group, char *filter)
+{
+ int rv;
+ GroupObj_t *goptr = 0;
+ void *padb;
+ USI_t *uidlist;
+ char *user;
+ int i;
+ int id;
+ char *memuser;
+ int userCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list user membership.");
+ } else {
+ /* See if the group exists. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ /* Group doesn't exist, so we've failed. */
+ nsadbClose(padb, 0);
+ report_error(SYSTEM_ERROR, group,
+ "Unable to find group when trying to "
+ "list user membership.");
+ rv = 1;
+ } else {
+ userCount = UILCOUNT(&goptr->go_users);
+ if (userCount > 0) {
+ void *sortList;
+ ulsAlloc(&sortList);
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>%s has these user members:</b>", group);
+ printf("</caption>\n");
+ uidlist = UILLIST(&goptr->go_users);
+ for (i = 0; i < userCount; ++i) {
+ rv = nsadbIdToName(NULL,
+ padb, uidlist[i], AIF_USER, &user);
+ if ((rv >= 0) && (user != 0) && (strlen(user) != 0)) {
+ ulsAddToList(sortList, uidlist[i], user);
+ }
+ }
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &userCount);
+ for (i=0; i<userCount; ++i) {
+ memuser = NULL;
+ ulsGetEntry(sortList, i, &id, &memuser);
+ if (memuser && passfilter(memuser, filter)) {
+ printf("<tr><td>");
+ printf("<b>%s</b></td><td>", memuser);
+ sprintf(line, "user=%s", memuser);
+ output_cgi_link("Edit User", "usred", line);
+ printf("</td><td>");
+ sprintf(line, "remfromgrp_but=1&memuser=%s&group=%s",
+ memuser, group);
+ output_cgi_link("Remove from Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ ulsFree(&sortList);
+ } else {
+ nsadbClose(padb, 0);
+ printf("<b>This group has no user members.</b>");
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Output a group showing all users.
+ */
+NSAPI_PUBLIC int output_users_list(char *db_path, char *filter)
+{
+ int rv;
+ void *padb;
+ int i;
+ int id;
+ char *user;
+ int userCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list users.");
+ else {
+ void *sortList;
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateUsers(NULL, padb, (void *)sortList, userEnumCB);
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &userCount);
+
+ if (userCount > 0) {
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>User List:</b>");
+ printf("</caption>\n");
+
+ for (i=0; i<userCount; ++i) {
+ user = NULL;
+ ulsGetEntry(sortList, i, &id, &user);
+ if (user && passfilter(user, filter)) {
+ printf("<tr><td>");
+ printf("<b>%s</b></td><td>", user);
+ sprintf(line, "user=%s", user);
+ output_cgi_link("Edit User", "usred", line);
+ printf("</td><td>\n");
+ output_cgi_link("Remove User", "usrrem", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ } else {
+ printf("<b>There are no users in the database.</b>");
+ }
+ ulsFree(&sortList);
+ }
+ return rv;
+}
+
+/*
+ * Output a table showing all groups.
+ */
+NSAPI_PUBLIC int output_groups_list(char *db_path, char *filter)
+{
+ int rv;
+ void *padb;
+ int i;
+ int id;
+ char *group;
+ int groupCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list groups.");
+ else {
+ void *sortList;
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateGroups(NULL, padb, (void *)sortList, groupEnumCB);
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+
+ if (groupCount > 0) {
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>Group List:</b>");
+ printf("</caption>\n");
+
+ for (i=0; i<groupCount; ++i) {
+ group = NULL;
+ ulsGetEntry(sortList, i, &id, &group);
+ if ((group) && (passfilter(group, filter))) {
+ printf("<tr><td>");
+ printf("<b>%s</b></td><td>", group);
+ sprintf(line, "group=%s", group);
+ output_cgi_link("Edit Group", "grped", line);
+ printf("</td><td>");
+ output_cgi_link("Remove Group", "grprem", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ } else {
+ printf("<b>There are no groups in the database.</b>");
+ }
+ ulsFree(&sortList);
+ }
+ return rv;
+}
+
+/* Helper function: Return a uls list of all the groups a user is in. MLM */
+void *_list_user_groups(void *padb, char *user, int group_users)
+{
+ int rv;
+ register int i;
+ UserObj_t *uoptr = 0;
+ GroupObj_t *ugoptr = 0;
+ GroupObj_t *goptr = 0;
+ void *userGroupList = NULL;
+ int userGroupCount= 0;
+ USI_t *gidlist;
+ char *ugname = NULL;
+
+ if(!group_users) {
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ } else {
+ rv = nsadbFindByName(NULL, padb, user, AIF_GROUP, (void **)&ugoptr);
+ }
+ if ((uoptr == 0) && (ugoptr == 0)) {
+ /* User doesn't exist, so we've failed. */
+ return NULL;
+ } else {
+ if(uoptr) {
+ userGroupCount = UILCOUNT(&uoptr->uo_groups);
+ } else {
+ userGroupCount = UILCOUNT(&ugoptr->go_groups);
+ }
+ if (userGroupCount > 0) {
+ ulsAlloc(&userGroupList);
+ if(uoptr) {
+ gidlist = UILLIST(&uoptr->uo_groups);
+ } else {
+ gidlist = UILLIST(&ugoptr->go_groups);
+ }
+
+ for (i = 0; i < userGroupCount; ++i) {
+ rv = nsadbIdToName(NULL, padb,
+ gidlist[i], AIF_GROUP, &ugname);
+
+ if (rv >= 0) {
+ rv = nsadbFindByName(NULL, padb, ugname, AIF_GROUP,
+ (void **)&goptr);
+ }
+ if (goptr != 0) {
+ if (goptr->go_name && strlen((char *)goptr->go_name)) {
+ if(uoptr) {
+ if (idfound(uoptr->uo_uid,
+ (int*)UILLIST(&goptr->go_users),
+ UILCOUNT(&goptr->go_users))) {
+ ulsAddToList(userGroupList, goptr->go_gid,
+ (char *)goptr->go_name);
+ }
+ } else {
+ ulsAddToList(userGroupList, goptr->go_gid,
+ (char *)goptr->go_name);
+ }
+ }
+ groupFree(goptr);
+ goptr = 0;
+ }
+ }
+ }
+ }
+ return userGroupList;
+}
+
+/* Output a selector box, with name "name", and make it a multiple
+ * selector box if multiple=1. */
+/* If user is non-null, then if it's a multiple selector, correctly highlight
+ * the groups the user is in.
+ * If group_user is 1, then the variable "user" refers to a *group* as
+ * a member, rather than a user.
+ * Highlight the item "highlight" regardless of membership (as long as
+ * it's non-NULL.) MLM */
+NSAPI_PUBLIC void output_group_selector(char *db_path, int group_user,
+ char *user,
+ char *highlight, char *except,
+ char *name, int none, int multiple)
+{
+ int rv;
+ void *padb;
+ int i, j, isselected;
+ int id;
+ char *group;
+ int groupCount;
+ void *userGroupList = NULL;
+ int userGroupCount= 0;
+ char *ugname = NULL;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list groups.");
+ else {
+ void *sortList;
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateGroups(NULL, padb, (void *)sortList, groupEnumCB);
+
+ if((multiple) && (user)) {
+ userGroupList=_list_user_groups(padb, user, group_user);
+ if(userGroupList) {
+ ulsSortName(userGroupList);
+ ulsGetCount(userGroupList, &userGroupCount);
+ }
+ }
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+
+ if (groupCount > 0) {
+ /* Make a pulldown if we can. If the size is bigger than the
+ * overflow value, make it a box to hack around the fact that
+ * the X Navigator can't scroll pulldown lists. */
+ if((multiple) || (groupCount > SELECT_OVERFLOW)) {
+ printf("<SELECT size=5 name=%s %s>",
+ name, multiple? "MULTIPLE" : "");
+ } else {
+ printf("<SELECT name=%s>", name);
+ }
+ if((!multiple) && (none)) {
+ printf("<OPTION value=NONE>NONE\n");
+ }
+
+ for (i=0; i<groupCount; ++i) {
+ group = NULL;
+ ugname = NULL;
+ isselected=0;
+ ulsGetEntry(sortList, i, &id, &group);
+ if (group) {
+ if((except) && (!strcmp(group, except)))
+ continue;
+ if((highlight) && (!strcmp(group, highlight)))
+ isselected=1;
+ if(userGroupList && !isselected) {
+ for(j=0; j < userGroupCount; j++) {
+ ulsGetEntry(userGroupList, j, &id, &ugname);
+#if 0
+ if(ugname[0] > group[0]) {
+ /* Both lists are sorted, therefore, if we've
+ * hit a letter that's after the group letter,
+ * it must not be here. */
+ /* What can I say, it's a pathetic attempt
+ * on my part to mask the fact that I know
+ * this is inefficient. */
+ break;
+ }
+#endif
+ if(!strcmp(ugname, group)) {
+ isselected=1;
+ break;
+ }
+ }
+ }
+ printf("<OPTION %s>%s\n",
+ isselected? "SELECTED" : "", group);
+ }
+ }
+ printf("</SELECT>");
+ } else {
+ printf("<b>(No groups have been created.)</b>");
+ }
+ ulsFree(&sortList);
+ if(userGroupList)
+ ulsFree(&userGroupList);
+ }
+}
+
+void *_list_group_users(void *padb, char *group, int group_users)
+{
+ int rv;
+ GroupObj_t *goptr = 0;
+ USI_t *uidlist;
+ char *user;
+ int i;
+ int userCount;
+ void *sortList=NULL;
+
+ /* See if the group exists. */
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ /* Group doesn't exist, so we've failed. */
+ return NULL;
+ } else {
+ if(group_users)
+ userCount = UILCOUNT(&goptr->go_groups);
+ else
+ userCount = UILCOUNT(&goptr->go_users);
+
+ if (userCount > 0) {
+ ulsAlloc(&sortList);
+
+ if(group_users)
+ uidlist = UILLIST(&goptr->go_groups);
+ else
+ uidlist = UILLIST(&goptr->go_users);
+
+ for (i = 0; i < userCount; ++i) {
+ if(group_users)
+ rv = nsadbIdToName(NULL,padb, uidlist[i], AIF_GROUP, &user);
+ else
+ rv = nsadbIdToName(NULL, padb, uidlist[i], AIF_USER, &user);
+ if ((rv >= 0) && (user != 0) && (strlen(user) != 0)) {
+ ulsAddToList(sortList, uidlist[i], user);
+ }
+ }
+ }
+ }
+ return sortList;
+}
+
+/*
+ * Output a selector box of users. If group is non-null, highlight the
+ * users in that group. MLM
+ */
+NSAPI_PUBLIC void output_user_selector(char *db_path, char *group,
+ char *highlight, char *except,
+ char *name, int none, int multiple)
+{
+ int rv;
+ void *padb;
+ int i, j, isselected;
+ int id;
+ char *user;
+ int userCount;
+ void *groupUserList = NULL;
+ int groupUserCount= 0;
+ char *guname = NULL;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list groups.");
+ else {
+ void *sortList;
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateUsers(NULL, padb, (void *)sortList, userEnumCB);
+
+ if((multiple) && (group)) {
+ groupUserList=_list_group_users(padb, group, 0);
+ if(groupUserList) {
+ ulsSortName(groupUserList);
+ ulsGetCount(groupUserList, &groupUserCount);
+ }
+ }
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &userCount);
+
+ if (userCount > 0) {
+ /* Make a pulldown if we can. If the size is bigger than the
+ * overflow value, make it a box to hack around the fact that
+ * the X Navigator can't scroll pulldown lists. */
+ if((multiple) || (userCount > SELECT_OVERFLOW)) {
+ printf("<SELECT size=5 name=%s %s>",
+ name, multiple? "MULTIPLE" : "");
+ } else {
+ printf("<SELECT name=%s>", name);
+ }
+ if((!multiple) && (none)) {
+ printf("<OPTION value=NONE>NONE\n");
+ }
+
+ for (i=0; i<userCount; ++i) {
+ user = NULL;
+ guname = NULL;
+ isselected=0;
+ ulsGetEntry(sortList, i, &id, &user);
+ if (user) {
+ if((except) && (!strcmp(user, except)))
+ continue;
+ if((highlight) && (!strcmp(user, highlight)))
+ isselected=1;
+ if(groupUserList && !isselected) {
+ for(j=0; j < groupUserCount; j++) {
+ ulsGetEntry(groupUserList, j, &id, &guname);
+#if 0
+ if(guname[0] > user[0]) {
+ /* Both lists are sorted, therefore, if we've
+ * hit a letter that's after the group letter,
+ * it must not be here. */
+ /* What can I say, it's a pathetic attempt
+ * on my part to mask the fact that I know
+ * this is inefficient. */
+ break;
+ }
+#endif
+ if(!strcmp(guname, user)) {
+ isselected=1;
+ break;
+ }
+ }
+ }
+ printf("<OPTION %s>%s\n",
+ isselected? "SELECTED" : "", user);
+ }
+ }
+ printf("</SELECT>");
+ } else {
+ printf("<b>(No users have been created.)</b>");
+ }
+ ulsFree(&sortList);
+ if(groupUserList)
+ ulsFree(&groupUserList);
+ }
+}
+
+
+int _item_in_list(char *item, char **list)
+{
+ register int i;
+ if(!list) return -1;
+ for(i=0; list[i]; i++) {
+ if(!strcmp(list[i], item))
+ return i;
+ }
+ return -1;
+}
+
+/* Take a char ** null terminated list of group names, and change a user's
+ * memberships so those are the only groups he's in. MLM */
+NSAPI_PUBLIC void change_user_membership(char *db_path, char *user,
+ char **new_groups)
+{
+ void *sortList;
+ int rv;
+ void *padb;
+ UserObj_t *uoptr = NULL;
+ GroupObj_t *goptr = NULL;
+ int groupCount=0;
+ register int i;
+ int index;
+ int id;
+ char *group;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list groups.");
+
+ sortList=_list_user_groups(padb, user, 0);
+ if(sortList) {
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+ }
+
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ report_error(INCORRECT_USAGE, user, "The user was not found.");
+ }
+
+ /* First check the groups he's already in. Remove any that no longer
+ * appear in the list. */
+ for(i=0; i<groupCount; ++i) {
+ ulsGetEntry(sortList, i, &id, &group);
+
+ if( (index=_item_in_list(group, new_groups)) == -1) {
+ goptr=0;
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ report_error(INCORRECT_USAGE, group,
+ "The group was not found.");
+ }
+ rv = nsadbRemUserFromGroup(NULL, padb, goptr, uoptr);
+ } else {
+ /* This group is in the list, so mark it as taken care of. */
+ if(new_groups)
+ new_groups[index][0]='\0';
+ }
+ }
+ /* Add the user to any remaining groups. */
+ if(new_groups) {
+ for(i=0; new_groups[i]; i++) {
+ if(new_groups[i][0] == '\0')
+ continue;
+ goptr=0;
+ rv = nsadbFindByName(NULL, padb, new_groups[i],
+ AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ report_error(INCORRECT_USAGE, group,"The group was not found.");
+ }
+ rv = nsadbAddUserToGroup(NULL, padb, goptr, uoptr);
+ }
+ }
+
+ nsadbClose(padb, 0);
+}
+
+/* Take a char ** null terminated list of user names, and change a group's
+ * memberships so those are the only users it has. MLM */
+/* Again, if group_users is 1, then the new_users are assumed to be groups. */
+NSAPI_PUBLIC void change_group_membership(char *db_path, char *group,
+ int group_users, char **new_users)
+{
+ void *sortList;
+ int rv;
+ void *padb;
+ UserObj_t *uoptr = NULL;
+ GroupObj_t *goptr = NULL;
+ GroupObj_t *ugoptr = NULL;
+ int userCount=0;
+ register int i;
+ int index;
+ int id;
+ char *user;
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0)
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list groups.");
+
+ sortList=_list_group_users(padb, group, group_users);
+ if(sortList) {
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &userCount);
+ }
+
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ report_error(INCORRECT_USAGE, group, "The group was not found.");
+ }
+
+ /* First check the users already there. Remove any that no longer
+ * appear in the list. */
+ for(i=0; i<userCount; ++i) {
+ ulsGetEntry(sortList, i, &id, &user);
+ if( (index=_item_in_list(user, new_users)) == -1) {
+ if(group_users) {
+ ugoptr=0;
+ rv = nsadbFindByName(NULL, padb, user, AIF_GROUP,
+ (void **)&ugoptr);
+ if (ugoptr == 0) {
+ report_error(INCORRECT_USAGE, user,
+ "The group was not found.");
+ }
+ rv = nsadbRemGroupFromGroup(NULL, padb, goptr, ugoptr);
+ } else {
+ uoptr=0;
+ rv = nsadbFindByName(NULL, padb, user, AIF_USER,
+ (void **)&uoptr);
+ if (uoptr == 0) {
+ report_error(INCORRECT_USAGE, user,
+ "The user was not found.");
+ }
+ rv = nsadbRemUserFromGroup(NULL, padb, goptr, uoptr);
+ }
+ } else {
+ /* This user is in the list, so mark it as taken care of. */
+ if(new_users)
+ new_users[index][0]='\0';
+ }
+ }
+ /* Add any remaining users. */
+ if(new_users) {
+ for(i=0; new_users[i]; i++) {
+ if(new_users[i][0] == '\0')
+ continue;
+ if(group_users) {
+ ugoptr=0;
+ rv = nsadbFindByName(NULL, padb, new_users[i],
+ AIF_GROUP, (void **)&ugoptr);
+ if (ugoptr == 0) {
+ report_error(INCORRECT_USAGE, new_users[i],
+ "The group was not found.");
+ }
+ rv = nsadbAddGroupToGroup(NULL, padb, goptr, ugoptr);
+ if(rv) report_error(SYSTEM_ERROR, new_users[i],
+ "Unable to add group to group");
+ } else {
+ uoptr=0;
+ rv = nsadbFindByName(NULL, padb, new_users[i],
+ AIF_USER, (void **)&uoptr);
+ if (uoptr == 0) {
+ report_error(INCORRECT_USAGE, new_users[i],
+ "The user was not found.");
+ }
+ rv = nsadbAddUserToGroup(NULL, padb, goptr, uoptr);
+ if(rv) report_error(SYSTEM_ERROR, new_users[i],
+ "Unable to add user to group");
+ }
+ }
+ }
+
+ nsadbClose(padb, 0);
+}
+
+/*
+ * output a table with the groups that aren't members of the group
+ */
+NSAPI_PUBLIC void output_nongrpgroup_membership(char *db_path, char *group, char *filter)
+{
+ int rv;
+ GroupObj_t *goptr = 0;
+ void *padb;
+ USI_t *gidlist;
+ int i;
+ int id;
+ char *memgroup;
+ int groupCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list group membership.");
+ } else {
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ report_error(SYSTEM_ERROR, group,
+ "Unable to find group when trying to "
+ "list group membership.");
+ rv = 1;
+ nsadbClose(padb, 0);
+ } else {
+ void *sortList;
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>These groups are not members of %s:</b>", group);
+ printf("</caption>\n");
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateGroups(NULL,
+ padb, (void *)sortList, groupEnumCB);
+ nsadbClose(padb, 0);
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &groupCount);
+
+ if (groupCount > 0) {
+ gidlist = UILLIST(&goptr->go_groups);
+ for (i=0; i<groupCount; ++i) {
+ memgroup = NULL;
+ ulsGetEntry(sortList, i, &id, &memgroup);
+ if ( memgroup &&
+ strcmp(memgroup, group) &&
+ !idfound(id, (int*)gidlist, UILCOUNT(&goptr->go_groups)) &&
+ passfilter(memgroup, filter)) {
+ printf("<tr>");
+ printf("<td><b>%s</b></td><td>", memgroup);
+ sprintf(line, "group=%s", memgroup);
+ output_cgi_link("Edit Group", "grped", line);
+ printf("</td><td>");
+ sprintf(line, "addtogrp_but=1&memgroup=%s&group=%s",
+ memgroup, group);
+ output_cgi_link("Add to Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ }
+ ulsFree(&sortList);
+ groupFree(goptr);
+ }
+ }
+ return;
+}
+
+/*
+ * output a table with the users that aren't members of the group
+ */
+NSAPI_PUBLIC void output_nonuser_membership(char *db_path, char *group, char *filter)
+{
+ int rv;
+ GroupObj_t *goptr = 0;
+ void *padb;
+ USI_t *gidlist;
+ int i;
+ int id;
+ char *memuser;
+ int userCount;
+ char line[BIG_LINE];
+
+ rv = nsadbOpen(NULL, db_path, 0, &padb);
+ if (rv < 0) {
+ report_error(SYSTEM_ERROR, db_path,
+ "Failed to open database while trying "
+ "to list group membership.");
+ } else {
+ rv = nsadbFindByName(NULL, padb, group, AIF_GROUP, (void **)&goptr);
+ if (goptr == 0) {
+ nsadbClose(padb, 0);
+ report_error(SYSTEM_ERROR, group,
+ "Unable to find group when trying to "
+ "list user membership.");
+ rv = 1;
+ } else {
+ void *sortList;
+
+ printf("<table border=1><caption align=left>\n");
+ printf("<b>These users are not members of %s:</b>", group);
+ printf("</caption>\n");
+
+ ulsAlloc(&sortList);
+ rv = nsadbEnumerateUsers(NULL, padb, (void *)sortList, userEnumCB);
+ nsadbClose(padb, 0);
+
+ ulsSortName(sortList);
+ ulsGetCount(sortList, &userCount);
+
+ if (userCount > 0) {
+ gidlist = UILLIST(&goptr->go_users);
+ for (i=0; i<userCount; ++i) {
+ memuser = NULL;
+ ulsGetEntry(sortList, i, &id, &memuser);
+ if ( memuser &&
+ !idfound(id, (int*)gidlist, UILCOUNT(&goptr->go_users)) &&
+ passfilter(memuser, filter)) {
+ printf("<tr>");
+ printf("<td><b>%s</b></td><td>", memuser);
+ sprintf(line, "memuser=%s", memuser);
+ output_cgi_link("Edit User", "usred", line);
+ printf("</td><td>");
+ sprintf(line, "addtogrp_but=1&memuser=%s&group=%s",
+ memuser, group);
+ output_cgi_link("Add to Group", "grped", line);
+ printf("</td>\n");
+ }
+ }
+ printf("</table>\n");
+ }
+ ulsFree(&sortList);
+ groupFree(goptr);
+ }
+ }
+ return;
+}
+
+NSAPI_PUBLIC char *get_acl_file()
+{
+ char line[BIG_LINE];
+ char *acl_file = get_mag_var("ACLFile");
+ if (!acl_file) {
+ sprintf(line, "%s%cgenerated.%s.acl",
+ get_httpacl_dir(), FILE_PATHSEP, get_srvname(0));
+ set_mag_var("ACLFile", line);
+ acl_file = STRDUP(line);
+ }
+ if(!file_exists(acl_file)) {
+ FILE *f;
+ if(! (f=fopen(acl_file, "w")) )
+ report_error(FILE_ERROR, acl_file, "Could not open file.");
+ fclose(f);
+ }
+ return acl_file;
+}
+
+NSAPI_PUBLIC char *get_workacl_file()
+{
+ char line[BIG_LINE];
+ char *workacl_file;
+ sprintf(line, "%s%cgenwork.%s.acl",
+ get_httpacl_dir(), FILE_PATHSEP, get_srvname(0));
+ workacl_file = STRDUP(line);
+
+ if(!file_exists(workacl_file)) {
+ FILE *f;
+ char *current=get_acl_file();
+ if(file_exists(current)) {
+ cp_file(current, workacl_file, 0644);
+ } else {
+ if(! (f=fopen(workacl_file, "w")) )
+ report_error(FILE_ERROR, workacl_file, "Could not open file.");
+ fclose(f);
+ }
+ }
+ return workacl_file;
+}
+
+/*
+ * get_acl_info - Open the specified ACL file. Return a context
+ * handle into it, the data it contains, and whether this is
+ * a default allow or default deny resource.
+ *
+ * Returns: 0 if it works
+ * AUTHDB_ACL_FAIL (-1) if it fails
+ * AUTHDB_ACL_ODD_ACL (-2) if the ACL doesn't appear to be one
+ * generated by the CGI.
+ */
+NSAPI_PUBLIC int get_acl_info(char *acl_file, char *acl_name, void **pacl,
+ char ***hosts, authInfo_t **authinfo,
+ char ***users, char ***userhosts,
+ int *fdefaultallow)
+{
+ int rv = 0;
+ char *acl_sig = NULL;
+ ACContext_t *acl_con = NULL;
+ ACL_t *acl;
+
+ if (hosts)
+ *hosts = NULL;
+ if (authinfo)
+ *authinfo = NULL;
+ if (users)
+ *users = NULL;
+ if (userhosts)
+ *userhosts = NULL;
+ if (fdefaultallow)
+ *fdefaultallow = 0;
+
+ if ((rv = accReadFile(NULL, acl_file, &acl_con)))
+ rv = AUTHDB_ACL_FAIL;
+ else if (!(rv = aclFindByName(acl_con, acl_name, NULL, 0, &acl)))
+ rv = AUTHDB_ACL_NOT_FOUND;
+ else {
+ /*
+ * If we get the ACL open, get it's signiture to see if
+ * it looks like one of ours. Each directive is identified
+ * by a single character in the signiture string. The ones
+ * we care about are:
+ * 'a' - default allow
+ * 'd' - default deny
+ * 'r' - default authenticate
+ *
+ * The ACL used for default allow access has these directives:
+ * default allow anyone at *; (required, shows up as an 'a')
+ * default deny anyone at (hosts); (optional, shows up as a 'd')
+ *
+ * The ACL used for default deny access has these directives:
+ * default deny anyone at *; (required, shows up as an 'd')
+ * default allow anyone at (hosts); (optional, shows up as a 'a')
+ * default authenticate... (optional, shows up as an 'r')
+ * default allow (users) at (hosts); (optional, shows up as a 'a')
+ *
+ * Valid signitures are:
+ * "a"
+ * "ad"
+ * "d"
+ * "da"
+ * "dra"
+ * "dara"
+ */
+
+ if (acl)
+ acl_sig = aclGetSignature(acl);
+
+ if (acl_sig) {
+ if (!strcmp(acl_sig, "a")) {
+ if (fdefaultallow)
+ *fdefaultallow = 1;
+ rv = 0;
+ }
+ else if (!strcmp(acl_sig, "ad")) {
+ if (fdefaultallow)
+ *fdefaultallow = 1;
+ if (hosts)
+ *hosts = aclGetHosts(acl, 2, 1);
+ rv = 0;
+ }
+ else if (!strcmp(acl_sig, "d")) {
+ if (fdefaultallow)
+ *fdefaultallow = 0;
+ rv = 0;
+ }
+ else if (!strcmp(acl_sig, "da")) {
+ if (fdefaultallow)
+ *fdefaultallow = 0;
+ if (hosts)
+ *hosts = aclGetHosts(acl, 2, 1);
+ rv = 0;
+ }
+ else if (!strcmp(acl_sig, "dra")) {
+ if (fdefaultallow)
+ *fdefaultallow = 0;
+ if (authinfo) {
+ char *p;
+ *authinfo = (authInfo_t *)MALLOC(sizeof(authInfo_t));
+ memset(*authinfo, 0, (sizeof(authInfo_t)));
+ if ((p = aclGetAuthMethod(acl, 2)))
+ (*authinfo)->type = strdup(p);
+ if ((p = aclGetDatabase(acl, 2)))
+ (*authinfo)->db_path = strdup(p);
+ if ((p = aclGetPrompt(acl, 2)))
+ (*authinfo)->prompt = strdup(p);
+ }
+ if (users)
+ *users = aclGetUsers(acl, 3, 1);
+ if (userhosts)
+ *userhosts = aclGetHosts(acl, 3, 1);
+ rv = 0;
+ }
+ else if (!strcmp(acl_sig, "dara")) {
+ if (fdefaultallow)
+ *fdefaultallow = 0;
+ if (hosts)
+ *hosts = aclGetHosts(acl, 2, 1);
+ if (authinfo) {
+ char *p;
+ *authinfo = (authInfo_t *)MALLOC(sizeof(authInfo_t));
+ memset(*authinfo, 0, (sizeof(authInfo_t)));
+ if ((p = aclGetAuthMethod(acl, 3)))
+ (*authinfo)->type = strdup(p);
+ if ((p = aclGetDatabase(acl, 3)))
+ (*authinfo)->db_path = strdup(p);
+ if ((p = aclGetPrompt(acl, 3)))
+ (*authinfo)->prompt = strdup(p);
+ }
+ if (users)
+ *users = aclGetUsers(acl, 4, 1);
+ if (userhosts)
+ *userhosts = aclGetHosts(acl, 4, 1);
+ rv = 0;
+ }
+ else
+ rv = AUTHDB_ACL_ODD_ACL;
+ }
+ if (pacl)
+ *pacl = (void *)acl_con;
+ }
+ return rv;
+}
+
+
+static void add_acl_rights(ACContext_t *acc)
+{
+ int rv;
+ char **p;
+ for (p = acl_read_rights; *p; ++p) {
+ rv = aclRightDef(NULL, acc, *p, NULL);
+ }
+ for (p = acl_write_rights; *p; ++p) {
+ rv = aclRightDef(NULL, acc, *p, NULL);
+ }
+}
+
+/*
+ * delete_acl_by_name - remove a specified acl.
+ *
+ * Return: 0 if it deletes an ACL. Otherwise something else.
+ *
+ */
+NSAPI_PUBLIC int delete_acl_by_name(char *acl_file, char *acl_name)
+{
+ int rv = 1;
+ ACContext_t *acl_con = NULL;
+ ACL_t *acl = NULL;
+
+ if (acl_file && acl_name)
+ {
+ rv = accReadFile(NULL, acl_file, &acl_con);
+
+ if (!rv) {
+ rv = aclFindByName(acl_con, acl_name, NULL, 0, &acl);
+ if (rv == 1 && acl) {
+ aclDelete(acl);
+ rv = accWriteFile(acl_con, acl_file, 0);
+ set_commit(0, 1);
+ }
+ }
+ }
+ return rv;
+}
+
+/*
+ * set_acl_info - Replaces the specified ACL with the information
+ * provided. The fdefaultallow is tells us whether
+ * to generate a default allow everyone type ACL, or
+ * a default deny everyone type ACL.
+ *
+ * If opening the ACL file fails with a file open
+ * type error, it is assumed to not exist, and a
+ * new one is created.
+ *
+ * Returns: 0 if it works
+ * AUTHDB_ACL_FAIL if it fails
+ */
+NSAPI_PUBLIC int set_acl_info(char *acl_file, char *acl_name, int prefix,
+ void **pacl, char **rights,
+ char **hosts, authInfo_t *authinfo,
+ char **users, char **userhosts,
+ int fdefaultallow)
+{
+ int rv = AUTHDB_ACL_FAIL;
+ ACContext_t *acl_con = NULL;
+ ACL_t *acl = NULL;
+ int amethod = AUTH_METHOD_BASIC;
+ char *db_path = NULL;
+ char *prompt = NULL;
+
+ /*
+ * Digest parms
+ */
+ if (authinfo) {
+ if (!strcmp(authinfo->type, "SSL"))
+ amethod = AUTH_METHOD_SSL;
+ else
+ amethod = AUTH_METHOD_BASIC;
+ db_path = authinfo->db_path;
+ prompt = authinfo->prompt;
+ }
+
+ if (prefix)
+ prefix = ACLF_NPREFIX;
+ else
+ prefix = 0;
+
+ /*
+ * Open the specified ACL file, destroy the existing ACL with
+ * the specified name if it exists, and then write the new
+ * stuff back out.
+ */
+ if (acl_file && acl_name)
+ {
+ (void)delete_acl_by_name(acl_file, acl_name);
+ rv = accReadFile(NULL, acl_file, &acl_con);
+
+ /*
+ * If the file isn't there, create an empty context.
+ */
+ if (rv == ACLERROPEN)
+ rv = accCreate(0, 0, &acl_con);
+
+ if (rv)
+ rv = AUTHDB_ACL_FAIL;
+ else {
+ (void)add_acl_rights(acl_con);
+
+ if (aclMakeNew(acl_con, "", acl_name,
+ rights, prefix, &acl)) {
+ rv = AUTHDB_ACL_FAIL;
+ }
+ else if (aclPutAllowDeny(
+ NULL, acl, 0, fdefaultallow, NULL, NULL)) {
+ rv = AUTHDB_ACL_FAIL;
+ }
+ else if (hosts &&
+ (rv = aclPutAllowDeny(
+ NULL, acl, 0, !fdefaultallow, NULL, hosts))) {
+
+ rv = AUTHDB_ACL_FAIL;
+ }
+ else if (users && authinfo &&
+ ((rv = aclPutAuth(NULL, acl, 0, amethod, db_path, prompt))||
+ (rv = aclPutAllowDeny(NULL, acl, 0, !fdefaultallow,
+ users, userhosts)))) {
+
+ rv = AUTHDB_ACL_FAIL;
+ }
+ else {
+ if (accWriteFile(acl_con, acl_file, 0)) {
+ rv = AUTHDB_ACL_FAIL;
+ }
+ else {
+ set_commit(0, 1);
+ rv = 0;
+ if (pacl)
+ *pacl = (void *)acl;
+ }
+ }
+ }
+ }
+ return rv;
+}
+
+/*
+ * get_acl_names - Passes back the names of the read and write
+ * ACLs for the current resource.
+ * The directive parm is usually "acl", but is
+ * also used to find stashed items under names
+ * like "acl-disabled".
+ * Returns 0 if no other ACLs are found, 1 if an ACL that
+ * doesn't match the type of name we generate.
+ */
+NSAPI_PUBLIC int get_acl_names(char **readaclname, char **writeaclname, char *directive)
+{
+ pblock **pbs;
+ char *aclname;
+ int fother_acls = 0;
+ char **config = get_adm_config();
+ char *curres = get_current_resource(config);
+ int rtype = get_current_restype(config);
+ int i;
+
+ *readaclname = NULL;
+ *writeaclname = NULL;
+
+ pbs = list_pblocks(rtype, curres, "PathCheck", CHECK_ACL_FN);
+
+ if (pbs) {
+ for (i=0; pbs[i]; ++i) {
+ aclname = pblock_findval(directive, pbs[i]);
+ if (is_readacl(aclname))
+ *readaclname = strdup(aclname);
+ else if (is_writeacl(aclname))
+ *writeaclname = strdup(aclname);
+ else
+ fother_acls = 1;
+ }
+ }
+ return fother_acls;
+}
+
+NSAPI_PUBLIC int is_readacl(char *name) {
+ if (name)
+ return strstr(name, ACLNAME_READ_COOKIE)?1:0;
+ else
+ return 0;
+}
+
+NSAPI_PUBLIC int is_writeacl(char *name) {
+ if (name)
+ return strstr(name, ACLNAME_WRITE_COOKIE)?1:0;
+ else
+ return 0;
+}
+
+NSAPI_PUBLIC int admin_is_ipaddr(char *p)
+{
+ int i;
+ int num_found = 0;
+
+ if (!p || !p[0])
+ return 0; /* NULL isn't an IP Address */
+ else {
+ for (i=0; p[i]; ++i) {
+ if (isalpha(p[i]))
+ return 0; /* If it has an alpha character, it's not IP addr */
+ else if (isdigit(p[i])) {
+ num_found = 1;
+ }
+ }
+ }
+ /*
+ * Well, hard to say what it is, but if there's at least a number
+ * in it, and the ip number checker can parse it, we'll call it
+ * an IP address;
+ */
+ if (num_found && get_ip_and_mask(p))
+ return 1;
+ else
+ return 0;
+}
+
+/*
+ * Get the hostnames and ipaddrs strings from the single hosts array
+ * of string pointers.
+ */
+NSAPI_PUBLIC void get_hostnames_and_ipaddrs(char **hosts, char **hostnames, char **ipaddrs)
+{
+ char *p;
+ int nbipaddrs = 0;
+ int nbhostnames = 0;
+ int i;
+ if (hosts && hostnames && ipaddrs) {
+ *hostnames = NULL;
+ *ipaddrs = NULL;
+ /*
+ * Make two passes, once to total the size needed for
+ * the hosts and ipaddrs string, then alloc them and
+ * strcat the strings in.
+ */
+ for(i=0, p=hosts[i]; p; p=hosts[++i]) {
+ if (admin_is_ipaddr(p))
+ nbipaddrs += strlen(p) + 2; /* Teminator and "," */
+ else
+ nbhostnames += strlen(p) + 2;
+ }
+
+ if (nbhostnames) {
+ *hostnames = (char *)MALLOC(nbhostnames + 1);
+ memset(*hostnames, 0, nbhostnames);
+ }
+ if (nbipaddrs) {
+ *ipaddrs = (char *)MALLOC(nbipaddrs + 1);
+ memset(*ipaddrs, 0, nbipaddrs);
+ }
+
+ /*
+ * We've got the space, now go look at each, strcat it
+ * into the correct string, prefixed with a "," for all
+ * but the first.
+ */
+ for(i=0, p=hosts[i]; p; p=hosts[++i]) {
+ if (admin_is_ipaddr(p)) {
+ if (strlen(*ipaddrs))
+ strcat(*ipaddrs, ",");
+ strcat(*ipaddrs, p);
+ }
+ else {
+ if (strlen(*hostnames))
+ strcat(*hostnames, ",");
+ strcat(*hostnames, p);
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Get the usernames and groups strings from the single users array
+ * of string pointers.
+ */
+NSAPI_PUBLIC void get_users_and_groups(char **users, char **usernames, char **groups,
+ char *db_path)
+{
+ char *p;
+ int nbusernames = 0;
+ int nbgroups = 0;
+ int i;
+ int is_user = 0;
+ int is_group = 0;
+
+ if (users && usernames && groups) {
+ *usernames = NULL;
+ *groups = NULL;
+ /*
+ * Make two passes, once to total the size needed for
+ * the strings, then alloc them and strcat the strings in.
+ */
+ for(i=0, p=users[i]; p; p=users[++i]) {
+ is_user = 0;
+ is_group = 0;
+ groupOrUser(db_path, p, &is_user, &is_group);
+
+ /* Enclose user/group name in quotes if necessary */
+ p = aclSafeIdent(p);
+
+ if (is_user)
+ nbusernames += strlen(p) + 2; /* Teminator and "," */
+ else if (is_group)
+ nbgroups += strlen(p) + 2;
+ }
+
+ if (nbusernames) {
+ *usernames = (char *)MALLOC(nbusernames + 1);
+ memset(*usernames, 0, nbusernames);
+ }
+ if (nbgroups) {
+ *groups = (char *)MALLOC(nbgroups + 1);
+ memset(*groups, 0, nbgroups);
+ }
+
+ /*
+ * We've got the space, now go look at each, strcat it
+ * into the correct string, prefixed with a "," for all
+ * but the first.
+ */
+ for(i=0, p=users[i]; p; p=users[++i]) {
+ is_user = 0;
+ is_group = 0;
+ groupOrUser(db_path, p, &is_user, &is_group);
+
+ /* Enclose user/group name in quotes if necessary */
+ p = aclSafeIdent(p);
+
+ if (is_user) {
+ if (strlen(*usernames))
+ strcat(*usernames, ",");
+ strcat(*usernames, p);
+ }
+ else if (is_group) {
+ if (strlen(*groups))
+ strcat(*groups, ",");
+ strcat(*groups, p);
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Load from host and IP Addr strings into the array of
+ * pointers to strings.
+ */
+NSAPI_PUBLIC void load_host_array(char ***hosts, char *hostnames, char *ipaddrs)
+{
+ char *tok;
+ int nMax = 20;
+ int nCur = 0;
+ char **hostarr;
+ char *valid_ip;
+
+ if (hosts) {
+ hostarr = new_strlist(nMax);
+ hostarr[0] = NULL;
+ if (hostnames) {
+ for (tok = strtok(hostnames, ",");
+ tok;
+ tok = strtok(NULL, ","))
+ {
+ if (!(nCur < nMax)) {
+ nMax += 20;
+ hostarr = grow_strlist(hostarr, nMax);
+ }
+ hostarr[nCur] = strdup(tok);
+ hostarr[++nCur] = NULL;
+ }
+ }
+ if (ipaddrs) {
+ for (tok = strtok(ipaddrs, ",");
+ tok;
+ tok = strtok(NULL, ","))
+ {
+ if (!(nCur < nMax)) {
+ nMax += 20;
+ hostarr = grow_strlist(hostarr, nMax);
+ }
+ valid_ip = get_ip_and_mask(tok);
+ if (valid_ip) {
+ hostarr[nCur] = strdup(valid_ip);
+ hostarr[++nCur] = NULL;
+ }
+ }
+ }
+ *hosts = hostarr;
+ }
+
+ return;
+}
+
+void load_users_array(char ***users, char *usernames, char *groups)
+{
+ char *tok;
+ int nMax = 20;
+ int nCur = 0;
+ char **userarr;
+
+ if (users) {
+ userarr = new_strlist(nMax);
+ userarr[0] = NULL;
+ if (usernames) {
+ for (tok = strtok(usernames, ",");
+ tok;
+ tok = strtok(NULL, ","))
+ {
+ if (!(nCur < nMax)) {
+ nMax += 20;
+ userarr = grow_strlist(userarr, nMax);
+ }
+ userarr[nCur] = strdup(tok);
+ userarr[++nCur] = NULL;
+ }
+ }
+ if (groups) {
+ for (tok = strtok(groups, ",");
+ tok;
+ tok = strtok(NULL, ","))
+ {
+ if (!(nCur < nMax)) {
+ nMax += 20;
+ userarr = grow_strlist(userarr, nMax);
+ }
+ userarr[nCur] = strdup(tok);
+ userarr[++nCur] = NULL;
+ }
+ }
+ *users = userarr;
+ }
+
+ return;
+}
+
+/* Removes enclosing double quotes from a string (in place) */
+NSAPI_PUBLIC char * str_unquote(char * str)
+{
+ if (str) {
+ if (str[0] == '"') {
+ int len = strlen(str);
+
+ if (str[len-1] == '"') {
+ str[len-1] = 0;
+ ++str;
+ }
+ }
+ }
+
+ return str;
+}
diff --git a/lib/libadmin/error.c b/lib/libadmin/error.c
new file mode 100644
index 00000000..a4f87842
--- /dev/null
+++ b/lib/libadmin/error.c
@@ -0,0 +1,109 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * error.c - Handle error recovery
+ *
+ * All blame to Mike McCool
+ */
+
+#include "libadmin/libadmin.h"
+#if 0
+#include "cgiutils/cgi-util.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef XP_WIN32
+#include <windows.h>
+#include "base/nterr.h"
+#endif
+
+#define ERROR_HTML "error.html"
+
+/* Be sure to edit libadmin.h and add new #define types for these headers. */
+char *error_headers[MAX_ERROR] =
+ {"File System Error",
+ "Memory Error",
+ "System Error",
+ "Incorrect Usage",
+ "Form Element Missing",
+ "Registry Database Error",
+ "Network Error",
+ "Unexpected Failure",
+ "Warning"};
+
+#ifdef XP_UNIX
+#define get_error() errno
+#define verbose_error() system_errmsg()
+#else /* XP_WIN32 */
+int get_error()
+{
+ int error = GetLastError();
+ return(error ? error: WSAGetLastError());
+}
+char *verbose_error()
+{
+ /* Initialize error hash tables */
+ HashNtErrors();
+ return alert_word_wrap(system_errmsg(), WORD_WRAP_WIDTH, "\\n");
+}
+#endif /* XP_WIN32 */
+
+void _report_error(int type, char *info, char *details, int shouldexit)
+{
+ /* Be sure headers are terminated. */
+ fputs("\n", stdout);
+
+ fprintf(stdout, "<SCRIPT LANGUAGE=\"%s\">", MOCHA_NAME);
+ output_alert(type, info, details, 0);
+ if(shouldexit) {
+ fprintf(stdout, "if(history.length>1) history.back();");
+ }
+ fprintf(stdout, "</SCRIPT>\n");
+
+ if(shouldexit) {
+ WSACleanup();
+ exit(0);
+ }
+}
+
+/*
+ * Format and output a call to the JavaScript alert() function.
+ * The caller must ensure a JavaScript context.
+ */
+NSAPI_PUBLIC void output_alert(int type, char *info, char *details, int wait)
+{
+ char *wrapped=NULL;
+ int err;
+
+ if(type >= MAX_ERROR)
+ type=DEFAULT_ERROR;
+
+ wrapped=alert_word_wrap(details, WORD_WRAP_WIDTH, "\\n");
+
+ if(!info) info="";
+ fprintf(stdout, (wait) ? "confirm(\"" : "alert(\"");
+ fprintf(stdout, "%s:%s\\n%s", error_headers[type], info, wrapped);
+ if(type==FILE_ERROR || type==SYSTEM_ERROR) {
+ err = get_error();
+ if(err != 0)
+ fprintf(stdout,
+ "\\n\\nThe system returned error number %d, "
+ "which is %s.", err, verbose_error());
+ }
+ fprintf(stdout, "\");");
+}
+
+NSAPI_PUBLIC void report_error(int type, char *info, char *details)
+{
+ _report_error(type, info, details, 1);
+}
+
+NSAPI_PUBLIC void report_warning(int type, char *info, char *details)
+{
+ _report_error(type, info, details, 0);
+}
+
diff --git a/lib/libadmin/strlist.c b/lib/libadmin/strlist.c
new file mode 100644
index 00000000..46a0c600
--- /dev/null
+++ b/lib/libadmin/strlist.c
@@ -0,0 +1,46 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * strlist.c: Managing a handle to a list of strings
+ *
+ * All blame to Mike McCool
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "netsite.h"
+#include <libadmin/libadmin.h>
+
+NSAPI_PUBLIC char **new_strlist(int size)
+{
+ char **new_list;
+ register int x;
+
+ new_list = (char **) MALLOC((size+1)*(sizeof(char *)));
+/* <= so we get the one right after the given size as well */
+ for(x=0; x<= size; x++)
+ new_list[x] = NULL;
+
+ return new_list;
+}
+
+NSAPI_PUBLIC char **grow_strlist(char **strlist, int newsize)
+{
+ char **ans;
+
+ ans = (char **) REALLOC(strlist, (newsize+1)*sizeof(char *));
+
+ return ans;
+}
+
+NSAPI_PUBLIC void free_strlist(char **strlist)
+{
+ int x;
+
+ for(x=0; (strlist[x]); x++) free(strlist[x]);
+ free(strlist);
+}
diff --git a/lib/libadmin/template.c b/lib/libadmin/template.c
new file mode 100644
index 00000000..a689d3b5
--- /dev/null
+++ b/lib/libadmin/template.c
@@ -0,0 +1,820 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * template.c: The actual HTML templates in a static variable
+ *
+ * All blame to Mike McCool
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "template.h"
+#include "libadmin/libadmin.h"
+#include "libadmin/dbtlibadmin.h"
+#include "base/util.h"
+
+/* If you add something to this structure, don't forget to document it
+ * in templates.h, and increase MAXTEMPLATE!
+ *
+ * Also, save yourself a lot of grief and put a space after the name.
+ */
+
+static struct template_s templates[MAXTEMPLATE] = {
+ {"IF ", "FUNC conditional"},
+ {"ELSE ", "FUNC conditional"},
+ {"ENDIF ", "FUNC conditional"},
+ {"TITLE ", "<HTML><HEAD><TITLE>%s</TITLE></HEAD>\n"
+ "<BODY bgcolor=\"#C0C0C0\" link=\"#0000EE\" "
+ "vlink=\"#551A8B\" alink=\"#FF0000\" %s>\n"},
+ {"PAGEHEADER ", "FUNC pageheader"},
+ {"DOCSWITCHER ", ""},
+ {"COPYRIGHT ", ""},
+ {"RESOURCEPICKER ", "FUNC respicker"},
+ {"BOOKTRACK ", "FUNC booktrack"},
+ {"BEGININFO ", "<table border=2 width=100%% cellpadding=2>\n"
+ "<tr><td align=center colspan=2>"
+ "<b><FONT size=+1>%s</FONT></b></td></tr>"
+#if 0
+ "<tr><td>"
+ "<IMG src=\"../icons/b-open.gif\" hspace=8 alt=\"*\""
+ "height=26 width=55></td>"
+ "<td>\n"},
+#endif
+ "<td colspan=2>\n"},
+ {"ADDINFO ", "</td></tr><tr><td colspan=2>"},
+ {"ENDINFO ", "</td></tr></table>\n<hr width=10%%>\n"},
+ {"SUBMIT ", "FUNC submit\n"},
+ {"DOCUMENTROOT ", "FUNC docroot"},
+ {"BEGINELEM ", "<pre>"},
+/* {"ELEM ", "<hr width=100%%><b>%s</b>"}, */
+ {"ELEM ", "\n<b>%s</b>"},
+/* {"ENDELEM ", "<hr width=100%%></pre>\n"}, */
+ {"ENDELEM ", "</pre>\n"},
+ {"ELEMADD ", "<b>%s</b>"},
+/* {"ELEMDIV ", "<hr width=100%%>"}, */
+ {"ELEMDIV ", "\n"},
+ {"REFERER ", "FUNC link_referer"},
+ {"INDEX ", "<a href=\"index\">%s</a>\n"},
+ {"SERVERROOT ", "FUNC serverroot"},
+ {"RESTART ", "<a href=\"pcontrol\">%s</a>\n"},
+ {"ACCESS ", "FUNC makeurl"},
+ {"COMMIT ", "<a href=\"commit?commit\">%s</a>\n"},
+ {"BACKOUT ", "<center>If you don't want to %s, you can <a href=index>"
+ "return to the server manager.</a></center>\n"},
+ {"CURSERVNAME", "FUNC curservname"},
+ {"VERIFY ", "FUNC verify"},
+ {"HELPBUTTON", "FUNC helpbutton"},
+ {"DIALOGSUBMIT", "FUNC dialogsubmit"},
+ {"HELPJSFN", "FUNC helpjsfn"}
+};
+
+int get_directive(char *string);
+void conditional(char *input, char **vars, int index);
+void respicker(char **config);
+void currentres(char **config);
+void prevres(char **config);
+void booktrack(char *input, char **vars);
+void docswitcher(char *input);
+void docroot(char **vars);
+void link_referer(char **input, char **vars);
+void serverroot(char **vars);
+char **get_vars(char *string);
+static void output(char *string);
+void makeurl(char **vars);
+void curservname(void);
+void pageheader(char **vars, char **config);
+void submit(int verify, char **vars);
+void helpbutton(char *topic);
+void dialogsubmit(char *topic);
+
+static int status = -1;
+
+/* Filter a page. Takes the page to filter as an argument. Uses above
+ * filters to process.
+ */
+NSAPI_PUBLIC int parse_line(char *line_input, char **input)
+{
+ register int index;
+ char *position;
+ int dirlen = strlen(DIRECTIVE_START);
+ char **vars;
+
+
+ if(!strncmp(line_input, DIRECTIVE_START, dirlen)) {
+ position = (char *) (line_input + dirlen);
+ index = get_directive(position);
+
+ /* did we get one? */
+ if(index != -1) {
+ /* if so, get the vars. */
+ position += strlen(templates[index].name);
+ vars = get_vars(position);
+ /* Dispatch the correct function (done for readability,
+ * although I'm starting to wonder if I should bother)
+ */
+ if(!strncmp(templates[index].format, "FUNC ", 5)) {
+
+ if(!strncmp(templates[index].format+5, "conditional", 11))
+ conditional(input[0], vars, index);
+ else if(!strncmp(templates[index].format+5, "respicker", 9))
+ respicker(input);
+ else if(!strncmp(templates[index].format+5, "booktrack", 9))
+ booktrack(input[0], vars);
+ else if(!strncmp(templates[index].format+5, "docswitcher", 11))
+ docswitcher(input[0]);
+ else if(!strncmp(templates[index].format+5, "docroot", 7))
+ docroot(vars);
+ else if(!strncmp(templates[index].format+5, "link_referer",12))
+ link_referer(input, vars);
+ else if(!strncmp(templates[index].format+5, "serverroot",10))
+ serverroot(vars);
+ else if(!strncmp(templates[index].format+5, "makeurl",7))
+ makeurl(vars);
+ else if(!strncmp(templates[index].format+5, "curservname",11))
+ curservname();
+ else if(!strncmp(templates[index].format+5, "pageheader",10))
+ pageheader(vars, input);
+ else if(!strncmp(templates[index].format+5, "submit",6))
+ submit(0, vars);
+ else if(!strncmp(templates[index].format+5, "verify",6))
+ submit(1, vars);
+ else if(!strncmp(templates[index].format+5, "helpbutton",10))
+ helpbutton(vars[0]);
+ else if(!strncmp(templates[index].format+5, "dialogsubmit",12))
+ dialogsubmit(vars[0]);
+ /* We don't know what this template is. Send it back. */
+ else return -1;
+ } else {
+ /* I just can't believe there's no easy way to create
+ * a va_list. */
+ char line[BIG_LINE];
+ sprintf(line, templates[index].format,
+ (vars[0] != NULL) ? vars[0]: "",
+ (vars[1] != NULL) ? vars[1]: "",
+ (vars[2] != NULL) ? vars[2]: "",
+ (vars[3] != NULL) ? vars[3]: "");
+ output(line);
+ }
+ } else {
+ /* We found a directive, but we can't identify it. Send it back.*/
+ /* Check status first; if we're not supposed to be outputing */
+ /* because of an "IF" block, don't tell the program to */
+ /* try and cope with it. */
+ if(status)
+ return -1;
+ else
+ return 0;
+ }
+ } else
+ /* We found no directive. The line is normal. */
+ output(line_input);
+
+ /* If we're here, we either handled it correctly or the line was benign.*/
+ return 0;
+}
+
+void conditional(char *input, char **vars, int index)
+{
+ if((!strncmp(templates[index].name, "IF", 2)) &&
+ (vars[0] != NULL)) {
+ status = input[atoi(vars[0])] - '0';
+ } else
+ if((!strncmp(templates[index].name, "ELSE", 4)) &&
+ (status != -1)) {
+ status ^= 1;
+ } else
+ if(!strncmp(templates[index].name, "ENDIF", 5))
+ status = -1;
+}
+
+void respicker(char **config)
+{
+ output("<FORM action=rsrcpckr method=GET>\n");
+ output("<hr size=4><center>\n");
+ prevres(config);
+ output("</center><hr size=4>\n");
+ output("</FORM>\n");
+}
+
+void currentres(char **config)
+{
+ int l;
+ char line[BIG_LINE];
+ char *resname, *restype;
+
+ resname = get_current_resource(config);
+ restype = get_current_typestr(config);
+ if(!strcmp(restype, NAME)) {
+ if(!strcmp(resname, "default"))
+ sprintf(line, "<font size=+1>Modifying: "
+ "<b>the entire server</b>.</font>");
+ else
+ sprintf(line, "<font size=+1>Modifying: "
+ "<b>the object named %s</b>.</font>", resname);
+ }
+ else if(!strcmp(restype, FILE_OR_DIR)) {
+ l = strlen(resname) - 1;
+ if(resname[l] == '*') {
+ sprintf(line, "<font size=+1>Modifying: <b>the directory "
+ "%s</b></font>",
+ resname);
+ } else {
+ sprintf(line, "<font size=+1>Modifying: <b>%s %s</b></font>",
+ (strchr(resname, '*')) ? "files matching" : "the file",
+ resname);
+ }
+ }
+ else if(!strcmp(restype, TEMPLATE)) {
+ sprintf(line, "<font size=+1>Modifying: <b>the template %s</b></font>",
+ resname);
+ }
+ else if(!strcmp(restype, WILDCARD)) {
+#ifdef MCC_PROXY
+ sprintf(line, "<font size=+1>Modifying: <b>URLs matching RE %s"
+#else
+ sprintf(line, "<font size=+1>Modifying: <b>files matching %s"
+#endif
+ "</b></font>",
+ resname);
+ }
+ output(line);
+}
+
+void prevres(char **config)
+{
+#ifndef MCC_NEWS
+ char *res = get_current_resource(config);
+ int rtype = get_current_restype(config);
+
+ if(status) {
+ char **options = NULL;
+ register int x=0;
+ int found=0;
+ int option_cnt = total_object_count();
+
+ fprintf(stdout, "<SCRIPT language=JavaScript>\n");
+ fprintf(stdout, "function checkForClick() {\n");
+ fprintf(stdout, " document.forms[0].resource.blur();\n");
+ fprintf(stdout, " var idx=document.forms[0]."
+ "resource.options.selectedIndex;\n");
+ fprintf(stdout, " if(document.forms[0].resource."
+ "options[idx].defaultSelected == 0) {\n");
+ fprintf(stdout, " document.forms[0].submit();\n");
+ fprintf(stdout, " return 1;\n");
+ fprintf(stdout, " } else return 0;\n");
+ fprintf(stdout, "}\n");
+ fprintf(stdout, "</SCRIPT>\n");
+
+#ifdef MCC_PROXY
+ fprintf(stdout, "<TABLE BORDER=0>\n");
+ fprintf(stdout, "<TR><TD><font size=+1>Editing:</font></TD>\n");
+ fprintf(stdout,
+ "<TD><SELECT name=\"resource\" onChange=\"checkForClick()\" SIZE=\"%d\">\n",
+ option_cnt <= 20 ? 1 : 5);
+#else
+ output("<nobr>");
+ fputs("<font size=+1>Editing:</font>\n", stdout);
+ fprintf(stdout, "<SELECT name=\"resource\" "
+ "onChange=\"checkForClick()\" %s>\n",
+ option_cnt <=20 ? "" : "size=5");
+#endif
+
+#ifdef MCC_HTTPD /* template->styles nightmare */
+ if((rtype==PB_NAME) && (strcmp(res, "default"))) {
+ /* enter: STYLES MODE */
+ fprintf(stdout, "<OPTION value=ndefault>Exit styles mode\n");
+ } else {
+ fprintf(stdout, "<OPTION value=ndefault %s>The entire server\n",
+ (!strcmp(res, "default")) ? "SELECTED" : "");
+ }
+#else
+ fprintf(stdout, "<OPTION value=ndefault %s>The entire server\n",
+ (!strcmp(res, "default")) ? "SELECTED" : "");
+#endif
+ if(!strcmp(res, "default")) found=1;
+ options = list_objects(PB_PATH);
+#ifdef MCC_HTTPD /* template->styles nightmare */
+ if((options) && !((rtype==PB_NAME) && (strcmp(res, "default"))) ) {
+#else
+ if(options) {
+#endif
+ for(x=0; options[x]; x++) {
+ fprintf(stdout, "<OPTION value=f%s %s>%s\n",
+ options[x],
+ (!strcmp(options[x], res)) ? "SELECTED" : "",
+ options[x]);
+ if(!strcmp(options[x], res)) found=1;
+ }
+ }
+ options=list_objects(PB_NAME);
+#ifdef MCC_HTTPD /* template->styles nightmare */
+ if((options) && ((rtype==PB_NAME) && (strcmp(res, "default"))) ) {
+#else
+ if(options) {
+#endif
+ for(x=0; options[x]; x++) {
+ if(!strcmp(options[x], "default") ||
+ !strcmp(options[x], "cgi"))
+ continue;
+#ifdef MCC_HTTPD /* template->style usability */
+ fprintf(stdout, "<OPTION value=n%s %s>The style '%s'\n",
+ options[x],
+ (!strcmp(options[x], res)) ? "SELECTED":"",
+ options[x]);
+#else
+ fprintf(stdout, "<OPTION value=n%s %s>The template '%s'\n",
+ options[x],
+ (!strcmp(options[x], res)) ? "SELECTED":"",
+ options[x]);
+#endif
+ if(!strcmp(options[x], res)) found=1;
+ }
+ }
+ if(!found) {
+ if(rtype==PB_NAME) {
+ fprintf(stdout, "<OPTION value=n%s SELECTED>The template %s\n",
+ res, res);
+ } else {
+ fprintf(stdout, "<OPTION value=f%s SELECTED>%s\n",
+ res, res);
+ }
+ }
+ fputs("</SELECT></nobr>\n", stdout);
+ fputs("<nobr>", stdout);
+#ifndef MCC_PROXY
+ fprintf(stdout, "<INPUT type=button value=\"Browse...\" "
+ "onClick=\"window.location='rsrcpckr?b'\"> ");
+#endif
+#ifdef MCC_PROXY
+ fprintf(stdout, "</TD>\n<TD>");
+ fprintf(stdout, "<INPUT type=button value=\"Regular Expression...\" "
+ "onClick=\"var pat="
+ "prompt('Enter the regular expression to edit:', ''); "
+#else
+ fprintf(stdout, "<INPUT type=button value=\"Wildcard...\" "
+ "onClick=\"var pat="
+ "prompt('Enter the wildcard pattern to edit:', ''); "
+#endif
+ "if(pat!=null) window.location='rsrcpckr?"
+ "type="WILDCARD"&resource='+escape(pat);\">");
+#ifdef MCC_PROXY
+ fprintf(stdout, "</TD>\n</TR>\n</TABLE>\n");
+#endif
+ fputs("</nobr>", stdout);
+ /* output("</td></tr>\n"); */
+ }
+#endif
+}
+
+void booktrack(char *input, char **vars)
+{
+ char line[BIG_LINE];
+
+ if((vars[0] != NULL) && (vars[1] != NULL)) {
+ sprintf(line, "<a href=index?0>"
+ "<img src=\"%s\" hspace=8 align=%s alt=\"\"></a>",
+ (input[0] - '0') ? vars[0] : vars[1],
+ (vars[2] != NULL) ? vars[2] : "none");
+ output(line);
+ }
+}
+
+void docswitcher(char *input)
+{
+ char line[BIG_LINE];
+ char *whichimg, *whatmode;
+#ifdef USE_ADMSERV
+ char *qs = getenv("QUERY_STRING");
+ char *sname = getenv("SCRIPT_NAME");
+ char *mtmp;
+
+ char *tmp = getenv("SERVER_NAMES");
+ char *servers = NULL;
+ if(tmp) servers = STRDUP(tmp);
+#endif
+
+ if(!(input[0] - '0')) {
+ whichimg = "b-clsd.gif";
+ whatmode = "Express mode";
+ } else {
+ whichimg = "b-open.gif";
+ whatmode = "Full docs";
+ }
+
+ mtmp = (char *) MALLOC( (sname? strlen(sname) : 0) +
+ (qs? strlen(qs) : 0) +
+ (strlen(whichimg) + strlen(whatmode)) +
+ 1024);
+ sprintf(mtmp, "<center><table border=2 width=95%%>\n"
+ "<tr><td rowspan=2><a href=index%s>"
+ "<img src=\"../icons/%s\" "
+ "alt=\"[%s] \" border=2>"
+ "</td>\n",
+ (qs ? "?0" : sname),
+ whichimg, whatmode);
+ output(mtmp);
+
+#ifdef USE_ADMSERV
+ if(!servers) {
+ sprintf(line, "<td width=100%% align=center rowspan=2><b>%s</b></td>\n",
+ whatmode);
+ output(line);
+ } else
+ if(servers[0] == '(') {
+
+ sprintf(line, "<td width=100%% align=center>Current servers:<br>\n");
+ output(line);
+ output("<b>");
+
+ tmp=strtok(++servers, "|)");
+ while(tmp) {
+ char *tmp2;
+ output("<nobr>");
+ tmp2=strchr(tmp, '-');
+ tmp2++;
+ output(tmp2);
+ tmp=strtok(NULL, "|)");
+ if(tmp)
+ output(",");
+ output("</nobr>\n");
+ }
+ output("</b></td>\n");
+ } else {
+
+ sprintf(line, "<td width=100%% align=center>Current server: ");
+ output(line);
+ output("<b>");
+ tmp = strchr(servers, '-');
+ *tmp++ = '\0';
+ output(tmp);
+ output("</b>");
+ output("</td>\n");
+ }
+#endif
+ sprintf(mtmp, "<td rowspan=2><a href=index%s>"
+ "<img src=\"../icons/%s\" "
+ "alt=\"\" border=2></a></td></tr>\n",
+ (qs? "?0" : sname),
+ whichimg);
+ output(mtmp);
+#ifdef USE_ADMSERV
+ if(servers) {
+ sprintf(line, "<tr><td align=center>"
+ "<a href=\"/admin-serv/bin/chooser\">"
+ "Choose</a> a new server or set of servers</a></td>\n");
+ output(line);
+ }
+#endif
+ sprintf(line, "</tr></table></center>\n");
+ output(line);
+ output("<hr width=10%%>\n");
+}
+
+void docroot(char **vars)
+{
+#ifndef MCC_NEWS
+ char line[BIG_LINE];
+ pblock *pb = grab_pblock(PB_NAME, "default", "NameTrans", "document-root",
+ NULL, NULL);
+ char *docroot = "";
+ if(pb)
+ docroot = pblock_findval("root", pb);
+ sprintf(line, "<b>%s%s</b>\n", docroot, (vars[0] != NULL) ? vars[0] : "");
+ output(line);
+#endif
+}
+
+void serverroot(char **vars)
+{
+ char line[BIG_LINE];
+#ifdef USE_ADMSERV
+ char *sroot = getenv("NETSITE_ROOT");
+#else
+ char *sroot = get_mag_var("#ServerRoot");
+#endif
+ sprintf(line, "%s%s", (sroot) ? sroot : "", (vars[0]) ? vars[0] : "");
+ output(line);
+}
+
+void makeurl(char **vars)
+{
+ char line[BIG_LINE];
+
+ sprintf(line,"<a href=%s target=_blank>%s</a>\n",
+ get_serv_url(), vars[0] ? vars[0] : "");
+ output(line);
+}
+
+void curservname(void)
+{
+ output(get_srvname(0));
+}
+
+NSAPI_PUBLIC
+void pageheader(char **vars, char **config)
+{
+ char line[BIG_LINE];
+#if 0 /* MLM - put in to have non-working Back button */
+ char *ref=get_referer(config);
+ char *t;
+#endif
+
+ output("<center><table border=2 width=100%%>\n");
+
+ util_snprintf(line, BIG_LINE, "<tr>");
+ output(line);
+
+ util_snprintf(line, BIG_LINE, "<td align=center width=100%%>");
+ output(line);
+ util_snprintf(line, BIG_LINE, "<hr size=0 width=0>");
+ output(line);
+#if 0 /* MLM - put in to have non-working Back button */
+ t=strrchr(ref, '/');
+ *t++='\0';
+ util_snprintf(line, BIG_LINE, "<a href=\"%s/index/%s\">", ref, t);
+ output(line);
+ util_snprintf(line, BIG_LINE, "<img align=right src=../icons/back.gif "
+ "width=41 height=26 border=0></a>\n");
+ output(line);
+#endif
+ util_snprintf(line, BIG_LINE, "<FONT size=+2><b>%s</b></FONT>"
+ "<hr size=0 width=0>"
+ "</td>", vars[2]);
+ output(line);
+
+ output("</tr></table></center>\n");
+}
+
+char *_get_help_button(char *topic)
+{
+ char line[BIG_LINE];
+
+ util_snprintf( line, BIG_LINE,
+ "<input type=button value=\"%s\" "
+ "onClick=\"%s\">", XP_GetAdminStr(DBT_help_),
+ topic ? helpJavaScriptForTopic( topic ) : helpJavaScript() );
+
+ return(STRDUP(line));
+}
+
+NSAPI_PUBLIC char *helpJavaScriptForTopic( char *topic )
+{
+ char *tmp;
+ char line[BIG_LINE];
+ char *server=get_srvname(0);
+ char *type;
+ int typeLen;
+
+ /* Get the server type, without the instance name into type */
+ tmp = strchr( server, '-' );
+ typeLen = tmp - server;
+
+ type = (char *)MALLOC( typeLen + 1 );
+ type[typeLen] = '\0';
+ while ( typeLen-- ) {
+ type[typeLen] = server[typeLen];
+ }
+ util_snprintf( line, BIG_LINE,
+ "if ( top.helpwin ) {"
+ " top.helpwin.focus();"
+ " top.helpwin.infotopic.location='%s/%s/admin/tutor?!%s';"
+ "} else {"
+ " window.open('%s/%s/admin/tutor?%s', '"
+ INFO_IDX_NAME"_%s', "
+ HELP_WIN_OPTIONS");}",
+ getenv("SERVER_URL"), server, topic,
+ getenv("SERVER_URL"), server, topic,
+ type );
+
+ return(STRDUP(line));
+}
+
+NSAPI_PUBLIC char *helpJavaScript()
+{
+ char *tmp, *sn;
+
+ tmp=STRDUP(getenv("SCRIPT_NAME"));
+ if(strlen(tmp) > (unsigned)BIG_LINE)
+ tmp[BIG_LINE-2]='\0';
+ sn=strrchr(tmp, '/');
+ if( sn )
+ *sn++='\0';
+ return helpJavaScriptForTopic( sn );
+}
+
+void submit(int verify, char **vars)
+{
+ char line[BIG_LINE];
+ char outline[BIG_LINE];
+
+ if(verify) {
+ util_snprintf(line, BIG_LINE, "<SCRIPT language="MOCHA_NAME">\n"
+ "function verify(form) {\n"
+ " if(confirm('Do you really want to %s?'))\n"
+ " form.submit();\n"
+ "}\n"
+ "</SCRIPT>\n", vars[0]);
+ output(line);
+ }
+
+ output("<center><table border=2 width=100%%><tr>");
+
+ if(!verify) {
+ util_snprintf(outline, BIG_LINE, "%s%s%s%s%s",
+ "<td width=33%% align=center>",
+ "<input type=submit value=\"",
+ XP_GetAdminStr(DBT_ok_),
+ "\">",
+ "</td>\n");
+ } else {
+ util_snprintf(outline, BIG_LINE, "%s%s%s%s%s%s",
+ "<td width=33%% align=center>",
+ "<input type=button value=\"",
+ XP_GetAdminStr(DBT_ok_),
+ "\" ",
+ "onclick=\"verify(this.form)\">",
+ "</td>\n");
+ }
+ output(outline);
+ util_snprintf(outline, BIG_LINE, "%s%s%s%s",
+ "<td width=34%% align=center>",
+ "<input type=reset value=\"",
+ XP_GetAdminStr(DBT_reset_),
+ "\"></td>\n");
+ output(outline);
+
+ util_snprintf(line, BIG_LINE, "<td width=33%% align=center>%s</td>\n",
+ _get_help_button( vars[0] ));
+ output(line);
+
+ output("</tr></table></center>\n");
+
+ output("</form>\n");
+
+ output("<SCRIPT language="MOCHA_NAME">\n");
+ output("</SCRIPT>\n");
+}
+
+void helpbutton(char *topic)
+{
+ output("<form><p><div align=right><table width=33%% border=2>"
+ "<tr><td align=center>");
+ output(_get_help_button(topic));
+ output("</td></tr></table></div></form>\n");
+ output("<SCRIPT language="MOCHA_NAME">\n");
+ output("</SCRIPT>\n");
+}
+
+void dialogsubmit(char *topic)
+{
+ char line[BIG_LINE];
+ char outline[BIG_LINE];
+
+ output("<center><table border=2 width=100%%><tr>");
+
+ util_snprintf(outline, BIG_LINE, "%s%s%s%s%s",
+ "<td width=33%% align=center>",
+ "<input type=submit value=\"",
+ XP_GetAdminStr(DBT_done_),
+ "\">",
+ "</td>\n");
+ output(outline);
+ util_snprintf(outline, BIG_LINE, "%s%s%s%s%s",
+ "<td width=34%% align=center>",
+ "<input type=button value=\"",
+ XP_GetAdminStr(DBT_cancel_),
+ "\" "
+ "onClick=\"top.close()\"></td>\n");
+ output(outline);
+
+ util_snprintf(line, BIG_LINE, "<td width=33%% align=center>%s</td>\n",
+ _get_help_button(topic));
+ output(line);
+
+ output("</tr></table></center>\n");
+
+ output("</form>\n");
+
+ output("<SCRIPT language="MOCHA_NAME">\n");
+ output("</SCRIPT>\n");
+}
+
+void helpjsfn(void)
+{
+ char *tmp;
+ char line[BIG_LINE];
+ char *server=get_srvname(0);
+ char *type;
+ int typeLen;
+
+ /* Get the server type, without the instance name into type */
+ tmp = strchr( server, '-' );
+ typeLen = tmp - server;
+
+ type = (char *)MALLOC( typeLen + 1 );
+ type[typeLen] = '\0';
+ while ( typeLen-- ) {
+ type[typeLen] = server[typeLen];
+ }
+
+ output("function displayHelpTopic(topic)\n");
+ output("{\n");
+ util_snprintf(line, BIG_LINE,
+ " if (top.helpwin) {\n"
+ " top.helpwin.focus();\n"
+ " top.helpwin.infotopic.location='%s/%s/admin/tutor?!' + topic;\n"
+ " } else {\n"
+ " window.open('%s/%s/admin/tutor?' + topic, '"
+ INFO_IDX_NAME"_%s', "
+ HELP_WIN_OPTIONS");\n"
+ " }\n"
+ "}\n",
+ getenv("SERVER_URL"), server,
+ getenv("SERVER_URL"), server,
+ type );
+ output(line);
+}
+
+void link_referer(char **input, char **vars)
+{
+ char line[BIG_LINE];
+
+ sprintf( line, "<SCRIPT language="MOCHA_NAME">\n"
+ "document.writeln( '%s'.link( '%s' ) );\n"
+ "</SCRIPT>\n", ( vars[0] ? vars[0] : getenv( "SCRIPT_NAME" ) ),
+ cookieValue( "adminReferer", NULL ) );
+ output( line );
+}
+
+int get_directive(char *string)
+{
+ int index = -1;
+ register int x;
+
+ for(x=0; x < MAXTEMPLATE; x++) {
+ if(!strncmp(string, templates[x].name,
+ strlen(templates[x].name))) {
+ index = x;
+ break;
+ }
+ }
+ return index;
+}
+
+NSAPI_PUBLIC int directive_is(char *target, char *directive)
+{
+ char *position = (target + strlen(DIRECTIVE_START));
+ return(!(strncmp(directive, position, strlen(directive))));
+}
+
+char **get_vars(char *string)
+{
+ char **vars;
+ register int x;
+ int isvar;
+ char scratch[BIG_LINE];
+ char lastchar;
+
+/* Initialize the vars array.
+ */
+ vars = (char **) MALLOC((MAXVARS)*(sizeof(char *)));
+ for(x=0; x< MAXVARS; x++)
+ vars[x] = NULL;
+
+ isvar = -1;
+ x = 0;
+ scratch[0] = '\0';
+ lastchar = ' ';
+
+ while(*string != '\0') {
+ if((*string == '\"') && (lastchar != '\\'))
+ if(isvar != -1) {
+ vars[x++] = (char *)STRDUP(scratch);
+ isvar = -1;
+ if(x == MAXVARS)
+ break;
+ } else
+ isvar = 0;
+ else
+ if(isvar != -1) {
+ scratch[isvar++] = *string;
+ scratch[isvar] = '\0';
+ }
+ else
+ if(*string == DIRECTIVE_END)
+ break;
+ lastchar = *string;
+ string++;
+ }
+ return vars;
+}
+
+static void output(char *line)
+{
+ if(status)
+ fputs(line, stdout);
+}
diff --git a/lib/libadmin/util.c b/lib/libadmin/util.c
new file mode 100644
index 00000000..b560055d
--- /dev/null
+++ b/lib/libadmin/util.c
@@ -0,0 +1,1340 @@
+/** BEGIN COPYRIGHT BLOCK
+ * Copyright 2001 Sun Microsystems, Inc.
+ * Portions copyright 1999, 2001-2003 Netscape Communications Corporation.
+ * All rights reserved.
+ * END COPYRIGHT BLOCK **/
+/*
+ * util.c: Miscellaneous stuffs
+ *
+ * All blame to Mike McCool
+ */
+
+#include "libadmin/libadmin.h"
+#include "base/util.h"
+#include "private/pprio.h"
+
+#ifdef XP_UNIX
+#include <dirent.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#else
+#include <base/file.h>
+#include <sys/stat.h>
+#endif /* WIN32? */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <ctype.h> /* isdigit */
+
+#define NUM_ENTRIES 64
+
+#ifdef MCC_PROXY
+char *
+XP_GetString()
+{
+ return "ZAP";
+}
+#endif
+
+#ifdef XP_WIN32
+char *GetQueryNT(void)
+{
+ char *qs = getenv("QUERY_STRING");
+ if(qs && (*qs == '\0'))
+ qs = NULL;
+ return qs;
+}
+#endif /* XP_WIN32 */
+
+void escape_for_shell(char *cmd) {
+ register int x,y,l;
+
+ l=strlen(cmd);
+ for(x=0;cmd[x];x++) {
+ if(strchr(" &;`'\"|*!?~<>^()[]{}$\\\x0A",cmd[x])){
+ for(y=l+1;y>x;y--)
+ cmd[y] = cmd[y-1];
+ l++; /* length has been increased */
+ cmd[x] = '\\';
+ x++; /* skip the character */
+ }
+ }
+}
+
+int _admin_dumbsort(const void *s1, const void *s2)
+{
+ return strcmp(*((char **)s1), *((char **)s2));
+}
+
+#ifdef XP_UNIX /* WIN32 change */
+/* Lists all files in a directory. */
+char **list_directory(char *path, int dashA)
+{
+ char **ar;
+ DIR *ds;
+ struct dirent *d;
+ int n, p;
+
+ n = NUM_ENTRIES;
+ p = 0;
+
+ ar = (char **) MALLOC(n * sizeof(char *));
+
+ if(!(ds = opendir(path))) {
+ return NULL;
+ }
+
+ while( (d = readdir(ds)) ) {
+ if ( ( d->d_name[0] != '.' ) ||
+ ( dashA && d->d_name[1] &&
+ ( d->d_name[1] != '.' || d->d_name[2] ) ) ) {
+ if(p == (n-1)) {
+ n += NUM_ENTRIES;
+ ar = (char **) REALLOC(ar, n*sizeof(char *));
+ }
+ /* 2: Leave space to add a trailing slash later */
+ ar[p] = (char *) MALLOC(strlen(d->d_name) + 2);
+ strcpy(ar[p++], d->d_name);
+ }
+ }
+ closedir(ds);
+
+ qsort((void *)ar, p, sizeof(char *), _admin_dumbsort);
+ ar[p] = NULL;
+
+ return ar;
+}
+
+#else /* WIN32 change */
+/* Lists all files in a directory. */
+char **list_directory(char *path, int dashA)
+{
+ char **ar;
+ SYS_DIR ds;
+ SYS_DIRENT *d;
+ int n, p;
+
+ n = NUM_ENTRIES;
+ p = 0;
+
+ ar = (char **) MALLOC(n * sizeof(char *));
+
+ if(!(ds = dir_open(path))) {
+ return NULL;
+ }
+
+ while( (d = dir_read(ds)) ) {
+ if ( ( d->d_name[0] != '.' ) ||
+ ( dashA && d->d_name[1] &&
+ ( d->d_name[1] != '.' || d->d_name[2] ) ) ) {
+ if(p == (n-1)) {
+ n += NUM_ENTRIES;
+ ar = (char **) REALLOC(ar, n*sizeof(char *));
+ }
+ /* 2: Leave space to add a trailing slash later */
+ ar[p] = (char *) MALLOC(strlen(d->d_name) + 2);
+ strcpy(ar[p++], d->d_name);
+ }
+ }
+ dir_close(ds);
+
+ qsort((void *)ar, p, sizeof(char *), _admin_dumbsort);
+ ar[p] = NULL;
+
+ return ar;
+}
+#endif /* WIN32 */
+
+int file_exists(char *fn)
+{
+ struct stat finfo;
+
+ if(!stat(fn, &finfo))
+ return 1;
+ else
+ return 0;
+}
+
+int get_file_size(char *fn)
+{
+ struct stat finfo;
+ int ans = -1;
+
+ if(!stat(fn, &finfo)) {
+ ans = finfo.st_size;
+ } else {
+ report_error(FILE_ERROR, fn, "Could not get size of file.");
+ }
+ return ans;
+}
+
+int ADM_mkdir_p(char *dir, int mode)
+{
+ char path[PATH_MAX];
+ struct stat fi;
+ char *slash = NULL;
+
+ if (dir)
+ strcpy (path, dir);
+ else
+ return 0;
+
+ if (slash = strchr(path, FILE_PATHSEP))
+ slash++; /* go past root */
+ else
+ return 0;
+
+ while (slash && *slash) {
+ slash = strchr(slash, FILE_PATHSEP);
+ if (slash) *slash = '\0'; /* check path till here */
+
+ if (stat(path, &fi) == -1) {
+#ifdef XP_UNIX
+ if (mkdir(path, mode) == -1)
+#else /* XP_WIN32 */
+ if (!CreateDirectory(path, NULL))
+#endif
+ return 0;
+ }
+
+ if (slash) {
+ *slash = FILE_PATHSEP; /* restore path */
+ slash++; /* check remaining path */
+ }
+ }
+ return 1;
+}
+
+int ADM_copy_directory(char *src_dir, char *dest_dir)
+{
+ SYS_DIR ds;
+ SYS_DIRENT *d;
+ struct stat fi;
+ char src_file[PATH_MAX], dest_file[PATH_MAX], fullname[PATH_MAX];
+
+ if (!(ds = dir_open(src_dir)))
+ report_error(FILE_ERROR, "Can't read directory", src_dir);
+
+ while (d = dir_read(ds)) {
+ if (d->d_name[0] != '.') {
+ sprintf(fullname, "%s/%s", src_dir, d->d_name);
+ if (system_stat(fullname, &fi) == -1)
+ continue;
+
+ sprintf(src_file, "%s%c%s", src_dir, FILE_PATHSEP, d->d_name);
+ sprintf(dest_file, "%s%c%s", dest_dir, FILE_PATHSEP, d->d_name);
+ if (S_ISDIR(fi.st_mode)) {
+ char *sub_src_dir = STRDUP(src_file);
+ char *sub_dest_dir = STRDUP(dest_file);
+ if (!ADM_mkdir_p(sub_dest_dir, 0755)) {
+ report_error(FILE_ERROR, "Cannot create directory",
+ sub_dest_dir);
+ return 0;
+ }
+ if (!ADM_copy_directory(sub_src_dir, sub_dest_dir))
+ return 0;
+ FREE(sub_src_dir);
+ FREE(sub_dest_dir);
+ }
+ else
+ cp_file(src_file, dest_file, 0644);
+ }
+ }
+ dir_close(ds);
+ return(1);
+}
+
+void ADM_remove_directory(char *path)
+{
+ struct stat finfo;
+ char **dirlisting;
+ register int x=0;
+ int stat_good = 0;
+ char *fullpath = NULL;
+
+#ifdef XP_UNIX
+ stat_good = (lstat(path, &finfo) == -1 ? 0 : 1);
+#else /* XP_WIN32 */
+ stat_good = (stat(path, &finfo) == -1 ? 0 : 1);
+#endif
+
+ if(!stat_good) return;
+
+ if(S_ISDIR(finfo.st_mode)) {
+ dirlisting = list_directory(path,1);
+ if(!dirlisting) return;
+
+ for(x=0; dirlisting[x]; x++) {
+ fullpath = (char *) MALLOC(strlen(path) +
+ strlen(dirlisting[x]) + 4);
+ sprintf(fullpath, "%s%c%s", path, FILE_PATHSEP, dirlisting[x]);
+#ifdef XP_UNIX
+ stat_good = (lstat(fullpath, &finfo) == -1 ? 0 : 1);
+#else /* XP_WIN32 */
+ stat_good = (stat(fullpath, &finfo) == -1 ? 0 : 1);
+#endif
+ if(!stat_good) continue;
+ if(S_ISDIR(finfo.st_mode)) {
+ ADM_remove_directory(fullpath);
+ } else {
+ unlink(fullpath);
+ }
+ FREE(fullpath);
+ }
+#ifdef XP_UNIX
+ rmdir(path);
+#else /* XP_WIN32 */
+ RemoveDirectory(path);
+#endif
+ } else {
+ delete_file(path);
+ }
+ return;
+}
+
+/* return: mtime(f1) < mtime(f2) ? */
+int mtime_is_earlier(char *file1, char *file2)
+{
+ struct stat fi1, fi2;
+
+ if(stat(file1, &fi1)) {
+ return -1;
+ }
+ if(stat(file2, &fi2)) {
+ return -1;
+ }
+ return( (fi1.st_mtime < fi2.st_mtime) ? 1 : 0);
+}
+
+time_t get_mtime(char *fn)
+{
+ struct stat fi;
+
+ if(stat(fn, &fi))
+ return 0;
+ return fi.st_mtime;
+}
+
+int all_numbers(char *target)
+{
+ register int x=0;
+
+ while(target[x])
+ if(!isdigit(target[x++]))
+ return 0;
+ return 1;
+}
+
+
+int all_numbers_float(char *target)
+{
+ register int x;
+ int seenpt;
+
+ for(x = 0, seenpt = 0; target[x]; ++x) {
+ if((target[x] == '.') && (!seenpt))
+ seenpt = 1;
+ else if((!isdigit(target[x])) && seenpt)
+ return 0;
+ }
+ return 1;
+}
+
+/* Get the admin/config directory. */
+char *get_admcf_dir(int whichone)
+{
+#ifdef USE_ADMSERV
+ char *confdir = NULL;
+
+ char *tmp = get_num_mag_var(whichone, "#ServerRoot");
+ if(!tmp) {
+ /* sigh */
+ report_error(INCORRECT_USAGE, "No server root variable",
+ "The magnus.conf variable #ServerRoot was "
+ "not set. Please set the value of your server "
+ "root through the administrative forms.");
+ }
+ confdir = (char *) MALLOC(strlen(tmp) + strlen("config") + 4);
+ sprintf(confdir, "%s%cconfig%c", tmp, FILE_PATHSEP, FILE_PATHSEP);
+
+ return confdir;
+#else
+ char *confdir;
+ char line[BIG_LINE];
+ sprintf(line, "%s%cadmin%cconfig%c", get_mag_var("#ServerRoot"),
+ FILE_PATHSEP, FILE_PATHSEP, FILE_PATHSEP);
+ confdir = STRDUP(line);
+#endif
+ return STRDUP(confdir);
+}
+
+/* Get the current HTTP server URL. */
+char *get_serv_url(void)
+{
+#ifdef USE_ADMSERV
+ char *name = get_mag_var("ServerName");
+ char *port = get_mag_var("Port");
+ char *protocol = NULL;
+ char line[BIG_LINE];
+
+#ifndef NS_UNSECURE
+ char *security = get_mag_var("Security");
+
+ if(!security || strcasecmp(security, "on")) {
+ protocol = STRDUP("http");
+ if(!strcmp(port, "80"))
+ port = STRDUP("");
+ else {
+ sprintf(line, ":%s", port);
+ port = STRDUP(line);
+ }
+ } else {
+ protocol = STRDUP("https");
+ if(!strcmp(port, "443"))
+ port = STRDUP("");
+ else {
+ sprintf(line, ":%s", port);
+ port = STRDUP(line);
+ }
+ }
+#else
+ protocol = STRDUP("http");
+ if(!strcmp(port, "80"))
+ port = STRDUP("");
+ else {
+ sprintf(line, ":%s", port);
+ port = STRDUP(line);
+ }
+#endif
+
+ sprintf(line, "%s://%s%s", protocol, name, port);
+ return(STRDUP(line));
+#else
+ return(getenv("SERVER_URL"));
+#endif
+}
+
+/* ------------------------------- run_cmd -------------------------------- */
+
+
+/* Previously in install. This is also pretty UNIX-ish. */
+
+/* Nirmal: Added code for Win32 implementation of this function. */
+
+#include <signal.h>
+#ifdef XP_UNIX
+#include <sys/wait.h>
+#endif /* XP_UNIX */
+
+
+int run_cmd(char *cmd, FILE *closeme, struct runcmd_s *rm)
+{
+#ifdef WIN32
+ HANDLE hproc;
+ PROCESS_INFORMATION child;
+ STARTUPINFO siStartInfo ;
+#else
+ struct stat fi;
+ int exstat;
+ char *errmsg, tfn[128];
+ FILE *f;
+ int fd;
+ pid_t pid;
+#endif
+
+
+#ifdef WIN32
+ /* Nirmal:
+ For now, i will just spawn
+ a child in WINNT to execute the command. Communication to
+ the parent is done through stdout pipe, that was setup by
+ the parent.
+
+ */
+ hproc = OpenProcess(STANDARD_RIGHTS_REQUIRED, FALSE, GetCurrentProcessId());
+ if (hproc == NULL) {
+ fprintf(stdout, "Content-type: text/html\n\n");
+ fflush(stdout);
+ report_error(SYSTEM_ERROR, NULL, "Could not open handle to myself");
+ return -1; // stmt. not reached.
+ }
+
+ ZeroMemory(&child, sizeof(PROCESS_INFORMATION));
+ ZeroMemory(&siStartInfo, sizeof(STARTUPINFO));
+ siStartInfo.cb = sizeof(STARTUPINFO);
+ siStartInfo.lpReserved = siStartInfo.lpReserved2 = NULL;
+ siStartInfo.cbReserved2 = 0;
+ siStartInfo.lpDesktop = NULL;
+ siStartInfo.dwFlags = STARTF_USESHOWWINDOW;
+// Several fields arent used when dwFlags is not set.
+// siStartInfo.hStdInput = hChildStdinRd;
+// siStartInfo.hStdOutput = siStartInfo.hStdError = hChildStdoutWr;
+ siStartInfo.wShowWindow = SW_HIDE;
+
+ if ( ! CreateProcess(
+ NULL, // pointer to name of executable module
+ cmd, // pointer to command line string
+ NULL, // pointer to process security attribute
+ NULL, // pointer to thread security attributes
+ TRUE, // handle inheritance flag
+ 0, // creation flags
+ NULL, // pointer to new environment block
+ NULL, // pointer to current directory name
+ &siStartInfo, // pointer to STARTUPINFO
+ &child // pointer to PROCESS_INFORMATION
+ ))
+ {
+ rm->title = "CreateProcess failed";
+ rm->msg = "run_cmd: Can't create new process. ";
+ rm->arg = "";
+ rm->sysmsg = 1;
+ return -1;
+ }
+ else
+ return 0;
+#else
+ sprintf(cmd, "%s > /tmp/startmsg.%d 2>&1 < /dev/null", cmd, getpid()); /* */
+ /* FUCK UNIX SIGNALS. */
+ signal(SIGCHLD, SIG_DFL);
+ switch( (pid = fork()) ) {
+ case 0:
+ /* Hmm. Work around an apparent bug in stdio. */
+ if(closeme)
+ close(fileno(closeme));
+ execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
+ /* DOH! */
+ sprintf(tfn, "/tmp/startmsg.%d", getpid());
+ if(!(f = fopen(tfn, "w")))
+ exit(1);
+ fprintf(f, "Exec of %s failed. The error was %s.\n", cmd,
+ system_errmsg());
+ fclose(f);
+ exit(1);
+ case -1:
+ rm->title = "Fork failed";
+ rm->msg = "Can't create new process. %s";
+ rm->arg = "";
+ rm->sysmsg = 1;
+ return -1;
+ default:
+ sprintf(tfn, "/tmp/startmsg.%d", getpid());
+
+ if(waitpid(pid, &exstat, 0) == -1) {
+ rm->title = "Can't wait for child";
+ rm->msg = "Can't wait for process. %s";
+ rm->arg = "";
+ rm->sysmsg = 1;
+ return -1;
+ }
+ if(exstat) {
+ if(!(fd = open(tfn, O_RDONLY))) {
+ rm->title = "Can't open error file";
+ rm->msg = "Can't find error file %s.";
+ rm->arg = cmd;
+ rm->sysmsg = 1;
+ return -1;
+ }
+ fstat(fd, &fi);
+ if((fi.st_size > 0) && (fi.st_size < 8192)) {
+ errmsg = (char *) MALLOC(fi.st_size + 1);
+ read(fd, errmsg, fi.st_size);
+ errmsg[fi.st_size] = '\0';
+ close(fd);
+ unlink(tfn);
+ rm->title = "Command execution failed";
+ rm->msg = "The command did not execute. "
+ "Here is the output:<p>\n<pre>\n%s\n</pre>\n";
+ rm->arg = errmsg;
+ rm->sysmsg = 0;
+ return -1;
+ }
+ else {
+ close(fd);
+ unlink(tfn);
+
+ rm->title = "Command execution failed";
+ rm->msg = "The command didn't execute, and it did not produce "
+ "any output. Run <code>%s</code> from the command "
+ "line and examine the output.\n";
+ rm->arg = cmd;
+ rm->sysmsg = 0;
+ return -1;
+ }
+ }
+ unlink(tfn);
+ return 0;
+ }
+#endif /* WIN32 */
+
+}
+
+
+
+/* This is basically copy_file from the install section, with the error
+ * reporting changed to match the admin stuff. Since some stuff depends
+ * on copy_file being the install version, I'll cheat and call this one
+ * cp_file. */
+#ifdef XP_UNIX
+
+#define COPY_BUFFER_SIZE 4096
+
+void cp_file(char *sfile, char *dfile, int mode)
+{
+ int sfd, dfd, len;
+ struct stat fi;
+
+ char copy_buffer[COPY_BUFFER_SIZE];
+ unsigned long read_len;
+
+/* Make sure we're in the right umask */
+ umask(022);
+
+ if( (sfd = open(sfile, O_RDONLY)) == -1)
+ report_error(FILE_ERROR, sfile, "Can't open file for reading.");
+
+ fstat(sfd, &fi);
+ if(!(S_ISREG(fi.st_mode))) {
+ close(sfd);
+ return;
+ }
+ len = fi.st_size;
+
+ if( (dfd = open(dfile, O_RDWR | O_CREAT | O_TRUNC, mode)) == -1)
+ report_error(FILE_ERROR, dfile, "Can't write to file.");
+
+ while(len) {
+ read_len = len>COPY_BUFFER_SIZE?COPY_BUFFER_SIZE:len;
+
+ if ( (read_len = read(sfd, copy_buffer, read_len)) == -1) {
+ report_error(FILE_ERROR, sfile, "Error reading file for copy.");
+ }
+
+ if ( write(dfd, copy_buffer, read_len) != read_len) {
+ report_error(FILE_ERROR, dfile, "Error writing file for copy.");
+ }
+
+ len -= read_len;
+ }
+ close(sfd);
+ close(dfd);
+}
+
+#else /* XP_WIN32 */
+void cp_file(char *sfile, char *dfile, int mode)
+{
+ HANDLE sfd, dfd, MapHandle;
+ PCHAR fp;
+ DWORD BytesWritten = 0;
+ DWORD len;
+
+ if( (sfd = CreateFile(sfile, GENERIC_READ,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL))
+ == INVALID_HANDLE_VALUE) {
+ report_error(FILE_ERROR, "Cannot open file for reading", sfile);
+ }
+ len = GetFileSize(sfd, NULL);
+ if( (dfd = CreateFile(dfile, GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) {
+ report_error(FILE_ERROR, "Cannot open destination file for writing",
+ dfile);
+ }
+ if (len == 0)
+ return;
+ if( (MapHandle = CreateFileMapping(sfd, NULL, PAGE_READONLY,
+ 0, 0, NULL)) == NULL) {
+ report_error(FILE_ERROR, "Cannot create file mapping", sfile);
+ }
+ if (!(fp = MapViewOfFile(MapHandle, FILE_MAP_READ, 0, 0, 0))) {
+ report_error(FILE_ERROR, "Cannot map file %s", sfile);
+ }
+ while ( len) {
+ if(!WriteFile(dfd, fp, len, &BytesWritten, NULL)) {
+ report_error(FILE_ERROR, "Cannot write new file", dfile);
+ }
+ len -= BytesWritten;
+ fp += BytesWritten;
+ }
+
+ CloseHandle(sfd);
+ UnmapViewOfFile(fp);
+ CloseHandle(MapHandle);
+ FlushFileBuffers(dfd);
+ CloseHandle(dfd);
+}
+#endif
+
+int delete_file(char *path)
+{
+#ifdef XP_UNIX
+ return unlink(path);
+#else
+ return !(DeleteFile(path));
+#endif
+}
+
+void create_dir(char *dir, int mode)
+{
+ if ((dir == (char *) NULL) || (strlen(dir) == 0)) {
+ report_error(FILE_ERROR, "No directory is specified",
+ "Could not create a necessary directory.");
+ }
+
+ if(!file_exists(dir)) {
+#ifdef XP_UNIX
+ if(mkdir(dir, mode) == -1) {
+#else /* XP_WIN32 */
+ if(!CreateDirectory(dir, NULL)) {
+ if (GetLastError() != ERROR_ALREADY_EXISTS)
+#endif /* XP_WIN32 */
+ report_error(FILE_ERROR, dir,
+ "Could not create a necessary directory.");
+ }
+ }
+}
+
+#ifdef XP_UNIX
+SYS_FILE lf;
+#elif defined(XP_WIN32)
+HANDLE lf;
+#endif
+
+char *get_flock_path(void)
+{
+ char *result="";
+ char *port=getenv("SERVER_PORT");
+#ifdef XP_UNIX
+ result=(char *) MALLOC(strlen("/tmp/lock.%%s.")+strlen(port)+4);
+ sprintf(result, "/tmp/lock.%%s.%s", port);
+#endif
+ return result;
+}
+
+/* Open a file with locking, close a file with unlocking. */
+FILE *fopen_l(char *path, char *mode)
+{
+ FILE *f = fopen(path, mode);
+ char *lockpath;
+ char *sn=get_srvname(0);
+ char *flp=FILE_LOCK_PATH;
+
+ if(f == NULL) return NULL;
+ lockpath=(char *) MALLOC(strlen(sn)+strlen(flp)+16);
+ sprintf(lockpath, flp, sn);
+#ifdef XP_UNIX
+ if( (lf=system_fopenRW(lockpath)) == SYS_ERROR_FD)
+ report_error(FILE_ERROR, lockpath, "Could not open file.");
+ if(system_flock(lf)==IO_ERROR)
+ report_error(FILE_ERROR, lockpath, "Could not lock file.");
+#elif defined(XP_WIN32)
+ /* Using mutexes because if the CGI program dies, the mutex will be
+ * automatically released by the OS for another process to grab.
+ * Semaphores do not have this property; and if the CGI program crashes,
+ * the admin server would be effectively crippled.
+ */
+ if ( (lf = CreateMutex(NULL, 0, lockpath)) == NULL) {
+ report_error(FILE_ERROR, lockpath, "Could not create admin mutex.");
+ } else {
+ if ( WaitForSingleObject(lf, 60*1000) == WAIT_FAILED) {
+ report_error(FILE_ERROR, lockpath, "Unable to obtain mutex after 60 seconds.");
+ }
+ }
+#endif /* XP_UNIX */
+ return f;
+}
+
+void fclose_l(FILE *f)
+{
+ fclose(f);
+#ifdef XP_UNIX
+ if(system_ulock(lf)==IO_ERROR)
+ report_error(FILE_ERROR, NULL, "Could not unlock lock file.");
+ system_fclose(lf);
+#elif defined(XP_WIN32)
+ if (lf) {
+ ReleaseMutex(lf);
+ CloseHandle(lf);
+ }
+#endif /* XP_UNIX */
+}
+
+/* Ripped off from the client. (Sorry, Lou.) */
+/* */
+/* The magic set of 64 chars in the uuencoded data */
+unsigned char uuset[] = {
+'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T',
+'U','V','W','X','Y','Z','a','b','c','d','e','f','g','h','i','j','k','l','m','n',
+'o','p','q','r','s','t','u','v','w','x','y','z','0','1','2','3','4','5','6','7',
+'8','9','+','/' };
+
+int do_uuencode(unsigned char *src, unsigned char *dst, int srclen)
+{
+ int i, r;
+ unsigned char *p;
+
+/* To uuencode, we snip 8 bits from 3 bytes and store them as
+6 bits in 4 bytes. 6*4 == 8*3 (get it?) and 6 bits per byte
+yields nice clean bytes
+
+It goes like this:
+ AAAAAAAA BBBBBBBB CCCCCCCC
+turns into the standard set of uuencode ascii chars indexed by numbers:
+ 00AAAAAA 00AABBBB 00BBBBCC 00CCCCCC
+
+Snip-n-shift, snip-n-shift, etc....
+
+*/
+
+ for (p=dst,i=0; i < srclen; i += 3) {
+ /* Do 3 bytes of src */
+ register char b0, b1, b2;
+
+ b0 = src[0];
+ if (i==srclen-1)
+ b1 = b2 = '\0';
+ else if (i==srclen-2) {
+ b1 = src[1];
+ b2 = '\0';
+ }
+ else {
+ b1 = src[1];
+ b2 = src[2];
+ }
+
+ *p++ = uuset[b0>>2];
+ *p++ = uuset[(((b0 & 0x03) << 4) | ((b1 & 0xf0) >> 4))];
+ *p++ = uuset[(((b1 & 0x0f) << 2) | ((b2 & 0xc0) >> 6))];
+ *p++ = uuset[b2 & 0x3f];
+ src += 3;
+ }
+ *p = 0; /* terminate the string */
+ r = (unsigned char *)p - (unsigned char *)dst;/* remember how many we did */
+
+ /* Always do 4-for-3, but if not round threesome, have to go
+ clean up the last extra bytes */
+
+ for( ; i != srclen; i--)
+ *--p = '=';
+
+ return r;
+}
+
+char *alert_word_wrap(char *str, int width, char *linefeed)
+{
+ char *ans = NULL;
+ int counter=0;
+ int lsc=0, lsa=0;
+ register int strc=0, ansc=0;
+ register int x=0;
+
+ /* assume worst case */
+ ans = (char *) MALLOC((strlen(str)*strlen(linefeed))+32);
+
+ for(strc=0, ansc=0; str[strc]; /*none*/) {
+ if(str[strc]=='\n') {
+ counter=0;
+ lsc=0, lsa=0;
+ for(x=0; linefeed[x]; x++) {
+ ans[ansc++]=linefeed[x];
+ }
+ strc++;
+ } else if(str[strc]=='\r') {
+ strc++;
+ } else if(str[strc]=='\\') {
+ ans[ansc++]='\\';
+ ans[ansc++]=strc++;
+ } else {
+ if(counter==width) {
+ if(lsc && lsa) {
+ strc=lsc;
+ ansc=lsa;
+
+ counter=0;
+ lsc=0, lsa=0;
+ for(x=0; linefeed[x]; x++) {
+ ans[ansc++]=linefeed[x];
+ }
+ strc++;
+ } else {
+ /* else, you're a loser, I'm breaking your big word anyway */
+ counter=0;
+ lsc=0, lsa=0;
+ for(x=0; linefeed[x]; x++) {
+ ans[ansc++]=linefeed[x];
+ }
+ strc++;
+ }
+ } else {
+ if(str[strc] == ' ') {
+ lsc=strc;
+ lsa=ansc;
+ }
+ ans[ansc++]=str[strc++];
+ counter++;
+ }
+ }
+ }
+ ans[ansc]='\0';
+ return ans;
+}
+
+void remove_directory(char *path)
+{
+ struct stat finfo;
+ char **dirlisting;
+ register int x=0;
+ int stat_good = 0;
+ char *fullpath = NULL;
+
+#ifdef XP_UNIX
+ stat_good = (lstat(path, &finfo) == -1 ? 0 : 1);
+#else /* WIN32 */
+ stat_good = (stat(path, &finfo) == -1 ? 0 : 1);
+#endif /* XP_UNIX */
+
+ if(!stat_good) return;
+
+ if(S_ISDIR(finfo.st_mode)) {
+ dirlisting = list_directory(path,1);
+ if(!dirlisting) return;
+
+ for(x=0; dirlisting[x]; x++) {
+ fullpath = (char *) MALLOC(strlen(path) +
+ strlen(dirlisting[x]) + 4);
+ sprintf(fullpath, "%s%c%s", path, FILE_PATHSEP, dirlisting[x]);
+#ifdef XP_UNIX
+ stat_good = (lstat(fullpath, &finfo) == -1 ? 0 : 1);
+#else /* WIN32 */
+ stat_good = (stat(fullpath, &finfo) == -1 ? 0 : 1);
+#endif /* XP_UNIX */
+ if(!stat_good) continue;
+ if(S_ISDIR(finfo.st_mode)) {
+ remove_directory(fullpath);
+ } else {
+ fprintf(stdout, "<i>Removing file</i> "
+ "<code>%s</code><br>\n", fullpath);
+ unlink(fullpath);
+ }
+ FREE(fullpath);
+ }
+ fprintf(stdout, "<i>Removing directory</i> "
+ "<code>%s</code><br>\n", path);
+#ifdef XP_UNIX
+ rmdir(path);
+#else /* XP_WIN32 */
+ RemoveDirectory(path);
+#endif /* XP_WIN32 */
+ } else {
+ fprintf(stdout, "<i>Removing file</i> <code>%s</code><br>\n", path);
+ unlink(path);
+ }
+ return;
+}
+
+int str_flag_to_int(char *str_flag)
+{
+ if (!str_flag)
+ return -1;
+ if (!strcmp(str_flag, "1"))
+ return 1;
+ return 0;
+}
+
+/*
+ * get_ip_and_mask - function to take something that may be an IP Address
+ * and netmaks, and validate it. It takes two possible
+ *
+ * Parmaters: char *candidate
+ *
+ * Returns NULL if it isn't a valid IP address and mask. It returns
+ * the IP address and mask in the form "iii.iii.iii.iii mmm.mmm.mmm.mmm"
+ * if it is valid. This is in a string dynamicly allocated in this
+ * function.
+ *
+ * Processing: the candidate is assumed to be in one of
+ * these two formats:
+ *
+ * 1. "iii.iii.iii.iii" (returns: "iii.iii.iii.iii 255.255.255.255")
+ * 2. "iii.iii.iii.iii mmm.mmm.mmm.mmm"
+ * 3. "iii.*", "iii.iii.*", or "iii.iii.iii.*"
+ *
+ * The rules are:
+ * I. If it has a space in it, it is assumed to be the delimiter in
+ * format 2.
+ * II. If it has a "*" in it, it's assumed to be format 3.
+ * III. If it's in format 3, the net mask returned is:
+ * 255.0.0.0, 255.255.0.0, or 255.255.255.0 respectivly,
+ * and parts of the address right of the * is replaced with 0s.
+ * IV. We use inet_addr on the pieces to validate them.
+ *
+ *
+ */
+
+char *get_ip_and_mask(char *candidate)
+{
+ char work[BIG_LINE];
+
+ char *p;
+ char *result = NULL;
+ int len;
+ int dots = 0;
+ int i;
+
+ if (candidate && strlen(candidate) < (unsigned) BIG_LINE) {
+
+ if ((p = strchr(candidate, ' '))) {
+ len = p-candidate+1;
+ memcpy(work, candidate, len);
+ work[len] = '\0';
+ if (inet_addr(work) != -1) {
+ len = strlen(candidate)-strlen(p)-1;
+ if (len > 0) {
+ memcpy(work, p+1, len);
+ work[len] = '\0';
+ if (inet_addr(work) != -1) {
+ result = strdup(candidate);
+ }
+ }
+ }
+ }
+ else if ((p = strchr(candidate, '*')) &&
+ (p-candidate > 1 ) &&
+ (*(p-1) == '.') ) {
+ memset(work, 0, BIG_LINE);
+ for (i=0; candidate[i]!='*'; ++i) {
+ if (candidate[i+1] != '*')
+ work[i] = candidate[i];
+ if (candidate[i] == '.')
+ ++dots;
+ }
+ if (dots == 1 || dots == 2 || dots == 3) {
+ for (i=0; i<4-dots; ++i) {
+ strcat(work, ".0");
+ }
+ if (inet_addr(work) != -1) {
+ strcat(work, " ");
+ p = &work[strlen(work)];
+ for (i=0; i<dots; ++i) {
+ if (i==0)
+ strcat(work, "255");
+ else
+ strcat(work, ".255");
+ }
+ for (i=0; i<4-dots; ++i) {
+ strcat(work, ".0");
+ }
+ if (inet_addr(p) != -1) {
+ result = strdup(work);
+ }
+ }
+ }
+ }
+ else {
+ if (inet_addr(candidate) != -1) {
+ strcpy(work, candidate);
+ strcat(work, " 255.255.255.255");
+ result = strdup(work);
+ }
+ }
+ }
+ else
+ result = NULL;
+
+ return result;
+}
+
+/* do fgets with a filebuffer *, instead of a File *. Can't use util_getline
+ because it complains if the line is too long.
+ It does throw away <CR>s, though.
+ */
+NSAPI_PUBLIC char *system_gets( char *line, int size, filebuffer *fb )
+{
+ int c;
+ int i = 0;
+
+ while ( --size ) {
+ switch ( c = filebuf_getc( fb ) ) {
+ case IO_EOF:
+ line[i] = '\0';
+ return i ? line : NULL;
+ case LF:
+ line[i] = c;
+ line[i+1] = '\0';
+ return line; /* got a line, and it fit! */
+ case IO_ERROR:
+ return NULL;
+ case CR:
+ ++size;
+ break;
+ default:
+ line[i++] = c;
+ break;
+ }
+ }
+ /* if we got here, then we overran the buffer size */
+ line[i] = '\0';
+ return line;
+}
+
+#ifndef WIN32
+
+/* make a zero length file, no matter how long it was before */
+NSAPI_PUBLIC int
+system_zero( SYS_FILE f )
+{
+ ftruncate( PR_FileDesc2NativeHandle( f ), 0 );
+ return 0;
+}
+
+#endif
+
+/***********************************************************************
+** FUNCTION: cookieValue
+** DESCRIPTION:
+** Get the current value of the cookie variable
+** INPUTS: var - the name of the cookie variable
+** val - if non-NULL, set the in-memory copy of the var
+** OUTPUTS: None
+** RETURN: NULL if the var doesn't exist, else the value
+** SIDE EFFECTS:
+** Eats memory
+** RESTRICTIONS:
+** Don't screw around with the returned string, if anything else wants
+** to use it.
+** MEMORY: This is a memory leak, so only use it in CGIs
+** ALGORITHM:
+** If it's never been called, build a memory structure of the
+** cookie variables.
+** Look for the passed variable, and return its value, or NULL
+***********************************************************************/
+
+NSAPI_PUBLIC char *
+cookieValue( char *var, char *val )
+{
+ static char **vars = NULL;
+ static char **vals = NULL;
+ static int numVars = -1;
+ int i;
+
+ if ( numVars == -1 ) { /* first time, init the structure */
+ char *cookie = getenv( "HTTP_COOKIE" );
+
+ if ( cookie && *cookie ) {
+ int len = strlen( cookie );
+ int foundVal = 0;
+
+ cookie = STRDUP( cookie );
+ numVars = 0;
+ vars = (char **)MALLOC( sizeof( char * ) );
+ vals = (char **)MALLOC( sizeof( char * ) );
+ vars[0] = cookie;
+ for ( i = 0 ; i < len ; ++i ) {
+ if ( ( ! foundVal ) && ( cookie[i] == '=' ) ) {
+ vals[numVars++] = cookie + i + 1;
+ cookie[i] = '\0';
+ foundVal = 1;
+ } else if ( ( cookie[i] == ';' ) && ( cookie[i+1] == ' ' ) ) {
+ cookie[i] = '\0';
+ vals = (char **) REALLOC( vals,
+ sizeof( char * ) * ( numVars + 1 ) );
+ vars = (char **) REALLOC( vars,
+ sizeof( char * ) * ( numVars + 1 ) );
+ vars[numVars] = cookie + i + 2;
+ i += 2;
+ foundVal = 0;
+ }
+ }
+ } else { /* no cookie, no vars */
+ numVars = 0;
+ }
+ }
+ for ( i = 0 ; i < numVars ; ++i ) {
+ if ( strcmp( vars[i], var ) == 0 ) {
+ if ( val ) {
+ vals[i] = STRDUP( val );
+ } else {
+ return vals[i];
+ }
+ }
+ }
+ return NULL;
+}
+
+/***********************************************************************
+** FUNCTION: jsEscape
+** DESCRIPTION:
+** Escape the usual suspects, so the parser javascript parser won't eat them
+** INPUTS: src - the string
+** OUTPUTS: NONE
+** RETURN: A malloced string, containing the escaped src
+** SIDE EFFECTS:
+** None, except for more memory being eaten
+** RESTRICTIONS:
+** None
+** MEMORY: One Malloc, you should free this if you care
+***********************************************************************/
+
+NSAPI_PUBLIC char *
+jsEscape( char *src )
+{
+ int needsEscaping = 0;
+ int i;
+ char *dest;
+
+ for ( i = 0 ; src[i] ; ++i ) {
+ if ( src[i] == '\\' || src[i] == '\'' || src[i] == '"' ) {
+ ++needsEscaping;
+ }
+ }
+ dest = (char *)MALLOC( i + needsEscaping + 1 );
+ for ( i = 0 ; *src ; ++src ) {
+ if ( ( *src == '\\' ) || ( *src == '\'' ) || ( *src == '"' ) ) {
+ dest[i++] = '\\'; /* escape */
+ }
+ dest[i++] = *src;
+ }
+ dest[i] = '\0';
+ return dest;
+}
+
+/***********************************************************************
+** FUNCTION: jsPWDialogSrc
+** DESCRIPTION:
+** Put the source to the passwordDialog JavaScript function out.
+** INPUTS: inScript - if true, don't put <SCRIPT> stuff out
+** otherJS - if nonNULL, other javascript to execute
+** OUTPUTS: None
+** RETURN: None
+** SIDE EFFECTS:
+** clogs up stdout
+** RESTRICTIONS:
+** Don't use this outside of a CGI, or before the Content-type:
+** MEMORY: No memory change
+** ALGORITHM:
+** @+@What's really going on?
+***********************************************************************/
+
+NSAPI_PUBLIC void
+jsPWDialogSrc( int inScript, char *otherJS )
+{
+ static int srcSpewed = 0;
+
+ otherJS = otherJS ? otherJS : "";
+
+ if ( ! inScript ) {
+ fprintf( stdout, "<SCRIPT LANGUAGE=\""MOCHA_NAME"\">\n" );
+ }
+ if ( ! srcSpewed ) {
+ srcSpewed = 1;
+ fprintf( stdout, "function passwordDialog( prompt, element ) {\n"
+ " var dlg = window.open( '', 'dialog', 'height=60,width=500' );\n"
+ " dlg.document.write(\n"
+ " '<form name=f1 onSubmit=\"opener.document.'\n"
+ " + element + '.value = goo.value; window.close(); "
+ "%s; return false;\">',\n"
+ " prompt, '<input type=password name=goo></form>' );\n"
+ " dlg.document.f1.goo.focus();\n"
+ " dlg.document.close();\n"
+ "}\n", otherJS );
+ }
+ if ( ! inScript ) {
+ fprintf( stdout, "</SCRIPT>\n" );
+ }
+}
+
+static int adm_initialized=0;
+
+/* Initialize NSPR for all the base functions we use */
+NSAPI_PUBLIC int ADM_Init(void)
+{
+ if(!adm_initialized) {
+ NSPR_INIT("AdminPrograms");
+ adm_initialized=1;
+ }
+ return 0;
+}
+
+
+#ifdef XP_UNIX
+/*
+ * This function will return the SuiteSpot user id and group id used to
+ * recommend that Netscape Servers to run as. Any line starts with '#'
+ * is treated as comment. It looks for SuiteSpotUser/SuiteSpotGroup
+ * name/value pair.
+ *
+ * It returns 0 when success and allocate storage for user and group.
+ * returns -1 when only SuiteSpot user id is found.
+ * returns -2 when only SuiteSpot group id is found.
+ * returns -3 when NO SuiteSpot user and group is found.
+ * returns -4 when fails to open <server_root>/install/ssusers.conf
+ */
+NSAPI_PUBLIC int ADM_GetUXSSid(char *sroot, char **user, char **group)
+{
+ int foundUser, foundGroup;
+ char fn[BIG_LINE];
+ char line[BIG_LINE];
+ FILE *f;
+
+ foundUser = 0;
+ foundGroup = 0;
+ *user = (char *) NULL;
+ *group = (char *) NULL;
+
+ sprintf(fn, "%s/install/ssusers.conf", sroot);
+ if (f = fopen(fn, "r")) {
+ while (fgets(line, sizeof(line), f)) {
+ if (line[0] == '#') {
+ continue;
+ }
+ if (!strncmp(line, "SuiteSpotUser", strlen("SuiteSpotUser"))) {
+ char *ptr1;
+ ptr1 = line + strlen("SuiteSpotUser");
+ while ((*ptr1 == '\t') || (*ptr1 == ' ')) {
+ ptr1++;
+ }
+ if ((strlen(ptr1) > 0) && (*user == (char *) NULL)) {
+ *user = (char *) MALLOC(strlen(ptr1)+1);
+ if (ptr1[strlen(ptr1)-1] == '\n') {
+ ptr1[strlen(ptr1)-1] = '\0';
+ }
+ strcpy(*user, ptr1);
+ }
+ foundUser = 1;
+ continue;
+ }
+ if (!strncmp(line, "SuiteSpotGroup", strlen("SuiteSpotGroup"))) {
+ char *ptr1;
+ ptr1 = line + strlen("SuiteSpotGroup");
+ while ((*ptr1 == '\t') || (*ptr1 == ' ')) {
+ ptr1++;
+ }
+ if ((strlen(ptr1) > 0) && (*group == (char *) NULL)) {
+ *group = (char *) MALLOC(strlen(ptr1)+1);
+ if (ptr1[strlen(ptr1)-1] == '\n') {
+ ptr1[strlen(ptr1)-1] = '\0';
+ }
+ strcpy(*group, ptr1);
+ }
+ foundGroup = 1;
+ continue;
+ }
+ }
+ fclose(f);
+ } else {
+ return(-4);
+ }
+
+ if (foundUser && foundGroup) {
+ return(0);
+ } else if (foundUser) {
+ return(-1);
+ } else if (foundGroup) {
+ return(-2);
+ } else {
+ return(-3);
+ }
+}
+#endif /* XP_UNIX */