HEX
Server: LiteSpeed
System: Linux houston.panomity.com 6.8.0-100-generic #100-Ubuntu SMP PREEMPT_DYNAMIC Tue Jan 13 16:40:06 UTC 2026 x86_64
User: nudepix (1011)
PHP: 7.4.33
Disabled: pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,pcntl_unshare,
Upload Files
File: //tmp/wsgi-lsapi-2.1/wsgi.c
/*-
 * Copyright (c) 2006 Allan Saddi <allan@saddi.com>
 * 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.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS 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 AUTHOR OR 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.
 *
 * $Id$
 */

#include <Python.h>
#include <locale.h>
#include <wchar.h>

#include <assert.h>
#include <ctype.h>

#include "wsgi-int.h"
#include "lsapilib.h"

#include "interp.h"

const char *wsgiPyVersion = PY_VERSION;
PyObject *wsgiStderr;
const char *wsgiScriptName = "";
int wsgiScriptNameLen = 0;

static PyThreadState *_main;

#define LOG_FLAG   (LSAPI_LOG_TIMESTAMP_FULL|LSAPI_LOG_FLAG_ERROR|LSAPI_LOG_PID)
#define LOG_ERR(...)   LSAPI_Log(LOG_FLAG, __VA_ARGS__)


/* Assumes c is a valid hex digit */
static inline int toxdigit(int c)
{
    if (c >= '0' && c <= '9')
        return c - '0';
    else if (c >= 'A' && c <= 'F')
        return c - 'A' + 10;
    else if (c >= 'a' && c <= 'f')
        return c - 'a' + 10;
    return -1;
}


/* Unquote an escaped path */
const char *wsgiUnquote(const char *s)
{
    int len = strlen(s);
    char *result, *t;

    if ((result = PyMem_Malloc(len + 1)) == NULL)
        return NULL;

    t = result;
    while (*s)
    {
        if (*s == '%')
        {
            if (s[1] && s[2] && isxdigit(s[1]) && isxdigit(s[2]))
            {
                * (t++) = (toxdigit(s[1]) << 4) | toxdigit(s[2]);
                s += 3;
            }
            else
                * (t++) = * (s++);
        }
        else
            * (t++) = * (s++);
    }
    *t = '\0';

    return result;
}


int wsgiPutEnv(Request *self, const char *key, const char *value)
{
    PyObject *val;
    int ret;

#if PY_MAJOR_VERSION < 3
    if ((val = PyBytes_FromString(value)) == NULL)
#else
    if ((val = PyUnicode_DecodeLatin1(value, strlen(value), NULL)) == NULL)
#endif        
        return -1;
    ret = PyDict_SetItemString(self->environ, key, val);
    Py_DECREF(val);
    if (ret)
        return -1;
    return 0;
}


static void sendResponse500(void *ctxt)
{
    static const char *headers[] =
    {
        "Content-Type", "text/html; charset=iso-8859-1",
    };
    static const char *body =
        "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\n"
        "<html><head>\n"
        "<title>500 Internal Error</title>\n"
        "</head><body>\n"
        "<h1>Internal Error</h1>\n"
        "<p>The server encountered an unexpected condition which\n"
        "prevented it from fulfilling the request.</p>\n"
        "</body></html>\n";

    if (!wsgiSendHeaders(ctxt, 500, 1, headers))
        wsgiSendBody(ctxt, (uint8_t *) body, strlen(body));
}


static void Request_clear(Request *self)
{
    PyObject *tmp;

    tmp = self->result;
    self->result = NULL;
    Py_XDECREF(tmp);

    tmp = self->headers;
    self->headers = NULL;
    Py_XDECREF(tmp);

    tmp = self->input;
    self->input = NULL;
    Py_XDECREF(tmp);

    tmp = self->environ;
    self->environ = NULL;
    Py_XDECREF(tmp);
}


static void Request_dealloc(Request *self)
{
    Request_clear(self);
    Py_TYPE(self)->tp_free((PyObject *) self);
}


static PyObject *Request_new(PyTypeObject *type, PyObject *args,
                             PyObject *kwds)
{
    Request *self;

    self = (Request *) type->tp_alloc(type, 0);
    if (self != NULL)
    {
        self->environ = PyDict_New();
        if (self->environ == NULL)
        {
            Py_DECREF(self);
            return NULL;
        }

        self->input = NULL;
        self->statusCode = 200;
        self->headers = NULL;
        self->result = NULL;
        self->headers_sent = 0;
    }

    return (PyObject *) self;
}


