/***************************************************************************
 *
 * Copyright (c) 2000, 2001 BalaBit IT Ltd, Budapest, Hungary
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 * $Id: pyproxy.c,v 1.26.2.1.2.3 2001/09/19 19:22:17 bazsi Exp $
 *
 * Author  : Bazsi
 * Auditor : kisza
 * Last version: 1.15
 * Notes:
 *   - comments
 *
 ***************************************************************************/

#include <zorp/pyproxy.h>
#include <zorp/proxy.h>
#include <zorp/policy.h>
#include <zorp/registry.h>
#include <zorp/modules.h>
#include <zorp/pystream.h>
#include <zorp/log.h>

#include <ExtensionClass.h>

static PyObject *
z_py_zorp_proxy_new(ZorpProxy *self, PyObject *args);

static PyObject *
z_py_zorp_proxy_destroy(ZorpProxy *self, PyObject *args);

static PyMethodDef z_py_zorp_proxy_methods[] =
{
  { "__init__", (PyCFunction) z_py_zorp_proxy_new, METH_VARARGS },
  { "destroy", (PyCFunction) z_py_zorp_proxy_destroy, METH_VARARGS },
  { NULL, NULL }
};

static PyObject *
z_py_zorp_proxy_new(ZorpProxy *self, PyObject *args)
{
  gchar *module_name, *session_id;
  ZorpStream *client;
  gpointer proxy_create;
  int proxy_type = 0;

  z_enter();
  if (!PyArg_ParseTuple(args, "ssOi", &module_name, &session_id, &client, &proxy_type))
    {
      z_leave();
      return NULL;
    }
    
  if (!z_py_zorp_stream_check(client))
    {
      PyErr_SetString(PyExc_TypeError, "client must be a ZorpStream");
      z_leave();
      return NULL;
    }

  proxy_create = z_registry_get(module_name, &proxy_type);
  if (!proxy_create)
    {
      z_load_module(module_name);
      proxy_create = z_registry_get(module_name, &proxy_type);
    }
  Py_XINCREF(self);
  switch (proxy_type)
    {
    case ZR_SPROXY:
      self->proxy = (*(ZSProxyCreateFunc) proxy_create)(session_id, client->stream, (PyObject *) self);
      break;
    case ZR_SPYPROXY:
      self->proxy = (*(ZPyProxyCreateFunc) proxy_create)(session_id, (PyObject *) client, (PyObject *) self);
      break;
    case ZR_DPROXY:
      self->proxy = (*(ZDProxyCreateFunc) proxy_create)(session_id, (PyObject *) self);
      break;
    default:
      /*LOG
        This module indicates that the given proxy module couldn't be found
        or an error occured during the loading of the module.
       */
      Py_XDECREF(self);
      z_log(NULL, CORE_ERROR, 1, "Cannot find proxy module; module='%s' type='%d'", module_name, proxy_type);
      PyErr_SetString(PyExc_RuntimeError, "Error loading proxy module.");
      return NULL;
    }
  Py_XDECREF(self);
  Py_XINCREF(Py_None);
  z_leave();
  return Py_None;
}

static PyObject *
z_py_zorp_proxy_destroy(ZorpProxy *self, PyObject *args)
{
  z_proxy_quit(self->proxy);
  Py_XINCREF(Py_None);
  return Py_None;
}

static void
z_py_zorp_proxy_free(ZorpProxy *self)
{
  if (self->proxy)
    z_proxy_free(self->proxy);
  PyMem_DEL(self);
}

static PyObject *
z_py_zorp_proxy_getattr(ZorpProxy *self, char *name)
{
  PyObject *v;

  if (self->proxy && self->proxy->getattr)
    {
      v = ZPROXY_GETATTR(self->proxy, name);
      if (v)
        {
          PyObject *repr = PyObject_Repr(v);
          /*LOG
            This debug message informs you that the given proxy-exported 
            attribute was fetched, and it contained the also given value.
           */
          z_log(self->proxy->session_id, CORE_DEBUG, 6, "Attribute fetched; attribute='%s', value='%s'", name, PyString_AsString(repr));
          Py_XDECREF(repr);
          return v;
        }
    }
  
  return Py_FindMethod(z_py_zorp_proxy_methods, (PyObject *) self, name);
}

static gint
z_py_zorp_proxy_setattr(ZorpProxy *self, char *name, PyObject *value)
{
  if (self->proxy && self->proxy->setattr)
    { 
      if (ZPROXY_SETATTR(self->proxy, name, value))
        {
          PyObject *repr = PyObject_Repr(value);
          /*LOG
            This debug message indicates that the given proxy-exported attribute
            was changed to the given value.
           */
          z_log(self->proxy->session_id, CORE_DEBUG, 6, "Attribute changed; attribute='%s', newvalue='%s'", name, PyString_AsString(repr));
          Py_XDECREF(repr);
          return 0;
        }
      else
        if (PyErr_Occurred())
          {
            return 1;
          }
    }
  return PyEC_SetAttrString((PyObject *) self, name, value);
}

static PyExtensionClass z_py_zorp_proxy_type = 
{
  PyObject_HEAD_INIT(&PyType_Type)
  0,                                        /*ob_size*/
  "ZorpProxy",                              /*tp_name*/
  sizeof(ZorpProxy),                        /*tp_basicsize*/
  0,                                        /*tp_itemsize*/
  /* methods */
  (destructor)z_py_zorp_proxy_free,         /*tp_dealloc*/
  (printfunc)0,                             /*tp_print*/
  (getattrfunc)z_py_zorp_proxy_getattr,     /*tp_getattr*/
  (setattrfunc)z_py_zorp_proxy_setattr,     /*tp_setattr*/
  (cmpfunc)0,                               /*tp_compare*/
  (reprfunc)0,                              /*tp_repr*/
  0,                                        /*tp_as_number*/
  0,                   		            /*tp_as_sequence*/
  0,                   		            /*tp_as_mapping*/
  (hashfunc)0,         		            /*tp_hash*/
  (ternaryfunc)0,      		            /*tp_call*/
  (reprfunc)0,         		            /*tp_str*/

  /* Space for future expansion */
  0L,0L,0L,0L,
  "ZorpProxy class", /* Documentation string */
  METHOD_CHAIN(z_py_zorp_proxy_methods)
};

#if 0
static PyMethodDef z_py_zorp_proxy_funcs[] =
{
  { NULL, NULL }
};
#endif
              
void
z_py_zorp_proxy_init(void)
{
  PyObject *m, *d;

  m = PyImport_AddModule("Zorp.Zorp");
  /* Py_InitModule("Zorp.Proxy", z_py_zorp_proxy_funcs); */
  d = PyModule_GetDict(m);
  PyExtensionClass_Export(d, "ZorpProxy", z_py_zorp_proxy_type);
}
