def read_file_view(self, nodeid, filename): """Access notebook file.""" nodeid = urllib.unquote(nodeid) filename = urllib.unquote(filename) if not filename: filename = '/' #default_mime = 'application/octet-stream' default_mime = 'text' try: if filename.endswith("/"): # list directory files = list(self.conn.list_dir(nodeid, filename)) return self.json_response({ 'files': files, }) else: # return node file with self.conn.open_file(nodeid, filename) as stream: mime, encoding = mimetypes.guess_type(filename, strict=False) response.content_type = (mime if mime else default_mime) # TODO: return stream. return stream.read() except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'cannot find node ' + str(e))
def write_file_view(self, nodeid, filename): """ Write node file. """ nodeid = urllib.unquote(nodeid) filename = urllib.unquote(filename) if not filename: filename = '/' if filename.endswith("/"): # Create dir. if request.method == 'PUT': self.conn.create_dir(nodeid, filename) else: abort(BAD_REQUEST, 'Invalid method on directory') else: # Write file. try: if request.query.get("mode", "w") == ["a"]: if request.method == 'PUT': abort(BAD_REQUEST, 'Invalid method for file append') stream = self.conn.open_file(nodeid, filename, "a") else: stream = self.conn.open_file(nodeid, filename, "w") stream.write(request.body.read()) stream.close() except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'cannot find node ' + str(e)) except connlib.FileError, e: keepnote.log_error() abort(FORBIDDEN, 'Could not write file ' + str(e))
def add_node(self, nodeid, parentid, basename, attr, mtime, commit=False): """Add a node to the index""" # TODO: remove single parent assumption if self.con is None: return try: # get info if parentid is None: parentid = self._uniroot basename = u"" symlink = False # update nodegraph self.cur.execute( u"""INSERT INTO NodeGraph VALUES (?, ?, ?, ?, ?)""", (nodeid, parentid, basename, mtime, symlink)) self.add_node_attr(self.cur, nodeid, attr) if commit: self.con.commit() except Exception, e: keepnote.log_error("error index node %s '%s'" % (nodeid, attr.get("title", ""))) self._on_corrupt(e, sys.exc_info()[2])
def _on_corrupt(self, error, tracebk=None): self._corrupt = True self._need_index = True # display error keepnote.log_error(error, tracebk)
def read_file_view(self, nodeid, filename): """Access notebook file.""" nodeid = urllib.unquote(nodeid) filename = urllib.unquote(filename) if not filename: filename = '/' #default_mime = 'application/octet-stream' default_mime = 'text' try: if filename.endswith("/"): # list directory files = list(self.conn.list_dir(nodeid, filename)) return self.json_response({ 'files': files, }) else: # return node file with self.conn.open_file(nodeid, filename) as stream: mime, encoding = mimetypes.guess_type( filename, strict=False) response.content_type = (mime if mime else default_mime) # TODO: return stream. return stream.read() except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'cannot find node ' + str(e))
def add_node(self, nodeid, parentid, basename, attr, mtime): """Add a node to the index""" # TODO: remove single parent assumption if self.con is None: return try: # get info if parentid is None: parentid = self._uniroot basename = u"" symlink = False # update nodegraph self.cur.execute( u"""INSERT INTO NodeGraph VALUES (?, ?, ?, ?, ?)""", (nodeid, parentid, basename, mtime, symlink)) # update attrs for attrindex in self._attrs.itervalues(): attrindex.add_node(self.cur, nodeid, attr) # update fulltext infile = self._nconn.read_data_as_plain_text(nodeid) self.index_node_text(nodeid, attr, infile) except Exception, e: keepnote.log_error("error index node %s '%s'" % (nodeid, attr.get("title", ""))) self._on_corrupt(e, sys.exc_info()[2])
def add_node(self, nodeid, parentid, basename, attr, mtime, commit=True): """Add a node to the index""" # TODO: remove single parent assumption if self.con is None: return try: # get info if parentid is None: parentid = self._uniroot basename = u"" symlink = False # update nodegraph self.cur.execute( u"""INSERT INTO NodeGraph VALUES (?, ?, ?, ?, ?)""", (nodeid, parentid, basename, mtime, symlink)) self.add_node_attr(self.cur, nodeid, attr) if commit: self.con.commit() except Exception as e: keepnote.log_error("error index node %s '%s'" % (nodeid, attr.get("title", ""))) self._on_corrupt(e, sys.exc_info()[2])
def index_node_text(self, nodeid, attr, infile): try: text = attr.get("title", "") + "\n" + "".join(infile) self.insert_text(nodeid, text) except Exception, e: keepnote.log_error()
def read(self, infile, partial=False, ignore_errors=False): """Read from stream infile to populate textbuffer""" #self._text_queue = [] self._within_body = False self._partial = partial self._dom = TextBufferDom() self._dom_ptr = self._dom self._tag_stack = [(None, self._dom)] try: self.reset() #for line in infile: # self.feed(line) self.feed(infile.read()) self.close() except Exception as e: log_error(e, sys.exc_info()[2]) # reraise error if not ignored self.close() if not ignore_errors: raise self.process_dom_read(self._dom) return unnest_indent_tags(self._dom.get_contents())
def save_options(self, app): for widget in self.extlist: try: widget.ext.enable(widget.enabled) except Exception, e: keepnote.log_error(e) widget.update()
def on_new_window(self, window): """Initialize extension for a particular window""" if self._enabled: try: self.on_add_ui(window) self.__uis.add(window) except Exception, e: keepnote.log_error(e, sys.exc_info()[2])
def delete_node_view(self, nodeid): """Delete notebook node.""" nodeid = urllib.unquote(nodeid) try: self.conn.delete_node(nodeid) except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'node not found ' + str(e))
def insert_clipboard_page(pkg): # debug.write("Inside of ICP\n") # if pkg.textview is None : # if pkg.editor is None : main_viewer = pkg.window.get_viewer() # debug.write("ICP - I seem to have gotten viewer\n") # debug.write("main viewer class is: " + main_viewer.__class__.__name__ + "\n") textview = None if isinstance(main_viewer, TabbedViewer): viewer = main_viewer.get_current_viewer() if isinstance(viewer, ThreePaneViewer): try: textview = viewer.editor._editor.get_textview() except: pass # debug.write("Exception getting textview\n") if textview is None: return # debug.write("viewer class is: " + viewer.__class__.__name__ + "\n") try: # textview.emit("paste-clipboard") # DEBUG # debug.write("Trying ...") if pkg.clipboard.wait_is_text_available(): # debug.write(" text\n") last_text = pkg.clipboard.wait_for_text() if last_text and last_text != pkg.last_text: # debug.write("trying to get textview\n") # textview = viewer.editor._editor.get_textview() # debug.write("got textview. Trying emit\n") # textview.emit("paste-clipboard") textview.get_buffer().insert_at_cursor(last_text) # debug.write("Thinks its done emit\n") # pkg.clipboard.set_text("\n\n") # textview.emit("paste-clipboard") # pkg.clipboard.set_text(last_text) pkg.last_text = last_text # pkg.clipboard.clear() # pkg.clipboard.set_text("ZZZ") else: return # elif pkg.clipboard.wait_is_image_available() : # debug.write(" text\n") # textview = viewer.editor._editor.get_textview() textview.emit("paste-clipboard") pkg.clipboard.set_text("\n\n") textview.emit("paste-clipboard") pkg.last_text = "\n\n" except: # debug.write("Some error trying to emit clipboard\n") # raise keepnote.log_error() pass
def insert_clipboard_page(pkg): #debug.write("Inside of ICP\n") #if pkg.textview is None : #if pkg.editor is None : main_viewer = pkg.window.get_viewer() #debug.write("ICP - I seem to have gotten viewer\n") #debug.write("main viewer class is: " + main_viewer.__class__.__name__ + "\n") textview = None if isinstance(main_viewer, TabbedViewer): viewer = main_viewer.get_current_viewer() if isinstance(viewer, ThreePaneViewer): try: textview = viewer.editor._editor.get_textview() except: pass #debug.write("Exception getting textview\n") if textview is None: return #debug.write("viewer class is: " + viewer.__class__.__name__ + "\n") try: #textview.emit("paste-clipboard") # DEBUG #debug.write("Trying ...") if pkg.clipboard.wait_is_text_available(): #debug.write(" text\n") last_text = pkg.clipboard.wait_for_text() if last_text and last_text != pkg.last_text: #debug.write("trying to get textview\n") #textview = viewer.editor._editor.get_textview() #debug.write("got textview. Trying emit\n") #textview.emit("paste-clipboard") textview.get_buffer().insert_at_cursor(last_text) #debug.write("Thinks its done emit\n") #pkg.clipboard.set_text("\n\n") #textview.emit("paste-clipboard") #pkg.clipboard.set_text(last_text) pkg.last_text = last_text #pkg.clipboard.clear() #pkg.clipboard.set_text("ZZZ") else: return #elif pkg.clipboard.wait_is_image_available() : #debug.write(" text\n") #textview = viewer.editor._editor.get_textview() textview.emit("paste-clipboard") pkg.clipboard.set_text("\n\n") textview.emit("paste-clipboard") pkg.last_text = "\n\n" except: #debug.write("Some error trying to emit clipboard\n") #raise keepnote.log_error() pass
def _on_corrupt(self, error, tracebk=None): """ Called when database appears corrupt Logs error and schedules re-indexing """ self._corrupt = True self._need_index = True # display error keepnote.log_error(error, tracebk)
def on_close_window(self, window): """Callback for when window is closed""" if window in self.__windows: if window in self.__uis: try: self.on_remove_ui(window) except Exception, e: keepnote.log_error(e, sys.exc_info()[2]) self.__uis.remove(window) self.__windows.remove(window)
def search_contents(self, text): """Search node contents""" cur = self.con.cursor() try: for res in self.search_node_contents(cur, text): yield res except: keepnote.log_error("SQLITE error while performing search") finally: cur.close()
def execute(code, vars, stdout, stderr): """Execute user's python code""" __stdout = sys.stdout __stderr = sys.stderr sys.stdout = stdout sys.stderr = stderr try: exec(code, vars) except Exception, e: keepnote.log_error(e, sys.exc_info()[2], stderr)
def _recover_attr(self, filename): if os.path.exists(filename): self._move_to_lostdir(filename) try: out = open(filename, "w") out.write("<node></node>") out.close() except: keepnote.log_error(u"failed to recover '%s'" % filename) pass
def convert_node_attr(filename, filename2, attr_defs=g_attr_defs_lookup): """Convert a node.xml file from version 5 to 6""" keepnote.log_message("converting '%s'...\n" % filename2) try: attr = read_attr_v5(filename, attr_defs) attr["version"] = 6 write_attr_v6(filename2, attr) except Exception, e: keepnote.log_error("cannot convert %s: %s\n" % (filename, str(e)), sys.exc_info()[2])
def save_options(self, app): app.pref.set( "extension_info", "disabled", [widget.ext.key for widget in self.extlist if not widget.enabled]) # enable/disable extensions for widget in self.extlist: if widget.enabled != widget.ext.is_enabled(): try: widget.ext.enable(widget.enabled) except: keepnote.log_error()
def update_node_view(self, nodeid): """Update notebook node attr.""" nodeid = urllib.unquote(nodeid) # update node data = request.body.read() attr = json.loads(data) try: self.conn.update_node(nodeid, attr) except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'node not found ' + str(e))
def _on_closing_notebook(self, notebook, save): """ Callback for when notebook is about to close """ keepnote.KeepNote._on_closing_notebook(self, notebook, save) try: if save: self.save() except: keepnote.log_error("Error while closing notebook") for window in self._windows: window.close_notebook(notebook)
def do_POST(self): parts, nodeid, filename = self.parse_path() content_len = int(self.headers.get("Content-length", 0)) data = self.rfile.read(content_len) try: if nodeid == "": # pure command if parts.query == "save": self.server.conn.save() elif parts.query == "index": query = plist.loads(data) res = self.server.conn.index(query) if hasattr(res, "next"): res = list(res) self.send_response(httplib.OK) self.send_header("content_type", "text/xml") self.end_headers() self.wfile.write(XML_HEADER) self.wfile.write(plist.dumps(res).encode("utf8")) return elif not filename: # update node attr = plist.loads(data) attr["nodeid"] = nodeid self.server.conn.update_node(nodeid, attr) else: # write file params = urlparse.parse_qs(parts.query) if params.get("mode", "r") == ["a"]: stream = self.server.conn.open_file(nodeid, filename, "a") else: stream = self.server.conn.open_file(nodeid, filename, "w") stream.write(data) stream.close() self.send_response(httplib.OK) self.send_header("content_type", "text/plain") self.end_headers() except Exception, e: # FIX response keepnote.log_error() self.send_error(httplib.NOT_FOUND, "cannot create node: " + str(e))
def do_POST(self): parts, nodeid, filename = self.parse_path() content_len = int(self.headers.get("Content-length", 0)) data = self.rfile.read(content_len) try: if nodeid == "": # pure command if parts.query == "save": self.server.conn.save() elif parts.query == "index": query = plist.loads(data) res = self.server.conn.index(query) if hasattr(res, "next"): res = list(res) self.send_response(httplib.OK) self.send_header("content_type", "text/xml") self.end_headers() self.wfile.write(XML_HEADER) self.wfile.write(plist.dumps(res).encode("utf8")) return elif not filename: # update node attr = plist.loads(data) attr["nodeid"] = nodeid self.server.conn.update_node(nodeid, attr) else: # write file params = urlparse.parse_qs(parts.query) if params.get("mode", "r") == ["a"]: stream = self.server.conn.open_file(nodeid, filename, "a") else: stream = self.server.conn.open_file(nodeid, filename, "w") stream.write(data) stream.close() self.send_response(httplib.OK) self.send_header("content_type", "text/plain") self.end_headers() except Exception as e: # FIX response keepnote.log_error() self.send_error(httplib.NOT_FOUND, "cannot create node: " + str(e))
def delete_file_view(self, nodeid, filename): """ Delete node file. """ nodeid = urllib.unquote(nodeid) filename = urllib.unquote(filename) if not filename: filename = '/' try: # delete file/dir self.conn.delete_file(nodeid, filename) except connlib.UnknownNode, e: keepnote.log_error() abort(NOT_FOUND, 'cannot find node ' + str(e))
def close_all_notebook(self, notebook, save=True): """Close all instances of a notebook""" try: notebook.close(save) except: keepnote.log_error() notebook.closing_event.remove(self._on_closing_notebook) del self._notebook_count[notebook] for key, val in self._notebooks.iteritems(): if val == notebook: del self._notebooks[key] break
def init_extensions_windows(self, windows=None, exts=None): """Initialize all extensions for a window""" if exts is None: exts = self.iter_extensions() if windows is None: windows = self.get_windows() for window in windows: for ext in exts: try: if isinstance(ext, keepnote.gui.extension.Extension): ext.on_new_window(window) except Exception, e: log_error(e, sys.exc_info()[2])
def init_extensions_windows(self, windows=None, exts=None): """Initialize all extensions for a window""" if exts is None: exts = self.get_enabled_extensions() if windows is None: windows = self.get_windows() for window in windows: for ext in exts: try: if isinstance(ext, keepnote.gui.extension.Extension): ext.on_new_window(window) except Exception, e: log_error(e, sys.exc_info()[2])
def _on_window_close(self, window, event): """Callback for window close event""" if window in self._windows: for ext in self.get_enabled_extensions(): try: if isinstance(ext, keepnote.gui.extension.Extension): ext.on_close_window(window) except Exception, e: log_error(e, sys.exc_info()[2]) # remove window from window list self._windows.remove(window) if window == self._current_window: self._current_window = None
def _on_window_close(self, window, event): """Callback for window close event""" if window in self._windows: for ext in self.iter_extensions(): try: if isinstance(ext, keepnote.gui.extension.Extension): ext.on_close_window(window) except Exception, e: log_error(e, sys.exc_info()[2]) # remove window from window list self._windows.remove(window) if window == self._current_window: self._current_window = None
def process_connection(conn, addr, passwd, execfunc): """ Process a connection conn -- connection to other process addr -- address of other process passwd -- password required to accept connect execfunc -- function to call with command """ try: connfile = conn.makefile("rw") connfile.write(KEEPNOTE_HEADER) connfile.flush() passwd2 = connfile.readline().rstrip("\n") command = connfile.readline().rstrip("\n") # ensure password matches if passwd2 != passwd: # password failed, close connection conn.close() return # parse command and execute try: # redirect stdout to connection sys.stdout.flush() stdout = sys.stdout sys.stdout = connfile #QuotedOutput(connfile) execfunc(parse_command(command)) #connfile.write(KEEPNOTE_EOF) connfile.flush() except: keepnote.log_error() pass finally: sys.stdout = stdout # close connection connfile.close() conn.shutdown(socket.SHUT_RDWR) conn.close() except socket.error, e: # socket error, close connection print >>sys.stderr, e, ": error with connection" conn.close()
def process_connection(conn, addr, passwd, execfunc): """ Process a connection conn -- connection to other process addr -- address of other process passwd -- password required to accept connect execfunc -- function to call with command """ try: connfile = conn.makefile("rw") connfile.write(KEEPNOTE_HEADER) connfile.flush() passwd2 = connfile.readline().rstrip("\n") command = connfile.readline().rstrip("\n") # ensure password matches if passwd2 != passwd: # password failed, close connection conn.close() return # parse command and execute try: # redirect stdout to connection sys.stdout.flush() stdout = sys.stdout sys.stdout = connfile #QuotedOutput(connfile) execfunc(parse_command(command)) #connfile.write(KEEPNOTE_EOF) connfile.flush() except: keepnote.log_error() pass finally: sys.stdout = stdout # close connection connfile.close() conn.shutdown(socket.SHUT_RDWR) conn.close() except socket.error as e: # socket error, close connection print >>sys.stderr, e, ": error with connection" conn.close()
def create_node_view(self, nodeid=None): """ Create new notebook node. """ if nodeid is not None: nodeid = urllib.unquote(nodeid) else: nodeid = new_nodeid() data = request.body.read() attr = json.loads(data) try: self.conn.create_node(nodeid, attr) except connlib.NodeExists, e: keepnote.log_error() abort(FORBIDDEN, 'node already exists.' + str(e))
def view_nodes(self, nodes): """View a node(s) in the editor""" # editor cannot view multiple nodes at once # if asked to, it will view none if len(nodes) > 1: nodes = [] # save current page before changing nodes self.save() self._save_cursor() if len(nodes) == 0: self.clear_view() else: page = nodes[0] self._page = page self._textview.enable() try: if page.has_attr("payload_filename"): infile = page.open_file( page.get_attr("payload_filename"), "r", "utf-8") text = infile.read() infile.close() self._textview.get_buffer().set_text(text) self._load_cursor() else: self.clear_view() except UnicodeDecodeError as e: self.clear_view() except RichTextError as e: self.clear_view() self.emit("error", e.msg, e) except Exception as e: keepnote.log_error() self.clear_view() self.emit("error", "Unknown error", e) if len(nodes) > 0: self.emit("view-node", nodes[0])
def on_text2nodes(self, window): """Callback from gui for text2nodes""" # Assert focus is textview # Assert textview has selected text # Get current node # For each line of selected text create child page #nb = window.get_notebook() widget = self._widget_focus.get(window, None) if not isinstance(widget, gtk.TextView): keepnote.log_error("T2N: focus") return # For testing simply duplicate at end of page #eop = buf.get_end_iter() #buf.insert(eop, '\n>>>PAGE END\n') #return buf = widget.get_buffer() bounds = buf.get_selection_bounds() if not bounds: return txt = unicode_gtk(buf.get_text(bounds[0], bounds[1])) # Ask the window for the currently selected nodes nodes = window.get_selected_nodes() if len(nodes) == 0: return node = nodes[0] task = tasklib.Task() # For testing simply duplicate at end of page for title in txt.splitlines(): title = title.strip() if title != '': #eop = buf.get_end_iter() #buf.insert(eop, '\n>>>\n'+txt) self.make_page(node, title, '') task.finish()
def error(self, text, error=None, tracebk=None, parent=None): """Display an error message""" if parent is None: parent = self.get_current_window() dialog = gtk.MessageDialog(parent, flags= gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=text) dialog.connect("response", lambda d,r: d.destroy()) dialog.set_title(_("Error")) dialog.show() # add message to error log if error is not None: keepnote.log_error(error, tracebk)
def error(self, text, error=None, tracebk=None, parent=None): """Display an error message""" if parent is None: parent = self.get_current_window() dialog = gtk.MessageDialog(parent, flags=gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT, type=gtk.MESSAGE_ERROR, buttons=gtk.BUTTONS_OK, message_format=text) dialog.connect("response", lambda d, r: d.destroy()) dialog.set_title(_("Error")) dialog.show() # add message to error log if error is not None: keepnote.log_error(error, tracebk)
def do_DELETE(self): parts, nodeid, filename = self.parse_path() try: if not filename: # delete node self.server.conn.delete_node(nodeid) else: # delete file/dir self.server.conn.delete_file(nodeid, filename) self.send_response(httplib.OK) self.send_header("content_type", "text/plain") self.end_headers() except Exception as e: # TDOD: fix response keepnote.log_error() self.send_error(httplib.NOT_FOUND, "cannot delete node: " + str(e))
def _list_children_attr(self, nodeid, _path=None, _full=True): """List attr of children nodes of nodeid""" path = self._path_cache.get_path(nodeid) if _path is None else _path assert path is not None try: files = os.listdir(path) except: raise keepnote.compat.notebook_v4.NoteBookError( _(u"Do not have permission to read folder contents: %s") % path, e) for filename in files: path2 = os.path.join(path, filename) if os.path.exists(get_node_meta_file(path2)): try: yield self._read_node(nodeid, path2, _full=_full) except keepnote.compat.notebook_v4.NoteBookError, e: keepnote.log_error(u"error reading %s" % path2) continue
def do_DELETE(self): parts, nodeid, filename = self.parse_path() try: if not filename: # delete node self.server.conn.delete_node(nodeid) else: # delete file/dir self.server.conn.delete_file(nodeid, filename) self.send_response(httplib.OK) self.send_header("content_type", "text/plain") self.end_headers() except Exception, e: # TDOD: fix response keepnote.log_error() self.send_error(httplib.NOT_FOUND, "cannot delete node: " + str(e))