]> git.sur5r.net Git - openldap/commitdiff
Initial import of web_ldap written and contributed
authorKurt Zeilenga <kurt@openldap.org>
Mon, 14 Dec 1998 23:10:02 +0000 (23:10 +0000)
committerKurt Zeilenga <kurt@openldap.org>
Mon, 14 Dec 1998 23:10:02 +0000 (23:10 +0000)
by Jens Moller <Jens.Moller@mci.com>.

12 files changed:
contrib/web_ldap/COPYRIGHT [new file with mode: 0644]
contrib/web_ldap/Makefile [new file with mode: 0644]
contrib/web_ldap/README [new file with mode: 0644]
contrib/web_ldap/maint_form.h [new file with mode: 0644]
contrib/web_ldap/process_form.h [new file with mode: 0644]
contrib/web_ldap/util.c [new file with mode: 0644]
contrib/web_ldap/web_ldap.c [new file with mode: 0644]
contrib/web_ldap/web_ldap.cfg [new file with mode: 0644]
contrib/web_ldap/web_ldap.html [new file with mode: 0644]
contrib/web_ldap/web_ldap.log.sample [new file with mode: 0644]
contrib/web_ldap/web_ldap_usage.html [new file with mode: 0644]
contrib/web_ldap/web_ldap_usage.txt [new file with mode: 0644]

