blob: 43def46f4caab541227f885767d669b6eab78a78 [file] [log] [blame]
/* ====================================================================
* The Apache Software License, Version 1.1
*
* Copyright (c) 2000 The Apache Software Foundation. All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
*
* 3. The end-user documentation included with the redistribution,
* if any, must include the following acknowledgment:
* "This product includes software developed by the
* Apache Software Foundation (http://www.apache.org/)."
* Alternately, this acknowledgment may appear in the software itself,
* if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Apache" and "Apache Software Foundation" must
* not be used to endorse or promote products derived from this
* software without prior written permission. For written
* permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
* nor may "Apache" appear in their name, without prior written
* permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
* Portions of this software are based upon public domain software
* originally written at the National Center for Supercomputing Applications,
* University of Illinois, Urbana-Champaign.
*/
#include "mod_tcl.h"
extern Tcl_Interp *interp;
extern apr_array_header_t *fcache;
extern request_rec *_r;
extern char *current_namespace;
extern int read_post_ok;
const uint8_t base64[] = {
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
};
const uint8_t inv_base64[128] =
{
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 255, 255, 255, 255, 255,
255, 255, 255, 62, 255, 255, 255, 63,
52, 53, 54, 55, 56, 57, 58, 59,
60, 61, 255, 255, 255, 255, 255, 255,
255, 0, 1, 2, 3, 4, 5, 6,
7, 8, 9, 10, 11, 12, 13, 14,
15, 16, 17, 18, 19, 20, 21, 22,
23, 24, 25, 255, 255, 255, 255, 255,
255, 26, 27, 28, 29, 30, 31, 32,
33, 34, 35, 36, 37, 38, 39, 40,
41, 42, 43, 44, 45, 46, 47, 48,
49, 50, 51, 255, 255, 255, 255, 255,
};
static size_t is_base64_buf(uint8_t *buf, size_t buf_len)
{
size_t i;
for (i = 0; i < buf_len; i++) {
/* Accept equal sign. */
if (buf[i] == '=') {
continue;
}
/* Don't accept anything else which isn't in base64. */
if (buf[i] > 127) {
break;
}
if (inv_base64[buf[i]] == 255) {
break;
}
}
return i;
}
static uint8_t* buf_to_base64(const uint8_t *buf, size_t buf_len)
{
uint8_t *out;
size_t i, j;
uint32_t limb;
out = (uint8_t*) malloc(((buf_len * 8 + 5) / 6) + 5);
for (i = 0, j = 0, limb = 0; i + 2 < buf_len; i += 3, j += 4) {
limb =
((uint32_t) buf[i] << 16) |
((uint32_t) buf[i + 1] << 8) |
((uint32_t) buf[i + 2]);
out[j] = base64[(limb >> 18) & 63];
out[j + 1] = base64[(limb >> 12) & 63];
out[j + 2] = base64[(limb >> 6) & 63];
out[j + 3] = base64[(limb) & 63];
}
switch (buf_len - i) {
case 0:
break;
case 1:
limb = ((uint32_t) buf[i]);
out[j++] = base64[(limb >> 2) & 63];
out[j++] = base64[(limb << 4) & 63];
out[j++] = '=';
out[j++] = '=';
break;
case 2:
limb = ((uint32_t) buf[i] << 8) | ((uint32_t) buf[i + 1]);
out[j++] = base64[(limb >> 10) & 63];
out[j++] = base64[(limb >> 4) & 63];
out[j++] = base64[(limb << 2) & 63];
out[j++] = '=';
break;
default:
// something wonkey happened...
break;
}
out[j] = '\0';
return out;
}
static uint8_t* base64_to_buf(uint8_t *str, size_t *buf_len)
{
uint8_t *buf;
int i, j, len;
uint32_t limb;
len = strlen((char *) str);
*buf_len = (len * 6 + 7) / 8;
buf = (uint8_t*) malloc(*buf_len);
for (i = 0, j = 0, limb = 0; i + 3 < len; i += 4) {
if (str[i] == '=' || str[i + 1] == '=' || str[i + 2] == '=' || str[i + 3] == '=') {
if (str[i] == '=' || str[i + 1] == '=') {
break;
}
if (str[i + 2] == '=') {
limb =
((uint32_t) inv_base64[str[i]] << 6) |
((uint32_t) inv_base64[str[i + 1]]);
buf[j] = (uint8_t) (limb >> 4) & 0xff;
j++;
}
else {
limb =
((uint32_t) inv_base64[str[i]] << 12) |
((uint32_t) inv_base64[str[i + 1]] << 6) |
((uint32_t) inv_base64[str[i + 2]]);
buf[j] = (uint8_t) (limb >> 10) & 0xff;
buf[j + 1] = (uint8_t) (limb >> 2) & 0xff;
j += 2;
}
}
else {
limb =
((uint32_t) inv_base64[str[i]] << 18) |
((uint32_t) inv_base64[str[i + 1]] << 12) |
((uint32_t) inv_base64[str[i + 2]] << 6) |
((uint32_t) inv_base64[str[i + 3]]);
buf[j] = (uint8_t) (limb >> 16) & 0xff;
buf[j + 1] = (uint8_t) (limb >> 8) & 0xff;
buf[j + 2] = (uint8_t) (limb) & 0xff;
j += 3;
}
}
*buf_len = j;
return buf;
}
static uint8_t* base64_remove_whitespace(const uint8_t *str, size_t len)
{
uint8_t *cp;
size_t i, j;
if (len == 0) {
len = strlen((char *) str);
}
cp = (uint8_t*) malloc(len + 1);
for (i = 0, j = 0; i < len; i++) {
if (!(str[i] & 128)) {
if (inv_base64[str[i]] != 255 || str[i] == '=') {
cp[j++] = str[i];
}
}
}
cp[j] = '\0';
return cp;
}
static char* mstrstr(char *haystack, char *needle, size_t n, size_t m)
{
size_t i;
if (m >= n) {
if (!memcmp(haystack, needle, n)) {
return haystack;
}
else {
return NULL;
}
}
for (i = 0; (i + m) < n; i++, haystack++) {
if (!memcmp(haystack, needle, m)) {
return haystack;
}
}
return NULL;
}
static int read_post_data(request_rec *r, Tcl_Interp *interp, char *boundary)
{
int rc, lpos = 0, blen = strlen(boundary);
char *lbuf, *ptr;
long remaining;
if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
return rc;
}
remaining = r->remaining;
lbuf = (char*) apr_palloc(r->pool, remaining + 1);
if (ap_should_client_block(r)) {
char buf[HUGE_STRING_LEN];
int len_read;
// ap_hard_timeout("read_post_data", r);
while ((len_read = ap_get_client_block(r, buf, sizeof(buf))) > 0) {
// ap_reset_timeout(r);
memcpy(lbuf + lpos, buf, len_read);
lpos += len_read;
}
lbuf[lpos] = '\0';
// ap_kill_timeout(r);
}
ptr = strstr(lbuf, boundary);
remaining -= (ptr - lbuf - sizeof(char*));
lbuf = ptr;
while (1) {
int i, vlen;
char *key, *val, *filename, *eptr;
if (!ptr) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post_data(...): bad boundry condition in multipart/form-data");
return DECLINED;
}
if ((*(ptr + blen + 1) == '-') && (*(ptr + blen + 1) == '-')) {
return OK;
}
lbuf += (blen + 2);
remaining -= (blen + 2);
eptr = strstr(lbuf, "\r\n\r\n");
if (!eptr) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post_data(...): bad headers in multipart/form-data");
return DECLINED;
}
ptr = lbuf;
memset(eptr + 2, 0, 2);
remaining -= (eptr - lbuf - sizeof(char*));
lbuf = eptr + 4;
while (*ptr) {
char *xptr = ap_getword(r->pool, (const char**) &ptr, ' ');
if (!strcmp("Content-Disposition:", xptr)) {
xptr = strstr(ptr, "name=");
if (!xptr) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post_data(...): bad `Content-Disposition:' header");
return DECLINED;
}
xptr += 6;
for (i = 0; xptr[i] != '"'; i++) {
;
}
key = (char*) apr_palloc(r->pool, i + 1);
memcpy(key, xptr, i);
key[i] = '\0';
xptr = strstr(ptr, "filename=");
if (xptr) {
char *file_key, *file_val;
xptr += 10;
for (i = 0; xptr[i] != '"'; i++) {
;
}
file_val = (char*) apr_palloc(r->pool, i + 1);
memcpy(file_val, xptr, i);
file_val[i] = '\0';
file_key = apr_psprintf(r->pool, "%s_filename", key);
set_var2(interp, "::pram", file_key, file_val, i);
}
break;
}
ptr = strstr(ptr, "\r\n");
ptr += 2;
}
ptr = mstrstr(lbuf, boundary, remaining, blen);
vlen = (ptr - lbuf) - sizeof(char*);
if (vlen <= 0) {
val = (char*) malloc(1);
val[0] = '\0';
vlen = 0;
}
else {
val = (char*) malloc(vlen + 1);
memcpy(val, lbuf, vlen);
val[vlen] = '\0';
}
set_var2(interp, "::pram", key, val, vlen);
free(val);
lbuf = ptr;
remaining -= vlen;
}
return DECLINED;
}
static int read_post(request_rec *r, Tcl_Interp *interp)
{
int rc;
const char *val, *key;
char *rbuf;
if ((rc = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR)) != OK) {
return rc;
}
if (ap_should_client_block(r)) {
char buf[HUGE_STRING_LEN];
int rsize, len_read, rpos = 0;
long length = r->remaining;
rbuf = (char*) apr_pcalloc(r->pool, length + 1);
// ap_hard_timeout("read_post", r);
while ((len_read = ap_get_client_block(r, buf, sizeof(buf))) > 0) {
// ap_reset_timeout(r);
if ((rpos + len_read) > length) {
rsize = length - rpos;
}
else {
rsize = len_read;
}
memcpy(rbuf + rpos, buf, rsize);
rpos += rsize;
}
// ap_kill_timeout(r);
}
// ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, r->server, 0, "read_post(...): %u, rbuf = %s", getpid(), rbuf);
while (rbuf && *rbuf && (val = ap_getword(r->pool, (const char**) &rbuf, '&'))) {
key = ap_getword(r->pool, &val, '=');
ap_unescape_url((char*) key);
ap_unescape_url((char*) val);
if (!key || !val) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post(...): invalid key or value, key = %s, val = %s", key, val);
break;
}
set_var(interp, "::pram", key, val);
}
return OK;
}
static int read_post_init(request_rec *r, Tcl_Interp *interp)
{
const char *type = apr_table_get(r->headers_in, "Content-Type");
char *boundary;
if (read_post_ok) {
read_post_ok = 0;
}
else {
/* already read */
return OK;
}
if (!strcmp(type, "application/x-www-form-urlencoded")) {
return read_post(r, interp);
}
else if (strstr(type, "multipart/form-data")) {
boundary = strstr(type, "boundary=");
if (!boundary) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post_init(...): no boundry in multipart/form-data");
return DECLINED;
}
boundary += 9;
return read_post_data(r, interp, boundary);
}
else {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, r->server, "read_post_init(...): unknown, Content-Type: %s", type);
return DECLINED;
}
}
int cmd_rputs(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
char *opt = NULL, *data;
switch (objc) {
case 3:
opt = Tcl_GetString(objv[1]);
data = Tcl_GetString(objv[2]);
break;
case 2:
data = Tcl_GetString(objv[1]);
break;
default:
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? string");
return TCL_ERROR;
}
if (opt && strcmp(opt, "-nonewline")) {
Tcl_WrongNumArgs(interp, 1, objv, "?-nonewline? string");
return TCL_ERROR;
}
ap_rprintf(_r, "%s%s", data, opt ? "" : "\n");
return TCL_OK;
}
int cmd_rwrite(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
char *data = NULL;
int length;
switch (objc) {
case 2:
data = (char*) Tcl_GetByteArrayFromObj(objv[1], &length);
break;
default:
Tcl_WrongNumArgs(interp, 1, objv, "data");
return TCL_ERROR;
}
ap_rwrite(data, length, _r);
return TCL_OK;
}
int cmd_ap_send_http_header(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_Obj *obj;
obj = Tcl_GetVar2Ex(ixx, "content_type", NULL, 0);
if (obj) {
_r->content_type = Tcl_GetString(obj);
}
ap_send_http_header(_r);
return TCL_OK;
}
static int set_headers_in(void *data, const char *key, const char *val)
{
Tcl_Interp *interp = (Tcl_Interp*) data;
set_var(interp, "headers_in", key, val);
return 1;
}
int cmd_r(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "variable");
return TCL_ERROR;
}
if (!strcmp("method_number", Tcl_GetString(objv[1]))) {
Tcl_SetObjResult(ixx, Tcl_NewIntObj(_r->method_number));
}
else if (!strcmp("uri", Tcl_GetString(objv[1]))) {
Tcl_SetObjResult(ixx, Tcl_NewStringObj(_r->uri, -1));
}
else if (!strcmp("headers_in", Tcl_GetString(objv[1]))) {
apr_table_do(set_headers_in, ixx, _r->headers_in, NULL);
run_script(ixx, "array names headers_in");
}
return TCL_OK;
}
int cmd_r_set(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc < 3) {
Tcl_WrongNumArgs(interp, 1, objv, "variable ?variables?");
return TCL_ERROR;
}
if (!strcmp("content_type", Tcl_GetString(objv[1]))) {
_r->content_type = Tcl_GetString(objv[2]);
}
else if (!strcmp("headers_out", Tcl_GetString(objv[1]))) {
if (objc != 4) {
return TCL_ERROR;
}
apr_table_set(_r->headers_out, Tcl_GetString(objv[2]), Tcl_GetString(objv[3]));
}
return TCL_OK;
}
int cmd_read_post(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (read_post_init(_r, ixx) != OK) {
ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, _r->server, "cmd_read_post(...): read failed");
Tcl_AddErrorInfo(ixx, "read failed");
return TCL_ERROR;
}
return TCL_OK;
}
int cmd_ap_get_server_version(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_get_server_version(), -1));
return TCL_OK;
}
int cmd_ap_create_environment(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
char **env;
int i;
ap_add_cgi_vars(_r);
ap_add_common_vars(_r);
env = ap_create_environment(_r->pool, _r->subprocess_env);
for (i = 0; env[i]; i++) {
char *sptr = strchr(env[i], '=');
*sptr = '\0';
set_var(ixx, "::env", env[i], sptr + 1);
*sptr = '=';
}
return TCL_OK;
}
int cmd_abort(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc == 2) {
Tcl_AddObjErrorInfo(ixx, Tcl_GetString(objv[1]), -1);
}
return TCL_ERROR;
}
int cmd_ap_internal_redirect(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "uri");
return TCL_ERROR;
}
ap_internal_redirect(Tcl_GetString(objv[1]), _r);
return TCL_OK;
}
int cmd_random(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(interp, Tcl_NewLongObj(random()));
return TCL_OK;
}
int cmd_srandom(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
int i;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "integer");
return TCL_ERROR;
}
Tcl_GetIntFromObj(interp, objv[1], &i);
srandom((unsigned int) i);
return TCL_OK;
}
int cmd_base64_encode(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
uint8_t *data, *enc_data;
int length;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "data");
return TCL_ERROR;
}
data = Tcl_GetByteArrayFromObj(objv[1], &length);
enc_data = buf_to_base64(data, length);
Tcl_SetObjResult(interp, Tcl_NewStringObj((char*) enc_data, -1));
free(enc_data);
return TCL_OK;
}
int cmd_base64_decode(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
uint8_t *enc_data, *ws_data, *data;
size_t length;
Tcl_Obj *obj;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "string");
return TCL_ERROR;
}
enc_data = (uint8_t*) Tcl_GetString(objv[1]);
ws_data = base64_remove_whitespace(enc_data, 0);
data = base64_to_buf(data, &length);
obj = Tcl_NewObj();
Tcl_SetByteArrayObj(obj, (unsigned char*) data, length);
free(ws_data);
free(data);
return TCL_OK;
}
int cmd_ap_allow_options(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_allow_options(_r)));
return TCL_OK;
}
int cmd_ap_allow_overrides(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_allow_overrides(_r)));
return TCL_OK;
}
int cmd_ap_default_type(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_default_type(_r), -1));
return TCL_OK;
}
int cmd_ap_document_root(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_document_root(_r), -1));
return TCL_OK;
}
int cmd_ap_get_remote_host(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
int i;
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "type");
return TCL_ERROR;
}
Tcl_GetIntFromObj(interp, objv[1], &i);
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_get_remote_host(_r->connection, _r->per_dir_config, i), -1));
return TCL_OK;
}
int cmd_ap_get_remote_logname(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_get_remote_logname(_r), -1));
return TCL_OK;
}
int cmd_ap_construct_url(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc != 2) {
Tcl_WrongNumArgs(interp, 1, objv, "uri");
return TCL_ERROR;
}
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_construct_url(_r->pool, Tcl_GetString(objv[1]), _r), -1));
return TCL_OK;
}
int cmd_ap_get_server_name(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_get_server_name(_r), -1));
return TCL_OK;
}
int cmd_ap_get_server_port(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
/* int should suffice since ports are usually unsigned short */
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_get_server_port(_r)));
return TCL_OK;
}
int cmd_ap_get_limit_req_body(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
/* ap_get_limit_req_body returns an unsigned long, its possible it could overflow in TCL
as it doesn't appear to have any unsigned support... it might be possible to assign it
to a double?
*/
Tcl_SetObjResult(ixx, Tcl_NewLongObj(ap_get_limit_req_body(_r)));
return TCL_OK;
}
int cmd_ap_get_limit_xml_body(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_get_limit_xml_body(_r)));
return TCL_OK;
}
int cmd_ap_custom_response(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
int i;
if (objc != 3) {
Tcl_WrongNumArgs(interp, 1, objv, "status string");
return TCL_ERROR;
}
Tcl_GetIntFromObj(interp, objv[1], &i);
ap_custom_response(_r, i, Tcl_GetString(objv[2]));
return TCL_OK;
}
int cmd_ap_exists_config_define(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
if (objc != 1) {
Tcl_WrongNumArgs(interp, 1, objv, "name");
return TCL_ERROR;
}
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_exists_config_define(Tcl_GetString(objv[1]))));
return TCL_OK;
}
int cmd_ap_auth_type(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_auth_type(_r), -1));
return TCL_OK;
}
int cmd_ap_auth_name(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewStringObj(ap_auth_name(_r), -1));
return TCL_OK;
}
int cmd_ap_satisfies(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
Tcl_SetObjResult(ixx, Tcl_NewIntObj(ap_satisfies(_r)));
return TCL_OK;
}
int cmd_ap_requires(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[])
{
int i;
const apr_array_header_t *a = ap_requires(_r);
require_line *ra = (require_line*) a->elts;
Tcl_Obj *obj = Tcl_NewObj();
for (i = 0; i < a->nelts; i++) {
Tcl_Obj *xobj = Tcl_NewObj();
Tcl_ListObjAppendElement(ixx, xobj, Tcl_NewIntObj(ra[i].method_mask));
Tcl_ListObjAppendElement(ixx, xobj, Tcl_NewStringObj(ra[i].requirement, -1));
Tcl_ListObjAppendElement(ixx, obj, xobj);
}
Tcl_SetObjResult(ixx, obj);
return TCL_OK;
}