def worksheet_cell_list(worksheet): """ Return a list of cells in JSON format. """ r = {} r['state_number'] = worksheet.state_number() r['cell_list'] = [c.basic() for c in worksheet.cell_list()] return encode_response(r)
def worksheet_delete_cell_output(worksheet): """Delete's a cell's output.""" r = {} r['id'] = id = get_cell_id() worksheet.get_cell_with_id(id).delete_output() r['command'] = 'delete_output' return encode_response(r)
def worksheet_cell_list(worksheet): """ Return a list of cells in JSON format. """ r = {} r["state_number"] = worksheet.state_number() r["cell_list"] = [c.basic() for c in worksheet.cell_list()] return encode_response(r)
def worksheet_delete_cell_output(worksheet): """Delete's a cell's output.""" r = {} r["id"] = id = get_cell_id() worksheet.get_cell_with_id(id).delete_output() r["command"] = "delete_output" return encode_response(r)
def worksheet_delete_cell_output(worksheet): """Delete's a cell's output.""" r = {} r['id'] = id = get_cell_id() worksheet.get_cell_with_id(id).delete_output() r['command'] = 'delete_output' from sagenb.notebook.misc import encode_response return encode_response(r)
def suspend_user(): user = request.values['username'] try: U = g.notebook.user_manager().user(user) U.set_suspension() except KeyError: pass return encode_response({ 'message': _('User <strong>%(username)s</strong> has been suspended/unsuspended.', username=user) })
def worksheet_introspect(worksheet): """ Cell introspection. This is called when the user presses the tab key in the browser in order to introspect. """ r = {} r['id'] = id = get_cell_id() if worksheet.tags().get('_pub_', [False])[0]: #tags set in pub_worksheet r['command'] = 'error' r['message'] = 'Cannot evaluate public cell introspection.' return encode_response(r) before_cursor = request.values.get('before_cursor', '') after_cursor = request.values.get('after_cursor', '') cell = worksheet.get_cell_with_id(id) cell.evaluate(introspect=[before_cursor, after_cursor]) r['command'] = 'introspect' return encode_response(r)
def worksheet_introspect(worksheet): """ Cell introspection. This is called when the user presses the tab key in the browser in order to introspect. """ r = {} r["id"] = id = get_cell_id() if worksheet.tags().get("_pub_", [False])[0]: # tags set in pub_worksheet r["command"] = "error" r["message"] = "Cannot evaluate public cell introspection." return encode_response(r) before_cursor = request.values.get("before_cursor", "") after_cursor = request.values.get("after_cursor", "") cell = worksheet.get_cell_with_id(id) cell.evaluate(introspect=[before_cursor, after_cursor]) r["command"] = "introspect" return encode_response(r)
def worksheet_new_cell_before(self, worksheet): """Add a new cell before a given cell.""" r = {} r['id'] = id = self.get_cell_id() input = unicode_str(self.request_values.get('input', '')) cell = worksheet.new_cell_before(id, input=input) worksheet.increase_state_number() r['new_id'] = cell.id() #r['new_html'] = cell.html(div_wrap=False) return encode_response(r)
def worksheet_cell_list(worksheet): """ Return the state number and the HTML for the main body of the worksheet, which consists of a list of cells. """ r = {} r['state_number'] = worksheet.state_number() # TODO: Send and actually use the body's HTML. r['html_cell_list'] = '' #r['html_cell_list'] = W.html_cell_list() return encode_response(r)
def add_user(): from sagenb.notebook.misc import is_valid_username username = request.values['username'] password = random_password() if not is_valid_username(username): return encode_response({ 'error': _('<strong>Invalid username!</strong>') }) if username in g.notebook.user_manager().usernames(): return encode_response({ 'error': _('The username <strong>%(username)s</strong> is already taken!', username=username) }) g.notebook.user_manager().add_user(username, password, '', force=True) return encode_response({ 'message': _('The temporary password for the new user <strong>%(username)s</strong> is <strong>%(password)s</strong>', username=username, password=password) })
def worksheet_new_cell_before(worksheet): """Add a new cell before a given cell.""" r = {} r["id"] = id = get_cell_id() input = unicode_str(request.values.get("input", "")) cell = worksheet.new_cell_before(id, input=input) worksheet.increase_state_number() r["new_id"] = cell.id() # r['new_html'] = cell.html(div_wrap=False) return encode_response(r)
def worksheet_new_cell_after(worksheet): """Add a new cell after a given cell.""" r = {} r['id'] = id = get_cell_id() input = unicode_str(request.values.get('input', '')) cell = worksheet.new_cell_after(id, input=input) worksheet.increase_state_number() r['new_id'] = cell.id() r['new_html'] = cell.html(div_wrap=True) return encode_response(r)
def worksheet_new_cell_before(worksheet): """Add a new cell before a given cell.""" r = {} r['id'] = id = get_cell_id() input = unicode_str(request.values.get('input', '')) cell = worksheet.new_cell_before(id, input=input) worksheet.increase_state_number() r['new_id'] = cell.id() r['new_html'] = cell.html(div_wrap=False) from sagenb.notebook.misc import encode_response return encode_response(r)
def reset_user_password(): user = request.values['username'] password = random_password() try: # U = g.notebook.user_manager().user(user) g.notebook.user_manager().set_password(user, password) except KeyError: pass return encode_response({ 'message': _('The temporary password for the new user <strong>%(username)s</strong> is <strong>%(password)s</strong>', username=user, password=password) })
def worksheet_list(): """ Returns a worksheet listing. INPUT: - ``args`` - ctx.args where ctx is the dict passed into a resource's render method - ``pub`` - boolean, True if this is a listing of public worksheets - ``username`` - the user whose worksheets we are listing OUTPUT: a string """ from sagenb.notebook.notebook import sort_worksheet_list from sagenb.misc.misc import unicode_str, SAGE_VERSION from sagenb.notebook.misc import encode_response r = {} pub = 'pub' in request.args readonly = g.notebook.readonly_user(g.username) typ = request.args['type'] if 'type' in request.args else 'active' search = unicode_str(request.args['search']) if 'search' in request.args else None sort = request.args['sort'] if 'sort' in request.args else 'last_edited' reverse = (request.args['reverse'] == 'True') if 'reverse' in request.args else False try: if not pub: r['worksheets'] = [x.basic() for x in g.notebook.worksheet_list_for_user(g.username, typ=typ, sort=sort, search=search, reverse=reverse)] else: r['worksheets'] = [x.basic() for x in g.notebook.worksheet_list_for_public(g.username, sort=sort, search=search, reverse=reverse)] except ValueError as E: # for example, the sort key was not valid print "Error displaying worksheet listing: ", E return current_app.message(_("Error displaying worksheet listing.")) #if pub and (not g.username or g.username == tuple([])): # r['username'] = '******' r['accounts'] = g.notebook.user_manager().get_accounts() r['sage_version'] = SAGE_VERSION # r['pub'] = pub return encode_response(r)
def worksheet_new_text_cell_after(worksheet): """Add a new text cell after a given cell.""" r = {} r['id'] = id = get_cell_id() input = unicode_str(request.values.get('input', '')) cell = worksheet.new_text_cell_after(id, input=input) worksheet.increase_state_number() r['new_id'] = cell.id() r['new_html'] = cell.html(editing=True) # XXX: Does editing correspond to TinyMCE? If so, we should try # to centralize that code. return encode_response(r)
def worksheet_properties(self, worksheet): """ Send worksheet properties as a JSON object """ r = worksheet.basic() if worksheet.has_published_version(): hostname = request.headers.get('host', self.notebook.interface + ':' + str(self.notebook.port)) r['published_url'] = 'http%s://%s/home/%s' % ('' if not self.notebook.secure else 's', hostname, worksheet.published_version().filename()) return encode_response(r)
def add_user(): from sagenb.notebook.misc import is_valid_username username = request.values['username'] password = random_password() if not is_valid_username(username): return encode_response( {'error': _('<strong>Invalid username!</strong>')}) if username in g.notebook.user_manager().usernames(): return encode_response({ 'error': _('The username <strong>%(username)s</strong> is already taken!', username=username) }) g.notebook.user_manager().add_user(username, password, '', force=True) return encode_response({ 'message': _('The temporary password for the new user <strong>%(username)s</strong> is <strong>%(password)s</strong>', username=username, password=password) })
def worksheet_delete_cell(worksheet): """ Deletes a worksheet cell, unless there's only one compute cell left. This allows functions which evaluate relative to existing cells, e.g., inserting a new cell, to continue to work. """ r = {} r['id'] = id = get_cell_id() if len(worksheet.compute_cell_id_list()) <= 1: r['command'] = 'ignore' else: r['command'] = 'delete' r['prev_id'] = worksheet.delete_cell_with_id(id) r['cell_id_list'] = worksheet.cell_id_list() return encode_response(r)
def worksheet_cell_update(worksheet): import time from sagenb.notebook.misc import encode_response r = {} r['id'] = id = get_cell_id() # update the computation one "step". worksheet.check_comp() # now get latest status on our cell r['status'], cell = worksheet.check_cell(id) if r['status'] == 'd': r['new_input'] = cell.changed_input_text() r['output_html'] = cell.output_html() # Update the log. t = time.strftime('%Y-%m-%d at %H:%M', time.localtime(time.time())) H = "Worksheet '%s' (%s)\n" % (worksheet.name(), t) H += cell.edit_text(ncols=g.notebook.HISTORY_NCOLS, prompts=False, max_out=g.notebook.HISTORY_MAX_OUTPUT) g.notebook.add_to_user_history(H, g.username) else: r['new_input'] = '' r['output_html'] = '' if cell.interrupted(): r['interrupted'] = 'true' else: r['interrupted'] = 'false' if 'Unhandled SIGSEGV' in cell.output_text(raw=True).split('\n'): r['interrupted'] = 'restart' print 'Segmentation fault detected in output!' r['output'] = cell.output_text(html=True) + ' ' r['output_wrapped'] = cell.output_text(g.notebook.conf()['word_wrap_cols'], html=True) + ' ' r['introspect_html'] = cell.introspect_html() # Compute 'em, if we got 'em. worksheet.start_next_comp() return encode_response(r)
def worksheet_delete_cell(worksheet): """ Deletes a worksheet cell, unless there's only one compute cell left. This allows functions which evaluate relative to existing cells, e.g., inserting a new cell, to continue to work. """ r = {} r['id'] = id = get_cell_id() if len(worksheet.compute_cell_id_list()) <= 1: r['command'] = 'ignore' else: prev_id = worksheet.delete_cell_with_id(id) r['command'] = 'delete' r['prev_id'] = worksheet.delete_cell_with_id(id) r['cell_id_list'] = worksheet.cell_id_list() return encode_response(r)
def worksheet_cell_update(worksheet): import time r = {} r['id'] = id = get_cell_id() # update the computation one "step". worksheet.check_comp() # now get latest status on our cell r['status'], cell = worksheet.check_cell(id) if r['status'] == 'd': r['new_input'] = cell.changed_input_text() r['output_html'] = cell.output_html() # Update the log. t = time.strftime('%Y-%m-%d at %H:%M', time.localtime(time.time())) H = "Worksheet '%s' (%s)\n" % (worksheet.name(), t) H += cell.edit_text(ncols=g.notebook.HISTORY_NCOLS, prompts=False, max_out=g.notebook.HISTORY_MAX_OUTPUT) g.notebook.add_to_user_history(H, g.username) else: r['new_input'] = '' r['output_html'] = '' if cell.interrupted(): r['interrupted'] = 'true' else: r['interrupted'] = 'false' if 'Unhandled SIGSEGV' in cell.output_text(raw=True).split('\n'): r['interrupted'] = 'restart' print 'Segmentation fault detected in output!' r['output'] = cell.output_text(html=True) + ' ' r['output_wrapped'] = cell.output_text(g.notebook.conf()['word_wrap_cols'], html=True) + ' ' r['introspect_html'] = cell.introspect_html() # Compute 'em, if we got 'em. worksheet.start_next_comp() return encode_response(r)
def worksheet_properties(worksheet): """ Send worksheet properties as a JSON object """ from sagenb.notebook.misc import encode_response r = worksheet.basic() if worksheet.has_published_version(): hostname = request.headers.get( 'host', g.notebook.interface + ':' + str(g.notebook.port)) r['published_url'] = 'http%s://%s/home/%s' % ( '' if not g.notebook.secure else 's', hostname, worksheet.published_version().filename()) return encode_response(r)
def worksheet_properties(worksheet): """ Send worksheet properties as a JSON object """ from sagenb.notebook.misc import encode_response r = worksheet.basic() if worksheet.has_published_version(): hostname = request.headers.get("host", g.notebook.interface + ":" + str(g.notebook.port)) r["published_url"] = "http%s://%s/home/%s" % ( "" if not g.notebook.secure else "s", hostname, worksheet.published_version().filename(), ) return encode_response(r)
def worksheet_cell_update(worksheet): import time r = {} r["id"] = id = get_cell_id() # update the computation one "step". worksheet.check_comp() # now get latest status on our cell r["status"], cell = worksheet.check_cell(id) if r["status"] == "d": r["new_input"] = cell.changed_input_text() r["output_html"] = cell.output_html() # Update the log. t = time.strftime("%Y-%m-%d at %H:%M", time.localtime(time.time())) H = "Worksheet '%s' (%s)\n" % (worksheet.name(), t) H += cell.edit_text(ncols=g.notebook.HISTORY_NCOLS, prompts=False, max_out=g.notebook.HISTORY_MAX_OUTPUT) g.notebook.add_to_user_history(H, g.username) else: r["new_input"] = "" r["output_html"] = "" r["interrupted"] = cell.interrupted() if "Unhandled SIGSEGV" in cell.output_text(raw=True).split("\n"): r["interrupted"] = "restart" print "Segmentation fault detected in output!" r["output"] = cell.output_text(html=True) r["output_wrapped"] = cell.output_text(g.notebook.conf()["word_wrap_cols"]) r["introspect_output"] = cell.introspect_output() # Compute 'em, if we got 'em. worksheet.start_next_comp() return encode_response(r)
def worksheet_eval(worksheet): """ Evaluate a worksheet cell. If the request is not authorized (the requester did not enter the correct password for the given worksheet), then the request to evaluate or introspect the cell is ignored. If the cell contains either 1 or 2 question marks at the end (not on a comment line), then this is interpreted as a request for either introspection to the documentation of the function, or the documentation of the function and the source code of the function respectively. """ from base import notebook_updates r = {} r['id'] = id = get_cell_id() cell = worksheet.get_cell_with_id(id) public = worksheet.tags().get('_pub_', [False])[0] #this is set in pub_worksheet if public and not cell.is_interactive_cell(): r['command'] = 'error' r['message'] = 'Cannot evaluate non-interactive public cell with ID %r.' % id return encode_response(r) worksheet.increase_state_number() if public: # Make public input cells read-only. input_text = cell.input_text() else: input_text = unicode_str(request.values.get('input', '')).replace('\r\n', '\n') #DOS # Handle an updated / recomputed interact. TODO: JSON encode # the update data. if 'interact' in request.values: r['interact'] = 1 input_text = INTERACT_UPDATE_PREFIX variable = request.values.get('variable', '') if variable!='': adapt_number = int(request.values.get('adapt_number', -1)) value = request.values.get('value', '') input_text += "\n_interact_.update('%s', '%s', %s, _interact_.standard_b64decode('%s'), globals())" % (id, variable, adapt_number, value) if int(request.values.get('recompute', 0)): input_text += "\n_interact_.recompute('%s')" % id cell.set_input_text(input_text) if int(request.values.get('save_only', '0')): notebook_updates() return encode_response(r) elif int(request.values.get('text_only', '0')): notebook_updates() r['cell_html'] = cell.html() return encode_response(r) cell.evaluate(username=g.username) new_cell = int(request.values.get('newcell', 0)) #whether to insert a new cell or not if new_cell: new_cell = worksheet.new_cell_after(id) r['command'] = 'insert_cell' r['new_cell_id'] = new_cell.id() r['new_cell_html'] = new_cell.html(div_wrap=False) else: r['next_id'] = cell.next_compute_id() notebook_updates() return encode_response(r)
def handle_feedback(): userdata = request.get_json(silent=True) # spamschutz vor Bots, die github durchlesen: domain = "."+".".join("de uni-frankfurt physik".split(" ")[::-1]) from_addr = ("POKAL-Feedback", "*****@*****.**") to_addrs = [ ("eLearning", "elearning@th%s" % domain), ("POTT", "pott@elearning%s" % domain), ] subject = "POKAL Feedback" # Force python to encode utf-8 as quoted-printable and not base64 # (both subject and body). unfortunately this modifies a global setting, # but email sending in POKAL is not such a popular task yet. Charset.add_charset('utf-8', Charset.QP, Charset.QP, 'utf-8') if userdata: # could correctly parse userdata output = {'status': 'JSON could be retrieved'} output['userdata'] = userdata status = 200 # OK msg = MIMEMultipart() msg['From'] = formataddr(from_addr) msg['To'] = ", ".join(map(formataddr,to_addrs)) msg['Date'] = formatdate(localtime=True) msg['Subject'] = subject msg['Content-Type'] = 'text/html; charset=utf-8' body = u""" Ein neuer POKAL-Feedback ist durch das Feedbacksystem (#984) eingereicht worden. == Vom Besucher ausgefüllter Text == $note == Screenshot == [[Image($screenshot_filename, width=100%)]] == Daten == URL des Worksheets:: $url Name (Titel) des Worksheets:: ''$worksheet_name'' HRZ-Username des Benutzers:: `$username` Nickname des Benutzers:: `$nickname` Browser des Benutzers (User Agent):: `$HTTP_USER_AGENT` IP-Adresse des Besuchers:: `HTTP_X_FORWARDED_FOR = $HTTP_X_FORWARDED_FOR` Verarbeitender POKAL-Server:: `SERVER_NAME:... = $SERVER_NAME:$SERVER_PORT` Zwischenpunkt (Remote IP des bearbeitenden Pokal-Servers):: `REMOTE_ADDR = $REMOTE_ADDR` Endpunkt POKAL-Host:: `HTTP_HOST = $HTTP_HOST` Uhrzeit:: $date Anzahl Benutzer im Chat:: $chat_nicknames_count Anzahl Chatzeilen:: $chat_messages_count Länge Worksheet (Anzahl Worksheet-Zellen):: $cells_count @type: Designen @component: POKAL @keywords: pokal, feedback @sensitive: 1 """ # look at the image if "img" in userdata: screenshot_filename = "screenshot-%s.png" % str(uuid4())[:6] binaryimg = unpack_html2image_screenshot(userdata["img"]) img_part = MIMEImage(binaryimg) img_part.set_param('name', screenshot_filename) img_part.add_header('Content-Disposition', 'attachment; filename="%s"' % screenshot_filename) else: screenshot_filename = "<no screenshot present>" # enrich the data with classical CGI ENV vars serverdata = request.environ # further data furtherdata = { "screenshot_filename": screenshot_filename, "date": datetime.now().strftime("%c") } # userdata are overwritten by serverdata replace_data = dict(userdata.items() + serverdata.items() + furtherdata.items()) body = Template(body).safe_substitute(replace_data) # make sure of a quoted printable body msg.attach( MIMEText(body.encode('utf-8'), 'plain', 'utf-8') ) # format the image attachment msg.attach(img_part) # consider also the HTML attachments for key in ["cells", "chat_messages"]: if not key in userdata: continue text_part = MIMEText(userdata[key], "text/html", "utf-8") text_part.set_param('name', key+".html") text_part.add_header('Content-Disposition', 'attachment; filename="%s.html"' % key) msg.attach(text_part) try: smtp = smtplib.SMTP('localhost') smtp.sendmail( emailaddr(from_addr), map(emailaddr, to_addrs), msg.as_string() ) smtp.close() output['status'] = 'Feedback mail successfully sent.' except smtplib.SMTPException as e: output['status'] = 'Error sending mail: '+str(e) status = 502 # bad mail else: # could not parse userdata, or error, or not given output = {'status': 'Error: Please POST valid JSON feedback data.'} status = 400 # bad request # um auf POST-Argumente zuzugreifen: # request.form.get('key') res = make_response(encode_response(output)) res.headers['Content-Type'] = 'application/json' return res, status
def worksheet_list(): """ Returns a worksheet listing. INPUT: - ``args`` - ctx.args where ctx is the dict passed into a resource's render method - ``pub`` - boolean, True if this is a listing of public worksheets - ``username`` - the user whose worksheets we are listing OUTPUT: a string """ from sagenb.notebook.notebook import sort_worksheet_list from sagenb.misc.misc import unicode_str, SAGE_VERSION from sagenb.notebook.misc import encode_response import re r = {} pub = 'pub' in request.args readonly = g.notebook.readonly_user(g.username) typ = request.args['type'] if 'type' in request.args else 'active' search = unicode_str(request.args['search']) if 'search' in request.args else None # Support for the 'tag:' and 'tags:' keyword tags = [] option = '' if search != None: strs = search.split() singletags = [s[4:] for s in strs if s.startswith('tag:')] multitags = [s[5:].split(',') for s in strs if s.startswith('tags:')] tags = singletags + [tag for m in multitags for tag in m] option = [s[7:] for s in strs if s.startswith('option:')] if len(option) > 0 and (option[0] in ['published']): #currently only one option allowed option = option[0] search = " ".join([s for s in strs if not s.startswith('tag:') and not s.startswith('tags:') and not s.startswith('option:')]) sort = request.args['sort'] if 'sort' in request.args else 'last_edited' reverse = (request.args['reverse'] == 'True') if 'reverse' in request.args else False try: if not pub: WList = [x for x in g.notebook.worksheet_list_for_user(g.username, typ=typ, sort=sort, search=search, reverse=reverse)] r['worksheets'] = [] for W in WList: if not option or any([option == 'published' and W.has_published_version()]): try: if tags==[] or all([t in W.pokaltags()[g.username] for t in tags]): d = W.basic() d.update({'owner_nickname': g.notebook.user_manager().user(W.owner()).get_nickname()}) temp = W.basic()['collaborators'] d.update({'collaborators_nicknames':[g.notebook.user_manager().user(x).get_nickname() for x in temp]}) r['worksheets'].append(d) except KeyError: pass else: return current_app.message(_("Public listing is not supported.")) except ValueError as E: # for example, the sort key was not valid print "Error displaying worksheet listing: ", E return current_app.message(_("Error displaying worksheet listing.")) #if pub and (not g.username or g.username == tuple([])): # r['username'] = '******' r['accounts'] = g.notebook.user_manager().get_accounts() r['sage_version'] = SAGE_VERSION # r['pub'] = pub return encode_response(r)
def worksheet_eval(worksheet): """ Evaluate a worksheet cell. If the request is not authorized (the requester did not enter the correct password for the given worksheet), then the request to evaluate or introspect the cell is ignored. If the cell contains either 1 or 2 question marks at the end (not on a comment line), then this is interpreted as a request for either introspection to the documentation of the function, or the documentation of the function and the source code of the function respectively. """ from .base import notebook_updates r = {} r['id'] = id = get_cell_id() cell = worksheet.get_cell_with_id(id) public = worksheet.tags().get('_pub_', [False])[0] #this is set in pub_worksheet if public and not cell.is_interactive_cell(): r['command'] = 'error' r['message'] = 'Cannot evaluate non-interactive public cell with ID %r.' % id return encode_response(r) worksheet.increase_state_number() if public: # Make public input cells read-only. input_text = cell.input_text() else: input_text = unicode_str(request.values.get('input', '')).replace('\r\n', '\n') #DOS # Handle an updated / recomputed interact. TODO: JSON encode # the update data. if 'interact' in request.values: r['interact'] = 1 input_text = INTERACT_UPDATE_PREFIX variable = request.values.get('variable', '') if variable != '': adapt_number = int(request.values.get('adapt_number', -1)) value = request.values.get('value', '') input_text += "\n_interact_.update('%s', '%s', %s, _interact_.standard_b64decode('%s'), globals())" % ( id, variable, adapt_number, value) if int(request.values.get('recompute', 0)): input_text += "\n_interact_.recompute('%s')" % id cell.set_input_text(input_text) if int(request.values.get('save_only', '0')): notebook_updates() return encode_response(r) elif int(request.values.get('text_only', '0')): notebook_updates() r['cell_html'] = cell.html() return encode_response(r) cell.evaluate(username=g.username) new_cell = int(request.values.get('newcell', 0)) #whether to insert a new cell or not if new_cell: new_cell = worksheet.new_cell_after(id) r['command'] = 'insert_cell' r['new_cell_id'] = new_cell.id() r['new_cell_html'] = new_cell.html(div_wrap=False) else: r['next_id'] = cell.next_compute_id() notebook_updates() return encode_response(r)
def worksheet_cell_properties(worksheet): """ Return the cell with the given id as a JSON object """ id = get_cell_id() return encode_response(worksheet.get_cell_with_id(id).basic())