diff --git a/contrib/web_ldap/COPYRIGHT b/contrib/web_ldap/COPYRIGHT
new file mode 100644 (file)
index 0000000..29a1eaf
--- /dev/null
@@ -0,0 +1,25 @@
+Copyright 1998, Jens Moller, All rights reserved.
+This software is not subject to any license of the COLOMAR
+Group.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+   software, no matter how awful, even if they arise from flaws in it.
+   
+2. The origin of this software must not be misrepresented, either by
+   explicit claim or by omission.  Since few users ever read sources,
+   credits should appear in the documentation.
+        
+3. Altered versions must be plainly marked as such, and must not be
+   misrepresented as being the original software.  Since few users
+   ever read sources, credits should appear in the documentation.
+              
+4. This notice may not be removed or altered.
+
+Redistribution and use in source and binary forms are permitted
+without restriction or fee of any kind as long as this notice
+is preserved.
+              
diff --git a/contrib/web_ldap/Makefile b/contrib/web_ldap/Makefile
new file mode 100644 (file)
index 0000000..900c133
--- /dev/null
@@ -0,0 +1,28 @@
+#
+# This file used under Irix (SGI) - please modify for your needs
+#
+CC = cc -signed
+
+#For Optimization
+CFLAGS= -O2
+#For debugging
+#CFLAGS= -g
+
+#
+# Create Executables
+#
+web_ldap: web_ldap.o util.o
+       $(CC) -o web_ldap web_ldap.o util.o \
+       libldap.a liblber.a
+
+#
+# Create Objects
+#
+web_ldap.o: web_ldap.c
+       $(CC) -c web_ldap.c
+
+util.o: util.c
+       $(CC) -c util.c
+#
+# all done
+#
diff --git a/contrib/web_ldap/README b/contrib/web_ldap/README
new file mode 100644 (file)
index 0000000..6efe36b
--- /dev/null
@@ -0,0 +1,17 @@
+The web_ldap package contains the following files:
+
+  COPYRIGHT             - Your rights to use this software
+  Makefile              - Build file
+  README                - This file
+  maint_form.h          - HTML form processing
+  process_form.h        - HTML form processing
+  util.c                - HTML form processingg
+  web_ldap.c            - Form/LDAP processing
+  web_ldap.cfg          - configuration File
+  web_ldap.html         - HTML Form
+  web_ldap.log.sample   - Sample Log file
+  web_ldap_usage.txt    - Instructions for use
+  web_ldap_usage.html   - Instructions for use in HTML
+  
+Please reveiw the web_ldap.txt or web_ldap_usage.html 
+file to understand how to utilize this software.
diff --git a/contrib/web_ldap/maint_form.h b/contrib/web_ldap/maint_form.h
new file mode 100644 (file)
index 0000000..525783b
--- /dev/null
@@ -0,0 +1,114 @@
+/* maint_form.h */
+
+#ifndef __MAINT_FORM_H
+#define __MAINT_FORM_H
+
+#define max number of passed fields.
+#define MAX_ENTRIES 400  /* way bigger than needed. */
+
+/* define the maximum length of a single config line */
+#define MAX_LINE_LEN   256
+
+typedef struct {
+    char *name;
+    char *val;
+} entry;
+
+/* prototypes */
+char  *makeword(char *line,
+                char stop);
+
+char  *fmakeword(FILE *f,
+                 char stop,
+                 int *len);
+
+char  x2c(char *what);
+
+void  unescape_url(char *url);
+
+void  plustospace(char *str);
+
+int   strcompare(char* a,
+                 char* b);
+
+int   getvalue(entry* list,
+               char* key,
+               char** value);
+
+int append_to_list(entry* list,
+                   char* key,
+                   char* value);
+
+void  remove_leading_blanks(char* str);
+
+void  remove_trailing_blanks(char* str);
+
+void  pad_with_char(char* buffer,
+                    int length,
+                    char padchar);
+
+char* lower_case_string(char* inputbuf);
+
+char* upper_case_string(char* inputbuf);
+
+void  strip_CR(char* buffer);
+
+void  show_form_data(entry* entries);
+
+void  display_html_text(char* filename);
+
+long unformat_cost(char* cost);
+
+int get_line(FILE* file,
+             char* returned_line);
+
+void print_header(char* title);
+
+void maint_trailer();
+
+void maint_header(char* name);
+
+void maint_update_form(entry* list,
+                       char* maint_filename,
+                       char* DatabaseName);
+
+/*
+int draw_form_fields(char* maint_filename,
+                       CGIDB_REC* cgidb_rec);
+*/
+void maint_remove_form(entry* list,
+                       char* DatabaseName);
+
+void maint_add_form(entry* list,
+                    char* maint_filename,
+                    char* DatabaseName);
+
+/*
+char* get_field_data(CGIDB_REC* cgidb_rec,
+                     char* data,
+                     char* buffer);
+*/
+void maint_dump_db(entry* list,
+                   char* maint_filename,
+                   char* DatabaseName);
+/*
+void display_dump_entry(CGIDB_REC* cgidb_rec,
+                        int cols,
+                        char* item1,
+                        char* item2,
+                        char* item3,
+                        char* item4);
+*/
+void maint_upload_photo(char* MFileName);
+
+void maint_remove_photo(entry* list,
+                        char* MFileName);
+/*
+int copy_data_to_db_field(CGIDB_REC* cgidb_rec,
+                          char* field,
+                          char* fieldmaxlength,
+                          char* data);
+*/
+#endif
+
+/* end file 'maint_form.h' */
diff --git a/contrib/web_ldap/process_form.h b/contrib/web_ldap/process_form.h
new file mode 100644 (file)
index 0000000..eeaabcc
--- /dev/null
@@ -0,0 +1,32 @@
+/* process_form.h */
+
+#ifndef __PROCESS_FORM_H
+#define __PROCESS_FORM_H
+
+#define MAX_ENTRIES 10000
+
+typedef struct {
+    char *name;
+    char *val;
+} entry;
+
+char  *makeword(char *line, char stop);
+char  *fmakeword(FILE *f, char stop, int *len);
+char  x2c(char *what);
+void  unescape_url(char *url);
+void  plustospace(char *str);
+
+int   strcompare(char* a, char* b);
+int   getvalue(entry* list, char* key, char** value);
+void  remove_leading_blanks(char* str);
+void  remove_trailing_blanks(char* str);
+void  pad_with_char(char* buffer, int length, char padchar);
+char* lower_case_string(char* inputbuf);
+char* upper_case_string(char* inputbuf);
+void  strip_CR(char* buffer);
+void  show_form_data(entry* entries);
+void  display_html_text(char* filename);
+long unformat_cost(char* cost);
+#endif
+
+/* end file 'process_form.h' */
diff --git a/contrib/web_ldap/util.c b/contrib/web_ldap/util.c
new file mode 100644 (file)
index 0000000..f120efb
--- /dev/null
@@ -0,0 +1,540 @@
+/* util.c 
+ *
+ * This code module originates from NCSA 
+ * See: http://hoohoo.ncsa.uiuc.edu/cgi/
+ * and: ftp://ftp.ncsa.uiuc.edu/Web/httpd/Unix/ncsa_httpd/cgi/cgi-src/
+ * 
+ * Most of the above listed programs were combined into a single
+ * file (this one) - everything here is public domain and free for
+ * use in any form..
+ *
+ * Corrections made for SGI systems (Irix) and
+ * time/date functions added - R. Scott Guthrie 
+ */ 
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "process_form.h"
+
+/*--------------*/
+/*  strcompare  */
+/*--------------*/
+/* This fixes the SGI strcmp function which aborts when passed
+ * a NULL in place of a NULL TERMINATED STRING.
+ * (The code that depended on it was ported from SUN which considered
+ * a NULL to be a NULL terminated string. The standard says strcmp
+ * action is undefined when passed a NULL. SGI abends.)
+ */
+int strcompare(char* a, char* b)
+{
+  if(a && b)
+    return(strcmp(a, b));  /* neither char* is NULL */
+  return(1);    /* different if either (or both) char* are NULL */
+}
+
+
+/*------------*/
+/*  getvalue  */
+/*------------*/
+/* put a pointer to the value in 'value' for the key specified.
+ */
+int getvalue(entry* list, char* key, char** value)
+{
+  int index = 0;
+
+  *value = NULL;    /* initialize value to NULL */
+
+  while(list[index].name)
+  {
+    if(strcmp(list[index].name, key) == 0)
+    {
+      *value = list[index].val;
+      return(1);  /* success */
+    }
+    index++;
+  }
+  return(0);  /* no key value found in list */
+}
+
+
+/*------------------*/
+/*  append_to_list  */
+/*------------------*/
+/* Append name/value pair to end of list */
+int append_to_list(entry* list, char* key, char* value)
+{
+  int index = 0;
+  char* newname;
+  char* newvalue;
+
+  /* go to end of list */
+  while(list[index].name)
+    index++;
+
+  if(index > MAX_ENTRIES)
+    return(0); /* out of room */
+
+  newname = (char *) malloc(sizeof(char) * (strlen(key) + 1));
+  strcpy(newname, key);
+  list[index].name = newname;
+
+  newvalue = (char *) malloc(sizeof(char) * (strlen(value) + 1));
+  strcpy(newvalue, value);
+  list[index].val = newvalue;
+
+  /* put new nulls at end. */
+  index++;
+  list[index].name = NULL;
+  list[index].val = NULL;
+  return(1);  /* success */
+}
+
+/*----------------------*/
+/*  remove_table_entry  */
+/*----------------------*/
+/* replaces table entry 'name' name field with '~' */
+int remove_table_entry(entry* list, char* name)
+{
+  int index = 0;
+
+  /* search table for matching name entry */
+  while(1)  /* FOREVER  - breaks out with return */
+  {
+    if(list[index].name == NULL)
+      return(0);   /* not in list */
+
+    if(strcmp(list[index].name, name) == 0)
+    {
+      /* found match.  remove name */
+      free(list[index].name);
+
+      /* allocate space for deleted name */
+      if((list[index].name = (char*)malloc(2 * sizeof(char))) == NULL)
+        return(0);  /* malloc error */
+      else
+        strcpy(list[index].name, "~");    /* DELETE INDICATOR */
+      return(1);  /* replacement successful */
+    }
+    index++;  /* try next name */
+  }
+  return(0);  /* cannot get here */
+}  /* remove_table_entry */
+
+
+/*------------*/
+/*  makeword  */
+/*------------*/
+char* makeword(char *line, char stop) 
+{
+  int x = 0,y;
+  char *word = (char *) malloc(sizeof(char) * (strlen(line) + 1));
+
+  for(x=0;((line[x]) && (line[x] != stop));x++)
+    word[x] = line[x];
+
+  word[x] = '\0';
+  if(line[x]) ++x;
+  y=0;
+
+  while(line[y++] = line[x++]);
+  return word;
+}
+
+
+/*-------------*/
+/*  fmakeword  */
+/*-------------*/
+char* fmakeword(FILE *f, char stop, int *cl)
+{
+  int wsize;
+  char *word;
+  int ll;
+
+  wsize = 102400;
+  ll=0;
+  word = (char *) malloc(sizeof(char) * (wsize + 1));
+
+  while(1)
+  {
+    word[ll] = (char)fgetc(f);
+    if(ll==wsize)
+    {
+      word[ll+1] = '\0';
+      wsize+=102400;
+      word = (char *)realloc(word,sizeof(char)*(wsize+1));
+    }
+    --(*cl);
+
+    if((word[ll] == stop) || (feof(f)) || (!(*cl)))
+    {
+      if(word[ll] != stop) ll++;
+      word[ll] = '\0';
+      return word;
+    }
+    ++ll;
+  }
+  return(NULL);
+}
+
+
+/*-------*/
+/*  x2c  */
+/*-------*/
+char x2c(char *what) 
+{
+  register char digit;
+
+  digit = (what[0] >= 'A' ? ((what[0] & 0xdf) - 'A')+10 : (what[0] - '0'));
+  digit *= 16;
+  digit += (what[1] >= 'A' ? ((what[1] & 0xdf) - 'A')+10 : (what[1] - '0'));
+  return(digit);
+}
+
+/*----------------*/
+/*  unescape_url  */
+/*----------------*/
+void unescape_url(char *url)
+{
+  register int x,y;
+
+  for(x=0,y=0;url[y];++x,++y)
+  {
+    if((url[x] = url[y]) == '%')
+    {
+      url[x] = x2c(&url[y+1]);
+      y+=2;
+    }
+  }
+  url[x] = '\0';
+}
+
+
+/*---------------*/
+/*  plustospace  */
+/*---------------*/
+void plustospace(char *str) 
+{
+  register int x;
+
+  for(x=0;str[x];x++) if(str[x] == '+') str[x] = ' ';
+}
+
+
+/*-------------------------*/
+/*  remove_leading_blanks  */
+/*-------------------------*/
+void remove_leading_blanks(char* str)
+{
+  int i;
+  while(str[0] == ' ')
+  {
+    i = 1;
+    do
+    {
+      str[i-1] = str[i];
+    } while(str[i++]);
+  }
+} /* end 'remove_leading_blanks()' */
+
+
+/*-------------------------*/
+/* remove_trailing_blanks  */
+/*-------------------------*/
+void remove_trailing_blanks(char* str)
+{
+  while(str[strlen(str) - 1] == ' ')
+    str[strlen(str) - 1] = '\0';
+} /* end 'remove_trailing_blanks()' */
+
+
+/*-----------------*/
+/*  pad_with_char  */
+/*-----------------*/
+void pad_with_char(char* buffer, int length, char padchar)
+{
+  /* if the 'buffer' is >= then 'length', return.
+   * Pad the 'buffer' with 'padchar' until = 'length'
+   */
+  int pos;
+  while((pos = strlen(buffer)) < length)
+  {
+    buffer[pos] = padchar;
+    buffer[pos+1] = '\0';
+  }
+} /* end pad_with_char */
+
+
+/*---------------------*/
+/*  lower_case_string  */
+/*---------------------*/
+char* lower_case_string(char* inputbuf)
+{
+  int pos = 0;
+
+  while(inputbuf[pos])
+  {
+    inputbuf[pos] = (char)tolower(inputbuf[pos]);
+    pos++;
+  }
+  return(inputbuf);
+}  /* lower_case_string */
+
+
+/*---------------------*/
+/*  upper_case_string  */
+/*---------------------*/
+char* upper_case_string(char* inputbuf)
+{
+  int pos = 0;
+
+  while(inputbuf[pos])
+  {
+    inputbuf[pos] = (char)toupper(inputbuf[pos]);
+    pos++;
+  }
+  return(inputbuf);
+}  /* upper_case_string */
+
+
+/*------------*/
+/*  strip_CR  */
+/*------------*/
+void strip_CR(char* buffer)
+{
+  char* bufferptr;
+  char* newptr;
+
+  bufferptr = buffer;
+  newptr = buffer;
+
+  while(*bufferptr)
+  {
+    if(*bufferptr != '\r')
+    {
+      *newptr = *bufferptr;
+      newptr++;
+    }
+    bufferptr++; 
+  }
+  *newptr = '\0';
+
+  return;
+}
+
+/*------------------*/
+/*  show_form_data  */
+/*------------------*/
+/* THIS ROUTINE IS USED FOR DEBUGGING and will not be called in production */
+void show_form_data(entry* entries)
+{
+  int x = 0;
+
+  printf("<HR><H1>Form Data</H1>");
+  printf("The following Name Value pairs currently exist:<p>%c",10);
+  printf("<ul><pre>%c",10);
+
+  while(entries[x].name)
+  {
+    printf("<li> <code>%s = [%s]</code>%c",entries[x].name,
+            entries[x].val,10);
+    x++;
+  }
+  printf("</pre></ul>%c",10);
+}
+
+/*------------------------*/
+/*  maint_show_form_data  */
+/*------------------------*/
+/* THIS ROUTINE IS USED FOR DEBUGGING and will not be called in production */
+void maint_show_form_data(entry* entries)
+{
+  int x = 0;
+
+  printf("Content-type: text/html\n\n");
+  printf("<HR><H1>Form Data</H1>");
+  printf("The following Name Value pairs currently exist:<p>%c",10);
+  printf("<ul><pre>%c",10);
+
+  while(entries[x].name)
+  {
+    printf("<li> <code>%s = [%s]</code>%c",entries[x].name,
+            entries[x].val,10);
+    x++;
+  }
+  printf("</pre></ul>%c",10);
+}
+
+/*---------------------*/
+/*  display_html_text  */
+/*---------------------*/
+/* display the text found in the indicated file */
+void display_html_text(char* filename)
+{
+  FILE *fp;
+  char buffer[256];
+
+  if((fp = fopen(filename, "r")) == NULL)
+  {
+    printf("%s%s%s",
+      "<p><b>(OOPS... We are unable to open file ",
+      filename,
+      " for reading)</b><p>\n");
+  }
+  while(fgets(buffer, 256, fp) != NULL)
+  {
+    if(buffer[strlen(buffer) - 1] == '\n')
+      buffer[strlen(buffer) - 1] = '\0';
+    printf("%s\n", buffer);
+  }
+  fclose(fp);
+  return ;
+}  /* display_html_text */
+
+
+/*-----------------*/
+/*  unformat_cost  */
+/*-----------------*/
+/* this routine converts a string value and
+ * converts it to an integer.
+ */
+long unformat_cost(char* cost)
+{
+  char buf[100];
+  int buf_siz = 0;
+
+  char* spos = cost;
+  char* dpos = buf;
+
+  /* Make sure a string was passed */
+  if(!spos)
+    return(0L);
+
+  /* while in the string */
+  while(*spos)
+  {
+    if(*spos == '.')
+      break;
+    if(isdigit(*spos))
+      *dpos++ = *spos;
+    spos++;
+    if(buf_siz++ == 98) /* make sure we don't overrun buf */
+      break;
+  }
+  *spos = '\n';
+  return(atol(buf));
+}
+
+/*---------------*/
+/*  digits_only  */
+/*---------------*/
+int digits_only(char* str)
+{
+  char* pos;
+
+  pos = str;
+  while(*pos)
+  {
+    if(!isdigit(*pos))
+      return(0);    /* non-digit found */
+    pos++;
+  } 
+  return(1);
+}
+
+/*-------------*/
+/*  util_year  */
+/*-------------*/
+/* return current year -> 0 thru 99 */
+int util_year()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_year;
+   return(ret_val);
+}
+
+/*--------------*/
+/*  util_month  */
+/*--------------*/
+/* return Month of current year -> 1 thru 12 */
+int util_month()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_mon;
+   return(ret_val + 1);
+}
+
+/*------------*/
+/*  util_day  */
+/*------------*/
+/* return day of Month -> 1 thru 31 */
+int util_day()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_mday;
+   return(ret_val);
+}
+
+/*-------------*/
+/*  util_hour  */
+/*-------------*/
+/* return hour of day -> 0 thru 23 */
+int util_hour()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_hour;
+   return(ret_val);
+}
+
+/*---------------*/
+/*  util_minute  */
+/*---------------*/
+/* return minute of day -> 0 thru 59 */
+int util_minute()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_min;
+   return(ret_val);
+}
+
+/*---------------*/
+/*  util_second  */
+/*---------------*/
+/* return second of day -> 0 thru 59 */
+int util_second()
+{
+   time_t  t;
+   struct  tm *tptr;
+   int     ret_val;
+   time(&t);
+   tptr    = localtime(&t);
+   ret_val = tptr->tm_sec;
+   return(ret_val);
+}
+
+/* end file 'util.c' */
diff --git a/contrib/web_ldap/web_ldap.c b/contrib/web_ldap/web_ldap.c
new file mode 100644 (file)
index 0000000..f08cd6b
--- /dev/null
@@ -0,0 +1,612 @@
+/* web_ldap.c
+ * Form Processing Web application that returns html based
+ * LDAP data with definitions from a configuration file.
+ *
+ * Jens Moller - Dec 11, 1998
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <time.h>
+#include <lber.h>
+#include <ldap.h>
+#include <ldif.h> 
+#include "maint_form.h" /* for HTML Form manipulations */
+
+/* default values */
+#define LDAP_PORT 389
+#define SERVER "ldap.bigfoot.com" 
+#define CONFIG "web_ldap.cfg"
+
+#define MAX_ATTRIB 100
+#define MAX_CHARS  256
+#define version "v 1.1"
+
+entry entries[MAX_ENTRIES];
+
+typedef struct {
+   char servername[MAX_CHARS];
+   char query[MAX_CHARS];
+   char searchbase[MAX_CHARS];
+   char htmlfile[MAX_CHARS];
+   int  ldap_port_num;
+   int  num_of_attrib;
+   int  debug; /* if zero, no debug text displayed */
+} LDAP_INFO;
+
+typedef struct {
+   char  title[40];
+} ATTRIB_TITLE; 
+
+/* function Prototypes */
+void process_cfg(char *config, 
+                LDAP_INFO *ldap_data,
+                char *attribute_array[],
+                ATTRIB_TITLE *disp_attrib);
+
+int  strscn(char *istring, 
+           char *tstring);
+
+void upcase_string(char *array, 
+                  char *uparray);
+
+int  find_comma(char *array);
+
+int find_colon(char *array);
+
+void squeeze_blanks(char *array);
+
+/* Pass in nothing and use the default config file, or
+ * pass in the config file to use */
+
+main(int argc, char ** argv) {
+   LDAP         *ld;
+   LDAPMessage  *res, *e;
+   int          i, j, cl, x, how_many;
+   char         *a, *dn, *value;
+   BerElement   *ptr;
+   char         **vals;
+   char         *read_attrs[MAX_ATTRIB]; /* up to MAX_ATTRIB attribs returned */
+   struct       berval **bvals;
+   char         attrs_name[MAX_CHARS];
+   char         config_file[MAX_CHARS];
+   char         temp[MAX_CHARS];
+   char         passed_in[MAX_CHARS];
+   LDAP_INFO    ldap_data;
+   ATTRIB_TITLE attribute[MAX_ATTRIB];
+   time_t       now;
+   FILE         *logfp;
+   
+   
+   /* html initialization */
+   printf("Content-type: text/html\n\n");
+   printf("<html>\n<head>\n<title>Web Ldap Results</title>\n");
+   printf("</head>\n");
+   printf("<body text=\"#000000\" bgcolor=\"#FFFFFF\">\n");
+   printf("<h2>Web LDAP Results</h2>\n");
+   
+   /* initialize ldap_data structure */
+   memset(ldap_data.servername,0,MAX_CHARS);
+   memset(ldap_data.query,0,MAX_CHARS);
+   memset(ldap_data.searchbase,0,MAX_CHARS);
+   memset(ldap_data.htmlfile,0,MAX_CHARS);
+   ldap_data.ldap_port_num  = 0;
+   ldap_data.num_of_attrib  = 0;
+   ldap_data.debug          = 0;
+   
+   memset(passed_in,0,MAX_CHARS);
+
+   if (argc > 1) { /* interactive mode */
+      
+      /* To use in this fashion when run from a Unix command line:
+       * 
+       * > web_ldap DEF "cn=j*moller"
+       * > web_ldap DEF cn=jens moller
+       *
+       * NOTE: The quotes are required if a special
+       * character is a part of the LDAP request such
+       * as the asterix (*) in the above example.
+       */
+      
+      /* Parameters passed in are
+       * 
+       * argv[0] = Program Name     (argc =  1)
+       * argv[1] = Config File Name (argc =  2)
+       * argv[2] = Ldap Request     (argc => 3)
+       */
+      
+      /* do we use a different config file ? */
+      strcpy(config_file, CONFIG);
+   
+      if (argc == 2){
+        if ((strcmp(argv[1],"DEF")) == 0) {
+           strcpy(config_file, CONFIG);
+        }
+        else {
+           strcpy(config_file, argv[1]);
+        }
+      }
+   
+      /* is there an LDAP request?   
+       * if so, it may take up to 3 argv[x] values */
+      
+      if (argc >= 3) {
+        if (argc == 3) {
+           strcpy(temp, argv[2]);
+        }
+        
+        if (argc == 4) {
+           strcpy(temp, argv[2]);
+           strcat(temp, " ");
+           strcat(temp, argv[3]);
+        }
+        
+        if (argc == 5) {
+           strcpy(temp, argv[2]);
+           strcat(temp, " ");
+           strcat(temp, argv[3]);
+           strcat(temp, " ");
+           strcat(temp, argv[4]);
+        }
+        
+        j = 0;
+        for (i=0; i<strlen(temp);i++) {
+           if ((temp[i] != '"') &&
+               (temp[i] != '\\')){
+              passed_in[j] = temp[i];
+              j++;
+           }
+        }
+      }
+   }
+   else { /* Non Interactive Mode - read from a form */
+      if (strcompare(getenv("REQUEST_METHOD"),"POST"))
+       {
+          printf("<p>++ Error - This script should be referenced with a METHOD of POST.\n");
+          exit(1);
+       }
+      if (strcompare(getenv("CONTENT_TYPE"),"application/x-www-form-urlencoded"))
+       {
+          printf("<p>++ Error - This script can only be used to decode form results. \n");
+          exit(1);
+       }
+      cl = atoi(getenv("CONTENT_LENGTH"));
+      
+      for(x=0; cl && (!feof(stdin));x++)
+       {
+          entries[x].val = fmakeword(stdin,'&',&cl);
+          plustospace(entries[x].val);
+          unescape_url(entries[x].val);
+          entries[x].name = makeword(entries[x].val,'=');
+          how_many = x; /* keep track of how many we got */
+          
+#ifdef DEBUG_TEXT
+          printf("entries[%d].name=%s - ",x,entries[x].name);
+          printf("entries[%d].val =%s<br>\n",x,entries[x].val);
+#endif
+       }
+      
+      entries[x].name = NULL;    /* entry after last valid one */
+      entries[x].val = NULL;     /* is set to NULL */
+      
+      if(!getvalue(entries, "FORM", &value))
+       {
+          printf("%s%s%s", "This script expected a 'FORM' value returned ",
+                 "and did not get one.  Make sure the HTML used for this ",
+                 "script is correct.");
+          exit(1);
+       } 
+      
+      /* Looking for:
+       * LDAP_REQUEST - actual LDAP request, ie 'cn=j*moller'
+       * CONFIG       = Configuration file
+       */
+
+      strcpy(config_file, CONFIG);
+      
+      if(getvalue(entries, "LDAP_REQUEST", &value)) {
+               strcpy(passed_in,value);
+      }
+      
+      if(getvalue(entries, "CONFIG", &value)) {
+        if ((strcmp("DEF",value)) == 0) {
+           strcpy(config_file, CONFIG);
+        }
+        else {
+           strcpy(config_file, value);
+        }
+      }
+      
+   }
+   
+   /* zero out the attribute pointers/data area */
+   for (i = 0; i < MAX_ATTRIB; i++) {
+      read_attrs[i] = NULL;
+      memset(attribute[i].title,0,40);
+   } 
+   
+   /* read in the config file */
+   process_cfg(config_file, &ldap_data, read_attrs, attribute);
+   
+   if (passed_in[0] != 0) {
+      strcpy(ldap_data.query,passed_in);
+   }
+   
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","w")) == 0) {
+        printf("<font color=red size=5>\n");
+        printf("<p>Unable to open requested log file: web_ldap.log<p>\n");
+        printf("</font>\n");
+      }
+      else { 
+        time(&now);
+        sprintf(temp,"==> web_ldap request made at: %s\n",ctime(&now));
+        fputs(temp,logfp);
+        if (argc > 1) {
+           sprintf(temp," Interactive Unix Command Line Request:\n\n");
+        }
+        else {
+           sprintf(temp," Browser/Form Request:\n\n");
+        }
+        fputs(temp,logfp);
+        sprintf(temp," Server Name: %s\n", ldap_data.servername);
+        fputs(temp,logfp);
+        sprintf(temp," Query: %s\n", ldap_data.query);
+        fputs(temp,logfp);
+        sprintf(temp," Passed In: %s\n", passed_in);
+        fputs(temp,logfp);
+        sprintf(temp," Searchbase: %s\n",ldap_data.searchbase);
+        fputs(temp,logfp);
+        if (ldap_data.htmlfile[0] != 0) {
+           sprintf(temp," HTML File: %s\n",ldap_data.htmlfile);
+        }
+        else {
+           sprintf(temp," HTML File: Non Provided - Use Default Processing\n");
+        }
+        fputs(temp,logfp);
+        sprintf(temp," LDAP Port: %d\n",ldap_data.ldap_port_num);
+        fputs(temp,logfp);
+        sprintf(temp," Number of Attributes: %d\n",ldap_data.num_of_attrib);
+        fputs(temp,logfp);
+        if (ldap_data.num_of_attrib > 0) {
+           for (i = 0; i < ldap_data.num_of_attrib; i++) {
+              sprintf(temp," - %s\n",read_attrs[i]);
+              fputs(temp,logfp);
+           }
+        }
+        
+        sprintf(temp,"\n==< Process Arguments: %d >==\n\n argv[0]: %s\n",
+                argc, argv[0]);
+        fputs(temp,logfp);
+        if (argc >= 2) {
+          sprintf(temp," argv[1]: %s\n",argv[1]);
+           fputs(temp,logfp);
+        }
+        if (argc >= 3) {
+           sprintf(temp," argv[2]: %s\n",argv[2]);
+           fputs(temp,logfp);
+        }
+        if (argc >= 4) {
+           sprintf(temp," argv[3]: %s\n",argv[3]);
+           fputs(temp,logfp);
+        }
+        if (argc >= 5) {
+           sprintf(temp," argv[4]: %s\n",argv[4]);
+           fputs(temp,logfp);
+        }
+        fflush(logfp);
+        fclose(logfp);
+      }
+   }
+   
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","a")) == 0) {
+      }
+      else {
+        time(&now);
+        sprintf(temp,"\n==< Results >==\n\n");
+        fputs(temp,logfp);
+        sprintf(temp,"** performing ldap_open at %s\n", ctime(&now));
+        fputs(temp,logfp);
+        fflush(logfp);
+        fclose(logfp);
+      }
+   }
+   if ( (ld = ldap_open(ldap_data.servername, ldap_data.ldap_port_num) ) == NULL)
+     {
+       printf("<font color=red><b>ldap_open error</b></font>\n");
+       if (ldap_data.debug != 0) {
+          if ((logfp = fopen("web_ldap.log","a")) == 0) {
+          }
+          else {
+             sprintf(temp,"++ ldap_open error\n");
+             fputs(temp,logfp);
+             fflush(logfp);
+             fclose(logfp);
+          }
+       }
+       printf("</body>\n</html>\n");
+       exit(1);
+     }
+   
+   /*authenticate as nobody */
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","a")) == 0) {
+      }
+      else {
+        time(&now);
+        sprintf(temp,"** performing ldap_bind_s at %s\n",ctime(&now));
+        fputs(temp,logfp);
+        fflush(logfp);
+        fclose(logfp);
+      }   
+   }   
+   if(ldap_bind_s(ld, "", "", LDAP_AUTH_SIMPLE) != 0)
+     {
+       printf("<font color=red><b>");
+       ldap_perror (ld, "ldap_simple_bind_s");
+       printf("</b></font>\n");
+
+       if (ldap_data.debug != 0) {
+          if ((logfp = fopen("web_ldap.log","a")) == 0) {
+          }
+          else {
+             sprintf(temp,"++ ldap_bind_s error\n");
+             fputs(temp,logfp);
+             fflush(logfp);
+             fclose(logfp);
+          }
+       }
+       printf("</body>\n</html>\n");
+       exit(1);
+     }
+   
+   printf("<b>Directory Lookup Results</b>\n<pre>\n");
+   printf("<hr><p>\n<pre>\n");
+   
+   /* Get data */
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","a")) == 0) {
+      }
+      else {
+        time(&now);
+        sprintf(temp,"** performing ldap_search_s at %s\n",ctime(&now));
+        fputs(temp,logfp);
+        fflush(logfp);
+        fclose(logfp);
+      }
+   }
+   if(ldap_search_s(ld, ldap_data.searchbase, LDAP_SCOPE_SUBTREE,
+                   ldap_data.query, read_attrs, 0, &res)
+      != LDAP_SUCCESS)
+     {
+       ldap_perror(ld, "ldap_search_s");
+     }
+   
+   for (e=ldap_first_entry(ld, res); e != NULL; e=ldap_next_entry(ld, e))
+     {
+       dn = ldap_get_dn(ld, e);
+       
+       if (ldap_data.debug != 0) {     
+          if ((logfp = fopen("web_ldap.log","a")) == 0) {
+          }
+          else {
+             sprintf(temp," dn=%s\n", dn);
+             fputs(temp,logfp);
+             fflush(logfp);
+             fclose(logfp);
+          }
+       }
+       
+       /*print each attribute */
+       for (a = ldap_first_attribute(ld, e, &ptr);
+            a != NULL;
+            a = ldap_next_attribute(ld, e, ptr) )
+         {
+            strcpy(attrs_name, a);
+            /* print attribute name */
+            printf("%s: ", attrs_name);
+            
+            /*print each value */
+            
+            vals = ldap_get_values(ld, e, a);
+            
+            for(i=0; vals[i] != NULL; i++)
+              /* print value of attribute */
+              printf("%s\n", vals[i],strlen(vals[i]));
+          
+            ldap_value_free(vals);
+         } /*end for*/
+       free(a);
+       free(dn);
+       printf("<p>\n");
+     }
+   /*free the search results */
+   ldap_msgfree (res);
+   
+   printf("</pre>\n");
+
+   ldap_unbind(ld);
+   
+   if (ldap_data.debug != 0) {
+      if ((logfp = fopen("web_ldap.log","a")) == 0) {
+      }
+      else {
+        time(&now);
+        sprintf(temp,"\nFinished gathering results at %s\n",ctime(&now));
+        fputs(temp,logfp);
+        sprintf(temp,"==< Done >==\n");
+        fputs(temp,logfp);
+        fflush(logfp);
+        fclose(logfp);
+      }
+   }
+   printf("</body>\n</html>\n");
+}
+   
+/* Process the user passed in configuration file */
+void process_cfg(char *config, 
+                LDAP_INFO *ldap_data,
+                char *attribute_array[],
+                ATTRIB_TITLE *disp_attrib) {
+   
+   char   file_data[1024];
+   char   upfile_data[1024];
+   char   temp[1024];
+   int    lcomma, lcolon, attrib_pos;
+   FILE * fp;
+   
+   strcpy(ldap_data->servername,SERVER);
+   ldap_data->ldap_port_num = LDAP_PORT;
+   strcpy(ldap_data->query,"cn=jens*moller");
+   
+   /* config file needs to be in the cgi-bin directory */
+   if ((fp = fopen(config,"r")) == 0) {
+      return;
+   }
+   
+   attrib_pos = 0;
+   
+   for (;;) { /* read until eof */
+      fgets (file_data,1024,fp);
+      if (feof(fp)) break;
+      if (file_data[0] != '#') { /* skip commented lines */
+        upcase_string(file_data,upfile_data);
+
+        /* get the server specific data */
+        if (strscn(upfile_data,"SERVER:") == 0) {
+           lcolon = find_colon(file_data) + 1;
+           lcomma = find_comma(file_data);
+           if (lcomma > 0) {
+              memset(ldap_data->servername,0,MAX_CHARS);
+              strncpy(ldap_data->servername,&file_data[lcolon],
+                      lcomma - lcolon);
+              ldap_data->ldap_port_num = atoi(&file_data[lcomma + 1]);
+           }
+           else {
+              strcpy(ldap_data->servername,&file_data[lcolon]);
+           }
+           squeeze_blanks(ldap_data->servername);
+        }
+        else if (strscn(upfile_data,"SEARCHBASE:") == 0) {
+           lcolon = find_colon(file_data) + 1;
+           strcpy(ldap_data->searchbase,&file_data[lcolon]);
+           squeeze_blanks(ldap_data->searchbase);
+        }
+        else if (strscn(upfile_data,"HTMLFILE:") == 0) {
+           lcolon = find_colon(file_data) + 1;
+           strcpy(ldap_data->htmlfile,&file_data[lcolon]);
+        }
+        else if (strscn(upfile_data,"DEBUG:") == 0) {
+           lcolon = find_colon(file_data) + 1;
+           ldap_data->debug = atoi(&file_data[lcolon]);
+        }
+        
+        /* get the attribute list */
+        else if ((file_data[0] != ' ') && (file_data[0] != 0)) {
+           memset(temp,0,1024);
+           /* data appears as a comma delimited list, where:
+            * 
+            * attrib_name (char),display_length (int)
+            *
+            * (default length = 20 if display_length undefined)
+            * 
+            * is how each record is defined */
+           lcomma = find_comma(file_data);
+           if (lcomma < 0) {
+              strcpy(temp,file_data);
+              squeeze_blanks(temp);
+           }
+           else {
+              strncpy(temp,file_data,lcomma);
+              squeeze_blanks(temp);
+           }
+           attribute_array[attrib_pos] = malloc(strlen(temp));
+           strcpy(attribute_array[attrib_pos],temp);
+           attrib_pos++;
+           ldap_data->num_of_attrib = attrib_pos;
+        }
+      }
+   }
+}
+
+/* find character substring matches */
+int strscn(char * istring, 
+          char * tstring) {
+   int  i, status, icmp, len;
+   status = -1;
+   len = (strlen(istring) + 1) - strlen(tstring);
+   if (len < 1) len = 1;
+   for (i=0;i<len ;i++) {
+      icmp = memcmp(&istring[i],tstring,strlen(tstring));
+      if (icmp == 0) {
+        status = i;
+        break;
+      }
+   }
+   return status;
+}
+
+/* convert the array to uparray, where uparray contains upper
+ * case characters */
+void upcase_string(char *array, 
+                  char *uparray) {
+   int  i;
+   for (i=0; i < strlen(array); i++) {
+      uparray[i] = toupper(array[i]);
+      uparray[i + 1] = 0;
+   }
+   return;
+}
+
+/* return the position of the first comma - ',' - from within a string */
+int find_comma(char *array){
+   int  i;
+   for (i = 0; i < strlen(array); i++) {
+      if (array[i] == ',') return(i);
+   }
+   return -1;
+}
+
+/* return the position of the first colon - '.' - from within a string */
+int find_colon(char *array){
+   int  i;
+   for (i = 0; i < strlen(array); i++) {
+      if (array[i] == ':') return(i);
+   }
+   return -1;
+}
+
+/* Remove unneeded blanks from a character array. Don't leave 
+ * any at the end & throw away any newline characters  */
+void squeeze_blanks(char *array){
+   int  i, pos, blank;
+   char temp[1024];
+   memset(temp,0,1024);
+   
+   pos   = 0; /* location within temp array */
+   blank = 0; /* # of blanks written in a row */
+   for (i = 0; i < strlen(array); i++) {
+      if (array[i] != ' ') {
+        temp[pos] = array[i];
+        blank = 0;
+        pos++;
+      }
+      else if ((blank == 0) && 
+              (array[i] == ' ') &&
+              (pos != 0)) {
+        temp[pos] = array[i];
+        blank += 1;
+        pos++;
+      }
+   }
+   strcpy(array,temp);
+   if (array[strlen(array) - 1] <= ' ') 
+     array[strlen(array) - 1] = 0;
+}
diff --git a/contrib/web_ldap/web_ldap.cfg b/contrib/web_ldap/web_ldap.cfg
new file mode 100644 (file)
index 0000000..1679171
--- /dev/null
@@ -0,0 +1,27 @@
+#
+# web_ldap.cfg
+#
+#
+# Servers to access:
+#
+# server:dns_name,port_number - default = ldap.bigfoot.com,389
+server:ldap.bigfoot.com,389
+#
+# searchbase:?? Sample: 'o=Xyz, c=US', default - blank (nothing).
+searchbase:
+#
+# debug: Debug Mode; 0 = off, any other integer = on
+debug:1
+#
+# columns list across based on the order in the
+# attribute list.
+#
+# NOTE: Unknown Attributes will be ignored - so list any
+#       that you want. To find out what attributes a server
+#       has for a given entry, leave the attribute list blank.
+#
+# attribute list - default = all returned of nothing defined
+#
+#cn
+#email
+# done
diff --git a/contrib/web_ldap/web_ldap.html b/contrib/web_ldap/web_ldap.html
new file mode 100644 (file)
index 0000000..a7fb00c
--- /dev/null
@@ -0,0 +1,50 @@
+<html>
+<head>
+<title>Web LDAP Access</title>
+</head>
+<body text="#000000"
+bgcolor="#FFFFCC">
+<h2>Web LDAP Access</h2>
+<!-- Form Action Statement -->
+<form action="/cgi-bin/web_ldap" method="POST">
+<input type=hidden name="FORM" value="300">
+<p>
+Please fill in the LDAP request you desire. You may use
+wildcards (*) in this fashion:
+<ul>
+<b>Common Name Examples</b><p>
+<li>cn=jens moller
+<li>cn=*moller
+<li>cn=j* moller
+<p>
+<b>Surname Examples</b><p>
+<li>sn=moller
+<li>sn=*moller
+</ul>
+<p>
+You may specify a configuration file if you have created a
+new one, otherwise, leave it set to "DEF".
+<hr>
+
+<pre>
+ LDAP Request: <input type="text" size="40" name="LDAP_REQUEST">
+  
+  Config File: <input type="text" size="40" value="DEF" name="CONFIG">
+</pre>
+
+<input type="submit" name="button" value="Generate Results">
+<input type="reset" value="Reset">
+</ul>
+<p>
+</form>
+<hr>
+This is a freeware prototype application that includes the
+source code. Please study it if you need to understand how it
+works. It currenly only does simple LDAP Directory reads, however, 
+an interactive application has to start somewhere. 
+<p>
+Authored by: <a href="mailto:Jens@colomar.com">Jens Moller</a>.
+</body>
+</html>
+
+
diff --git a/contrib/web_ldap/web_ldap.log.sample b/contrib/web_ldap/web_ldap.log.sample
new file mode 100644 (file)
index 0000000..b269c89
--- /dev/null
@@ -0,0 +1,34 @@
+==> web_ldap request made at: Thu Dec 10 12:17:02 1998
+
+ Interactive Unix Command Line Request:
+
+ Server Name: ldap.bigfoot.com
+ Query: cn=jens*moller
+ Passed In: 
+ Searchbase: 
+ LDAP Port: 389
+ Number of Attributes: 0
+
+--- Process Arguments: 2 ----
+
+ argv[0]: web_ldap
+ argv[1]: DEF
+
+==< Results >==
+
+** performing ldap_open at Thu Dec 10 12:17:02 1998
+
+** performing ldap_bind_s at Thu Dec 10 12:17:02 1998
+
+** performing ldap_search_s at Thu Dec 10 12:17:02 1998
+
+ dn=cn="JENS MOLLER",mail=jmoller@con5097.cs.mci.com,c=US,o=con5097.cs.mci.com
+ dn=cn="JENS MOLLER",mail=100321.3153@compuserve.com,c=US,o=compuserve.com
+ dn=cn="jens moller",mail=jens1lund2moller@hotmail.com,c=US,o=hotmail.com
+ dn=cn="Jens Moller",mail=jensklethmoller@hotmail.com,c=US,o=hotmail.com
+ dn=cn="jens moller",mail=jamoller@hotmail.com,c=US,o=hotmail.com
+ dn=cn="Jens Mollerup",mail=jmollerup@aki.ku.dk,c=US,o=aki.ku.dk
+
+Finished gathering results at Thu Dec 10 12:17:02 1998
+
+==< Done >==
diff --git a/contrib/web_ldap/web_ldap_usage.html b/contrib/web_ldap/web_ldap_usage.html
new file mode 100644 (file)
index 0000000..202e9ff
--- /dev/null
@@ -0,0 +1,355 @@
+<html>
+<title>web_ldap_usage</title>
+<body text="#000000"
+bgcolor="#FFFFFF">
+
+<h2>web_ldap V 1.1</h2>
+<i>
+The files provided in the file set for 'web_ldap'
+were developed under the GNU General Public License (GPL). 
+Under the GPL, the source code is freely-distributed and available
+to the general public. There is no warranty on the software,
+and it does not come with support, however, I would appreciate
+it if you emailed me any bug-fixes you create 
+(<a href="mailto:jens@colomar.com">jens@colomar.com</a>).
+<p>
+All code here is generic Ansi C, allowing most Unix compilers
+to generate the required object files and executable images.
+It was tested against an Apache HTTPD server and uses no
+special HTML functionality that does not appear within V 3.x
+versions of Netscapes or Microsofts Web Browsers. The goal was
+to create a starting point example to help people build
+effective interactive HTML based LDAP clients.
+</i>
+<h3>Introduction:</h3>
+
+The 'web_ldap' package is a complete LDAP application that 
+provides a functional Web Server Based client. The intent
+is to give you a working example that you can expand upon
+for your own needs. It does not solve a specific problem
+for you, rather it solves a general problem by giving
+you a functional starting point from where to begin your
+development efforts. It runs under Unix.
+<p>
+The application consists of a number of C programs, header
+files, an HTML file with form entry, a configuration file
+and a sample makefile. You will need the LDAP SDK for your
+specific Unix System (both the UofM libraries and Netscape 
+libraries - which are also free - have been tested).
+<p>
+The tool allows You to specify that actions taken
+be logged to a file. This provides you a method by which
+you can build out larger applications and see what is happening.
+<p>
+The application can be run interactively (without use of
+a Web Browser) but was intended for use as an HTML LDAP Web 
+page application.
+<p>
+One thing to consider when running a program of this nature
+is that there are 2 totally different sets of environments
+involved. The program is written assuming very little in
+the way of file/directory organization. As such it looks for
+files either in the directory it was run from, or where ever
+you have configured your Web Server to look for things.
+<p>
+The C CGI program will attempt to open a default configuration
+file called 'web_ldap.cfg'. If you set the debug mode on
+in the configuration file, it will also attempt to create
+a log file called 'web_ldap.log' in the same directory as
+the 'web_ldap.cfg' files appears in.
+<p>
+The 2 environments are 'Interactive' and 'Web Server'.
+<p>
+When you execute the application from a command line such as:
+<pre>      
+     &gt; web_ldap DEF cn=jens moller
+</pre>
+All actions take place in the same directory that the web_ldap 
+program resides in. Most people would typically build an
+application of this nature in one of their own directorys and
+this would give them Read/Write access to all of the files
+associated with the program. Any file restrictions or capabilities
+that you have will be enabled as part of your session.
+<p>
+This is quite different than when you ask a Web Server to
+execute the program for you. The Web Server is typically
+using the user 'nobody'. This is not you, its a separate
+application user and it may not have access to the same
+files that you have nor the same process capabilities.
+<p>
+When your program executes from a Web Browser, you will
+see something like:
+<pre>
+    http://my.system.com/cgi-bin/web_ldap
+    
+</pre>    
+displayed by the Web Browser as the URL that its executing.
+The Web Server is executing the program on your behalf.
+File protections normally cause initial problems, possibly
+because the Web Browser doesn't own the files or doesn't
+have execute access. For your initial testing, please set these
+files to full access - ie. 'chmod 777 web_ldap*' - You can 
+adjust the file protections once you get everything working.
+If you get errors - start with this simple change.
+
+<h3>Building the application:</h3>
+
+Requires Ansi C (your standard OS compiler or GCC should
+work fine).
+<p>
+The make file contains:
+<pre>
+web_ldap: web_ldap.o
+        $(CC) -o web_ldap web_ldap.o util.o \
+       libldap.a liblber.a
+               
+
+web_ldap.o: web_ldap.c
+        $(CC) -c web_ldap.c
+
+util.o: util.c
+        $(CC) -c util.c
+
+</pre> 
+
+<h3>Configuration:</h3>
+
+Its a very simple tool that allows you to make LDAP requests
+to any existing LDAP Directory Server. By default, it
+attempts to connect to 'ldap.bigfoot.com', which is a
+commercial LDAP server on the Internet - usually available
+from anywhere.
+<p>
+To specify a different LDAP server, you could either modify
+the program to default elsewhere, or you could modify the
+existing 'web_ldap.cfg' file, or create another one with
+a different name. 
+<p><i>
+NOTE: A '#' in the first column of any line
+in the configuration file is considered a comment.
+</i>
+<p>
+The configuration file allows you specify:
+<pre>
+  server:
+</pre>  
+This is the servername. For example:
+<pre>
+  server:ldap.bigfoot.com,389
+</pre>
+connects you up to port 389 on the ldap server 'ldap.bigfoot.com'.
+You can specify one of your own servers here if you desire.
+<p>
+Next you will see:
+<pre>
+  searchbase:
+</pre>  
+This is where within a tree you want to start looking. For
+'ldap.bigfoot.com', you would leave this blank and it will
+look in all the trees. For many companies a specific tree
+structure will be defined, and you will want to specify the
+highest point in the tree structure that defines the area that
+you are interested in. For example, if you have a tree that
+starts at 'c=US', and branches at 'o=ABC, c=US' and
+'o=XYZ, c=US', you could specify:
+<pre>
+  searchbase:c=US
+</pre>
+and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or
+if you only wanted to search against 'o=ABC, c=US',
+you could specify:
+<pre>
+  searchbase:o=ABC, c=US
+</pre>
+If you want to turn on a simple Debug mode, you can specify any number
+other than zero for 'debug:'. For example:
+<pre>
+  debug:1
+</pre>
+turns on the Debug logging mode, and
+<pre>
+  debug:0
+</pre>
+turns it off. Debug logging simply creates a file called
+'web_ldap.log' in the same directory that the web_ldap
+executable is located. It flushes everything after each
+event, so if it gets stuck anywhere, you will be able
+to see it. It also time-stamps most of the results, so you
+can get an idea where things are running faster and/or
+slower for different queries.
+<p>
+The remainder of the configuration file is where you list
+the attributes that you are interested in displaying.
+<p>
+You could list parameters (up to 100) like:
+<pre>
+  cn
+  givenname
+  sn
+</pre>
+and that is all it will return. If you don't specify
+anything, it returns everything it finds. if you
+specify an attribute that the directory has never
+heard of (ie. its not a member of any object class
+anyone has defined), that attribute will simply be 
+ignored. If you misspell an attribute name and wonder
+why it never gets listed in the results - this might be
+why. If you specify an attribute that some users have and
+others don't, only ones with that attribute will list
+a value for it. 
+<p>
+Directory data can be multi-valued. This means that any
+attribute could have multiple values. This application will
+list all the values it finds for any given attribute.
+
+
+<h3?Where to put the files:</h3>
+
+If running this interactively (from a Unix shell prompt),
+all the files can reside in any of your home directories.
+I suggest that you test the application in your home
+directory first.
+<p>
+If running this application from a Web Server, you need
+to find out where the Web Server keeps its cgi applications
+and where it keeps its html applications. This varies
+from operating system to operating system and Web Server
+to Web Server.
+<p>
+Once you have located the cgi-bin (or equivalent) directory,
+put these 2 files there:
+<pre>
+  web_ldap
+  web_ldap.cfg
+</pre>  
+then make sure that these files are accessible to the Web
+Server by executing the Unix shell command:
+<pre>
+  &gt; chmod 777 web_ldap*
+</pre>  
+Now find the HTML source directory. Copy
+<pre>
+  web_ldap.html
+</pre>  
+to this directory. Make sure that this file is accessible to the Web
+Server by executing the Unix shell command:
+<pre>
+  &gt; chmod 777 web_ldap*
+</pre>
+
+<h3>Running the application:</h3>
+
+Test it in your own directory by entering:
+<pre>
+  &gt; web_ldap DEF
+</pre>  
+This should connect to 'ldap.bigfoot.com' and try to find a number
+of entries (it does when I try it). You will notice that it
+outputs results in the form of an HTML file - this is what it
+is supposed to do. If you leave out the 'DEF', you will get the
+error:
+<pre>
+&lt;p&gt;++ Error - This script should be referenced with a METHOD of POST.
+</pre>
+as a part of your result with no LDAP data returned.
+<p>
+Interactively, the program assumes that you will always pass it at least
+the name of the Configuration file ('DEF' tells it to use the default
+configuration file). If there is no configuration file, it still will
+find 'ldap.bigfoot.com'.
+<p>
+Once you have it working there, try the version in the HTML directory.
+To do so, enter your WEB Servers URL, the cgi-bin directory reference
+and then the application name, all separated by slashes. For example,
+if your Web Server URL is 'http://my.server.com', then you will want
+to specify the URL:
+<pre>
+  http://my.server.com/cgi-bin/web_ldap
+</pre>
+NOTE: You can only run cgi scripts out of a directory that the Web Server
+allows. It is unlikely that you can execute Web Server CGI applications 
+from your own directory.
+<p>
+This will provide a simple Web Based form. It will have 2 user entry 
+fields. The first allows you to enter an LDAP request. The second
+allows you to specify a configuration file (it defaults to 'DEF').
+<p>
+Enter a simple LDAP request, such as the ones shown and see if you
+get back a response. You should if connected to 'ldap.bigfoot.com'.
+
+
+<h3>Now that you have it working:</h3>
+
+Feel free to adapt this program to fit your needs. You will need
+to have the 'dn' in order to do updates. It is recovered within
+the program, so you can save it for use once you retrieve it
+(it is listed in the web_ldap.log file of you enable debug mode).
+<p>
+This program does not update anything. The goal was to create a very
+simple and expandable LDAP client and provide the complete source
+code for doing it. To this goal, it is successful. From here
+you should be able to experiment with the interfaces and create
+new functionality to suit your given needs.
+<p>
+This was tested against the UofM V 3.3 LDAP Libraries and the Netscape
+V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and 
+Solaris 2.6 (Sun). I don't have other hardware or OS's to test 
+against here.
+
+
+<h3>Usage Information:</h3>
+
+If you want to find out what attributes are being used, you can enable
+the application to tell you all that it finds. Do this by simply
+not defining any attributes within the configuration file. It will
+list all the attributes it finds. You could create a special configuration
+file specifically for this purpose.
+<p>
+If you are getting fatal errors from your Web Server when you attempt to 
+execute a command, please try the same command using interactive mode. Look
+to see if the HTML being generated makes sense or not. If the HTML
+looks good, run it again interactively and pipe the results to a file, then
+attempt to submit the resulting file as the URL. If it works, it is
+likely that the environment you run is different than the one the Web
+server is using - Unix file protections frequently are a cause of these
+problems. If you can't determine what is different, discuss the problem 
+with your Unix system administrator - is is likely a resource problem.
+If you add code that causes problems, but you still get a result, try the
+application in interactive mode and verify the HTML being generated. Any
+additional HTML code you add may need to to have proper termination syntax
+(tables are very touchy about this), and you may need to further enhance
+your changes to compensate.
+<p>
+When creating new applications, please test your 
+results on both Netscape's Web Browser and Internet
+Explorer. Nothing is more irritating to end users than getting different
+results based on their Web Browser selection.
+<p>
+The Unix Command line will not allow you to pass some characters into
+an application unless you surround the characters or command with quotes.
+Some common examples of executing web_ldap interactively are:
+<pre>
+  &gt; web_ldap DEF "cn=j*moller"
+       
+  &gt; web_ldap DEF cn=jens moller
+</pre>
+The command with the '*' in it requires quotes around it. Also note
+that the application only allows the LDAP command to use up to 3 argv
+values. This is as a limitation of the current parsing within the program 
+of argc/argv parameters. You could alter the program, or simply put 
+quotes around the LDAP request. Enable the debug mode within the 
+configuration file if you feel that the application is losing 
+arguments to see what its operating against. When operated by the Web Server,
+and passing in FORM data - you won't have this limitation, and you don't
+need quotes.
+<p>
+You can pass hidden fields from the Web Form into the web_ldap program.
+An example is shown with the name of 'FORM' having a value of '300'.
+You can create additional hidden fields, named anything you want them
+to be, with any value you want. These can be used to define existing
+options (such as which configuration file to use), or other options
+that your modified web_ldap.c program may want to have passed to it.
+<p>
+<hr>
+Jens Moller - Jens@colomar.com - 
+<a href="http://www.colomar.com">COLOMAR Group</a>
diff --git a/contrib/web_ldap/web_ldap_usage.txt b/contrib/web_ldap/web_ldap_usage.txt
new file mode 100644 (file)
index 0000000..d002a58
--- /dev/null
@@ -0,0 +1,346 @@
+web_ldap V 1.0 
+
+The files provided in the file set for 'web_ldap'
+were developed under the GNU General Public License (GPL). 
+Under the GPL, the source code is freely-distributed and available
+to the general public. There is no warranty on the software,
+and it does not come with support, however, I would appreciate
+it if you emailed me any bug-fixes you create (jens@colomar.com).
+
+All code here is generic Ansi C, allowing most Unix compilers
+to generate the required object files and executable images.
+It was tested against an Apache HTTPD server and uses no
+special HTML functionality that does not appear within V 3.x
+versions of Netscapes or Microsofts Web Browsers. The goal was
+to create a starting point example to help people build
+effective interactive HTML based LDAP clients.
+
+Introduction:
+
+The 'web_ldap' package is a complete LDAP application that 
+provides a functional Web Server Based client. The intent
+is to give you a working example that you can expand upon
+for your own needs. It does not solve a specific problem
+for you, rather it solves a general problem by giving
+you a functional starting point from where to begin your
+development efforts. It runs under Unix.
+
+The application consists of a number of C programs, header
+files, an HTML file with form entry, a configuration file
+and a sample makefile. You will need the LDAP SDK for your
+specific Unix System (both the UofM libraries and Netscape 
+libraries - which are also free - have been tested).
+
+The tool allows You to specify that actions taken
+be logged to a file. This provides you a method by which
+you can build out larger applications and see what is happening.
+
+The application can be run interactively (without use of
+a Web Browser) but was intended for use as an HTML LDAP Web 
+page application.
+
+One thing to consider when running a program of this nature
+is that there are 2 totally different sets of environments
+involved. The program is written assuming very little in
+the way of file/directory organization. As such it looks for
+files either in the directory it was run from, or where ever
+you have configured your Web Server to look for things.
+
+The C CGI program will attempt to open a default configuration
+file called 'web_ldap.cfg'. If you set the debug mode on
+in the configuration file, it will also attempt to create
+a log file called 'web_ldap.log' in the same directory as
+the 'web_ldap.cfg' files appears in.
+
+The 2 environments are 'Interactive' and 'Web Server'.
+
+When you execute the application from a command line such as:
+      
+      > web_ldap DEF cn=jens moller
+
+All actions take place in the same directory that the web_ldap 
+program resides in. Most people would typically build an
+application of this nature in one of their own directorys and
+this would give them Read/Write access to all of the files
+associated with the program. Any file restrictions or capabilities
+that you have will be enabled as part of your session.
+
+This is quite different than when you ask a Web Server to
+execute the program for you. The Web Server is typically
+using the user 'nobody'. This is not you, its a separate
+application user and it may not have access to the same
+files that you have nor the same process capabilities.
+
+When your program executes from a Web Browser, you will
+see something like:
+
+    http://my.system.com/cgi-bin/web_ldap
+    
+displayed by the Web Browser as the URL that its executing.
+The Web Server is executing the program on your behalf.
+File protections normally cause initial problems, possibly
+because the Web Browser doesn't own the files or doesn't
+have execute access. For your initial testing, please set these
+files to full access - ie. 'chmod 777 web_ldap*' - You can 
+adjust the file protections once you get everything working.
+If you get errors - start with this simple change.
+
+
+Building the application:
+
+Requires Ansi C (your standard OS compiler or GCC should
+work fine).
+
+The make file contains:
+
+web_ldap: web_ldap.o
+        $(CC) -o web_ldap web_ldap.o util.o \
+       libldap.a liblber.a
+               
+
+web_ldap.o: web_ldap.c
+        $(CC) -c web_ldap.c
+
+util.o: util.c
+        $(CC) -c util.c
+
+       
+
+Configuration:
+
+Its a very simple tool that allows you to make LDAP requests
+to any existing LDAP Directory Server. By default, it
+attempts to connect to 'ldap.bigfoot.com', which is a
+commercial LDAP server on the Internet - usually available
+from anywhere.
+
+To specify a different LDAP server, you could either modify
+the program to default elsewhere, or you could modify the
+existing 'web_ldap.cfg' file, or create another one with
+a different name. 
+
+NOTE: A '#' in the first column of any line
+in the configuration file is considered a comment.
+
+The configuration file allows you specify:
+
+  server:
+  
+This is the servername. For example:
+
+  server:ldap.bigfoot.com,389
+
+connects you up to port 389 on the ldap server 'ldap.bigfoot.com'.
+You can specify one of your own servers here if you desire.
+
+Next you will see:
+
+  searchbase:
+  
+This is where within a tree you want to start looking. For
+'ldap.bigfoot.com', you would leave this blank and it will
+look in all the trees. For many companies a specific tree
+structure will be defined, and you will want to specify the
+highest point in the tree structure that defines the area that
+you are interested in. For example, if you have a tree that
+starts at 'c=US', and branches at 'o=ABC, c=US' and
+'o=XYZ, c=US', you could specify:
+
+  searchbase:c=US
+
+and search both 'o=ABC, c=US' and 'o=XYZ, c=US', or
+if you only wanted to search against 'o=ABC, c=US',
+you could specify:
+
+  searchbase:o=ABC, c=US
+
+If you want to turn on a simple Debug mode, you can specify any number
+other than zero for 'debug:'. For example:
+
+  debug:1
+  
+turns on the Debug logging mode, and
+
+  debug:0
+
+turns it off. Debug logging simply creates a file called
+'web_ldap.log' in the same directory that the web_ldap
+executable is located. It flushes everything after each
+event, so if it gets stuck anywhere, you will be able
+to see it. It also time-stamps most of the results, so you
+can get an idea where things are running faster and/or
+slower for different queries.
+
+The remainder of the configuration file is where you list
+the attributes that you are interested in displaying.
+
+You could list parameters (up to 100) like:
+
+  cn
+  givenname
+  sn
+  
+and that is all it will return. If you don't specify
+anything, it returns everything it finds. if you
+specify an attribute that the directory has never
+heard of (ie. its not a member of any object class
+anyone has defined), that attribute will simply be 
+ignored. If you misspell an attribute name and wonder
+why it never gets listed in the results - this might be
+why. If you specify an attribute that some users have and
+others don't, only ones with that attribute will list
+a value for it. 
+
+Directory data can be multi-valued. This means that any
+attribute could have multiple values. This application will
+list all the values it finds for any given attribute.
+
+
+Where to put the files:
+
+If running this interactively (from a Unix shell prompt),
+all the files can reside in any of your home directories.
+I suggest that you test the application in your home
+directory first.
+
+If running this application from a Web Server, you need
+to find out where the Web Server keeps its cgi applications
+and where it keeps its html applications. This varies
+from operating system to operating system and Web Server
+to Web Server.
+
+Once you have located the cgi-bin (or equivalent) directory,
+put these 2 files there:
+
+  web_ldap
+  web_ldap.cfg
+  
+then make sure that these files are accessible to the Web
+Server by executing the Unix shell command:
+
+  > chmod 777 web_ldap*
+  
+Now find the HTML source directory. Copy
+
+  web_ldap.html
+  
+to this directory. Make sure that this file is accessible to the Web
+Server by executing the Unix shell command:
+
+  > chmod 777 web_ldap*
+
+
+Running the application:
+
+Test it in your own directory by entering:
+
+  > web_ldap DEF
+  
+This should connect to 'ldap.bigfoot.com' and try to find a number
+of entries (it does when I try it). You will notice that it
+outputs results in the form of an HTML file - this is what it
+is supposed to do. If you leave out the 'DEF', you will get the
+error:
+
+<p>++ Error - This script should be referenced with a METHOD of POST.
+
+as a part of your result with no LDAP data returned.
+
+Interactively, the program assumes that you will always pass it at least
+the name of the Configuration file ('DEF' tells it to use the default
+configuration file). If there is no configuration file, it still will
+find 'ldap.bigfoot.com'.
+
+Once you have it working there, try the version in the HTML directory.
+To do so, enter your WEB Servers URL, the cgi-bin directory reference
+and then the application name, all separated by slashes. For example,
+if your Web Server URL is 'http://my.server.com', then you will want
+to specify the URL:
+
+  http://my.server.com/cgi-bin/web_ldap
+
+NOTE: You can only run cgi scripts out of a directory that the Web Server
+allows. It is unlikely that you can execute Web Server CGI applications 
+from your own directory.
+
+This will provide a simple Web Based form. It will have 2 user entry 
+fields. The first allows you to enter an LDAP request. The second
+allows you to specify a configuration file (it defaults to 'DEF').
+
+Enter a simple LDAP request, such as the ones shown and see if you
+get back a response. You should if connected to 'ldap.bigfoot.com'.
+
+
+Now that you have it working:
+
+Feel free to adapt this program to fit your needs. You will need
+to have the 'dn' in order to do updates. It is recovered within
+the program, so you can save it for use once you retrieve it
+(it is listed in the web_ldap.log file of you enable debug mode).
+
+This program does not update anything. The goal was to create a very
+simple and expandable LDAP client and provide the complete source
+code for doing it. To this goal, it is successful. From here
+you should be able to experiment with the interfaces and create
+new functionality to suit your given needs.
+
+This was tested against the UofM V 3.3 LDAP Libraries and the Netscape
+V 1.x and V 3.x SDK under both Irix 6.2 (Silicon Graphics) and 
+Solaris 2.6 (Sun). I don't have other hardware or OS's to test 
+against here.
+
+
+Usage Information:
+
+If you want to find out what attributes are being used, you can enable
+the application to tell you all that it finds. Do this by simply
+not defining any attributes within the configuration file. It will
+list all the attributes it finds. You could create a special configuration
+file specifically for this purpose.
+
+If you are getting fatal errors from your Web Server when you attempt to 
+execute a command, please try the same command using interactive mode. Look
+to see if the HTML being generated makes sense or not. If the HTML
+looks good, run it again interactively and pipe the results to a file, then
+attempt to submit the resulting file as the URL. If it works, it is
+likely that the environment you run is different than the one the Web
+server is using - Unix file protections frequently are a cause of these
+problems. If you can't determine what is different, discuss the problem 
+with your Unix system administrator - is is likely a resource problem.
+If you add code that causes problems, but you still get a result, try the
+application in interactive mode and verify the HTML being generated. Any
+additional HTML code you add may need to to have proper termination syntax
+(tables are very touchy about this), and you may need to further enhance
+your changes to compensate.
+
+Please test your results on both Netscape's Web Browser and Internet
+Explorer. Nothing is more irritating to end users than getting different
+results based on their Web Browser selection.
+
+The Unix Command line will not allow you to pass some characters into
+an application unless you surround the characters or command with quotes.
+Some common examples of executing web_ldap interactively are:
+
+  > web_ldap DEF "cn=j*moller"
+       
+  > web_ldap DEF cn=jens moller
+
+The command with the '*' in it requires quotes around it. Also note
+that the application only allows the LDAP command to use up to 3 argv
+values. This is as a limitation of the current parsing within the program 
+of argc/argv parameters. You could alter the program, or simply put 
+quotes around the LDAP request. Enable the debug mode within the 
+configuration file if you feel that the application is losing 
+arguments to see what its operating against. When operated by the Web Server,
+and passing in FORM data - you won't have this limitation, and you don't
+need quotes.
+
+You can pass hidden fields from the Web Form into the web_ldap program.
+An example is shown with the name of 'FORM' having a value of '300'.
+You can create additional hidden fields, named anything you want them
+to be, with any value you want. These can be used to define existing
+options (such as which configuration file to use), or other options
+that your modified web_ldap.c program may want to have passed to it.
+
+
+Jens Moller - Jens@colomar.com - COLOMAR Group