/*
Reveal the order in which things are done.

Copyright (C) 1996, 1998 Ben Laurie
*/


#include "httpd.h"
#include "http_config.h"
#include "http_protocol.h"
#include "http_request.h" [2.0]
#include "apr_strings.h" [2.0]
#include "http_connection.h" [2.0]
#include "http_log.h" [2.0]
#include "http_core.h" [2.0]
#include "scoreboard.h" [2.0]
#include <unistd.h> [2.0]


typedef struct
    {
    char *szDir;
    char *szTag;
    } SPerDir;


typedef struct
    {
    char *szServer;
    char *szTag;
    } SPerServer;


extern module reveal_module;

static const char *None(const char *szStr)
    {
    if(szStr)
    return szStr;
    return "(none)";
    }

static void SubRevealInit(server_rec *pServer,pool *pPool)
    {
    SPerServer *pPerServer=ap_get_module_config(pServer->module_config,
                                                &amp;reveal_module);

    if(pServer->server_hostname &amp;&amp;
       (!strncmp(pPerServer->szServer,"(none):",7)
        || !strcmp(pPerServer->szServer+strlen(pPerServer->szServer)
                   -2,":0")))
    {
        char szPort[20];

        fprintf(stderr,"Init        : update server name from %s\n",
                pPerServer->szServer);
        sprintf(szPort,"%d",pServer->port);
        pPerServer->szServer=ap_pstrcat(pPool,pServer->server_hostname,":",
                                        szPort,NULL);
    }
    fprintf(stderr,"Init        : host=%s port=%d server=%s tag=%s\n",
            pServer->server_hostname,pServer->port,pPerServer->szServer,
            None(pPerServer->szTag));
    }

static void RevealInit(server_rec *pServer,pool *pPool)
    {
    ap_add_version_component("Reveal/0.0");
    for( ; pServer ; pServer=pServer->next)
        SubRevealInit(pServer,pPool);
    fprintf(stderr,"Init        : done\n");
    }


static void *RevealCreateServer(pool *pPool,server_rec *pServer)
    {
    SPerServer *pPerServer=ap_palloc(pPool,sizeof *pPerServer);
    const char *szServer;
    char szPort[20];

    szServer=None(pServer->server_hostname);
    sprintf(szPort,"%d",pServer->port);

    pPerServer->szTag=NULL;
    pPerServer->szServer=ap_pstrcat(pPool,szServer,":",szPort,NULL);

    fprintf(stderr,"CreateServer: server=%s:%s\n",szServer,szPort);
    return pPerServer;
    }


static void *RevealMergeServer(pool *pPool,void *_pBase,void *_pNew)
    {
    SPerServer *pBase=_pBase;
    SPerServer *pNew=_pNew;
    SPerServer *pMerged=ap_palloc(pPool,sizeof *pMerged);

    fprintf(stderr,
          "MergeServer : pBase: server=%s tag=%s pNew: server=%s tag=%s\n",
          pBase->szServer,None(pBase->szTag),
          pNew->szServer,None(pNew->szTag));

    pMerged->szServer=ap_pstrcat(pPool,pBase->szServer,"+",pNew->szServer,
                                 NULL);
    pMerged->szTag=ap_pstrcat(pPool,None(pBase->szTag),"+",
                              None(pNew->szTag),NULL);

    return pMerged;
    }


static void *RevealCreateDir(pool *pPool,char *_szDir)
    {
    SPerDir *pPerDir=ap_palloc(pPool,sizeof *pPerDir);
    const char *szDir=None(_szDir);

    fprintf(stderr,"CreateDir   : dir=%s\n",szDir);

    pPerDir->szDir=ap_pstrdup(pPool,szDir);
    pPerDir->szTag=NULL;

    return pPerDir;
    }


static void *RevealMergeDir(pool *pPool,void *_pBase,void *_pNew)
    {
    SPerDir *pBase=_pBase;
    SPerDir *pNew=_pNew;
    SPerDir *pMerged=ap_palloc(pPool,sizeof *pMerged);

    fprintf(stderr,"MergeDir    : pBase: dir=%s tag=%s "
            "pNew: dir=%s tag=%s\n",pBase->szDir,None(pBase->szTag),
            pNew->szDir,None(pNew->szTag));
    pMerged->szDir=ap_pstrcat(pPool,pBase->szDir,"+",pNew->szDir,NULL);
    pMerged->szTag=ap_pstrcat(pPool,None(pBase->szTag),"+",
                              None(pNew->szTag),NULL);

    return pMerged;
    }


