Ejemplo n.º 1
0
static int
header_field_cb(http_parser *p, const char *buf, size_t len)
{
    request *req = get_current_request(p);
    PyObject *env = NULL, *obj = NULL;
#ifdef PY3
    char *c1, *c2;
    PyObject *f, *v;
#endif
    /* DEBUG("field key:%.*s", (int)len, buf); */

    if(req->last_header_element != FIELD){
        env = req->environ;
        if(LIMIT_REQUEST_FIELDS <= req->num_headers){
            req->bad_request_code = 400;
            return -1;
        }
#ifdef PY3
        //TODO CHECK ERROR 
        c1 = PyBytes_AS_STRING(req->field);
        f = PyUnicode_DecodeLatin1(c1, strlen(c1), NULL);
        c2 = PyBytes_AS_STRING(req->value);
        v = PyUnicode_DecodeLatin1(c2, strlen(c2), NULL);
        PyDict_SetItem(env, f, v);
        Py_DECREF(f);
        Py_DECREF(v);
#else
        PyDict_SetItem(env, req->field, req->value);
#endif
        Py_DECREF(req->field);
        Py_DECREF(req->value);
        req->field = NULL;
        req->value = NULL;
        req->num_headers++;
    }

    if(likely(req->field == NULL)){
        obj = get_http_header_key(buf, len);
    }else{
        char temp[len];
        key_upper(temp, buf, len);
        obj = concat_string(req->field, temp, len);
    }

    if(unlikely(obj == NULL)){
        req->bad_request_code = 500;
        return -1;
    }
    if(unlikely(PyBytes_GET_SIZE(obj) > LIMIT_REQUEST_FIELD_SIZE)){
        req->bad_request_code = 400;
        return -1;
    }

    req->field = obj;
    req->last_header_element = FIELD;
    return 0;
}
Ejemplo n.º 2
0
static PyObject *
HunSpell_suggest(HunSpell * self, PyObject *args)
{
    char *word, **slist;
    int i, num_slist, ret, str_size;
    PyObject *slist_list, *pystr;
    PyObject *etype, *evalue, *etrace;

    if (!PyArg_ParseTuple(args, "et", self->encoding, &word))
        return NULL;

    slist_list = PyList_New(0);
    if (!slist_list) {
        return NULL;
    }
    num_slist = self->handle->suggest(&slist, word);
    PyMem_Free(word);

    for (i = 0, ret = 0; !ret && i < num_slist; i++) {
        str_size = strlen(slist[i]);
        pystr = PyUnicode_DecodeUTF8(slist[i], str_size, "strict");
        if (!pystr) {
            PyErr_Fetch(&etype, &evalue, &etrace);
            Py_DECREF(etype);
            pystr = PyUnicode_DecodeLatin1(slist[i], str_size, "strict");
            if (!pystr)
                break;
        }
        ret = PyList_Append(slist_list, pystr);
        Py_DECREF(pystr);
    }

    self->handle->free_list(&slist, num_slist);
    return slist_list;
}
Ejemplo n.º 3
0
static PyObject* evaluate(PyObject* self, PyObject *args){
	ri = 0;
	oi = 0;
	if (!PyArg_ParseTuple(args, "s#|d", &input_buffer, &ibl, &timeout)) {
      return NULL;
	}
	timeout = timeout * 1000; //convert to seconds
	readp(0);
	return PyUnicode_DecodeLatin1(output_buffer, oi, NULL);
}
Ejemplo n.º 4
0
static PyObject *ffi_getctype(FFIObject *self, PyObject *args, PyObject *kwds)
{
    PyObject *c_decl, *res;
    char *p, *replace_with = "";
    int add_paren, add_space;
    CTypeDescrObject *ct;
    size_t replace_with_len;
    static char *keywords[] = {"cdecl", "replace_with", NULL};
#if PY_MAJOR_VERSION >= 3
    PyObject *u;
#endif

    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|s:getctype", keywords,
                                     &c_decl, &replace_with))
        return NULL;

    ct = _ffi_type(self, c_decl, ACCEPT_STRING|ACCEPT_CTYPE);
    if (ct == NULL)
        return NULL;

    while (replace_with[0] != 0 && isspace(replace_with[0]))
        replace_with++;
    replace_with_len = strlen(replace_with);
    while (replace_with_len > 0 && isspace(replace_with[replace_with_len - 1]))
        replace_with_len--;

    add_paren = (replace_with[0] == '*' &&
                 ((ct->ct_flags & CT_ARRAY) != 0));
    add_space = (!add_paren && replace_with_len > 0 &&
                 replace_with[0] != '[' && replace_with[0] != '(');

    res = _combine_type_name_l(ct, replace_with_len + add_space + 2*add_paren);
    if (res == NULL)
        return NULL;

    p = PyBytes_AS_STRING(res) + ct->ct_name_position;
    if (add_paren)
        *p++ = '(';
    if (add_space)
        *p++ = ' ';
    memcpy(p, replace_with, replace_with_len);
    if (add_paren)
        p[replace_with_len] = ')';

#if PY_MAJOR_VERSION >= 3
    /* bytes -> unicode string */
    u = PyUnicode_DecodeLatin1(PyBytes_AS_STRING(res),
                               PyBytes_GET_SIZE(res),
                               NULL);
    Py_DECREF(res);
    res = u;
