#include "httpd.h"     
#include "http_config.h"     
#include "http_request.h"     
#include "http_protocol.h"     
#include "http_core.h"     
#include "http_main.h"    
#include "http_log.h"     
  
/*    
 * C version of chapter 7's Apache::LogMail
 */    

/*
 * configure like so:
 * LoadModule logmail_module modules/mod_logmail.so 
 * <Location /~dougm>
 * LogMailTo dougm@pobox.com 
 * LogMailPattern \.(html|txt)$ 
 * </Location>
 *
 */

module MODULE_VAR_EXPORT logmail_module;

typedef struct {
    char *mailto;
    regex_t *pattern;
} logmail_dir_config;

static void *logmail_create_dir_config(pool *p, char *path)  
{  
    logmail_dir_config *dcfg =   
        (logmail_dir_config *)ap_pcalloc(p, sizeof(*dcfg));  
 
    dcfg->mailto = NULL;
    dcfg->pattern = NULL;

    return (void *)dcfg;  
}  

static void *logmail_merge_dir_config(pool *p, void *base, void *new) 
{
    logmail_dir_config *merged = 
	(logmail_dir_config *)ap_pcalloc(p, sizeof(*merged)); 
    logmail_dir_config *parent = (logmail_dir_config *)base; 
    logmail_dir_config *child  = (logmail_dir_config *)new; 
 
    merged->mailto = child->mailto ?  
	child->mailto : parent->mailto; 

    merged->pattern = child->pattern ?  
	child->pattern : parent->pattern; 

    return (void*)merged; 
}

static const char *logmail_pattern_cmd(cmd_parms *parms, void *mconfig, const char *arg)  
{ 
    logmail_dir_config *dcfg = (logmail_dir_config *)mconfig; 
    dcfg->pattern = ap_pregcomp(parms->pool, arg, REG_EXTENDED|REG_NOSUB); 
    return NULL;
}

#define SENDMAIL_CMD "/usr/lib/sendmail"
#define SENDMAIL_ARGS "-oi", "-t"

static int logmail_child(void *data, child_info *pinfo)
{ 
    ap_cleanup_for_exec();

#ifdef WIN32
    /*XXX*/
#else
    execl(SENDMAIL_CMD, SENDMAIL_CMD, SENDMAIL_ARGS, NULL);
#endif
    ap_log_error(APLOG_MARK, APLOG_ERR, NULL, "exec of %s failed", SENDMAIL_CMD); 
    exit(0);
    return(1);
}

#define LOGMAIL_DATEFMT "%a, %d %b %Y %H:%M:%S %Z"
static char *logmail_datestamp(request_rec *r) 
{ 
    return ap_ht_time(r->pool, r->request_time, LOGMAIL_DATEFMT, 0);
} 

static request_rec *last_r(request_rec *first)
{
    request_rec *r;
    /* make sure we use the last request of the internal chain
     * for most infos
     */
    for(r=first; r->next != NULL; r=r->next) { 
        continue;  
    } 

    return r;
}

static int logmail_handler(request_rec *first)
{
    request_rec *r = last_r(first); 
    logmail_dir_config *dcfg = (logmail_dir_config *) 
        ap_get_module_config(r->per_dir_config, &logmail_module); 
    char *mailto = dcfg->mailto;
    regex_t *pattern = dcfg->pattern;
    const char *remote_host;
    FILE *ioip=NULL, *ioop=NULL, *ioep=NULL;
    int rc;

    if (!(mailto && pattern)) {
	return DECLINED;
    }
    else {
	if (regexec(pattern, r->filename, 0, NULL, 0) != 0) {   
	    return DECLINED;
	}
    }

    rc = ap_spawn_child(r->pool, logmail_child, 
			(void *)r, kill_after_timeout, 
			&ioip, &ioop, &ioep); 

    if (rc == 0 || ioip == NULL) { 
	ap_log_error(APLOG_MARK, APLOG_ERR, r->server, 
		     "mod_logmail: could not fork child (rc=%d)", rc); 
	return HTTP_INTERNAL_SERVER_ERROR;
    } 

    remote_host = ap_get_remote_host(r->connection, 
				     r->per_dir_config, REMOTE_NAME);

    fprintf(ioip, "To: %s\nFrom: Apache httpd <%s>\nSubject: Somebody looked at %s\n\nAt %s, a user at %s looked at\n%s using the %s browser.\n\nThe request was %s,\nwhich resulted returned a code of %s.\n\n%ld bytes were transferred.",
	    mailto, r->server->server_admin ? r->server->server_admin : "webmaster", 
	    first->uri, logmail_datestamp(first), remote_host, first->uri, 
	    ap_table_get(r->headers_in, "User-Agent"),
	    first->the_request, r->status_line, r->bytes_sent);

    ap_pfclose(r->pool, ioip);
    return OK;
}

static command_rec logmail_cmds[] = { 
    { 
	"LogMailTo", 
	ap_set_string_slot, 
	(void *)XtOffsetOf(logmail_dir_config, mailto), 
	OR_ALL, 
	TAKE1, 
	"an email address",
    }, 
    { 
	"LogMailPattern", logmail_pattern_cmd,
	NULL, OR_ALL, TAKE1, 
	"pattern to match against uri",
    }, 
    { NULL },
};

module MODULE_VAR_EXPORT logmail_module = {
    STANDARD_MODULE_STUFF, 
    NULL,                  /* module initializer                  */
    logmail_create_dir_config, /* create per-dir    config structures */
    logmail_merge_dir_config, /* merge  per-dir    config structures */
    NULL,                  /* create per-server config structures */
    NULL,                  /* merge  per-server config structures */
    logmail_cmds,          /* table of config file commands       */
    NULL,                  /* [#8] MIME-typed-dispatched handlers */
    NULL,                  /* [#1] URI to filename translation    */
    NULL,                  /* [#4] validate user id from request  */
    NULL,                  /* [#5] check if the user is ok _here_ */
    NULL,                  /* [#3] check access by host address   */
    NULL,                  /* [#6] determine MIME type            */
    NULL,                  /* [#7] pre-run fixups                 */
    logmail_handler,       /* [#9] log a transaction              */
    NULL,                  /* [#2] header parser                  */
    NULL,                  /* child_init                          */
    NULL,                  /* child_exit                          */
    NULL                   /* [#0] post read-request              */
};