/* Constructor. Accepts the context CObject as its sole argument. */
static int Request_init(Request *self, PyObject *args, PyObject *kwds)
{
    PyObject *context_obj, *args2;

    if (!PyArg_ParseTuple(args, "O!", &PyCapsule_Type, &context_obj))
        return -1;

    self->context = PyCapsule_GetPointer(context_obj, "Request");

    if ((args2 = Py_BuildValue("(Oi)", self,
                               wsgiGetContentLength(self->context))) == NULL)
        return -1;

    self->input = PyObject_CallObject((PyObject *) &InputStream_Type, args2);
    Py_DECREF(args2);
    if (self->input == NULL)
        return -1;

    return wsgiPopulateEnviron(self);
}


/* start_response() callable implementation */
static PyObject *Request_start_response(Request *self, PyObject *args)
{
    char *psStatus;
    PyObject *headers, *exc_info = NULL;
    PyObject *tmp;

    if (!PyArg_ParseTuple(args, "sO!|O:start_response", &psStatus,
                          &PyList_Type, &headers, &exc_info))
    {
        LOG_ERR(
                "Request_start_response() ParseTuple 'sO!|O:start_response' failed.\n");
        return NULL;
    }

    if (exc_info != NULL && exc_info != Py_None)
    {
        /* If the headers have already been sent, just propagate the
           exception. */
        if (self->headers_sent)
        {
            PyObject *type, *value, *tb;
            if (!PyArg_ParseTuple(exc_info, "OOO", &type, &value, &tb))
            {
                LOG_ERR("Request_start_response() ParseTuple 'OOO' failed.\n");
                return NULL;
            }
            Py_INCREF(type);
            Py_INCREF(value);
            Py_INCREF(tb);
            PyErr_Restore(type, value, tb);
            return NULL;
        }
    }
    else if (self->headers != NULL)
    {
        LOG_ERR("Request_start_response headers already set.\n");
        PyErr_SetString(PyExc_AssertionError, "headers already set");
        return NULL;
    }

    /* TODO validation of status and headers */

    self->statusCode = strtol(psStatus, NULL, 10);

    tmp = self->headers;
    Py_INCREF(headers);
    self->headers = headers;
    Py_XDECREF(tmp);

    return PyObject_GetAttrString((PyObject *) self, "write");
}


/* Sends headers. Assumes self->status and self->headers are valid. */
static int _wsgiSendHeaders(Request *self)
{
    int headerCount;
    const char **headers;
    int i, j;

    headerCount = PyList_Size(self->headers);
    if (PyErr_Occurred())
        return -1;

    /* NB: 1 extra header for Content-Length */
    if ((headers = PyMem_Malloc(sizeof(*headers) *
                                (headerCount * 2 + 2))) == NULL)
        return -1;

    for (i = 0, j = 0; i < headerCount; i++)
    {
        PyObject *item;
        const char *header, *value;

        if ((item = PyList_GetItem(self->headers, i)) == NULL)
            goto bad;

        if (!PyArg_ParseTuple(item, "ss", &header, &value))
            goto bad;

        headers[j++] = header;
        headers[j++] = value;
    }

    if (wsgiSendHeaders(self->context, self->statusCode,
                        headerCount, headers))
        goto bad;

    PyMem_Free(headers);
    return 0;

bad:
    PyMem_Free(headers);
    return -1;
}


/* Send a chunk of data */
static inline int wsgiWrite(Request *self, const char *data, int len)
{
    if (len)
    {
        if (wsgiSendBody(self->context, (uint8_t *) data, len))
            return -1;
    }
    return 0;
}


/* write() callable implementation */
static PyObject *Request_write(Request *self, PyObject *args)
{
    const char *data;
    int dataLen;

    if (self->headers == NULL)
    {
        PyErr_SetString(PyExc_AssertionError, "write() before start_response()");
        return NULL;
    }

    if (!PyArg_ParseTuple(args, "s#:write", &data, &dataLen))
        return NULL;

    /* Send headers if necessary */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return NULL;
        self->headers_sent = 1;
    }

    if (wsgiWrite(self, data, dataLen))
        return NULL;

    Py_INCREF(Py_None);
    return Py_None;
}

