/*
 *  (C) Copyright 2002,2003 Sergiusz Rozanski <rozanski@sergiusz.com>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License Version 2 as
 *  published by the Free Software Foundation.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */


#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <signal.h>
#include <time.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <stdarg.h>
#include <sys/stat.h>
#include <stdio.h>
#include <dirent.h>

#define SIZE sizeof(struct sockaddr_in)

#ifdef WORDS_BIGENDIAN
#define swap_short(sh) (sh)
#else
#define swap_short(sh) ((((sh)&0xff00)>>8)|(((sh)&0x00ff)<<8))
#endif

// globale
void catcher (int sig);
int newsockfd;
char home[101];
char dirgg[21];
char emotdir[201];
long int maxpdu = 2700;

/*
icgi  = 1 - tryb cgi
flbw = 1 - tryb freeblwr
maxslots - ilosc slotow dla freeblwr, domyslnie 30
aauth = 1 - alternatywne logowanie przez link
noold = 1 - gdy 0 pisze wap-log i oldwap, gdy 1 nie pozostawia żadnej historii
nopl = 0 - gdy 0 pisze po polsku, gdy 1, pisze polskawo
checkreason = 0 - gdy 1 reason-y pojawią się na stronie check
*/
int icgi = 0, fblw = 0, maxslots = 30, aauth = 0, noold = 0, nopl =
  0, checkreason = 0;

int debug = 1;			// 0-nic nie wyświetlaj, 1-tylko komunikaty, 2-komunikaty i output

char logname[51];
char aauthhash[128];
long int fbuser = 0;

#include "version.c"
#include "xemoticon.c"
#include "wbmps.c"
#include "mincrypt.c"
#include "sendmail.c"
#include "wap.c"
// #include "www.c"

/*
licznik bajtow nadanych i wyslanych z rtg z podzialem
na sesje freeblwr
*/

int
countersadd (char *pathhome, long int in, long int out)
{
  char pom[255], ins[42], outs[42];
  FILE *plik;

  sprintf (ins, "0");
  sprintf (outs, "0");
  if (debug > 1)
    printf ("[rtg] %s in %ld out %ld\n", pathhome, in, out);
  snprintf (pom, sizeof (pom), "%s/wap-counters", pathhome);
  if ((plik = fopen (pom, "r")))
    {
      if (!feof (plik))
	fgets (ins, 41, plik);
      if (!feof (plik))
	fgets (outs, 41, plik);
      fclose (plik);
    }
  if ((plik = fopen (pom, "w")))
    {
      fprintf (plik, "%ld\n%ld\n", atol (ins) + in, atol (outs) + out);
      fclose (plik);
    }
  return 0;
}

/*
funkcja czyści katalog slotu o podanym numerze
gdy kat==1 kasuje również sam katalog
*/

int
clrdir (int slot, int kat)
{
  struct dirent **namelist;
  char wapfile[201], tmp[201];
  int n, k;

  //wyczysc katalog
  snprintf (tmp, sizeof (tmp), "%s/%d/", home, slot);
  n = scandir (tmp, &namelist, 0, alphasort);
  if (n < 0)
    {
      // jakis problem z lista katalogow
      if (debug > 0)
	printf ("[%d] Problem z katalogiem: %s\n", slot, tmp);
      return 0;
    }
  else
    {
      k = n;
      while (n--)
	{
	  snprintf (wapfile, sizeof (wapfile), "%s%s", tmp,
		    namelist[k - n - 1]->d_name);
	  unlink (wapfile);
	}
      free (namelist[k - n - 1]);
    }
  free (namelist);

  if (kat == 1)
    {
      snprintf (tmp, sizeof (tmp), "%s/%d/", home, slot);
      rmdir (tmp);
    }

  return 0;
}

/*
funkcja szuka wolnego slotu dla freeblwr mode
jeśli go znajdzie zwraca jego numer, jeśli go nie znajdzie
zwraca zero
*/

