#include <stdio.h>
#include <string.h>
#include <dirent.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/param.h>

/* workaround Linux-Solaris	*/
#ifdef NAME_MAX
#define MAXNAMELEN NAME_MAX
#endif

/* CGI Environment Variablen */
#define SERVER_NAME getenv("SERVER_NAME")
#define SERVER_PROTOCOL getenv("SERVER_PROTOCOL")
#define SERVER_PORT getenv("SERVER_PORT")
#define PATH_INFO getenv("PATH_INFO")
#define PATH_TRANSLATED getenv("PATH_TRANSLATED")
#define SCRIPT_NAME getenv("SCRIPT_NAME")
#define REMOTE_HOST getenv("REMOTE_HOST")
#define REMOTE_ADDR getenv("REMOTE_ADDR")
#define CONTENT_TYPE getenv("CONTENT_TYPE")
#define REQUEST_METHOD getenv("REQUEST_METHOD")
#define CONTENT_LENGTH getenv("CONTENT_LENGTH")
#define QUERY_STRING getenv("QUERY_STRING")


#define FILEPATH "/home/wiki/"

void scan_dir(char *Dateiname, char *Suchwort);
int scan_file(char *Dateiname, char *Suchwort);
int u_isalpha(char c);
int u_isalnum(char c);
void nextword(FILE *fp, char *Wort);
void unescape(char *url);
char x2c(char hex[]);
void CGIReadInput(char *Suchwort);

int main(int argc, char *argv[])
  {
  char Suchwort[1000] = "";
  char Dirname[MAXNAMELEN+1];

  strcpy(Dirname,FILEPATH);
  printf("Content-Type: text/html\r\n\r\n");
  printf("<HTML>\n<HEAD>\n<TITLE>Lexikon-Suche</TITLE>\n</HEAD>\n");
  printf("<BODY>\n");
  printf("<H1>Lexikon-Suche</H1>\n");

  CGIReadInput(Suchwort);
  if (Suchwort[0] == '\0')
    {
    printf("<FORM method=POST");
    printf(" action=\"http://localhost/~plate/cgi-bin/suche.cgi\">\n");
    printf("Suchbegriff: <INPUT TYPE=TEXT NAME=\"Suchwort\" SIZE=\"30\">\n");
    printf("<INPUT TYPE=\"SUBMIT\" NAME=\"SUBMIT\" VALUE=\"Suchen\">");
    printf("</FORM>\n");
    printf("</BODY>\n</HTML>\n");
    }
  else
    {
    scan_dir(Dirname,Suchwort);
    }

  printf("</BODY>\n</HTML>\n");
  return 0;
  }


void scan_dir(char *Dirname, char *Suchwort)
  {
  DIR *dir;
  struct dirent *dirzeiger;
  char dateiname[MAXNAMELEN+1] = "";
  char fullpath[MAXNAMELEN+1] = "";
  dir = opendir(Dirname);

  if(dir != NULL)
    {
    printf("<UL>\n");
    while((dirzeiger = readdir(dir)) != NULL)
      {
      strcpy(dateiname,(*dirzeiger).d_name);
      if (dateiname[0] != '.')
        {
        strcpy(fullpath,Dirname);
        strcat(fullpath,dateiname);
        if (scan_file(fullpath,Suchwort))
           printf("<LI>%s\n",dateiname);
        }
      }
    printf("</UL>\n");
    closedir(dir);
    }
  }

int scan_file(char *Dateiname, char *Suchwort)
/* Datei nach dem Wort durchsuchen */
  {
  char Wort[1000];
  FILE *fp;

  fp = fopen(Dateiname,"r");
  if (fp == NULL)
    {
    printf("Kann Datei %s nicht oeffnen\n",Dateiname);
    exit(1);
    }
  do
    {
    nextword(fp,Wort);
    /* Suchwort im Wort enthalten? */
    if (strstr(Wort,Suchwort) != NULL)
      return(1);
    }
  while (Wort[0] != '\0');
  fclose(fp);
  return 0;
  }

int u_isalpha (char c)
/* isalpha mit Umlauten */
  {
  if ( (c=='ä') || (c=='ö') || (c=='ü') ||
       (c=='Ä') || (c=='Ö') || (c=='Ü') ||
       (c=='ß') || (isalpha(c)) ) return 1;
  return 0;
  }

int u_isalnum (char c)
/* isalnum mit Umlauten */
  {
  if ( (c=='ä') || (c=='ö') || (c=='ü') ||
       (c=='Ä') || (c=='Ö') || (c=='Ü') ||
       (c=='ß') || (isalnum(c)) ) return 1;
  return 0;
  }

void nextword(FILE *fp, char *Wort)
/* lies naechstes Wort aus der Datei */
  {
  int c = '\0';

  /* Zeichen bis zum ersten Buchstaben ueberlesen */
  while (!(u_isalpha(c)) && (c != EOF))
    c = fgetc(fp);
  /* ein Wort besteht aus Buchstaben und Zahlen */
  while (u_isalnum(c) && (c != EOF))
    {
    *Wort = c;
    Wort++;
    c = fgetc(fp);
    }
  *Wort = '\0';
  }