/* Send a wrapped file using wsgiSendFile */
static int
wsgiSendFileWrapper(Request *self, FileWrapper *wrapper)
{
    PyObject *pFileno, *args, *pFD;
    int fd;

    /* file-like must have fileno */
    if (!PyObject_HasAttrString((PyObject *) wrapper->filelike, "fileno"))
        return 1;

    if ((pFileno = PyObject_GetAttrString((PyObject *) wrapper->filelike,
                                          "fileno")) == NULL)
        return -1;

    if ((args = PyTuple_New(0)) == NULL)
    {
        Py_DECREF(pFileno);
        return -1;
    }

    pFD = PyObject_CallObject(pFileno, args);
    Py_DECREF(args);
    Py_DECREF(pFileno);
    if (pFD == NULL)
        return -1;

#if PY_MAJOR_VERSION >= 3
    fd = PyLong_AsLong(pFD);
#else
    fd = PyInt_AsLong(pFD);
#endif
    Py_DECREF(pFD);
    if (PyErr_Occurred())
        return -1;

    /* Send headers if necessary */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return -1;
        self->headers_sent = 1;
    }

    if (wsgiSendFile(self->context, fd))
        return -1;

    return 0;
}


/* Send the application's response */
static int wsgiSendResponse(Request *self, PyObject *result)
{
    PyObject *iter;
    PyObject *item;
    int ret;

    /* Check if it's a FileWrapper */
    if (result->ob_type == &FileWrapper_Type)
    {
        ret = wsgiSendFileWrapper(self, (FileWrapper *) result);
        if (ret < 0)
            return -1;
        if (!ret)
            return 0;
        /* Fallthrough */
    }

    iter = PyObject_GetIter(result);
    if (iter == NULL)
        return -1;

    while ((item = PyIter_Next(iter)))
    {
        int dataLen;
        const char *data;
        if (PyUnicode_Check(item))
        {
            PyObject *pBytes = PyUnicode_AsASCIIString(item);
            Py_DECREF(item);
            item = pBytes;
        }


        dataLen = PyBytes_Size(item);
        if (PyErr_Occurred())
        {
            Py_DECREF(item);
            break;
        }

        if (dataLen)
        {
            if ((data = PyBytes_AsString(item)) == NULL)
            {
                Py_DECREF(item);
                break;
            }

            /* Send headers if necessary */
            if (!self->headers_sent)
            {
                if (_wsgiSendHeaders(self))
                {
                    Py_DECREF(item);
                    break;
                }
                self->headers_sent = 1;
            }

            if (wsgiWrite(self, data, dataLen))
            {
                Py_DECREF(item);
                break;
            }
        }

        Py_DECREF(item);
    }

    Py_DECREF(iter);

    if (PyErr_Occurred())
        return -1;

    /* Send headers if they haven't been sent at this point */
    if (!self->headers_sent)
    {
        if (_wsgiSendHeaders(self))
            return -1;
        self->headers_sent = 1;
    }

    return 0;
}


/* Ensure application's iterator's close() method is called */
static void wsgiCallClose(PyObject *result)
{
    PyObject *type, *value, *traceback;
    PyObject *pClose, *args, *ret;

    /* Save exception state */
    PyErr_Fetch(&type, &value, &traceback);

    if (PyObject_HasAttrString(result, "close"))
    {
        pClose = PyObject_GetAttrString(result, "close");
        if (pClose != NULL)
        {
            args = PyTuple_New(0);
            if (args != NULL)
            {
                ret = PyObject_CallObject(pClose, args);
                Py_DECREF(args);
                Py_XDECREF(ret);
            }
            Py_DECREF(pClose);
        }
    }

    /* Restore exception state */
    PyErr_Restore(type, value, traceback);
}


static PyMethodDef Request_methods[] =
{
    {
        "start_response", (PyCFunction) Request_start_response, METH_VARARGS,
        "WSGI start_response callable"
    },
    {
        "write", (PyCFunction) Request_write, METH_VARARGS,
        "WSGI write callable"
    },
    { NULL }
};


