Witam,
zwracam się z prośba o pomoc w poprawieniu programu. Muszę napisać skrypt CGI w Borland C++ Builder, który będzie wyszukiwał użytkownika w bazie danych w formacie .txt (rekordy typu - w każdej linijce pliku informacje: nazwa użytkownika, miasto, telefon, wiek oddzielane separatorem , czyli np.: KowalskiWrocław71-333-33-4437). Po przyjęciu zapytania, program ma dynamicznie generować stronę HTML z wynkiem zapytania wyświetlanym drabinką cout. Program ma umożliwiać/zawierać:

  1. wyszukiwanie z paska przeglądarki (np.: http://nazwa.serwera/katalog/skrypt.exe?Kowalski i to ma wyszukać odpowiedni rekord) <-- to już jest zrobione
  2. formularz umożliwiający dodawanie użytkownika i jego danych do bazy w pliku .txt (przy czym trzeba zaimplementować zabezpieczenie przed dodaniem użytkownika, który już istnieje w bazie)
  3. formularz umożliwiający wyszukanie użytkownika w bazie
  4. button umożliwiający pokazanie zawartości bazy w .txt (czyli po prostu skierowanie pod odpowiedni URL po kliknięciu w guzik)

Dodatkowo mam pytanie - czy zna ktoś z Was jakiś dobry darmowy serwer obsługujący CGI? Tak by można było testować działanie napisanego programu. Do tej pory korzystałem z prywatnego serwera znajomego, ale ta możliwość już niestety odpadła, a jak próbuję skorzystać z jakichś darmowych serwerów internetowych, to po umieszczeniu skompilowanego programu oraz bazy danych na serwerze i próbie wyszukiwania użytkownika albo otrzymuję komunikat, że żądany URL nie istnieje, albo spotykam się z próbą zapisania programu na dysku.

Poniżej zamieszczam kod tego, co do tej pory mam:

#include <iostream>
#include <stdlib.h>
#include <string>
#include <fstream>
#define UNHEX(C) \
    ((C >= '0' && C <= '9') ? C - '0' : \
     ((C >= 'A' && C <= 'F') ? C - 'A' + 10 : \
     ((C >= 'a' && C <= 'f') ? C - 'a' + 10 : 0)))

const char * header = "Content-type: text/html\n\n<html><head><title>cgi-bin</title></head> <body bgcolor=\"#FFFF00\">\n";
const char * foot = "</body> </html>\n";

using namespace std;

main(int argc, char *argv[])
{
	string query;
	char * method;
	ifstream plik;
	int znaleziony=0; // flaga pozwalająca oznaczyć znalezienie rekordu w bazie danych

	// wyświetlenie nagłówka
	cout << header << endl;
	// do pobierania danych ma służyć metoda get
	// tutaj sprawdzamy, czy program został uruchomiony jak zwykły plik .exe
	if ((method = getenv("REQUEST_METHOD")) == NULL || strcmp(method,"GET"))
	{
		cout << "Ten program nie służy do samodzielnego uruchamiania." << endl;
		exit(1);
	}
	// sprawdzenie, czy program dostał jakieś dane
	query = (getenv("QUERY_STRING") == NULL ? "" : getenv("QUERY_STRING"));
	if(!query.empty())
	{
		// tu opcjonalnie można sprawdzić, co zostało zadane przez użytkownika
		//   cout << "Wej&#182;cie: "" << query << """ << "<br>" << endl;
		/* zamiana kodów na znaki */
		// + na spacje
		while (query.find("+",0) != string::npos)
		{
			string::size_type pos = query.find("+",0);
			query.replace(pos, 1, " ");
		}
		// kody z postaci %nn na znak
		while (query.find("%",0) != string::npos)
		{
			string::size_type pos = query.find("%",0);
			char c[2];
			c[0] = (UNHEX(query[pos+1])) << 4;
			c[0] += UNHEX(query[pos+2]);
			c[1] = 0x0;
			query.replace(pos, 3, c);
		}
		// Tu można sprawdzić poprawność dekodowania danych 
		//   cout << "Zdekodowane wej&#182;cie: "" << query << """ << "<br>" << endl;
		// otwarcie bazy danych
		plik.open("baza.txt", ifstream::in);
		if (!plik.is_open())
		{
			cout << "Nie można otworzyć pliku bazy danych<br>" << endl;
		}
		char buf[1024];
		// wyszukiwanie nazwiska okreslonego parametrem w bazie rekordow
		do
		{
			plik.getline(buf, 1024, 'n');
			string e = buf;
			string::size_type pos = e.find("*",0);
			if (pos == string::npos && !e.empty())
			{
				cout << "Baza danych w nieprawidłowym formacie (przetwarzany rekord: "" << buf << "")" << endl;
		        	break;
			}
			else
			{
				// sprawdzenie, czy wczytany rekord jest poszukiwanym
			        if (e.substr(0,pos) == query) // tak, to jest ten
				{
			        	/* struktura rekordu: nazwa uzytkownika*miasto*telefon*wiek
			          	W jednej linii - jeden rekord. Wyszukiwanie jest czułe na wielkość znaków, czyli:
			          	Jan Kowalski to NIE JEST to samo co jan kowalski */
					// pobieranie pozostałych 3 pól wyszukanego rekordu bazy danych
					string dane[3];
					for (int i=0; i<3; i++)
					{
						string::size_type tmppos = e.find("*", pos+1);
						if (tmppos == string::npos && i<2)
						{
							// po ostatniej kolumnie nie musi być "*"
							cout << "Dane w bazie w nieprawidłowym formacie (przetwarzany rekord: "" << buf << "")" << endl;
							break;
						}
						dane[i] = e.substr(pos+1, tmppos-pos-1);
						pos = tmppos;
					}
				// drabinka cout wyswietlająca zawartość znalezionego rekordu bazy damych
				cout << "Znaleziono rekord pasujący do parametru wyszukiwania:<br>n";
				cout << "<table>";
				cout << "<tr><td><b>Nazwa uzytkownika:</b></td><td><i>" << query << "</i></td></tr>" << endl;
				cout << "<tr><td><b>Miasto:</b></td><td><i>" << dane[0] << "</i></td></tr>" << endl;
				cout << "<tr><td><b>Telefon:</b></td><td><i>" << dane[1] << "</i></td></tr>" << endl;
				cout << "<tr><td><b>Wiek:</b></td><td><i>" << dane[2] << "</i></td></tr>" << endl;
				cout << "</table>" << endl;
				znaleziony = 1;
        			}
			}
		}
		while (!plik.eof());
		plik.close();
		// gdy nie znaleziono oosoby odpowiadającej parametrowi wyszukiwania
		if (!znaleziony)
		{
			cout << "Szukana osoba " << query << " nie została znaleziona w bazie" << endl;
		}
	}
	// zamknięcie znaczników dokumentu
	cout << foot;
}

Z góry dziękuję za wszelką okazaną pomoc.

Paweł