#endif

    return res;
}
Ejemplo n.º 5
0
static int
set_path(PyObject *env, char *buf, int len)
{
    int c, c1, slen;
    char *s0, *t;
    PyObject *obj;

    t = s0 = buf;
    while(len > 0){
        c = *buf++;
        if(c == '%' && len > 2){
            c = *buf++;
            c1 = c;
            c = *buf++;
            c = hex2int(c1) * 16 + hex2int(c);
            len -= 2;
        }else if(c == '?'){
            //stop
            if(set_query(env, buf, len) == -1){
                //Error
                return -1;
            }
            break;
        }else if(c == '#'){
            //stop 
            //ignore fragment
            break;
        }
        *t++ = c;
        len--;
    }
    //*t = 0;
    slen = t - s0;
    slen = urldecode(s0, slen);

#ifdef PY3
    obj = PyUnicode_DecodeLatin1(s0, slen, "strict");
#else
    obj = PyBytes_FromStringAndSize(s0, slen);
#endif
    if (likely(obj != NULL)) {
        PyDict_SetItem(env, path_info_key, obj);
        Py_DECREF(obj);
        return slen;
    } else {
        return -1;
    }
}
Ejemplo n.º 6
0
static int
set_query(PyObject *env, char *buf, int len)
{
    int c, ret, slen = 0;
    char *s0;
    PyObject *obj;
#ifdef PY3
    char *c2;
    PyObject *v;
#endif
    s0 = buf;
    while(len > 0){
        c = *buf++;
        if(c == '#'){
            slen++;
            break;
        }
        len--;
        slen++;
    }

    if(slen > 1){
        obj = PyBytes_FromStringAndSize(s0, slen -1);
        /* DEBUG("query:%.*s", len, PyBytes_AS_STRING(obj)); */
        if(unlikely(obj == NULL)){
            return -1;
        }
        
#ifdef PY3
        //TODO CHECK ERROR 
        c2 = PyBytes_AS_STRING(obj);
        v = PyUnicode_DecodeLatin1(c2, strlen(c2), NULL);
        ret = PyDict_SetItem(env, query_string_key, v);
        Py_DECREF(v);
#else
        ret = PyDict_SetItem(env, query_string_key, obj);
#endif
        Py_DECREF(obj);
        
        if(unlikely(ret == -1)){
            return -1;
        }
    }
    
    return 1; 
}
Ejemplo n.º 7
0
static PyObject *PyTraceObject_read(PyObject *self, PyObject *args)
{
    if (!PyArg_ParseTuple(args, ":read"))
        return NULL;
    int len;
    char *data;
    BOOL ok = static_cast<PyTraceObject*>(self)->ReadData(&data, &len, 0);
    if (!ok)
        return NULL;
#if (PY_VERSION_HEX < 0x03000000)
    PyObject *result = PyString_FromStringAndSize(data, len);
#else
    PyObject *result = PyUnicode_DecodeLatin1(data, len, "replace");
#endif
    free(data);
    return result;
}
Ejemplo n.º 8
0
 virtual void write(const char *a)
 {
     PyObject *result = NULL;
     if (_write_method) {
         PyObject *decoded = NULL;
         decoded = PyUnicode_DecodeLatin1(a, strlen(a), "");
         if (decoded == NULL) {
             throw py::exception();
         }
         result = PyObject_CallFunction(_write_method, (char *)"O", decoded);
         Py_DECREF(decoded);
         if (!result) {
             throw py::exception();
         }
         Py_DECREF(result);
     }
 }
