diff --git a/modules/webmessage/.cvsignore b/modules/webmessage/.cvsignore
new file mode 100644
index 000000000..a3409fca7
--- /dev/null
+++ b/modules/webmessage/.cvsignore
@@ -0,0 +1,5 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
\ No newline at end of file
diff --git a/modules/webmessage/Makefile.am b/modules/webmessage/Makefile.am
new file mode 100644
index 000000000..8e5384351
--- /dev/null
+++ b/modules/webmessage/Makefile.am
@@ -0,0 +1,22 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+SUBDIRS = lib web doc
+
+CLEANFILES = *~
diff --git a/modules/webmessage/doc/.cvsignore b/modules/webmessage/doc/.cvsignore
new file mode 100644
index 000000000..f0878fb91
--- /dev/null
+++ b/modules/webmessage/doc/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.py
+*.shtml
+*.html
\ No newline at end of file
diff --git a/modules/webmessage/doc/Makefile.am b/modules/webmessage/doc/Makefile.am
new file mode 100644
index 000000000..f9de00106
--- /dev/null
+++ b/modules/webmessage/doc/Makefile.am
@@ -0,0 +1,22 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+SUBDIRS = admin hacking
+
+CLEANFILES = *~
diff --git a/modules/webmessage/doc/admin/.cvsignore b/modules/webmessage/doc/admin/.cvsignore
new file mode 100644
index 000000000..f0878fb91
--- /dev/null
+++ b/modules/webmessage/doc/admin/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.py
+*.shtml
+*.html
\ No newline at end of file
diff --git a/modules/webmessage/doc/admin/Makefile.am b/modules/webmessage/doc/admin/Makefile.am
new file mode 100644
index 000000000..ddd946333
--- /dev/null
+++ b/modules/webmessage/doc/admin/Makefile.am
@@ -0,0 +1,29 @@
+## $Id$
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+docdir = $(WEBDIR)/admin/webmessage
+
+doc_DATA = guide.html
+
+FILESWML = $(wildcard $(srcdir)/*.wml)
+EXTRA_DIST = $(FILESWML:$(srcdir)/%=%)
+
+CLEANFILES = $(doc_DATA) *~ *.tmp
+
+%.html: %.html.wml $(top_srcdir)/config/config.wml $(top_builddir)/config/configbis.wml $(top_srcdir)/config/cdsnavbar.wml
+ $(WML) -o\(ALL-LANG_*\)+LANG_EN:$@ $<
diff --git a/modules/webmessage/doc/admin/guide.html.wml b/modules/webmessage/doc/admin/guide.html.wml
new file mode 100644
index 000000000..fa4684db6
--- /dev/null
+++ b/modules/webmessage/doc/admin/guide.html.wml
@@ -0,0 +1,27 @@
+## -*- mode: html; coding: utf-8; -*-
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+#include "cdspage.wml" \
+ title="WebMessage Admin Guide" \
+ navtrail_previous_links="/admin/> > /admin/webmessage/>WebMessage Admin" \
+ navbar_name="admin" \
+ navbar_select="webmessage-admin-guide"
+
+FIXME
diff --git a/modules/webmessage/doc/hacking/.cvsignore b/modules/webmessage/doc/hacking/.cvsignore
new file mode 100644
index 000000000..f0878fb91
--- /dev/null
+++ b/modules/webmessage/doc/hacking/.cvsignore
@@ -0,0 +1,8 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*~
+*.py
+*.shtml
+*.html
\ No newline at end of file
diff --git a/modules/webmessage/doc/hacking/Makefile.am b/modules/webmessage/doc/hacking/Makefile.am
new file mode 100644
index 000000000..e69de29bb
diff --git a/modules/webmessage/lib/.cvsignore b/modules/webmessage/lib/.cvsignore
new file mode 100644
index 000000000..c2eb99c3e
--- /dev/null
+++ b/modules/webmessage/lib/.cvsignore
@@ -0,0 +1,7 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*.shtml
+*~
+*.pyc
diff --git a/modules/webmessage/lib/Makefile.am b/modules/webmessage/lib/Makefile.am
new file mode 100644
index 000000000..85b48b312
--- /dev/null
+++ b/modules/webmessage/lib/Makefile.am
@@ -0,0 +1,26 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+pylibdir=$(libdir)/python/cdsware
+
+pylib_DATA=webmessage.py webmessage_templates.py webmessage_config.py webmessage_dblayer.py webmessage_mailutils.py
+
+EXTRA_DIST = $(pylib_DATA)
+
+CLEANFILES = *~ *.tmp *.pyc
diff --git a/modules/webmessage/lib/webmessage.py b/modules/webmessage/lib/webmessage.py
new file mode 100644
index 000000000..65e68e26f
--- /dev/null
+++ b/modules/webmessage/lib/webmessage.py
@@ -0,0 +1,547 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Messaging system (internal)
+
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+__lastupdated__ = """$Date$"""
+
+# External imports
+from datetime import date
+
+# CDSWare imports
+from cdsware.webmessage_dblayer import *
+from cdsware.webmessage_config import *
+from cdsware.config import cdslang
+from cdsware.messages import gettext_set_language
+
+import cdsware.template
+
+webmessage_templates = cdsware.template.load('webmessage')
+
+def perform_request_display_msg(uid, msgid, ln = cdslang):
+ """
+ Displays a specific message
+ @param uid: user id
+ @param msgid: message id
+
+ @return a (body, errors[], warnings[]) formed tuple
+ """
+ # Wash the arguments...
+ uid = wash_url_argument(uid, 'int')
+ msgid = wash_url_argument(msgid, 'int')
+
+ errors = []
+ warnings = []
+ body = ""
+
+ if (check_user_owns_message(uid, msgid) == 0):
+ # The user doesn't own this message
+ errors.append(('ERR_WEBMESSAGE_NOTOWNER',))
+ else:
+ (msg_id,
+ msg_from_id,
+ msg_from_nickname,
+ msg_sent_to,
+ msg_sent_to_group,
+ msg_subject,
+ msg_body,
+ msg_sent_date,
+ msg_received_date,
+ msg_status) = get_message(uid, msgid)
+
+ if (msg_id == ""):
+ # The message exists in table user_msgMESSAGE
+ # but not in table msgMESSAGE => table inconsistency
+ errors.append(('ERR_WEBMESSAGE_NOMESSAGE',))
+ else:
+ if (msg_status == 'N'):
+ set_message_status(uid, msgid, 'R')
+ body = webmessage_templates.tmpl_display_msg(msg_id,
+ msg_from_id,
+ msg_from_nickname,
+ msg_sent_to,
+ msg_sent_to_group,
+ msg_subject,
+ msg_body,
+ msg_sent_date,
+ msg_received_date,
+ ln)
+
+ return (body, errors, warnings)
+
+
+def perform_request_display(uid, errors=[], warnings=[], infos=[], ln=cdslang):
+ """
+ Displays the user's Inbox
+ @param uid: user id
+
+ @return a (body, [errors], [warnings]) formed tuple
+ """
+ # Wash the arguments...
+ uid = wash_url_argument(uid, 'int')
+
+ body = ""
+ rows = []
+ rows = get_all_messages_for_user(uid)
+ nb_messages = 0
+
+ if (uid != 1):
+ nb_messages = count_nb_messages(uid)
+
+ body = webmessage_templates.tmpl_display_inbox(messages=rows,
+ infos=infos,
+ warnings=warnings,
+ nb_messages=nb_messages,
+ ln=ln)
+ return (body, errors, warnings)
+
+
+def perform_request_delete_msg(uid, msgid, ln=cdslang):
+ """
+ Delete a given message from user inbox
+ @param uid: user id (int)
+ @param msgid: message id (int)
+ @param ln: language
+ @return a (body, errors, warning tuple)
+ """
+ # Wash the arguments...
+ uid = wash_url_argument(uid, 'int')
+ msgid = wash_url_argument(msgid, 'int')
+
+ _ = gettext_set_language(ln)
+
+ errors = []
+ warnings = []
+ infos = []
+
+ if (check_user_owns_message(uid, msgid) == 0):
+ # The user doesn't own this message
+ errors.append(('ERR_WEBMESSAGE_NOTOWNER',))
+ else:
+ if (delete_message_from_user_inbox(uid, msgid)==0):
+ warnings.append(_("The message could not be deleted"))
+ else:
+ infos.append(_("Delete successful"))
+
+ return perform_request_display(uid, errors, warnings, infos, ln)
+
+
+def perform_request_delete_all(uid, confirmed=0, ln=cdslang):
+ """
+ Delete every message for a given user
+ @param uid: user id (int)
+ @param confirmed: 0 will produce a confirmation message
+ @param ln: language
+ @return a (body, errors, warnings) tuple
+ """
+
+ infos = []
+ warnings = []
+ errors = []
+ confirmed = wash_url_argument(confirmed, 'int')
+
+ _ = gettext_set_language(ln)
+ if (confirmed == 1):
+ delete_all_messages(uid)
+ infos = [_("Your mailbox has been emptied")]
+ return perform_request_display(uid, warnings, errors, infos, ln)
+ else:
+ body = webmessage_templates.tmpl_confirm_delete(ln)
+ return (body, errors, warnings)
+
+
+def perform_request_write(uid,
+ msg_reply_id="",
+ msg_to="",
+ msg_to_group="",
+ ln=cdslang):
+ """
+ Display a write a message page.
+ @param uid: user id (int)
+ @param msg_reply_id: if this message is a reply to another, other's ID (int)
+ @param msg_to: comma separated usernames (string)
+ @param msg_to_group: comma separated groupnames (string)
+ @param ln: language
+ @return a (body, errors, warnings) tuple
+ """
+ # wash arguments
+ uid = wash_url_argument(uid, 'int')
+ msg_reply_id = wash_url_argument(msg_reply_id, 'int')
+ msg_to = wash_url_argument(msg_to, 'str')
+ msg_to_group = wash_url_argument(msg_to_group, 'str')
+ # ln has already been washed in yourmessages.py
+
+ errors = []
+ warnings = []
+ body = ""
+
+ msg_from_nickname = ""
+ msg_subject = ""
+ msg_body = ""
+ msg_id = 0
+ if (msg_reply_id):
+ if (check_user_owns_message(uid, msg_reply_id) == 0):
+ # The user doesn't own this message
+ errors.append(('ERR_WEBMESSAGE_NOTOWNER',))
+ else:
+ # Junk== make pylint happy!
+ junk = 0
+ (msg_id,
+ junk,
+ msg_from_nickname,
+ junk,
+ junk,
+ msg_subject,
+ msg_body,
+ junk,
+ junk,
+ junk) = get_message(uid, msg_reply_id)
+ if (msg_id == ""):
+ # The message exists in table user_msgMESSAGE
+ # but not in table msgMESSAGE => table inconsistency
+ errors.append(('ERR_WEBMESSAGE_NOMESSAGE',))
+ else:
+ msg_to = msg_from_nickname
+
+ body = webmessage_templates.tmpl_write(msg_to=msg_to,
+ msg_to_group=msg_to_group,
+ msg_id=msg_id,
+ msg_subject=msg_subject,
+ msg_body=msg_body,
+ warnings=[],
+ ln=ln)
+ return (body, errors, warnings)
+
+
+
+def perform_request_write_with_search(msg_to_user="",
+ msg_to_group="",
+ msg_subject="",
+ msg_body="",
+ msg_send_year=0,
+ msg_send_month=0,
+ msg_send_day=0,
+ users_to_add=[],
+ groups_to_add=[],
+ user_search_pattern="",
+ group_search_pattern="",
+ mode_user=1,
+ add_values=0,
+ ln=cdslang):
+ """
+ Display a write message page, with prefilled values
+ @param msg_to_user: comma separated usernames (str)
+ @param msg_to_group: comma separated groupnames (str)
+ @param msg_subject: message subject (str)
+ @param msg_bidy: message body (string)
+ @param msg_send_year: year to send this message on (int)
+ @param_msg_send_month: month to send this message on (int)
+ @param_msg_send_day: day to send this message on (int)
+ @param users_to_add: list of usernames ['str'] to add to msg_to_user
+ @param groups_to_add: list of groupnames ['str'] to add to msg_to_group
+ @param user_search_pattern: will search users with this pattern (str)
+ @param group_search_pattern: will search groups with this pattern (str)
+ @param mode_user: if 1 display user search box, else group search box
+ @param add_values: if 1 users_to_add will be added to msg_to_user field..
+ @param ln: language
+ @return a (body, errors, warnings) formed tuple.
+ """
+
+ # wash arguments
+ users_to_add = wash_url_argument(users_to_add, 'list')
+ groups_to_add = wash_url_argument(groups_to_add, 'list')
+ msg_send_year = wash_url_argument(msg_send_year, 'int')
+ msg_send_month = wash_url_argument(msg_send_month, 'int')
+ msg_send_day = wash_url_argument(msg_send_day, 'int')
+
+ user_list_output = []
+ group_list_output = []
+ warnings = []
+ errors = []
+
+ def separate(name1, name2):
+ """
+ name1, name2 => "name1, name2"
+ """
+ return name1 + cfg_webmessage_separator + " " + name2
+
+ if mode_user:
+ if add_values and users_to_add:
+ tmp = users_to_add
+ if msg_to_user:
+ tmp.insert(0, msg_to_user)
+ msg_to_user = reduce(separate, tmp)
+ if user_search_pattern:
+ users_found = get_nicknames_like(user_search_pattern)
+ if users_found:
+ for user_name in users_found:
+ user_list_output.append((user_name[0], user_name[0] in users_to_add))
+ else:
+ if add_values and groups_to_add:
+ tmp = groups_to_add
+ if msg_to_group:
+ tmp.insert(0, msg_to_group)
+ msg_to_group = reduce(separate, tmp)
+ if group_search_pattern:
+ groups_found = get_groupnames_like(group_search_pattern)
+ if groups_found:
+ for group_name in groups_found:
+ group_list_output.append((group_name[0], group_name[0] in groups_to_add))
+ body = webmessage_templates.tmpl_write(msg_to=msg_to_user,
+ msg_to_group=msg_to_group,
+ msg_subject=msg_subject,
+ msg_body=msg_body,
+ msg_send_year=msg_send_year,
+ msg_send_month=msg_send_month,
+ msg_send_day=msg_send_day,
+ warnings=warnings,
+ users_to_add=user_list_output,
+ groups_to_add=group_list_output,
+ user_search_pattern=user_search_pattern,
+ group_search_pattern=group_search_pattern,
+ display_users_to_add=mode_user,
+ ln=ln)
+ return (body, errors, warnings)
+
+
+def perform_request_send(uid,
+ msg_to_user="",
+ msg_to_group="",
+ msg_subject="",
+ msg_body="",
+ msg_send_year=0,
+ msg_send_month=0,
+ msg_send_day=0,
+ ln=cdslang):
+ """
+ send a message. if unable return warenings to write page
+ @param uid: id of user from (int)
+ @param msg_to_user: comma separated usernames (recipients) (str)
+ @param msg_to_group: comma separated groupnames (recipeints) (str)
+ @param msg_subject: subject of message (str)
+ @param msg_body: body of message (str)
+ @param msg_send_year: send this message on year x (int)
+ @param msg_send_month: send this message on month y (int)
+ @param msg_send_day: send this message on day z (int)
+ @param ln: language
+ @return a (body, errors, warnings) tuple
+ """
+ # wash arguments
+ msg_to_user = wash_url_argument(msg_to_user, 'str')
+ msg_to_group = wash_url_argument(msg_to_group, 'str')
+ msg_subject = wash_url_argument(msg_subject, 'str')
+ msg_body = wash_url_argument(msg_body, 'str')
+ msg_send_year = wash_url_argument(msg_send_year, 'int')
+ msg_send_month = wash_url_argument(msg_send_month, 'int')
+ msg_send_day = wash_url_argument(msg_send_day, 'int')
+
+ _ = gettext_set_language(ln)
+
+ def strip_spaces(str):
+ """suppress spaces before and after x (str)"""
+ return str.strip()
+ # wash user input
+ users_to = map(strip_spaces, msg_to_user.split(cfg_webmessage_separator))
+ groups_to = map(strip_spaces, msg_to_group.split(cfg_webmessage_separator))
+
+ if users_to == [""]:
+ users_to = []
+ if groups_to == [""]:
+ groups_to = []
+
+
+ warnings = []
+ errors = []
+ infos = []
+ problem = None
+
+ users_to_str = cfg_webmessage_separator.join(users_to)
+ groups_to_str = cfg_webmessage_separator.join(groups_to)
+
+ if (msg_send_year == msg_send_month == msg_send_day == 0):
+ status = cfg_webmessage_status_code['NEW']
+ else:
+ status = cfg_webmessage_status_code['REMINDER']
+
+ try:
+ send_on_date = convert_date(msg_send_year, msg_send_month, msg_send_day)
+ except ValueError:
+ warnings.append(_("The chosen date (%i/%i/%i) is invalid")%(msg_send_year, msg_send_month, msg_send_day))
+ problem = 1
+
+ if not(users_to_str or groups_to_str):
+ # <=> not(users_to_str) AND not(groups_to_str)
+ warnings.append(_("Please enter a user name or a group name"))
+ problem = 1
+
+ if len(msg_body) > cfg_webmessage_max_size_of_message:
+ warnings.append(_("""Your message is too long, please edit it.
+ Max size allowed is %i characters
+ """)%(cfg_webmessage_max_size_of_message,))
+ problem = 1
+
+
+ users_dict = get_uids_from_nicks(users_to)
+ users_to = users_dict.items()
+ groups_dict = get_gids_from_groupnames(groups_to)
+ groups_to = groups_dict.items()
+ gids_to = []
+ for (group_name, group_id) in groups_to:
+ if not(group_id):
+ warnings.append(_("Group '%s' doesn't exist\n")%(group_name))
+ problem = 1
+ else:
+ gids_to.append(group_id)
+
+ # Get uids from gids
+ uids_from_group = get_uids_members_of_groups(gids_to)
+ # Add the original uids, and make sure there is no double values.
+ tmp_dict = dict.fromkeys(uids_from_group)
+ for (user_nick, user_id) in users_to:
+ if user_id:
+ if user_id not in tmp_dict:
+ uids_from_group.append(user_id)
+ tmp_dict[user_id] = None
+ else:
+ warnings.append(_("User '%s' doesn't exist\n")%(user_nick))
+ problem = 1
+ if problem:
+ body = webmessage_templates.tmpl_write(msg_to=users_to_str,
+ msg_to_group=groups_to_str,
+ msg_subject=msg_subject,
+ msg_body=msg_body,
+ msg_send_year=msg_send_year,
+ msg_send_month=msg_send_month,
+ msg_send_day=msg_send_day,
+ warnings=warnings,
+ ln=ln)
+ return (body, errors, warnings)
+ else:
+ msg_id = create_message(uid,
+ users_to_str,
+ groups_to_str,
+ msg_subject,
+ msg_body,
+ send_on_date)
+ uid_problem = send_message(uids_from_group, msg_id, status)
+ if len(uid_problem) > 0:
+ usernames_problem_dict = get_nicks_from_uids(uid_problem)
+ usernames_problem = usernames_problem_dict.values()
+ def listing(name1, name2):
+ """ name1, name2 => 'name1, name2' """
+ return str(name1) + ", " + str(name2)
+ warning = _("Your message couldn't be sent to the following recipients\n")
+ warning += _("These users are overquota: ")
+ warnings.append(warning + reduce(listing, usernames_problem))
+
+
+ if len(uids_from_group) != len(uid_problem):
+ infos.append(_("Your message has been sent."))
+ return perform_request_display(uid, errors, warnings, infos, ln)
+
+
+def account_new_mail(uid, ln=cdslang):
+ """
+ display new mail info for myaccount.py page.
+ @param uid: user id (int)
+ @param ln: language
+ @return html body
+ """
+ nb_new_mail = get_nb_new_mail_for_user(uid)
+ return webmessage_templates.tmpl_account_new_mail(nb_new_mail, ln)
+
+
+def convert_date(year, month, day):
+ """
+ convert a given date to mySQL notation
+ @param year: year as an int
+ @param month: month as an int
+ @param day: day as an int
+ @return string representation of date
+ """
+ format = "%Y-%m-%d %H:%M:%S"
+ if ((year, month, day)!=(0, 0, 0)):
+ out = date(year, month, day).strftime(format)
+ else:
+ out = '0000-00-00 00:00:00'
+ return out
+
+
+def get_navtrail(ln=cdslang, title=""):
+ """
+ gets the navtrail for title...
+ @param title: title of the page
+ @param ln: language
+ @return HTML output
+ """
+ navtrail = webmessage_templates.tmpl_navtrail(ln, title)
+ return navtrail
+
+def wash_url_argument(var, new_type):
+ """
+ Wash argument into 'new_type', that can be 'list', 'str', or 'int'.
+ If var is a list, will change first element into new_type.
+ If int check unsuccessful, returns 0
+ If needed, the check 'type(var) is not None' should be done before calling this function
+ """
+ out = []
+ if new_type == 'list': # return lst
+ if type(var) is list or type(var) is tuple:
+ out = var
+ else:
+ out = [var]
+ elif new_type == 'str': # return str
+ if type(var) is list:
+ try:
+ out = "%s" % var[0]
+ except:
+ out = ""
+ elif type(var) is str:
+ out = var
+ else:
+ out = "%s" % var
+ elif new_type == 'int': # return int
+ if type(var) is list:
+ try:
+ out = int(var[0])
+ except:
+ out = 0
+ elif type(var) is int:
+ out = var
+ elif type(var) is str:
+ try:
+ out = int(var)
+ except:
+ out = 0
+ else:
+ out = 0
+ elif new_type == 'tuple': # return tuple
+ if type(var) is tuple:
+ out = var
+ else:
+ out = (var,)
+ elif new_type == 'dict': # return dictionary
+ if type(var) is dict:
+ out = var
+ else:
+ out = {0:var}
+ return out
+
diff --git a/modules/webmessage/lib/webmessage_config.py b/modules/webmessage/lib/webmessage_config.py
new file mode 100644
index 000000000..e12492e4e
--- /dev/null
+++ b/modules/webmessage/lib/webmessage_config.py
@@ -0,0 +1,39 @@
+# -*- coding: utf-8 -*-
+## $Id$
+##
+## Configuration for webmessage module
+##
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+cfg_webmessage_error_messages = \
+{ 'ERR_WEBMESSAGE_NOTOWNER': " This message is not in your mailbox ",
+ 'ERR_WEBMESSAGE_NONICKNAME':' No nickname or user for uid #%s ',
+ 'ERR_WEBMESSAGE_NOMESSAGE': " This message doesn't exist "
+}
+
+cfg_webmessage_status_code = \
+{
+ 'NEW': 'N',
+ 'READ': 'R',
+ 'REMINDER': 'M'
+}
+
+cfg_webmessage_separator = ','
+cfg_webmessage_max_size_of_message = 20000
+cfg_webmessage_max_nb_of_messages = 30
diff --git a/modules/webmessage/lib/webmessage_dblayer.py b/modules/webmessage/lib/webmessage_dblayer.py
new file mode 100644
index 000000000..4fc812eff
--- /dev/null
+++ b/modules/webmessage/lib/webmessage_dblayer.py
@@ -0,0 +1,474 @@
+# -*- coding: utf-8 -*-
+## $Id$
+##
+## Every db-related function of module webmessage
+##
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+import time
+
+from MySQLdb import escape_string
+
+from cdsware.dbquery import run_sql
+from cdsware.webmessage_config import cfg_webmessage_status_code, \
+ cfg_webmessage_max_nb_of_messages
+
+
+def check_user_owns_message(uid, msgid):
+ """
+ Checks whether a user owns a message
+ @param uid: user id
+ @param msgid: message id
+ @return 1 if the user owns the message, else 0
+ """
+ query = """SELECT count(*)
+ FROM user_msgMESSAGE
+ WHERE id_user_to=%(user_id)i AND
+ id_msgMESSAGE=%(message_id)i"""
+ params = {'user_id': int(uid),
+ 'message_id': int(msgid)}
+ res = run_sql(query%params)
+ return int(res[0][0])
+
+def get_message(uid, msgid):
+ """
+ get a message with its status
+ @param uid: user id
+ @param msgid: message id
+ @return a (message_id,
+ id_user_from,
+ nickname_user_from,
+ sent_to_user_nicks,
+ sent_to_group_names,
+ subject,
+ body,
+ sent_date,
+ received_date,
+ status)
+ formed tuple or 0 (ZERO) if none found
+ """
+ query = """SELECT m.id,
+ m.id_user_from,
+ u.nickname,
+ m.sent_to_user_nicks,
+ m.sent_to_group_names,
+ m.subject,
+ m.body,
+ m.sent_date,
+ m.received_date,
+ um.status
+ FROM msgMESSAGE m,
+ user_msgMESSAGE um,
+ user u
+ WHERE m.id=%(message_id)i AND
+ um.id_msgMESSAGE=%(message_id)i AND
+ um.id_user_to=%(user_id)i AND
+ u.id=m.id_user_from"""
+ params = {'message_id': int(msgid),
+ 'user_id': int(uid)}
+ res = run_sql(query%params)
+ if res:
+ return res[0]
+ else:
+ return 0
+
+def set_message_status(uid, msgid, new_status):
+ """
+ Change the status of a message (e.g. from "new" to "read").
+ the status is a single character string, specified in constant
+ cfg_webmessage_status_code in file webmessage_config.py
+ examples:
+ N: New message
+ R: alreay Read message
+ M: reminder
+ @param uid: user ID
+ @param msgid: Message ID
+ @param new_status: new status. Should be a single character
+ @return 1 if succes, 0 if not
+ """
+
+ query = """UPDATE user_msgMESSAGE
+ SET status='%s'
+ WHERE id_user_to=%i AND
+ id_msgMESSAGE=%i"""
+ params = (escape_string(new_status), uid, msgid)
+ return int(run_sql(query%params))
+
+def get_nb_new_mail_for_user(uid):
+ """ Get number of new mails for a given user
+ @param uid: user id (int)
+ @return number of new mails as int.
+ """
+ update_user_inbox_for_reminders(uid)
+ new_status = cfg_webmessage_status_code['NEW']
+ query = """SELECT count(id_msgMESSAGE)
+ FROM user_msgMESSAGE
+ WHERE id_user_to=%i AND
+ BINARY status='%s'"""
+ params = (int(uid), escape_string(new_status))
+ res = run_sql(query%params)
+ if res:
+ return res[0][0]
+ else:
+ return 0
+
+def get_all_messages_for_user(uid):
+ """
+ Get all messages for a user's inbox, without the eventual
+ non-expired reminders.
+
+ @param uid: user id
+ @return [(message_id,
+ id_user_from,
+ nickname_user_from,
+ message_subject,
+ message_sent_date,
+ message_status)]
+ """
+ update_user_inbox_for_reminders(uid)
+ reminder_status = cfg_webmessage_status_code['REMINDER']
+ query = """SELECT m.id,
+ m.id_user_from,
+ u.nickname,
+ m.subject,
+ m.sent_date,
+ um.status
+ FROM user_msgMESSAGE um,
+ msgMESSAGE m,
+ user u
+ WHERE um.id_user_to = %(user_to)i AND
+ !(BINARY um.status='%(status)s') AND
+ um.id_msgMESSAGE=m.id AND
+ u.id=m.id_user_from
+ ORDER BY m.sent_date DESC
+ """
+ params = {'user_to': int(uid),
+ 'status': escape_string(reminder_status)
+ }
+ return run_sql(query%params)
+
+def count_nb_messages(uid):
+ """
+ @param uid: user id
+ @return integer of number of messages a user has, 0 if none
+ """
+ uid = int(uid)
+ query = """SELECT count(id_user_to)
+ FROM user_msgMESSAGE
+ WHERE id_user_to=%i
+ """
+ res = run_sql(query%uid)
+ if res:
+ return int(res[0][0])
+ else:
+ return 0
+
+def delete_message_from_user_inbox(uid, msg_id):
+ """
+ Delete message from users inbox
+ If this message was does not exist in any other user's inbox,
+ delete it permanently from the database
+ @param uid: user id
+ @param msg_id: message id
+ @return integer 1 if delete was successful, integer 0 else
+ """
+ query1 = """DELETE FROM user_msgMESSAGE
+ WHERE id_user_to=%i AND
+ id_msgMESSAGE=%i"""
+ params1 = (int(uid), int(msg_id))
+ res1 = run_sql(query1%params1)
+ check_if_need_to_delete_message_permanently([msg_id])
+ return int(res1)
+
+def check_if_need_to_delete_message_permanently(msg_ids):
+ """
+ Checks if a list of messages exist in anyone's inbox, if not,
+ delete them permanently
+ @param msg_id: sequence of message ids
+ @return number of deleted messages
+ """
+ if not((type(msg_ids) is list) or (type(msg_ids) is tuple)):
+ msg_ids = [msg_ids]
+ query1 = """SELECT count(id_msgMESSAGE)
+ FROM user_msgMESSAGE
+ WHERE id_msgMESSAGE=%i"""
+ messages_to_delete = []
+ for msg_id in msg_ids:
+ nb_users = int(run_sql(query1%(int(msg_id),))[0][0])
+ if nb_users == 0:
+ messages_to_delete.append(int(msg_id))
+
+ if len(messages_to_delete) > 0:
+ query2 = """DELETE FROM msgMESSAGE
+ WHERE"""
+ for msg_id in messages_to_delete[0:-1]:
+ query2 += " id=%i" % (msg_id,) + " OR"
+ query2 += " id=%i" % (messages_to_delete[-1])
+
+ run_sql(query2)
+ return len(messages_to_delete)
+
+def delete_all_messages(uid):
+ """
+ Delete all messages of a user (except reminders)
+ @param uid: user id
+ @return the number of messages deleted
+ """
+ reminder_status = cfg_webmessage_status_code['REMINDER']
+ query1 = """SELECT id_msgMESSAGE
+ FROM user_msgMESSAGE
+ WHERE id_user_to=%i AND
+ NOT(BINARY status like '%s')"""
+ params = (int(uid), reminder_status)
+ msg_ids = map(get_element, run_sql(query1%params))
+
+ query2 = """DELETE FROM user_msgMESSAGE
+ WHERE id_user_to=%i AND
+ NOT(BINARY status like '%s')"""
+ nb_messages = int(run_sql(query2%params))
+ check_if_need_to_delete_message_permanently(msg_ids)
+ return nb_messages
+
+def get_uids_from_nicks(nicks):
+ """
+ Get the association uid/nickname of given nicknames
+ @param nicks: list or sequence of strings, each string being a nickname
+ @return a dictionary {nickname: uid}
+ """
+ if not((type(nicks) is list) or (type(nicks) is tuple)):
+ nicks = [nicks]
+ users = {}
+ query = "SELECT nickname, id FROM user WHERE BINARY nickname in("
+ if len(nicks)> 0:
+ users = dict.fromkeys(nicks)
+ for nick in nicks[0:-1]:
+ query += "'%s'," % escape_string(nick)
+ query += "'%s')" % escape_string(nicks[-1])
+ res = run_sql(query)
+ def enter_dict(couple):
+ """ takes a a tuple and enters it into dict users """
+ users[couple[0]] = int(couple[1])
+ map(enter_dict, res)
+ return users
+
+def get_nicks_from_uids(uids):
+ """
+ Get the association uid/nickname of given uids
+ @param uids: list or sequence of uids
+ @return a dictionary {uid: nickname} where empty value is possible
+ """
+ if not((type(uids) is list) or (type(uids) is tuple)):
+ uids = [uids]
+ users = {}
+ query = "SELECT id, nickname FROM user WHERE id in("
+ if len(uids) > 0:
+ users = dict.fromkeys(uids)
+ for uid in uids[0:-1]:
+ query += "%i," % int(uid)
+ query += "%i)" % int(uids[-1])
+ res = run_sql(query)
+ for (user_id, nickname) in res:
+ users[int(user_id)] = nickname
+ return users
+
+def get_gids_from_groupnames(groupnames):
+ """
+ Get the gids of given groupnames
+ @param groupnames: list or sequence of strings, each string being a groupname
+ @return a dictionary {groupname: gid}
+ """
+ if not((type(groupnames) is list) or (type(groupnames) is tuple)):
+ groupnames = [groupnames]
+ groups = {}
+ query = "SELECT name, id FROM usergroup WHERE BINARY name in("
+ if len(groupnames) > 0:
+ groups = dict.fromkeys(groupnames)
+ for groupname in groupnames[0:-1]:
+ query += "'%s'," % escape_string(groupname)
+ query += "'%s')" % escape_string(groupnames[-1])
+ res = run_sql(query)
+ def enter_dict(couple):
+ """ enter a tuple into dictionary groups """
+ groups[couple[0]] = int(couple[1])
+ map(enter_dict, res)
+ return groups
+
+def get_uids_members_of_groups(gids):
+ """
+ Get the distinct ids of users members of given groups.
+ @param groupnames: list or sequence of group ids
+ @return a list of uids.
+ """
+ if not((type(gids) is list) or (type(gids) is tuple)):
+ gids = [gids]
+ query = "SELECT DISTINCT id_user FROM user_usergroup WHERE"
+ if len(gids) > 0:
+ for gid in gids[0:-1]:
+ query += " id_usergroup=" + str(int(gid)) + " OR"
+ query += " id_usergroup=" + str(int(gids[-1]))
+ return map(get_element, run_sql(query))
+ return []
+
+def create_message(uid_from,
+ users_to_str="",
+ groups_to_str="",
+ msg_subject="",
+ msg_body="",
+ msg_send_on_date="0000-00-00 00:00:00"):
+ """
+ Creates a message in the msgMESSAGE table. Does NOT send the message.
+ This function is like a datagramPacket...
+ @param uid_from: uid of the sender (int)
+ @param users_to_str: a string, with nicknames separated by semicolons (';')
+ @param groups_to_str: a string with groupnames separated by semicolons
+ @param msg_subject: string containing the subject of the message
+ @param msg_body: string containing the body of the message
+ @param msg_send_on_date: date on which message must be sent. Has to be a
+ mySQL format (i.e. YYYY-mm-dd HH:MM:SS)
+ @return id of the created message
+ """
+ now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
+ query = """INSERT INTO msgMESSAGE(id_user_from,
+ sent_to_user_nicks,
+ sent_to_group_names,
+ subject,
+ body,
+ sent_date,
+ received_date)
+ VALUES(%i,'%s','%s','%s','%s','%s','%s')"""
+ params = (int(uid_from),
+ escape_string(users_to_str),
+ escape_string(groups_to_str),
+ escape_string(msg_subject),
+ escape_string(msg_body),
+ escape_string(now),
+ escape_string(msg_send_on_date))
+ msg_id = run_sql(query%params)
+ return int(msg_id)
+
+def send_message(uids_to, msgid, status=cfg_webmessage_status_code['NEW']):
+ """
+ Send message to uids
+ @param uids: sequence of user ids
+ @param msg_id: id of message
+ @param status: status of the message. (single char, see webmessage_config.py).
+ @return a list of users having their mailbox full
+ """
+ if not((type(uids_to) is list) or (type(uids_to) is tuple)):
+ uids_to = [uids_to]
+
+ user_problem = []
+ if len(uids_to) > 0:
+ users_quotas = check_quota(cfg_webmessage_max_nb_of_messages - 1)
+ query = """INSERT INTO user_msgMESSAGE
+ (id_user_to, id_msgMESSAGE, status)
+ VALUES """
+ fixed_value = "," + str(int(msgid)) + ",'" + escape_string(status) + "')"
+
+ def not_users_quotas_has_key(key):
+ """ not(is key in users over quota?)"""
+ return not(users_quotas.has_key(key))
+ user_ids_to = filter(not_users_quotas_has_key, uids_to)
+ user_problem = filter(users_quotas.has_key, uids_to)
+ if len(user_ids_to) > 0:
+ for uid_to in user_ids_to[0:-1]:
+ query += "(%i" % int(uid_to) + fixed_value + ","
+ query += "(" + str(int(user_ids_to[-1])) + fixed_value
+ run_sql(query)
+ return user_problem
+
+def check_quota(nb_messages):
+ """
+ @param nb_messages: max number of messages a user can have
+ @return a dictionary of users over-quota
+ """
+ query = """SELECT id_user_to, count(id_user_to)
+ FROM user_msgMESSAGE
+ WHERE id_user_to!=1
+ GROUP BY id_user_to
+ HAVING count(id_user_to)>%i"""
+ res = run_sql(query % int(nb_messages))
+ user_over_quota = {}
+ def enter_dict(couple):
+ """ enter a tuple in user_over_quota dict """
+ user_over_quota[int(couple[0])] = int(couple[1])
+ map(enter_dict, res)
+ return user_over_quota
+
+def update_user_inbox_for_reminders(uid):
+ """
+ Updates user's inbox with any reminders that should have arrived
+ @param uid: user id
+ @return integer number of new expired reminders
+ """
+ now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time()))
+ reminder_status = cfg_webmessage_status_code['REMINDER']
+ new_status = cfg_webmessage_status_code['NEW']
+
+ query1 = """SELECT m.id
+ FROM msgMESSAGE m,
+ user_msgMESSAGE um
+ WHERE um.id_user_to=%(uid)i AND
+ um.id_msgMESSAGE=m.id AND
+ m.received_date <= '%(date)s' AND
+ um.status like binary '%(old_status)s'
+ """
+ params1 = {'uid': int(uid),
+ 'date': now,
+ 'old_status': reminder_status
+ }
+
+ res_ids = run_sql(query1%params1)
+
+ out = len(res_ids)
+ if (out>0):
+ query2 = """UPDATE user_msgMESSAGE
+ SET status='%(new_status)s'
+ WHERE id_user_to=%(uid)i AND ("""
+
+ for msg_id in res_ids[0:-1]:
+ query2 += "id_msgMESSAGE=" + str(int(msg_id[0])) + " OR "
+
+ params2 = {'uid': int(uid),
+ 'new_status': new_status,
+ }
+ query2 += "id_msgMESSAGE=" + str(int(res_ids[-1][0])) + ")"
+ run_sql(query2%params2)
+
+ return out
+
+def get_nicknames_like(pattern):
+ """get nicknames like pattern"""
+ query = "SELECT nickname FROM user WHERE nickname RLIKE '%s'"
+ pattern = escape_string(pattern)
+ res = run_sql(query%pattern)
+ return res
+
+def get_groupnames_like(pattern):
+ """Get groupnames like pattern"""
+ query = "SELECT name FROM usergroup WHERE name RLIKE '%s'"
+ pattern = escape_string(pattern)
+ res = run_sql(query%pattern)
+ return res
+
+def get_element(sql_res):
+ """convert mySQL output
+ @param x: a tuple like this: (6789L,)
+ @return integer conversion of the number in tuple
+ """
+ return int(sql_res[0])
diff --git a/modules/webmessage/lib/webmessage_mailutils.py b/modules/webmessage/lib/webmessage_mailutils.py
new file mode 100644
index 000000000..71b5da8b9
--- /dev/null
+++ b/modules/webmessage/lib/webmessage_mailutils.py
@@ -0,0 +1,118 @@
+# -*- coding: utf-8 -*-
+## $Id$
+##
+## Some functions on html
+##
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+def email_quoted_txt2html(text,
+ tabs_before=0,
+ indent_txt='>>',
+ linebreak_txt="\n",
+ indent_html=('
', "
"),
+ linebreak_html=' '):
+ """
+ Takes a typical mail quoted text, e.g.:
+ hello,
+ you told me:
+ >> Your mother was a hamster and your father smelt of elderberries
+ I must tell you that I'm not convinced. Then in this discussion:
+ >>>> Is there someone else up there we could talk to?
+ >> No. Now, go away, or I shall taunt you a second time-a!
+ I think we're not going to be friends!
+ and return an html formatted output, e.g.:
+ hello,
+ you told me:
+
+ Your mother was a hamster and your father smelt of elderberries
+
+ I must tell you that I'm not convinced. Then in this discussion:
+
+
+ Is there someone else up there we could talk to?
+
+ No. Now, go away, or I shall taunt you a second time-a!
+
+ I think we're not going to be friends!
+
+ @param text: the text in quoted format
+ @param tabs_before: number of tabulations before each line
+ @param indent_str: quote separator in email (default:'>>')
+ @param linebreak_str: line separator in email (default: '\n')
+ @param indent_html: tuple of (opening, closing) html tags.
+ default: ('
', "
")
+ @param linebrak_html: line separator in html (default: ' ')
+ @return string containing html formatted output
+ """
+ final_body = ""
+ nb_indent = 0
+ lines = text.split(linebreak_txt)
+ for line in lines:
+ new_nb_indent = line.count(indent_txt)
+ if (new_nb_indent > nb_indent):
+ for _ in range(nb_indent, new_nb_indent):
+ final_body += tabs_before*"\t" + indent_html[0] + "\n"
+ tabs_before += 1
+ elif (new_nb_indent < nb_indent):
+ for _ in range(new_nb_indent, nb_indent):
+ tabs_before -= 1
+ final_body += (tabs_before)*"\t" + indent_html[1] + "\n"
+ final_body += tabs_before*"\t" + line.replace(indent_txt, '')
+ final_body += linebreak_html + "\n"
+ nb_indent = new_nb_indent
+ for _ in range(0, nb_indent):
+ tabs_before -= 1
+ final_body += (tabs_before)*"\t" + "\n"
+ return final_body
+
+
+def email_quote_txt(text,
+ indent_txt='>>',
+ linebreak_input="\n",
+ linebreak_output="\n"):
+ """
+ Takes a text and returns it in a typical mail quoted format, e.g.:
+ C'est un lapin, lapin de bois.
+ >>Quoi?
+ Un cadeau.
+ >>What?
+ A present.
+ >>Oh, un cadeau.
+ will return:
+ >>C'est un lapin, lapin de bois.
+ >>>>Quoi?
+ >>Un cadeau.
+ >>>>What?
+ >>A present.
+ >>>>Oh, un cadeau.
+ @param text: the string to quote
+ @param indent_txt: the string used for quoting (default: '>>')
+ @param linebreak_input: in the text param, string used for linebreaks
+ default: '\n'
+ @param linebreak_output: linebreak used for output
+ default: '\n'
+ @return the text as a quoted string
+ """
+ if (text == ""):
+ return ""
+ lines = text.split(linebreak_input)
+ text = ""
+ for line in lines:
+ text += indent_txt + line + linebreak_output
+ return text
diff --git a/modules/webmessage/lib/webmessage_templates.py b/modules/webmessage/lib/webmessage_templates.py
new file mode 100644
index 000000000..733397760
--- /dev/null
+++ b/modules/webmessage/lib/webmessage_templates.py
@@ -0,0 +1,614 @@
+# -*- coding: utf-8 -*-
+## $Id$
+##
+## handles rendering of webmessage module
+##
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+# CDS imports
+from cdsware.webmessage_mailutils import email_quoted_txt2html, email_quote_txt
+from cdsware.webmessage_config import cfg_webmessage_status_code, \
+ cfg_webmessage_separator, \
+ cfg_webmessage_max_nb_of_messages
+from cdsware.textutils import indent_text
+from cdsware.dateutils import date_convert_MySQL_to_text, \
+ create_day_selectbox, \
+ create_month_selectbox, \
+ create_year_inputbox
+from cdsware.config import weburl, cdslang
+from cdsware.messages import gettext_set_language
+
+
+class Template:
+ def tmpl_display_inbox(self, messages, infos=[], warnings=[], nb_messages=0, ln=cdslang):
+ """
+ Displays a list of messages, with the appropriate links and buttons
+ @param messages: a list of tuples:
+ [(message_id,
+ user_from_id,
+ user_from_nickname,
+ subject,
+ sent_date,
+ status=]
+ @param infos: a list of informations to print on top of page
+ @param ln: language of the page.
+ @return the list in HTML format
+ """
+ _ = gettext_set_language(ln)
+ junk = 0
+ inbox = self.tmpl_warning(warnings, ln)
+ inbox += self.tmpl_infobox(infos, ln)
+ inbox += self.tmpl_quota(nb_messages, ln)
+ inbox += """
+
""" % {'ln': ln,
+ 'write_label': _("New message"),
+ 'delete_all_label': _("Delete All")}
+ return indent_text(inbox, 2)
+
+ def tmpl_write(self,
+ msg_to="",
+ msg_to_group="",
+ msg_id=0,
+ msg_subject="",
+ msg_body="",
+ msg_send_year=0,
+ msg_send_month=0,
+ msg_send_day=0,
+ warnings=[],
+ users_to_add=[],
+ groups_to_add=[],
+ user_search_pattern="",
+ group_search_pattern="",
+ display_users_to_add=1,
+ ln=cdslang):
+ """
+ Displays a writing message form with optional prefilled fields
+ @param msg_to: nick of the user (prefills the To: field)
+ @param msg_subject: subject of the message (prefills the Subject: field)
+ @param msg_body: body of the message (prefills the Message: field)
+ @param msg_send_year: prefills to year field
+ @param msg_send_month: prefills the month field
+ @param msg_send_day: prefills the day field
+ @param warnings: display warnings on top of page
+ @param users_to_add: list to select users
+ @param groups_to_add: list to select groups
+ @param user_search_pattern: prefills this field!
+ @param group_search_pattern: idem
+ @param display_users_to_add: 1: display user search box, 0: group...
+ @param ln: language of the form
+ @return the form in HTML format
+ """
+
+ _ = gettext_set_language(ln)
+ write_box = self.tmpl_warning(warnings)
+
+ # escape forbidden character
+ msg_to = msg_to.replace('"', '"')
+ msg_to_group = msg_to_group.replace('"', '"')
+ msg_subject = msg_subject.replace('"', '"')
+ user_search_pattern = user_search_pattern.replace('"','"')
+ group_search_pattern = group_search_pattern.replace('"','"')
+
+ if display_users_to_add:
+ to_select = self.tmpl_user_or_group_search(users_to_add,
+ user_search_pattern,
+ 1,
+ ln)
+ else:
+ to_select = self.tmpl_user_or_group_search(groups_to_add,
+ group_search_pattern,
+ 0,
+ ln)
+ if (msg_id != 0):
+ msg_subject = _("Re: ") + msg_subject
+ msg_body = email_quote_txt(msg_body)
+ msg_body = msg_body.replace('>', '>')
+ write_box += """
+
+"""
+ write_box_part2 = indent_text(write_box_part2, 2)
+ write_box += "%(body)s" ""+ write_box_part2
+ day_field = create_day_selectbox('msg_send_day', msg_send_day, ln)
+ month_field = create_month_selectbox('msg_send_month', msg_send_month, ln)
+ year_field = create_year_inputbox('msg_send_year', msg_send_year)
+ write_box = write_box % {'to_users' : msg_to,
+ 'to_groups': msg_to_group,
+ 'subject' : msg_subject,
+ 'body' : msg_body,
+ 'ln': ln,
+ 'day_field': day_field,
+ 'month_field': month_field,
+ 'year_field': year_field,
+ 'to_select': to_select,
+ 'send_later_label': _("Send Later:"),
+ 'to_label': _("To:"),
+ 'users_label': _("Users"),
+ 'groups_label': _("Groups"),
+ 'subject_label': _("Subject:"),
+ 'message_label': _("Message:"),
+ 'send_label': _("SEND")}
+ return write_box
+
+ def tmpl_display_msg(self,
+ msg_id="",
+ msg_from_id="",
+ msg_from_nickname="",
+ msg_sent_to="",
+ msg_sent_to_group="",
+ msg_subject="",
+ msg_body="",
+ msg_sent_date="",
+ msg_received_date="0000-00-00 00:00:00",
+ ln=cdslang):
+ """
+ Displays a given message
+ @param msg_id: id of the message
+ @param msg_from_id: id of user who sent the message
+ @param msg_from_nickname: nickname of the user who sent the message
+ @param msg_sent_to: list of users who received the message
+ (comma separated string)
+ @param msg_sent_to_group: list of groups who received the message
+ (comma separated string)
+ @param msg_subject: subject of the message
+ @param msg_body: body of the message
+ @param msg_sent_date: date at which the message was sent
+ @param msg_received_date: date at which the message had to be received
+ (if this argument != 0000-00-00 => reminder
+ @param ln: language of the page
+ @return the message in HTML format
+ """
+
+ # load the right message language
+ _ = gettext_set_language(ln)
+
+ sent_to_link = ""
+ tos = msg_sent_to.split(cfg_webmessage_separator)
+ if (tos):
+ for to in tos[0:-1]:
+ sent_to_link += ''% (to, ln)
+ sent_to_link += '%s%s '% (to, cfg_webmessage_separator)
+ sent_to_link += '%s'% (tos[-1], ln, tos[-1])
+ group_to_link = ""
+ groups = msg_sent_to_group.split(cfg_webmessage_separator)
+ if (groups):
+ for group in groups[0:-1]:
+ group_to_link += ''% (group, ln)
+ group_to_link += '%s%s '% (group, cfg_webmessage_separator)
+ group_to_link += '%s'% (groups[-1], ln, groups[-1])
+ # format the msg so that the '>>' chars give vertical lines
+ final_body = email_quoted_txt2html(msg_body)
+
+ out = """
+
"""
+ if (msg_received_date != '0000-00-00 00:00:00'):
+ out += """
+
+
Received:
+
%(received_date)s
+
"""
+ out += """
+
+
CC:
+
%(sent_to)s
+
"""
+ if (msg_sent_to_group != ""):
+ out += """
+
+
Groups:
+
%(sent_to_group)s
+
"""
+ out += """
+
+
+
+
%(body)s
+
+
+
+
+
+
+
+
+
+
+
+
+
+ """
+ out = out % {'from' : msg_from_nickname,
+ 'sent_date' : date_convert_MySQL_to_text(msg_sent_date, ln),
+ 'received_date': date_convert_MySQL_to_text(msg_received_date, ln),
+ 'sent_to': sent_to_link,
+ 'sent_to_group': group_to_link,
+ 'subject' : msg_subject,
+ 'body' : final_body,
+ 'reply_to': msg_from_id,
+ 'msg_id': msg_id,
+ 'ln': ln,
+ 'reply_txt':_("REPLY"),
+ 'delete_txt': _("DELETE")}
+ return indent_text(out, 2)
+
+ def tmpl_navtrail(self, ln=cdslang, title=""):
+ """
+ display the navtrail, e.g.:
+ Your account > Your messages > title
+ @param title: the last part of the navtrail. Is not a link
+ @param ln: language
+ return html formatted navtrail
+ """
+ _ = gettext_set_language(ln)
+ nav_h1 = '%s'
+ nav_h2 = ""
+ if (title != ""):
+ nav_h2 = ' > %s'
+ nav_h2 = nav_h2 % (weburl, _("Your Messages"))
+
+ return nav_h1% (weburl,_("Your Account")) + nav_h2
+
+
+ def tmpl_confirm_delete(self, ln=cdslang):
+ """
+ display a confirm message
+ @param ln: language
+ @return html output
+ """
+ _ = gettext_set_language(ln)
+ out = """
+
+
+
+ %(message)s
+
+
+
+
+
+
+
+
+
+
+
"""% {'message': _("Are your sure you want to empty your whole mailbox?"),
+ 'ln':ln,
+ 'yes_label': _("Yes"),
+ 'no_label': _("No")}
+ return indent_text(out, 2)
+
+ def tmpl_infobox(self, infos, ln=cdslang):
+ """Display len(infos) information fields
+ @param infos: list of strings
+ @param ln=language
+ @return html output
+ """
+ _ = gettext_set_language(ln)
+ if not((type(infos) is list) or (type(infos) is tuple)):
+ infos = [infos]
+ infobox = ""
+ for info in infos:
+ infobox += "
"
+ lines = info.split("\n")
+ for line in lines[0:-1]:
+ infobox += line + " \n"
+ infobox += lines[-1] + "
\n"
+ return infobox
+
+
+ def tmpl_warning(self, warnings, ln=cdslang):
+ """
+ Display len(warnings) warning fields
+ @param infos: list of strings
+ @param ln=language
+ @return html output
+ """
+ if not((type(warnings) is list) or (type(warnings) is tuple)):
+ warnings = [warnings]
+ warningbox = ""
+ if warnings != []:
+ warningbox = "
\n Warning:\n"
+ for warning in warnings:
+ lines = warning.split("\n")
+ warningbox += "
"
+ for line in lines[0:-1]:
+ warningbox += line + " \n"
+ warningbox += lines[-1] + "
"
+ warningbox += "
\n"
+ return warningbox
+
+
+ def tmpl_quota(self, nb_messages=0, ln=cdslang):
+ """
+ Display a quota bar.
+ @nb_messages: number of messages in inbox.
+ @ln=language
+ @return html output
+ """
+ _ = gettext_set_language(ln)
+ quota = float(cfg_webmessage_max_nb_of_messages)
+ ratio = float(nb_messages) / quota
+ out = """
+%(quota_label)s
+
+
+
""" %{'quota_label' : _("Quota: %.1f%%")%(ratio * 100.0),
+ 'width' : int(ratio * 200)
+ }
+
+ return out
+
+
+ def tmpl_multiple_select(self, select_name, tuples_list, ln=cdslang):
+ """displays a multiple select environment
+ @param tuples_list: a list of (value, isSelected) tuples
+ @return HTML output
+ """
+ _ = gettext_set_language(ln)
+ if not((type(tuples_list) is list) or (type(tuples_list) is tuple)):
+ tuples_list = [tuples_list]
+ out = """
+\n"
+ return out
+
+
+ def tmpl_user_or_group_search(self,
+ tuples_list=[],
+ search_pattern="",
+ display_user=1,
+ ln=cdslang):
+ """
+ Display a box for user searching
+ @param tuples_list: list of (value, is_selected) tuples
+ @param search_pattern: text to display in this field
+ @param display_user: 1 for user 0 for group
+ @param ln: language
+ @return html output
+ """
+ _ = gettext_set_language(ln)
+ if display_user:
+ header = """
+
+
+"""
+ out = out% {'search_user_label' : _("Find a user"),
+ 'search_group_label' : _("Find a group"),
+ 'search_button_label': _("Search"),
+ 'search_field_name' : search_field_name,
+ 'search_pattern' : search_pattern,
+ 'search_button_name' : search_button_name,
+ 'multiple_select' : multiple_select,
+ 'add_button' : add_button}
+ return out
+
+ def tmpl_account_new_mail(self, nb_new_mail=0, ln=cdslang):
+ """
+ display infos about inbox (used by myaccount.py)
+ @param nb_new_mail: number of new mails
+ @param ln: language
+ retourn: html output.
+ """
+ _ = gettext_set_language(ln)
+ out = _("You got %i new messages. \n")% nb_new_mail
+ out += _("You can see all your messages in your inbox")% ln
+ return out
+
+
diff --git a/modules/webmessage/web/.cvsignore b/modules/webmessage/web/.cvsignore
new file mode 100644
index 000000000..df3ddb84d
--- /dev/null
+++ b/modules/webmessage/web/.cvsignore
@@ -0,0 +1,6 @@
+Makefile
+Makefile.in
+z_*
+*.O
+*.shtml
+*~
\ No newline at end of file
diff --git a/modules/webmessage/web/Makefile.am b/modules/webmessage/web/Makefile.am
new file mode 100644
index 000000000..c50fb0aec
--- /dev/null
+++ b/modules/webmessage/web/Makefile.am
@@ -0,0 +1,26 @@
+## $Id$
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+webappdir = $(WEBDIR)
+
+webapp_DATA = yourmessages.py
+
+EXTRA_DIST = $(webapp_DATA)
+
+CLEANFILES = *~ *.tmp
diff --git a/modules/webmessage/web/yourmessages.py b/modules/webmessage/web/yourmessages.py
new file mode 100644
index 000000000..9ab4a0c98
--- /dev/null
+++ b/modules/webmessage/web/yourmessages.py
@@ -0,0 +1,300 @@
+# -*- coding: utf-8 -*-
+## $Id$
+## Messaging system (internal)
+
+
+## This file is part of the CERN Document Server Software (CDSware).
+## Copyright (C) 2002, 2003, 2004, 2005 CERN.
+##
+## The CDSware 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.
+##
+## The CDSware 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 CDSware; if not, write to the Free Software Foundation, Inc.,
+## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+
+
+__lastupdated__ = """$Date$"""
+
+# external imports
+from mod_python import apache
+
+# CDSWare imports
+from cdsware.access_control_config import CFG_ACCESS_CONTROL_LEVEL_SITE
+from cdsware.config import weburl, cdslang
+from cdsware.webuser import getUid, isGuestUser, page_not_authorized
+from cdsware.webmessage import *
+from cdsware.webpage import page
+from cdsware.messages import wash_language, gettext_set_language
+
+
+
+from cdsware.webmessage_scalability_tests import my_tester
+
+
+### CALLABLE INTERFACE
+def index(req):
+ """ The function called by default
+ """
+ req.err_headers_out.add("Location", "%s/yourmessages.py/display?%s" % (weburl, req.args))
+ raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY
+
+
+def display(req, ln = cdslang):
+ """
+ Displays the Inbox of a given user
+ @param ln: language
+ @return the page for inbox
+ """
+ # Check if user is logged
+ uid = getUid(req)
+ if uid == -1 or isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1:
+ return page_not_authorized(req, "%s/yourmessages.py/display" % (weburl,))
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+
+ (body, errors, warnings) = perform_request_display(uid=uid,
+ ln=ln)
+
+ return page(title = _("Your Messages"),
+ body = body,
+ navtrail = get_navtrail(ln),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+
+
+
+def write(req, msg_reply_id="", msg_to="", msg_to_group="", mode_user=1, ln=cdslang):
+ """ write(): interface for message composing
+ @param msg_reply_id: if this message is a reply to another, id of the other
+ @param msg_to: if this message is not a reply, nickname of the user it must be
+ delivered to.
+ @param msg_to_group: name of group to send message to
+ @param ln: language
+ @return the compose page
+ """
+
+ # Check if user is logged
+ uid = getUid(req)
+
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1 or isGuestUser(uid):
+ return page_not_authorized(req, "%s/yourmessages.py/write" % (weburl,))
+
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+
+ # Request the composing page
+ (body, errors, warnings) = perform_request_write(uid=uid,
+ msg_reply_id=msg_reply_id,
+ msg_to=msg_to,
+ msg_to_group=msg_to_group,
+ ln=ln)
+ title = _("Write a message")
+
+ return page(title = title,
+ body = body,
+ navtrail = get_navtrail(ln, title),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+
+
+def send(req,
+ msg_to_user="",
+ msg_to_group="",
+ msg_subject="",
+ msg_body="",
+ msg_send_year="0000",
+ msg_send_month="00",
+ msg_send_day="00",
+ users_to_add=[],
+ groups_to_add=[],
+ user_search_pattern="",
+ group_search_pattern="",
+ send_button="",
+ switch_to_group_button="",
+ switch_to_user_button="",
+ search_user_button="",
+ search_group_button="",
+ add_to_group_button="",
+ add_to_user_button="",
+ ln=cdslang):
+ """
+ Sends the message
+ @param msg_to_user: comma separated usernames (str)
+ @param msg_to_group: comma separated groupnames (str)
+ @param msg_subject: message subject (str)
+ @param msg_bidy: message body (string)
+ @param msg_send_year: year to send this message on (int)
+ @param_msg_send_month: month to send this message on (int)
+ @param_msg_send_day: day to send this message on (int)
+ @param users_to_add: list of usernames ['str'] to add to msg_to_user
+ @param groups_to_add: list of groupnames ['str'] to add to msg_to_group
+ @param user_search_pattern: will search users with this pattern (str)
+ @param group_search_pattern: will search groups with this pattern (str)
+ @param mode_user: if 1 display user search box, else group search box
+ @param add_values: if 1 users_to_add will be added to msg_to_user field..
+ @param *button: which button was pressed
+ @param ln: language
+ @return a (body, errors, warnings) formed tuple.
+ """
+ # Check if user is logged
+ uid = getUid(req)
+ if uid == -1 or isGuestUser(uid) or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1:
+ return page_not_authorized(req, "%s/yourmessages.py/send" % (weburl,))
+
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+
+ if send_button:
+ (body, errors, warnings) = perform_request_send(uid,
+ msg_to_user,
+ msg_to_group,
+ msg_subject,
+ msg_body,
+ msg_send_year,
+ msg_send_month,
+ msg_send_day,
+ ln)
+ else:
+ mode_user = 1
+ add_values = 0
+ if switch_to_group_button or search_group_button or add_to_group_button:
+ mode_user = 0
+ if add_to_group_button or add_to_user_button:
+ add_values = 1
+ (body, errors, warnings) = perform_request_write_with_search(msg_to_user,
+ msg_to_group,
+ msg_subject,
+ msg_body,
+ msg_send_year,
+ msg_send_month,
+ msg_send_day,
+ users_to_add,
+ groups_to_add,
+ user_search_pattern,
+ group_search_pattern,
+ mode_user,
+ add_values,
+ ln=cdslang)
+ return page(title = _("Your Messages"),
+ body = body,
+ navtrail = get_navtrail(ln),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+
+
+def delete(req, msgid=-1, ln = cdslang):
+ """
+ Suppress a message
+ @param msgid: id of message
+ @param ln: language
+ @return page
+ """
+ # Check if user is logged
+ uid = getUid(req)
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1 or isGuestUser(uid):
+ return page_not_authorized(req, "%s/yourmessages.py/delete_msg" % (weburl,))
+
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+
+ # Generate content
+ (body, errors, warnings) = perform_request_delete_msg(uid, msgid, ln)
+ return page(title = _("Your Messages"),
+ body = body,
+ navtrail = get_navtrail(ln),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+
+
+def delete_all(req, confirmed=0, ln=cdslang):
+ """
+ Empty user's inbox
+ @param confimed: 1 if message is confirmed
+ @param ln: language
+ \return page
+ """
+ # Check if user is logged
+ uid = getUid(req)
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1 or isGuestUser(uid):
+ return page_not_authorized(req, "%s/yourmessages.py/delete_all" % (weburl,))
+
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+
+ # Generate content
+ (body, errors, warnings) = perform_request_delete_all(uid, confirmed, ln)
+ return page(title = _("Your Messages"),
+ body = body,
+ navtrail = get_navtrail(ln),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+
+
+def display_msg(req, msgid=-1, ln=cdslang):
+ """
+ Display a message
+ @param msgid: id of message
+ @param ln: languae
+ @return page
+ """
+ # Check if user is logged
+ uid = getUid(req)
+ if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1 or isGuestUser(uid):
+ return page_not_authorized(req, "%s/yourmessages.py/display_msg" % (weburl,))
+
+
+ # wash language argument
+ ln = wash_language(ln)
+ _ = gettext_set_language(ln)
+ # Generate content
+ (body, errors, warnings) = perform_request_display_msg(uid, msgid, ln)
+ title = _("Read a message")
+ return page(title = title,
+ body = body,
+ navtrail = get_navtrail(ln, title),
+ description = "",
+ keywords = "",
+ uid = uid,
+ lastupdated = __lastupdated__,
+ language = ln,
+ errors = errors,
+ warnings = warnings)
+