def receive_packet(self, data): data = data[:-len(self.endseq)] term_info = TerminalClient.all_cookies.get(self.cookie) if not term_info: return self.shutdown() host_connection, term_name = term_info headers, content = lineterm.parse_headers(data) if headers["x_gterm_response"] == "capture_feedback": feedback = headers["x_gterm_parameters"].get("cookie") if feedback and feedback.isdigit() and feedback in TerminalClient.all_cookies: self.set_feedback_status(feedback) else: logging.warning("gtermhost: Invalid feedback cookie %s", feedback) elif headers["x_gterm_response"] == "create_blob": blob_id = headers["x_gterm_parameters"].get("blob_id") if not blob_id: logging.warning("gtermhost: No id for blob creation") elif "content_length" not in headers: logging.warning("gtermhost: No content_length specified for create_blob") else: host_connection.blob_cache.add_blob(blob_id, headers, content) else: params = {"validated": True, "headers": headers} host_connection.send_request_threadsafe("response", term_name, [["terminal", "graphterm_widget", [params, base64.b64encode(content) if content else ""]]]) self.cookie = None self.next_packet()
def receive_packet(self, data): data = data[:-len(self.endseq)] term_info = TerminalClient.all_cookies.get(self.cookie) if not term_info: return self.shutdown() host_connection, term_name = term_info headers, content = lineterm.parse_headers(data) if headers["x_gterm_response"] == "capture_feedback": feedback = headers["x_gterm_parameters"].get("cookie") if feedback and feedback.isdigit() and feedback in TerminalClient.all_cookies: self.set_feedback_status(feedback) else: logging.warning("gtermhost: Invalid feedback cookie %s", feedback) elif headers["x_gterm_response"] == "create_blob": blob_id = headers["x_gterm_parameters"].get("blob_id") if not blob_id: logging.warning("gtermhost: No id for blob creation") elif "content_length" not in headers: logging.warning("gtermhost: No content_length specified for create_blob") else: host_connection.blob_cache.add_blob(blob_id, headers, content) else: params = {"validated": True, "headers": headers} host_connection.send_request_threadsafe("response", term_name, "", [["terminal", "graphterm_widget", [params, base64.b64encode(content) if content else ""]]]) self.cookie = None self.next_packet()
def receive_packet(self, data): data = data[:-len(self.endseq)] term_info = TerminalClient.all_cookies.get(self.packet_cookie) if not term_info: return self.shutdown() host_connection, term_name = term_info headers, content = lineterm.parse_headers(data) resp_type = headers["x_gterm_response"] if resp_type == "capture_chat": chat_cookie = headers["x_gterm_parameters"].get("cookie") widget_token = headers["x_gterm_parameters"].get( "widget_token", "") if chat_cookie == self.packet_cookie: # Redundant? prev_widget = self.get_chat_widget(chat_cookie) if prev_widget and prev_widget is not self: # Only one active chat widget per terminal at a time prev_widget.shutdown() self.chat_cookie = chat_cookie self._chat_widgets[chat_cookie] = self self.set_chat_status(True, widget_token) else: logging.warning("Invalid chat cookie %s", chat_cookie) elif resp_type == "create_blob": blob_id = headers["x_gterm_parameters"].get("blob_id") if not blob_id: logging.warning("No id for blob creation") elif "content_length" not in headers: logging.warning("No content_length specified for create_blob") else: host_connection.blob_cache.add_blob(blob_id, headers, content) else: params = {"validated": True, "headers": headers} args = [params, base64.b64encode(content) if content else ""] if not resp_type or resp_type == "pagelet": # HTML pagelet widget prev_widget = self.get_pagelet_widget(self.packet_cookie) if prev_widget and prev_widget is not self: # Only one active pagelet widget per terminal at a time prev_widget.shutdown() self._pagelet_widgets[self.packet_cookie] = self self.last_pagelet_args = args self.send_widget_content(*args) self.packet_cookie = "" self.next_packet()
def receive_packet(self, data): data = data[:-len(self.endseq)] term_info = TerminalClient.all_cookies.get(self.packet_cookie) if not term_info: return self.shutdown() host_connection, term_name = term_info headers, content = lineterm.parse_headers(data) resp_type = headers["x_gterm_response"] if resp_type == "capture_chat": chat_cookie = headers["x_gterm_parameters"].get("cookie") widget_token = headers["x_gterm_parameters"].get("widget_token", "") if chat_cookie == self.packet_cookie: # Redundant? prev_widget = self.get_chat_widget(chat_cookie) if prev_widget and prev_widget is not self: # Only one active chat widget per terminal at a time prev_widget.shutdown() self.chat_cookie = chat_cookie self._chat_widgets[chat_cookie] = self self.set_chat_status(True, widget_token) else: logging.warning("Invalid chat cookie %s", chat_cookie) elif resp_type == "create_blob": blob_id = headers["x_gterm_parameters"].get("blob_id") if not blob_id: logging.warning("No id for blob creation") elif "content_length" not in headers: logging.warning("No content_length specified for create_blob") else: host_connection.blob_cache.add_blob(blob_id, headers, content) else: params = {"validated": True, "headers": headers} args = [params, base64.b64encode(content) if content else ""] if not resp_type or resp_type == "pagelet": # HTML pagelet widget prev_widget = self.get_pagelet_widget(self.packet_cookie) if prev_widget and prev_widget is not self: # Only one active pagelet widget per terminal at a time prev_widget.shutdown() self._pagelet_widgets[self.packet_cookie] = self self.last_pagelet_args = args self.send_widget_content(*args) self.packet_cookie = "" self.next_packet()
def remote_request(self, term_name, req_list): """ Setup commands: reconnect Input commands: incomplete_input <line> input <line> click_paste <text> <file_url> {command:, clear_last:, normalize:, enter:} paste_command <text> get_finder <kind> <directory> save_file <filepath> <filedata> Output commands: completed_input <line> prompt <str> stdin <str> stdout <str> stderr <str> """ try: lterm_cookie = self.terms.get(term_name) resp_list = [] for cmd in req_list: action = cmd.pop(0) if action == "shutdown": if cmd: logging.warning("gtermhost: SHUTDOWN %s", cmd[0]) self.shutdown() elif action == "reconnect": if self.lineterm: self.lineterm.reconnect(term_name, cmd[0]) elif action == "set_size": if term_name != OSHELL_NAME: self.xterm(term_name, cmd[0][0], cmd[0][1]) elif action == "kill_term": self.remove_term(term_name) elif action == "clear_term": if self.lineterm: self.lineterm.clear(term_name) elif action == "export_environment": if self.lineterm: self.lineterm.export_environment(term_name) elif action == "keypress": if self.lineterm: self.lineterm.term_write(term_name, cmd[0].encode(self.term_encoding, "ignore")) elif action == "feedback": widget_stream = WidgetStream.get_feedback_connection(lterm_cookie) if widget_stream: widget_stream.send_packet(cmd[0].encode(self.term_encoding, "ignore")) elif action == "save_file": if self.lineterm: self.lineterm.save_file(term_name, cmd[0], cmd[1]) elif action == "click_paste": # click_paste: text, file_url, {command:, clear_last:, normalize:, enter:} if self.lineterm: paste_text = self.lineterm.click_paste(term_name, cmd[0], cmd[1], cmd[2]) self.paste_command(term_name, paste_text) elif action == "paste_command": # paste_command: command_line self.paste_command(term_name, cmd[0]) elif action == "clear_last_entry": if self.lineterm: self.lineterm.clear_last_entry(term_name, long(cmd[0])) elif action == "get_finder": if self.lineterm: self.lineterm.get_finder(term_name, cmd[0], cmd[1]) elif action == "incomplete_input": cmd_incomplete = cmd[0].encode("ascii", "ignore") dummy, sep, text = cmd_incomplete.rpartition(" ") options = otrace.OShell.instance.completer(text, 0, line=cmd_incomplete, all=True) if text: options = [cmd_incomplete[:-len(text)]+option for option in options] else: options = [cmd_incomplete+option for option in options] resp_list.append(["completed_input", options]) # Not escaped; handle as text elif action == "input": cmd_input = cmd[0].encode("ascii", "ignore").lstrip() # Unescaped text here_doc = base64.b64decode(cmd[1]) if cmd[1] else cmd[1] entry_list = [] if cmd_input == "cat episode4.txt": # Easter egg std_out, std_err = Episode4, "" else: std_out, std_err = otrace.OShell.instance.execute(cmd_input, here_doc=here_doc) resp_list.append(["input", cmd[0]]) # Not escaped; handle as text prompt, cur_dir_path = otrace.OShell.instance.get_prompt() resp_list.append(["prompt", cgi.escape(prompt), "file://"+urllib.quote(cur_dir_path)]) auth_html = False if lterm_cookie and std_out.startswith(HTML_ESCAPES[0]): auth_prefix = HTML_ESCAPES[0]+lterm_cookie+HTML_ESCAPES[1] auth_html = std_out.startswith(auth_prefix) if auth_html: offset = len(auth_prefix) else: # Unauthenticated html offset = std_out.find(HTML_ESCAPES[1])+len(HTML_ESCAPES[1]) if std_out.endswith(HTML_ESCAPES[-1]): html_output = std_out[offset:-len(HTML_ESCAPES[-1])] elif std_out.endswith(HTML_ESCAPES[-1]+"\n"): html_output = std_out[offset:-len(HTML_ESCAPES[-1])-1] else: html_output = std_out[offset:] headers, content = lineterm.parse_headers(html_output) if auth_html: resp_list.append(["html_output", content]) else: # Unauthenticated; extract plain text from html try: import lxml.html std_out = lxml.html.fromstring(content).text_content() except Exception: std_out = content if not auth_html: entry_list.append('<pre class="output">') if std_out and std_out != "_NoPrompt_": entry_list.append('<span class="stdout">%s</span>' % cgi.escape(std_out)) if std_err: entry_list.append('<span class="stderr">%s</span>' % cgi.escape(std_err)) entry_list.append('</pre>') resp_list.append(["output", "\n".join(entry_list)]) elif action == "file_request": request_id, request_method, file_path, if_mod_since = cmd status = (404, "Not Found") etag = None last_modified = None content_type = None content_length = None content_b64 = "" remote_modtime = None if if_mod_since: remote_modtime = str2datetime(if_mod_since) if not file_path.startswith("/"): # Blob request btime, bheaders, bcontent = self.blob_cache.get_blob(file_path) if bheaders: mod_datetime = datetime.datetime.fromtimestamp(btime) if remote_modtime and remote_modtime >= mod_datetime: # Somewhat redundant check, since blobs are never modified! status = (304, "Not Modified") else: last_modified = datetime2str(mod_datetime) etag = file_path content_type = bheaders.get("content_type") or "text/html" content_length = bheaders["content_length"] if request_method != "HEAD": content_b64 = bcontent # B64 encoded status = (200, "OK") else: abspath = file_path if os.path.sep != "/": abspath = abspath.replace("/", os.path.sep) if os.path.isfile(abspath) and os.access(abspath, os.R_OK): mod_datetime = datetime.datetime.fromtimestamp(os.path.getmtime(abspath)) if remote_modtime and remote_modtime >= mod_datetime: status = (304, "Not Modified") else: # Read file contents try: last_modified = datetime2str(mod_datetime) mime_type, encoding = mimetypes.guess_type(abspath) if mime_type: content_type = mime_type with open(abspath, "rb") as file: data = file.read() hasher = hashlib.sha1() hasher.update(data) digest = hasher.hexdigest() etag = '"%s"' % digest if request_method == "HEAD": content_length = len(data) else: content_b64 = base64.b64encode(data) status = (200, "OK") except Exception: pass resp_list.append(["file_response", request_id, dict(status=status, last_modified=last_modified, etag=etag, content_type=content_type, content_length=content_length, content_b64=content_b64)]) elif action == "errmsg": logging.warning("remote_request: ERROR %s", cmd[0]) else: raise Exception("Invalid action: "+action) self.remote_response(term_name, "", resp_list); except Exception, excp: import traceback errmsg = "%s\n%s" % (excp, traceback.format_exc()) print >> sys.stderr, "TerminalClient.remote_request: "+errmsg self.remote_response(term_name, "", [["errmsg", errmsg]])
offset = len(auth_prefix) else: # Unauthenticated html offset = std_out.find(HTML_ESCAPES[1]) + len( HTML_ESCAPES[1]) if std_out.endswith(HTML_ESCAPES[-1]): html_output = std_out[offset:-len(HTML_ESCAPES[-1] )] elif std_out.endswith(HTML_ESCAPES[-1] + "\n"): html_output = std_out[ offset:-len(HTML_ESCAPES[-1]) - 1] else: html_output = std_out[offset:] headers, content = lineterm.parse_headers(html_output) if auth_html: resp_list.append(["html_output", content]) else: # Unauthenticated; extract plain text from html try: import lxml.html std_out = lxml.html.fromstring( content).text_content() except Exception: std_out = content if not auth_html: entry_list.append('<pre class="output">') if std_out and std_out != "_NoPrompt_":
auth_prefix = HTML_ESCAPES[0]+lterm_cookie+HTML_ESCAPES[1] auth_html = std_out.startswith(auth_prefix) if auth_html: offset = len(auth_prefix) else: # Unauthenticated html offset = std_out.find(HTML_ESCAPES[1])+len(HTML_ESCAPES[1]) if std_out.endswith(HTML_ESCAPES[-1]): html_output = std_out[offset:-len(HTML_ESCAPES[-1])] elif std_out.endswith(HTML_ESCAPES[-1]+"\n"): html_output = std_out[offset:-len(HTML_ESCAPES[-1])-1] else: html_output = std_out[offset:] headers, content = lineterm.parse_headers(html_output) if auth_html: resp_list.append(["html_output", content]) else: # Unauthenticated; extract plain text from html try: import lxml.html std_out = lxml.html.fromstring(content).text_content() except Exception: std_out = content if not auth_html: entry_list.append('<pre class="output">') if std_out and std_out != "_NoPrompt_": entry_list.append('<span class="stdout">%s</span>' % cgi.escape(std_out))
def remote_request(self, term_name, from_user, req_list): """ Setup commands: reconnect Input commands: incomplete_input <line> input <line> click_paste <text> <file_url> {command:, clear_last:, normalize:, enter:} paste_command <text> get_finder <kind> <directory> save_data <save_params> <filedata> open_notebook <filepath> <prompts> <content> close_notebook <discard> save_notebook <filepath> <input_data> <params> add_cell <new_cell_type> <init_text> <before_cell_index> select_cell <cell_index> <move_up> <next_code> select_page <move_up> <endpoint> <slide> move_cell <move_up> delete_cell <move_up> merge_above erase_output <all_cells> update_type <cell_type> complete_cell <incomplete_line> update_cell <cellIndex> <execute> <save> <input_data> Output commands: completed_input <line> prompt <str> stdin <str> stdout <str> stderr <str> """ try: lterm_cookie, blobs = self.terms.get(term_name, [None, None]) resp_list = [] for cmd in req_list: action = cmd.pop(0) if action == "shutdown": if cmd: logging.warning("gtermhost: SHUTDOWN %s", cmd[0]) self.shutdown() elif action == "reconnect": if self.lineterm: self.lineterm.reconnect(term_name, cmd[0]) elif action == "set_size": if term_name != OSHELL_NAME: self.xterm(term_name, cmd[0][0], cmd[0][1], cmd[0][2], cmd[0][3], cmd[0][4]) elif action == "kill_term": self.remove_term(term_name) elif action == "clear_term": if self.lineterm: self.lineterm.clear(term_name) elif action == "export_environment": if self.lineterm: self.lineterm.export_environment(term_name, cmd[0]) elif action == "keypress": if self.lineterm: self.lineterm.term_write(term_name, cmd[0].encode(self.term_encoding, "ignore")) elif action == "feedback": msg = from_user + ": " + cmd[0] if from_user else cmd[0] widget_stream = WidgetStream.get_feedback_connection(lterm_cookie) if widget_stream: widget_stream.send_packet(msg.encode(self.term_encoding, "ignore")) elif action == "save_data": # save_data <save_params> <filedata> if self.lineterm: self.lineterm.save_data(term_name, cmd[0], cmd[1]) elif action == "click_paste": # click_paste: text, file_url, {command:, clear_last:, normalize:, enter:} if self.lineterm: paste_text = self.lineterm.click_paste(term_name, cmd[0], cmd[1], cmd[2]) self.paste_command(term_name, paste_text) elif action == "open_notebook": # open_notebook <filepath> <prompts> <content> if self.lineterm: self.lineterm.open_notebook(term_name, cmd[0], cmd[1], cmd[2]) elif action == "close_notebook": # close_notebook <discard> if self.lineterm: self.lineterm.close_notebook(term_name, cmd[0]) elif action == "save_notebook": # save_notebook <filepath> <input_data> <params> if self.lineterm: self.lineterm.save_notebook(term_name, cmd[0], cmd[1], cmd[2]) elif action == "add_cell": # add_cell <new_cell_type> <init_text> <before_cell_index> if self.lineterm: self.lineterm.add_cell(term_name, cmd[0], cmd[1], cmd[2]) elif action == "select_cell": # select_cell <cell_index> <move_up> <next_code> if self.lineterm: self.lineterm.select_cell(term_name, cmd[0], cmd[1], cmd[2]) elif action == "select_page": # select_page <move_up> <endpoint> <slide> if self.lineterm: self.lineterm.select_page(term_name, cmd[0], cmd[1], cmd[2]) elif action == "move_cell": # move_cell <move_up> if self.lineterm: self.lineterm.move_cell(term_name, cmd[0]) elif action == "delete_cell": # delete_cell <move_up> if self.lineterm: self.lineterm.delete_cell(term_name, cmd[0]) elif action == "merge_above": # merge_above if self.lineterm: self.lineterm.merge_above(term_name) elif action == "erase_output": # erase_output <all_cells> if self.lineterm: self.lineterm.erase_output(term_name, cmd[0]) elif action == "update_type": # update_type <cell_type> if self.lineterm: self.lineterm.update_type(term_name, cmd[0]) elif action == "complete_cell": # complete_cell <incomplete_line> if self.lineterm: self.lineterm.complete_cell(term_name, cmd[0]) elif action == "update_cell": # update_cell <cellIndex> <execute> <save>, <input_data> if self.lineterm: self.lineterm.update_cell(term_name, cmd[0], cmd[1], cmd[2], cmd[3]) elif action == "paste_command": # paste_command: command_line self.paste_command(term_name, cmd[0]) elif action == "clear_last_entry": if self.lineterm: self.lineterm.clear_last_entry(term_name, long(cmd[0])) elif action == "get_finder": if self.lineterm: self.lineterm.get_finder(term_name, cmd[0], cmd[1]) elif action == "incomplete_input": cmd_incomplete = cmd[0].encode("ascii", "ignore") dummy, sep, text = cmd_incomplete.rpartition(" ") options = otrace.OShell.instance.completer(text, 0, line=cmd_incomplete, all=True) if text: options = [cmd_incomplete[:-len(text)]+option for option in options] else: options = [cmd_incomplete+option for option in options] resp_list.append(["completed_input", options]) # Not escaped; handle as text elif action == "input": cmd_input = cmd[0].encode("ascii", "ignore").lstrip() # Unescaped text here_doc = base64.b64decode(cmd[1]) if cmd[1] else cmd[1] entry_list = [] if cmd_input == "cat episode4.txt": # Easter egg std_out, std_err = Episode4, "" else: std_out, std_err = otrace.OShell.instance.execute(cmd_input, here_doc=here_doc) resp_list.append(["input", cmd[0]]) # Not escaped; handle as text prompt, cur_dir_path = otrace.OShell.instance.get_prompt() resp_list.append(["prompt", cgi.escape(prompt), "file://"+urllib.quote(cur_dir_path)]) auth_html = False if lterm_cookie and std_out.startswith(HTML_ESCAPES[0]): auth_prefix = HTML_ESCAPES[0]+lterm_cookie+HTML_ESCAPES[1] auth_html = std_out.startswith(auth_prefix) if auth_html: offset = len(auth_prefix) else: # Unauthenticated html offset = std_out.find(HTML_ESCAPES[1])+len(HTML_ESCAPES[1]) if std_out.endswith(HTML_ESCAPES[-1]): html_output = std_out[offset:-len(HTML_ESCAPES[-1])] elif std_out.endswith(HTML_ESCAPES[-1]+"\n"): html_output = std_out[offset:-len(HTML_ESCAPES[-1])-1] else: html_output = std_out[offset:] headers, content = lineterm.parse_headers(html_output) if auth_html: resp_list.append(["html_output", content]) else: # Unauthenticated; extract plain text from html try: import lxml.html std_out = lxml.html.fromstring(content).text_content() except Exception: std_out = content if not auth_html: entry_list.append('<pre class="output">') if std_out and std_out != "_NoPrompt_": entry_list.append('<span class="stdout">%s</span>' % cgi.escape(std_out)) if std_err: entry_list.append('<span class="stderr">%s</span>' % cgi.escape(std_err)) entry_list.append('</pre>') resp_list.append(["output", "\n".join(entry_list)]) elif action == "file_request": request_id, request_method, file_path, if_mod_since = cmd status = (404, "Not Found") etag = None last_modified = None content_type = None content_length = None content_b64 = "" remote_modtime = None if if_mod_since: remote_modtime = str2datetime(if_mod_since) if not file_path.startswith("/"): # Blob request btime, bheaders, bcontent = self.blob_cache.get_blob(file_path) if bheaders: mod_datetime = datetime.datetime.fromtimestamp(btime) if remote_modtime and remote_modtime >= mod_datetime: # Somewhat redundant check, since blobs are never modified! status = (304, "Not Modified") else: last_modified = datetime2str(mod_datetime) etag = file_path content_type = bheaders.get("content_type") or "text/html" content_length = bheaders["content_length"] if request_method != "HEAD": content_b64 = bcontent # B64 encoded status = (200, "OK") else: abspath = file_path if os.path.sep != "/": abspath = abspath.replace("/", os.path.sep) if os.path.isfile(abspath) and os.access(abspath, os.R_OK): mod_datetime = datetime.datetime.fromtimestamp(os.path.getmtime(abspath)) if remote_modtime and remote_modtime >= mod_datetime: status = (304, "Not Modified") else: # Read file contents try: last_modified = datetime2str(mod_datetime) mime_type, encoding = mimetypes.guess_type(abspath) if mime_type: content_type = mime_type with open(abspath, "rb") as file: data = file.read() hasher = hashlib.sha1() hasher.update(data) digest = hasher.hexdigest() etag = '"%s"' % digest if request_method == "HEAD": content_length = len(data) else: content_b64 = base64.b64encode(data) status = (200, "OK") except Exception: pass resp_list.append(["file_response", request_id, dict(status=status, last_modified=last_modified, etag=etag, content_type=content_type, content_length=content_length, content_b64=content_b64)]) elif action == "errmsg": logging.warning("remote_request: ERROR %s", cmd[0]) else: raise Exception("Invalid action: "+action) self.remote_response(term_name, "", resp_list); except Exception, excp: import traceback errmsg = "%s\n%s" % (excp, traceback.format_exc()) print >> sys.stderr, "TerminalClient.remote_request: "+errmsg self.remote_response(term_name, "", [["errmsg", errmsg]])