Ejemplo n.º 9
0
static PyObject *DecodeString (UMTypeInfo *ti, char *value, size_t cbValue)
{
  //FIXME: This code must be endiness aware of system isn't little endian

  switch (ti->charset)
  {
  case MCS_big5_chinese_ci://1,
  case MCS_big5_bin://84,
  case MCS_dec8_swedish_ci://3,
  case MCS_dec8_bin://69,
  case MCS_cp850_general_ci://4,
  case MCS_cp850_bin://80,
  case MCS_hp8_english_ci://6,
  case MCS_hp8_bin://72,
  case MCS_koi8r_general_ci://7,
  case MCS_koi8r_bin://74,
    break;

  case MCS_latin1_german1_ci://5,
  case MCS_latin1_swedish_ci://8,
  case MCS_latin1_danish_ci://15,
  case MCS_latin1_german2_ci://31,
  case MCS_latin1_bin://47,
  case MCS_latin1_general_ci://48,
  case MCS_latin1_general_cs://49,
  case MCS_latin1_spanish_ci://94,
    return PyUnicode_DecodeLatin1 (value, cbValue, NULL);

  case MCS_latin2_czech_cs:// 2,
  case MCS_latin2_general_ci://9,
  case MCS_latin2_hungarian_ci://21,
  case MCS_latin2_croatian_ci://27,
  case MCS_latin2_bin://77,
  case MCS_swe7_swedish_ci://10,
  case MCS_swe7_bin://82,
    break;

  case MCS_ascii_general_ci://11,
  case MCS_ascii_bin://65,
    return PyUnicode_DecodeASCII(value, cbValue, NULL);

  case MCS_ujis_japanese_ci://12,
  case MCS_ujis_bin://91,
  case MCS_sjis_japanese_ci://13,
  case MCS_sjis_bin://88,
  case MCS_hebrew_general_ci://16,
  case MCS_hebrew_bin://71,
  case MCS_tis620_thai_ci://18,
  case MCS_tis620_bin://89,
  case MCS_euckr_korean_ci://19,
  case MCS_euckr_bin://85,
  case MCS_koi8u_general_ci://22,
  case MCS_koi8u_bin://75,
  case MCS_gb2312_chinese_ci://24,
  case MCS_gb2312_bin://86,
  case MCS_greek_general_ci://25,
  case MCS_greek_bin://70,
    break;

  case MCS_cp1250_general_ci://26,
  case MCS_cp1250_czech_cs://34,
  case MCS_cp1250_croatian_ci://44,
  case MCS_cp1250_bin://66,
  case MCS_cp1250_polish_ci://99,
    return PyUnicode_Decode(value, cbValue, "cp1250", NULL);

  case MCS_gbk_chinese_ci://28,
  case MCS_gbk_bin://87,
  case MCS_latin5_turkish_ci://30,
  case MCS_latin5_bin://78,
  case MCS_armscii8_general_ci://32,
  case MCS_armscii8_bin://64,
    break;

  case MCS_utf8_general_ci://33,
  case MCS_utf8_bin://83,
  case MCS_utf8_unicode_ci://192,
  case MCS_utf8_icelandic_ci://193,
  case MCS_utf8_latvian_ci://194,
  case MCS_utf8_romanian_ci://195,
  case MCS_utf8_slovenian_ci://196,
  case MCS_utf8_polish_ci://197,
  case MCS_utf8_estonian_ci://198,
  case MCS_utf8_spanish_ci://199,
  case MCS_utf8_swedish_ci://200,
  case MCS_utf8_turkish_ci://201,
  case MCS_utf8_czech_ci://202,
  case MCS_utf8_danish_ci://203,
  case MCS_utf8_lithuanian_ci://204,
  case MCS_utf8_slovak_ci://205,
  case MCS_utf8_spanish2_ci://206,
  case MCS_utf8_roman_ci://207,
  case MCS_utf8_persian_ci://208,
  case MCS_utf8_esperanto_ci://209,
  case MCS_utf8_hungarian_ci://210,
  case MCS_utf8_sinhala_ci://211,
    return PyUnicode_DecodeUTF8 (value, cbValue, NULL);

  case MCS_ucs2_general_ci://35,
  case MCS_ucs2_bin://90,
  case MCS_ucs2_unicode_ci://128,
  case MCS_ucs2_icelandic_ci://129,
  case MCS_ucs2_latvian_ci://130,
  case MCS_ucs2_romanian_ci://131,
  case MCS_ucs2_slovenian_ci://132,
  case MCS_ucs2_polish_ci://133,
  case MCS_ucs2_estonian_ci://134,
  case MCS_ucs2_spanish_ci://135,
  case MCS_ucs2_swedish_ci://136,
  case MCS_ucs2_turkish_ci://137,
  case MCS_ucs2_czech_ci://138,
  case MCS_ucs2_danish_ci://139,
  case MCS_ucs2_lithuanian_ci://140,
  case MCS_ucs2_slovak_ci://141,
  case MCS_ucs2_spanish2_ci://142,
  case MCS_ucs2_roman_ci://143,
  case MCS_ucs2_persian_ci://144,
  case MCS_ucs2_esperanto_ci://145,
  case MCS_ucs2_hungarian_ci://146,
  case MCS_ucs2_sinhala_ci://147,
    break;

  case MCS_cp866_general_ci://36,
  case MCS_cp866_bin://68,
  case MCS_keybcs2_general_ci://37,
  case MCS_keybcs2_bin://73,
  case MCS_macce_general_ci://38,
  case MCS_macce_bin://43,
  case MCS_macroman_general_ci://39,
  case MCS_macroman_bin://53,
  case MCS_cp852_general_ci://40,
  case MCS_cp852_bin://81,
  case MCS_latin7_estonian_cs://20,
  case MCS_latin7_general_ci://41,
  case MCS_latin7_general_cs://42,
  case MCS_latin7_bin://79,
  case MCS_utf8mb4_general_ci://45,
  case MCS_utf8mb4_bin://46,
  case MCS_utf8mb4_unicode_ci://224,
  case MCS_utf8mb4_icelandic_ci://225,
  case MCS_utf8mb4_latvian_ci://226,
  case MCS_utf8mb4_romanian_ci://227,
  case MCS_utf8mb4_slovenian_ci://228,
  case MCS_utf8mb4_polish_ci://229,
  case MCS_utf8mb4_estonian_ci://230,
  case MCS_utf8mb4_spanish_ci://231,
  case MCS_utf8mb4_swedish_ci://232,
  case MCS_utf8mb4_turkish_ci://233,
  case MCS_utf8mb4_czech_ci://234,
  case MCS_utf8mb4_danish_ci://235,
  case MCS_utf8mb4_lithuanian_ci://236,
  case MCS_utf8mb4_slovak_ci://237,
  case MCS_utf8mb4_spanish2_ci://238,
  case MCS_utf8mb4_roman_ci://239,
  case MCS_utf8mb4_persian_ci://240,
  case MCS_utf8mb4_esperanto_ci://241,
  case MCS_utf8mb4_hungarian_ci://242,
  case MCS_utf8mb4_sinhala_ci://243,
  case MCS_cp1251_bulgarian_ci://14,
  case MCS_cp1251_ukrainian_ci://23,
  case MCS_cp1251_bin://50,
  case MCS_cp1251_general_ci://51,
  case MCS_cp1251_general_cs://52,
    break;

  case MCS_utf16_general_ci://54,
  case MCS_utf16_bin://55,
  case MCS_utf16_unicode_ci://101,
  case MCS_utf16_icelandic_ci://102,
  case MCS_utf16_latvian_ci://103,
  case MCS_utf16_romanian_ci://104,
  case MCS_utf16_slovenian_ci://105,
  case MCS_utf16_polish_ci://106,
  case MCS_utf16_estonian_ci://107,
  case MCS_utf16_spanish_ci://108,
  case MCS_utf16_swedish_ci://109,
  case MCS_utf16_turkish_ci://110,
  case MCS_utf16_czech_ci://111,
  case MCS_utf16_danish_ci://112,
  case MCS_utf16_lithuanian_ci://113,
  case MCS_utf16_slovak_ci://114,
  case MCS_utf16_spanish2_ci://115,
  case MCS_utf16_roman_ci://116,
  case MCS_utf16_persian_ci://117,
  case MCS_utf16_esperanto_ci://118,
  case MCS_utf16_hungarian_ci://119,
  case MCS_utf16_sinhala_ci://120,
    //return PyUnicode_DecodeUTF16(value, cbValue / 2, NULL, NULL);
    break;

  case MCS_cp1256_general_ci://57,
  case MCS_cp1256_bin://67,
    break;

  case MCS_cp1257_lithuanian_ci://29,
  case MCS_cp1257_bin://58,
  case MCS_cp1257_general_ci://59,
    break;

  case MCS_utf32_general_ci://60,
  case MCS_utf32_bin://61,
  case MCS_utf32_unicode_ci://160,
  case MCS_utf32_icelandic_ci://161,
  case MCS_utf32_latvian_ci://162,
  case MCS_utf32_romanian_ci://163,
  case MCS_utf32_slovenian_ci://164,
  case MCS_utf32_polish_ci://165,
  case MCS_utf32_estonian_ci://166,
  case MCS_utf32_spanish_ci://167,
  case MCS_utf32_swedish_ci://168,
  case MCS_utf32_turkish_ci://169,
  case MCS_utf32_czech_ci://170,
  case MCS_utf32_danish_ci://171,
  case MCS_utf32_lithuanian_ci://172,
  case MCS_utf32_slovak_ci://173,
  case MCS_utf32_spanish2_ci://174,
  case MCS_utf32_roman_ci://175,
  case MCS_utf32_persian_ci://176,
  case MCS_utf32_esperanto_ci://177,
  case MCS_utf32_hungarian_ci://178,
  case MCS_utf32_sinhala_ci://179,
    //return PyUnicode_DecodeUTF32 (value, cbValue / 4, NULL, NULL);
    break;

  case MCS_geostd8_general_ci://92,
  case MCS_geostd8_bin://93,
  case MCS_cp932_japanese_ci://95,
  case MCS_cp932_bin://96,
  case MCS_eucjpms_japanese_ci://97,
  case MCS_eucjpms_bin://98,
    break;

  case MCS_binary:
    return PyString_FromStringAndSize(value, cbValue);

  default:
    break;
  }

  return PyErr_Format (PyExc_ValueError, "Unsupported character set %d when decoding string", (int) ti->charset);
}
Ejemplo n.º 10
0
void *uwsgi_request_subhandler_wsgi(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {

	PyObject *zero;
	int i;
	PyObject *pydictkey, *pydictvalue;
	char *path_info;

        for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
                uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
                pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
                pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
                pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
                pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif

#ifdef UWSGI_DEBUG
		uwsgi_log("%p %d %p %d\n", pydictkey, wsgi_req->hvec[i].iov_len, pydictvalue, wsgi_req->hvec[i + 1].iov_len);
#endif
                PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
                Py_DECREF(pydictkey);
		Py_DECREF(pydictvalue);
        }

        if (wsgi_req->uh.modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
                wsgi_req->uh.modifier1 = 0;
                pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
                if (pydictkey) {
                        if (PyString_Check(pydictkey)) {
                                pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
                                if (pydictvalue) {
                                        if (PyString_Check(pydictvalue)) {
                                                path_info = PyString_AsString(pydictvalue);
                                                PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
                                        }
                                }
                        }
                }
        }


        // if async_post is mapped as a file, directly use it as wsgi.input
        if (wsgi_req->async_post) {
#ifdef PYTHREE
                wsgi_req->async_input = PyFile_FromFd(fileno((FILE *)wsgi_req->async_post), "wsgi_input", "rb", 0, NULL, NULL, NULL, 0);
#else
                wsgi_req->async_input = PyFile_FromFile(wsgi_req->async_post, "wsgi_input", "r", NULL);
#endif
        }
        else {
                // create wsgi.input custom object
                wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
                ((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;
                ((uwsgi_Input*)wsgi_req->async_input)->pos = 0;
                ((uwsgi_Input*)wsgi_req->async_input)->readline_pos = 0;
                ((uwsgi_Input*)wsgi_req->async_input)->readline_max_size = 0;

        }


        PyDict_SetItemString(wsgi_req->async_environ, "wsgi.input", wsgi_req->async_input);

#ifdef UWSGI_SENDFILE
	PyDict_SetItemString(wsgi_req->async_environ, "wsgi.file_wrapper", wi->sendfile);
#endif

#ifdef UWSGI_ASYNC
	if (uwsgi.async > 1) {
		PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.readable", wi->eventfd_read);
		PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.writable", wi->eventfd_write);
		PyDict_SetItemString(wsgi_req->async_environ, "x-wsgiorg.fdevent.timeout", Py_None);
	}
#endif

	PyDict_SetItemString(wsgi_req->async_environ, "wsgi.version", wi->gateway_version);

	zero = PyFile_FromFile(stderr, "wsgi_errors", "w", NULL);
	PyDict_SetItemString(wsgi_req->async_environ, "wsgi.errors", zero);
	Py_DECREF(zero);

	PyDict_SetItemString(wsgi_req->async_environ, "wsgi.run_once", Py_False);



	if (uwsgi.threads > 1) {
		PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_True);
	}
	else {
		PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multithread", Py_False);
	}
	if (uwsgi.numproc == 1) {
		PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_False);
	}
	else {
		PyDict_SetItemString(wsgi_req->async_environ, "wsgi.multiprocess", Py_True);
	}


	if (wsgi_req->scheme_len > 0) {
		zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
	}
	else if (wsgi_req->https_len > 0) {
		if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
			zero = UWSGI_PYFROMSTRING("https");
		}
		else {
			zero = UWSGI_PYFROMSTRING("http");
		}
	}
	else {
		zero = UWSGI_PYFROMSTRING("http");
	}
	PyDict_SetItemString(wsgi_req->async_environ, "wsgi.url_scheme", zero);
	Py_DECREF(zero);

	wsgi_req->async_app = wi->callable;

	// export .env only in non-threaded mode
	if (uwsgi.threads < 2) {
		PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
	}

	PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);

	if (uwsgi.cores > 1) {
		zero = PyInt_FromLong(wsgi_req->async_id);
		PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", zero);
		Py_DECREF(zero);
	}

	// cache this ?
	if (uwsgi.cluster_fd >= 0) {
		zero = PyString_FromString(uwsgi.cluster);
		PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster", zero);
		Py_DECREF(zero);
		zero = PyString_FromString(uwsgi.hostname);
		PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.cluster_node", zero);
		Py_DECREF(zero);
	}

	PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);

	// call
	PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
	return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
