~dustin-spy/twisted/dustin

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
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/*
 * Copyright (c) 2001-2004 Twisted Matrix Laboratories.
 * See LICENSE for details.

 *
 */
/* _c_urlarg.c */

#ifdef __cplusplus
extern "C" {
#endif
#include <Python.h>
#include <cStringIO.h>
#ifdef __cplusplus
}
#endif

#ifdef __GNUC__
#       define TM_INLINE inline
#else
#       define TM_INLINE /* */
#endif

static PyObject* UrlargError;

#define OUTPUTCHAR(c,n) PycStringIO->cwrite(output, c, n)

#define STATE_INITIAL 0
#define STATE_PERCENT 1
#define STATE_HEXDIGIT 2

#define NOT_HEXDIGIT 255
unsigned char hexdigits[256];

TM_INLINE int ishexdigit(unsigned char c) {
    return hexdigits[c];
}

static PyObject *unquote(PyObject *self, PyObject *args, PyObject *kwargs)
{
    unsigned char *s, *r, *end;
    unsigned char quotedchar, quotedchartmp = 0, tmp;
    unsigned char escchar = '%'; /* the character we use to begin %AB sequences */
    static char *kwlist[] = {"s", "escchar", NULL};
    int state = STATE_INITIAL, length;
    PyObject *output, *str;
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s#|c:unquote", kwlist, &s, &length, &escchar)) {
        return NULL;
    }
    /* output = cStringIO() */
    output = PycStringIO->NewOutput(length);
    if (output == NULL) {
        return NULL;
    }
    end = s + length;
    s = s - 1;
    while ((++s) < end) {
        switch(state) {
        case STATE_INITIAL:
            if (*s == escchar) {
                state = STATE_PERCENT;
            } else {
                r = s - 1;
                while (*(++r) != escchar && r < end);
                OUTPUTCHAR(s, r-s);
                s = r-1;
            }
            break;
        case STATE_PERCENT:
            if ((quotedchartmp = ishexdigit(*s)) != NOT_HEXDIGIT) {
                tmp = *s;
                state = STATE_HEXDIGIT;
            } else {
                state = STATE_INITIAL;
                OUTPUTCHAR(&escchar, 1);
                s--;
            }
            break;
        case STATE_HEXDIGIT:
            state = STATE_INITIAL;
            if ((quotedchar = ishexdigit(*s)) != NOT_HEXDIGIT) {
                quotedchar |= (quotedchartmp << 4);
                OUTPUTCHAR(&quotedchar, 1);
            } else {
                OUTPUTCHAR(&escchar, 1);
                s -= 2;
            }
            break;
        }
    }
    switch(state) {
    case STATE_PERCENT:
        OUTPUTCHAR(&escchar, 1);
        break;
    case STATE_HEXDIGIT:
        OUTPUTCHAR(&escchar, 1);
        OUTPUTCHAR(&tmp, 1);
        break;
    }

    /* return output.getvalue() */
    str = PycStringIO->cgetvalue(output);
    Py_DECREF(output);
    return str;
}

static PyMethodDef _c_urlarg_methods[] = {
    {"unquote",  (PyCFunction)unquote, METH_VARARGS|METH_KEYWORDS},
    {NULL, NULL} /* sentinel */
};

DL_EXPORT(void) init_c_urlarg(void)
{
    PyObject* m;
    PyObject* d;
    unsigned char i;

    PycString_IMPORT;
    m = Py_InitModule("_c_urlarg", _c_urlarg_methods);
    d = PyModule_GetDict(m);

    /* add our base exception class */
    UrlargError = PyErr_NewException("urlarg.UrlargError", PyExc_Exception, NULL);
    PyDict_SetItemString(d, "UrlargError", UrlargError);

    /* initialize hexdigits */
    for(i = 0; i < 255; i++) {
        hexdigits[i] = NOT_HEXDIGIT;
    }
    hexdigits[255] = NOT_HEXDIGIT;
    for(i = '0'; i <= '9'; i++) {
        hexdigits[i] = i - '0';
    }
    for(i = 'a'; i <= 'f'; i++) {
        hexdigits[i] = 10 + (i - 'a');
    }
    for(i = 'A'; i <= 'F'; i++) {
        hexdigits[i] = 10 + (i - 'A');
    }
    /* Check for errors */
    if (PyErr_Occurred()) {
        PyErr_Print();
        Py_FatalError("can't initialize module _c_urlarg");
    }
}