char x2c(char hex[])
  {
  /* Hexadezimal zu Character Umwandlung */
  char digit;

  if (hex[0] >= 'A') digit = ((hex[0] & 0xdf) - 'A') + 10;
  else               digit = (hex[0] - '0');
  digit = digit * 16;
  if (hex[1] >= 'A') digit = digit + ((hex[1] & 0xdf) - 'A') + 10;
  else               digit = digit + (hex[1] - '0');
  return(digit);
  /* Das ginge sogar noch einfacher:
     digit = (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A')+10 : (hex[0] - '0'));
     digit = digit * 16;
     digit += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A')+10 : (hex[1] - '0')); */
  }

void unescape(char *url)
  /* Diese Funktion wandelt eine URL wieder in eine Folge
     von ASCII-Zeichen um */
  {
  int x, y;
  char hex[2];

  for (x=0,y=0; url[y] != '\0'; x++,y++)
    {
    if (url[y] == '+')           /* Leerzeichen restaurieren */
      url[x] = ' ';
    else if(url[y] == '%')       /* Hexadezimalangabe */
      {
      hex[0] = url[y+1];
      hex[1] = url[y+2];
      y = y + 2;
      url[x] = x2c(hex);
      }
    else
      url[x] = url[y];           /* 'normales' Zeichen */
    }
  url[x] = '\0';                 /* Stringende-Zeichen anhängen */
  }




void CGIReadInput(char *Suchwort)
  /* Bearbeiten der CGI-Daten und Aufspalten in
     die Paare Name/Wert. Es werden GET- und
     POST-Requests verarbeitet. */
  {
  int i, j, content_length, maxlen;
  short NM = 1; /* Statusvariable, NM=1: Name, NM=0: Wert */
  char *input, *name, *value;


  /* Eingabe prüfen */
 if (REQUEST_METHOD == NULL)
    {
    fprintf(stderr,"Error: REQUEST_METHOD is null\n");
    exit(1);
    }

 if (CONTENT_LENGTH == NULL)
    {
    Suchwort[0]='\0';
    return;
    }

  /* Benoetigte Werte holen und Speicher reservieren */
  content_length = atoi(CONTENT_LENGTH);
  maxlen = content_length - 1;
  /* genügend Speicher fuer die Eingabe reservieren */
  input = malloc(sizeof(char) * content_length + 1);
  /* Name und Wert koennen maximal so lang sein wie die Eingabe */
  name = malloc(sizeof(char) * content_length + 1);
  value = malloc(sizeof(char) * content_length + 1);
  if (!strcmp(REQUEST_METHOD,"POST"))
    { /* Daten von der Standardeingabe lesen */
     if (fread(input,sizeof(char),content_length,stdin) != content_length)
      {
      /* consistency error. */
      fprintf(stderr,"Error: input length < CONTENT_LENGTH\n");
      exit(1);
      }
    }
  else if (!strcmp(REQUEST_METHOD,"GET"))
    { /* Daten aus der Umgebungsvariablen QUERY_STRING holen */
    if (QUERY_STRING == NULL)
      {
      fprintf(stderr,"Error: QUERY_STRING is null\n");
      exit(1);
      }
    strcpy(input,QUERY_STRING);
    }
  else
    { /* error: invalid request method */
    fprintf(stderr,"Error: REQUEST_METHOD invalid\n");
    exit(1);
    }

  /* Daten aufsplitten */
  j = 0;
  for (i = 0; i < content_length; i++)
    {
    if (input[i] == '=')
      { /* Name zuende, nun Wert verarbeiten */
      name[j] = '\0';
      unescape(name);
      if (i == maxlen)
        { /* Ende der Eingabe, kein Wert */
        strcpy(value,"");
        /* abspeichern */
        // printf ("%s --> '%s'\n",name, value);
        if (!strcmp(name,"Suchwort"))
          {
          strcpy(Suchwort,value);
          }
        }
      j = 0; NM = 0;
      }
    else if ((input[i] == '&') || (i == maxlen))
      { /* Wertangabe zuende */
      if (i == maxlen)
        { /* Ende der Eingabe, letzter Wert */
        value[j] = input[i];
        j++;
        }
      value[j] = '\0';
      unescape(value);
      /* abspeichern */
      // printf ("%s --> '%s'\n\n\n",name, value);
      if (!strcmp(name,"Suchwort"))
        {
        strcpy(Suchwort,value);
        }
        j = 0; NM = 1;
      }
    else if (NM)
      { /* Name wird gerade gelesen */
      name[j] = input[i];
      j++;
      }
    else if (!NM)
      { /* Wert wird gerade gelesen */
      value[j] = input[i];
      j++;
      }
    }
  }


