/*
	ZazouMiniWebServer

	Copyright (C) 2003-2011 Xavier Garreau <xavier@xgarreau.org>

	This file is part of ZazouMiniWebServer.

    ZazouMiniWebServer is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    ZazouMiniWebServer 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 ZazouMiniWebServer; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
	
// ZMWS.h: interface for the ZMWS class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_ZMWS_H__FC202BD8_1D8E_4297_832B_555AB1649B9E__INCLUDED_)
#define AFX_ZMWS_H__FC202BD8_1D8E_4297_832B_555AB1649B9E__INCLUDED_

#include "ZOSAL.h"
#include "ZMWSCommon.h"
#include "ZMWSConfig.h"
#include "ZMWSmime.h"
#include "ZMWSFileUtils.h"
#include "ZMWSHTTPUtils.h"
#include "ZMWSReqResp.h"
#include "../ZazouModSsl/ZazouModSsl.h"

typedef std::map<std::string, std::string> REQVARS;
typedef std::map<std::string, std::string> RESPVARS;
typedef std::pair<std::string, std::string> REQVAR;

class ZMWS;

typedef struct _QUEUECLIENTPARAM {
	ZMWS* object;
	SOCKET clientSocket;
	DWORD tinit;
	ZazouModData_t modssl_data;
} QUEUECLIENTPARAM;

class ZMWS  
{
protected:
	UINT ZMWSSTOPMESSAGE;
	HMODULE ZazouModSslHandle;
	ZazouModSslLoad_t ZazouModSslLoad;
	ZazouModSsl_Functions modssl_functions;

	WSADATA wsaData;
	std::string serverVersion;
	std::string serverIPs;
	HANDLE_THREAD serverThread;
	SOCKET serverSocket;
	SOCKET secureServerSocket;
	volatile BOOL ServerStop;
	
	HANDLE_MUTEX ZMWS_SERVERSTOP_MUTEX;
	HANDLE_MUTEX ZMWS_NBCLIENTS_MUTEX;

	ZMWSConfig serverConfig;
	ZMWSMIME MIME_Manager;
	ZMWSHTTPUtils HTTP_Utils;

	static volatile DWORD nbClients;

	ZMWS();

public:
	static ZMWS& GetInstance();
	virtual ~ZMWS();

	BOOL StartServer(int argc, char** argv);
	void StopServer(BOOL postMessage = FALSE);
	void ShutdownServer(unsigned short port = 80);
	void WaitForShutDown();
	BOOL Configure(const char* config_file_path);
	void GetConfig(CBaseZMWSConfig* zbc);
	void FreeConfig (CBaseZMWSConfig* zbc);
	void BrowseNow();
	const char* GetVersion () { return serverVersion.c_str(); }
	const char* GetIPs () { return serverIPs.c_str(); }

protected:
	std::string ZMWS::CreateIPList ();
	BOOL CreateServerSockets ();
	void HandleClient (QUEUECLIENTPARAM* qcp);
	int  HandleRequest (ZMWSReqResp* RR, const SOCKET& clientSocket);
	int  Reply ( ZMWSReqResp& rr);
	BOOL SendHeaders (ZMWSReqResp& rr, BOOL EndHeaders = TRUE);
	void AddRespVars (ZMWSReqResp& rr, std::stringstream& Response);
	LPCTSTR SetupCgiEnvironment (ZMWSReqResp& rr);
	int StartPHP (ZMWSReqResp& rr);
	int StartHandler (ZMWSReqResp& rr);
	int StartZMWSSAPIHandler(ZMWSReqResp& rr);
	int LogRequest (ZMWSReqResp& rr);

	int LogSentBytes (ZMWSReqResp& rr);
	int CheckSentBytesOK (ZMWSReqResp& rr);
	BOOL CheckClientIPOK (ZMWSReqResp& rr);
	BOOL CheckClientIPDenied (ZMWSReqResp& rr);

	int GetStartPage (ZMWSReqResp& rr, ZMWSFileUtils& indexZFU);
	int FindLocalFile (ZMWSReqResp& rr, std::string FilePath);
	BOOL FindWithMultiview (ZMWSReqResp& rr, std::string FilePath);
	BOOL FindWithLangNegotiation (ZMWSReqResp& rr, std::string FilePath);
	int GetLocalFile (ZMWSReqResp& rr);
	int SendFile (ZMWSReqResp& rr);
	int SendChunk (ZMWSReqResp& rr, void* chunk, const DWORD& chunksize, const BOOL is_header = FALSE);

	void DefaultErrorMessage ( ZMWSReqResp& rr );
	void Redirect (ZMWSReqResp& rr, const std::string& newUrl);
	int SendDirListing (ZMWSReqResp& rr);
	int SendRSSDirListing (ZMWSReqResp& rr);
	int SendXMLDirListing (ZMWSReqResp& rr);
	void CloseBrowser (ZMWSReqResp& rr);

	// realms, users, ...
	BOOL FindAuthFile (ZMWSReqResp& rr);
	BOOL AuthenticateUser (ZMWSReqResp& rr);
	void SendAuthChallenge (ZMWSReqResp& rr);

	// Client Cache
	BOOL LocalFileIsMoreRecentThanClientCache (ZMWSReqResp& rr);


	BOOL WaitForInputOnSocket (const SOCKET& clientSocket) const;

	std::string GetResponseLine (const HANDLE_FILE& h) const;
	ZMWSReqResp* GetRequestLines (ZMWSReqResp* RR);
	ZMWSReqResp* InitializeRR (const SOCKET& clientSocket);
	void ParseRequestLine (std::string& RequestLine, ZMWSReqResp* RR) const;
	void ParseHeaderLine (std::string& HeaderLine, ZMWSReqResp* RR) const;

	void HideConsole ();
	UINT MainThread ();
	
#ifdef WIN32
	static void __cdecl Run (LPVOID param);
	static void __cdecl QueueClient (LPVOID param);
#else
	static void Run (LPVOID param);
	static void QueueClient (LPVOID param);
#endif
};

#endif // !defined(AFX_ZMWS_H__FC202BD8_1D8E_4297_832B_555AB1649B9E__INCLUDED_)
