diff --git a/modules/websubmit/lib/websubmit_engine.py b/modules/websubmit/lib/websubmit_engine.py index 15241cb21..d38a8a734 100644 --- a/modules/websubmit/lib/websubmit_engine.py +++ b/modules/websubmit/lib/websubmit_engine.py @@ -1,1497 +1,1499 @@ ## $Id$ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN. ## ## CDS Invenio 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. ## ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """WebSubmit: the mechanism for the submission of new records into CDS Invenio via a Web interface. """ __revision__ = "$Id$" ## import interesting modules: import string import os import sys import time import types import re import shutil from mod_python import apache from invenio.config import \ bibconvert, \ cdslang, \ cdsname, \ images, \ pylibdir, \ storage, \ urlpath, \ version, \ weburl from invenio.dbquery import run_sql, Error from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import acc_is_role from invenio.webpage import page, create_error_box from invenio.webuser import getUid, get_email, collect_user_info from invenio.websubmit_config import * from invenio.file import * from invenio.messages import gettext_set_language, wash_language from websubmit_dblayer import \ get_storage_directory_of_action, \ get_longname_of_doctype, \ get_longname_of_action, \ get_num_pages_of_submission, \ get_parameter_value_for_doctype, \ submission_exists_in_log, \ log_new_pending_submission, \ log_new_completed_submission, \ update_submission_modified_date_in_log, \ update_submission_reference_in_log, \ update_submission_reference_and_status_in_log, \ get_form_fields_on_submission_page, \ get_element_description, \ get_element_check_description, \ get_form_fields_not_on_submission_page, \ function_step_is_last, \ get_collection_children_of_submission_collection, \ get_submission_collection_name, \ get_doctype_children_of_submission_collection, \ get_categories_of_doctype, \ get_doctype_details, \ get_actions_on_submission_page_for_doctype, \ get_action_details, \ get_parameters_of_function, \ get_details_of_submission, \ get_functions_for_submission_step, \ get_submissions_at_level_X_with_score_above_N, \ submission_is_finished import invenio.template websubmit_templates = invenio.template.load('websubmit') def interface(req, c=cdsname, ln=cdslang, doctype="", act="", startPg=1, indir="", access="", mainmenu="", fromdir="", file="", nextPg="", nbPg="", curpage=1): """This function is called after a user has visited a document type's "homepage" and selected the type of "action" to perform. Having clicked an action-button (e.g. "Submit a New Record"), this function will be called . It performs the task of initialising a new submission session (retrieving information about the submission, creating a working submission-directory, etc), and "drawing" a submission page containing the WebSubmit form that the user uses to input the metadata to be submitted. When a user moves between pages in the submission interface, this function is recalled so that it can save the metadata entered into the previous page by the user, and draw the current submission-page. Note: During a submission, for each page refresh, this function will be called while the variable "step" (a form variable, seen by websubmit_webinterface, which calls this function) is 0 (ZERO). In other words, this function handles the FRONT-END phase of a submission, BEFORE the WebSubmit functions are called. @param req: (apache request object) *** NOTE: Added into this object, is a variable called "form" (req.form). This is added into the object in the index function of websubmit_webinterface. It contains a "mod_python.util.FieldStorage" instance, that contains the form-fields found on the previous submission page. @param c: (string), defaulted to cdsname. The name of the CDS Invenio installation. @param ln: (string), defaulted to cdslang. The language in which to display the pages. @param doctype: (string) - the doctype ID of the doctype for which the submission is being made. @param act: (string) - The ID of the action being performed (e.g. submission of bibliographic information; modification of bibliographic information, etc). @param startPg: (integer) - Starting page for the submission? Defaults to 1. @param indir: (string) - the directory used to store all submissions of the given "type" of this submission. For example, if the submission is of the type "modify bibliographic information", this variable would contain "modify". @param access: (string) - the "access" number for the submission (e.g. 1174062451_7010). This number is also used as the name for the current working submission directory. @param mainmenu: (string) - contains the URL (minus the CDS Invenio home stem) for the submission's home-page. (E.g. If this submission is "PICT", the "mainmenu" file would contain "/submit?doctype=PICT". @param fromdir: (integer) @param file: (string) @param nextPg: (string) @param nbPg: (string) @param curpage: (integer) - the current submission page number. Defaults to 1. """ ln = wash_language(ln) # load the right message language _ = gettext_set_language(ln) sys.stdout = req # get user ID: try: uid = getUid(req) uid_email = get_email(uid) except Error, e: return errorMsg(e, req, c, ln) # variable initialisation t = "" field = [] fieldhtml = [] level = [] fullDesc = [] text = [] check = [] select = [] radio = [] upload = [] txt = [] noPage = [] # Preliminary tasks # check that the user is logged in if uid_email == "" or uid_email == "guest": return warningMsg(websubmit_templates.tmpl_warning_message( ln = ln, msg = _("Sorry, you must log in to perform this action.") ), req, ln) # warningMsg("""<center><font color="red"></font></center>""",req, ln) # check we have minimum fields if "" in (doctype, act, access): ## We don't have all the necessary information to go ahead ## with this submission: return errorMsg(_("Invalid parameter"), req, c, ln) ## Before continuing to display the submission form interface, ## verify that this submission has not already been completed: if submission_is_finished(doctype, act, access, uid_email): ## This submission has already been completed. ## This situation can arise when, having completed a submission, ## the user uses the browser's back-button to go back to the form ## stage of the submission and then tries to submit once more. ## This is unsafe and should not be allowed. Instead of re-displaying ## the submission forms, display an error message to the user: wrnmsg = """<b>This submission has been completed. Please go to the""" \ """ <a href="/submit?doctype=%(doctype)s&ln=%(ln)s">""" \ """main menu</a> to start a new submission.</b>""" \ % { 'doctype' : doctype, 'ln' : ln } return warningMsg(wrnmsg, req) ## retrieve the action and doctype data: ## Concatenate action ID and doctype ID to make the submission ID: subname = "%s%s" % (act, doctype) if indir == "": ## Get the submission storage directory from the DB: submission_dir = get_storage_directory_of_action(act) if submission_dir not in ("", None): indir = submission_dir else: ## Unable to determine the submission-directory: return errorMsg(_("Unable to find the submission directory."), req, c, ln) ## get the document type's long-name: doctype_lname = get_longname_of_doctype(doctype) if doctype_lname is not None: ## Got the doctype long-name: replace spaces with HTML chars: docname = doctype_lname.replace(" ", " ") else: ## Unknown document type: return errorMsg(_("Unknown document type"), req, c, ln) ## get the action's long-name: action_lname = get_longname_of_action(act) if action_lname is not None: ## Got the action long-name: replace spaces with HTML chars: actname = action_lname.replace(" ", " ") else: ## Unknown action: return errorMsg(_("Unknown action"), req, c, ln) ## Get the number of pages for this submission: num_submission_pages = get_num_pages_of_submission(subname) if num_submission_pages is not None: nbpages = num_submission_pages else: ## Unable to determine the number of pages for this submission: return errorMsg(_("Unable to determine the number of submission pages."), req, c, ln) ## If unknown, get the current page of submission: if startPg != "" and curpage in ("", 0): curpage = startPg ## retrieve the name of the file in which the reference of ## the submitted document will be stored rn_filename = get_parameter_value_for_doctype(doctype, "edsrn") if rn_filename is not None: edsrn = rn_filename else: ## Unknown value for edsrn - set it to an empty string: edsrn = "" ## This defines the path to the directory containing the action data curdir = "%s/%s/%s/%s" % (storage, indir, doctype, access) ## if this submission comes from another one (fromdir is then set) ## We retrieve the previous submission directory and put it in the proper one if fromdir != "": olddir = "%s/%s/%s/%s" % (storage, fromdir, doctype, access) if os.path.exists(olddir): os.rename(olddir, curdir) ## If the submission directory still does not exist, we create it if not os.path.exists(curdir): try: os.makedirs(curdir) except: return errorMsg(_("Unable to create a directory for this submission."), req, c, ln) # retrieve the original main menu url and save it in the "mainmenu" file if mainmenu != "": fp = open("%s/mainmenu" % curdir, "w") fp.write(mainmenu) fp.close() # and if the file containing the URL to the main menu exists # we retrieve it and store it in the $mainmenu variable if os.path.exists("%s/mainmenu" % curdir): fp = open("%s/mainmenu" % curdir, "r"); mainmenu = fp.read() fp.close() else: mainmenu = "%s/submit" % (urlpath,) # various authentication related tasks... if uid_email != "guest" and uid_email != "": #First save the username (email address) in the SuE file. This way bibconvert will be able to use it if needed fp = open("%s/SuE" % curdir, "w") fp.write(uid_email) fp.close() # is user authorized to perform this action? (auth_code, auth_message) = acc_authorize_action(req, "submit", verbose=0, doctype=doctype, act=act) if acc_is_role("submit", doctype=doctype, act=act) and auth_code != 0: return warningMsg("""<center><font color="red">%s</font></center>""" % auth_message, req) ## update the "journal of submission": ## Does the submission already exist in the log? submission_exists = \ submission_exists_in_log(doctype, act, access, uid_email) if submission_exists == 1: ## update the modification-date of this submission in the log: update_submission_modified_date_in_log(doctype, act, access, uid_email) else: ## Submission doesn't exist in log - create it: log_new_pending_submission(doctype, act, access, uid_email) # Save the form fields entered in the previous submission page # If the form was sent with the GET method form = req.form value = "" # we parse all the form variables for key in form.keys(): formfields = form[key] if re.search("\[\]", key): filename = key.replace("[]", "") else: filename = key # the field is an array if isinstance(formfields, types.ListType): fp = open("%s/%s" % (curdir, filename), "w") for formfield in formfields: #stripslashes(value) value = specialchars(formfield) fp.write(value+"\n") fp.close() # the field is a normal string elif isinstance(formfields, types.StringTypes) and formfields != "": value = formfields fp = open("%s/%s" % (curdir, filename), "w") fp.write(specialchars(value)) fp.close() # the field is a file elif hasattr(formfields,"filename") and formfields.filename is not None: if not os.path.exists("%s/files/%s" % (curdir, key)): try: os.makedirs("%s/files/%s" % (curdir, key)) except: return errorMsg(_("Cannot create submission directory."), req, c, ln) filename = formfields.filename if filename != "": # This may be dangerous if the file size is bigger than the available memory data = formfields.file.read() fp = open("%s/files/%s/%s" % (curdir, key, filename), "w") fp.write(data) fp.close() fp = open("%s/lastuploadedfile" % curdir, "w") fp.write(filename) fp.close() fp = open("%s/%s" % (curdir, key), "w") fp.write(filename) fp.close() ## if the found field is the reference of the document, ## save this value in the "journal of submissions": if uid_email != "" and uid_email != "guest": if key == edsrn: update_submission_reference_in_log(doctype, access, uid_email, value) ## create the interface: subname = "%s%s" % (act, doctype) ## Get all of the form fields that appear on this page, ordered by fieldnum: form_fields = get_form_fields_on_submission_page(subname, curpage) full_fields = [] values = [] for field_instance in form_fields: full_field = {} ## Retrieve the field's description: element_descr = get_element_description(field_instance[3]) if element_descr is None: ## The form field doesn't seem to exist - return with error message: return \ errorMsg(_("Unknown form field found on submission page."), \ req, c, ln) if element_descr[8] is None: val = "" else: val = element_descr[8] ## we also retrieve and add the javascript code of the checking function, if needed ## Set it to empty string to begin with: full_field['javascript'] = '' if field_instance[7] != '': check_descr = get_element_check_description(field_instance[7]) if check_descr is not None: ## Retrieved the check description: full_field['javascript'] = check_descr full_field['type'] = element_descr[3] full_field['name'] = field_instance[3] full_field['rows'] = element_descr[5] full_field['cols'] = element_descr[6] full_field['val'] = val full_field['size'] = element_descr[4] full_field['maxlength'] = element_descr[7] full_field['htmlcode'] = element_descr[9] full_field['typename'] = field_instance[1] ## TODO: Investigate this, Not used? ## It also seems to refer to pagenum. # The 'R' fields must be executed in the engine's environment, # as the runtime functions access some global and local # variables. if full_field ['type'] == 'R': co = compile (full_field ['htmlcode'].replace("\r\n","\n"), "<string>", "exec") exec(co) else: text = websubmit_templates.tmpl_submit_field (ln = ln, field = full_field) # we now determine the exact type of the created field if full_field['type'] not in [ 'D','R']: field.append(full_field['name']) level.append(field_instance[5]) fullDesc.append(field_instance[4]) txt.append(field_instance[6]) check.append(field_instance[7]) # If the field is not user-defined, we try to determine its type # (select, radio, file upload...) # check whether it is a select field or not if re.search("SELECT", text, re.IGNORECASE) is not None: select.append(1) else: select.append(0) # checks whether it is a radio field or not if re.search(r"TYPE=[\"']?radio", text, re.IGNORECASE) is not None: radio.append(1) else: radio.append(0) # checks whether it is a file upload or not if re.search(r"TYPE=[\"']?file", text, re.IGNORECASE) is not None: upload.append(1) else: upload.append(0) # if the field description contains the "<COMBO>" string, replace # it by the category selected on the document page submission page combofile = "combo%s" % doctype if os.path.exists("%s/%s" % (curdir, combofile)): f = open("%s/%s" % (curdir, combofile), "r") combo = f.read() f.close() else: combo="" text = text.replace("<COMBO>", combo) # if there is a <YYYY> tag in it, replace it by the current year year = time.strftime("%Y"); text = text.replace("<YYYY>", year) # if there is a <TODAY> tag in it, replace it by the current year today = time.strftime("%d/%m/%Y"); text = text.replace("<TODAY>", today) fieldhtml.append(text) else: select.append(0) radio.append(0) upload.append(0) # field.append(value) - initial version, not working with JS, taking a submitted value field.append(field_instance[3]) level.append(field_instance[5]) txt.append(field_instance[6]) fullDesc.append(field_instance[4]) check.append(field_instance[7]) fieldhtml.append(text) full_field['fullDesc'] = field_instance[4] full_field['text'] = text # If a file exists with the name of the field we extract the saved value text = '' if os.path.exists("%s/%s" % (curdir, full_field['name'])): file = open("%s/%s" % (curdir, full_field['name']), "r"); text = file.read() text = re.compile("[\n\r]*$").sub("", text) text = re.compile("\n").sub("\\n", text) text = re.compile("\r").sub("", text) file.close() values.append(text) full_fields.append(full_field) returnto = {} if int(curpage) == int(nbpages): subname = "%s%s" % (act, doctype) other_form_fields = \ get_form_fields_not_on_submission_page(subname, curpage) nbFields = 0 message = "" fullcheck_select = [] fullcheck_radio = [] fullcheck_upload = [] fullcheck_field = [] fullcheck_level = [] fullcheck_txt = [] fullcheck_noPage = [] fullcheck_check = [] for field_instance in other_form_fields: if field_instance[5] == "M": ## If this field is mandatory, get its description: element_descr = get_element_description(field_instance[3]) if element_descr is None: ## The form field doesn't seem to exist - return with error message: return \ errorMsg(_("Unknown form field found on one of the submission pages."), \ req, c, ln) if element_descr[3] in ['D', 'R']: if element_descr[3] == "D": text = element_descr[9] else: text = eval(element_descr[9]) formfields = text.split(">") for formfield in formfields: match = re.match("name=([^ <>]+)", formfield, re.IGNORECASE) if match is not None: names = match.groups for value in names: if value != "": value = re.compile("[\"']+").sub("", value) fullcheck_field.append(value) fullcheck_level.append(field_instance[5]) fullcheck_txt.append(field_instance[6]) fullcheck_noPage.append(field_instance[1]) fullcheck_check.append(field_instance[7]) nbFields = nbFields + 1 else: fullcheck_noPage.append(field_instance[1]) fullcheck_field.append(field_instance[3]) fullcheck_level.append(field_instance[5]) fullcheck_txt.append(field_instance[6]) fullcheck_check.append(field_instance[7]) nbFields = nbFields+1 # tests each mandatory field fld = 0 res = 1 for i in range (0, nbFields): res = 1 if not os.path.exists("%s/%s" % (curdir, fullcheck_field[i])): res=0 else: file = open("%s/%s" % (curdir, fullcheck_field[i]), "r") text = file.read() if text == '': res=0 else: if text == "Select:": res=0 if res == 0: fld = i break if not res: returnto = { 'field' : fullcheck_txt[fld], 'page' : fullcheck_noPage[fld], } t += websubmit_templates.tmpl_page_interface( ln = ln, docname = docname, actname = actname, curpage = curpage, nbpages = nbpages, file = file, nextPg = nextPg, access = access, nbPg = nbPg, doctype = doctype, act = act, indir = indir, fields = full_fields, javascript = websubmit_templates.tmpl_page_interface_js( ln = ln, upload = upload, field = field, fieldhtml = fieldhtml, txt = txt, check = check, level = level, curdir = curdir, values = values, select = select, radio = radio, curpage = curpage, nbpages = nbpages, images = images, returnto = returnto, ), images = images, mainmenu = mainmenu, ) # start display: req.content_type = "text/html" req.send_http_header() p_navtrail = """<a href="/submit">%(submit)s</a> > <a href="/submit?doctype=%(doctype)s\">%(docname)s</a> """ % { 'submit' : _("Submit"), 'doctype' : doctype, 'docname' : docname, } return page(title= actname, body = t, navtrail = p_navtrail, description = "submit documents", keywords = "submit", uid = uid, language = ln, req = req, navmenuid='submit') def endaction(req, c=cdsname, ln=cdslang, doctype="", act="", startPg=1, indir="", access="", mainmenu="", fromdir="", file="", nextPg="", nbPg="", curpage=1, step=1, mode="U"): """Having filled-in the WebSubmit form created for metadata by the interface function, the user clicks a button to either "finish the submission" or to "proceed" to the next stage of the submission. At this point, a variable called "step" will be given a value of 1 or above, which means that this function is called by websubmit_webinterface. So, during all non-zero steps of the submission, this function is called. In other words, this function is called during the BACK-END phase of a submission, in which WebSubmit *functions* are being called. The function first ensures that all of the WebSubmit form field values have been saved in the current working submission directory, in text- files with the same name as the field elements have. It then determines the functions to be called for the given step of the submission, and executes them. Following this, if this is the last step of the submission, it logs the submission as "finished" in the journal of submissions. @param req: (apache request object) *** NOTE: Added into this object, is a variable called "form" (req.form). This is added into the object in the index function of websubmit_webinterface. It contains a "mod_python.util.FieldStorage" instance, that contains the form-fields found on the previous submission page. @param c: (string), defaulted to cdsname. The name of the CDS Invenio installation. @param ln: (string), defaulted to cdslang. The language in which to display the pages. @param doctype: (string) - the doctype ID of the doctype for which the submission is being made. @param act: (string) - The ID of the action being performed (e.g. submission of bibliographic information; modification of bibliographic information, etc). @param startPg: (integer) - Starting page for the submission? Defaults to 1. @param indir: (string) - the directory used to store all submissions of the given "type" of this submission. For example, if the submission is of the type "modify bibliographic information", this variable would contain "modify". @param access: (string) - the "access" number for the submission (e.g. 1174062451_7010). This number is also used as the name for the current working submission directory. @param mainmenu: (string) - contains the URL (minus the CDS Invenio home stem) for the submission's home-page. (E.g. If this submission is "PICT", the "mainmenu" file would contain "/submit?doctype=PICT". @param fromdir: @param file: @param nextPg: @param nbPg: @param curpage: (integer) - the current submission page number. Defaults to 1. @param step: (integer) - the current step of the submission. Defaults to 1. @param mode: """ global rn, sysno, dismode, curdir, uid, uid_email, last_step, action_score # load the right message language _ = gettext_set_language(ln) try: rn except NameError: rn = "" dismode = mode ln = wash_language(ln) sys.stdout = req t = "" # get user ID: try: uid = getUid(req) uid_email = get_email(uid) except Error, e: return errorMsg(e, req, c, ln) # Preliminary tasks # check that the user is logged in if uid_email == "" or uid_email == "guest": return warningMsg(websubmit_templates.tmpl_warning_message( ln = ln, msg = _("Sorry, you must log in to perform this action.") ), req, ln) ## check we have minimum fields if "" in (doctype, act, access): ## We don't have all the necessary information to go ahead ## with this submission: return errorMsg(_("Invalid parameter"), req, c, ln) ## Before continuing to process the submitted data, verify that ## this submission has not already been completed: if submission_is_finished(doctype, act, access, uid_email): ## This submission has already been completed. ## This situation can arise when, having completed a submission, ## the user uses the browser's back-button to go back to the form ## stage of the submission and then tries to submit once more. ## This is unsafe and should not be allowed. Instead of re-processing ## the submitted data, display an error message to the user: wrnmsg = """<b>This submission has been completed. Please go to the""" \ """ <a href="/submit?doctype=%(doctype)s&ln=%(ln)s">""" \ """main menu</a> to start a new submission.</b>""" \ % { 'doctype' : doctype, 'ln' : ln } return warningMsg(wrnmsg, req) ## retrieve the action and doctype data if indir == "": ## Get the submission storage directory from the DB: submission_dir = get_storage_directory_of_action(act) if submission_dir not in ("", None): indir = submission_dir else: ## Unable to determine the submission-directory: return errorMsg(_("Unable to find the submission directory."), \ req, c, ln) # The following words are reserved and should not be used as field names reserved_words = ["stop", "file", "nextPg", "startPg", "access", "curpage", "nbPg", "act", \ "indir", "doctype", "mode", "step", "deleted", "file_path", "userfile_name"] # This defines the path to the directory containing the action data curdir = "%s/%s/%s/%s" % (storage, indir, doctype, access) # If the submission directory still does not exist, we create it if not os.path.exists(curdir): try: os.makedirs(curdir) except: return errorMsg(_("Cannot create submission directory."), req, c, ln) # retrieve the original main menu url ans save it in the "mainmenu" file if mainmenu != "": fp = open("%s/mainmenu" % curdir, "w") fp.write(mainmenu) fp.close() # and if the file containing the URL to the main menu exists # we retrieve it and store it in the $mainmenu variable if os.path.exists("%s/mainmenu" % curdir): fp = open("%s/mainmenu" % curdir, "r"); mainmenu = fp.read() fp.close() else: mainmenu = "%s/submit" % (urlpath,) ## retrieve the name of the file in which the reference of ## the submitted document will be stored rn_filename = get_parameter_value_for_doctype(doctype, "edsrn") if rn_filename is not None: edsrn = rn_filename else: ## Unknown value for edsrn - set it to an empty string: edsrn = "" ## Determine whether the action is finished ## (ie there are no other steps after the current one): finished = function_step_is_last(doctype, act, step) # Save the form fields entered in the previous submission page # If the form was sent with the GET method form = req.form value = "" # we parse all the form variables for key in form.keys(): formfields = form[key] if re.search("\[\]", key): filename = key.replace("[]", "") else: filename = key # the field is an array if isinstance(formfields,types.ListType): fp = open("%s/%s" % (curdir, filename), "w") for formfield in formfields: #stripslashes(value) value = specialchars(formfield) fp.write(value+"\n") fp.close() # the field is a normal string elif isinstance(formfields, types.StringTypes) and formfields != "": value = formfields fp = open("%s/%s" % (curdir, filename), "w") fp.write(specialchars(value)) fp.close() # the field is a file elif hasattr(formfields, "filename") and formfields.filename is not None: if not os.path.exists("%s/files/%s" % (curdir, key)): try: os.makedirs("%s/files/%s" % (curdir, key)) except: return errorMsg("can't create submission directory", req, cdsname, ln) filename = formfields.filename if filename != "": # This may be dangerous if the file size is bigger than the available memory data = formfields.file.read() fp = open("%s/files/%s/%s" % (curdir, key, filename), "w") fp.write(data) fp.close() fp = open("%s/lastuploadedfile" % curdir, "w") fp.write(filename) fp.close() fp = open("%s/%s" % (curdir, key), "w") fp.write(filename) fp.close() ## if the found field is the reference of the document ## we save this value in the "journal of submissions" if uid_email != "" and uid_email != "guest": if key == edsrn: update_submission_reference_in_log(doctype, access, uid_email, value) ## get the document type's long-name: doctype_lname = get_longname_of_doctype(doctype) if doctype_lname is not None: ## Got the doctype long-name: replace spaces with HTML chars: docname = doctype_lname.replace(" ", " ") else: ## Unknown document type: return errorMsg(_("Unknown document type"), req, c, ln) ## get the action's long-name: action_lname = get_longname_of_action(act) if action_lname is not None: ## Got the action long-name: replace spaces with HTML chars: actname = action_lname.replace(" ", " ") else: ## Unknown action: return errorMsg(_("Unknown action"), req, c, ln) ## Get the number of pages for this submission: subname = "%s%s" % (act, doctype) num_submission_pages = get_num_pages_of_submission(subname) if num_submission_pages is not None: nbpages = num_submission_pages else: ## Unable to determine the number of pages for this submission: return errorMsg(_("Unable to determine the number of submission pages."), \ req, cdsname, ln) ## Determine whether the action is finished ## (ie there are no other steps after the current one): last_step = function_step_is_last(doctype, act, step) next_action = '' ## The next action to be proposed to the user # Prints the action details, returning the mandatory score action_score = action_details(doctype, act) current_level = get_level(doctype, act) # Calls all the function's actions function_content = '' try: ## Handle the execution of the functions for this ## submission/step: start_time = time.time() function_content = print_function_calls(req=req, doctype=doctype, action=act, step=step, form=form, start_time=start_time, ln=ln) except InvenioWebSubmitFunctionError, e: ## There was a serious function-error. Execution ends. return errorMsg(e.value, req, c, ln) except InvenioWebSubmitFunctionStop, e: ## For one reason or another, one of the functions has determined that ## the data-processing phase (i.e. the functions execution) should be ## halted and the user should be returned to the form interface once ## more. (NOTE: Redirecting the user to the Web-form interface is ## currently done using JavaScript. The "InvenioWebSubmitFunctionStop" ## exception contains a "value" string, which is effectively JavaScript ## - probably an alert box and a form that is submitted). **THIS WILL ## CHANGE IN THE FUTURE WHEN JavaScript IS REMOVED!** if e.value is not None: function_content = e.value else: function_content = e else: ## No function exceptions (InvenioWebSubmitFunctionStop, ## InvenioWebSubmitFunctionError) were raised by the functions. Propose ## the next action (if applicable), and log the submission as finished: ## If the action was mandatory we propose the next ## mandatory action (if any) if action_score != -1 and last_step == 1: next_action = Propose_Next_Action(doctype, \ action_score, \ access, \ current_level, \ indir) ## If we are in the last step of an action, we can update ## the "journal of submissions" if last_step == 1: if uid_email != "" and uid_email != "guest" and rn != "": ## update the "journal of submission": ## Does the submission already exist in the log? submission_exists = \ submission_exists_in_log(doctype, act, access, uid_email) if submission_exists == 1: ## update the rn and status to finished for this submission ## in the log: update_submission_reference_and_status_in_log(doctype, \ act, \ access, \ uid_email, \ rn, \ "finished") else: ## Submission doesn't exist in log - create it: log_new_completed_submission(doctype, \ act, \ access, \ uid_email, \ rn) ## Having executed the functions, create the page that will be displayed ## to the user: t = websubmit_templates.tmpl_page_endaction( ln = ln, weburl = weburl, # these fields are necessary for the navigation file = file, nextPg = nextPg, startPg = startPg, access = access, curpage = curpage, nbPg = nbPg, nbpages = nbpages, doctype = doctype, act = act, docname = docname, actname = actname, indir = indir, mainmenu = mainmenu, finished = finished, images = images, function_content = function_content, next_action = next_action, ) # start display: req.content_type = "text/html" req.send_http_header() p_navtrail = """<a href="/submit">""" + _("Submit") +\ """</a> > <a href="/submit?doctype=%(doctype)s">%(docname)s</a>""" % { 'doctype' : doctype, 'docname' : docname, } return page(title= actname, body = t, navtrail = p_navtrail, description="submit documents", keywords="submit", uid = uid, language = ln, req = req, navmenuid='submit') def home(req, c=cdsname, ln=cdslang): """This function generates the WebSubmit "home page". Basically, this page contains a list of submission-collections in WebSubmit, and gives links to the various document-type submissions. Document-types only appear on this page when they have been connected to a submission-collection in WebSubmit. @param req: (apache request object) @param c: (string) - defaults to cdsname @param ln: (string) - The CDS Invenio interface language of choice. Defaults to cdslang (the default language of the installation). @return: (string) - the Web page to be displayed. """ ln = wash_language(ln) # get user ID: try: uid = getUid(req) except Error, e: return errorMsg(e, req, c, ln) # start display: req.content_type = "text/html" req.send_http_header() # load the right message language _ = gettext_set_language(ln) finaltext = websubmit_templates.tmpl_submit_home_page( ln = ln, catalogues = makeCataloguesTable(ln) ) return page(title=_("Submit"), body=finaltext, navtrail=[], description="submit documents", keywords="submit", uid=uid, language=ln, req=req, navmenuid='submit' ) def makeCataloguesTable(ln=cdslang): """Build the 'catalogues' (submission-collections) tree for the WebSubmit home-page. This tree contains the links to the various document types in WebSubmit. @param ln: (string) - the language of the interface. (defaults to 'cdslang'). @return: (string) - the submission-collections tree. """ text = "" catalogues = [] ## Get the submission-collections attached at the top level ## of the submission-collection tree: top_level_collctns = get_collection_children_of_submission_collection(0) if len(top_level_collctns) != 0: ## There are submission-collections attatched to the top level. ## retrieve their details for displaying: for child_collctn in top_level_collctns: catalogues.append(getCatalogueBranch(child_collctn[0], 1)) text = websubmit_templates.tmpl_submit_home_catalogs( ln=ln, catalogs=catalogues ) else: text = websubmit_templates.tmpl_submit_home_catalog_no_content(ln=ln) return text def getCatalogueBranch(id_father, level): """Build up a given branch of the submission-collection tree. I.e. given a parent submission-collection ID, build up the tree below it. This tree will include doctype-children, as well as other submission- collections and their children. Finally, return the branch as a dictionary. @param id_father: (integer) - the ID of the submission-collection from which to begin building the branch. @param level: (integer) - the level of the current submission- collection branch. @return: (dictionary) - the branch and its sub-branches. """ elem = {} ## The dictionary to contain this branch of the tree. ## First, get the submission-collection-details: collctn_name = get_submission_collection_name(id_father) if collctn_name is not None: ## Got the submission-collection's name: elem['name'] = collctn_name else: ## The submission-collection is unknown to the DB ## set its name as empty: elem['name'] = "" elem['id'] = id_father elem['level'] = level ## Now get details of the doctype-children of this ## submission-collection: elem['docs'] = [] ## List to hold the doctype-children ## of the submission-collection doctype_children = \ get_doctype_children_of_submission_collection(id_father) for child_doctype in doctype_children: elem['docs'].append(getDoctypeBranch(child_doctype[0])) ## Now, get the collection-children of this submission-collection: elem['sons'] = [] collctn_children = \ get_collection_children_of_submission_collection(id_father) for child_collctn in collctn_children: elem['sons'].append(getCatalogueBranch(child_collctn[0], level + 1)) ## Now return this branch of the built-up 'collection-tree': return elem def getDoctypeBranch(doctype): """Create a document-type 'leaf-node' for the submission-collections tree. Basically, this leaf is a dictionary containing the name and ID of the document-type submission to which it links. @param doctype: (string) - the ID of the document type. @return: (dictionary) - the document-type 'leaf node'. Contains the following values: + id: (string) - the document-type ID. + name: (string) - the (long) name of the document-type. """ ldocname = get_longname_of_doctype(doctype) if ldocname is None: ldocname = "Unknown Document Type" return { 'id' : doctype, 'name' : ldocname, } def displayCatalogueBranch(id_father, level, catalogues): text = "" collctn_name = get_submission_collection_name(id_father) if collctn_name is None: ## If this submission-collection wasn't known in the DB, ## give it the name "Unknown Submission-Collection" to ## avoid errors: collctn_name = "Unknown Submission-Collection" ## Now, create the display for this submission-collection: if level == 1: text = "<LI><font size=\"+1\"><strong>%s</strong></font>\n" \ % collctn_name else: ## TODO: These are the same (and the if is ugly.) Why? if level == 2: text = "<LI>%s\n" % collctn_name else: if level > 2: text = "<LI>%s\n" % collctn_name ## Now display the children document-types that are attached ## to this submission-collection: ## First, get the children: doctype_children = get_doctype_children_of_submission_collection(id_father) collctn_children = get_collection_children_of_submission_collection(id_father) if len(doctype_children) > 0 or len(collctn_children) > 0: ## There is something to display, so open a list: text = text + "<UL>\n" ## First, add the doctype leaves of this branch: for child_doctype in doctype_children: ## Add the doctype 'leaf-node': text = text + displayDoctypeBranch(child_doctype[0], catalogues) ## Now add the submission-collection sub-branches: for child_collctn in collctn_children: catalogues.append(child_collctn[0]) text = text + displayCatalogueBranch(child_collctn[0], level+1, catalogues) ## Finally, close up the list if there were nodes to display ## at this branch: if len(doctype_children) > 0 or len(collctn_children) > 0: text = text + "</UL>\n" return text def displayDoctypeBranch(doctype, catalogues): text = "" ldocname = get_longname_of_doctype(doctype) if ldocname is None: ldocname = "Unknown Document Type" text = "<LI><a href=\"\" onmouseover=\"javascript:" \ "popUpTextWindow('%s',true,event);\" onmouseout" \ "=\"javascript:popUpTextWindow('%s',false,event);\" " \ "onClick=\"document.forms[0].doctype.value='%s';" \ "document.forms[0].submit();return false;\">%s</a>\n" \ % (doctype, doctype, doctype, ldocname) return text def action(req, c=cdsname, ln=cdslang, doctype=""): # load the right message language _ = gettext_set_language(ln) nbCateg = 0 snameCateg = [] lnameCateg = [] actionShortDesc = [] indir = [] actionbutton = [] statustext = [] t = "" ln = wash_language(ln) # get user ID: try: uid = getUid(req) uid_email = get_email(uid) except Error, e: return errorMsg(e, req, c, ln) #parses database to get all data ## first, get the list of categories doctype_categs = get_categories_of_doctype(doctype) for doctype_categ in doctype_categs: nbCateg = nbCateg+1 snameCateg.append(doctype_categ[0]) lnameCateg.append(doctype_categ[1]) ## Now get the details of the document type: doctype_details = get_doctype_details(doctype) if doctype_details is None: ## Doctype doesn't exist - raise error: return errorMsg (_("Unable to find document type.") + str(doctype), req) else: docFullDesc = doctype_details[0] docShortDesc = doctype_details[1] description = doctype_details[4] ## Get the details of the actions supported by this document-type: doctype_actions = get_actions_on_submission_page_for_doctype(doctype) for doctype_action in doctype_actions: ## Get the details of this action: action_details = get_action_details(doctype_action[0]) if action_details is not None: actionShortDesc.append(doctype_action[0]) indir.append(action_details[1]) actionbutton.append(action_details[4]) statustext.append(action_details[5]) ## Send the gathered information to the template so that the doctype's ## home-page can be displayed: t = websubmit_templates.tmpl_action_page( ln=ln, uid=uid, guest=(uid_email == "" or uid_email == "guest"), pid = os.getpid(), now = time.time(), doctype = doctype, description = description, docfulldesc = docFullDesc, snameCateg = snameCateg, lnameCateg = lnameCateg, actionShortDesc = actionShortDesc, indir = indir, # actionbutton = actionbutton, statustext = statustext, ) p_navtrail = """<a href="/submit">%(submit)s</a>""" % {'submit' : _("Submit")} return page(title = docFullDesc, body=t, navtrail=p_navtrail, description="submit documents", keywords="submit", uid=uid, language=ln, req=req, navmenuid='submit' ) def Request_Print(m, txt): """The argumemts to this function are the display mode (m) and the text to be displayed (txt). If the argument mode is 'ALL' then the text is unconditionally echoed m can also take values S (Supervisor Mode) and U (User Mode). In these circumstances txt is only echoed if the argument mode is the same as the current mode """ global dismode if m == "A" or m == dismode: return txt else: return "" def Evaluate_Parameter (field, doctype): # Returns the literal value of the parameter. Assumes that the value is # uniquely determined by the doctype, i.e. doctype is the primary key in # the table # If the table name is not null, evaluate the parameter ## TODO: The above comment looks like nonesense? This ## function only seems to get the values of parameters ## from the db... ## Get the value for the parameter: param_val = get_parameter_value_for_doctype(doctype, field) if param_val is None: ## Couldn't find a value for this parameter for this doctype. ## Instead, try with the default doctype (DEF): param_val = get_parameter_value_for_doctype("DEF", field) if param_val is None: ## There was no value for the parameter for the default doctype. ## Nothing can be done about it - return an empty string: return "" else: ## There was some kind of value for the parameter; return it: return param_val def Get_Parameters (function, doctype): """For a given function of a given document type, a dictionary of the parameter names and values are returned. @param function: (string) - the name of the function for which the parameters are to be retrieved. @param doctype: (string) - the ID of the document type. @return: (dictionary) - of the parameters of the function. Keyed by the parameter name, values are of course the parameter values. """ parray = {} ## Get the names of the parameters expected by this function: func_params = get_parameters_of_function(function) for func_param in func_params: ## For each of the parameters, get its value for this document- ## type and add it into the dictionary of parameters: parameter = func_param[0] parray[parameter] = Evaluate_Parameter (parameter, doctype) return parray def get_level(doctype, action): """Get the level of a given submission. If unknown, return 0 as the level. @param doctype: (string) - the ID of the document type. @param action: (string) - the ID of the action. @return: (integer) - the level of the submission; 0 otherwise. """ subm_details = get_details_of_submission(doctype, action) if subm_details is not None: ## Return the level of this action subm_level = subm_details[9] try: int(subm_level) except ValueError: return 0 else: return subm_level else: return 0 def action_details (doctype, action): # Prints whether the action is mandatory or optional. The score of the # action is returned (-1 if the action was optional) subm_details = get_details_of_submission(doctype, action) if subm_details is not None: if subm_details[9] != "0": ## This action is mandatory; return the score: return subm_details[10] else: return -1 else: return -1 def print_function_calls (req, doctype, action, step, form, start_time, ln=cdslang): # Calls the functions required by an "action" action on a "doctype" document # In supervisor mode, a table of the function calls is produced global htdocsdir,storage,access,pylibdir,dismode,user_info user_info = collect_user_info(req) # load the right message language _ = gettext_set_language(ln) t = "" ## Get the list of functions to be called funcs_to_call = get_functions_for_submission_step(doctype, action, step) ## If no functions are found at this step for this doctype, ## get the functions for the DEF(ault) doctype: if len(funcs_to_call) == 0: funcs_to_call = get_functions_for_submission_step("DEF", action, step) if len(funcs_to_call) > 0: # while there are functions left... functions = [] for function in funcs_to_call: function_name = function[0] function_score = function[1] currfunction = { 'name' : function_name, 'score' : function_score, 'error' : 0, 'text' : '', } if os.path.exists("%s/invenio/websubmit_functions/%s.py" % (pylibdir, function_name)): # import the function itself #function = getattr(invenio.websubmit_functions, function_name) execfile("%s/invenio/websubmit_functions/%s.py" % (pylibdir, function_name), globals()) if not globals().has_key(function_name): currfunction['error'] = 1 else: function = globals()[function_name] # Evaluate the parameters, and place them in an array parameters = Get_Parameters(function_name, doctype) # Call function: log_function(curdir, "Start %s" % function_name, start_time) try: func_returnval = function(parameters, curdir, form) except InvenioWebSubmitFunctionWarning, err: ## There was an unexpected behaviour during the execution. ## Log the message into function's log and go to next function log_function(curdir, "***Warning*** from %s: %s" % (function_name, str(err)), start_time) log_function(curdir, "End %s" % function_name, start_time) if func_returnval is not None: ## Append the returned value as a string: currfunction['text'] = str(func_returnval) else: ## The function the NoneType. Don't keep that value as ## the currfunction->text. Replace it with the empty ## string. currfunction['text'] = "" else: currfunction['error'] = 1 functions.append(currfunction) t = websubmit_templates.tmpl_function_output( ln = ln, display_on = (dismode == 'S'), action = action, doctype = doctype, step = step, functions = functions, ) else : if dismode == 'S': t = "<br /><br /><b>" + _("The chosen action is not supported by the document type.") + "</b>" return t def Propose_Next_Action (doctype, action_score, access, currentlevel, indir, ln=cdslang): global machine, storage, act, rn t = "" next_submissions = \ get_submissions_at_level_X_with_score_above_N(doctype, currentlevel, action_score) if len(next_submissions) > 0: actions = [] first_score = next_submissions[0][10] for action in next_submissions: if action[10] == first_score: ## Get the submission directory of this action: nextdir = get_storage_directory_of_action(action[1]) if nextdir is None: nextdir = "" curraction = { 'page' : action[11], 'action' : action[1], 'doctype' : doctype, 'nextdir' : nextdir, 'access' : access, 'indir' : indir, 'name' : action[12], } actions.append(curraction) t = websubmit_templates.tmpl_next_action( ln = ln, actions = actions, ) return t def errorMsg(title, req, c=cdsname, ln=cdslang): # load the right message language _ = gettext_set_language(ln) return page(title = _("Error"), body = create_error_box(req, title=title, verbose=0, ln=ln), description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='submit') def warningMsg(title, req, c=cdsname, ln=cdslang): # load the right message language _ = gettext_set_language(ln) return page(title = _("Warning"), body = title, description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='submit') def specialchars(text): text = string.replace(text, "“", "\042"); text = string.replace(text, "”", "\042"); text = string.replace(text, "’", "\047"); text = string.replace(text, "—", "\055"); text = string.replace(text, "…", "\056\056\056"); return text def log_function(curdir, message, start_time, filename="function_log"): """Write into file the message and the difference of time between starttime and current time @param curdir:(string) path to the destination dir @param message: (string) message to write into the file @param starttime: (float) time to compute from @param filname: (string) name of log file """ time_lap = "%.3f" % (time.time() - start_time) if os.access(curdir, os.F_OK|os.W_OK): fd = open("%s/%s" % (curdir, filename), "a+") fd.write("""%s --- %s\n""" % (message, time_lap)) fd.close() diff --git a/modules/websubmit/lib/websubmit_webinterface.py b/modules/websubmit/lib/websubmit_webinterface.py index e8b29b776..b07a975f8 100644 --- a/modules/websubmit/lib/websubmit_webinterface.py +++ b/modules/websubmit/lib/websubmit_webinterface.py @@ -1,481 +1,483 @@ ## $Id$ ## ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN. ## ## CDS Invenio 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. ## ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. __lastupdated__ = """$Date$""" __revision__ = "$Id$" import string import os import time import types import re from mod_python import apache import sys from urllib import quote from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ cdslang, \ cdsname, \ images, \ storage, \ urlpath, \ version, \ weburl from invenio.dbquery import run_sql, Error from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import acc_is_role from invenio.webpage import page, create_error_box, pageheaderonly, pagefooteronly from invenio.webuser import getUid, get_email, page_not_authorized from invenio.websubmit_config import * from invenio.file import * from invenio.webinterface_handler import wash_urlargd, WebInterfaceDirectory from invenio.urlutils import make_canonical_urlargd, redirect_to_url from invenio.messages import gettext_set_language from invenio.search_engine import \ guess_primary_collection_of_a_record, \ get_colID, \ create_navtrail_links import invenio.template websubmit_templates = invenio.template.load('websubmit') from invenio.websearchadminlib import get_detailed_page_tabs import invenio.template webstyle_templates = invenio.template.load('webstyle') websearch_templates = invenio.template.load('websearch') class WebInterfaceFilesPages(WebInterfaceDirectory): def __init__(self,recid): self.recid = recid def _lookup(self, component, path): # after /record/<recid>/files/ every part is used as the file # name (with possible path in the case of archives to be # uncompressed) filename = component def getfile(req, form): args = wash_urlargd(form, websubmit_templates.files_default_urlargd) ln = args['ln'] _ = gettext_set_language(ln) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE > 1: return page_not_authorized(req, "../getfile.py/index", navmenuid='submit') uid_email = get_email(uid) readonly = CFG_ACCESS_CONTROL_LEVEL_SITE == 1 # From now on: either the user provided a specific file # name (and a possible version), or we return a list of # all the available files. In no case are the docids # visible. bibarchive = BibRecDocs(self.recid) if filename: # We know the complete file name, guess which docid it # refers to ## TODO: Change the extension system according to ext.py from setlink ## and have a uniform extension mechanism... name = file_strip_ext(filename) format = filename[len(name):] if format and format[0] == '.': format = format[1:] # search this filename in the complete list of files for doc in bibarchive.listBibDocs(): if filename in [f.fullname for f in doc.listAllFiles()]: try: docfile = doc.getFile(name,format,args['version']) except StandardError, msg: return errorMsg(msg, req, cdsname, ln) (auth_code, auth_message) = docfile.isRestricted(req) if auth_code != 0: return warningMsg(_("This file is restricted: ") + auth_message, req, cdsname, ln) if not readonly: ip = str(req.get_remote_host(apache.REMOTE_NOLOOKUP)) res = doc.registerDownload(ip, version, format, uid) try: return docfile.stream(req) except StandardError, msg: return errorMsg(msg, req, cdsname, ln) elif doc.getIcon() is not None and doc.getIcon().docname in filename: icon = doc.getIcon() try: iconfile = icon.getFile(icon.docname, 'gif', args['version']) except StandardError, msg: return errorMsg(msg, req, cdsname, ln) (auth_code, auth_message) = iconfile.isRestricted(req) if auth_code != 0: return streamRestrictedIcon(req) #return warningMsg(_("This Icon is restricted: ") + auth_message, req, cdsname, ln) if not readonly: ip = str(req.get_remote_host(apache.REMOTE_NOLOOKUP)) res = doc.registerDownload(ip, version, format, uid) try: return iconfile.stream(req) except StandardError, msg: return errorMsg(msg, req, c, ln) filelist = bibarchive.display("", args['version'], ln=ln) t = websubmit_templates.tmpl_filelist( ln=ln, recid=self.recid, docid="", version=args['version'], filelist=filelist) cc = guess_primary_collection_of_a_record(self.recid) unordered_tabs = get_detailed_page_tabs(get_colID(cc), self.recid) ordered_tabs_id = [(tab_id, values['order']) for (tab_id, values) in unordered_tabs.iteritems()] ordered_tabs_id.sort(lambda x,y: cmp(x[1],y[1])) tabs = [(unordered_tabs[tab_id]['label'], \ '%s/record/%s/%s' % (weburl, self.recid, tab_id), \ tab_id == 'files', unordered_tabs[tab_id]['enabled']) \ for (tab_id, order) in ordered_tabs_id if unordered_tabs[tab_id]['visible'] == True] t = webstyle_templates.detailed_record_container(t, self.recid, tabs, args['ln']) title, description, keywords = websearch_templates.tmpl_record_page_header_content(req, self.recid, args['ln']) return pageheaderonly(title=title, navtrail=create_navtrail_links(cc=cc, as=0, ln=ln) + \ ''' > <a class="navtrail" href="%s/record/%s">%s</a> > %s''' % \ (weburl, self.recid, title, _("Access to Fulltext")), description="", keywords="keywords", uid=uid, language=ln, req=req, navmenuid='search', navtrail_append_title_p=0) + \ websearch_templates.tmpl_search_pagestart(ln) + \ t + \ websearch_templates.tmpl_search_pageend(ln) + \ pagefooteronly(lastupdated=__lastupdated__, language=ln, req=req) return getfile, [] def __call__(self, req, form): """Called in case of URLs like /record/123/files without trailing slash. """ return redirect_to_url(req, '%s/record/%s/files/' % (weburl, self.recid)) def websubmit_legacy_getfile(req, form): """ Handle legacy /getfile.py URLs """ # FIXME: this should _redirect_ to the proper # /record/.../files/... URL. args = wash_urlargd(form, { 'c': (str, cdsname), 'recid': (str, ''), 'docid': (str, ''), 'version': (str, ''), 'name': (str, ''), 'format': (str, '') }) def _getfile_py(req,c=cdsname,ln=cdslang,recid="",docid="",version="",name="",format=""): _ = gettext_set_language(ln) # get user ID: try: uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../getfile.py/index", navmenuid='submit') uid_email = get_email(uid) except Error, e: return errorMsg(e.value,req) filelist="" # redirect to a canonical URL as far as it is possible (what # if we only have a docid, and no file supplied?) if name!="": if docid=="": return errorMsg(_("Parameter docid missing"), req, c, ln) try: doc = BibDoc(bibdocid=docid) except StandardError, msg: return errorMsg(msg, req, c, ln) try: docfile = doc.getFile(name,format,version) except StandardError, msg: return errorMsg(msg, req, c, ln) # redirect to this specific file, possibly dropping # the version if we are referring to the latest one. if docfile.format: format = '.' + docfile.format else: format = '' target = '%s/record/%d/files/%s%s' % ( weburl, doc.recid, quote(docfile.name), format) if version and int(version) == int(doc.getLatestVersion()): version = '' target += make_canonical_urlargd({ 'version': version}, websubmit_templates.files_default_urlargd) return redirect_to_url(req, target) # all files attached to a record elif recid!="": return redirect_to_url(req, '%s/record/%s/files/' % (weburl, recid)) # a precise filename elif docid!="": try: bibdoc = BibDoc(bibdocid=docid) except StandardError, msg: return errorMsg(msg, req, cdsname, ln) recid = bibdoc.getRecid() filelist = bibdoc.display(version, ln=ln) t = websubmit_templates.tmpl_filelist( ln = ln, recid = recid, docid = docid, version = version, filelist = filelist, ) p_navtrail = _("Access to Fulltext") return page(title="", body=t, navtrail = p_navtrail, description="", keywords="keywords", uid=uid, language=ln, req=req, navmenuid='search') return _getfile_py(req, **args) # -------------------------------------------------- from invenio.websubmit_engine import home, action, interface, endaction class WebInterfaceSubmitPages(WebInterfaceDirectory): _exports = ['summary', 'sub', 'direct', ''] def direct(self, req, form): args = wash_urlargd(form, {'sub': (str, '')}) sub = args['sub'] uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../direct.py/index", navmenuid='submit') myQuery = req.args if sub == "": return errorMsg("Sorry parameter missing...",req) res = run_sql("select docname,actname from sbmIMPLEMENT where subname=%s", (sub,)) if len(res)==0: return errorMsg("Sorry. Cannot analyse parameter",req) else: # get document type doctype = res[0][0] # get action name action = res[0][1] # retrieve other parameter values params = re.sub("sub=[^&]*","",myQuery) # find existing access number result = re.search("access=([^&]*)",params) if result is not None: access = result.group(1) params = re.sub("access=[^&]*","",params) else: # create 'unique' access number pid = os.getpid() now = time.time() access = "%i_%s" % (now,pid) # retrieve 'dir' value res = run_sql ("select dir from sbmACTION where sactname=%s",(action,)) dir = res[0][0] try: mainmenu = req.headers_in['Referer'] except: mainmenu = "" url = "/submit?doctype=%s&dir=%s&access=%s&act=%s&startPg=1%s&mainmenu=%s" % ( doctype,dir,access,action,params,quote(mainmenu)) req.err_headers_out.add("Location", url) raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY return "" def sub(self, req, form): uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../sub/", navmenuid='submit') myQuery = req.args if myQuery: if re.search("@",myQuery): param = re.sub("@.*","",myQuery) IN = re.sub(".*@","",myQuery) else: IN = myQuery url = "%s/submit/direct?sub=%s&%s" % (urlpath,IN,param) req.err_headers_out.add("Location", url) raise apache.SERVER_RETURN, apache.HTTP_MOVED_PERMANENTLY return "" else: return "<html>Illegal page access</html>" def summary(self, req, form): args = wash_urlargd(form, { 'doctype': (str, ''), 'act': (str, ''), 'access': (str, ''), 'indir': (str, '')}) uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../summary.py/index", navmenuid='submit') t="" curdir = "%s/%s/%s/%s" % (storage,args['indir'],args['doctype'],args['access']) subname = "%s%s" % (args['act'], args['doctype']) res = run_sql("select sdesc,fidesc,pagenb,level from sbmFIELD where subname=%s " "order by pagenb,fieldnb", (subname,)) nbFields = 0 values = [] for arr in res: if arr[0] != "": val = { 'mandatory' : (arr[3] == 'M'), 'value' : '', 'page' : arr[2], 'name' : arr[0], } if os.path.exists("%s/%s" % (curdir,arr[1])): fd = open("%s/%s" % (curdir,arr[1]),"r") value = fd.read() fd.close() value = value.replace("\n"," ") value = value.replace("Select:","") else: value = "" val['value'] = value values.append(val) return websubmit_templates.tmpl_submit_summary( ln = args['ln'], values = values, images = images, ) def index(self, req, form): args = wash_urlargd(form, { 'c': (str, cdsname), 'doctype': (str, ''), 'act': (str, ''), 'startPg': (str, "1"), 'indir': (str, ''), 'access': (str, ''), 'mainmenu': (str, ''), 'fromdir': (str, ''), 'file': (str, ''), 'nextPg': (str, ''), 'nbPg': (str, ''), 'curpage': (str, '1'), 'step': (str, '0'), 'mode': (str, 'U'), }) req.form = form def _index(req, c, ln, doctype, act, startPg, indir, access, mainmenu, fromdir, file, nextPg, nbPg, curpage, step, mode): uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../submit", navmenuid='submit') if doctype=="": return home(req,c,ln) elif act=="": return action(req,c,ln,doctype) elif int(step)==0: return interface(req,c,ln, doctype, act, startPg, indir, access, mainmenu, fromdir, file, nextPg, nbPg, curpage) else: return endaction(req,c,ln, doctype, act, startPg, indir, access,mainmenu, fromdir, file, nextPg, nbPg, curpage, step, mode) return _index(req, **args) # Answer to both /submit/ and /submit __call__ = index def errorMsg(title,req,c=cdsname,ln=cdslang): _ = gettext_set_language(ln) return page(title=_("Error"), body = create_error_box(req, title=title,verbose=0, ln=ln), description=_("Internal Error"), keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='submit') def warningMsg(title,req,c=cdsname,ln=cdslang): _ = gettext_set_language(ln) return page(title=_("Warning"), body = title, description=_("Internal Error"), keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='submit') diff --git a/modules/websubmit/web/publiline.py b/modules/websubmit/web/publiline.py index 85a2e7eda..996402297 100644 --- a/modules/websubmit/web/publiline.py +++ b/modules/websubmit/web/publiline.py @@ -1,1258 +1,1260 @@ ## $Id$ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN. ## ## CDS Invenio 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. ## ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. """ publiline_complex.py -- implementes ... actors in this process are: 1. author -- subilmts ... 2. edi 3; ref Il ne faut pas oublier de definir les roles... """ __revision__ = "$Id$" ## import interesting modules: import string import os import sys import time import types import re import shutil from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ accessurl, \ adminemail, \ cdslang, \ cdsname, \ images, \ pylibdir, \ storage, \ supportemail, \ sweburl, \ urlpath, \ version from invenio.dbquery import run_sql, Error from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import * from invenio.webpage import page, create_error_box from invenio.webuser import getUid, get_email, list_registered_users, page_not_authorized from invenio.messages import gettext_set_language, wash_language from invenio.websubmit_config import * from invenio.search_engine import search_pattern from invenio.websubmit_functions.Retrieve_Data import Get_Field from invenio.mailutils import send_email from invenio.urlutils import wash_url_argument from invenio.webgroup_dblayer import get_group_infos, insert_new_group, insert_new_member, delete_member from invenio.webaccessadmin_lib import cleanstring_email from invenio.access_control_config import MAXSELECTUSERS from invenio.access_control_admin import acc_get_user_email from invenio.webmessage import perform_request_send, perform_request_write_with_search import invenio.webbasket_dblayer as basketdb from invenio.webbasket_config import CFG_WEBBASKET_SHARE_LEVELS, CFG_WEBBASKET_CATEGORIES, CFG_WEBBASKET_SHARE_LEVELS_ORDERED from invenio.webbasket import perform_request_display_item, perform_request_save_comment from invenio.websubmit_functions.Retrieve_Data import Get_Field execfile("%s/invenio/websubmit_functions/Retrieve_Data.py" % pylibdir) import invenio.template websubmit_templates = invenio.template.load('websubmit') def index(req,c=cdsname,ln=cdslang,doctype="",categ="",RN="",send="",flow="",apptype="", action="", email_user_pattern="", id_user="", id_user_remove="", validate="", id_user_val="", msg_subject="", msg_body=""): global uid ln = wash_language(ln) categ = wash_url_argument(categ, 'str') RN = wash_url_argument(RN, 'str') send = wash_url_argument(send, 'str') flow = wash_url_argument(flow, 'str') apptype = wash_url_argument(apptype, 'str') action = wash_url_argument(action, 'str') email_user_pattern = wash_url_argument(email_user_pattern, 'str') id_user = wash_url_argument(id_user, 'int') id_user_remove = wash_url_argument(id_user_remove, 'int') validate = wash_url_argument(validate, 'str') id_user_val = wash_url_argument(id_user_val, 'int') msg_subject = wash_url_argument(msg_subject, 'str') msg_body = wash_url_argument(msg_body, 'str') # load the right message language _ = gettext_set_language(ln) t="" # get user ID: try: uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../publiline.py/index", navmenuid='yourapprovals') uid_email = get_email(uid) except Error, e: return errorMsg(e.value,req, ln = ln) if flow == "cplx": if doctype == "": t = selectCplxDoctype(ln) elif (categ == "") or (apptype == ""): t = selectCplxCateg(doctype, ln) elif RN == "": t = selectCplxDocument(doctype, categ, apptype, ln) elif action == "": t = displayCplxDocument(req, doctype, categ, RN, apptype, ln) else: t = doCplxAction(req, doctype, categ, RN, apptype, action, email_user_pattern, id_user, id_user_remove, validate, id_user_val, msg_subject, msg_body, ln) return page(title="specific publication line", navtrail= """<a class="navtrail" href="%(sweburl)s/youraccount/display">%(account)s</a>""" % { 'sweburl' : sweburl, 'account' : _("Your Account"), }, body=t, description="", keywords="", uid=uid, language=ln, req=req, navmenuid='yourapprovals') else: if doctype == "": t = selectDoctype(ln) elif categ == "": t = selectCateg(doctype, ln) elif RN == "": t = selectDocument(doctype, categ, ln) else: t = displayDocument(req, doctype, categ, RN, send, ln) return page(title="publication line", navtrail= """<a class="navtrail" href="%(sweburl)s/youraccount/display">%(account)s</a>""" % { 'sweburl' : sweburl, 'account' : _("Your Account"), }, body=t, description="", keywords="", uid=uid, language=ln, req=req, navmenuid='yourapprovals') def selectDoctype(ln = cdslang): res = run_sql("select DISTINCT doctype from sbmAPPROVAL") docs = [] for row in res: res2 = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (row[0],)) docs.append({ 'doctype' : row[0], 'docname' : res2[0][0], }) t = websubmit_templates.tmpl_publiline_selectdoctype( ln = ln, docs = docs, ) return t def selectCplxDoctype(ln = cdslang): res = run_sql("select DISTINCT doctype from sbmCPLXAPPROVAL") docs = [] for row in res: res2 = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (row[0],)) docs.append({ 'doctype' : row[0], 'docname' : res2[0][0], }) t = websubmit_templates.tmpl_publiline_selectcplxdoctype( ln = ln, docs = docs, ) return t def selectCateg(doctype, ln = cdslang): t="" res = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s",(doctype,)) title = res[0][0] sth = run_sql("select * from sbmCATEGORIES where doctype=%s order by lname",(doctype,)) if len(sth) == 0: categ = "unknown" return selectDocument(doctype,categ, ln = ln) categories = [] for arr in sth: waiting = 0 rejected = 0 approved = 0 sth2 = run_sql("select COUNT(*) from sbmAPPROVAL where doctype=%s and categ=%s and status='waiting'", (doctype,arr[1],)) waiting = sth2[0][0] sth2 = run_sql("select COUNT(*) from sbmAPPROVAL where doctype=%s and categ=%s and status='approved'",(doctype,arr[1],)) approved = sth2[0][0] sth2 = run_sql("select COUNT(*) from sbmAPPROVAL where doctype=%s and categ=%s and status='rejected'",(doctype,arr[1],)) rejected = sth2[0][0] categories.append({ 'waiting' : waiting, 'approved' : approved, 'rejected' : rejected, 'id' : arr[1], }) t = websubmit_templates.tmpl_publiline_selectcateg( ln = ln, categories = categories, doctype = doctype, title = title, images = images, ) return t def selectCplxCateg(doctype, ln = cdslang): t="" res = run_sql("SELECT ldocname FROM sbmDOCTYPE WHERE sdocname=%s",(doctype,)) title = res[0][0] sth = run_sql("SELECT * FROM sbmCATEGORIES WHERE doctype=%s ORDER BY lname",(doctype,)) if len(sth) == 0: categ = "unknown" return selectCplxDocument(doctype,categ, "", ln = ln) types = {} for apptype in ('RRP', 'RPB', 'RDA'): for arr in sth: info = {'id' : arr[1], 'desc' : arr[2],} for status in ('waiting', 'rejected', 'approved', 'cancelled'): info[status] = __db_count_doc (doctype, arr[1], status, apptype) types.setdefault (apptype, []).append(info) t = websubmit_templates.tmpl_publiline_selectcplxcateg( ln = ln, types = types, doctype = doctype, title = title, images = images, ) return t def selectDocument(doctype,categ, ln = cdslang): t="" res = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (doctype,)) title = res[0][0] if categ == "": categ == "unknown" docs = [] sth = run_sql("select rn,status from sbmAPPROVAL where doctype=%s and categ=%s order by status DESC,rn DESC",(doctype,categ)) for arr in sth: docs.append({ 'RN' : arr[0], 'status' : arr[1], }) t = websubmit_templates.tmpl_publiline_selectdocument( ln = ln, doctype = doctype, title = title, categ = categ, images = images, docs = docs, ) return t def selectCplxDocument(doctype,categ,apptype, ln = cdslang): t="" res = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (doctype,)) title = res[0][0] sth = run_sql("select lname from sbmCATEGORIES where doctype=%s and sname=%s order by lname",(doctype,categ,)) if len(sth) != 0: categname = sth[0][0] else: categname = "Unknown" docs = [] sth = run_sql("select rn,status from sbmCPLXAPPROVAL where doctype=%s and categ=%s and type=%s order by status DESC,rn DESC",(doctype,categ,apptype)) for arr in sth: docs.append({ 'RN' : arr[0], 'status' : arr[1], }) t = websubmit_templates.tmpl_publiline_selectcplxdocument( ln = ln, doctype = doctype, title = title, categ = categ, categname = categname, images = images, docs = docs, apptype = apptype, ) return t def displayDocument(req, doctype,categ,RN,send, ln = cdslang): # load the right message language _ = gettext_set_language(ln) t="" res = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (doctype,)) docname = res[0][0] if categ == "": categ = "unknown" sth = run_sql("select rn,status,dFirstReq,dLastReq,dAction,access from sbmAPPROVAL where rn=%s",(RN,)) if len(sth) > 0: arr = sth[0] rn = arr[0] status = arr[1] dFirstReq = arr[2] dLastReq = arr[3] dAction = arr[4] access = arr[5] else: return _("Approval has never been requested for this document.") + "<BR> " try: (authors,title,sysno,newrn) = getInfo(doctype,categ,RN) except TypeError: return _("Unable to display document.") confirm_send = 0 if send == _("Send Again"): if authors == "unknown" or title == "unknown": SendWarning(doctype,categ,RN,title,authors,access, ln = ln) else: # @todo - send in different languages SendEnglish(doctype,categ,RN,title,authors,access,sysno) run_sql("update sbmAPPROVAL set dLastReq=NOW() where rn=%s",(RN,)) confirm_send = 1 if status == "waiting": (auth_code, auth_message) = acc_authorize_action(req, "referee",verbose=0,doctype=doctype, categ=categ) else: (auth_code, auth_message) = (None, None) t = websubmit_templates.tmpl_publiline_displaydoc( ln = ln, docname = docname, doctype = doctype, categ = categ, rn = rn, status = status, dFirstReq = dFirstReq, dLastReq = dLastReq, dAction = dAction, access = access, images = images, accessurl = accessurl, confirm_send = confirm_send, auth_code = auth_code, auth_message = auth_message, authors = authors, title = title, sysno = sysno, newrn = newrn, ) return t def displayCplxDocument(req, doctype,categ,RN,apptype, ln = cdslang): # load the right message language _ = gettext_set_language(ln) t="" uid = getUid(req) res = run_sql("select ldocname from sbmDOCTYPE where sdocname=%s", (doctype,)) docname = res[0][0] if categ == "": categ = "unknown" key = (RN, apptype) infos = __db_get_infos (key) if len(infos) > 0: (status, id_group, id_bskBASKET, id_EdBoardGroup, dFirstReq,dLastReq,dEdBoardSel, dRefereeSel, dRefereeRecom, dEdBoardRecom, dPubComRecom, dProjectLeaderAction) = infos[0] dates = {'dFirstReq' : dFirstReq, 'dLastReq' : dLastReq, 'dEdBoardSel' : dEdBoardSel, 'dRefereeSel' : dRefereeSel, 'dRefereeRecom' : dRefereeRecom, 'dEdBoardRecom' : dEdBoardRecom, 'dPubComRecom' : dPubComRecom, 'dProjectLeaderAction' : dProjectLeaderAction, } else: return _("Approval has never been requested for this document.") + "<BR> " try: (authors,title,sysno,newrn) = getInAlice(doctype,categ,RN) except TypeError: return _("Unable to display document.") if status == "waiting": isPubCom = __is_PubCom (req, doctype) isEdBoard = __is_EdBoard (uid, id_EdBoardGroup) isReferee = __is_Referee (uid, id_bskBASKET) isProjectLeader = __is_ProjectLeader (req, doctype, categ) isAuthor = __is_Author (uid, sysno) else: isPubCom = None isEdBoard = None isReferee = None isProjectLeader = None isAuthor = None t += websubmit_templates.tmpl_publiline_displaycplxdoc( ln = ln, docname = docname, doctype = doctype, categ = categ, rn = RN, apptype = apptype, status = status, dates = dates, images = images, accessurl = accessurl, isPubCom = isPubCom, isEdBoard = isEdBoard, isReferee = isReferee, isProjectLeader = isProjectLeader, isAuthor = isAuthor, authors = authors, title = title, sysno = sysno, newrn = newrn, ) if id_bskBASKET > 0: rights = basketdb.get_max_user_rights_on_basket(uid, id_bskBASKET) if not(__check_basket_sufficient_rights(rights, CFG_WEBBASKET_SHARE_LEVELS['READITM'])): return t comments = basketdb.get_comments(id_bskBASKET, sysno) if dProjectLeaderAction != None: user_can_add_comment = 0 else: user_can_add_comment = __check_basket_sufficient_rights(rights, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) t += websubmit_templates.tmpl_publiline_displaycplxdocitem( doctype, categ, RN, apptype, "AddComment", comments, (__check_basket_sufficient_rights(rights, CFG_WEBBASKET_SHARE_LEVELS['READCMT']), user_can_add_comment, __check_basket_sufficient_rights(rights, CFG_WEBBASKET_SHARE_LEVELS['DELCMT'])), selected_category=CFG_WEBBASKET_CATEGORIES['GROUP'], selected_topic=0, selected_group_id=id_group, ln=ln) return t def __check_basket_sufficient_rights(rights_user_has, rights_needed): """Private function, check if the rights are sufficient.""" try: out = CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights_user_has) >= \ CFG_WEBBASKET_SHARE_LEVELS_ORDERED.index(rights_needed) except ValueError: out = 0 return out def __is_PubCom (req,doctype): (isPubCom, auth_message) = acc_authorize_action(req, "pubcomchair",verbose=0,doctype=doctype) return isPubCom def __is_EdBoard (uid, id_EdBoardGroup): isEdBoard = None if id_EdBoardGroup > 0: edBoard = run_sql("""SELECT u.id FROM user u LEFT JOIN user_usergroup ug ON u.id = ug.id_user WHERE ug.id_usergroup = '%s' and user_status != 'A' AND user_status != 'P'""" % (id_EdBoardGroup, )) for uid_scan in edBoard: if uid == uid_scan[0]: isEdBoard = 0 break return isEdBoard def __is_Referee (uid, id_bskBASKET): isReferee = None if id_bskBASKET > 0: if basketdb.check_user_owns_baskets (uid, id_bskBASKET) == 1: isReferee = 0 return isReferee def __is_ProjectLeader (req, doctype, categ): (isProjectLeader, auth_message) = acc_authorize_action(req, "projectleader",verbose=0,doctype=doctype,categ=categ) return isProjectLeader def __is_Author (uid, sysno): email = Get_Field("8560_f",sysno) email = re.sub("[\n\r ]+","",email) uid_email = re.sub("[\n\r ]+","", acc_get_user_email(uid)) isAuthor = None if (re.search(uid_email,email,re.IGNORECASE) != None) and (uid_email != ""): isAuthor = 0 return isAuthor def __db_count_doc (doctype, categ, status, apptype): return run_sql("SELECT COUNT(*) FROM sbmCPLXAPPROVAL WHERE doctype=%s AND categ=%s AND status=%s AND type=%s",(doctype,categ,status,apptype,))[0][0] def __db_get_infos (key): return run_sql("SELECT status,id_group,id_bskBASKET,id_EdBoardGroup,dFirstReq,dLastReq,dEdBoardSel,dRefereeSel,dRefereeRecom,dEdBoardRecom,dPubComRecom,dProjectLeaderAction FROM sbmCPLXAPPROVAL WHERE rn=%s and type=%s", key) def __db_set_EdBoardSel_time (key): run_sql("UPDATE sbmCPLXAPPROVAL SET dEdBoardSel=NOW() WHERE rn=%s and type=%s", key) def __db_check_EdBoardGroup ((RN,apptype), id_EdBoardGroup, uid, group_descr): res = get_group_infos (id_EdBoardGroup) if len(res) == 0: id_EdBoardGroup = insert_new_group (uid, RN, group_descr % RN, "VM") run_sql("UPDATE sbmCPLXAPPROVAL SET id_EdBoardGroup=%s WHERE rn=%s and type=%s", (id_EdBoardGroup,RN,apptype,)) return id_EdBoardGroup def __db_set_basket ((RN,apptype), id_bsk): run_sql("UPDATE sbmCPLXAPPROVAL SET id_bskBASKET=%s, dRefereeSel=NOW() WHERE rn=%s and type=%s", (id_bsk,RN,apptype,)) def __db_set_RefereeRecom_time (key): run_sql("UPDATE sbmCPLXAPPROVAL SET dRefereeRecom=NOW() WHERE rn=%s and type=%s", key) def __db_set_EdBoardRecom_time (key): run_sql("UPDATE sbmCPLXAPPROVAL SET dEdBoardRecom=NOW() WHERE rn=%s and type=%s", key) def __db_set_PubComRecom_time (key): run_sql("UPDATE sbmCPLXAPPROVAL SET dPubComRecom=NOW() WHERE rn=%s and type=%s", key) def __db_set_status ((RN,apptype), status): run_sql("UPDATE sbmCPLXAPPROVAL SET status=%s, dProjectLeaderAction=NOW() WHERE rn=%s and type=%s", (status,RN,apptype,)) def doCplxAction(req, doctype, categ, RN, apptype, action, email_user_pattern, id_user, id_user_remove, validate, id_user_val, msg_subject, msg_body, ln=cdslang): """ Perform complex action. Note: all argume,ts are supposed to be washed already. Return HTML body for the paget. In case of errors, deletes hard drive. ;-) """ # load the right message language _ = gettext_set_language(ln) TEXT_RRP_RefereeSel_BASKET_DESCR = "Requests for refereeing process" TEXT_RRP_RefereeSel_MSG_REFEREE_SUBJECT = "Referee selection" TEXT_RRP_RefereeSel_MSG_REFEREE_BODY = "You have been named as a referee for this document :" TEXT_RRP_RefereeSel_MSG_GROUP_SUBJECT = "Please, review this publication" TEXT_RRP_RefereeSel_MSG_GROUP_BODY = "Please, review the following publication" TEXT_RRP_RefereeRecom_MSG_PUBCOM_SUBJECT = "Final recommendation from the referee" TEXT_RRP_PubComRecom_MSG_PRJLEADER_SUBJECT = "Final recommendation from the publication board" TEXT_RRP_ProjectLeaderDecision_MSG_SUBJECT = "Final decision from the project leader" TEXT_RPB_EdBoardSel_MSG_EDBOARD_SUBJECT = "You have been selected in a editorial board" TEXT_RPB_EdBoardSel_MSG_EDBOARD_BODY = "You have been selected as a member of the editorial board of this document :" TEXT_RPB_EdBoardSel_EDBOARD_GROUP_DESCR = "Editorial board for %s" TEXT_RPB_RefereeSel_BASKET_DESCR = "Requests for publication" TEXT_RPB_RefereeSel_MSG_REFEREE_SUBJECT = "Referee selection" TEXT_RPB_RefereeSel_MSG_REFEREE_BODY = "You have been named as a referee for this document :" TEXT_RPB_RefereeSel_MSG_GROUP_SUBJECT = "Please, review this publication" TEXT_RPB_RefereeSel_MSG_GROUP_BODY = "Please, review the following publication" TEXT_RPB_RefereeRecom_MSG_EDBOARD_SUBJECT = "Final recommendation from the referee" TEXT_RPB_EdBoardRecom_MSG_PUBCOM_SUBJECT = "Final recommendation from the editorial board" TEXT_RPB_PubComRecom_MSG_PRJLEADER_SUBJECT = "Final recommendation from the publication board" TEXT_RPB_ProjectLeaderDecision_MSG_SUBJECT = "Final decision from the project leader" t="" uid = getUid(req) if categ == "": categ = "unknown" key = (RN, apptype) infos = __db_get_infos (key) if len(infos) > 0: (status, id_group, id_bskBASKET, id_EdBoardGroup, dummy, dummy, dEdBoardSel, dRefereeSel, dRefereeRecom, dEdBoardRecom, dPubComRecom, dProjectLeaderAction) = infos[0] else: return _("Approval has never been requested for this document.") + "<br /> " try: (authors,title,sysno,newrn) = getInAlice(doctype,categ,RN) except TypeError: return _("Unable to display document.") if (action == "EdBoardSel") and (apptype == "RPB"): if __is_PubCom (req, doctype) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " if validate == "go": if dEdBoardSel == None: __db_set_EdBoardSel_time (key) perform_request_send (uid, "", RN, TEXT_RPB_EdBoardSel_MSG_EDBOARD_SUBJECT, TEXT_RPB_EdBoardSel_MSG_EDBOARD_BODY) return displayCplxDocument(req, doctype,categ,RN,apptype, ln) id_EdBoardGroup = __db_check_EdBoardGroup (key, id_EdBoardGroup, uid, TEXT_RPB_EdBoardSel_EDBOARD_GROUP_DESCR) subtitle1 = _('Adding users to the editorial board') # remove letters not allowed in an email email_user_pattern = cleanstring_email(email_user_pattern) stopon1 = "" stopon2 = "" stopon3 = "" users = [] extrausers = [] # pattern is entered if email_user_pattern: # users with matching email-address users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE %s ORDER BY email """, (email_user_pattern, )) # users that are connected users2 = run_sql("""SELECT DISTINCT u.id, u.email FROM user u LEFT JOIN user_usergroup ug ON u.id = ug.id_user WHERE ug.id_usergroup = %s AND u.email RLIKE %s ORDER BY u.email """, (id_EdBoardGroup, email_user_pattern)) # no users that match the pattern if not (users1 or users2): stopon1 = '<p>%s</p>' % _("no qualified users, try new search.") elif len(users1) > MAXSELECTUSERS: stopon1 = '<p><strong>%s %s</strong>, %s (%s %s)</p>' % (len(users1), _("hits"), _("too many qualified users, specify more narrow search."), _("limit"), MAXSELECTUSERS) # show matching users else: users = [] extrausers = [] for (user_id, email) in users1: if (user_id, email) not in users2: users.append([user_id,email,'']) for (user_id, email) in users2: extrausers.append([-user_id, email,'']) try: id_user = int(id_user) except ValueError: pass # user selected already connected to role email_out = acc_get_user_email(id_user) if id_user < 0: stopon2 = '<p>%s</p>' % _("users in brackets are already attached to the role, try another one...") # a user is selected elif email_out: result = insert_new_member(id_user, id_EdBoardGroup, "M") stopon2 = '<p>confirm: user <strong>%s</strong> added to the editorial board.</p>' % (email_out, ) subtitle2 = _('Removing users from the editorial board') usersremove = run_sql("""SELECT DISTINCT u.id, u.email FROM user u LEFT JOIN user_usergroup ug ON u.id = ug.id_user WHERE ug.id_usergroup = %s and user_status != 'A' AND user_status != 'P' ORDER BY u.email """, (id_EdBoardGroup, )) try: id_user_remove = int(id_user_remove) except ValueError: pass # user selected already connected to role email_out = acc_get_user_email(id_user_remove) # a user is selected if email_out: result = delete_member(id_EdBoardGroup, id_user_remove) stopon3 = '<p>confirm: user <strong>%s</strong> removed from the editorial board.</p>' % (email_out, ) t = websubmit_templates.tmpl_publiline_displaydocplxaction ( ln = ln, doctype = doctype, categ = categ, rn = RN, apptype = apptype, action = action, status = status, images = images, authors = authors, title = title, sysno = sysno, subtitle1 = subtitle1, email_user_pattern = email_user_pattern, stopon1 = stopon1, users = users, extrausers = extrausers, stopon2 = stopon2, subtitle2 = subtitle2, usersremove = usersremove, stopon3 = stopon3, validate_btn = _("Validate the editorial board selection"), ) return t elif (action == "RefereeSel") and ((apptype == "RRP") or (apptype == "RPB")): if apptype == "RRP": to_check = __is_PubCom (req, doctype) TEXT_RefereeSel_BASKET_DESCR = TEXT_RRP_RefereeSel_BASKET_DESCR TEXT_RefereeSel_MSG_REFEREE_SUBJECT = TEXT_RRP_RefereeSel_MSG_REFEREE_SUBJECT TEXT_RefereeSel_MSG_REFEREE_BODY = TEXT_RRP_RefereeSel_MSG_REFEREE_BODY TEXT_RefereeSel_MSG_GROUP_SUBJECT = TEXT_RRP_RefereeSel_MSG_GROUP_SUBJECT TEXT_RefereeSel_MSG_GROUP_BODY = TEXT_RRP_RefereeSel_MSG_GROUP_BODY elif apptype == "RPB": to_check = __is_EdBoard (uid, id_EdBoardGroup) TEXT_RefereeSel_BASKET_DESCR = TEXT_RRP_RefereeSel_BASKET_DESCR TEXT_RefereeSel_MSG_REFEREE_SUBJECT = TEXT_RRP_RefereeSel_MSG_REFEREE_SUBJECT TEXT_RefereeSel_MSG_REFEREE_BODY = TEXT_RRP_RefereeSel_MSG_REFEREE_BODY TEXT_RefereeSel_MSG_GROUP_SUBJECT = TEXT_RRP_RefereeSel_MSG_GROUP_SUBJECT TEXT_RefereeSel_MSG_GROUP_BODY = TEXT_RRP_RefereeSel_MSG_GROUP_BODY else: to_check = None if to_check != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " if validate == "go": if dRefereeSel == None: id_bsk = basketdb.create_basket (int(id_user_val), RN, TEXT_RefereeSel_BASKET_DESCR) basketdb.share_basket_with_group (id_bsk, id_group, CFG_WEBBASKET_SHARE_LEVELS['ADDCMT']) basketdb.add_to_basket (int(id_user_val), (sysno, ), (id_bsk, )) __db_set_basket (key, id_bsk) referee_name = run_sql("""SELECT nickname FROM user WHERE id = %s """, (id_user_val, ))[0][0] perform_request_send (uid, referee_name, "", TEXT_RefereeSel_MSG_REFEREE_SUBJECT, TEXT_RefereeSel_MSG_REFEREE_BODY) group_name = run_sql("""SELECT name FROM usergroup WHERE id = %s""", (id_group, ))[0][0] perform_request_send (int(id_user_val), "", group_name, TEXT_RefereeSel_MSG_GROUP_SUBJECT, TEXT_RefereeSel_MSG_GROUP_BODY) return displayCplxDocument(req, doctype,categ,RN,apptype, ln) subtitle1 = _('Referee selection') # remove letters not allowed in an email email_user_pattern = cleanstring_email(email_user_pattern) stopon1 = "" stopon2 = "" users = [] extrausers = [] # pattern is entered if email_user_pattern: # users with matching email-address users1 = run_sql("""SELECT id, email FROM user WHERE email RLIKE %s ORDER BY email """, (email_user_pattern, )) # no users that match the pattern if not users1: stopon1 = '<p>%s</p>' % _("no qualified users, try new search.") elif len(users1) > MAXSELECTUSERS: stopon1 = '<p><strong>%s %s</strong>, %s (%s %s)</p>' % (len(users1), _("hits"), _("too many qualified users, specify more narrow search."), _("limit"), MAXSELECTUSERS) # show matching users else: users = [] for (user_id, email) in users1: users.append([user_id,email,'']) try: id_user = int(id_user) except ValueError: pass # user selected already connected to role email_out = acc_get_user_email(id_user) # a user is selected if email_out: stopon2 = """<p>user <strong>%s</strong> will be the referee ? <input type="hidden" name="id_user_val" value="%s" /> <input type="hidden" name="validate" value="go" /> <input class="adminbutton" type="submit" value="Validate the referee selection" /> </p>""" % (email_out, id_user) t = websubmit_templates.tmpl_publiline_displaydocplxaction ( ln = ln, doctype = doctype, categ = categ, rn = RN, apptype = apptype, action = action, status = status, images = images, authors = authors, title = title, sysno = sysno, subtitle1 = subtitle1, email_user_pattern = email_user_pattern, stopon1 = stopon1, users = users, extrausers = [], stopon2 = stopon2, subtitle2 = "", usersremove = [], stopon3 = "", validate_btn = "", ) return t elif (action == "AddAuthorList") and (apptype == "RPB"): return "" elif (action == "AddComment") and ((apptype == "RRP") or (apptype == "RPB")): t = "" if validate == "go": (errors, infos) = perform_request_save_comment (uid, id_bskBASKET, sysno, msg_subject, msg_body, ln) t += "%(infos)s<br /><br />" % {'infos' : infos[0]} t += """ <form action="publiline.py"> <input type="hidden" name="flow" value="cplx" /> <input type="hidden" name="doctype" value="%(doctype)s" /> <input type="hidden" name="categ" value="%(categ)s" /> <input type="hidden" name="RN" value="%(rn)s" /> <input type="hidden" name="apptype" value="%(apptype)s" /> <input type="submit" class="formbutton" value="%(button_label)s" /> </form>""" % {'doctype' : doctype, 'categ' : categ, 'rn' : RN, 'apptype' : apptype, 'button_label' : _("Come back to the document"), } return t elif (action == "RefereeRecom") and ((apptype == "RRP") or (apptype == "RPB")): if __is_Referee (uid, id_bskBASKET) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " if apptype == "RRP": # Build publication committee chair's email address user_addr = "" # Try to retrieve the publication committee chair's email from the role database for user in acc_get_role_users(acc_get_role_id("pubcomchair_%s_%s" % (doctype,categ))): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," # And if there are general publication committee chair's for user in acc_get_role_users(acc_get_role_id("pubcomchair_%s_*" % doctype)): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," user_addr = re.sub(",$","",user_addr) group_addr = "" TEXT_RefereeRecom_MSG_SUBJECT = TEXT_RRP_RefereeRecom_MSG_PUBCOM_SUBJECT elif apptype == "RPB": user_addr = "" group_addr = RN TEXT_RefereeRecom_MSG_SUBJECT = TEXT_RPB_RefereeRecom_MSG_EDBOARD_SUBJECT else: user_addr = "" group_addr = "" TEXT_RefereeRecom_MSG_SUBJECT = "" if validate == "go": if dRefereeRecom == None: perform_request_send (uid, user_addr, group_addr, msg_subject, msg_body) __db_set_RefereeRecom_time (key) return displayCplxDocument(req, doctype,categ,RN,apptype, ln) t = websubmit_templates.tmpl_publiline_displaycplxrecom ( ln = ln, doctype = doctype, categ = categ, rn = RN, apptype = apptype, action = action, status = status, images = images, authors = authors, title = title, sysno = sysno, msg_to = user_addr, msg_to_group = group_addr, msg_subject = TEXT_RefereeRecom_MSG_SUBJECT, ) return t elif (action == "EdBoardRecom") and (apptype == "RPB"): if __is_EdBoard (uid, id_EdBoardGroup) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " # Build publication committee chair's email address user_addr = "" # Try to retrieve the publication committee chair's email from the role database for user in acc_get_role_users(acc_get_role_id("pubcomchair_%s_%s" % (doctype,categ))): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," # And if there are general publication committee chair's for user in acc_get_role_users(acc_get_role_id("pubcomchair_%s_*" % doctype)): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," user_addr = re.sub(",$","",user_addr) if validate == "go": if dEdBoardRecom == None: perform_request_send (uid, user_addr, "", msg_subject, msg_body) __db_set_EdBoardRecom_time (key) return displayCplxDocument(req, doctype,categ,RN,apptype, ln) t = websubmit_templates.tmpl_publiline_displaycplxrecom ( ln = ln, doctype = doctype, categ = categ, rn = RN, apptype = apptype, action = action, status = status, images = images, authors = authors, title = title, sysno = sysno, msg_to = user_addr, msg_to_group = "", msg_subject = TEXT_RPB_EdBoardRecom_MSG_PUBCOM_SUBJECT, ) return t elif (action == "PubComRecom") and ((apptype == "RRP") or (apptype == "RPB")): if __is_PubCom (req, doctype) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " # Build project leader's email address user_addr = "" # Try to retrieve the project leader's email from the role database for user in acc_get_role_users(acc_get_role_id("projectleader_%s_%s" % (doctype,categ))): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," # And if there are general project leader's for user in acc_get_role_users(acc_get_role_id("projectleader_%s_*" % doctype)): user_addr += run_sql("""SELECT nickname FROM user WHERE id = %s """, (user[0], ))[0][0] + "," user_addr = re.sub(",$","",user_addr) if apptype == "RRP": TEXT_PubComRecom_MSG_SUBJECT = TEXT_RRP_PubComRecom_MSG_PRJLEADER_SUBJECT elif apptype == "RPB": group_addr = RN TEXT_PubComRecom_MSG_SUBJECT = TEXT_RPB_PubComRecom_MSG_PRJLEADER_SUBJECT else: TEXT_PubComRecom_MSG_SUBJECT = "" if validate == "go": if dPubComRecom == None: perform_request_send (uid, user_addr, "", msg_subject, msg_body) __db_set_PubComRecom_time (key) return displayCplxDocument(req, doctype,categ,RN,apptype, ln) t = websubmit_templates.tmpl_publiline_displaycplxrecom ( ln = ln, doctype = doctype, categ = categ, rn = RN, apptype = apptype, action = action, status = status, images = images, authors = authors, title = title, sysno = sysno, msg_to = user_addr, msg_to_group = "", msg_subject = TEXT_PubComRecom_MSG_SUBJECT, ) return t elif (action == "ProjectLeaderDecision") and ((apptype == "RRP") or (apptype == "RPB")): if __is_ProjectLeader (req, doctype, categ) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " t += """ <form action="publiline.py"> <input type="hidden" name="flow" value="cplx" /> <input type="hidden" name="doctype" value="%(doctype)s" /> <input type="hidden" name="categ" value="%(categ)s" /> <input type="hidden" name="RN" value="%(rn)s" /> <input type="hidden" name="apptype" value="%(apptype)s" /> <input type="submit" class="formbutton" value="%(button_label)s" /> </form>""" % {'doctype' : doctype, 'categ' : categ, 'rn' : RN, 'apptype' : apptype, 'button_label' : _("Come back to the document"), } if validate == "approve": if dProjectLeaderAction == None: (errors, infos) = perform_request_save_comment (uid, id_bskBASKET, sysno, msg_subject, msg_body, ln) out = "%(infos)s<br /><br />" % {'infos' : infos[0]} __db_set_status (key, 'approved') return out + t elif validate == "reject": if dProjectLeaderAction == None: (errors, infos) = perform_request_save_comment (uid, id_bskBASKET, sysno, msg_subject, msg_body, ln) out = "%(infos)s<br /><br />" % {'infos' : infos[0]} __db_set_status (key, 'rejected') return out + t validation = """ <select name="validate"> <option> %(select)s</option> <option value="approve">%(approve)s</option> <option value="reject">%(reject)s</option> </select> <input type="submit" class="formbutton" value="%(button_label)s" />""" % {'select' : _('Select:'), 'approve' : _('Approve'), 'reject' : _('Reject'), 'button_label' : _('Take a decision'), } if apptype == "RRP": TEXT_ProjectLeaderDecision_MSG_SUBJECT = TEXT_RRP_ProjectLeaderDecision_MSG_SUBJECT elif apptype == "RPB": TEXT_ProjectLeaderDecision_MSG_SUBJECT = TEXT_RPB_ProjectLeaderDecision_MSG_SUBJECT else: TEXT_ProjectLeaderDecision_MSG_SUBJECT = "" t = websubmit_templates.tmpl_publiline_displaywritecomment(doctype, categ, RN, apptype, action, _("Take a decision"), TEXT_ProjectLeaderDecision_MSG_SUBJECT, validation, ln) return t elif (action == "ProjectLeaderDecision") and (apptype == "RDA"): if __is_ProjectLeader (req, doctype, categ) != 0: return _("Action unauthorized for this document.") + "<br /> " if status == "cancelled": return _("Action unavailable for this document.") + "<br /> " if validate == "approve": if dProjectLeaderAction == None: __db_set_status (key, 'approved') return displayCplxDocument(req, doctype,categ,RN,apptype, ln) elif validate == "reject": if dProjectLeaderAction == None: __db_set_status (key, 'rejected') return displayCplxDocument(req, doctype,categ,RN,apptype, ln) t = """<p> <form action="publiline.py"> <input type="hidden" name="flow" value="cplx" /> <input type="hidden" name="doctype" value="%(doctype)s" /> <input type="hidden" name="categ" value="%(categ)s" /> <input type="hidden" name="RN" value="%(rn)s" /> <input type="hidden" name="apptype" value="%(apptype)s" /> <input type="hidden" name="action" value="%(action)s" /> <input type="hidden" name="validate" value="approve" /> <input class="adminbutton" type="submit" value="%(approve)s" /> </form> <form action="publiline.py"> <input type="hidden" name="flow" value="cplx" /> <input type="hidden" name="doctype" value="%(doctype)s" /> <input type="hidden" name="categ" value="%(categ)s" /> <input type="hidden" name="RN" value="%(rn)s" /> <input type="hidden" name="apptype" value="%(apptype)s" /> <input type="hidden" name="action" value="%(action)s" /> <input type="hidden" name="validate" value="reject" /> <input class="adminbutton" type="submit" value="%(reject)s" /> </form> </p>""" % { 'rn' : RN, 'categ' : categ, 'doctype' : doctype, 'apptype' : apptype, 'action' : action, 'approve' : _('Approve'), 'reject' : _('Reject'), } return t elif (action == "AuthorCancel") and ((apptype == "RRP") or (apptype == "RPB") or (apptype == "RDA")): if __is_Author (uid, sysno) != 0: return _("Action unauthorized for this document.") + "<br /> " if (status == "cancelled") or (dProjectLeaderAction != None): return _("Action unavailable for this document.") + "<br /> " if validate == "go": __db_set_status (key, 'cancelled') return displayCplxDocument(req, doctype,categ,RN,apptype, ln) t = """<p> <form action="publiline.py"> <input type="hidden" name="flow" value="cplx" /> <input type="hidden" name="doctype" value="%(doctype)s" /> <input type="hidden" name="categ" value="%(categ)s" /> <input type="hidden" name="RN" value="%(rn)s" /> <input type="hidden" name="apptype" value="%(apptype)s" /> <input type="hidden" name="action" value="%(action)s" /> <input type="hidden" name="validate" value="go" /> <input class="adminbutton" type="submit" value="%(cancel)s" /> </form> </p>""" % { 'rn' : RN, 'categ' : categ, 'doctype' : doctype, 'apptype' : apptype, 'action' : action, 'cancel' : _('Cancel'), } return t else: return _("Wrong action for this document.") + "<BR> " return t # Retrieve info about document def getInfo(doctype,categ,RN): result = getInPending(doctype,categ,RN) if not result: result = getInAlice(doctype,categ,RN) return result #seek info in pending directory def getInPending(doctype,categ,RN): PENDIR="%s/pending" % storage if os.path.exists("%s/%s/%s/AU" % (PENDIR,doctype,RN)): fp = open("%s/%s/%s/AU" % (PENDIR,doctype,RN),"r") authors=fp.read() fp.close() else: authors = "" if os.path.exists("%s/%s/%s/TI" % (PENDIR,doctype,RN)): fp = open("%s/%s/%s/TI" % (PENDIR,doctype,RN),"r") title=fp.read() fp.close() else: title = "" if os.path.exists("%s/%s/%s/SN" % (PENDIR,doctype,RN)): fp = open("%s/%s/%s/SN" % (PENDIR,doctype,RN),"r") sysno=fp.read() fp.close() else: sysno = "" if title == "" and os.path.exists("%s/%s/%s/TIF" % (PENDIR,doctype,RN)): fp = open("%s/%s/%s/TIF" % (PENDIR,doctype,RN),"r") title=fp.read() fp.close() if title == "": return 0 else: return (authors,title,sysno,"") #seek info in Alice database def getInAlice(doctype,categ,RN): # initialize sysno variable sysno = "" searchresults = list(search_pattern(req=None, p=RN, f="reportnumber")) if len(searchresults) == 0: return 0 sysno = searchresults[0] if sysno != "": title = Get_Field('245__a',sysno) emailvalue = Get_Field('8560_f',sysno) authors = Get_Field('100__a',sysno) authors += "\n%s" % Get_Field('700__a',sysno) newrn = Get_Field('037__a',sysno) return (authors,title,sysno,newrn) else: return 0 def SendEnglish(doctype,categ,RN,title,authors,access,sysno): FROMADDR = '%s Submission Engine <%s>' % (cdsname,supportemail) # retrieve useful information from webSubmit configuration res = run_sql("select value from sbmPARAMETERS where name='categformatDAM' and doctype=%s", (doctype,)) categformat = res[0][0] categformat = re.sub("<CATEG>","([^-]*)",categformat) categs = re.match(categformat,RN) if categs is not None: categ = categs.group(1) else: categ = "unknown" res = run_sql("select value from sbmPARAMETERS where name='addressesDAM' and doctype=%s",(doctype,)) if len(res) > 0: otheraddresses = res[0][0] otheraddresses = otheraddresses.replace("<CATEG>",categ) else: otheraddresses = "" # Build referee's email address refereeaddress = "" # Try to retrieve the referee's email from the referee's database for user in acc_get_role_users(acc_getRoleId("referee_%s_%s" % (doctype,categ))): refereeaddress += user[1] + "," # And if there are general referees for user in acc_get_role_users(acc_getRoleId("referee_%s_*" % doctype)): refereeaddress += user[1] + "," refereeaddress = re.sub(",$","",refereeaddress) # Creation of the mail for the referee addresses = "" if refereeaddress != "": addresses = refereeaddress + "," if otheraddresses != "": addresses += otheraddresses else: addresses = re.sub(",$","",addresses) if addresses=="": SendWarning(doctype,categ,RN,title,authors,access) return 0 if authors == "": authors = "-" res = run_sql("select value from sbmPARAMETERS where name='directory' and doctype=%s", (doctype,)) directory = res[0][0] message = """ The document %s has been published as a Communication. Your approval is requested for it to become an official Note. Title: %s Author(s): %s To access the document(s), select the file(s) from the location: <%s/record/%s/files/> To approve/reject the document, you should go to this URL: <%s/approve.py?%s> --------------------------------------------- Best regards. The submission team.""" % (RN,title,authors,urlpath,sysno,urlpath,access) # send the mail send_email(FROMADDR,addresses,"Request for Approval of %s" % RN, message,footer="") return "" def SendWarning(doctype,categ,RN,title,authors,access): FROMADDR = '%s Submission Engine <%s>' % (cdsname,supportemail) message = "Failed sending approval email request for %s" % RN # send the mail send_email(FROMADDR,adminemail,"Failed sending approval email request",message) return "" def errorMsg(title,req,c=cdsname,ln=cdslang): return page(title="error", body = create_error_box(req, title=title,verbose=0, ln=ln), description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='yourapprovals') def warningMsg(title,req,c=cdsname,ln=cdslang): return page(title="warning", body = title, description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='yourapprovals') diff --git a/modules/websubmit/web/yoursubmissions.py b/modules/websubmit/web/yoursubmissions.py index 829918a67..9652ef35d 100644 --- a/modules/websubmit/web/yoursubmissions.py +++ b/modules/websubmit/web/yoursubmissions.py @@ -1,216 +1,218 @@ ## $Id$ ## This file is part of CDS Invenio. ## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN. ## ## CDS Invenio 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. ## ## CDS Invenio 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 CDS Invenio; if not, write to the Free Software Foundation, Inc., ## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. __revision__ = "$Id$" ## import interesting modules: import string import os import sys import time import types import re import shutil import operator from invenio.config import \ CFG_ACCESS_CONTROL_LEVEL_SITE, \ cdslang, \ cdsname, \ images, \ storage, \ sweburl, \ version, \ weburl from invenio.dbquery import run_sql, Error from invenio.access_control_engine import acc_authorize_action from invenio.access_control_admin import * from invenio.webpage import page, create_error_box from invenio.webuser import getUid, get_email, list_registered_users, page_not_authorized from invenio.messages import gettext_set_language, wash_language from invenio.websubmit_config import * from invenio.search_engine import search_pattern import invenio.template websubmit_templates = invenio.template.load('websubmit') def index(req,c=cdsname,ln=cdslang,order="",doctype="",deletedId="",deletedAction="",deletedDoctype=""): global uid ln = wash_language(ln) # load the right message language _ = gettext_set_language(ln) t="" # get user ID: try: uid = getUid(req) if uid == -1 or CFG_ACCESS_CONTROL_LEVEL_SITE >= 1: return page_not_authorized(req, "../yoursubmissions.py/index", navmenuid='yoursubmissions') u_email = get_email(uid) except Error, e: return errorMsg(e.value, req, ln) if u_email == "guest" or u_email == "": return warningMsg(websubmit_templates.tmpl_warning_message( ln = ln, msg = _("Sorry, you must log in to perform this action."), ),req, ln = ln) if deletedId != "": t += deleteSubmission(deletedId,deletedAction,deletedDoctype,u_email) # doctypes res = run_sql("select ldocname,sdocname from sbmDOCTYPE order by ldocname") doctypes = [] for row in res: doctypes.append({ 'id' : row[1], 'name' : row[0], 'selected' : (doctype == row[1]), }) # submissions # request order default value reqorder = "sbmSUBMISSIONS.md DESC, lactname" # requested value if order == "actiondown": reqorder = "lactname ASC, sbmSUBMISSIONS.md DESC" elif order == "actionup": reqorder = "lactname DESC, sbmSUBMISSIONS.md DESC" elif order == "refdown": reqorder = "reference ASC, sbmSUBMISSIONS.md DESC, lactname DESC" elif order == "refup": reqorder = "reference DESC, sbmSUBMISSIONS.md DESC, lactname DESC" elif order == "cddown": reqorder = "sbmSUBMISSIONS.cd DESC, lactname" elif order == "cdup": reqorder = "sbmSUBMISSIONS.cd ASC, lactname" elif order == "mddown": reqorder = "sbmSUBMISSIONS.md DESC, lactname" elif order == "mdup": reqorder = "sbmSUBMISSIONS.md ASC, lactname" elif order == "statusdown": reqorder = "sbmSUBMISSIONS.status DESC, lactname" elif order == "statusup": reqorder = "sbmSUBMISSIONS.status ASC, lactname" if doctype != "": docselect = " and doctype='%s' " % doctype else: docselect = "" res = run_sql("SELECT sbmSUBMISSIONS.* FROM sbmSUBMISSIONS,sbmACTION WHERE sactname=action and email=%s and id!='' "+docselect+" ORDER BY doctype,"+reqorder,(u_email,)) currentdoctype = "" currentaction = "" currentstatus = "" submissions = [] for row in res: if currentdoctype != row[1]: currentdoctype = row[1] currentaction = "" currentstatus = "" res2 = run_sql("SELECT ldocname FROM sbmDOCTYPE WHERE sdocname=%s",(currentdoctype,)) if res2: ldocname = res2[0][0] else: ldocname = """***Unknown Document Type - (%s)""" % (currentdoctype,) if currentaction != row[2]: currentaction = row[2] res2 = run_sql("SELECT lactname FROM sbmACTION WHERE sactname=%s",(currentaction,)) if res2: lactname = res2[0][0] else: lactname = "\"" else: lactname = "\"" if currentstatus != row[3]: currentstatus = row[3] status=row[3] else: status = "\"" submissions.append({ 'docname' : ldocname, 'actname' : lactname, 'status' : status, 'cdate' : row[6], 'mdate' : row[7], 'reference' : row[5], 'id' : row[4], 'act' : currentaction, 'doctype' : currentdoctype, 'pending' : (row[3] == "pending") }) # display t += websubmit_templates.tmpl_yoursubmissions( ln = ln, weburl = weburl, images = images, order = order, doctypes = doctypes, submissions = submissions, ) return page(title=_("Your Submissions"), navtrail= """<a class="navtrail" href="%(sweburl)s/youraccount/display">%(account)s</a>""" % { 'sweburl' : sweburl, 'account' : _("Your Account"), }, body=t, description="", keywords="", uid=uid, language=ln, req=req, navmenuid='yoursubmissions') def deleteSubmission(id, action, doctype, u_email): global storage run_sql("delete from sbmSUBMISSIONS WHERE doctype=%s and action=%s and email=%s and status='pending' and id=%s",(doctype,action,u_email,id,)) res = run_sql("select dir from sbmACTION where sactname=%s",(action,)) dir = res[0][0] if not ('..' in doctype or '..' in id) and id != "": full = os.path.join(storage, dir, doctype, id) if os.path.isdir(full): shutil.rmtree(full) return "" def warningMsg(title,req,c=cdsname,ln=cdslang): return page(title="warning", body = title, description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='yoursubmissions') def errorMsg(title,req,c=cdsname,ln=cdslang): return page(title="error", body = create_error_box(req, title=title,verbose=0, ln=ln), description="%s - Internal Error" % c, keywords="%s, Internal Error" % c, + uid = getUid(req), language=ln, req=req, navmenuid='yoursubmissions')