Ejemplo n.º 11
0
int
headers_complete_cb(http_parser *p)
{
    PyObject *obj;
    int ret;
    uint64_t content_length = 0;

    client_t *client = get_client(p);
    request *req = client->current_req;
    PyObject *env = req->environ;
    
    DEBUG("should keep alive %d", http_should_keep_alive(p));
    client->keep_alive = http_should_keep_alive(p);

    if(p->content_length != ULLONG_MAX){
        content_length = p->content_length;
        if(max_content_length < content_length){
            RDEBUG("max_content_length over %d/%d", (int)content_length, (int)max_content_length);
            DEBUG("set request code %d", 413);
            req->bad_request_code = 413;
            return -1;
        }
    }

    if(p->http_major == 1 && p->http_minor == 1){
        obj = server_protocol_val11;
    }else{
        obj = server_protocol_val10;
    }

    ret = PyDict_SetItem(env, server_protocol_key, obj);
    if(unlikely(ret == -1)){
        return -1;
    }

    if(likely(req->path)){
        ret = set_path(env, req->path->buf, req->path->len);
        free_buffer(req->path);
        if(unlikely(ret == -1)){
           //TODO Error 
           return -1;
        }
    }else{
        ret = PyDict_SetItem(env, path_info_key, empty_string);
        if(ret == -1){
            return -1;
        }
    }
    req->path = NULL;

    //Last header
    if(likely(req->field && req->value)){

#ifdef PY3
        //TODO CHECK ERROR 
        char *c1 = PyBytes_AS_STRING(req->field);
        PyObject *f = PyUnicode_DecodeLatin1(c1, strlen(c1), NULL);
        char *c2 = PyBytes_AS_STRING(req->value);
        PyObject *v = PyUnicode_DecodeLatin1(c2, strlen(c2), NULL);
        PyDict_SetItem(env, f, v);
        Py_DECREF(f);
        Py_DECREF(v);
#else
        PyDict_SetItem(env, req->field, req->value);
#endif
        Py_DECREF(req->field);
        Py_DECREF(req->value);
        req->field = NULL;
        req->value = NULL;
        if(unlikely(ret == -1)){
            return -1;
        }
    }
    ret = replace_env_key(env, h_content_type_key, content_type_key);
    if(unlikely(ret == -1)){
        return -1;
    }
    ret = replace_env_key(env, h_content_length_key, content_length_key);
    if(unlikely(ret == -1)){
        return -1;
    }

    switch(p->method){
        case HTTP_DELETE:
            obj = http_method_delete;
            break;
        case HTTP_GET:
            obj = http_method_get;
            break;
        case HTTP_HEAD:
            obj = http_method_head;
            break;
        case HTTP_POST:
            obj = http_method_post;
            break;
        case HTTP_PUT:
            obj = http_method_put;
            break;
        case HTTP_PATCH:
            obj = http_method_patch;
            break;
        case HTTP_CONNECT:
            obj = http_method_connect;
            break;
        case HTTP_OPTIONS:
            obj = http_method_options;
            break;
        case  HTTP_TRACE:
            obj = http_method_trace;
            break;
        case HTTP_COPY:
            obj = http_method_copy;
            break;
        case HTTP_LOCK:
            obj = http_method_lock;
            break;
        case HTTP_MKCOL:
            obj = http_method_mkcol;
            break;
        case HTTP_MOVE:
            obj = http_method_move;
            break;
        case HTTP_PROPFIND:
            obj = http_method_propfind;
            break;
        case HTTP_PROPPATCH:
            obj = http_method_proppatch;
            break;
        case HTTP_UNLOCK:
            obj = http_method_unlock;
            break;
        case HTTP_REPORT:
            obj = http_method_report;
            break;
        case HTTP_MKACTIVITY:
            obj = http_method_mkactivity;
            break;
        case HTTP_CHECKOUT:
            obj = http_method_checkout;
            break;
        case HTTP_MERGE:
            obj = http_method_merge;
            break;
        default:
            obj = http_method_get;
            break;
    }

    ret = PyDict_SetItem(env, request_method_key, obj);
    if(unlikely(ret == -1)){
        return -1;
    }
    req->body_length = content_length;
    /* client->current_req = NULL; */

    //keep client data
    obj = ClientObject_New(client);
    if(unlikely(obj == NULL)){
        return -1;
    }
    ret = PyDict_SetItem(env, client_key, obj);
    Py_DECREF(obj);
    if(unlikely(ret == -1)){
        return -1;
    }

    DEBUG("fin headers_complete_cb");
    return 0;
}
Ejemplo n.º 12
0
static PyObject *parse_qs(PyObject *self, PyObject *args)
{

    PyObject *pairs, *dict;
    int i, n, len, lsize;
    char *qs;
    PyObject *qso;
    char unicode = 0;
    int keep_blank_values = 0;
    int strict_parsing = 0; /* XXX not implemented */

    if (! PyArg_ParseTuple(args, "O|ii", &qso, &keep_blank_values,
                           &strict_parsing))
        return NULL; /* error */

    if (PyUnicode_Check(qso))
        unicode = 1;

    MP_ANYSTR_AS_STR(qs, qso, 1);
    if (!qs) {
        Py_DECREF(qso); /* MP_ANYSTR_AS_STR */
        return NULL;
    }

    /* split query string by '&' and ';' into a list of pairs */
    pairs = PyList_New(0);
    if (pairs == NULL) {
        Py_DECREF(qso);
        return NULL;
    }

    i = 0;
    len = strlen(qs);

    while (i < len) {

        PyObject *pair;
        char *cpair;
        int j = 0;

        pair = PyBytes_FromStringAndSize(NULL, len);
        if (pair == NULL) {
            Py_DECREF(qso);
            return NULL;
        }

        /* split by '&' or ';' */
        cpair = PyBytes_AS_STRING(pair);
        while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) {
            /* replace '+' with ' ' */
            cpair[j] = (qs[i] == '+') ? ' ' : qs[i];
            i++;
            j++;
        }

        if (j) {
            _PyBytes_Resize(&pair, j);
            if (pair)
                PyList_Append(pairs, pair);
        }

        Py_XDECREF(pair);
        i++;
    }

    Py_DECREF(qso); /* MP_ANYSTR_AS_STR */

    /*
     * now we have a list of "abc=def" string (pairs), let's split
     * them all by '=' and put them in a dictionary.
     */

    dict = PyDict_New();
    if (dict == NULL)
        return NULL;

    lsize = PyList_Size(pairs);
    n = 0;

    while (n < lsize) {

        PyObject *pair, *key, *val;
        char *cpair, *ckey, *cval;
        int k, v;

        pair = PyList_GET_ITEM(pairs, n);
        cpair = PyBytes_AS_STRING(pair);

        len = strlen(cpair);
        key = PyBytes_FromStringAndSize(NULL, len);
        if (key == NULL)
            return NULL;

        val = PyBytes_FromStringAndSize(NULL, len);
        if (val == NULL)
            return NULL;

        ckey = PyBytes_AS_STRING(key);
        cval = PyBytes_AS_STRING(val);

        i = 0;
        k = 0;
        v = 0;
        while (i < len) {
            if (cpair[i] != '=') {
                ckey[k] = cpair[i];
                k++;
                i++;
            }
            else {
                i++;      /* skip '=' */
                while (i < len) {
                    cval[v] = cpair[i];
                    v++;
                    i++;
                }
            }
        }

        ckey[k] = '\0';
        cval[v] = '\0';

        if (keep_blank_values || (v > 0)) {

            ap_unescape_url(ckey);
            ap_unescape_url(cval);

            _PyBytes_Resize(&key, strlen(ckey));
            _PyBytes_Resize(&val, strlen(cval));

            if (key && val) {

                ckey = PyBytes_AS_STRING(key);
                cval = PyBytes_AS_STRING(val);

                if (unicode) {
                    PyObject *list, *ukey, *uval;
                    ukey = PyUnicode_DecodeLatin1(ckey, strlen(ckey), NULL);
                    uval = PyUnicode_DecodeLatin1(ckey, strlen(cval), NULL);
                    list = PyDict_GetItem(dict, ukey);
                    if (list) {
                        PyList_Append(list, uval);
                        Py_DECREF(uval);
                    } else {
                        list = Py_BuildValue("[O]", uval);
                        PyDict_SetItem(dict, ukey, list);
                        Py_DECREF(ukey);
                        Py_DECREF(list);
                    }
                } else {
                    PyObject *list;
                    list = PyDict_GetItem(dict, key);
                    if (list)
                        PyList_Append(list, val);
                    else {
                        list = Py_BuildValue("[O]", val);
                        PyDict_SetItem(dict, key, list);
                        Py_DECREF(list);
                    }
                }
            }
        }

        Py_XDECREF(key);
        Py_XDECREF(val);

        n++;
    }

    Py_DECREF(pairs);
    return dict;
}
Ejemplo n.º 13
0
void *uwsgi_request_subhandler_web3(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {

	PyObject *zero;

	int i;
        PyObject *pydictkey, *pydictvalue;
        char *path_info;

        for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
                uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
#ifdef PYTHREE
                pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len, NULL);
                pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
                pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i].iov_len);
                pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
                PyDict_SetItem(wsgi_req->async_environ, pydictkey, pydictvalue);
                Py_DECREF(pydictkey);
                Py_DECREF(pydictvalue);
        }

        if (wsgi_req->uh->modifier1 == UWSGI_MODIFIER_MANAGE_PATH_INFO) {
                wsgi_req->uh->modifier1 = python_plugin.modifier1;
                pydictkey = PyDict_GetItemString(wsgi_req->async_environ, "SCRIPT_NAME");
                if (pydictkey) {
                        if (PyString_Check(pydictkey)) {
                                pydictvalue = PyDict_GetItemString(wsgi_req->async_environ, "PATH_INFO");
                                if (pydictvalue) {
                                        if (PyString_Check(pydictvalue)) {
                                                path_info = PyString_AsString(pydictvalue);
                                                PyDict_SetItemString(wsgi_req->async_environ, "PATH_INFO", PyString_FromString(path_info + PyString_Size(pydictkey)));
                                        }
                                }
                        }
                }
        }

        // create wsgi.input custom object
        wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
        ((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;

        PyDict_SetItemString(wsgi_req->async_environ, "web3.input", wsgi_req->async_input);

	PyDict_SetItemString(wsgi_req->async_environ, "web3.version", wi->gateway_version);

	zero = PyFile_FromFile(stderr, "web3_input", "w", NULL);
	PyDict_SetItemString(wsgi_req->async_environ, "web3.errors", zero);
	Py_DECREF(zero);

	PyDict_SetItemString(wsgi_req->async_environ, "web3.run_once", Py_False);

	PyDict_SetItemString(wsgi_req->async_environ, "web3.multithread", Py_False);
	if (uwsgi.numproc == 1) {
		PyDict_SetItemString(wsgi_req->async_environ, "web3.multiprocess", Py_False);
	}
	else {
		PyDict_SetItemString(wsgi_req->async_environ, "web3.multiprocess", Py_True);
	}

	if (wsgi_req->scheme_len > 0) {
		zero = UWSGI_PYFROMSTRINGSIZE(wsgi_req->scheme, wsgi_req->scheme_len);
	}
	else if (wsgi_req->https_len > 0) {
		if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
			zero = UWSGI_PYFROMSTRING("https");
		}
		else {
			zero = UWSGI_PYFROMSTRING("http");
		}
	}
	else {
		zero = UWSGI_PYFROMSTRING("http");
	}
	PyDict_SetItemString(wsgi_req->async_environ, "web3.url_scheme", zero);
	Py_DECREF(zero);


	wsgi_req->async_app = wi->callable;

	// export .env only in non-threaded mode
        if (uwsgi.threads < 2) {
        	PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
        }

        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);

        if (uwsgi.cores > 1) {
                PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
        }

        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);


	// call

	if (PyTuple_GetItem(wsgi_req->async_args, 0) != wsgi_req->async_environ) {
	    if (PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ)) {
	        uwsgi_log_verbose("unable to set environ to the python application callable, consider using the holy env allocator\n");
	        return NULL;
	    }
	}
	return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
