/*
 *  (C) Copyright 2002-2004 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 <sys/wait.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>
#include "globals.h"
#include "b64.h"
#include "xemoticon.h"
#include "wbmps.h"
#include "mincrypt.h"
#include "sendmail.h"
#include "decode.h"
#include "ckm.h"
#include "wap.h"
#include "utils.h"
#include "www.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

void catcher(int sig);
int newsockfd;

/*
 Opis niektorych zmiennych

 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 debug=1; // 0-nic nie wyświetlaj, 1-tylko komunikaty, 2-komunikaty i output
 */

int main(int a, char **b)
{
    int sockfd, w, auth, k, kk, token, sock_opt;
    long int incounter;
    char c;
    char line[4001];
    char ol[14101];
    char wout[14101];
    char qstr[3501];
    struct sockaddr_in server;
    static struct sigaction act;
    char passfilename[100], *orglogin, *orgpass;
    char listen_ip[16];
    FILE *passfile;
    char *r;
    int icgi = 0;		//tryb cgi gdy rowne 1
    int aauth = 0;		//auternatywne logowanie
    int fblw = 0;		//freeblwr mode
    long int fbuser = 0;	//numer usera we fblw
    long int maxpdu = 2700;	//dlugosc strony maksymalnie
    int maxslots = 30;		//ilosc slotow na fblw
    int xe_count = 0;
    int noold = 0;
    char aauthhash[128];
    char emotdir[201];
    char dirgg[21];
    pid_t p;

    debug = 1;
    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-2004 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, icgi, 0, xe_count, noold);
		    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);
    }

    sock_opt = 1;
    if ((setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (void *) &sock_opt, sizeof(sock_opt))) == -1) {
	perror("[error] socked reuse 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;


	//todo zrobic odpornym na dos, max ilosc forkow, max na minute itp.
	/*
	   * nalezy dopisac jeszcze kawalek kodu sprawdzajacy czy fork () nie zwrocil
	   * wartosci -1
	 */

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

		xe_count = xemoticon_load(emotdir, xe_count);
		if (debug == 2)
		    printf("[rtg] Załadowano %d emoticon\n", xe_count);

		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 == 4000)
			w = 3999;	// 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 (strstr(line, "?") != 0) {	//query string :)
				snprintf(qstr, sizeof(qstr), "%.3490s", (char *) (index(line, '?') + 1));
				r = (char *) index(qstr, ' ');
				if (r == NULL) {	//zle zapytanie
				    shutdown(newsockfd, SHUT_RDWR);
				    close(newsockfd);
				    exit(0);
				}
				r[0] = 0;
			    }

			    if (strncmp(qstr, "www", 3) == 0) {
				w3 = 1;
				aauth = 0;	//dla www nie ma aauth
			    }

			    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;
						}
					    }
					}
				    }
				}
			    }
			}
			// 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, aauth);
				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;
			    // int vcs=0;

			    for (ii = 0; ii < (WBMPS * 3); ii += 3)
				if (strcmp(qstr, wbmpstab[ii]) == 0) {
				    char *gc;
				    rys = wbmpstab[ii + 1];
				    size = atoi(wbmpstab[ii + 2]);
				    gc = (char *) index(wbmpstab[ii], '.');
				    if (gc)
					if (strcmp(gc, ".gif") == 0)
					    gif = 1;
				}

			    /* 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, xe_count, fblw);
				    snprintf(ol, sizeof(ol), "HTTP/1.0 200 OK\r\n%.14000s", wout);
				}
				else {
				    wap(wout, qstr, 3100, icgi, fblw, xe_count, noold);
				    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 || strncmp(qstr, "www=0fblw", 9) == 0)
				    ) {	// obsluga formularza zakladania nowej sesji
				    char *lg, *pas;
				    if (debug > 0)
					printf("[freeblwr]: proba rejestracji nowej sesji %s\n", qstr);
				    if (!w3) {
					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, ';');
				    }
				    else {
					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/html\r\n"
						 "\r\n" "<html>" "<head>" "<META HTTP-EQUIV=\"content-type\" CONTENT=\"text/html; CHARSET=iso-8859-2\">");
					lg = (char *) index(qstr + 10, '=');
				    }
				    if (lg == NULL) {
					if (debug > 0)
					    printf("[%ld] blad wywolania formularza\n", fbuser);
					if (!w3)
					    snprintf(ol + strlen(ol),
						     sizeof(ol) -
						     strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>error: blad wywolania formularza 1</p>");
					else
					    snprintf(ol + strlen(ol), sizeof(ol) - strlen(ol), "</head><body>blad wywołania formularza");
				    }
				    else {
					lg++[0] = 0;
					if (!w3)
					    pas = (char *) index(lg, ';');
					else
					    pas = (char *) index(lg, '=');
					if (pas == NULL) {
					    if (debug > 0)
						printf("[%ld] blad wywolania formularza\n", fbuser);
					    if (!w3)
						snprintf(ol + strlen(ol),
							 sizeof(ol) -
							 strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>error: blad wywolania formularza 2</p>");
					    else
						snprintf(ol + strlen(ol), sizeof(ol) - strlen(ol), "</head><body>blad wywołania formularza");
					}
					else {
					    int slot = 0, allow = 1;
					    FILE *fslot;
					    char pome[200], *ppr;
					    pas++[0] = 0;

					    if (w3) {
						ppr = (char *) index(lg, '&');
						if (ppr)
						    ppr[0] = 0;
						ppr = (char *) index(pas, '&');
						if (ppr)
						    ppr[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(maxslots);	// 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");
						snprintf(ol + strlen(ol),
							 sizeof(ol) -
							 strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Blad utworzenia sesji, brak gniazd</p>");
					    }
					    else if (strlen(pas) > 30) {
						clrdir(slot, 1);
						if (debug > 0)
						    printf("[error] nieudana, zbyt dlugie haslo\n");
						snprintf(ol + strlen(ol),
							 sizeof(ol) -
							 strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Blad utworzenia sesji, zbyt dlugie haslo</p>");
					    }
					    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);
							if (!w3)
							    snprintf(ol +
								     strlen
								     (ol),
								     sizeof
								     (ol) -
								     strlen
								     (ol),
								     "<card id=\"gg\" title=\"RTG FreeBlwr\" ontimer=\"/%d/\">"
								     "<timer name=\"time3\" value=\"1\"/>", slot);
							else
							    snprintf(ol +
								     strlen
								     (ol),
								     sizeof
								     (ol) - strlen(ol), "<META http-equiv=\"Refresh\" content=\"0;URL=/%d/?www\"><body>", 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);
							snprintf(ol + strlen(ol), sizeof(ol)
								 - strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Nieudane uruchomienie ekg</p>");
						    }
						}
						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);
						    snprintf(ol +
							     strlen(ol),
							     sizeof(ol) -
							     strlen(ol), "<card id=\"gg\" title=\"RTG FreeBlwr\"><p>Nieudane zakladanie pliku z haslem</p>");
						}
					    }
					}
				    }
				    if (!w3)
					snprintf(ol + strlen(ol), sizeof(ol) - strlen(ol), "</card></wml>");
				    else
					snprintf(ol + strlen(ol), sizeof(ol) - strlen(ol), "</body></html>");
				}	//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 {	//todo chyba pierwszy / trzeba skasować (majkel)
					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");
					if (!w3)
					    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");
					if (w3)
					    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/html\r\n"
						     "\r\n" "<html>\r\n"
						     "<head>\r\n"
						     "<title>RTG FreeBlwr</title>"
						     "</head>\r\n"
						     "<body>\r\n"
						     "<form action=\"?\">"
						     "<p align=center>"
						     "<input type=hidden name=www value=\"0fblw\">"
						     "<img src=http://www.comm.pl/~serek/ekgwap/foto/rtg.gif alt=RTG><br>"
						     "<font size=5>RTG Freeblwr mode</font><br>"
						     "new session<br>"
						     "Gg number: <input name=\"g\" type=\"text\"><br>\r\n"
						     "Gg passwd: <input name=\"p\" type=\"password\"><br>\r\n"
						     "<input type=\"submit\" name=OK value=\"Send\"></form>\r\n" "</p></body></html>\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 {
		exit(0);
		//glowny proces
//              close(newsockfd);

		//// czasami moze byc potrzebny, gdy zostaja zombie
		// wait(0);
	    }
	}
	else {
	    close(newsockfd);
	    waitpid(p, NULL, 0);
	}
    }
}

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