/* * Copyright 1995, 1998 Perforce Software. * * This file is part of WebKeeper, a perforce client apache module. * * License is hereby granted to use this software and distribute it * freely, as long as this copyright notice is retained and modifications * are clearly marked. * * ALL WARRANTIES ARE HEREBY DISCLAIMED. * * $Id: //public/perforce/webkeeper/mod_webkeep.c#1 $ */ /* * mod_webkeep.c: the apache side glue (in C) to the Perforce client * * This module by Perforce Software, from a template by the Apache Group. */ #include "httpd.h" #include "http_config.h" #include "ap_compat.h" #include "mod_webkeep.h" typedef struct { char *real; char *fake; } alias_entry; typedef struct { array_header *aliases; WebKeepConnect p4; } alias_server_conf; module webkeep; static void *create_webkeep_config (pool *p, server_rec *s) { alias_server_conf *a; a = (alias_server_conf *)pcalloc (p, sizeof(alias_server_conf)); a->aliases = make_array (p, 20, sizeof(alias_entry)); a->p4.port = 0; a->p4.user = 0; a->p4.pass = 0; a->p4.client = 0; return a; } static void *merge_webkeep_config (pool *p, void *basev, void *overridesv) { alias_server_conf *a, *b, *o; a = (alias_server_conf *)pcalloc (p, sizeof(alias_server_conf)); b = (alias_server_conf *)basev; o = (alias_server_conf *)overridesv; a->aliases = append_arrays (p, o->aliases, b->aliases); a->p4.port = o->p4.port ? o->p4.port : a->p4.port ? a->p4.port : b->p4.port; a->p4.user = o->p4.user ? o->p4.user : a->p4.user ? a->p4.user : b->p4.user; a->p4.pass = o->p4.pass ? o->p4.pass : a->p4.pass ? a->p4.pass : b->p4.pass; a->p4.client = o->p4.client ? o->p4.client : a->p4.client ? a->p4.client : b->p4.client; return a; } static const char *add_webkeep(cmd_parms *cmd, void *dummy, char *f, char *r) { server_rec *s = cmd->server; alias_server_conf *conf; alias_entry *new; conf = (alias_server_conf *) get_module_config(s->module_config,&webkeep); new = push_array (conf->aliases); /* XX r can NOT be relative to DocumentRoot here... compat bug. */ new->fake = f; new->real = r; return NULL; } static const char *port_webkeep(cmd_parms *cmd, void *d, char *f) { server_rec *s = cmd->server; alias_server_conf *conf; conf = (alias_server_conf *) get_module_config(s->module_config,&webkeep); conf->p4.port = f; return NULL; } static const char *user_webkeep(cmd_parms *cmd, void *d, char *f) { server_rec *s = cmd->server; alias_server_conf *conf; conf = (alias_server_conf *) get_module_config(s->module_config,&webkeep); conf->p4.user = f; return NULL; } static const char *passwd_webkeep(cmd_parms *cmd, void *d, char *f) { server_rec *s = cmd->server; alias_server_conf *conf; conf = (alias_server_conf *) get_module_config(s->module_config,&webkeep); conf->p4.pass = f; return NULL; } static const char *client_webkeep(cmd_parms *cmd, void *d, char *f) { server_rec *s = cmd->server; alias_server_conf *conf; conf = (alias_server_conf *) get_module_config(s->module_config,&webkeep); conf->p4.client = f; return NULL; } static command_rec alias_cmds[] = { { "WebKeepAlias", add_webkeep, NULL, RSRC_CONF, TAKE2, "a fakename and a depot name"}, { "WebKeepPort", port_webkeep, NULL, RSRC_CONF, TAKE1, "a TCP/IP host:port"}, { "WebKeepUser", user_webkeep, NULL, RSRC_CONF, TAKE1, "a Perforce user name"}, { "WebKeepPasswd", passwd_webkeep, NULL, RSRC_CONF, TAKE1, "a Perforce user password"}, { "WebKeepClient", client_webkeep, NULL, RSRC_CONF, TAKE1, "a Perforce client name"}, { NULL } }; static int alias_matches (char *uri, char *alias_fakename) { char *end_fakename = alias_fakename + strlen (alias_fakename); char *aliasp = alias_fakename, *urip = uri; while (aliasp < end_fakename) { if (*aliasp == '/') { /* any number of '/' in the alias matches any number in * the supplied URI, but there must be at least one... */ if (*urip != '/') return 0; while (*aliasp == '/') ++ aliasp; while (*urip == '/') ++ urip; } else if ( aliasp == end_fakename - 1 && *aliasp == '$') { /* a $ at the end of the fakename means it must match * the IRI exactly: i.e. no initial substring match. */ if (*urip != 0) return 0; ++ aliasp; } else { /* Other characters are compared literally */ if (*urip++ != *aliasp++) return 0; } } /* Check last alias path component matched all the way */ if (aliasp[-1] != '/' && *urip != '\0' && *urip != '/') return 0; /* Return number of characters from URI which matched (may be * greater than length of alias, since we may have matched * doubled slashes) */ return urip - uri; } static int translate_webkeep(request_rec *r) { int i; void *sconf; alias_server_conf *conf; alias_entry *entries; if (r->uri[0] != '/' && r->uri[0] != '\0') return BAD_REQUEST; sconf = r->server->module_config; conf = (alias_server_conf *)get_module_config(sconf, &webkeep); entries = (alias_entry *)conf->aliases->elts; for (i = 0; i < conf->aliases->nelts; ++i) { alias_entry *p = &entries[i]; int l = alias_matches (r->uri, p->fake); if (l > 0) { /* * We stash this under webkeep-path, instead of r->filename, * because (a) we have to communicate to our handle_webkeep * that this is one of ours and (b) because filename gets * mangled by the access checking code. There must be a * way around this, but it is buried in the minds of the * apache writers. */ table_set( r->notes, "webkeep-path", pstrcat(r->pool, p->real, r->uri + l, NULL) ); return OK; } } return DECLINED; } /* Webkeeper glue */ /* * Expected protocol: * * Success: * data block with filename/type * one or more text blocks * * Error: * error block */ void webKeepData( WebKeepPrinter *printer, int isBinary ) { request_rec *r = (request_rec *)printer->closure; if( !r->content_type && isBinary ) r->content_type = "application/octet-stream"; /* Now that we've seen the header, we clear the status */ printer->status = OK; send_http_header( r ); } void webKeepError( WebKeepPrinter *printer, char *buf ) { request_rec *r = (request_rec *)printer->closure; log_reason(buf, r->uri, r); printer->status = NOT_FOUND; } void webKeepText( WebKeepPrinter *printer, char *buf, int len ) { request_rec *r = (request_rec *)printer->closure; while( len-- ) rputc( *buf++, r ); } /* The formal handler... */ static int handle_webkeep (request_rec *r) { void *sconf; alias_server_conf *conf; WebKeepPrinter printer; char *depotPath; /* For us? */ if (r->method_number != M_GET) return DECLINED; if (!( depotPath = table_get(r->notes, "webkeep-path") ) ) return DECLINED; /* The mulberry bush. */ sconf = r->server->module_config; conf = (alias_server_conf *)get_module_config(sconf, &webkeep); /* Start off with NOT_FOUND; cleared once we get the data block */ printer.status = NOT_FOUND; printer.closure = (void *)r; printer.data = webKeepData; printer.text = webKeepText; printer.error = webKeepError; webKeepPrint( &conf->p4, depotPath, &printer ); return printer.status; } handler_rec webkeep_handlers[] = { { "*/*", handle_webkeep }, { NULL } }; module webkeep = { STANDARD_MODULE_STUFF, NULL, /* initializer */ NULL, /* dir config creater */ NULL, /* dir merger --- default is to override */ create_webkeep_config, /* server config */ merge_webkeep_config, /* merge server configs */ alias_cmds, /* command table */ webkeep_handlers, /* handlers */ translate_webkeep, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ NULL /* logger */ };
# | Change | User | Description | Committed | |
---|---|---|---|---|---|
#7 | 809 | Stephen Vance | Take mainline changes back to my guest branch. | ||
#6 | 803 | Stephen Vance |
Update to Apache 1.3 API. Eliminate compilation warning. Add WebKeepDirectoryIndex. |
||
#5 | 766 | Stephen Vance | Add WebKeepSync to configuration directives, allowing a local workspace to be sync'ed based on the web request and letting the normal Apache mechanisms do the rest. | ||
#4 | 765 | Stephen Vance | One set of source updates. | ||
#3 | 730 | Stephen Vance |
Update so that everything builds smoothly in both loadable and static configs while still following the Apache conventions exactly. Update documentation to show how to load the module in the httpd.conf. |
||
#2 | 634 | Stephen Vance | Add tested platforms and update for DSO builds. | ||
#1 | 603 | Stephen Vance |
First public checkin of Webkeeper updated for Apache 1.3.X. Tested on FreeBSD 3.5 and Red Hat Linux 6.2 and 7.0. |