def send_message(fd, event): """ Sends the log enumeration result to the client. Necessary because IOLoop doesn't pass anything other than *fd* and *event* when it handles file descriptor events. """ message = q.get() #self.term_log.debug('message: %s' % message) if message == 'complete': io_loop.remove_handler(fd) total_bytes = 0 logs_dir = os.path.join(users_dir, "logs") log_files = os.listdir(logs_dir) for log in log_files: log_path = os.path.join(logs_dir, log) total_bytes += os.stat(log_path).st_size out_dict = { 'total_logs': len(log_files), 'total_bytes': total_bytes } # This signals to the client that we're done message = {'terminal:logging_logs_complete': out_dict} self.write_message(message) return message = json_encode(message) if message not in results: # Keep track of how many/how much if results: results.pop() # No need to keep old stuff hanging around results.append(message) self.write_message(message)
def save_bookmarks(self, bookmarks): """ Handles saving *bookmarks* for clients. """ out_dict = {'updates': [], 'count': 0, 'errors': []} try: user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.ws.settings['user_dir'], user) updates = bookmarks_db.sync_bookmarks(bookmarks) out_dict.update({ 'updates': updates, 'count': len(bookmarks), }) out_dict['updateSequenceNum'] = bookmarks_db.get_highest_USN() except Exception as e: import traceback self.term_log.error("Got exception synchronizing bookmarks: %s" % e) traceback.print_exc(file=sys.stdout) out_dict['errors'].append(str(e)) if out_dict['errors']: out_dict['result'] = "Upload completed but errors were encountered." else: out_dict['result'] = "Upload successful" message = {'terminal:bookmarks_save_result': out_dict} self.write_message(json_encode(message))
def save_bookmarks(self, bookmarks): """ Handles saving *bookmarks* for clients. """ out_dict = { 'updates': [], 'count': 0, 'errors': [] } try: user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.ws.settings['user_dir'], user) updates = bookmarks_db.sync_bookmarks(bookmarks) out_dict.update({ 'updates': updates, 'count': len(bookmarks), }) out_dict['updateSequenceNum'] = bookmarks_db.get_highest_USN() except Exception as e: import traceback self.term_log.error("Got exception synchronizing bookmarks: %s" % e) traceback.print_exc(file=sys.stdout) out_dict['errors'].append(str(e)) if out_dict['errors']: out_dict['result'] = "Upload completed but errors were encountered." else: out_dict['result'] = "Upload successful" message = {'terminal:bookmarks_save_result': out_dict} self.write_message(json_encode(message))
def rename_tags(self, renamed_tags): """ Handles renaming tags. """ user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.ws.settings['user_dir'], user) out_dict = {'result': "", 'count': 0, 'errors': [], 'updates': []} for pair in renamed_tags: old_name, new_name = pair.split(',') bookmarks_db.rename_tag(old_name, new_name) out_dict['count'] += 1 message = {'terminal:bookmarks_renamed_tags': out_dict} self.write_message(json_encode(message))
def get_bookmarks(self, updateSequenceNum): """ Returns a JSON-encoded list of bookmarks updated since the last *updateSequenceNum*. If *updateSequenceNum* resolves to False, all bookmarks will be sent to the client. """ user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.settings['user_dir'], user) if updateSequenceNum: updateSequenceNum = int(updateSequenceNum) else: # This will force a full download updateSequenceNum = 0 updated_bookmarks = bookmarks_db.get_bookmarks(updateSequenceNum) message = {'terminal:bookmarks_updated': updated_bookmarks} self.write_message(json_encode(message))
def rename_tags(self, renamed_tags): """ Handles renaming tags. """ user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.ws.settings['user_dir'], user) out_dict = { 'result': "", 'count': 0, 'errors': [], 'updates': [] } for pair in renamed_tags: old_name, new_name = pair.split(',') bookmarks_db.rename_tag(old_name, new_name) out_dict['count'] += 1 message = {'terminal:bookmarks_renamed_tags': out_dict} self.write_message(json_encode(message))
def save_term_settings(term, location, session, settings): """ Saves the *settings* associated with the given *term*, *location*, and *session* in the 'term_settings.json' file inside the user's session directory. When complete the given *callback* will be called (if given). """ term = str(term) # JSON wants strings as keys term_settings = RUDict() term_settings[location] = {term: settings} session_dir = options.session_dir session_dir = os.path.join(session_dir, session) settings_path = os.path.join(session_dir, 'term_settings.json') # First we read in the existing settings and then update them. if os.path.exists(settings_path): with io.open(settings_path, encoding='utf-8') as f: term_settings.update(json_decode(f.read())) term_settings[location][term].update(settings) with io.open(settings_path, 'w', encoding='utf-8') as f: f.write(json_encode(term_settings))
def save_term_settings(term, location, session, settings): """ Saves the *settings* associated with the given *term*, *location*, and *session* in the 'term_settings.json' file inside the user's session directory. When complete the given *callback* will be called (if given). """ if not session: return # Just a viewer of a broadcast terminal term = str(term) # JSON wants strings as keys term_settings = RUDict() term_settings[location] = {term: settings} session_dir = options.session_dir session_dir = os.path.join(session_dir, session) settings_path = os.path.join(session_dir, 'term_settings.json') # First we read in the existing settings and then update them. if os.path.exists(settings_path): with io.open(settings_path, encoding='utf-8') as f: term_settings.update(json_decode(f.read())) term_settings[location][term].update(settings) with io.open(settings_path, 'w', encoding='utf-8') as f: f.write(json_encode(term_settings))
def delete_bookmarks(self, deleted_bookmarks): """ Handles deleting bookmarks given a *deleted_bookmarks* list. """ user = self.current_user['upn'] bookmarks_db = BookmarksDB(self.ws.settings['user_dir'], user) out_dict = { 'result': "", 'count': 0, 'errors': [], } try: for bookmark in deleted_bookmarks: out_dict['count'] += 1 bookmarks_db.delete_bookmark(bookmark) out_dict['result'] = "Success" except Exception as e: # TODO: Make this more specific self.term_log.error("delete_bookmarks error: %s" % e) import traceback traceback.print_exc(file=sys.stdout) out_dict['result'] = "Errors" out_dict['errors'].append(str(e)) message = {'terminal:bookmarks_delete_result': out_dict} self.write_message(json_encode(message))
def save_bookmarks(self): """ Saves self.bookmarks to self.bookmarks_path as a JSON-encoded list. """ with open(self.bookmarks_path, 'w') as f: f.write(json_encode(self.bookmarks))
def _save_log_playback(queue, settings): """ Writes a JSON-encoded message to the client containing the log in a self-contained HTML format similar to:: ./logviewer.py log_filename The difference between this function and :py:meth:`_retrieve_log_playback` is that this one instructs the client to save the file to disk instead of opening it in a new window. :arg settings['log_filename']: The name of the log to display. :arg settings['colors']: The CSS color scheme to use when generating output. :arg settings['theme']: The CSS theme to use when generating output. :arg settings['where']: Whether or not the result should go into a new window or an iframe. The output will look like this:: { 'result': "Success", 'data': <HTML rendered output>, 'mimetype': 'text/html' 'filename': <filename of the log recording> } It is expected that the client will create a new window with the result of this method. """ #print("Running retrieve_log_playback(%s)" % settings); out_dict = { 'result': "Success", 'mimetype': 'text/html', 'data': "", # Will be replace with the rendered template } # Local variables user = settings['user'] users_dir = settings['users_dir'] container = settings['container'] prefix = settings['prefix'] log_filename = settings['log_filename'] short_logname = log_filename.split('.golog')[0] out_dict['filename'] = "%s.html" % short_logname # Important paths logs_dir = os.path.join(users_dir, "logs") log_path = os.path.join(logs_dir, log_filename) #templates_path = os.path.join(gateone_dir, 'templates') #colors_path = os.path.join(templates_path, 'term_colors') #themes_path = os.path.join(templates_path, 'themes') template_path = os.path.join(PLUGIN_PATH, 'templates') # recording format: # {"screen": [log lines], "time":"2011-12-20T18:00:01.033Z"} # Actual method logic if os.path.exists(log_path): # Next we render the theme and color templates so we can pass them to # our final template out_dict['metadata'] = get_or_update_metadata(log_path, user) try: rows = out_dict['metadata']['rows'] cols = out_dict['metadata']['columns'] except KeyError: # Log was created before rows/cols metadata was included via termio.py # Use some large values to ensure nothing wraps and hope for the best: rows = 40 cols = 500 # NOTE: 'colors' are customizable but colors_256 is universal. That's # why they're separate. # Lastly we render the actual HTML template file # NOTE: Using Loader() directly here because I was getting strange EOF # errors trying to do it the other way :) loader = tornado.template.Loader(template_path) playback_template = loader.load('playback_log.html') recording = render_log_frames(log_path, rows, cols) preview = 'false' playback_html = playback_template.generate( prefix=prefix, container=container, theme=settings['theme_css'], colors=settings['colors_css'], colors_256=settings['256_colors'], preview=preview, recording=json_encode(recording), ) out_dict['data'] = playback_html else: out_dict['result'] = _("ERROR: Log not found") message = {'go:save_file': out_dict} queue.put(message)
def _retrieve_log_playback(queue, settings): """ Writes a JSON-encoded message to the client containing the log in a self-contained HTML format similar to:: ./logviewer.py log_filename *settings* - A dict containing the *log_filename*, *colors*, and *theme* to use when generating the HTML output. :arg settings['log_filename']: The name of the log to display. :arg settings['colors_css']: The CSS color scheme to use when generating output. :arg settings['theme_css']: The entire CSS theme <style> to use when generating output. :arg settings['where']: Whether or not the result should go into a new window or an iframe. The output will look like this:: { 'result': "Success", 'log': <HTML rendered output>, 'metadata': {<metadata of the log>} } It is expected that the client will create a new window with the result of this method. """ #print("Running retrieve_log_playback(%s)" % settings); if 'where' not in settings: # Avoids a KeyError if it is missing settings['where'] = None out_dict = { 'result': "", 'html': "", # Will be replace with the rendered template 'metadata': {}, 'where': settings['where'] # Just gets passed as-is back to the client } # Local variables user = settings['user'] users_dir = settings['users_dir'] container = settings['container'] prefix = settings['prefix'] log_filename = settings['log_filename'] # Important paths # NOTE: Using os.path.join() in case Gate One can actually run on Windows # some day. logs_dir = os.path.join(users_dir, "logs") log_path = os.path.join(logs_dir, log_filename) template_path = os.path.join(PLUGIN_PATH, 'templates') # recording format: # {"screen": [log lines], "time":"2011-12-20T18:00:01.033Z"} # Actual method logic if os.path.exists(log_path): # First we setup the basics out_dict['metadata'] = get_or_update_metadata(log_path, user) out_dict['metadata']['filename'] = log_filename try: rows = out_dict['metadata']['rows'] cols = out_dict['metadata']['columns'] except KeyError: # Log was created before rows/cols metadata was included via termio.py # Use some large values to ensure nothing wraps and hope for the best: rows = 40 cols = 500 out_dict['result'] = "Success" # TODO: Add more error checking # NOTE: Using Loader() directly here because I was getting strange EOF # errors trying to do it the other way :) loader = tornado.template.Loader(template_path) playback_template = loader.load('playback_log.html') preview = 'false' if settings['where']: preview = 'true' recording = render_log_frames(log_path, rows, cols, limit=50) else: recording = render_log_frames(log_path, rows, cols) playback_html = playback_template.generate( prefix=prefix, container=container, theme=settings['theme_css'], colors=settings['colors_css'], colors_256=settings['256_colors'], preview=preview, recording=json_encode(recording)) if not isinstance(playback_html, str): playback_html = playback_html.decode('utf-8') out_dict['html'] = playback_html else: out_dict['result'] = _("ERROR: Log not found") message = {'terminal:logging_log_playback': out_dict} queue.put(message)
def _retrieve_log_playback(queue, settings): """ Writes a JSON-encoded message to the client containing the log in a self-contained HTML format similar to:: ./logviewer.py log_filename *settings* - A dict containing the *log_filename*, *colors*, and *theme* to use when generating the HTML output. :arg settings['log_filename']: The name of the log to display. :arg settings['colors_css']: The CSS color scheme to use when generating output. :arg settings['theme_css']: The entire CSS theme <style> to use when generating output. :arg settings['where']: Whether or not the result should go into a new window or an iframe. The output will look like this:: { 'result': "Success", 'log': <HTML rendered output>, 'metadata': {<metadata of the log>} } It is expected that the client will create a new window with the result of this method. """ #print("Running retrieve_log_playback(%s)" % settings); if 'where' not in settings: # Avoids a KeyError if it is missing settings['where'] = None out_dict = { 'result': "", 'html': "", # Will be replace with the rendered template 'metadata': {}, 'where': settings['where'] # Just gets passed as-is back to the client } # Local variables user = settings['user'] users_dir = settings['users_dir'] container = settings['container'] prefix = settings['prefix'] log_filename = settings['log_filename'] # Important paths # NOTE: Using os.path.join() in case Gate One can actually run on Windows # some day. logs_dir = os.path.join(users_dir, "logs") log_path = os.path.join(logs_dir, log_filename) template_path = os.path.join(PLUGIN_PATH, 'templates') # recording format: # {"screen": [log lines], "time":"2011-12-20T18:00:01.033Z"} # Actual method logic if os.path.exists(log_path): # First we setup the basics out_dict['metadata'] = get_or_update_metadata(log_path, user) out_dict['metadata']['filename'] = log_filename try: rows = out_dict['metadata']['rows'] cols = out_dict['metadata']['columns'] except KeyError: # Log was created before rows/cols metadata was included via termio.py # Use some large values to ensure nothing wraps and hope for the best: rows = 40 cols = 500 out_dict['result'] = "Success" # TODO: Add more error checking # NOTE: Using Loader() directly here because I was getting strange EOF # errors trying to do it the other way :) loader = tornado.template.Loader(template_path) playback_template = loader.load('playback_log.html') preview = 'false' if settings['where']: preview = 'true' recording = render_log_frames(log_path, rows, cols, limit=50) else: recording = render_log_frames(log_path, rows, cols) playback_html = playback_template.generate( prefix=prefix, container=container, theme=settings['theme_css'], colors=settings['colors_css'], colors_256=settings['256_colors'], preview=preview, recording=json_encode(recording) ) if not isinstance(playback_html, str): playback_html = playback_html.decode('utf-8') out_dict['html'] = playback_html else: out_dict['result'] = _("ERROR: Log not found") message = {'terminal:logging_log_playback': out_dict} queue.put(message)