tcl_cmds.c (1,605 lines of code) (raw):

/* ==================================================================== * 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 apr_pool_t *_pconf; extern char *current_namespace; extern int read_post_ok; static int sorted = 0, r_size = 0, connection_size = 0, server_size = 0; 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: 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, *nm_var = apr_psprintf(r->pool, "%s::pram", r->filename); 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; while ((len_read = ap_get_client_block(r, buf, sizeof(buf))) > 0) { memcpy(lbuf + lpos, buf, len_read); lpos += len_read; } lbuf[lpos] = '\0'; } 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_varb(interp, nm_var, 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_varb(interp, nm_var, 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 *nm_var = apr_psprintf(r->pool, "%s::pram", r->filename); 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); while ((len_read = ap_get_client_block(r, buf, sizeof(buf))) > 0) { if ((rpos + len_read) > length) { rsize = length - rpos; } else { rsize = len_read; } memcpy(rbuf + rpos, buf, rsize); rpos += rsize; } } 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, nm_var, (char*) key, "%s", (char*) 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; } } static Tcl_Obj* r_the_request(void) { return Tcl_NewStringObj(_r->the_request, -1); } static Tcl_Obj* r_assbackwards(void) { return Tcl_NewIntObj(_r->assbackwards); } static Tcl_Obj* r_proxyreq(void) { return Tcl_NewIntObj(_r->proxyreq); } static Tcl_Obj* r_header_only(void) { return Tcl_NewIntObj(_r->header_only); } static Tcl_Obj* r_protocol(void) { return Tcl_NewStringObj(_r->protocol, -1); } static Tcl_Obj* r_proto_num(void) { return Tcl_NewIntObj(_r->proto_num); } static Tcl_Obj* r_hostname(void) { return Tcl_NewStringObj(_r->hostname, -1); } static Tcl_Obj* r_request_time(void) { return Tcl_NewLongObj(_r->request_time); } static Tcl_Obj* r_status_line(void) { return Tcl_NewStringObj(_r->status_line, -1); } static Tcl_Obj* r_status(void) { return Tcl_NewIntObj(_r->status); } static Tcl_Obj* r_method(void) { return Tcl_NewStringObj(_r->method, -1); } static Tcl_Obj* r_method_number(void) { return Tcl_NewIntObj(_r->method_number); } static Tcl_Obj* r_allowed(void) { return Tcl_NewIntObj(_r->allowed); } /* hasn't been implemented ? */ static Tcl_Obj* r_allowed_xmethods(void) { return Tcl_NewStringObj("", -1); } static Tcl_Obj* r_allowed_methods(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; char **method_list = (char**) _r->allowed_methods->method_list->elts; Tcl_ListObjAppendElement(interp, obj, Tcl_NewIntObj(_r->allowed_methods->method_mask)); for (i = 0; i < _r->allowed_methods->method_list->nelts; i++) { Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(method_list[i], -1)); } return obj; } static Tcl_Obj* r_sent_bodyct(void) { return Tcl_NewIntObj(_r->sent_bodyct); } static Tcl_Obj* r_bytes_sent(void) { return Tcl_NewIntObj(_r->bytes_sent); } static Tcl_Obj* r_mtime(void) { return Tcl_NewLongObj(_r->mtime); } static Tcl_Obj* r_chunked(void) { return Tcl_NewIntObj(_r->chunked); } static Tcl_Obj* r_boundary(void) { /* doesn't exist anymore.... :( */ /* return Tcl_NewStringObj(_r->boundary, -1); */ } static Tcl_Obj* r_range(void) { return Tcl_NewStringObj(_r->range, -1); } static Tcl_Obj* r_clength(void) { return Tcl_NewLongObj(_r->clength); } static Tcl_Obj* r_remaining(void) { return Tcl_NewLongObj(_r->remaining); } static Tcl_Obj* r_read_length(void) { return Tcl_NewLongObj(_r->read_length); } static Tcl_Obj* r_read_body(void) { return Tcl_NewIntObj(_r->read_body); } static Tcl_Obj* r_read_chunked(void) { return Tcl_NewIntObj(_r->read_chunked); } static Tcl_Obj* r_expecting_100(void) { return Tcl_NewIntObj(_r->expecting_100); } static Tcl_Obj* r_headers_in(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->headers_in); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "headers_in", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } static Tcl_Obj* r_headers_out(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->headers_out); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "headers_out", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } static Tcl_Obj* r_err_headers_out(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->err_headers_out); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "err_headers_out", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } /* ap_create_environment() sets ::env */ static Tcl_Obj* r_subprocess_env(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->subprocess_env); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "subprocess_env", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } static Tcl_Obj* r_notes(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->notes); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "notes", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } static Tcl_Obj* r_content_type(void) { return Tcl_NewStringObj(_r->content_type, -1); } static Tcl_Obj* r_handler(void) { return Tcl_NewStringObj(_r->handler, -1); } static Tcl_Obj* r_content_encoding(void) { return Tcl_NewStringObj(_r->content_encoding, -1); } static Tcl_Obj* r_content_languages(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; char **content_languages = (char**) _r->content_languages->elts; for (i = 0; i < _r->content_languages->nelts; i++) { Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(content_languages[i], -1)); } return obj; } static Tcl_Obj* r_vlist_validator(void) { return Tcl_NewStringObj(_r->vlist_validator, -1); } static Tcl_Obj* r_user(void) { return Tcl_NewStringObj(_r->user, -1); } static Tcl_Obj* r_ap_auth_type(void) { return Tcl_NewStringObj(_r->ap_auth_type, -1); } static Tcl_Obj* r_no_cache(void) { return Tcl_NewIntObj(_r->no_cache); } static Tcl_Obj* r_no_local_copy(void) { return Tcl_NewIntObj(_r->no_local_copy); } static Tcl_Obj* r_unparsed_uri(void) { return Tcl_NewStringObj(_r->unparsed_uri, -1); } static Tcl_Obj* r_uri(void) { return Tcl_NewStringObj(_r->uri, -1); } static Tcl_Obj* r_filename(void) { return Tcl_NewStringObj(_r->filename, -1); } static Tcl_Obj* r_path_info(void) { return Tcl_NewStringObj(_r->path_info, -1); } static Tcl_Obj* r_args(void) { return Tcl_NewStringObj(_r->args, -1); } static Tcl_Obj* r_parsed_uri(void) { Tcl_Obj *obj = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.scheme, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.hostinfo, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.user, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.password, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.hostname, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.port_str, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.path, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.query, -1)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->parsed_uri.fragment, -1)); /* is the rest important? */ return obj; } /* variables in r->connection */ static Tcl_Obj* r_connection_remote_ip(void) { return Tcl_NewStringObj(_r->connection->remote_ip, -1); } static Tcl_Obj* r_connection_remote_host(void) { return Tcl_NewStringObj(_r->connection->remote_host, -1); } static Tcl_Obj* r_connection_remote_logname(void) { return Tcl_NewStringObj(_r->connection->remote_logname, -1); } static Tcl_Obj* r_connection_aborted(void) { return Tcl_NewIntObj(_r->connection->aborted); } static Tcl_Obj* r_connection_keepalive(void) { return Tcl_NewIntObj(_r->connection->keepalive); } static Tcl_Obj* r_connection_double_reverse(void) { return Tcl_NewIntObj(_r->connection->double_reverse); } static Tcl_Obj* r_connection_keepalives(void) { return Tcl_NewIntObj(_r->connection->keepalives); } static Tcl_Obj* r_connection_local_ip(void) { return Tcl_NewStringObj(_r->connection->local_ip, -1); } static Tcl_Obj* r_connection_local_host(void) { return Tcl_NewStringObj(_r->connection->local_host, -1); } static Tcl_Obj* r_connection_id(void) { return Tcl_NewLongObj(_r->connection->id); } static Tcl_Obj* r_connection_notes(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; const apr_array_header_t *ha = apr_table_elts(_r->connection->notes); apr_table_entry_t *hte = (apr_table_entry_t*) ha->elts; for (i = 0; i < ha->nelts; i++) { Tcl_SetVar2Ex(interp, "connection_notes", hte[i].key, Tcl_NewStringObj(hte[i].val, -1), 0); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(hte[i].key, -1)); } return obj; } static Tcl_Obj* r_server_defn_name(void) { return Tcl_NewStringObj(_r->server->defn_name, -1); } static Tcl_Obj* r_server_defn_line_number(void) { return Tcl_NewIntObj(_r->server->defn_line_number); } static Tcl_Obj* r_server_server_admin(void) { return Tcl_NewStringObj(_r->server->server_admin, -1); } static Tcl_Obj* r_server_server_hostname(void) { return Tcl_NewStringObj(_r->server->server_hostname, -1); } static Tcl_Obj* r_server_port(void) { return Tcl_NewIntObj(_r->server->port); } static Tcl_Obj* r_server_error_fname(void) { return Tcl_NewStringObj(_r->server->error_fname, -1); } static Tcl_Obj* r_server_loglevel(void) { return Tcl_NewIntObj(_r->server->loglevel); } static Tcl_Obj* r_server_is_virtual(void) { return Tcl_NewIntObj(_r->server->is_virtual); } static Tcl_Obj* r_server_addrs(void) { Tcl_Obj *obj = Tcl_NewObj(); Tcl_ListObjAppendElement(interp, obj, Tcl_NewIntObj(_r->server->addrs->host_port)); Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(_r->server->addrs->virthost, -1)); return obj; } static Tcl_Obj* r_server_timeout(void) { return Tcl_NewIntObj(_r->server->timeout); } static Tcl_Obj* r_server_keep_alive_timeout(void) { return Tcl_NewIntObj(_r->server->keep_alive_timeout); } static Tcl_Obj* r_server_keep_alive_max(void) { return Tcl_NewIntObj(_r->server->keep_alive_max); } static Tcl_Obj* r_server_keep_alive(void) { return Tcl_NewIntObj(_r->server->keep_alive); } static Tcl_Obj* r_server_path(void) { return Tcl_NewStringObj(_r->server->path, -1); } static Tcl_Obj* r_server_names(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; char **a = (char**) _r->server->names->elts; for (i = 0; i < _r->server->names->nelts; i++) { Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(a[i], -1)); } return obj; } static Tcl_Obj* r_server_wild_names(void) { Tcl_Obj *obj = Tcl_NewObj(); int i; char **a = (char**) _r->server->wild_names->elts; for (i = 0; i < _r->server->wild_names->nelts; i++) { Tcl_ListObjAppendElement(interp, obj, Tcl_NewStringObj(a[i], -1)); } return obj; } static Tcl_Obj* r_server_limit_req_line(void) { return Tcl_NewIntObj(_r->server->limit_req_line); } static Tcl_Obj* r_server_limit_req_fieldsize(void) { return Tcl_NewIntObj(_r->server->limit_req_fieldsize); } static Tcl_Obj* r_server_limit_req_fields(void) { return Tcl_NewIntObj(_r->server->limit_req_fields); } /* sets */ static int r_set_the_request(int objc, Tcl_Obj *CONST objv[]) { _r->the_request = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_assbackwards(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->assbackwards)); return TCL_OK; } static int r_set_proxyreq(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->proxyreq)); return TCL_OK; } static int r_set_header_only(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->header_only)); return TCL_OK; } static int r_set_protocol(int objc, Tcl_Obj *CONST objv[]) { _r->protocol = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_proto_num(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->proto_num)); return TCL_OK; } static int r_set_allowed(int objc, Tcl_Obj *CONST objv[]) { #if TCL_MAJOR_VERSION > 7 && TCL_MINOR_VERSION > 3 Tcl_GetWideIntFromObj(interp, objv[2], &(_r->allowed)); #endif return TCL_OK; } /* ? */ static int r_set_allowed_xmethods(int objc, Tcl_Obj *CONST objv[]) { return TCL_OK; } static int r_set_allowed_methods(int objc, Tcl_Obj *CONST objv[]) { int xxobjc; Tcl_Obj **xxobjv; int i; if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "method_mask method_list"); return TCL_ERROR; } #if TCL_MAJOR_VERSION > 7 && TCL_MINOR_VERSION > 3 Tcl_GetWideIntFromObj(interp, objv[2], &(_r->allowed_methods->method_mask)); if (Tcl_ListObjGetElements(interp, objv[3], &xxobjc, &xxobjv) == TCL_ERROR) { return TCL_ERROR; } _r->allowed_methods->method_list = (apr_array_header_t*) apr_array_make(_r->allowed_methods->method_list->pool, xxobjc, sizeof(char*)); for (i = 0; i < xxobjc; i++) { char *xx = (char*) apr_array_push(_r->allowed_methods->method_list); xx = apr_pstrdup(_r->allowed_methods->method_list->pool, Tcl_GetString(xxobjv[i])); } #endif return TCL_OK; } static int r_set_headers_out(int objc, Tcl_Obj *CONST objv[]) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "header_name header"); return TCL_ERROR; } apr_table_set(_r->headers_out, Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); return TCL_OK; } static int r_set_err_headers_out(int objc, Tcl_Obj *CONST objv[]) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "header_name header"); return TCL_ERROR; } apr_table_set(_r->err_headers_out, Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); return TCL_OK; } static int r_set_filename(int objc, Tcl_Obj *CONST objv[]) { _r->filename = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_subprocess_env(int objc, Tcl_Obj *CONST objv[]) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "variable_name variable"); return TCL_ERROR; } apr_table_set(_r->subprocess_env, Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); return TCL_OK; } static int r_set_notes(int objc, Tcl_Obj *CONST objv[]) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "note_name note"); return TCL_ERROR; } apr_table_set(_r->notes, Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); return TCL_OK; } static int r_set_content_type(int objc, Tcl_Obj *CONST objv[]) { _r->content_type = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_content_encoding(int objc, Tcl_Obj *CONST objv[]) { _r->content_encoding = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_content_languages(int objc, Tcl_Obj *CONST objv[]) { int xxobjc; Tcl_Obj **xxobjv; int i; if (Tcl_ListObjGetElements(interp, objv[2], &xxobjc, &xxobjv) == TCL_ERROR) { return TCL_ERROR; } _r->content_languages = apr_array_make(_r->content_languages->pool, xxobjc, sizeof(char*)); for (i = 0; i < xxobjc; i++) { char *xx = apr_array_push(_r->content_languages); xx = apr_pstrdup(_r->content_languages->pool, Tcl_GetString(xxobjv[i])); } return TCL_OK; } static int r_set_vlist_validator(int objc, Tcl_Obj *CONST objv[]) { _r->vlist_validator = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_user(int objc, Tcl_Obj *CONST objv[]) { _r->user = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_ap_auth_type(int objc, Tcl_Obj *CONST objv[]) { _r->ap_auth_type = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_no_cache(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->no_cache)); return TCL_OK; } static int r_set_no_local_copy(int objc, Tcl_Obj *CONST objv[]) { Tcl_GetIntFromObj(interp, objv[2], &(_r->no_local_copy)); return TCL_OK; } static int r_set_unparsed_uri(int objc, Tcl_Obj *CONST objv[]) { _r->unparsed_uri = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_uri(int objc, Tcl_Obj *CONST objv[]) { _r->uri = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_path_info(int objc, Tcl_Obj *CONST objv[]) { _r->path_info = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_args(int objc, Tcl_Obj *CONST objv[]) { _r->args = apr_pstrdup(_r->pool, Tcl_GetString(objv[2])); return TCL_OK; } static int r_set_parsed_uri(int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(apr_uri_parse(_r->pool, Tcl_GetString(objv[2]), &(_r->parsed_uri)))); return TCL_OK; } static int r_set_connection_notes(int objc, Tcl_Obj *CONST objv[]) { if (objc != 4) { Tcl_WrongNumArgs(interp, 2, objv, "note_name note"); return TCL_ERROR; } apr_table_set(_r->connection->notes, Tcl_GetString(objv[2]), Tcl_GetString(objv[3])); return TCL_OK; } typedef Tcl_Obj* (*fy_t)(void); typedef int (*fx_t)(int objc, Tcl_Obj *CONST objv[]); typedef struct { char *var; fy_t rd_func; fx_t wr_func; } r_table; static int r_find(const void *x, const void *y) { return strcmp(((r_table*) x)->var, ((r_table*) y)->var); } r_table r_tbl[] = { { "allowed", r_allowed, r_set_allowed }, { "allowed_methods", r_allowed_methods, r_set_allowed_methods }, { "allowed_xmethods", r_allowed_xmethods, r_set_allowed_xmethods }, { "ap_auth_type", r_ap_auth_type, r_set_ap_auth_type }, { "args", r_args, r_set_args }, { "assbackwards", r_assbackwards, r_set_assbackwards }, { "boundary", r_boundary, NULL }, { "bytes_sent", r_bytes_sent, NULL }, { "chunked", r_chunked, NULL }, { "clength", r_clength, NULL }, { "content_encoding", r_content_encoding, r_set_content_encoding }, /* { "content_languages", r_content_languages,r_set_content_languages }, this is fuct up, and I have no idea why */ { "content_type", r_content_type, r_set_content_type }, { "err_headers_out", r_err_headers_out, r_set_err_headers_out }, { "expecting_100", r_expecting_100, NULL }, { "filename", r_filename, r_set_filename }, { "handler", r_handler, NULL }, { "headers_in", r_headers_in, NULL }, { "headers_out", r_headers_out, r_set_headers_out }, { "header_only", r_header_only, r_set_header_only }, { "hostname", r_hostname, NULL }, { "method", r_method, NULL }, { "method_number", r_method_number, NULL }, { "mtime", r_mtime, NULL }, { "notes", r_notes, r_set_notes }, { "no_cache", r_no_cache, r_set_no_cache }, { "no_local_copy", r_no_local_copy, r_set_no_local_copy }, { "parsed_uri", r_parsed_uri, r_set_parsed_uri }, { "path_info", r_path_info, r_set_path_info }, { "protocol", r_protocol, r_set_protocol }, { "proto_num", r_proto_num, r_set_proto_num }, { "proxyreq", r_proxyreq, r_set_proxyreq }, { "range", r_range, NULL }, { "read_body", r_read_body, NULL }, { "read_chunked", r_read_chunked, NULL }, { "read_length", r_read_length, NULL }, { "remaining", r_remaining, NULL }, { "request_time", r_request_time, NULL }, { "sent_bodyct", r_sent_bodyct, NULL }, { "status", r_status, NULL }, { "status_line", r_status_line, NULL }, { "subprocess_env", r_subprocess_env, r_set_subprocess_env }, { "the_request", r_the_request, r_set_the_request }, { "unparsed_uri", r_unparsed_uri, r_set_unparsed_uri }, { "uri", r_uri, r_set_uri }, { "user", r_user, r_set_user }, { "vlist_validator", r_vlist_validator, r_set_vlist_validator }, { NULL, NULL, NULL } }; r_table r_connection_tbl[] = { { "remote_ip", r_connection_remote_ip, NULL }, { "remote_host", r_connection_remote_host, NULL }, { "remote_logname", r_connection_remote_logname, NULL }, { "aborted", r_connection_aborted, NULL }, { "keepalive", r_connection_keepalive, NULL }, { "doublereverse", r_connection_double_reverse, NULL }, { "keepalives", r_connection_keepalives, NULL }, { "local_ip", r_connection_local_ip, NULL }, { "local_host", r_connection_local_host, NULL }, { "id", r_connection_id, NULL }, { "notes", r_connection_notes, r_set_connection_notes }, { NULL, NULL, NULL } }; r_table r_server_tbl[] = { { "defn_name", r_server_defn_name, NULL }, { "defn_line_number", r_server_defn_line_number, NULL }, { "server_admin", r_server_server_admin, NULL }, { "server_hostname", r_server_server_hostname, NULL }, { "port", r_server_port, NULL }, { "error_fname", r_server_error_fname, NULL }, { "loglevel", r_server_loglevel, NULL }, { "is_virtual", r_server_is_virtual, NULL }, { "addrs", r_server_addrs, NULL }, { "timeout", r_server_timeout, NULL }, { "keep_alive_timeout", r_server_keep_alive_timeout, NULL }, { "keep_alive_max", r_server_keep_alive_max, NULL }, { "keep_alive", r_server_keep_alive, NULL }, { "path", r_server_path, NULL }, { "names", r_server_names, NULL }, { "wild_names", r_server_wild_names, NULL }, { "limit_req_line", r_server_limit_req_line, NULL }, { "limit_req_fieldsize", r_server_limit_req_fieldsize, NULL }, { "limit_req_fields", r_server_limit_req_fields, NULL }, { NULL, NULL, NULL } }; int cmd_r(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { char *xx = NULL, *yy = NULL; r_table *r_table_ptr, key; switch (objc) { case 3: yy = Tcl_GetString(objv[2]); case 2: xx = Tcl_GetString(objv[1]); break; default: Tcl_WrongNumArgs(interp, 1, objv, "variable"); return TCL_ERROR; } if (!sorted) { for (; r_tbl[r_size].var != NULL; r_size++); for (; r_connection_tbl[connection_size].var != NULL; connection_size++); for (; r_server_tbl[server_size].var != NULL; server_size++); qsort(r_tbl, r_size, sizeof(r_table), r_find); qsort(r_connection_tbl, connection_size, sizeof(r_table), r_find); qsort(r_server_tbl, server_size, sizeof(r_table), r_find); sorted = 1; } if (!strcmp(xx, "server")) { if (!yy) { Tcl_WrongNumArgs(interp, 2, objv, "variable"); return TCL_ERROR; } key.var = yy; r_table_ptr = (r_table*) bsearch(&key, r_server_tbl, server_size, sizeof(r_table), r_find); } else if (!strcmp(xx, "connection")) { if (!yy) { Tcl_WrongNumArgs(interp, 2, objv, "variable"); return TCL_ERROR; } key.var = yy; r_table_ptr = (r_table*) bsearch(&key, r_connection_tbl, connection_size, sizeof(r_table), r_find); } else { key.var = xx; r_table_ptr = (r_table*) bsearch(&key, r_tbl, r_size, sizeof(r_table), r_find); } if (!r_table_ptr) { char *p; asprintf(&p, "%s is not known in structure.", xx); Tcl_AddObjErrorInfo(interp, p, -1); free(p); return TCL_ERROR; } Tcl_SetObjResult(interp, r_table_ptr->rd_func()); return TCL_OK; } int cmd_r_set(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { char *xx, *yy; r_table *r_table_ptr, key; switch (objc) { default: case 3: yy = Tcl_GetString(objv[2]); case 2: xx = Tcl_GetString(objv[1]); break; case 1: Tcl_WrongNumArgs(interp, 1, objv, "variable"); return TCL_ERROR; } if (!sorted) { for (; r_tbl[r_size].var != NULL; r_size++); for (; r_connection_tbl[connection_size].var != NULL; connection_size++); for (; r_server_tbl[server_size].var != NULL; server_size++); qsort(r_tbl, r_size, sizeof(r_table), r_find); qsort(r_connection_tbl, connection_size, sizeof(r_table), r_find); qsort(r_server_tbl, server_size, sizeof(r_table), r_find); sorted = 1; } if (!strcmp(xx, "server")) { if (!yy) { Tcl_WrongNumArgs(interp, 2, objv, "variable ?variables?"); return TCL_ERROR; } key.var = yy; r_table_ptr = (r_table*) bsearch(&key, r_server_tbl, server_size, sizeof(r_table), r_find); } else if (!strcmp(xx, "connection")) { if (!yy) { Tcl_WrongNumArgs(interp, 2, objv, "variable ?variables?"); return TCL_ERROR; } key.var = yy; r_table_ptr = (r_table*) bsearch(&key, r_connection_tbl, connection_size, sizeof(r_table), r_find); } else { key.var = xx; r_table_ptr = (r_table*) bsearch(&key, r_tbl, r_size, sizeof(r_table), r_find); } if (!r_table_ptr) { char *p; asprintf(&p, "%s is not known in structure.", xx); Tcl_AddObjErrorInfo(interp, p, -1); free(p); return TCL_ERROR; } if (r_table_ptr->wr_func) { return r_table_ptr->wr_func(objc, objv); } else { Tcl_AddObjErrorInfo(interp, "this variable is not writable", -1); return TCL_ERROR; } } int cmd_read_post(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { if (read_post_init(_r, interp) != OK) { ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_ERR, 0, _r->server, "cmd_read_post(...): read failed"); Tcl_AddErrorInfo(interp, "read failed"); return TCL_ERROR; } return TCL_OK; } int cmd_abort(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { if (objc == 2) { Tcl_AddObjErrorInfo(interp, Tcl_GetString(objv[1]), -1); } return TCL_ERROR; } 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; } /* http_core.h */ int cmd_ap_allow_options(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, 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(interp, 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(interp, 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(interp, 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(interp, Tcl_NewStringObj(ap_get_remote_host(_r->connection, _r->per_dir_config, i, NULL), -1)); return TCL_OK; } int cmd_ap_get_remote_logname(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, 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(interp, 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(interp, 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(interp, 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 long long? */ Tcl_SetObjResult(interp, 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(interp, 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(interp, 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(interp, 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(interp, 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(interp, 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(interp, xobj, Tcl_NewIntObj(ra[i].method_mask)); Tcl_ListObjAppendElement(interp, xobj, Tcl_NewStringObj(ra[i].requirement, -1)); Tcl_ListObjAppendElement(interp, obj, xobj); } Tcl_SetObjResult(interp, obj); return TCL_OK; } /* http_log.h */ int cmd_ap_log_error(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int i, j; if (objc != 4) { Tcl_WrongNumArgs(interp, 1, objv, "level status string"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &i); Tcl_GetIntFromObj(interp, objv[2], &j); ap_log_error(APLOG_MARK, i, j, _r->server, Tcl_GetString(objv[3])); return TCL_OK; } /* http_protocol.h */ int cmd_ap_send_http_header(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { /* I don't know if this does anything anymore? */ /* Tcl_Obj *obj; obj = Tcl_GetVar2Ex(interp, "content_type", NULL, 0); if (obj) { _r->content_type = Tcl_GetString(obj); } ap_send_http_header(_r); */ return TCL_OK; } int cmd_ap_send_http_trace(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_send_http_trace(_r))); return TCL_OK; } int cmd_ap_send_http_options(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_send_http_options(_r))); return TCL_OK; } int cmd_ap_finalize_request_protocol(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_finalize_request_protocol(_r); return TCL_OK; } int cmd_ap_send_error_response(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int recursive_error; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "recursive_error"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &recursive_error); ap_send_error_response(_r, recursive_error); return TCL_OK; } int cmd_ap_set_content_length(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { apr_off_t length; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "length"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], (int*) &length); ap_set_content_length(_r, length); return TCL_OK; } int cmd_ap_set_keepalive(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_set_keepalive(_r))); return TCL_OK; } int cmd_ap_rationalize_mtime(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { apr_time_t mtime; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "mtime"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], (int*) &mtime); Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_rationalize_mtime(_r, mtime))); return TCL_OK; } int cmd_ap_make_etag(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int i; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "force_weak"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &i); Tcl_SetObjResult(interp, Tcl_NewStringObj(ap_make_etag(_r, i), -1)); return TCL_OK; } int cmd_ap_set_etag(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_set_etag(_r); return TCL_OK; } int cmd_ap_set_last_modified(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_set_last_modified(_r); return TCL_OK; } int cmd_ap_meets_conditions(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_meets_conditions(_r))); return TCL_OK; } /* ... skipping method stuff ... */ 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_rflush(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_rflush(_r); return TCL_OK; } /* skip ap_index_of_response() */ int cmd_ap_get_status_line(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int status; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "status"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &status); Tcl_SetObjResult(interp, Tcl_NewStringObj(ap_get_status_line(status), -1)); return TCL_OK; } int cmd_ap_setup_client_block(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int read_policy; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "read_policy"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &read_policy); Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_setup_client_block(_r, read_policy))); return TCL_OK; } int cmd_ap_get_client_block(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int bufsiz; char *buffer; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "bufsiz"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &bufsiz); buffer = malloc(bufsiz); bufsiz = ap_get_client_block(_r, buffer, bufsiz); Tcl_SetObjResult(interp, Tcl_NewIntObj(bufsiz)); if (bufsiz > 0) { Tcl_SetVar2Ex(interp, "R", NULL, Tcl_NewByteArrayObj(buffer, bufsiz), TCL_LEAVE_ERR_MSG); } free(buffer); return TCL_OK; } int cmd_ap_discard_request_body(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_discard_request_body(_r))); return TCL_OK; } int cmd_ap_note_auth_failure(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_note_auth_failure(_r); return TCL_OK; } int cmd_ap_note_basic_auth_failure(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_note_basic_auth_failure(_r); return TCL_OK; } int cmd_ap_note_digest_auth_failure(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { ap_note_digest_auth_failure(_r); return TCL_OK; } int cmd_ap_get_basic_auth_pw(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { const char *pw; int xx; xx = ap_get_basic_auth_pw(_r, &pw); Tcl_SetObjResult(interp, Tcl_NewIntObj(xx)); if (xx != 0) { Tcl_SetVar2Ex(interp, "R", NULL, Tcl_NewStringObj(pw, -1), TCL_LEAVE_ERR_MSG); } return TCL_OK; } /* skip ap_set_sub_req_protocol() and ap_finalize_sub_req_protocol() */ int cmd_ap_parse_uri(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "uri"); return TCL_ERROR; } ap_parse_uri(_r, Tcl_GetString(objv[1])); return TCL_OK; } /* skip ap_getline(), not sure what it does yet */ int cmd_ap_method_number_of(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "method"); return TCL_ERROR; } Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_method_number_of(Tcl_GetString(objv[1])))); return TCL_OK; } int cmd_ap_method_name_of(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int methnum; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "method"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &methnum); Tcl_SetObjResult(interp, Tcl_NewStringObj(ap_method_name_of(_r->pool, methnum), -1)); return TCL_OK; } /* http_request.h */ /* skip sub requests ... */ 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_ap_internal_redirect_handler(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_handler(Tcl_GetString(objv[1]), _r); return TCL_OK; } int cmd_ap_some_auth_required(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewIntObj(ap_some_auth_required(_r))); return TCL_OK; } /* skip ap_is_initial_req() */ int cmd_ap_update_mtime(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int dependency_mtime; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "dependency_mtime"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &dependency_mtime); ap_update_mtime(_r, dependency_mtime); return TCL_OK; } int cmd_ap_allow_methods(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { int reset; if (objc != 3) { Tcl_WrongNumArgs(interp, 1, objv, "reset methods"); return TCL_ERROR; } Tcl_GetIntFromObj(interp, objv[1], &reset); ap_allow_methods(_r, reset, Tcl_GetString(objv[2])); return TCL_OK; } /* httpd.h */ int cmd_ap_get_server_version(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewStringObj(ap_get_server_version(), -1)); return TCL_OK; } int cmd_ap_add_version_component(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "component"); return TCL_ERROR; } ap_add_version_component(_pconf, Tcl_GetString(objv[1])); return TCL_OK; } int cmd_ap_get_server_built(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { Tcl_SetObjResult(interp, Tcl_NewStringObj(ap_get_server_built(), -1)); return TCL_OK; } /* util_script.h */ int cmd_ap_create_environment(ClientData cd, Tcl_Interp *ixx, int objc, Tcl_Obj *CONST objv[]) { char **env, *nm_env; int i; asprintf(&nm_env, "::%s::env", _r->filename); 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(interp, nm_env, env[i], "%s", sptr + 1); *sptr = '='; } free(nm_env); return TCL_OK; }