PyTypeObject Request_Type =
{
    PyVarObject_HEAD_INIT(NULL, 0)
    "lsapi_wsgi.Request",        /*tp_name*/
    sizeof(Request),           /*tp_basicsize*/
    0,                         /*tp_itemsize*/
    (destructor) Request_dealloc,   /*tp_dealloc*/
    0,                         /*tp_print*/
    0,                         /*tp_getattr*/
    0,                         /*tp_setattr*/
    0,                         /*tp_compare*/
    0,                         /*tp_repr*/
    0,                         /*tp_as_number*/
    0,                         /*tp_as_sequence*/
    0,                         /*tp_as_mapping*/
    0,                         /*tp_hash */
    0,                         /*tp_call*/
    0,                         /*tp_str*/
    0,                         /*tp_getattro*/
    0,                         /*tp_setattro*/
    0,                         /*tp_as_buffer*/
    Py_TPFLAGS_DEFAULT,        /*tp_flags*/
    "WSGI Request class",      /* tp_doc */
    0,                         /* tp_traverse */
    0,                         /* tp_clear */
    0,                         /* tp_richcompare */
    0,                         /* tp_weaklistoffset */
    0,                         /* tp_iter */
    0,                         /* tp_iternext */
    Request_methods,           /* tp_methods */
    0,                         /* tp_members */
    0,                         /* tp_getset */
    0,                         /* tp_base */
    0,                         /* tp_dict */
    0,                         /* tp_descr_get */
    0,                         /* tp_descr_set */
    0,                         /* tp_dictoffset */
    (initproc) Request_init,   /* tp_init */
    0,                         /* tp_alloc */
    Request_new,               /* tp_new */
};


static PyMethodDef wsgisup_methods[] =
{
    { NULL }
};


#if PY_MAJOR_VERSION >= 3
static struct PyModuleDef wsgisup_moduledef =
{
    PyModuleDef_HEAD_INIT,
    "lsapi_wsgi",
    NULL,
    0,
    wsgisup_methods,
    NULL,
    NULL,
    NULL,
    NULL
};


#define INITERROR return NULL
#else

#define INITERROR return
#ifndef PyMODINIT_FUNC
#define PyMODINIT_FUNC void
#endif

#endif


PyMODINIT_FUNC init_wsgisup(void)
{
    PyObject *m = NULL;

    if (PyType_Ready(&Request_Type) < 0)
        INITERROR;
    if (PyType_Ready(&InputStream_Type) < 0)
        INITERROR;
    if (PyType_Ready(&FileWrapper_Type) < 0)
        INITERROR;

#if PY_MAJOR_VERSION >= 3
    m = PyModule_Create(&wsgisup_moduledef);
#else
    m = Py_InitModule3("lsapi_wsgi", wsgisup_methods,
                       "WSGI C support module");
#endif

    if (m == NULL)
        INITERROR;

    Py_INCREF(&Request_Type);
    PyModule_AddObject(m, "Request", (PyObject *) &Request_Type);

    Py_INCREF(&InputStream_Type);
    PyModule_AddObject(m, "InputStream", (PyObject *) &InputStream_Type);

    Py_INCREF(&FileWrapper_Type);
    PyModule_AddObject(m, "FileWrapper", (PyObject *) &FileWrapper_Type);

#if PY_MAJOR_VERSION >= 3
    return m;
#endif
}


void wsgiCleanup(void)
{
    PyEval_RestoreThread(_main);
    Py_XDECREF(wsgiStderr);
    Py_Finalize();
}


static PyObject *importModule(const char *name, const char *filename)
{
    PyObject *module = NULL;
    PyObject *code = NULL;
    PyObject *res = NULL;
    PyObject *io_module = NULL;
    PyObject *file_object = NULL;
    PyObject *source_object = NULL;
    const char *source_buf = NULL;

    io_module = PyImport_ImportModule("io");
    if (!io_module)
        goto end;

    file_object = PyObject_CallMethod(io_module, "open", "ss", filename, "rb");
    if (!file_object)
        goto end;

    source_object = PyObject_CallMethod(file_object, "read", "");
    if (!source_object)
        goto end;

    res = PyObject_CallMethod(file_object, "close", "");
    if (!res)
        goto end;

    source_buf = PyBytes_AsString(source_object);
    if (!source_buf)
        goto end;

    code = Py_CompileString(source_buf, filename, Py_file_input);
    if (code)
        module = PyImport_ExecCodeModuleEx((char *)name, code, (char *)filename);
end:
    if (PyErr_Occurred())
        PyErr_Print();
    Py_XDECREF(io_module);
    Py_XDECREF(file_object);
    Py_XDECREF(source_object);
    Py_XDECREF(res);
    Py_XDECREF(code);

    if (module)
        Py_XINCREF(module);
    return module;
}


