X Tutup
/* * Copyright (C) 2000, 2001, 2013 Gregory Trubetskoy * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); you * may not use this file except in compliance with the License. You * may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * * Originally developed by Gregory Trubetskoy. * * * util.c * * * See accompanying documentation and source code comments * for details. * */ #include "mod_python.h" /** ** tuple_from_array_header ** * Given an array header return a tuple. The array elements * assumed to be strings. */ PyObject * tuple_from_array_header(const apr_array_header_t *ah) { PyObject *t; int i; char **s; if (ah == NULL) t = PyTuple_New(0); else { t = PyTuple_New(ah->nelts); s = (char **) ah->elts; for (i = 0; i < ah->nelts; i++) PyTuple_SetItem(t, i, MpBytesOrUnicode_FromString(s[i])); } return t; } /** ** tuple_from_method_list ** * Given an apr_method_list_t return a tuple. */ PyObject * tuple_from_method_list(const ap_method_list_t *l) { PyObject *t; int i; char **methods; if ((l->method_list == NULL) || (l->method_list->nelts == 0)) t = PyTuple_New(0); else { t = PyTuple_New(l->method_list->nelts); methods = (char **)l->method_list->elts; for (i = 0; i < l->method_list->nelts; ++i) PyTuple_SetItem(t, i, MpBytesOrUnicode_FromString(methods[i])); } return t; } /** ** tuple_from_finfo ** * makes a tuple similar to return of os.stat() from apr_finfo_t * */ PyObject *tuple_from_finfo(apr_finfo_t *f) { PyObject *t; if (f->filetype == APR_NOFILE) { Py_INCREF(Py_None); return Py_None; } t = PyTuple_New(13); /* this should have been first, but was added later */ PyTuple_SET_ITEM(t, 12, PyLong_FromLong(f->filetype)); if (f->valid & APR_FINFO_PROT) { PyTuple_SET_ITEM(t, 0, PyLong_FromLong(f->protection)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 0, Py_None); } if (f->valid & APR_FINFO_INODE) { PyTuple_SET_ITEM(t, 1, PyLong_FromLong(f->inode)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 1, Py_None); } if (f->valid & APR_FINFO_DEV) { PyTuple_SET_ITEM(t, 2, PyLong_FromLong(f->device)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 2, Py_None); } if (f->valid & APR_FINFO_NLINK) { PyTuple_SET_ITEM(t, 3, PyLong_FromLong(f->nlink)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 3, Py_None); } if (f->valid & APR_FINFO_USER) { PyTuple_SET_ITEM(t, 4, PyLong_FromLong(f->user)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 4, Py_None); } if (f->valid & APR_FINFO_GROUP) { PyTuple_SET_ITEM(t, 5, PyLong_FromLong(f->group)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 5, Py_None); } if (f->valid & APR_FINFO_SIZE) { PyTuple_SET_ITEM(t, 6, PyLong_FromLong(f->size)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 6, Py_None); } if (f->valid & APR_FINFO_ATIME) { PyTuple_SET_ITEM(t, 7, PyLong_FromLong(f->atime*0.000001)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 7, Py_None); } if (f->valid & APR_FINFO_MTIME) { PyTuple_SET_ITEM(t, 8, PyLong_FromLong(f->mtime*0.000001)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 8, Py_None); } if (f->valid & APR_FINFO_CTIME) { PyTuple_SET_ITEM(t, 9, PyLong_FromLong(f->ctime*0.000001)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 9, Py_None); } if (f->fname) { PyTuple_SET_ITEM(t, 10, MpBytesOrUnicode_FromString(f->fname)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 10, Py_None); } if (f->valid & APR_FINFO_NAME) { PyTuple_SET_ITEM(t, 11, MpBytesOrUnicode_FromString(f->name)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 11, Py_None); } /* it'd be nice to also return the file dscriptor, f->filehand->filedes, but it's platform dependent, so may be later... */ return t; } /** ** tuple_from_apr_uri ** * makes a tuple from uri_components * */ PyObject *tuple_from_apr_uri(apr_uri_t *u) { PyObject *t; t = PyTuple_New(9); if (u->scheme) { PyTuple_SET_ITEM(t, 0, MpBytesOrUnicode_FromString(u->scheme)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 0, Py_None); } if (u->hostinfo) { PyTuple_SET_ITEM(t, 1, MpBytesOrUnicode_FromString(u->hostinfo)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 1, Py_None); } if (u->user) { PyTuple_SET_ITEM(t, 2, MpBytesOrUnicode_FromString(u->user)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 2, Py_None); } if (u->password) { PyTuple_SET_ITEM(t, 3, MpBytesOrUnicode_FromString(u->password)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 3, Py_None); } if (u->hostname) { PyTuple_SET_ITEM(t, 4, MpBytesOrUnicode_FromString(u->hostname)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 4, Py_None); } if (u->port_str) { PyTuple_SET_ITEM(t, 5, PyLong_FromLong(u->port)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 5, Py_None); } if (u->path) { PyTuple_SET_ITEM(t, 6, MpBytesOrUnicode_FromString(u->path)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 6, Py_None); } if (u->query) { PyTuple_SET_ITEM(t, 7, MpBytesOrUnicode_FromString(u->query)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 7, Py_None); } if (u->fragment) { PyTuple_SET_ITEM(t, 8, MpBytesOrUnicode_FromString(u->fragment)); } else { Py_INCREF(Py_None); PyTuple_SET_ITEM(t, 8, Py_None); } /* XXX hostent, is_initialized, dns_* */ return t; } /** ** python_decref ** * This helper function is used with apr_pool_cleanup_register to destroy * python objects when a certain pool is destroyed. */ apr_status_t python_decref(void *object) { Py_XDECREF((PyObject *) object); return 0; } /** ** find_module ** * Find an Apache module by name, used by get_addhandler_extensions */ static module *find_module(char *name) { int n; for (n = 0; ap_loaded_modules[n]; ++n) { if (strcmp(name, ap_loaded_modules[n]->name) == 0) return ap_loaded_modules[n]; } return NULL; } /** ** get_addhandler_extensions ** * Get extensions specified for AddHandler, if any. To do this we * retrieve mod_mime's config. This is used by the publisher to strip * file extentions from modules in the most meaningful way. * * XXX This function is a hack and will stop working if mod_mime people * decide to change their code. A better way to implement this would * be via the config tree, but it doesn't seem to be quite there just * yet, because it doesn't have .htaccess directives. */ char * get_addhandler_extensions(request_rec *req) { /* these typedefs are copied from mod_mime.c */ typedef struct { apr_hash_t *extension_mappings; apr_array_header_t *remove_mappings; char *default_language; int multimatch; } mime_dir_config; typedef struct extension_info { char *forced_type; /* Additional AddTyped stuff */ char *encoding_type; /* Added with AddEncoding... */ char *language_type; /* Added with AddLanguage... */ char *handler; /* Added with AddHandler... */ char *charset_type; /* Added with AddCharset... */ char *input_filters; /* Added with AddInputFilter... */ char *output_filters; /* Added with AddOutputFilter... */ } extension_info; mime_dir_config *mconf; apr_hash_index_t *hi; void *val; void *key; extension_info *ei; char *result = NULL; module *mod_mime = find_module("mod_mime.c"); mconf = (mime_dir_config *) ap_get_module_config(req->per_dir_config, mod_mime); if (mconf->extension_mappings) { for (hi = apr_hash_first(req->pool, mconf->extension_mappings); hi; hi = apr_hash_next(hi)) { apr_hash_this(hi, (const void **)&key, NULL, &val); ei = (extension_info *)val; if (ei->handler) if (strcmp("mod_python", ei->handler) == 0 || strcmp("python-program", ei->handler) == 0) result = apr_pstrcat(req->pool, (char *)key, " ", result, NULL); } } return result; } /** ** find_memberdef ** * Find a memberdef in a PyMemberDef array */ PyMemberDef *find_memberdef(const PyMemberDef *mlist, const char *name) { const PyMemberDef *md; for (md = mlist; md->name != NULL; md++) if (name[0] == md->name[0] && strcmp(md->name+1, name+1) == 0) return (PyMemberDef *)md; /* this should never happen or the mlist is screwed up */ return NULL; } /** ** cfgtree_walk ** * walks ap_directive_t tree returning a list of * tuples and lists */ PyObject *cfgtree_walk(ap_directive_t *dir) { PyObject *list = PyList_New(0); if (!list) return PyErr_NoMemory(); while (dir) { PyObject *t = Py_BuildValue("(s, s)", dir->directive, dir->args); if (!t) return PyErr_NoMemory(); PyList_Append(list, t); Py_DECREF(t); if (dir->first_child) { PyObject *child = cfgtree_walk(dir->first_child); if (!child) return PyErr_NoMemory(); PyList_Append(list, child); Py_DECREF(child); } dir = dir->next; } return list; } /** ** makeipaddr ** * utility func to make an ip address */ static PyObject *makeipaddr(struct apr_sockaddr_t *addr) { char *str = NULL; apr_status_t rc; PyObject *ret = NULL; rc = apr_sockaddr_ip_get(&str, addr); if (rc==APR_SUCCESS) { ret = MpBytesOrUnicode_FromString(str); } else { PyErr_SetString(PyExc_SystemError,"apr_sockaddr_ip_get failure"); } return ret; } /** ** makesockaddr ** * utility func to make a socket address */ PyObject *makesockaddr(struct apr_sockaddr_t *addr) { PyObject *addrobj = makeipaddr(addr); PyObject *ret = NULL; if (addrobj) { apr_port_t port; port = addr->port; ret = Py_BuildValue("Oi", addrobj, port ); Py_DECREF(addrobj); } return ret; }
X Tutup