/*
##--------------------------------------------------------------------------
##
## Copyright (c) 2001 Gerald Richter / ecos gmbh www.ecos.de
##
## You may distribute under the terms of either the GNU General Public
## License or the Artistic License, as specified in the Perl README file.
##
## THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED
## WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
## MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
## $Id: mod_aimproxy.c,v 1.1 2001/08/13 06:26:24 richter Exp $
##
##--------------------------------------------------------------------------
*/
#include "httpd.h"
#include "http_config.h"
#include "http_core.h"
#include "http_request.h"
#include "util_md5.h"
static void *aimproxySrvConfig(pool *p, char *d) ;
static const char * aimproxyCmdCacheDir(cmd_parms *cmd, void *config, char *val) ;
static const char * aimproxyCmdProxyPass(cmd_parms *cmd, void *config, char *val1, char * val2) ;
static int aimproxyHandler (request_rec *r) ;
/* the table of commands we provide */
static const command_rec command_table[] = {
{ "AIMCacheDir", aimproxyCmdCacheDir, NULL, RSRC_CONF, TAKE1,
"Gives the cache directory for Apache::ImageMagick Proxy" },
{ "AIMProxyPassTo", aimproxyCmdProxyPass, NULL, RSRC_CONF, TAKE2,
"Gives the destination host for images not cached" },
};
/* the main config structure */
module MODULE_VAR_EXPORT aimproxy_module = {
STANDARD_MODULE_STUFF,
NULL, /* module initializer */
NULL, /* create per-dir config structures */
NULL, /* merge per-dir config structures */
aimproxySrvConfig, /* create per-server config structures */
NULL, /* merge per-server config structures */
command_table, /* 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 */
aimproxyHandler, /* [#7] pre-run fixups */
NULL, /* [#9] log a transaction */
NULL, /* [#2] header parser */
NULL, /* child_init */
NULL, /* child_exit */
NULL /* [#0] post read-request */
};
struct aimconfig
{
char * cachedir ;
array_header * pass ;
} ;
struct aimpass
{
char * proxysrc ;
int proxysrclen ;
char * proxyhost ;
} ;
typedef struct aimconfig aimconfig ;
typedef struct aimpass aimpass ;
static int aimproxyHandler (request_rec *r)
{
char * args ;
char * path_info ;
char * file ;
char * uri ;
char * md5 ;
char * ext ;
char * cachefn ;
char * cachedir ;
char * cachepath ;
aimconfig * c ;
struct stat finfo ;
int i, len;
int n ;
aimpass *ent ;
int found = 0 ;
char * proxyhost ;
if (r->proxyreq != NOT_PROXY)
{ /* someone has already set up the proxy */
return DECLINED ;
}
c = (aimconfig *) ap_get_module_config(r->server->module_config, &aimproxy_module);
ent = (aimpass *) c->pass->elts;
uri = r -> uri ;
n = c -> pass -> nelts ;
for (i = 0; i < n; i++)
{
if (strncmp (uri, ent[i].proxysrc, ent[i].proxysrclen) == 0)
{
/*fprintf(stderr, "found %s -> %s\n" , ent[i].proxysrc, ent[i].proxyhost) ;*/
found = 1 ;
break ;
}
}
if (!found)
{
/*fprintf(stderr, "aimproxy not found %s\n" , uri) ;*/
return DECLINED ; /* is not our request */
}
proxyhost = ent[i].proxyhost ;
args = r -> args ;
path_info = r -> path_info ;
/* If the file exists and there are no transformation arguments
just decline the transaction. It will be handled as usual. */
/*fprintf(stderr, "uri %s args %s path_info %s\n" , uri, args, path_info) ;*/
/*fprintf(stderr, "r -> finfo.st_mode %d\n" , r -> finfo.st_mode) ;*/
if ((!args || !*args) && (!path_info || !*path_info) && r -> finfo.st_mode)
return DECLINED ;
/* calculate name of cache file */
file = r->filename;
md5 = ap_md5 (r -> pool, ap_pstrcat (r -> pool, uri, args, NULL)) ;
ext = strchr (file, '.') ;
if (ext)
ext++ ;
else
ext = "" ;
cachefn = ap_pstrcat (r -> pool, md5, ".", ext, NULL) ;
/*fprintf(stderr, "cachefn = %s\n" , cachefn) ;*/
cachedir = c -> cachedir ;
cachepath = ap_pstrcat (r -> pool, cachedir, "/", cachefn, NULL) ;
/*fprintf(stderr, "cachepath = %s\n" , cachepath) ;*/
if (stat (cachepath, &finfo) == 0)
{ /* let apache do the rest if image already exists */
r -> filename = cachepath ;
r -> path_info = "" ;
memcpy (&r -> finfo, &finfo, sizeof (r -> finfo)) ;
return OK ;
}
/* otherwise send it to the backend */
r->filename = ap_pstrcat(r->pool, "proxy:http://", proxyhost, r-> uri, NULL);
r->handler = "proxy-server";
r->proxyreq = PROXY_PASS;
/*fprintf(stderr, "proxy to = %s\n" , r->filename) ;*/
return OK;
}
static void *aimproxySrvConfig(pool *p, char *d)
{
aimconfig *rec = (aimconfig *) ap_pcalloc(p, sizeof(aimconfig));
memset (rec, 0, sizeof(aimconfig)) ;
rec->pass = ap_make_array(p, 10, sizeof(aimpass));
return rec;
}
static const char * aimproxyCmdCacheDir(cmd_parms *cmd, void *config, char *val)
{
server_rec *s = cmd->server;
aimconfig * c = (aimconfig *) ap_get_module_config(s->module_config, &aimproxy_module);
c -> cachedir = val ;
return NULL;
}
static const char * aimproxyCmdProxyPass(cmd_parms *cmd, void *config, char *val1, char * val2)
{
server_rec *s = cmd->server;
aimconfig * c = (aimconfig *) ap_get_module_config(s->module_config, &aimproxy_module);
aimpass * p = (aimpass *)ap_push_array(c->pass);
p -> proxyhost = val2 ;
p -> proxysrc = val1 ;
p -> proxysrclen = strlen (p -> proxysrc) ;
return NULL;
}