#if PY_MAJOR_VERSION >= 3
wchar_t *to_wchar(const char *str)
{
    int len = strlen(str) + 1;
    wchar_t *ret = malloc(sizeof(wchar_t) * len);
    if (ret)
        mbstowcs(ret, str, len);
    return ret;
}
#else
#define to_wchar(str)  ((char *)str)
#endif


void python_init()
{
#if PY_MAJOR_VERSION >= 3
    setlocale(LC_CTYPE, "");
#endif
    const char *python_home = getenv("PYTHONHOME");
    if (python_home)
        Py_SetPythonHome(to_wchar(python_home));
    const char *python_bin = getenv("LS_PYTHONBIN");
    if (python_bin)
        Py_SetProgramName(to_wchar(python_bin));
    Py_Initialize();
#if PY_VERSION_HEX < 0x03090000
    PyEval_InitThreads();
#endif
    const char *wsgi_root = getenv("WSGI_ROOT");
    if (wsgi_root)
        chdir(wsgi_root);
}


void wsgiInit()
{
    python_init();

    //init the Types, do it here???
    init_wsgisup();

    _main = PyEval_SaveThread();

    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    wsgi_interpreters = PyDict_New();
    PyGILState_Release(gstate);

}


PyObject *wsgiImport(const char *module_name, int deref)
{
    PyObject *name, *module;
    name = PyUnicode_FromString(module_name);
    if (name == NULL)
        return NULL;

    module = PyImport_Import(name);
    Py_XDECREF(name);
    if (deref && module)
        Py_XDECREF(module);
    return module;
}


//Just for sub interpreter init
int wsgiSubInit (const char *progName )
{
    PyObject *sys_module;

#if PY_MAJOR_VERSION >= 3
    wchar_t *argv[1];
    
    //setlocale(LC_CTYPE,"");
    argv[0] = to_wchar(progName);
    if (argv[0])
    {
        PySys_SetArgv( 1, argv ); /* make sure sys.argv gets set */
        free(argv[0]);
    }
#else
    char *argv[1];
    argv[0] = (char *)progName;
    PySys_SetArgv(1, argv); /* make sure sys.argv gets set */
#endif
    if (wsgiImport("threading", 1) != NULL 
        && (sys_module = wsgiImport("sys", 0)) != NULL)
    {
        wsgiStderr = PyObject_GetAttrString(sys_module, "stderr");
        Py_DECREF(sys_module);
        if (wsgiStderr != NULL)
            return 0;
    }

    PyErr_Print();
    return -1;
}


PyObject *wsgiLoadModule(const char *moduleName)
{
    PyObject *pModule;
    char baseName[PATH_MAX] = {0};
    int pos = -1;
    const char *p = strrchr(moduleName, '/');
    if (p)
        strncpy(baseName, p + 1, sizeof(baseName));
    else
        strncpy(baseName, moduleName, sizeof(baseName));

    p = strchr(baseName, '.');
    if (p)
    {
        pos = p - baseName;
        baseName[pos] = 0x00;
    }

    pModule = importModule(baseName, moduleName);
//  fprintf(stdout, "wsgiLoadModule %s %s\n", baseName, moduleName);
    return pModule;
}


int fixMainFile(const char *moduleName)
{
    PyObject *m, *d;
    m = PyImport_AddModule("__main__");
    if (m == NULL)
        return -1;
    Py_INCREF(m);
    d = PyModule_GetDict(m);
    if (PyDict_GetItemString(d, "__file__") == NULL) {
        PyObject *f;
#if PY_MAJOR_VERSION >= 3
        f = PyUnicode_DecodeFSDefault(moduleName);
#else
        f = PyString_FromString(moduleName);
#endif
        if (f != NULL)
            PyDict_SetItemString(d, "__file__", f);
        Py_DECREF(f);
    }
    Py_DECREF(m);
    return 0;
}