static void ShowRequestStuff(request_rec *pReq)
    {
    SPerDir *pPerDir=ap_get_module_config(pReq->per_dir_config,
               &amp;reveal_module); [1.3]
    SPerDir *pPerDir=pReq->per_dir_config ?
      ap_get_module_config(pReq->per_dir_config,&amp;reveal_module) : NULL; [2.0]
    SPerServer *pPerServer=ap_get_module_config(pReq->server->
               module_config,&amp;reveal_module);
    SPerDir none={"(null)","(null)"};
    SPerDir noconf={"(no per-dir config)","(no per-dir config)"};

    if(!pReq->per_dir_config)
        pPerDir=&amp;noconf;
    else if(!pPerDir)
        pPerDir=&amp;none;

    fprintf(stderr," server=%s tag=%s dir=%s tag=%s\n",
            pPerServer->szServer,pPerServer->szTag,pPerDir->szDir,
               pPerDir->szTag);
    }


static int RevealTranslate(request_rec *pReq)
    {
    fprintf(stderr,"Translate   : uri=%s",pReq->uri);
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealCheckUserID(request_rec *pReq)
    {
    fprintf(stderr,"CheckUserID :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealCheckAuth(request_rec *pReq)
    {
    fprintf(stderr,"CheckAuth   :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealCheckAccess(request_rec *pReq)
    {
    fprintf(stderr,"CheckAccess :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealTypeChecker(request_rec *pReq)
    {
    fprintf(stderr,"TypeChecker :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealFixups(request_rec *pReq)
    {
    fprintf(stderr,"Fixups      :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealLogger(request_rec *pReq)
    {
    fprintf(stderr,"Logger      :");
    ShowRequestStuff(pReq);
    return DECLINED;
    }

static int RevealHeaderParser(request_rec *pReq)
    {
    fprintf(stderr,"HeaderParser:");
    ShowRequestStuff(pReq);

    return DECLINED;
    }


static void RevealChildInit(server_rec *pServer, pool *pPool)
    {
    char szPID[20];

    fprintf(stderr,"Child Init  : pid=%d\n",(int)getpid( ));

    sprintf(szPID,"[%d]",(int)getpid( ));
    for( ; pServer ; pServer=pServer->next)
        {
        SPerServer *pPerServer=ap_get_module_config(pServer->module_config,
                                                    &amp;reveal_module);
        pPerServer->szServer=ap_pstrcat(pPool,pPerServer->szServer,szPID,
                                        NULL);
        }
    apr_pool_cleanup_register(pPool,pServer,RevealChildExit,RevealChildExit);[2.0]
    }


(1.3)
static void RevealChildExit(server_rec *pServer, pool *pPool)
    {
    fprintf(stderr,"Child Exit  : pid=%d\n",(int)getpid( ));
    }
(2.0)
static apr_status_t RevealChildExit(void *p)
    {
    fprintf(stderr,"Child Exit  : pid=%d\n",(int)getpid( ));

    return OK;
    }

static int RevealPostReadRequest(request_rec *pReq)
    {
    fprintf(stderr,"PostReadReq : method=%s uri=%s protocol=%s",
            pReq->method,pReq->unparsed_uri,pReq->protocol);
    ShowRequestStuff(pReq);

    return DECLINED;
    }


static const char *RevealTag(cmd_parms *cmd, SPerDir *pPerDir, char *arg)
    {
    SPerServer *pPerServer=ap_get_module_config(cmd->server->module_config,
                                                &amp;reveal_module);

    fprintf(stderr,"Tag         : new=%s dir=%s server=%s tag=%s\n",
            arg,pPerDir->szDir,pPerServer->szServer,
            None(pPerServer->szTag));

    if(pPerDir->szTag)
        pPerDir->szTag=ap_pstrcat(cmd->pool,pPerDir->szTag,"-",arg,NULL);
    else
        pPerDir->szTag=ap_pstrdup(cmd->pool,arg);

    return NULL;
    }


static const char *RevealServerTag(cmd_parms *cmd, SPerDir *pPerDir,
                                   char *arg)
    {
    SPerServer *pPerServer=ap_get_module_config(cmd->server->module_config,
                                                &amp;reveal_module);

    fprintf(stderr,"ServerTag   : new=%s server=%s stag=%s\n",arg,
            pPerServer->szServer,None(pPerServer->szTag));

    if(pPerServer->szTag)
        pPerServer->szTag=ap_pstrcat(cmd->pool,pPerServer->szTag,"-",arg,
                                     NULL);
    else
        pPerServer->szTag=ap_pstrdup(cmd->pool,arg);

    return NULL;
    }


(1.3)static command_rec aCommands[]=
    {
{ "RevealTag", RevealTag, NULL, ACCESS_CONF|OR_ALL, TAKE1, "a tag for this
    section"},
{ "RevealServerTag", RevealServerTag, NULL, RSRC_CONF, TAKE1, "a tag for this
    server" },
{ NULL }
    };
(2.0)static command_rec aCommands[]=
    {
    AP_INIT_TAKE1("RevealTag", RevealTag, NULL, ACCESS_CONF|OR_ALL,
                  "a tag for this section"),
    AP_INIT_TAKE1("RevealServerTag", RevealServerTag, NULL, RSRC_CONF,
                  "a tag for this server" ),
    { NULL }
    };


static void TShow(request_rec *pReq,const char *szHead,const char *szItem)
    {
    ap_rprintf(pReq,"<TR><TH>%s<TD>%s\n",szHead,szItem);
    }

static void TShowN(request_rec *pReq,const char *szHead,int nItem)
    {
    ap_rprintf(pReq,"<TR><TH>%s<TD>%d\n",szHead,nItem);
    }

static int RevealHandler(request_rec *pReq)
    {
    SPerDir *pPerDir=ap_get_module_config(pReq->per_dir_config,
               &amp;reveal_module);
    SPerServer *pPerServer=ap_get_module_config(pReq->server->
               module_config,&amp;reveal_module);

    pReq->content_type="text/html";
    ap_send_http_header(pReq);

    ap_rputs("<CENTER><H1>Revelation of ",pReq);
    ap_rputs(pReq->uri,pReq);
    ap_rputs("</H1></CENTER><HR>\n",pReq);
    ap_rputs("<TABLE>\n",pReq);
    TShow(pReq,"URI",pReq->uri);
    TShow(pReq,"Filename",pReq->filename);
    TShow(pReq,"Server name",pReq->server->server_hostname);
    TShowN(pReq,"Server port",pReq->server->port);
    TShow(pReq,"Server config",pPerServer->szServer);
    TShow(pReq,"Server config tag",pPerServer->szTag);
    TShow(pReq,"Directory config",pPerDir->szDir);
    TShow(pReq,"Directory config tag",pPerDir->szTag);
    ap_rputs("</TABLE>\n",pReq);

    return OK;
    }


static handler_rec aHandlers[]=
    {
{ "reveal", RevealHandler },
{ NULL },
    };

module reveal_module = {
   STANDARD_MODULE_STUFF,
   RevealInit,                  /* initializer */
   RevealCreateDir,             /* dir config creater */
   RevealMergeDir,              /* dir merger --- default is to override */
   RevealCreateServer,          /* server config */
   RevealMergeServer,           /* merge server configs */
   aCommands,                   /* command table */
   aHandlers,                   /* handlers */
   RevealTranslate,             /* filename translation */
   RevealCheckUserID,           /* check_user_id */
   RevealCheckAuth,             /* check auth */
   RevealCheckAccess,           /* check access */
   RevealTypeChecker,           /* type_checker */
   RevealFixups,                /* fixups */
   RevealLogger,                /* logger */
   RevealHeaderParser,          /* header parser */
   RevealChildInit,             /* child init */
   RevealChildExit,             /* child exit */
   RevealPostReadRequest,       /* post read request */
};

static void RegisterHooks(apr_pool_t *pPool)
    {
    ap_hook_post_config(RevealInit,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_handler(RevealHandler,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_translate_name(RevealTranslate,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_check_user_id(RevealCheckUserID,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_auth_checker(RevealCheckAuth,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_access_checker(RevealCheckAccess,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_type_checker(RevealTypeChecker,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_fixups(RevealFixups,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_log_transaction(RevealLogger,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_header_parser(RevealHeaderParser,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_child_init(RevealChildInit,NULL,NULL,APR_HOOK_MIDDLE);
    ap_hook_post_read_request(RevealPostReadRequest,NULL,NULL,APR_HOOK_MIDDLE);
    }

 module reveal_module = {
   STANDARD20_MODULE_STUFF,
   RevealCreateDir,             /* dir config creater */
   RevealMergeDir,              /* dir merger --- default is to override */
   RevealCreateServer,          /* server config */
   RevealMergeServer,           /* merge server configs */
   aCommands,                   /* command table */
   RegisterHooks		/* hook registration */
};