int
findslot (void)
{
  int i, fs = 0;
  char tmp[201];
  struct stat buf;
  time_t tczas;
  long int czas = 0;

  time (&tczas);

//szukam wogole wolnego slotu
  for (i = 1; i <= maxslots; i++)
    {
      snprintf (tmp, sizeof (tmp), "%.150s/%d", home, i);
      if (mkdir (tmp, 0700) == 0)
	{			// znaleziono slot
	  if (debug > 0)
	    printf ("[search] Znaleziono wolny slot %d\n", i);
	  return i;
	}
    }

//szukam najstarszego slotu
  if (debug > 0)
    printf ("[search] Brak wolnych slotow szukam najstarszego\n");
  for (i = 1; i <= maxslots; i++)
    {
      snprintf (tmp, sizeof (tmp), "%.150s/%d/wap-query.log", home, i);
      if (lstat (tmp, &buf) == 0)
	{
	  if (buf.st_mtime < czas || czas == 0)
	    {
	      czas = buf.st_mtime;
	      fs = i;
	    }
	}
    }
  if (debug > 0)
    printf ("[search] Najstarszy slot %d\n", fs);

  if (fs == 0)
    return 0;

// jeśli najstarsze gniazdo było urzywane w ciągu 10 minut to
// go nie można urzywać

  if ((tczas - czas) < 600)
    {
      if (debug > 0)
	printf ("[search] Slot %d nadal urzywany\n", fs);
      return 0;
    }

//jesli bardzo stary
  snprintf (tmp, sizeof (tmp), "%.150s/%d/wap-query.log", home, fs);
  if (unlink (tmp) == 0)
    {
      FILE *pwap;

      //tylko 1 proces tu wejdzie jesli szukalo wiecej (jeden zdarzy odlinkowac plik)
      //mozna by poszukac jeszcze, ale nie ma wogole wolnych
      //a jeszcze 2 naraz sie dobija

      //zatrzymaj ekg

      if (debug > 0)
	printf ("[search] slot %d przedawniony\n", fs);
      snprintf (tmp, sizeof (tmp), "%.150s/%d/pipewap", home, fs);
      if ((pwap = fopen (tmp, "r+")))
	{
	  //znaczy sie dziala
	  fprintf (pwap, "/quit\n");
	  fclose (pwap);
	  sleep (2);		//daj mu czas na zamkniecie
	}

      clrdir (fs, 0);

      return fs;
    }				//udal sie unlink

//sorry, no free slots
  return 0;
}