PyObject *wsgiInitModule(PyObject *modict, const char *moduleName,
                         const char *appName, int reload)
{
    PyObject *module, *app = NULL;
    
    char * p = (char *)strrchr(moduleName, '/');
    if (p)
    {
        *p = 0;
        chdir(moduleName);
        *p = '/';
    }

    module = PyDict_GetItemString(modict, moduleName);
    if (module != NULL)
    {
        if (reload)
        {
            Py_DECREF(module);
            module = NULL;
            PyDict_DelItemString(modict, moduleName);
        }
        else
        {
            Py_INCREF(module);
        }
    }
    if (!module)
        module = wsgiLoadModule(moduleName);
    if (module != NULL)
    {
        PyDict_SetItemString(modict, moduleName, module);
        if ( appName == NULL )
            appName = "application";
        app = PyObject_GetAttrString(module, (char *) appName);

        Py_XDECREF(module);

        if (app == NULL || !PyCallable_Check(app))
        {
            LOG_ERR("wsgiHandler getApp [%s] failed, pApp=%p.\n", appName,
                    app);
            if (app)
            {
                Py_XDECREF(app);
                app = NULL;
            }
        }
    }
    
    return app;
}


//The global modict
static PyObject *modict = NULL;


PyObject *preload_module(const char *moduleName, const char *appName, const char *progName)
{
    PyObject *app = NULL;
    PyGILState_STATE gstate;
    gstate = PyGILState_Ensure();
    if (wsgiSubInit(progName) != 0)
    {
        LOG_ERR("wsgiHandler wsgiSubInit ERROR.\n");
    }
    else
    {
        fixMainFile(moduleName);
        modict = PyDict_New();
        app = wsgiInitModule(modict, moduleName, appName, 0);
    }
    PyGILState_Release(gstate);
    return app;
}


int wsgiHandler(void *ctxt, char *moduleName, char *appName,
                const char *progName)
{
    PyGILState_STATE gstate;
    PyObject *ctxt_c_obj, *args, *start_resp;
    Request *req_obj = NULL;
    PyObject *result;
    int renew = 0;
    InterpreterObject *interp = NULL;
    const char *app_group_name = NULL;
    char *reloading = NULL;
    int reload = 0;
    PyObject *pApp;

    //a pointer to global or sub
    PyObject **pmodict = NULL;

    app_group_name = LSAPI_GetEnv_r((LSAPI_Request *)ctxt, "WSGIApplicationGroup");
#ifdef __DEBUG__
    //LOG_ERR("lsapi_wsgi: interpreter '%s'.\n", app_group_name);
#endif

    if (!app_group_name || strcasecmp(app_group_name, "global") == 0)
    {
        pmodict = &modict;
        gstate = PyGILState_Ensure();
    }
    else
    {
        interp = wsgi_acquire_interpreter(app_group_name, &renew);
        if (!interp)
        {
            LOG_ERR("wsgi_acquire_interpreter ERROR for name %s. \n", app_group_name);
            goto out;
        }
        pmodict = &interp->modict;
    }

    if (*pmodict == NULL)
    {
        if (wsgiSubInit(progName) != 0)
        {
            LOG_ERR("wsgiHandler wsgiSubInit ERROR.\n");
            goto out;
        }
        *pmodict = PyDict_New();
    }

    if (moduleName == NULL)
    {
        moduleName = LSAPI_GetScriptFileName_r((LSAPI_Request *) ctxt );
        appName = LSAPI_GetEnv_r((LSAPI_Request*)ctxt, "WSGICallableObject");
        if (moduleName == NULL )
        {
            LOG_ERR("wsgiLoadModule Error, moduleName is NULL.");
            goto out;
        }
    }
    
    if (renew == 0)
    {
        //setting "WSGIScriptReloading"
        reloading = LSAPI_GetEnv_r((LSAPI_Request*)ctxt, "WSGIScriptReloading");
        if (reloading != NULL && strcmp(reloading, "ON") == 0)
            reload = 1;
    }

    pApp = wsgiInitModule(*pmodict, moduleName, appName, reload);
    if (pApp == NULL)
        goto out;

    /* Create Request object, passing it the context as a CObject */
    ctxt_c_obj = PyCapsule_New(ctxt, "Request", NULL);
    if (ctxt_c_obj == NULL)
    {
        LOG_ERR("wsgiHandler failed to create Request object.\n");
        goto out;
    }

    args = Py_BuildValue("(O)", ctxt_c_obj);
    Py_DECREF(ctxt_c_obj);
    if (args == NULL)
    {
        LOG_ERR("wsgiHandler failed to build args.\n");
        goto out;
    }

    req_obj = (Request *) PyObject_CallObject((PyObject *) &Request_Type,
              args);
    Py_DECREF(args);
    if (req_obj == NULL)
    {
        LOG_ERR("wsgiHandler failed to create req_obj.\n");
        goto out;
    }
    wsgiSetRequestData(ctxt, req_obj);


    /* Get start_response callable */
    start_resp = PyObject_GetAttrString((PyObject *) req_obj,
                                        "start_response");
    if (start_resp == NULL)
    {
        LOG_ERR("wsgiHandler missing start_response.\n");
        goto out;
    }

    /* Build arguments and call application object */
    args = Py_BuildValue("(OO)", req_obj->environ, start_resp);
    Py_DECREF(start_resp);
    if (args == NULL)
    {
        LOG_ERR("wsgiHandler failed to build start_resp args.\n");
        goto out;
    }

    result = PyObject_CallObject(pApp, args);
    Py_DECREF(args);
    Py_XDECREF(pApp);

    if (result != NULL)
    {
        /* Handle the application response */
        req_obj->result = result;
        /* result now owned by req_obj */
        wsgiSendResponse(req_obj, result);    /* ignore return */
        wsgiCallClose(result);
    }
    else
        LOG_ERR("wsgiHandler pApp->start_response() return NULL.\n");
out:
    if (PyErr_Occurred())
    {
        PyErr_Print();

        /* Display HTTP 500 error, if possible */
        if (req_obj == NULL || !req_obj->headers_sent)
            sendResponse500(ctxt);
    }

    if (req_obj != NULL)
    {
        wsgiSetRequestData(ctxt, NULL);

        /* Don't rely on cyclic GC. Clear circular references NOW. */
        Request_clear(req_obj);

        Py_DECREF(req_obj);
    }

    if (interp)
        wsgi_release_interpreter(interp);
    else
        PyGILState_Release(gstate);

    /* Always return success. */
    return 0;
}


