1 /* Python plugin for Claws-Mail
2 * Copyright (C) 2009-2012 Holger Berndt
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "claws-features.h"
23 #include <glib/gi18n.h>
25 #include "messageinfotype.h"
27 #include "common/tags.h"
28 #include "common/defs.h"
29 #include "mainwindow.h"
30 #include "summaryview.h"
31 #include "procheader.h"
33 #include <structmember.h>
37 #define HEADER_CONTENT_SIZE BUFFSIZE
42 } clawsmail_MessageInfoObject;
45 static void MessageInfo_dealloc(clawsmail_MessageInfoObject* self)
47 self->ob_type->tp_free((PyObject*)self);
50 static int MessageInfo_init(clawsmail_MessageInfoObject *self, PyObject *args, PyObject *kwds)
55 static PyObject* MessageInfo_str(clawsmail_MessageInfoObject *self)
60 From = self->msginfo->from ? self->msginfo->from : "";
61 Subject = self->msginfo->subject ? self->msginfo->subject : "";
62 return PyString_FromFormat("MessageInfo: %s / %s", From, Subject);
67 static PyObject *py_boolean_return_value(gboolean val)
79 static PyObject *is_new(PyObject *self, PyObject *args)
81 return py_boolean_return_value(MSG_IS_NEW(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
84 static PyObject *is_unread(PyObject *self, PyObject *args)
86 return py_boolean_return_value(MSG_IS_UNREAD(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
89 static PyObject *is_marked(PyObject *self, PyObject *args)
91 return py_boolean_return_value(MSG_IS_MARKED(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
94 static PyObject *is_replied(PyObject *self, PyObject *args)
96 return py_boolean_return_value(MSG_IS_REPLIED(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
99 static PyObject *is_locked(PyObject *self, PyObject *args)
101 return py_boolean_return_value(MSG_IS_LOCKED(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
104 static PyObject *is_forwarded(PyObject *self, PyObject *args)
106 return py_boolean_return_value(MSG_IS_FORWARDED(((clawsmail_MessageInfoObject*)self)->msginfo->flags));
109 static PyObject* get_tags(PyObject *self, PyObject *args)
113 PyObject *tags_tuple;
115 tags_list = ((clawsmail_MessageInfoObject*)self)->msginfo->tags;
116 num_tags = g_slist_length(tags_list);
118 tags_tuple = PyTuple_New(num_tags);
119 if(tags_tuple != NULL) {
121 PyObject *tag_object;
125 for(walk = tags_list; walk; walk = walk->next) {
126 tag_object = Py_BuildValue("s", tags_get_tag(GPOINTER_TO_INT(walk->data)));
127 if(tag_object == NULL) {
128 Py_DECREF(tags_tuple);
131 PyTuple_SET_ITEM(tags_tuple, iTag++, tag_object);
139 static PyObject* add_or_remove_tag(PyObject *self, PyObject *args, gboolean add)
147 retval = PyArg_ParseTuple(args, "s", &tag_str);
151 tag_id = tags_get_id_for_str(tag_str);
153 PyErr_SetString(PyExc_ValueError, "Tag does not exist");
157 msginfo = ((clawsmail_MessageInfoObject*)self)->msginfo;
160 /* raise KeyError if tag is not set */
161 if(!g_slist_find(msginfo->tags, GINT_TO_POINTER(tag_id))) {
162 PyErr_SetString(PyExc_KeyError, "Tag is not set on this message");
167 procmsg_msginfo_update_tags(msginfo, add, tag_id);
170 mainwin = mainwindow_get_mainwindow();
172 summary_redisplay_msg(mainwin->summaryview);
179 static PyObject* add_tag(PyObject *self, PyObject *args)
181 return add_or_remove_tag(self, args, TRUE);
185 static PyObject* remove_tag(PyObject *self, PyObject *args)
187 return add_or_remove_tag(self, args, FALSE);
190 static PyObject* get_header(PyObject *self, PyObject *args)
194 char *header_str_dup;
196 gchar header_content[HEADER_CONTENT_SIZE];
198 retval = PyArg_ParseTuple(args, "s", &header_str);
202 msginfo = ((clawsmail_MessageInfoObject*)self)->msginfo;
204 header_str_dup = g_strdup(header_str);
205 retval = procheader_get_header_from_msginfo(msginfo, header_content, HEADER_CONTENT_SIZE, header_str);
206 g_free(header_str_dup);
208 PyObject *header_content_object;
209 gchar *content_start;
211 /* the string is now Header: Value. Strip the Header: part */
212 content_start = strstr(header_content, ":");
213 if(content_start == NULL)
214 content_start = header_content;
217 /* strip leading spaces */
218 while(*content_start == ' ')
220 header_content_object = Py_BuildValue("s", content_start);
221 return header_content_object;
228 static PyObject* get_From(clawsmail_MessageInfoObject *self, void *closure)
230 if(self->msginfo && self->msginfo->from)
231 return PyString_FromString(self->msginfo->from);
235 static PyObject* get_To(clawsmail_MessageInfoObject *self, void *closure)
237 if(self->msginfo && self->msginfo->to)
238 return PyString_FromString(self->msginfo->to);
242 static PyObject* get_Cc(clawsmail_MessageInfoObject *self, void *closure)
244 if(self->msginfo && self->msginfo->cc)
245 return PyString_FromString(self->msginfo->cc);
249 static PyObject* get_Subject(clawsmail_MessageInfoObject *self, void *closure)
251 if(self->msginfo && self->msginfo->subject)
252 return PyString_FromString(self->msginfo->subject);
256 static PyObject* get_MessageID(clawsmail_MessageInfoObject *self, void *closure)
258 if(self->msginfo && self->msginfo->msgid)
259 return PyString_FromString(self->msginfo->msgid);
263 static PyObject* get_FilePath(clawsmail_MessageInfoObject *self, void *closure)
267 filepath = procmsg_get_message_file_path(self->msginfo);
270 retval = PyString_FromString(filepath);
278 static PyMethodDef MessageInfo_methods[] = {
279 {"is_new", is_new, METH_NOARGS,
280 "is_new() - checks if the message is new\n"
282 "Returns True if the new flag of the message is set."},
284 {"is_unread", is_unread, METH_NOARGS,
285 "is_unread() - checks if the message is unread\n"
287 "Returns True if the unread flag of the message is set."},
289 {"is_marked", is_marked, METH_NOARGS,
290 "is_marked() - checks if the message is marked\n"
292 "Returns True if the marked flag of the message is set."},
294 {"is_replied", is_replied, METH_NOARGS,
295 "is_replied() - checks if the message has been replied to\n"
297 "Returns True if the replied flag of the message is set."},
299 {"is_locked", is_locked, METH_NOARGS,
300 "is_locked() - checks if the message has been locked\n"
302 "Returns True if the locked flag of the message is set."},
304 {"is_forwarded", is_forwarded, METH_NOARGS,
305 "is_forwarded() - checks if the message has been forwarded\n"
307 "Returns True if the forwarded flag of the message is set."},
309 {"get_tags", get_tags, METH_NOARGS,
310 "get_tags() - get message tags\n"
312 "Returns a tuple of tags that apply to this message."},
314 {"add_tag", add_tag, METH_VARARGS,
315 "add_tag(tag) - add a tag to this message\n"
317 "Add a tag to this message. If the tag is already set, nothing is done.\n"
318 "If the tag does not exist, a ValueError exception is raised."},
320 {"remove_tag", remove_tag, METH_VARARGS,
321 "remove_tag(tag) - remove a tag from this message\n"
323 "Remove a tag from this message. If the tag is not set, a KeyError exception is raised.\n"
324 "If the tag does not exist, a ValueError exception is raised."},
326 {"get_header", get_header, METH_VARARGS,
327 "get_header(name) - get a message header with a given name\n"
329 "Get a message header content with a given name. If the header does not exist,\n"
330 "the value 'None' is returned. If multiple headers with the same name exist,\n"
331 "the first one is returned."},
336 static PyGetSetDef MessageInfo_getset[] = {
337 { "From", (getter)get_From, (setter)NULL,
338 "From - the From header of the message", NULL},
340 { "To", (getter)get_To, (setter)NULL,
341 "To - the To header of the message", NULL },
343 { "Cc", (getter)get_Cc, (setter)NULL,
344 "Cc - the Cc header of the message", NULL },
346 {"Subject", (getter)get_Subject, (setter)NULL,
347 "Subject - the subject header of the message", NULL},
349 {"MessageID", (getter)get_MessageID, (setter)NULL,
350 "MessageID - the Message-ID header of the message", NULL},
352 {"FilePath", (getter)get_FilePath, (setter)NULL,
353 "FilePath - path and filename of the message", NULL},
359 static PyTypeObject clawsmail_MessageInfoType = {
360 PyObject_HEAD_INIT(NULL)
362 "clawsmail.MessageInfo", /* tp_name*/
363 sizeof(clawsmail_MessageInfoObject), /* tp_basicsize*/
365 (destructor)MessageInfo_dealloc, /* tp_dealloc*/
372 0, /* tp_as_sequence*/
373 0, /* tp_as_mapping*/
376 (reprfunc)MessageInfo_str, /* tp_str*/
380 Py_TPFLAGS_DEFAULT, /* tp_flags*/
381 "A MessageInfo represents" /* tp_doc */
382 " a single message.\n\n"
383 "Do not construct objects of this type yourself.",
386 0, /* tp_richcompare */
387 0, /* tp_weaklistoffset */
390 MessageInfo_methods, /* tp_methods */
392 MessageInfo_getset, /* tp_getset */
395 0, /* tp_descr_get */
396 0, /* tp_descr_set */
397 0, /* tp_dictoffset */
398 (initproc)MessageInfo_init,/* tp_init */
403 gboolean cmpy_add_messageinfo(PyObject *module)
405 clawsmail_MessageInfoType.tp_new = PyType_GenericNew;
406 if(PyType_Ready(&clawsmail_MessageInfoType) < 0)
409 Py_INCREF(&clawsmail_MessageInfoType);
410 return (PyModule_AddObject(module, "MessageInfo", (PyObject*)&clawsmail_MessageInfoType) == 0);
413 PyObject* clawsmail_messageinfo_new(MsgInfo *msginfo)
415 clawsmail_MessageInfoObject *ff;
420 ff = (clawsmail_MessageInfoObject*) PyObject_CallObject((PyObject*) &clawsmail_MessageInfoType, NULL);
424 ff->msginfo = msginfo;
425 return (PyObject*)ff;
428 PyTypeObject* clawsmail_messageinfo_get_type_object()
430 return &clawsmail_MessageInfoType;
433 MsgInfo* clawsmail_messageinfo_get_msginfo(PyObject *self)
435 return ((clawsmail_MessageInfoObject*)self)->msginfo;