Ejemplo n.º 14
0
void *uwsgi_request_subhandler_pump(struct wsgi_request *wsgi_req, struct uwsgi_app *wi) {

	PyObject *zero;

	int i;
        PyObject *pydictkey, *pydictvalue;

	char *port = memchr(wsgi_req->host, ':', wsgi_req->host_len);
	if (port) {

		zero = PyString_FromStringAndSize(wsgi_req->host, (port-wsgi_req->host));
		PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
		Py_DECREF(zero);

		zero = PyString_FromStringAndSize(port, wsgi_req->host_len-((port+1)-wsgi_req->host));
		PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
		Py_DECREF(zero);
	}
	else {

		zero = PyString_FromStringAndSize(wsgi_req->host, wsgi_req->host_len);
		PyDict_SetItemString(wsgi_req->async_environ, "server_name", zero);
		Py_DECREF(zero);

		zero = PyString_FromStringAndSize("80", 2);
		PyDict_SetItemString(wsgi_req->async_environ, "server_port", zero);
		Py_DECREF(zero);
	}

	zero = PyString_FromStringAndSize(wsgi_req->remote_addr, wsgi_req->remote_addr_len);
	PyDict_SetItemString(wsgi_req->async_environ, "remote_addr", zero);
	Py_DECREF(zero);

	zero = PyString_FromStringAndSize(wsgi_req->path_info, wsgi_req->path_info_len);
	PyDict_SetItemString(wsgi_req->async_environ, "uri", zero);
	Py_DECREF(zero);

	if (wsgi_req->query_string_len > 0) {
		zero = PyString_FromStringAndSize(wsgi_req->query_string, wsgi_req->query_string_len);
		PyDict_SetItemString(wsgi_req->async_environ, "query_string", zero);
		Py_DECREF(zero);
	}

	zero = PyString_FromStringAndSize(uwsgi_lower(wsgi_req->method, wsgi_req->method_len), wsgi_req->method_len);
	PyDict_SetItemString(wsgi_req->async_environ, "method", zero);
	Py_DECREF(zero);

	if (wsgi_req->post_cl > 0) {
		PyDict_SetItemString(wsgi_req->async_environ, "content_length", PyInt_FromLong(wsgi_req->post_cl));
		if (wsgi_req->content_type_len > 0) {
			zero = PyString_FromStringAndSize(wsgi_req->content_type, wsgi_req->content_type_len);
                	PyDict_SetItemString(wsgi_req->async_environ, "content_type", zero);
                	Py_DECREF(zero);
		}
	}



	PyObject *headers = PyDict_New();

        for (i = 0; i < wsgi_req->var_cnt; i += 2) {
#ifdef UWSGI_DEBUG
                uwsgi_debug("%.*s: %.*s\n", wsgi_req->hvec[i].iov_len, wsgi_req->hvec[i].iov_base, wsgi_req->hvec[i+1].iov_len, wsgi_req->hvec[i+1].iov_base);
#endif
		if (wsgi_req->hvec[i].iov_len < 6) continue;
		if (!uwsgi_startswith(wsgi_req->hvec[i].iov_base, "HTTP_", 5)) {
			(void) uwsgi_lower(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
#ifdef PYTHREE
                	pydictkey = PyUnicode_DecodeLatin1(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5, NULL);
                	pydictvalue = PyUnicode_DecodeLatin1(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len, NULL);
#else
                	pydictkey = PyString_FromStringAndSize(wsgi_req->hvec[i].iov_base+5, wsgi_req->hvec[i].iov_len-5);
                	pydictvalue = PyString_FromStringAndSize(wsgi_req->hvec[i + 1].iov_base, wsgi_req->hvec[i + 1].iov_len);
#endif
			PyObject *old_value = PyDict_GetItem(headers, pydictkey);
			if (old_value) {
				if (PyString_Check(old_value)) {
					PyObject *new_value = PyList_New(0);
					PyList_Append(new_value, old_value);
					old_value = new_value;
                			PyDict_SetItem(headers, pydictkey, old_value);
					Py_DECREF(old_value);
				}
				PyList_Append(old_value, pydictvalue);
			}
			else {
                		PyDict_SetItem(headers, pydictkey, pydictvalue);
			}
                	Py_DECREF(pydictkey);
                	Py_DECREF(pydictvalue);
		}
        }

	PyDict_SetItemString(wsgi_req->async_environ, "headers", headers);
	Py_DECREF(headers);

        // create wsgi.input custom object
        wsgi_req->async_input = (PyObject *) PyObject_New(uwsgi_Input, &uwsgi_InputType);
        ((uwsgi_Input*)wsgi_req->async_input)->wsgi_req = wsgi_req;

        PyDict_SetItemString(wsgi_req->async_environ, "body", wsgi_req->async_input);

	if (wsgi_req->scheme_len > 0) {
		zero = PyString_FromStringAndSize(wsgi_req->scheme, wsgi_req->scheme_len);
	}
	else if (wsgi_req->https_len > 0) {
		if (!strncasecmp(wsgi_req->https, "on", 2) || wsgi_req->https[0] == '1') {
			zero = PyString_FromString("https");
		}
		else {
			zero = PyString_FromString("http");
		}
	}
	else {
		zero = PyString_FromString("http");
	}
	PyDict_SetItemString(wsgi_req->async_environ, "scheme", zero);
	Py_DECREF(zero);


	wsgi_req->async_app = wi->callable;

	// export .env only in non-threaded mode
        if (uwsgi.threads < 2) {
        	PyDict_SetItemString(up.embedded_dict, "env", wsgi_req->async_environ);
        }

        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.version", wi->uwsgi_version);

        if (uwsgi.cores > 1) {
                PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.core", PyInt_FromLong(wsgi_req->async_id));
        }

        PyDict_SetItemString(wsgi_req->async_environ, "uwsgi.node", wi->uwsgi_node);

	// call

	PyTuple_SetItem(wsgi_req->async_args, 0, wsgi_req->async_environ);
	return python_call(wsgi_req->async_app, wsgi_req->async_args, uwsgi.catch_exceptions, wsgi_req);
}
Ejemplo n.º 15
0
/*template<> PyObject* toPy<char*>(const (char*) & val) {
    return PyUnicode_DecodeLatin1(val,strlen(val),"replace");
}*/
template<> PyObject* toPy<string>( string& val) {
    return PyUnicode_DecodeLatin1(val.c_str(),val.length(),"replace");
}
Ejemplo n.º 16
0
Archivo: _sane.c Proyecto: Bouke/Pillow
static PyObject *
SaneDev_get_options(SaneDevObject *self, PyObject *args)
{
  const SANE_Option_Descriptor *d;
  PyObject *list, *value;
  int i=1;
  
  if (!PyArg_ParseTuple(args, ""))
    return NULL;
  if (self->h==NULL)
    {
      PyErr_SetString(ErrorObject, "SaneDev object is closed");
      return NULL;
    }
  if (!(list = PyList_New(0)))
	    return NULL;

  do 
    {
      d=sane_get_option_descriptor(self->h, i);
      if (d!=NULL) 
	{
	  PyObject *constraint=NULL;
	  int j;
	  
	  switch (d->constraint_type)
	    {
	    case(SANE_CONSTRAINT_NONE): 
	      Py_INCREF(Py_None); constraint=Py_None; break;
	    case(SANE_CONSTRAINT_RANGE): 
	      if (d->type == SANE_TYPE_INT)
		constraint=Py_BuildValue("iii", d->constraint.range->min, 
					 d->constraint.range->max, 
					 d->constraint.range->quant);
	      else
		constraint=Py_BuildValue("ddd", 
					 SANE_UNFIX(d->constraint.range->min), 
					 SANE_UNFIX(d->constraint.range->max), 
					 SANE_UNFIX(d->constraint.range->quant));
	      break;
	    case(SANE_CONSTRAINT_WORD_LIST): 
	      constraint=PyList_New(d->constraint.word_list[0]);
	      if (d->type == SANE_TYPE_INT)
		for (j=1; j<=d->constraint.word_list[0]; j++)
		  PyList_SetItem(constraint, j-1, 
				 PyInt_FromLong(d->constraint.word_list[j]));
	      else
		for (j=1; j<=d->constraint.word_list[0]; j++)
		  PyList_SetItem(constraint, j-1, 
				 PyFloat_FromDouble(SANE_UNFIX(d->constraint.word_list[j])));
	      break;
	    case(SANE_CONSTRAINT_STRING_LIST): 
	      constraint=PyList_New(0);
	      for(j=0; d->constraint.string_list[j]!=NULL; j++)
		PyList_Append(constraint, 
#if PY_MAJOR_VERSION >= 3
			      PyUnicode_DecodeLatin1(d->constraint.string_list[j], strlen(d->constraint.string_list[j]), NULL));
#else
			      PyString_FromString(d->constraint.string_list[j]));
#endif
	      break;
	    }
	  value=Py_BuildValue("isssiiiiO", i, d->name, d->title, d->desc, 
			      d->type, d->unit, d->size, d->cap, constraint);
	  PyList_Append(list, value);
	}
      i++;
    } while (d!=NULL);
Ejemplo n.º 17
0
static PyObject *parse_qsl(PyObject *self, PyObject *args)
{

    PyObject *pairs;
    int i, len;
    PyObject *qso;
    char unicode = 0;
    char *qs = NULL;
    int keep_blank_values = 0;
    int strict_parsing = 0; /* XXX not implemented */

    if (! PyArg_ParseTuple(args, "O|ii", &qso, &keep_blank_values,
                           &strict_parsing))
        return NULL; /* error */

    if (PyUnicode_Check(qso))
        unicode = 1;

    MP_ANYSTR_AS_STR(qs, qso, 1);
    if (!qs) {
        Py_DECREF(qso); /* MP_ANYSTR_AS_STR */
        return NULL;
    }

    /* split query string by '&' and ';' into a list of pairs */
    pairs = PyList_New(0);
    if (pairs == NULL) {
        Py_DECREF(qso); /* MP_ANYSTR_AS_STR */
        return NULL;
    }

    i = 0;
    len = strlen(qs);

    while (i < len) {

        PyObject *pair, *key, *val;
        char *cpair, *ckey, *cval;
        int plen, j, p, k, v;

        pair = PyBytes_FromStringAndSize(NULL, len);
        if (pair == NULL)
            return NULL;

        /* split by '&' or ';' */
        cpair = PyBytes_AS_STRING(pair);
        j = 0;
        while ((qs[i] != '&') && (qs[i] != ';') && (i < len)) {
            /* replace '+' with ' ' */
            cpair[j] = (qs[i] == '+') ? ' ' : qs[i];
            i++;
            j++;
        }

        if (j == 0) {
            Py_XDECREF(pair);
            i++;
            continue;
        }

        cpair[j] = '\0';
        _PyBytes_Resize(&pair, j);
        cpair = PyBytes_AS_STRING(pair);

        /* split the "abc=def" pair */
        plen = strlen(cpair);

        key = PyBytes_FromStringAndSize(NULL, plen);
        if (key == NULL) {
            Py_DECREF(qso); /* MP_ANYSTR_AS_STR */
            return NULL;
        }

        val = PyBytes_FromStringAndSize(NULL, plen);
        if (val == NULL) {
            Py_DECREF(qso); /* MP_ANYSTR_AS_STR */
            return NULL;
        }

        ckey = PyBytes_AS_STRING(key);
        cval = PyBytes_AS_STRING(val);

        p = 0;
        k = 0;
        v = 0;
        while (p < plen) {
            if (cpair[p] != '=') {
                ckey[k] = cpair[p];
                k++;
                p++;
            }
            else {
                p++;      /* skip '=' */
                while (p < plen) {
                    cval[v] = cpair[p];
                    v++;
                    p++;
                }
            }
        }
        ckey[k] = '\0';
        cval[v] = '\0';

        if (keep_blank_values || (v > 0)) {

            ap_unescape_url(ckey);
            ap_unescape_url(cval);

            _PyBytes_Resize(&key, strlen(ckey));
            _PyBytes_Resize(&val, strlen(cval));

            if (key && val) {
                PyObject *listitem = NULL;
                if (unicode) {
                    PyObject *ukey, *uval;
                    ukey = PyUnicode_DecodeLatin1(ckey, strlen(ckey), NULL);
                    uval = PyUnicode_DecodeLatin1(cval, strlen(cval), NULL);
                    listitem = Py_BuildValue("(O,O)", ukey, uval);
                    Py_DECREF(ukey);
                    Py_DECREF(uval);
                } else
                    listitem = Py_BuildValue("(O,O)", key, val);
                if(listitem) {
                    PyList_Append(pairs, listitem);
                    Py_DECREF(listitem);
                }
            }

        }
        Py_XDECREF(pair);
        Py_XDECREF(key);
        Py_XDECREF(val);
        i++;
    }

    Py_DECREF(qso);
    return pairs;
}