int wsgiAppHandler(void *ctxt, PyObject *app)
{
    PyObject *ctxt_c_obj, *args, *start_resp;
    Request *req_obj = NULL;
    PyObject *result;

    //LOG_ERR("wsgiAppHandler(%p)\n", app);

    if (app == NULL)
        goto out;

    /* Create Request object, passing it the context as a CObject */
    ctxt_c_obj = PyCapsule_New(ctxt, "Request", NULL);
    if (ctxt_c_obj == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to create Request object.\n");
        goto out;
    }

    args = Py_BuildValue("(O)", ctxt_c_obj);
    Py_DECREF(ctxt_c_obj);
    if (args == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to build args.\n");
        goto out;
    }
    //LOG_ERR("wsgiAppHandler args created.\n");

    req_obj = (Request *) PyObject_CallObject((PyObject *) &Request_Type,
              args);
    Py_DECREF(args);
    if (req_obj == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to create req_obj.\n");
        goto out;
    }
    wsgiSetRequestData(ctxt, req_obj);

    //LOG_ERR("wsgiAppHandler create start_response.\n");

    /* Get start_response callable */
    start_resp = PyObject_GetAttrString((PyObject *) req_obj,
                                        "start_response");
    if (start_resp == NULL)
    {
        LOG_ERR("wsgiHandler missing start_response.\n");
        goto out;
    }

    /* Build arguments and call application object */
    args = Py_BuildValue("(OO)", req_obj->environ, start_resp);
    Py_DECREF(start_resp);
    if (args == NULL)
    {
        LOG_ERR("wsgiAppHandler failed to build start_resp args.\n");
        goto out;
    }

    //LOG_ERR("wsgiAppHandler call app->start_response.\n");

    result = PyObject_CallObject(app, args);
    Py_DECREF(args);

    if (result != NULL)
    {
        /* Handle the application response */
        req_obj->result = result;
        /* result now owned by req_obj */
        wsgiSendResponse(req_obj, result);    /* ignore return */
        wsgiCallClose(result);
    }
    else
        LOG_ERR("wsgiAppHandler pApp->start_response() return NULL.\n");
out:
    if (PyErr_Occurred())
    {
        PyErr_Print();

        /* Display HTTP 500 error, if possible */
        if (req_obj == NULL || !req_obj->headers_sent)
            sendResponse500(ctxt);
    }

    if (req_obj != NULL)
    {
        wsgiSetRequestData(ctxt, NULL);

        /* Don't rely on cyclic GC. Clear circular references NOW. */
        Request_clear(req_obj);

        Py_DECREF(req_obj);
    }

    /* Always return success. */
    return 0;
}