Home | History | Annotate | Download | only in python
      1 /*
      2  * Copyright 2001-2004 Brandon Long
      3  * All Rights Reserved.
      4  *
      5  * ClearSilver Templating System
      6  *
      7  * This code is made available under the terms of the ClearSilver License.
      8  * http://www.clearsilver.net/license.hdf
      9  *
     10  */
     11 
     12 #include <Python.h>
     13 #include "ClearSilver.h"
     14 
     15 #define NEO_CGI_MODULE
     16 #include "p_neo_util.h"
     17 
     18 static PyObject *CGIFinishedException;
     19 
     20 #define CGIObjectCheck(a) (!(strcmp((a)->ob_type->tp_name, CGIObjectType.tp_name)))
     21 
     22 typedef struct _CGIObject
     23 {
     24    PyObject_HEAD
     25    CGI *cgi;
     26    PyObject *hdf;
     27    PyObject *upload_cb;
     28    PyObject *upload_rock;
     29    int upload_error;
     30 } CGIObject;
     31 
     32 static PyObject *p_cgi_value_get_attr (CGIObject *self, char *name);
     33 static void p_cgi_dealloc (CGIObject *ho);
     34 
     35 PyTypeObject CGIObjectType = {
     36   PyObject_HEAD_INIT(NULL)
     37     0,			             /*ob_size*/
     38   "CGIObjectType",	             /*tp_name*/
     39   sizeof(CGIObject),	     /*tp_size*/
     40   0,			             /*tp_itemsize*/
     41   /* methods */
     42   (destructor)p_cgi_dealloc,	     /*tp_dealloc*/
     43   0,			             /*tp_print*/
     44   (getattrfunc)p_cgi_value_get_attr,     /*tp_getattr*/
     45   0,			             /*tp_setattr*/
     46   0,			             /*tp_compare*/
     47   (reprfunc)0,                       /*tp_repr*/
     48   0,                                 /* tp_as_number */
     49   0,                                 /* tp_as_sequence */
     50   0,                                 /* tp_as_mapping */
     51   0,                                 /* tp_as_hash */
     52 };
     53 
     54 static void p_cgi_dealloc (CGIObject *ho)
     55 {
     56   if (ho->cgi)
     57   {
     58     cgi_destroy (&(ho->cgi));
     59   }
     60   PyObject_DEL(ho);
     61 }
     62 
     63 PyObject * p_cgi_to_object (CGI *data)
     64 {
     65   PyObject *rv;
     66 
     67   if (data == NULL)
     68   {
     69     rv = Py_None;
     70     Py_INCREF (rv);
     71   }
     72   else
     73   {
     74     CGIObject *ho = PyObject_NEW (CGIObject, &CGIObjectType);
     75     if (ho == NULL) return NULL;
     76     ho->cgi = data;
     77     ho->hdf = p_hdf_to_object (data->hdf, 0);
     78     Py_INCREF(ho->hdf);
     79     rv = (PyObject *) ho;
     80   }
     81   return rv;
     82 }
     83 
     84 static PyObject * p_cgi_init (PyObject *self, PyObject *args)
     85 {
     86   CGI *cgi = NULL;
     87   NEOERR *err;
     88 
     89   err = cgi_init (&cgi, NULL);
     90   if (err) return p_neo_error (err);
     91   return p_cgi_to_object (cgi);
     92 }
     93 
     94 static PyObject * p_cgi_parse (PyObject *self, PyObject *args)
     95 {
     96   CGI *cgi = ((CGIObject *) self)->cgi;
     97   CGIObject *p_cgi = (CGIObject *) self;
     98   PyObject *rv;
     99   NEOERR *err;
    100 
    101   p_cgi->upload_error = 0;
    102 
    103   err = cgi_parse (cgi);
    104   if (err) return p_neo_error (err);
    105 
    106   if (p_cgi->upload_error)
    107   {
    108     p_cgi->upload_error = 0;
    109     return NULL;
    110   }
    111 
    112   rv = Py_None;
    113   Py_INCREF(rv);
    114   return rv;
    115 }
    116 
    117 static int python_upload_cb (CGI *cgi, int nread, int expected)
    118 {
    119   CGIObject *self = (CGIObject *)(cgi->data);
    120   PyObject *cb, *rock;
    121   PyObject *args, *result;
    122   int r;
    123 
    124   /* fprintf(stderr, "upload_cb: %d/%d\n", nread, expected); */
    125   cb = self->upload_cb;
    126   rock = self->upload_rock;
    127 
    128   if (cb == NULL) return 0;
    129   args = Py_BuildValue("(Oii)", rock, nread, expected);
    130 
    131   if (args == NULL) {
    132     self->upload_error = 1;
    133     return 1;
    134   }
    135   result = PyEval_CallObject(cb, args);
    136   Py_DECREF(args);
    137   if (result != NULL && !PyInt_Check(result)) {
    138     Py_DECREF(result);
    139     result = NULL;
    140     PyErr_SetString(PyExc_TypeError,
    141 	"upload_cb () returned non-integer");
    142     self->upload_error = 1;
    143     return 1;
    144   }
    145   r = PyInt_AsLong(result);
    146   Py_DECREF(result);
    147   result = NULL;
    148   return r;
    149 }
    150 
    151 static PyObject * p_cgi_set_upload_cb (PyObject *self, PyObject *args)
    152 {
    153   CGI *cgi = ((CGIObject *) self)->cgi;
    154   CGIObject *p_cgi = (CGIObject *) self;
    155   PyObject *rock, *cb;
    156 
    157   if (!PyArg_ParseTuple(args, "OO:setUploadCB(rock, func)", &rock, &cb))
    158     return NULL;
    159 
    160   cgi->data = self;
    161   cgi->upload_cb = python_upload_cb;
    162   p_cgi->upload_cb = cb;
    163   p_cgi->upload_rock = rock;
    164   p_cgi->upload_error = 0;
    165   Py_INCREF(cb);
    166   Py_INCREF(rock);
    167 
    168   Py_INCREF(Py_None);
    169   return Py_None;
    170 }
    171 
    172 static PyObject * p_cgi_error (PyObject *self, PyObject *args)
    173 {
    174   CGI *cgi = ((CGIObject *) self)->cgi;
    175   char *s;
    176   PyObject *rv;
    177 
    178   if (!PyArg_ParseTuple(args, "s:error(str)", &s))
    179     return NULL;
    180 
    181   cgi_error (cgi, s);
    182   rv = Py_None;
    183   Py_INCREF(rv);
    184   return rv;
    185 }
    186 
    187 static PyObject * p_cgi_display (PyObject *self, PyObject *args)
    188 {
    189   CGI *cgi = ((CGIObject *) self)->cgi;
    190   char *file;
    191   PyObject *rv;
    192   NEOERR *err;
    193 
    194   if (!PyArg_ParseTuple(args, "s:display(file)", &file))
    195     return NULL;
    196 
    197   err = cgi_display (cgi, file);
    198   if (err) return p_neo_error (err);
    199   rv = Py_None;
    200   Py_INCREF(rv);
    201   return rv;
    202 }
    203 
    204 static PyObject * p_cgi_redirect (PyObject *self, PyObject *args)
    205 {
    206   CGI *cgi = ((CGIObject *) self)->cgi;
    207   char *s;
    208   PyObject *rv;
    209 
    210   if (!PyArg_ParseTuple(args, "s:redirect(str)", &s))
    211     return NULL;
    212 
    213   cgi_redirect (cgi, "%s", s);
    214   rv = Py_None;
    215   Py_INCREF(rv);
    216   return rv;
    217 }
    218 
    219 static PyObject * p_cgi_redirect_uri (PyObject *self, PyObject *args)
    220 {
    221   CGI *cgi = ((CGIObject *) self)->cgi;
    222   char *s;
    223   PyObject *rv;
    224 
    225   if (!PyArg_ParseTuple(args, "s:redirectUri(str)", &s))
    226     return NULL;
    227 
    228   cgi_redirect_uri (cgi, "%s", s);
    229   rv = Py_None;
    230   Py_INCREF(rv);
    231   return rv;
    232 }
    233 
    234 static PyObject * p_cgi_cookie_authority (PyObject *self, PyObject *args)
    235 {
    236   CGI *cgi = ((CGIObject *) self)->cgi;
    237   char *s, *host;
    238   PyObject *rv;
    239 
    240   if (!PyArg_ParseTuple(args, "s:cookieAuthority(host)", &host))
    241     return NULL;
    242 
    243   s = cgi_cookie_authority (cgi, host);
    244   if (s == NULL)
    245   {
    246     rv = Py_None;
    247     Py_INCREF(rv);
    248   }
    249   else
    250   {
    251     rv = Py_BuildValue ("s", s);
    252   }
    253   return rv;
    254 }
    255 
    256 static PyObject * p_cgi_cookie_set (PyObject *self, PyObject *args,
    257     PyObject *keywds)
    258 {
    259   CGI *cgi = ((CGIObject *) self)->cgi;
    260   char *name, *value, *path = NULL, *domain = NULL, *time_str = NULL;
    261   int persist = 0;
    262   int secure = 0;
    263   NEOERR *err;
    264   static char *kwlist[] = {"name", "value", "path", "domain", "time_str", "persist", "secure", NULL};
    265 
    266   if (!PyArg_ParseTupleAndKeywords(args, keywds, "ss|sssii:cookieSet()", kwlist, &name, &value, &path, &domain, &time_str, &persist, &secure))
    267     return NULL;
    268 
    269   err = cgi_cookie_set (cgi, name, value, path, domain, time_str, persist, secure);
    270   if (err) return p_neo_error (err);
    271   Py_INCREF(Py_None);
    272   return Py_None;
    273 }
    274 
    275 static PyObject * p_cgi_cookie_clear (PyObject *self, PyObject *args)
    276 {
    277   CGI *cgi = ((CGIObject *) self)->cgi;
    278   char *name, *domain = NULL, *path = NULL;
    279   NEOERR *err;
    280 
    281   if (!PyArg_ParseTuple(args, "s|ss:cookieClear(name, domain, path)", &name, &domain, &path))
    282     return NULL;
    283 
    284   err = cgi_cookie_clear (cgi, name, domain, path);
    285   if (err) return p_neo_error (err);
    286   Py_INCREF(Py_None);
    287   return Py_None;
    288 }
    289 
    290 static PyObject * p_cgi_filehandle (PyObject *self, PyObject *args)
    291 {
    292   CGI *cgi = ((CGIObject *) self)->cgi;
    293   char *name;
    294   FILE *fp;
    295 
    296   if (!PyArg_ParseTuple(args, "s:filehandle(form_name)", &name))
    297     return NULL;
    298 
    299   fp = cgi_filehandle (cgi, name);
    300   if (fp == NULL)
    301   {
    302     Py_INCREF(Py_None);
    303     return Py_None;
    304   }
    305   return PyFile_FromFile (fp, name, "w+", NULL);
    306 }
    307 
    308 static PyObject * p_cgi_cs_init (PyObject *self, PyObject *args)
    309 {
    310   CGI *cgi = ((CGIObject *) self)->cgi;
    311   NEOERR *err;
    312   CSPARSE *cs;
    313 
    314   if (!PyArg_ParseTuple(args, ":cs()"))
    315     return NULL;
    316 
    317   err = cgi_cs_init(cgi, &cs);
    318   if (err) return p_neo_error (err);
    319   return p_cs_to_object(cs);
    320 }
    321 
    322 static PyMethodDef CGIMethods[] =
    323 {
    324 #if 0
    325   {"debugInit", p_cgi_debug_init, METH_VARARGS, NULL},
    326   {"wrapInit", p_cgi_wrap_init, METH_VARARGS, NULL},
    327 #endif
    328   {"parse", p_cgi_parse, METH_VARARGS, NULL},
    329   {"setUploadCB", p_cgi_set_upload_cb, METH_VARARGS, NULL},
    330   {"error", p_cgi_error, METH_VARARGS, NULL},
    331   {"display", p_cgi_display, METH_VARARGS, NULL},
    332   {"redirect", p_cgi_redirect, METH_VARARGS, NULL},
    333   {"redirectUri", p_cgi_redirect_uri, METH_VARARGS, NULL},
    334   {"cookieAuthority", p_cgi_cookie_authority, METH_VARARGS, NULL},
    335   {"cookieSet", (PyCFunction)p_cgi_cookie_set, METH_VARARGS|METH_KEYWORDS, NULL},
    336   {"cookieClear", p_cgi_cookie_clear, METH_VARARGS, NULL},
    337   {"filehandle", p_cgi_filehandle, METH_VARARGS, NULL},
    338   {"cs", p_cgi_cs_init, METH_VARARGS, NULL},
    339   {NULL, NULL}
    340 };
    341 
    342 static PyObject * p_cgi_url_escape (PyObject *self, PyObject *args)
    343 {
    344   char *s, *esc, *o = NULL;
    345   NEOERR *err;
    346   PyObject *rv;
    347 
    348   if (!PyArg_ParseTuple(args, "s|s:urlEscape(str, other=None)", &s, &o))
    349     return NULL;
    350 
    351   err = cgi_url_escape_more (s, &esc, o);
    352   if (err) return p_neo_error (err);
    353   rv = Py_BuildValue ("s", esc);
    354   free (esc);
    355   return rv;
    356 }
    357 
    358 static PyObject * p_cgi_url_unescape (PyObject *self, PyObject *args)
    359 {
    360   char *s;
    361   PyObject *rv;
    362   char *r;
    363 
    364   if (!PyArg_ParseTuple(args, "s:urlUnescape(str)", &s))
    365     return NULL;
    366 
    367   r = strdup(s);
    368   if (r == NULL) return PyErr_NoMemory();
    369   cgi_url_unescape (r);
    370   rv = Py_BuildValue ("s", r);
    371   free (r);
    372   return rv;
    373 }
    374 
    375 static PyObject * p_html_escape (PyObject *self, PyObject *args)
    376 {
    377   char *s, *esc;
    378   NEOERR *err;
    379   PyObject *rv;
    380   int len;
    381 
    382   if (!PyArg_ParseTuple(args, "s#:htmlEscape(str)", &s, &len))
    383     return NULL;
    384 
    385   err = html_escape_alloc (s, len, &esc);
    386   if (err) return p_neo_error (err);
    387   rv = Py_BuildValue ("s", esc);
    388   free (esc);
    389   return rv;
    390 }
    391 
    392 static PyObject * p_html_strip (PyObject *self, PyObject *args)
    393 {
    394   char *s, *esc;
    395   NEOERR *err;
    396   PyObject *rv;
    397   int len;
    398 
    399   if (!PyArg_ParseTuple(args, "s#:htmlStrip(str)", &s, &len))
    400     return NULL;
    401 
    402   err = html_strip_alloc (s, len, &esc);
    403   if (err) return p_neo_error (err);
    404   rv = Py_BuildValue ("s", esc);
    405   free (esc);
    406   return rv;
    407 }
    408 
    409 static PyObject * p_text_html (PyObject *self, PyObject *args, PyObject *keywds)
    410 {
    411   char *s, *esc;
    412   NEOERR *err;
    413   PyObject *rv;
    414   int len;
    415   HTML_CONVERT_OPTS opts;
    416   static char *kwlist[] = {"text", "bounce_url", "url_class", "url_target", "mailto_class", "long_lines", "space_convert", "newlines_convert", "longline_width", "check_ascii_art", "link_name", NULL};
    417 
    418   /* These defaults all come from the old version */
    419   opts.bounce_url = NULL;
    420   opts.url_class = NULL;
    421   opts.url_target = "_blank";
    422   opts.mailto_class = NULL;
    423   opts.long_lines = 0;
    424   opts.space_convert = 0;
    425   opts.newlines_convert = 1;
    426   opts.longline_width = 75; /* This hasn't been used in a while, actually */
    427   opts.check_ascii_art = 1;
    428   opts.link_name = NULL;
    429 
    430   if (!PyArg_ParseTupleAndKeywords(args, keywds, "s#|ssssiiiiis:text2html(text)",
    431 	kwlist,
    432 	&s, &len, &(opts.bounce_url), &(opts.url_class), &(opts.url_target),
    433 	&(opts.mailto_class), &(opts.long_lines), &(opts.space_convert),
    434 	&(opts.newlines_convert), &(opts.longline_width), &(opts.check_ascii_art), &(opts.link_name)))
    435     return NULL;
    436 
    437   err = convert_text_html_alloc_options (s, len, &esc, &opts);
    438   if (err) return p_neo_error (err);
    439   rv = Py_BuildValue ("s", esc);
    440   free (esc);
    441   return rv;
    442 }
    443 
    444 PyObject *p_cgi_value_get_attr (CGIObject *ho, char *name)
    445 {
    446   if (!strcmp(name, "hdf"))
    447   {
    448     Py_INCREF(ho->hdf);
    449     return ho->hdf;
    450   }
    451   return Py_FindMethod(CGIMethods, (PyObject *)ho, name);
    452 }
    453 
    454 /* Enable wrapping of newlib stdin/stdout output to go through python */
    455 typedef struct wrapper_data
    456 {
    457   PyObject *p_stdin;
    458   PyObject *p_stdout;
    459   PyObject *p_env;
    460 } WRAPPER_DATA;
    461 
    462 static WRAPPER_DATA Wrapper = {NULL, NULL, NULL};
    463 
    464 static char cgiwrap_doc[] = "cgiwrap(stdin, stdout, env)\nMethod that will cause all cgiwrapped stdin/stdout functions to be redirected to the python stdin/stdout file objects specified.  Also redirect getenv/putenv calls (env should be either a python dictionary or os.environ)";
    465 static PyObject * cgiwrap (PyObject *self, PyObject *args)
    466 {
    467   PyObject *p_stdin;
    468   PyObject *p_stdout;
    469   PyObject *p_env;
    470 
    471   if (!PyArg_ParseTuple(args, "OOO:cgiwrap(stdin, stdout, env)", &p_stdin, &p_stdout, &p_env))
    472     return NULL;
    473 
    474   if (p_stdin != Py_None)
    475   {
    476     if (Wrapper.p_stdin != NULL)
    477     {
    478       Py_DECREF (Wrapper.p_stdin);
    479     }
    480     Wrapper.p_stdin = p_stdin;
    481     Py_INCREF (Wrapper.p_stdin);
    482   }
    483   if (p_stdout != Py_None)
    484   {
    485     if (Wrapper.p_stdout != NULL)
    486     {
    487       Py_DECREF (Wrapper.p_stdout);
    488     }
    489     Wrapper.p_stdout = p_stdout;
    490     Py_INCREF (Wrapper.p_stdout);
    491   }
    492   if (p_env != Py_None)
    493   {
    494     if (Wrapper.p_env != NULL)
    495     {
    496       Py_DECREF (Wrapper.p_env);
    497     }
    498     Wrapper.p_env = p_env;
    499     Py_INCREF (Wrapper.p_env);
    500   }
    501 
    502   Py_INCREF(Py_None);
    503   return Py_None;
    504 }
    505 
    506 static int p_writef (void *data, const char *fmt, va_list ap)
    507 {
    508   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    509   PyObject *str;
    510   char *buf;
    511   int len;
    512   int err;
    513 
    514 
    515   buf = vsprintf_alloc(fmt, ap);
    516   len = visprintf_alloc(&buf, fmt, ap);
    517 
    518   if (buf == NULL)
    519     return 0;
    520 
    521   str = PyString_FromStringAndSize (buf, len);
    522   free(buf);
    523 
    524   err = PyFile_WriteObject(str, wrap->p_stdout, Py_PRINT_RAW);
    525   Py_DECREF(str);
    526 
    527   if (err == 0)
    528   {
    529     PyErr_Clear();
    530     return len;
    531   }
    532   PyErr_Clear();
    533   return err;
    534 }
    535 
    536 static int p_write (void *data, const char *buf, int len)
    537 {
    538   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    539   PyObject *s;
    540   int err;
    541 
    542   s = PyString_FromStringAndSize (buf, len);
    543 
    544   err = PyFile_WriteObject(s, wrap->p_stdout, Py_PRINT_RAW);
    545   Py_DECREF(s);
    546 
    547   if (err == 0)
    548   {
    549     PyErr_Clear();
    550     return len;
    551   }
    552   PyErr_Clear();
    553   return err;
    554 }
    555 
    556 /* Similar to the PyFile_GetLine function, this one invokes read on the
    557  * file object */
    558 static PyObject *PyFile_Read (PyObject *f, int n)
    559 {
    560   if (f == NULL)
    561   {
    562     PyErr_BadInternalCall();
    563     return NULL;
    564   }
    565   /* If this was in the python fileobject code, we could handle this
    566    * directly for builtin file objects.  Oh well. */
    567   /* if (!PyFile_Check(f))*/
    568   else
    569   {
    570     PyObject *reader;
    571     PyObject *args;
    572     PyObject *result;
    573     reader = PyObject_GetAttrString(f, "read");
    574     if (reader == NULL)
    575       return NULL;
    576     if (n <= 0)
    577       args = Py_BuildValue("()");
    578     else
    579       args = Py_BuildValue("(i)", n);
    580     if (args == NULL) {
    581       Py_DECREF(reader);
    582       return NULL;
    583     }
    584     result = PyEval_CallObject(reader, args);
    585     Py_DECREF(reader);
    586     Py_DECREF(args);
    587     if (result != NULL && !PyString_Check(result)) {
    588       Py_DECREF(result);
    589       result = NULL;
    590       PyErr_SetString(PyExc_TypeError,
    591 	  "object.read() returned non-string");
    592     }
    593     return result;
    594   }
    595 }
    596 
    597 static int p_read (void *data, char *ptr, int len)
    598 {
    599   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    600   PyObject *buf;
    601   char *s;
    602 
    603   buf = PyFile_Read (wrap->p_stdin, len);
    604 
    605   if (buf == NULL)
    606   {
    607     PyErr_Clear();
    608     return -1;
    609   }
    610 
    611   len = PyString_Size(buf);
    612   s = PyString_AsString(buf);
    613 
    614   memcpy (ptr, s, len);
    615 
    616   Py_DECREF(buf);
    617 
    618   PyErr_Clear();
    619   return len;
    620 }
    621 
    622 /* We can't really have an error return from this (and the other
    623  * cgiwrap) function, because the API doesn't have an error return,
    624  * and if we get back to python, the error will occur at the next random
    625  * place that python actually checks for errors independent of an error
    626  * return.  Not the best way to do things, but its what we've got.  Some
    627  * of these we can check for in cgiWrap() */
    628 static char *p_getenv (void *data, const char *s)
    629 {
    630   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    631   PyObject *get;
    632   PyObject *args = NULL;
    633   PyObject *result;
    634   char *ret = NULL;
    635 
    636   get = PyObject_GetAttrString(wrap->p_env, "__getitem__");
    637   if (get != NULL)
    638   {
    639     args = Py_BuildValue("(s)", s);
    640     if (args == NULL) {
    641       Py_DECREF(get);
    642       PyErr_Clear();
    643       return NULL;
    644     }
    645   }
    646   else
    647   {
    648     /* Python 1.5.2 and earlier don't have __getitem__ on the standard
    649      * dict object, so we'll just use get for them */
    650 
    651     get = PyObject_GetAttrString(wrap->p_env, "get");
    652     if (get != NULL)
    653     {
    654       args = Py_BuildValue("(s,O)", s, Py_None);
    655       if (args == NULL)
    656       {
    657 	Py_DECREF(get);
    658 	PyErr_Clear();
    659 	return NULL;
    660       }
    661     }
    662   }
    663   if (get == NULL)
    664   {
    665     ne_warn("Unable to get __getitem__ from env");
    666     PyErr_Clear();
    667     return NULL;
    668   }
    669   result = PyEval_CallObject(get, args);
    670   Py_DECREF(get);
    671   Py_DECREF(args);
    672   if (result != NULL && !PyString_Check(result) && (result != Py_None))
    673   {
    674     Py_DECREF(result);
    675     result = NULL;
    676     PyErr_SetString(PyExc_TypeError,
    677 	"env.get() returned non-string");
    678   }
    679   if (result != NULL && result != Py_None)
    680   {
    681     ret = strdup (PyString_AsString(result));
    682     Py_DECREF (result);
    683   }
    684 
    685   PyErr_Clear();
    686   return ret;
    687 }
    688 
    689 static int p_iterenv (void *data, int x, char **rk, char **rv)
    690 {
    691   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    692   PyObject *items;
    693   PyObject *env_list;
    694   PyObject *result;
    695   PyObject *k, *v;
    696 
    697   items = PyObject_GetAttrString(wrap->p_env, "items");
    698   if (items == NULL)
    699   {
    700     ne_warn ("p_iterenv: Unable to get items method");
    701     PyErr_Clear();
    702     return -1;
    703   }
    704   env_list = PyEval_CallObject(items, NULL);
    705   Py_DECREF(items);
    706   if (env_list == NULL)
    707   {
    708     ne_warn ("p_iterenv: Unable to call items method");
    709     PyErr_Clear();
    710     return -1;
    711   }
    712   if (x >= PyList_Size(env_list))
    713   {
    714     *rk = NULL;
    715     *rv = NULL;
    716     Py_DECREF(env_list);
    717     return 0;
    718   }
    719   result = PyList_GetItem (env_list, x);
    720   if (result == NULL)
    721   {
    722     ne_warn ("p_iterenv: Unable to get env %d", x);
    723     Py_DECREF(env_list);
    724     PyErr_Clear();
    725     return -1;
    726   }
    727   k = PyTuple_GetItem (result, 0);
    728   v = PyTuple_GetItem (result, 1);
    729   if (k == NULL || v == NULL)
    730   {
    731     ne_warn ("p_iterenv: Unable to get k,v %p,%p", k, v);
    732     Py_DECREF(env_list);
    733     PyErr_Clear();
    734     return -1;
    735   }
    736   *rk = strdup(PyString_AsString(k));
    737   *rv = strdup(PyString_AsString(v));
    738   if (*rk == NULL || *rv == NULL)
    739   {
    740     if (*rk) free (*rk);
    741     if (*rv) free (*rv);
    742     Py_DECREF(env_list);
    743     PyErr_Clear();
    744     return -1;
    745   }
    746 
    747   Py_DECREF(env_list);
    748   PyErr_Clear();
    749   return 0;
    750 }
    751 
    752 static int p_putenv (void *data, const char *k, const char *v)
    753 {
    754   WRAPPER_DATA *wrap = (WRAPPER_DATA *)data;
    755   PyObject *set;
    756   PyObject *args;
    757   PyObject *result;
    758 
    759   if (k == NULL || v == NULL) return -1;
    760 
    761   set = PyObject_GetAttrString(wrap->p_env, "__setitem__");
    762   if (set == NULL)
    763   {
    764     PyErr_Clear();
    765     return -1;
    766   }
    767   args = Py_BuildValue("(s,s)", k, v);
    768 
    769   if (args == NULL) {
    770     Py_DECREF(set);
    771     PyErr_Clear();
    772     return -1;
    773   }
    774   result = PyEval_CallObject(set, args);
    775   Py_DECREF(set);
    776   Py_DECREF(args);
    777   if (result == NULL)
    778   {
    779     PyErr_Clear();
    780     return -1;
    781   }
    782   Py_DECREF(result);
    783   PyErr_Clear();
    784   return 0;
    785 }
    786 
    787 static void p_cgiwrap_init(PyObject *m)
    788 {
    789   PyObject *sys, *os, *p_stdin, *p_stdout, *args, *p_env;
    790 #if 0
    791   PyObject *argv;
    792   int x;
    793 #endif
    794 
    795   /* Set up the python wrapper
    796    * This might not be enough to actually continue to point to
    797    * sys.stdin/sys.stdout, we'd probably have to actually do the lookup
    798    * every time... if we need that functionality
    799    */
    800   sys = PyImport_ImportModule("sys");
    801   os = PyImport_ImportModule("os");
    802   if (sys)
    803   {
    804     p_stdin = PyObject_GetAttrString(sys, "stdin");
    805     p_stdout = PyObject_GetAttrString(sys, "stdout");
    806 #if 0
    807     argv = PyObject_GetAttrString(sys, "argv");
    808     if (argv)
    809     {
    810       Argc = PyList_Size (argv);
    811       if (Argc != -1)
    812       {
    813 
    814 	Argv = (char **) malloc (sizeof (char *) * (Argc+1));
    815 	for (x = 0; x < Argc; x++)
    816 	{
    817 	  PyObject *a;
    818 	  char *b;
    819 
    820 	  a = PyList_GetItem (argv, x);
    821 	  if (a == NULL)
    822 	    break;
    823 	  b = PyString_AsString(a);
    824 	  if (b == NULL)
    825 	    break;
    826 	  Argv[x] = b;
    827 	}
    828 	Argv[x] = NULL;
    829       }
    830     }
    831 #endif
    832     if (os)
    833     {
    834       p_env = PyObject_GetAttrString(os, "environ");
    835     }
    836     else
    837     {
    838       Py_INCREF(Py_None);
    839       p_env = Py_None;
    840     }
    841     args = Py_BuildValue("(O,O,O)", p_stdin, p_stdout, p_env);
    842     if (args)
    843     {
    844       cgiwrap_init_emu (&Wrapper, p_read, p_writef, p_write, p_getenv, p_putenv, p_iterenv);
    845       cgiwrap (m, args);
    846       Py_DECREF(args);
    847     }
    848   }
    849 }
    850 
    851 static PyObject * p_ignore (PyObject *self, PyObject *args)
    852 {
    853   int i = 0;
    854 
    855   if (!PyArg_ParseTuple(args, "i:IgnoreEmptyFormVars(bool)", &i))
    856     return NULL;
    857 
    858   IgnoreEmptyFormVars = i;
    859   Py_INCREF(Py_None);
    860   return Py_None;
    861 }
    862 
    863 static PyObject * p_export_date (PyObject *self, PyObject *args)
    864 {
    865   NEOERR *err;
    866   PyObject *ho;
    867   int i = 0;
    868   char *prefix;
    869   char *timezone;
    870   HDF *hdf;
    871 
    872   if (!PyArg_ParseTuple(args, "Ossi:exportDate(hdf, prefix, timezone, time_t)", &ho, &prefix, &timezone, &i))
    873     return NULL;
    874 
    875   hdf = p_object_to_hdf (ho);
    876   if (hdf == NULL)
    877   {
    878     PyErr_SetString(PyExc_TypeError, "First argument must be an HDF Object");
    879     return NULL;
    880   }
    881 
    882   err = export_date_time_t (hdf, prefix, timezone, i);
    883   if (err) return p_neo_error (err);
    884 
    885   Py_INCREF(Py_None);
    886   return Py_None;
    887 }
    888 
    889 static PyObject * p_update (PyObject *self, PyObject *args)
    890 {
    891   if (_PyImport_FindExtension("neo_util","neo_util") == NULL)
    892     initneo_util();
    893 
    894   if (_PyImport_FindExtension("neo_cs","neo_cs") == NULL)
    895     initneo_cs();
    896 
    897   Py_INCREF(Py_None);
    898   return Py_None;
    899 }
    900 
    901 static PyMethodDef ModuleMethods[] =
    902 {
    903   {"CGI", p_cgi_init, METH_VARARGS, NULL},
    904   {"urlEscape", p_cgi_url_escape, METH_VARARGS, NULL},
    905   {"urlUnescape", p_cgi_url_unescape, METH_VARARGS, NULL},
    906   {"htmlEscape", p_html_escape, METH_VARARGS, NULL},
    907   {"htmlStrip", p_html_strip, METH_VARARGS, NULL},
    908   {"text2html", (PyCFunction)p_text_html, METH_VARARGS|METH_KEYWORDS, NULL},
    909   {"cgiWrap", cgiwrap, METH_VARARGS, cgiwrap_doc},
    910   {"IgnoreEmptyFormVars", p_ignore, METH_VARARGS, NULL},
    911   {"exportDate", p_export_date, METH_VARARGS, NULL},
    912   {"update", p_update, METH_VARARGS, NULL},
    913   {NULL, NULL}
    914 };
    915 
    916 DL_EXPORT(void) initneo_cgi(void)
    917 {
    918   PyObject *m, *d;
    919   static void *NEO_PYTHON_API[P_NEO_CGI_POINTERS];
    920   PyObject *c_api_object;
    921 
    922   CGIObjectType.ob_type = &PyType_Type;
    923 
    924 
    925 
    926   initneo_util();
    927   _PyImport_FixupExtension("neo_util", "neo_util");
    928 
    929   initneo_cs();
    930   _PyImport_FixupExtension("neo_cs", "neo_cs");
    931 
    932   m = Py_InitModule("neo_cgi", ModuleMethods);
    933   p_cgiwrap_init (m);
    934   d = PyModule_GetDict(m);
    935   CGIFinishedException = PyErr_NewException("neo_cgi.CGIFinished", NULL, NULL);
    936   PyDict_SetItemString(d, "CGIFinished", CGIFinishedException);
    937 
    938   /* Initialize the C API Pointer array */
    939   NEO_PYTHON_API[P_HDF_TO_OBJECT_NUM] = (void *)p_hdf_to_object;
    940   NEO_PYTHON_API[P_OBJECT_TO_HDF_NUM] = (void *)p_object_to_hdf;
    941   NEO_PYTHON_API[P_NEO_ERROR_NUM] = (void *)p_neo_error;
    942 
    943   /* create a CObject containing the API pointer array's address */
    944   c_api_object = PyCObject_FromVoidPtr((void *)NEO_PYTHON_API, NULL);
    945   if (c_api_object != NULL) {
    946     /* create a name for this object in the module's namespace */
    947     PyDict_SetItemString(d, "_C_API", c_api_object);
    948     Py_DECREF(c_api_object);
    949     PyDict_SetItemString(d, "_C_API_NUM", PyInt_FromLong(P_NEO_CGI_POINTERS));
    950   }
    951 }
    952