int
main (int a, char **b)
{
  int sockfd, w, auth, k, kk, token;
  long int incounter;
  char c;
  char line[1001];
  char ol[14101];
  char wout[14101];
  char qstr[501];
  struct sockaddr_in server;
  static struct sigaction act;
  char passfilename[100], *orglogin, *orgpass;
  char listen_ip[16];
  FILE *passfile;
  char *r;

  if (geteuid () == 0)
    {
      printf ("RTG: change mode to user\n");
      return 0;
    }

  memset (&qstr, 0, sizeof (qstr));
  snprintf (dirgg, sizeof (dirgg), ".gg");
  snprintf (qstr, sizeof (qstr), "%.500s", (char *) getenv ("QUERY_STRING"));
  if (strcmp (qstr, "(null)") != 0)
    icgi = 1;

  if (icgi == 0)
    {
      snprintf (home, sizeof (home), "%.100s/%s", (char *) getenv ("HOME"),
		dirgg);
      snprintf (emotdir, sizeof (emotdir), "%s/emots", home);
      snprintf (logname, sizeof (logname), "%.50s",
		(char *) getenv ("LOGNAME"));
      printf ("* RTG (http://gg.overwap.net)\n");
      printf ("* Wap server for EKG (http://dev.null.pl/ekg/)\n");
      printf ("* (C) 2002,2003 by Elita\n");
      printf ("* Home dir/ggdir: %s\n", home);
      if (a > 1)
	printf ("* Listen port: %d\n", atoi (b[1]));

      memset (&qstr, 0, sizeof (qstr));
      memset (&aauthhash, 0, sizeof (aauthhash));
      memset (&listen_ip, 0, sizeof (listen_ip));

      if (a > 2)
	for (kk = 2; kk < a; kk++)
	  {
	    if (strcmp (b[kk], "--freeblwr") == 0)
	      {
		// char tmp[100];
		fblw = 1;
		noold = 0;
		if (kk + 1 < a)
		  maxslots = atol (b[kk + 1]);
		if (maxslots < 1)
		  maxslots = 30;
		printf ("* FreeBlwr mode enabled, slots: %d\n", maxslots);
	      }
	    if (strcmp (b[kk], "-u") == 0)
	      {
		if (kk + 1 < a)
		  {
		    snprintf (home + strlen (home),
			      sizeof (home) - strlen (home), "/%.20s",
			      b[++kk]);
		  }
		else
		  {
		    printf ("Error: -u need home subdirectory\n");
		    return 0;
		  }
		printf ("* User change dir/ggdir: %s\n", home);
	      }
	    if (strcmp (b[kk], "-h") == 0)
	      {
		if (kk + 1 < a)
		  {
		    snprintf (listen_ip, sizeof (listen_ip), "%.15s",
			      b[++kk]);
		  }
		else
		  {
		    printf ("Error: -h need ip adress\n");
		    return 0;
		  }
		printf ("* Listen ip: %s\n", listen_ip);
	      }
	    if (strcmp (b[kk], "-d") == 0)
	      {
		if (kk + 1 < a)
		  {
		    debug = atol (b[++kk]);
		    if (debug < 0)
		      debug = 0;
		    if (debug > 2)
		      debug = 2;
		  }
		else
		  {
		    printf ("Error: -d need debug level\n");
		    return 0;
		  }
		printf ("* Debug: %d\n", debug);
	      }
	    if (strcmp (b[kk], "-a") == 0)
	      {
		printf ("* Alternative authorization: enabled\n");
		aauth = 1;
	      }
	    if ((strcmp (b[kk], "--noold") == 0) && (fblw == 0))
	      {
		printf ("* no old files mode: enabled\n");
		noold = 1;
	      }
	  }
      if (a < 2)
	{
	  printf ("\nWelcome in RTG, runing mode:\n"
		  "ekgwapd <port> [-a --noold -h]           - standard, one user\n"
		  "ekgwapd <port> --freeblwr [-a -h]        - public gateway (30 slots)\n"
		  "ekgwapd <port> --freeblwr <i> [-a -h]    - public gateway (i slots)\n"
		  "ekgwapd <port> -u <name> [-a --noold -h] - one selected user\n"
		  "                                           (like '-u' in ekg)\n"
		  "Options:\n"
		  " --noold - dont write old and log files\n"
		  " -h <ip> - listen ip\n"
		  " -d <i>  - debug level i=0,1,2 (default 1)\n"
		  " -a      - alternative authorization\n\n");
	  return 0;
	}
    }
  else
    {
      //odczyt home z passwd dla cgi
      int myuid = geteuid ();
      FILE *passwd;
      char passl[501], *k, *puid, *ki;

      if ((passwd = fopen ("/etc/passwd", "r")))
	{
	  while (fgets (passl, 500, passwd))
	    {
	      k = (char *) index (passl, 10);
	      if (k != NULL)
		k[0] = 0;
	      k = (char *) index (passl, ':');
	      if (k == NULL)
		return 0;
	      k++[0] = 0;
	      puid = (char *) index (k, ':');
	      if (puid == NULL)
		return 0;
	      puid++[0] = 0;
	      k = (char *) index (puid, ':');
	      if (k == NULL)
		return 0;
	      k++[0] = 0;
	      if (atoi (puid) == myuid)
		{
		  //          printf("%d ",atoi(puid));
		  k = (char *) index (k, ':');
		  if (k == NULL)
		    return 0;
		  k++[0] = 0;
		  k = (char *) index (k, ':');
		  if (k == NULL)
		    return 0;
		  k++[0] = 0;
		  ki = (char *) index (k, ':');
		  if (ki == NULL)
		    return 0;
		  ki++[0] = 0;
		  snprintf (home, sizeof (home), "%s/%s", k, dirgg);
		  snprintf (emotdir, sizeof (emotdir), "%s/emots", home);
		  snprintf (logname, sizeof (logname), "%.50s", passl);
		}
	    }
	  fclose (passwd);
	  if (strlen (home) > 1)
	    {
	      int ii;
	      char *rys = NULL;
	      int size = 0;

	      for (ii = 0; ii < (WBMPS * 3); ii += 3)
		if (strcmp (qstr, wbmpstab[ii]) == 0)
		  {
		    rys = wbmpstab[ii + 1];
		    size = atoi (wbmpstab[ii + 2]);
		  }
	      if (rys)
		{
		  printf ("Content-type: image/vnd.wap.wbmp\r\n\r\n");
		  for (ii = 0; ii < size; ii++)
		    printf ("%c", (rys + ii)[0]);
		}
	      else
		{
		  char http_accept[2000];
		  wap (wout, qstr, 3000);
		  printf ("%.4000s", wout);
		  snprintf (http_accept, sizeof (http_accept), "%s",
			    getenv ("HTTP-ACCEPT"));
		  countersadd (home,
			       200 + strlen (http_accept) + strlen (qstr),
			       36 + strlen (qstr));
		}
	    }
	  return 0;
	}
    }				// koniec cgi



  act.sa_handler = catcher;
  sigfillset (&(act.sa_mask));
  sigaction (SIGPIPE, &act, NULL);
  signal (SIGCHLD, SIG_IGN);

  server.sin_family = AF_INET;
  server.sin_port = swap_short (atoi (b[1]));
  if (strlen (listen_ip) == 0)
    server.sin_addr.s_addr = INADDR_ANY;
  else
    server.sin_addr.s_addr = inet_addr (listen_ip);

  if ((sockfd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
    {
      perror ("[error] socked call failed");
      exit (1);
    }

  if (bind (sockfd, (struct sockaddr *) &server, SIZE) == -1)
    {
      perror ("[error] connect call failed");
      exit (1);
    }

  if (listen (sockfd, 5) == -1)
    {
      perror ("[error] listen call failed");
      exit (1);
    }

  token = 0;
  incounter = 0;

  for (;;)
    {				//glowna petla
      if ((newsockfd = accept (sockfd, NULL, NULL)) == -1)
	{
	  perror ("[error] accept call failed");
	  continue;
	}

      w = 0;
      auth = 0;

      xemoticon_load (emotdir);

      //todo zrobic odpornym na dos, max ilosc forkow, max na minute itp.

      if (fork () == 0)
	{
	  int szlo_get = 0;
	  int szlo_auth = 0;
	  char xemobuf[20001];

	  while (recv (newsockfd, &c, 1, 0) > 0)
	    {
	      if (incounter > 1000000)
		{
		  // nagłówek http 1MB?
		  // to chyba nie z komórki ;)
		  return 0;
		}
	      incounter++;
	      if (w == 1000)
		w = 999;	// uwaga na koniec linii !!!!!!!!!!!!!!!!!!
	      if (c != 13 && c != 10)
		line[w++] = c;
	      if (c == 10)
		{
		  line[w] = 0;
		  if (debug > 1)
		    printf ("%s\n", line);

// pierwsza linia naglowka http
		  if (((strncmp (line, "GET", 3) == 0)
		       || strncmp (line, "POST", 4) == 0) && !szlo_get)
		    {
		      szlo_get = 1;
		      if (fblw == 1)
			{
			  char luid[21], *pk;
			  pk = (char *) index (line, '/');
			  if (pk != NULL)
			    {
			      snprintf (luid, sizeof (luid), "%.20s", pk + 1);
			      pk = (char *) index (luid, '/');
			      if (pk != NULL)
				{
				  (pk + 1)[0] = 0;
				  if (atol (luid) != 0)
				    {
				      snprintf (home + strlen (home),
						sizeof (home) - strlen (home),
						"/%ld",
						(long int) atol (luid));
				      if (debug > 0)
					printf
					  ("[%ld] freeblwr get, home: %s\n",
					   (long int) atol (luid), home);
				      fbuser = (long int) atol (luid);
				      fblw = 2;	//user z numerkiem
				    }
				}
			    }
			}
		      if (aauth)
			{
			  char ahash[51], *p;
			  p = (char *) index (line, '%');
			  if (p)
			    {
			      if (strlen (p) > 1)
				{
				  snprintf (ahash, sizeof (ahash), "%s",
					    p + 1);
				  p = (char *) index (ahash, '/');
				  if (p)
				    {
				      p[0] = 0;
				      snprintf (passfilename,
						sizeof (passfilename),
						"%s/wap-shash", home);
				      if (debug > 0)
					printf ("[%ld] shashfile: %s\n",
						fbuser, passfilename);
				      if ((passfile =
					   fopen (passfilename, "r")))
					{
					  fgets (passfilename, 1000,
						 passfile);
					  r =
					    (char *) index (passfilename, 10);
					  if (r != NULL)
					    r[0] = 0;
					  r =
					    (char *) index (passfilename, 13);
					  if (r != NULL)
					    r[0] = 0;
					  fclose (passfile);
					  if (strcmp (passfilename, ahash) ==
					      0)
					    {
					      auth = 1;
					    }
					}
				    }
				}
			    }
			}
		      if (strstr (line, "?") != 0)
			{	//query string :)
			  snprintf (qstr, sizeof (qstr), "%.501s",
				    (char *) (index (line, '?') + 1));
			  r = (char *) index (qstr, ' ');
			  if (r == NULL)
			    {	//zle zapytanie
			      shutdown (newsockfd, SHUT_RDWR);
			      close (newsockfd);
			      exit (0);
			    }
			  r[0] = 0;
			}
		    }
		  // tu wchodze w celu autoryzacji, gdy leci linia auth i jest zwykla autoryzacja
		  // lub get w alternatywnej
		  if (((strncmp (line, "Authorization", 13) == 0 && !aauth) ||
		       (strncmp (line, "GET", 3) == 0
			&& strncmp (qstr, "auth", 4) == 0 && aauth))
		      && (fblw == 2 || fblw == 0) && szlo_get && !szlo_auth)
		    {
		      szlo_auth = 1;
//odczyt hasla z pliku
		      snprintf (passfilename, sizeof (passfilename),
				"%s/wappasswd", home);
		      if (debug > 0)
			printf ("[%ld] authfile: %s\n", fbuser, passfilename);
		      if ((passfile = fopen (passfilename, "r")))
			{
			  fgets (passfilename, 1000, passfile);
			  r = (char *) index (passfilename, 10);
			  if (r != NULL)
			    r[0] = 0;
			  r = (char *) index (passfilename, 13);
			  if (r != NULL)
			    r[0] = 0;
			  fclose (passfile);
			}
		      else
			{
			  printf
			    ("[error] Brak pliku konfiguracyjnego z haslem do servera\n");
			  printf
			    ("[error] wykonaj htpasswd -c ~/.gg/wappasswd [login]\n");
			  auth = 2;
			}
		      if (auth == 0 && strlen (passfilename) == 0)
			{
			  printf
			    ("[error] Uszkodzony plik z haslem wappasswd\n");
			  auth = 2;
			}
		      if (auth == 0)
			{
			  orglogin = passfilename;
			  orgpass = (char *) index (passfilename, ':');
			  if (orgpass == NULL)
			    {
			      printf
				("[error] Uszkodzony plik z haslem wappasswd\n");
			      auth = 2;
			    }
			}
		      if (auth == 0)
			{
			  orgpass++[0] = 0;
			  if (strlen (orglogin) == 0 || strlen (orglogin) > 30
			      || strlen (orgpass) == 0
			      || strlen (orgpass) > 30)
			    {
			      printf
				("[error] Uszkodzony plik z haslem wappasswd\n");
			      auth = 2;
			    }
			}
		      if (auth == 0)
			{
			  auth = mincrypt (line, orglogin, orgpass);
			  if (debug > 0)
			    printf ("[%ld] Login: %s - %s\n", fbuser, orglogin, (auth == 1) ? "OK" : "false");	//haslo pobrane
			  if (aauth && auth == 1)
			    {
			      // zalorzyc plik wap-shash
			      FILE *pp;
			      char pl[256];
			      snprintf (pl, sizeof (pl), "%s/wap-shash",
					home);
			      if ((pp = fopen (pl, "w")))
				{
				  if (debug > 0)
				    printf
				      ("[%ld] Aauth OK: zakladam plik z hashem sesji\n",
				       fbuser);
				  snprintf (aauthhash, sizeof (aauthhash),
					    "%s", shash (orglogin, orgpass));
				  fprintf (pp, "%s\n", aauthhash);
				  fclose (pp);
				  chmod (pl, 0600);
				  auth = 0;
				  // qstr[0]=0;
				  // auth=1;
				}
			      else
				{
				  printf
				    ("[error] Nie mozna otworzyc pliku wap-shash\n");
				  auth = 0;
				}
			    }
			}
		    }
		  if (strncmp (line, "x-up-devcap-max-pdu: ", 21) == 0)
		    {
//dlugosc strony akceptowana przez browser
		      maxpdu = atol ((char *) index (line, ':'));
		      if (maxpdu > (sizeof (ol) - 5))
			maxpdu = sizeof (ol) - 5;
		    }
		  if (strlen (line) == 0)
		    {		//server wbmp
		      int ii;
		      char *rys = NULL;
		      int size = 0;
		      int gif = 0;
		      int midi = 0;

		      for (ii = 0; ii < (WBMPS * 3); ii += 3)
			if (strcmp (qstr, wbmpstab[ii]) == 0)
			  {
			    rys = wbmpstab[ii + 1];
			    size = atoi (wbmpstab[ii + 2]);
			  }

		      /* xemoticon */
		      for (ii = 0; ii < xe_count; ii++)
			if (strcmp (qstr, xe_gifs[ii]) == 0)
			  {
			    FILE *pgif;
			    char ngif[512];

			    snprintf (ngif, sizeof (ngif), "%s/1/%s", emotdir,
				      qstr);
			    if ((pgif = fopen (ngif, "rb")))
			      {
				printf ("%s\n", ngif);
				size = fread (xemobuf, 1, 20000, pgif);
				fclose (pgif);
				if (size > 0)
				  rys = xemobuf;
			      }
			    ii = xe_count;
			    gif = 1;
			  }

		      if (strcmp (qstr, "beep.midi") == 0)
			{
			  midi = 1;
			  rys = wbmpstab[1];
			  size = atoi (wbmpstab[2]);
			};

		      if (rys)
			{
			  if (debug > 0)
			    printf ("[%ld] wbmp: %s size:%d\n", fbuser, qstr,
				    size);
			  if (midi)
			    snprintf (ol, sizeof (ol), "HTTP/1.0 200 OK\r\n"
				      "Content-type: audio/midi\r\n\r\n");
			  else if (gif)
			    snprintf (ol, sizeof (ol), "HTTP/1.0 200 OK\r\n"
				      "Content-type: image/gif\r\n\r\n");
			  else
			    snprintf (ol, sizeof (ol), "HTTP/1.0 200 OK\r\n"
				      "Content-type: image/vnd.wap.wbmp\r\n\r\n");

			  countersadd (home, incounter, strlen (ol) + size);

			  w = 0;
			  do
			    {
			      k = send (newsockfd, &ol, strlen (ol), 0);
			      usleep (5);
			      w++;
			    }
			  while (strlen (ol) != k || w > 30);
			  if (w > 30)
			    exit (0);	//connect timeout
			  w = 0;
			  do
			    {
			      k = send (newsockfd, rys, size, 0);
			      usleep (5);
			      w++;
			    }
			  while (size != k || w > 30);
			  if (w > 30)
			    exit (0);	//connect timeout
			  shutdown (newsockfd, SHUT_RDWR);
			  close (newsockfd);
			  exit (0);
			}
		    }		//end server wbmp
		  if (strlen (line) == 0)
		    {		//glowna tresc z wap()
		      if (auth == 1)
			{	// autoryzacja udana mozna wejsc do rtg
			  if (strncmp (qstr, "www", 3) == 0)
			    {
			      //fewww(wout,qstr,12000);
			      //sprintf(ol,"HTTP/1.0 200 OK\r\n%.14000s",wout);
			    }
			  else
			    {
			      wap (wout, qstr, 3000);
			      // printf("\nHTTP/1.0 200 OK\r\n%.4000s\n\n",wout);
			      snprintf (ol, sizeof (ol),
					"HTTP/1.0 200 OK\r\n%.4000s", wout);
			    }
			  if (debug > 0)
			    printf ("[%ld] sesja home: %s query: %s\n",
				    fbuser, home, qstr);
			}	//auth==1
		      else
			{	//auth!=1
			  if (fblw == 1 && strncmp (qstr, "fblw", 4) == 0)
			    {	// obsluga formularza zakladania nowej sesji
			      char *lg, *pas;
			      if (debug > 0)
				printf
				  ("[freeblwr]: proba rejestracji nowej sesji %s\n",
				   qstr);
			      snprintf (ol, sizeof (ol),
					"HTTP/1.0 200 OK\r\n"
					"Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
					"Cache-Control: no-cache, must-revalidate\r\n"
					"Pragma: no-cache\r\n"
					"Content-type: text/vnd.wap.wml\r\n"
					"\r\n" "<?xml version=\"1.0\"?>"
					"<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">"
					"" "<wml>" "<head>"
					"<meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"max-age=0\"/>"
					"</head>");
			      lg = (char *) index (qstr + 5, ';');
			      if (lg == NULL)
				{
				  if (debug > 0)
				    printf
				      ("[%ld] blad wywolania formularza\n",
				       fbuser);
				  sprintf (ol,
					   "%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>error: blad wywolania formularza 1</p>",
					   ol);
				}
			      else
				{
				  lg++[0] = 0;
				  pas = (char *) index (lg, ';');
				  if (pas == NULL)
				    {
				      if (debug > 0)
					printf
					  ("[%ld] blad wywolania formularza\n",
					   fbuser);
				      sprintf (ol,
					       "%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>error: blad wywolania formularza 2</p>",
					       ol);
				    }
				  else
				    {
				      int slot = 0, allow = 1;
				      FILE *fslot;
				      char pome[200];
				      pas++[0] = 0;

				      if (debug > 0)
					printf
					  ("[freeblwr] Próba rejestracji konta: %s\n",
					   lg);

				      // deny file
				      snprintf (pome, sizeof (pome),
						"%.150s/freeblwr.deny", home);
				      if ((fslot = fopen (pome, "r")))
					{
					  while (fgets
						 (pome, sizeof (pome) - 1,
						  fslot))
					    {
					      char *tt;

					      tt = (char *) index (pome, 10);
					      if (tt)
						tt[0] = 0;
					      tt = (char *) index (pome, 13);
					      if (tt)
						tt[0] = 0;

					      if (strcmp (pome, lg) == 0)
						{
						  allow = 0;
						  if (debug > 0)
						    printf
						      ("[freeblwr] user %ld administracyjnie wywalony\n",
						       atol (lg));
						}
					    }
					  fclose (fslot);
					}

				      if (allow)
					slot = findslot ();	// znajdz nowy wolny slot
				      if (slot != 0)
					{	//zajmij slot tworzac query-log
					  snprintf (pome, sizeof (pome),
						    "%.150s/%d/wap-query.log",
						    home, slot);
					  // if
					  fslot = fopen (pome, "w");
					  fclose (fslot);
					  // else ktos tez wpadl na ten slot, ale do przemyslenia
					  // wiec slot=0
					}
				      if (slot == 0)
					{
					  if (debug > 0)
					    printf
					      ("[error] nieudana, brak slotow\n");
					  sprintf
					    ("%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Blad utworzenia sesji, brak gniazd</p>",
					     ol);
					}
				      else if (strlen (pas) > 30)
					{
					  clrdir (slot, 1);
					  if (debug > 0)
					    printf
					      ("[error] nieudana, zbyt dlugie haslo\n");
					  sprintf
					    ("%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Blad utworzenia sesji, zbyt dlugie haslo</p>",
					     ol);
					}
				      else
					{
					  FILE *exez;
					  int pomi;
// czy znaczki w hasle sa dozwolone
					  for (pomi = 0; pomi < strlen (pas);
					       pomi++)
					    if (!
						((pas[pomi] >= 'A'
						  && pas[pomi] <= 'Z')
						 || (pas[pomi] >= 'a'
						     && pas[pomi] <= 'z')
						 || (pas[pomi] >= '0'
						     && pas[pomi] <= '9')))
					      pas[pomi] = '_';
					  if (debug > 0)
					    printf
					      ("[freeblwr] udana slot: %d\n",
					       slot);

// zakladanie pliku z haslem (narazie brzydko, ale przerobie na c)

					  snprintf (pome, sizeof (pome),
						    "htpasswd -bc %s/%d/wappasswd %ld %s",
						    home, slot,
						    (long int) atol (lg),
						    pas);
					  exez = popen (pome, "r");
					  sleep (1);
					  pclose (exez);


					  if (1)
					    {	//jesli zakladanie pliku z haslem sie powiodlo
					      FILE *pwap;
// uruchamianie ekg dla slotu
					      snprintf (pome, sizeof (pome),
							"screen -dmS fekg ./bin/ekg -u %d -c %s/%d/pipewap",
							slot, home, slot);
					      exez = popen (pome, "r");
					      sleep (2);
					      pclose (exez);
					      snprintf (pome, sizeof (pome),
							"%s/%d/pipewap", home,
							slot);
					      if ((pwap = fopen (pome, "r+")))
						{	// zaprogramujmy ekg
						  fprintf (pwap,
							   "/set uin %ld\n",
							   (long int)
							   atol (lg));
						  fprintf (pwap,
							   "/set password %s\n",
							   pas);
						  fprintf (pwap,
							   "/set wap_enabled 2\n");
						  fprintf (pwap,
							   "/set auto_save 1\n");
// user się sam połączy jak się zaloguje
						  // fprintf(pwap,"/connect\n");
						  fflush (pwap);
						  sleep (1);
//                                              fprintf(pwap,"/list -g\n");
						  sleep (1);
						  fclose (pwap);
						  sprintf (ol,
							   "%s<card id=\"gg\" title=\"RTG FreeBlwr\" ontimer=\"/%d/\">"
							   "<timer name=\"time3\" value=\"1\"/>",
							   ol, slot);
						  if (debug > 0)
						    printf
						      ("[freeblwr] udana, śle przekierowanie slot: %d\n",
						       slot);
						}
					      else
						{
						  //ekg chyba nie ruszyl
						  clrdir (slot, 1);
						  if (debug > 0)
						    printf
						      ("[error] Problem z uruchomieniem ekg slot: %d\n",
						       slot);
						  sprintf (ol,
							   "%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Nieudane uruchomienie ekg</p>",
							   ol);
						}
					    }
					  else
					    {	// nieudane zakladanie pliku z haslem
					      snprintf (pome, sizeof (pome),
							"%.150s/%d/wap-query.log",
							home, slot);
					      unlink (pome);
					      snprintf (pome, sizeof (pome),
							"%.150s/%d/", home,
							slot);
					      rmdir (pome);
					      if (debug > 0)
						printf
						  ("[freeblwr] nieudana, niezlorzono pliku z haslem, slot: %d\n",
						   slot);
					      sprintf
						("%s<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Nieudane zakladanie pliku z haslem</p>",
						 ol);
					    }
					}
				    }
				}
			      sprintf (ol, "%s</card></wml>", ol);
			    }	//koniec obsługi formularza nowej sesji
			  else
			    if (aauth && strlen (aauthhash) > 0 &&
				strncmp (qstr, "auth", 4) == 0)
			    {
//sesja redirect dla aauth
			      char link[256];

			      if (fbuser != 0)
				{
				  snprintf (link, sizeof (link), "/%ld/%%%s/",
					    fbuser, aauthhash);
				}
			      else
				{
				  snprintf (link, sizeof (link), "/%%%s/",
					    aauthhash);
				}
			      if (debug > 0)
				printf ("[%ld] Sesja redirect %s\n", fbuser,
					aauthhash);
			      snprintf (ol, sizeof (ol),
					"HTTP/1.0 200 OK\r\n"
					"Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
					"Cache-Control: no-cache, must-revalidate\r\n"
					"Pragma: no-cache\r\n"
					"Content-type: text/vnd.wap.wml\r\n"
					"\r\n" "<?xml version=\"1.0\"?>"
					"<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">"
					"" "<wml>" "<head>"
					"<meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"max-age=0\"/>"
					"</head>"
					"<card id=\"gg\" title=\"RTG FreeBlwr\" ontimer=\"%s\">"
					"<timer name=\"time3\" value=\"1\"/>"
					"</card></wml>", link);
			    }
// koniec sesji redirect dla aauth
			  else
			    {
			      if (fblw == 1)
				{	//user bez mumerka czyli zakladanie (tak samo dla aauth jak i normalnie)
				  if (debug > 0)
				    printf
				      ("[freeblwr] Formularz nowej sesji\n");
				  snprintf (ol, sizeof (ol),
					    "HTTP/1.0 200 OK\r\n"
					    "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
					    "Cache-Control: no-cache, must-revalidate\r\n"
					    "Pragma: no-cache\r\n"
					    "Content-type: text/vnd.wap.wml\r\n"
					    "\r\n"
					    "<?xml version=\"1.0\"?>\r\n"
					    "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\r\n"
					    "\r\n" "<wml>\r\n"
					    "<head><meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"max-age=0\"/>\r\n"
					    "</head>\r\n"
					    "<card id=\"gg\" title=\"RTG FreeBlwr\" newcontext=\"true\">\r\n"
					    "<p>Gg number:</p><p><input format=\"*N\" name=\"g\" type=\"text\"/></p>\r\n"
					    "<p>Gg passwd:</p><p><input format=\"*M\" name=\"p\" type=\"text\"/></p>\r\n"
					    "<p><anchor>Send<go href=\"?fblw;s;$(g:escape);$(p:escape)\" method=\"get\"/></anchor></p>\r\n"
					    "</card></wml>\r\n");
				}
			      else if (aauth)
				{	//gdy autoryzacja alternatywna
				  if (debug > 0)
				    printf ("[rtg] Formularz logowania\n");
				  snprintf (ol, sizeof (ol),
					    "HTTP/1.0 200 OK\r\n"
					    "Expires: Mon, 26 Jul 1997 05:00:00 GMT\r\n"
					    "Cache-Control: no-cache, must-revalidate\r\n"
					    "Pragma: no-cache\r\n"
					    "Content-type: text/vnd.wap.wml\r\n"
					    "\r\n"
					    "<?xml version=\"1.0\"?>\r\n"
					    "<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\" \"http://www.wapforum.org/DTD/wml_1.1.xml\">\r\n"
					    "\r\n" "<wml>\r\n"
					    "<head><meta forua=\"true\" http-equiv=\"Cache-Control\" content=\"max-age=0\"/>\r\n"
					    "</head>\r\n"
					    "<card id=\"gg\" title=\"RTG Security Zone\" newcontext=\"true\">\r\n"
					    "<p>RTG login:</p><p><input format=\"*M\" name=\"g\" type=\"text\"/></p>\r\n"
					    "<p>RTG passwd:</p><p><input format=\"*M\" name=\"p\" type=\"text\"/></p>\r\n"
					    "<p><anchor>Login<go href=\"?auth;s;$(g:escape);$(p:escape)\" method=\"get\"/></anchor></p>\r\n"
					    "</card></wml>\r\n");
				}
			      else
				{	//gdy nie freeblwr to leci brak autoryzacji
				  if (debug > 0)
				    printf ("[rtg] Formularz HTTP/401\n");
				  snprintf (ol, sizeof (ol),
					    "HTTP/1.0 401 Authorization Required\r\n"
					    "Date: Wed, 31 Jul 2002 15:28:06 GMT\r\n"
					    "Server: GG/0.0.1 (Unix) Debian GNU/Linux\r\n"
					    "WWW-Authenticate: Basic realm=\"gg zone\"\r\n"
					    "Keep-Alive: timeout=15, max=100\r\n"
					    "Connection: Keep-Alive\r\n"
					    "Transfer-Encoding: chunked\r\n"
					    "Content-Type: text/html; charset=iso-8859-1\r\n"
					    "\r\n"
					    "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n"
					    "<HTML><HEAD>\r\n"
					    "<TITLE>401 Authorization Required</TITLE>\r\n"
					    "</HEAD><BODY>\r\n"
					    "<H1>Authorization Required</H1>\r\n"
					    "This server could not verify that you\r\n"
					    "are authorized to access the document\r\n"
					    "requested.  Either you supplied the wrong\r\n"
					    "credentials (e.g., bad password), or your\r\n"
					    "browser doesn't understand how to supply\r\n"
					    "the credentials required.<P>\r\n"
					    "</BODY></HTML>\r\n" "\r\n");
				}
			    }
			}	//auth==0
		    }		//line==0
		  if (strlen (line) == 0)
		    {
		      countersadd (home, incounter, strlen (ol));
		      w = 0;
		      do
			{
			  k = send (newsockfd, &ol, strlen (ol), 0);
			  usleep (5);
			  w++;
			}
		      while (strlen (ol) != k || w > 30);
		      shutdown (newsockfd, SHUT_RDWR);
		      close (newsockfd);
		      if (debug > 1)
			printf ("[query]\n%s\n\n", ol);
//                      printf("Baby killed\n");
		      exit (0);
		    }
		  w = 0;
		}
	    }
	  close (newsockfd);
	  exit (0);
	}
      else
	{
	  //glowny proces
	  close (newsockfd);

	  //// czasami moze byc potrzebny, gdy zostaja zombie
	  // wait(0);
	}
    }
}


void
catcher (int sig)
{
  close (newsockfd);
  printf ("Albercik, wychodzimy!\n");
  exit (0);
}
