Commit 44859c2a 44859c2a7a6cfb8e8ee2a9773a671535e3d69738 by Wojciech Polak

Add Secret class to Python interface.

* python/libmu_py/secret.c: New file.
* python/mailutils/secret.py: New file.
* python/mailutils/url.py (get_secret): New method.
(get_passwd): Remove.

* python/mailutils/mailbox.py (MailboxBase.open): Access mode argument
value can be now one of the following strings: "r", "w", "a", "c".
1 parent acef5b6f
......@@ -28,7 +28,11 @@ def parse (str):
print "\tscheme <%s>" % u.get_scheme ()
print "\tuser <%s>" % u.get_user ()
print "\tpasswd <%s>" % u.get_passwd ()
sec = u.get_secret ()
print "\tpasswd <%s>" % sec.password ()
sec.password_unref ()
print "\tauth <%s>" % u.get_auth ()
print "\thost <%s>" % u.get_host ()
print "\tport %d" % u.get_port ()
......
......@@ -112,6 +112,11 @@ typedef struct {
typedef struct {
PyObject_HEAD;
mu_secret_t secret;
} PySecret;
typedef struct {
PyObject_HEAD;
mu_stream_t stm;
} PyStream;
......@@ -137,6 +142,7 @@ extern int mu_py_init_mailbox (void);
extern int mu_py_init_mailcap (void);
extern int mu_py_init_message (void);
extern int mu_py_init_mime (void);
extern int mu_py_init_secret (void);
extern int mu_py_init_stream (void);
extern int mu_py_init_url (void);
......@@ -160,6 +166,7 @@ extern PyMailbox * PyMailbox_NEW ();
extern PyMailer * PyMailer_NEW ();
extern PyMessage * PyMessage_NEW ();
extern PyMime * PyMime_NEW ();
extern PySecret * PySecret_NEW ();
extern PyStream * PyStream_NEW ();
extern PyUrl * PyUrl_NEW ();
......@@ -169,6 +176,7 @@ extern int PyTicket_Check (PyObject *x);
extern int PyWicket_Check (PyObject *x);
extern int PyAuthData_Check (PyObject *x);
extern int PyMessage_Check (PyObject *x);
extern int PySecret_Check (PyObject *x);
extern int PyStream_Check (PyObject *x);
typedef struct {
......
......@@ -43,6 +43,7 @@ libmu_py_la_SOURCES = \
message.c \
mime.c \
script.c \
secret.c \
stream.c \
registrar.c \
url.c \
......
......@@ -438,6 +438,27 @@ api_ticket_destroy (PyObject *self, PyObject *args)
return _ro (Py_None);
}
static PyObject *
api_ticket_set_secret (PyObject *self, PyObject *args)
{
int status;
PyTicket *py_ticket;
PySecret *py_secret;
if (!PyArg_ParseTuple (args, "O!O", &PyTicketType, &py_ticket, &py_secret))
return NULL;
if (!PySecret_Check ((PyObject *)py_secret))
{
PyErr_SetString (PyExc_TypeError, "");
return NULL;
}
status = mu_ticket_set_secret (py_ticket->ticket,
py_secret->secret);
return _ro (PyInt_FromLong (status));
}
/*
* Wicket
*/
......@@ -468,6 +489,24 @@ api_wicket_destroy (PyObject *self, PyObject *args)
return _ro (Py_None);
}
static PyObject *
api_wicket_get_ticket (PyObject *self, PyObject *args)
{
int status;
char *user;
PyWicket *py_wicket;
PyTicket *py_ticket = PyTicket_NEW ();
if (!PyArg_ParseTuple (args, "O!s", &PyWicketType, &py_wicket, &user))
return NULL;
Py_INCREF (py_ticket);
status = mu_wicket_get_ticket (py_wicket->wicket, user,
&py_ticket->ticket);
return status_object (status, (PyObject *)py_ticket);
}
/*
* mu_auth
*/
......@@ -607,12 +646,18 @@ static PyMethodDef methods[] = {
{ "ticket_destroy", (PyCFunction) api_ticket_destroy, METH_VARARGS,
"" },
{ "ticket_set_secret", (PyCFunction) api_ticket_set_secret, METH_VARARGS,
"" },
{ "wicket_create", (PyCFunction) api_wicket_create, METH_VARARGS,
"" },
{ "wicket_destroy", (PyCFunction) api_wicket_destroy, METH_VARARGS,
"" },
{ "wicket_get_ticket", (PyCFunction) api_wicket_get_ticket, METH_VARARGS,
"" },
{ "register_module", (PyCFunction) api_register_module, METH_VARARGS,
"" },
......
......@@ -84,6 +84,7 @@ mu_py_init (void)
mu_py_init_mailcap ();
mu_py_init_message ();
mu_py_init_mime ();
mu_py_init_secret ();
mu_py_init_stream ();
mu_py_init_url ();
}
......@@ -123,6 +124,7 @@ mu_py_attach_modules (void)
_mu_py_attach_message ();
_mu_py_attach_mime ();
_mu_py_attach_registrar ();
_mu_py_attach_secret ();
_mu_py_attach_stream ();
_mu_py_attach_url ();
_mu_py_attach_util ();
......
......@@ -42,6 +42,7 @@
#include <mailutils/mutil.h>
#include <mailutils/registrar.h>
#include <mailutils/tls.h>
#include <mailutils/secret.h>
#include <mailutils/stream.h>
#include <mailutils/url.h>
#include <mailutils/python.h>
......@@ -73,6 +74,7 @@ extern void _mu_py_attach_mailcap (void);
extern void _mu_py_attach_message (void);
extern void _mu_py_attach_mime (void);
extern void _mu_py_attach_registrar (void);
extern void _mu_py_attach_secret (void);
extern void _mu_py_attach_stream (void);
extern void _mu_py_attach_url (void);
extern void _mu_py_attach_util (void);
......
/*
GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2009 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library; if not, write to the
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301 USA
*/
#include "libmu_py.h"
#define PY_MODULE "secret"
#define PY_CSNAME "SecretType"
static PyObject *
_repr (PyObject *self)
{
char buf[80];
sprintf (buf, "<" PY_MODULE "." PY_CSNAME " instance at %p>", self);
return PyString_FromString (buf);
}
static PyTypeObject PySecretType = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
PY_MODULE "." PY_CSNAME, /* tp_name */
sizeof (PySecret), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)_py_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr; __getattr__ */
0, /* tp_setattr; __setattr__ */
0, /* tp_compare; __cmp__ */
_repr, /* tp_repr; __repr__ */
0, /* tp_as_number */
0, /* tp_as_sequence */
0, /* tp_as_mapping */
0, /* tp_hash; __hash__ */
0, /* tp_call; __call__ */
_repr, /* tp_str; __str__ */
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT, /* tp_flags */
"", /* tp_doc */
0, /* tp_traverse */
0, /* tp_clear */
0, /* tp_richcompare */
0, /* tp_weaklistoffset */
0, /* tp_iter */
0, /* tp_iternext */
0, /* 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 */
0, /* tp_init */
0, /* tp_alloc */
0, /* tp_new */
};
PySecret *
PySecret_NEW ()
{
return (PySecret *)PyObject_NEW (PySecret, &PySecretType);
}
int
PySecret_Check (PyObject *x)
{
return x->ob_type == &PySecretType;
}
static PyObject *
api_secret_create (PyObject *self, PyObject *args)
{
int status;
char *str;
size_t len;
PySecret *py_secret;
if (!PyArg_ParseTuple (args, "O!si", &PySecretType, &py_secret,
&str, &len))
return NULL;
status = mu_secret_create (&py_secret->secret, str, len);
return _ro (PyInt_FromLong (status));
}
static PyObject *
api_secret_destroy (PyObject *self, PyObject *args)
{
PySecret *py_secret;
if (!PyArg_ParseTuple (args, "O!", &PySecretType, &py_secret))
return NULL;
mu_secret_destroy (&py_secret->secret);
return _ro (Py_None);
}
static PyObject *
api_secret_password (PyObject *self, PyObject *args)
{
int status;
const char *pass;
PySecret *py_secret;
if (!PyArg_ParseTuple (args, "O!", &PySecretType, &py_secret))
return NULL;
pass = mu_secret_password (py_secret->secret);
return _ro (PyString_FromString (pass ? pass : ""));
}
static PyObject *
api_secret_password_unref (PyObject *self, PyObject *args)
{
PySecret *py_secret;
if (!PyArg_ParseTuple (args, "O!", &PySecretType, &py_secret))
return NULL;
mu_secret_password_unref (py_secret->secret);
return _ro (Py_None);
}
static PyObject *
api_clear_passwd (PyObject *self, PyObject *args)
{
char *p;
if (!PyArg_ParseTuple (args, "s", &p))
return NULL;
while (*p)
*p++ = 0;
return _ro (Py_None);
}
static PyMethodDef methods[] = {
{ "create", (PyCFunction) api_secret_create, METH_VARARGS,
"Create the secret data structure." },
{ "destroy", (PyCFunction) api_secret_destroy, METH_VARARGS,
"Destroy the secret and free its resources." },
{ "password", (PyCFunction) api_secret_password, METH_VARARGS,
"" },
{ "password_unref", (PyCFunction) api_secret_password_unref, METH_VARARGS,
"" },
{ "clear_passwd", (PyCFunction) api_clear_passwd, METH_VARARGS,
"" },
{ NULL, NULL, 0, NULL }
};
int
mu_py_init_secret (void)
{
PySecretType.tp_new = PyType_GenericNew;
return PyType_Ready (&PySecretType);
}
void
_mu_py_attach_secret (void)
{
PyObject *m;
if ((m = _mu_py_attach_module (PY_MODULE, methods)))
{
Py_INCREF (&PySecretType);
PyModule_AddObject (m, PY_CSNAME, (PyObject *)&PySecretType);
}
}
......@@ -160,23 +160,21 @@ api_url_get_user (PyObject *self, PyObject *args)
return status_object (status, PyString_FromString (buf ? buf : ""));
}
#if 0
/* FIXME: Returning plaintext (unobfuscated) password from
a secret actually makes the latter useless. */
static PyObject *
api_url_get_passwd (PyObject *self, PyObject *args)
api_url_get_secret (PyObject *self, PyObject *args)
{
int status;
const char *buf = NULL;
PyUrl *py_url;
PySecret *py_secret = PySecret_NEW ();
if (!PyArg_ParseTuple (args, "O!", &PyUrlType, &py_url))
return NULL;
status = mu_url_sget_passwd (py_url->url, &buf);
return status_object (status, PyString_FromString (buf ? buf : ""));
Py_INCREF (py_secret);
status = mu_url_get_secret (py_url->url, &py_secret->secret);
return status_object (status, (PyObject *)py_secret);
}
#endif
static PyObject *
api_url_get_auth (PyObject *self, PyObject *args)
......@@ -271,9 +269,7 @@ static PyMethodDef methods[] = {
{ "get_port", (PyCFunction) api_url_get_port, METH_VARARGS, "" },
{ "get_scheme", (PyCFunction) api_url_get_scheme, METH_VARARGS, "" },
{ "get_user", (PyCFunction) api_url_get_user, METH_VARARGS, "" },
#if 0 /*FIXME: See above */
{ "get_passwd", (PyCFunction) api_url_get_passwd, METH_VARARGS, "" },
#endif
{ "get_secret", (PyCFunction) api_url_get_secret, METH_VARARGS, "" },
{ "get_auth", (PyCFunction) api_url_get_auth, METH_VARARGS, "" },
{ "get_host", (PyCFunction) api_url_get_host, METH_VARARGS, "" },
{ "get_path", (PyCFunction) api_url_get_path, METH_VARARGS, "" },
......
......@@ -35,6 +35,7 @@ MU_PY_PKGPYTHON_LIST=\
message.py \
mime.py \
registrar.py \
secret.py \
stream.py \
url.py \
util.py
......
......@@ -33,6 +33,7 @@ __all__ = [
"message",
"mime",
"registrar",
"secret",
"stream",
"url",
"util",
......
......@@ -100,6 +100,11 @@ class Ticket:
auth.ticket_destroy (self.ticket)
del self.ticket
def set_secret (self, secret):
status = auth.ticket_set_secret (self.ticket, secret.secret)
if status:
raise AuthError (status)
class Wicket:
__owner = False
......@@ -118,16 +123,8 @@ class Wicket:
auth.wicket_destroy (self.wicket)
del self.wicket
def __str__ (self):
return self.get_filename ()
def get_filename (self):
status, filename = auth.wicket_get_filename (self.wicket)
if status:
raise AuthError (status)
return filename
def set_filename (self, filename):
status = auth.wicket_set_filename (self.wicket, filename)
def get_ticket (self, user):
status, ticket = auth.wicket_get_ticket (self.wicket, user)
if status:
raise AuthError (status)
return Ticket (ticket)
......
......@@ -42,6 +42,7 @@ class MailboxError (Error): pass
class MailcapError (Error): pass
class MessageError (Error): pass
class MimeError (Error): pass
class SecretError (Error): pass
class StreamError (Error): pass
class UrlError (Error): pass
......
......@@ -18,6 +18,7 @@
# Boston, MA 02110-1301 USA
#
import types
from mailutils.c_api import mailbox
from mailutils import message
from mailutils import folder
......@@ -26,9 +27,21 @@ from mailutils import debug
from mailutils.error import MailboxError
class MailboxBase:
def open (self, flags = 0):
def open (self, mode = 0):
"""Open the connection."""
status = mailbox.open (self.mbox, flags)
if isinstance (mode, types.StringType):
from mailutils import stream
flags = 0
if mode == 'r':
flags = flags | stream.MU_STREAM_READ
elif mode == 'w':
flags = flags | stream.MU_STREAM_WRITE
elif mode == 'a':
flags = flags | stream.MU_STREAM_APPEND
elif mode == 'c':
flags = flags | stream.MU_STREAM_CREAT
mode = flags
status = mailbox.open (self.mbox, mode)
if status:
raise MailboxError (status)
......
#
# GNU Mailutils -- a suite of utilities for electronic mail
# Copyright (C) 2009 Free Software Foundation, Inc.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General
# Public License along with this library; if not, write to the
# Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
# Boston, MA 02110-1301 USA
#
from mailutils.c_api import secret
from mailutils.error import SecretError
def clear_passwd (passwd):
secret.clear_passwd (passwd)
class Secret:
__owner = False
def __init__ (self, sec):
if isinstance (sec, secret.SecretType):
self.secret = sec
else:
self.secret = secret.SecretType ()
self.__owner = True
status = secret.create (self.secret, sec, len (sec))
if status:
raise SecretError (status)
def __del__ (self):
if self.__owner:
secret.destroy (self.secret)
del self.secret
def password (self):
return secret.password (self.secret)
def password_unref (self):
secret.password_unref (self.secret)
......@@ -19,6 +19,7 @@
#
from mailutils.c_api import url
from mailutils import secret
from mailutils.error import *
class Url:
......@@ -72,13 +73,13 @@ class Url:
raise UrlError (status)
return user
def get_passwd (self):
status, passwd = url.get_passwd (self.url)
def get_secret (self):
status, sec = url.get_secret (self.url)
if status == MU_ERR_NOENT:
return ''
return secret.Secret ('')
elif status:
raise UrlError (status)
return passwd
return secret.Secret (sec)
def get_auth (self):
status, auth = url.get_auth (self.url)
......