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 += """ + + + + + + + + + + """ %(_("Subject"), _("Sender"), _("Date")) + if len(messages) == 0: + inbox += """ + + + """ %(_("No new mail"),) + for (msgid, junk, user_from_nick, subject, sent_date, status) in messages: + subject_link = '%s'% (msgid, ln, subject) + from_link = '%s'% (user_from_nick, ln, user_from_nick) + action_link = '%s'% (msgid, ln, _("Delete")) + + s_date = date_convert_MySQL_to_text(sent_date, ln) + stat_style = '' + if (status == cfg_webmessage_status_code['NEW']): + stat_style = ' style="font-weight:bold"' + inbox += """ + + %s + + + + """ %(stat_style, subject_link, from_link, s_date, action_link) + inbox += """ + + + + + + + + + +
%s%s%s 
+ %s +
%s%s%s
+
+ +
+
+
+ +
+
""" % {'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 += """ +
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +""" + search_field_name = "user_search_pattern" + search_button_name = "search_user_button" + multiple_select = self.tmpl_multiple_select('users_to_add', tuples_list) + add_button = "" + add_button = add_button % _("Add to users") + else: + header = """ + + + + + + +""" + search_field_name = "group_search_pattern" + search_button_name = "search_group_button" + multiple_select = self.tmpl_multiple_select('groups_to_add', tuples_list) + add_button = "" + add_button = add_button % _("Add to groups") + + out = "
%(to_label)s%(users_label)s + +
 %(groups_label)s + +
   
%(subject_label)s + +
%(message_label)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 += """ + + + + """ + out += """ + + + + """ + if (msg_sent_to_group != ""): + out += """ + + + + """ + out += """ + + + + + + + + + + + + +
From:%(from)s
Subject:%(subject)s
Sent:%(sent_date)s
Received:%(received_date)s
CC:%(sent_to)s
Groups:%(sent_to_group)s
%(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 = """ +
+ %(search_user_label)s + + +
+ + + %(search_group_label)s +
\n" + header + out += """ + + + + + + + + + +
+ + + +
+ %(multiple_select)s + + %(add_button)s +
+""" + 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) +