From d37422b5923e2e8ff011cfdd7b4d7ddb02b9d4b3 Mon Sep 17 00:00:00 2001 From: Dan Helfman Date: Tue, 19 May 2009 12:38:52 -0700 Subject: [PATCH] Fixed a bug in Luminotes Desktop in which a backslash within a note was duplicated each time the note was saved. --- NEWS | 2 ++ controller/Database.py | 29 +++++++++++++++-------- controller/test/Test_notebooks.py | 38 +++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 10 deletions(-) diff --git a/NEWS b/NEWS index 0730ce6..f272273 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ * Added a "start a new discussion" link to each discussion forum page. * Updated Luminotes Server INSTALL file with instructions for setting the http_url configuration setting. + * Fixed a bug in Luminotes Desktop in which a backslash within a note was + duplicated each time the note was saved. * Fixed a bug in which special characters in a customer's name prevented PayPal payments from going through properly. diff --git a/controller/Database.py b/controller/Database.py index 36cc2aa..879c6fb 100644 --- a/controller/Database.py +++ b/controller/Database.py @@ -174,6 +174,15 @@ class Database( object ): except ImportError: return None + def unescape( self, sql_command ): + """ + For backends that don't treat backslashes specially, un-double all backslashes in the given + sql_command. + """ + if self.__backend == Persistent.SQLITE_BACKEND: + return sql_command.replace( "\\\\", "\\" ) + return sql_command + @synchronized def save( self, obj, commit = True ): """ @@ -187,11 +196,11 @@ class Database( object ): connection = self.get_connection() cursor = connection.cursor() - cursor.execute( obj.sql_exists() ) + cursor.execute( self.unescape( obj.sql_exists() ) ) if cursor.fetchone(): - cursor.execute( obj.sql_update() ) + cursor.execute( self.unescape( obj.sql_update() ) ) else: - cursor.execute( obj.sql_create() ) + cursor.execute( self.unescape( obj.sql_create() ) ) if isinstance( obj, self.CLASSES_NOT_TO_CACHE ): cache = None @@ -285,7 +294,7 @@ class Database( object ): connection = self.get_connection() cursor = connection.cursor() - cursor.execute( sql_command ) + cursor.execute( self.unescape( sql_command ) ) row = self.__row_to_unicode( cursor.fetchone() ) if not row: @@ -317,7 +326,7 @@ class Database( object ): connection = self.get_connection() cursor = connection.cursor() - cursor.execute( sql_command ) + cursor.execute( self.unescape( sql_command ) ) objects = [] row = self.__row_to_unicode( cursor.fetchone() ) @@ -352,7 +361,7 @@ class Database( object ): connection = self.get_connection() cursor = connection.cursor() - cursor.execute( sql_command ) + cursor.execute( self.unescape( sql_command ) ) if commit: connection.commit() @@ -373,7 +382,7 @@ class Database( object ): if self.__backend == Persistent.SQLITE_BACKEND: cursor.executescript( sql_commands ) else: - cursor.execute( sql_commands ) + cursor.execute( self.unescape( sql_commands ) ) if commit: connection.commit() @@ -430,15 +439,15 @@ class Database( object ): # generate a random id, but on the off-chance that it collides with something else already in # the database, try again next_id = Database.generate_id() - cursor.execute( Object_type.sql_id_exists( next_id ) ) + cursor.execute( self.unescape( Object_type.sql_id_exists( next_id ) ) ) while cursor.fetchone() is not None: next_id = Database.generate_id() - cursor.execute( Object_type.sql_id_exists( next_id ) ) + cursor.execute( self.unescape( Object_type.sql_id_exists( next_id ) ) ) # save a new object with the next_id to the database obj = Object_type( next_id ) - cursor.execute( obj.sql_create() ) + cursor.execute( self.unescape( obj.sql_create() ) ) if commit: connection.commit() diff --git a/controller/test/Test_notebooks.py b/controller/test/Test_notebooks.py index b756c1c..1e3345c 100644 --- a/controller/test/Test_notebooks.py +++ b/controller/test/Test_notebooks.py @@ -3363,6 +3363,44 @@ class Test_notebooks( Test_controller ): assert note.contents == contents + " bar" assert note.user_id == self.user.object_id + def test_save_new_note_with_backslashes( self ): + self.login() + + # save a completely new note + contents = r"

newest title

c:\windows\foo\bar\baz.exe" + new_note = Note.create( "55", contents ) + previous_revision = new_note.revision + result = self.http_post( "/notebooks/save_note/", dict( + notebook_id = self.notebook.object_id, + note_id = new_note.object_id, + contents = new_note.contents, + startup = False, + previous_revision = None, + ), session_id = self.session_id ) + + assert result[ "new_revision" ] + assert result[ "new_revision" ] != previous_revision + assert result[ "new_revision" ].user_id == self.user.object_id + assert result[ "new_revision" ].username == self.username + assert result[ "previous_revision" ] == None + user = self.database.load( User, self.user.object_id ) + assert user.storage_bytes > 0 + assert result[ "storage_bytes" ] == user.storage_bytes + assert result[ "rank" ] == 0.0 + + # make sure the new title is now loadable + result = self.http_post( "/notebooks/load_note_by_title/", dict( + notebook_id = self.notebook.object_id, + note_title = new_note.title, + ), session_id = self.session_id ) + + note = result[ "note" ] + + assert note.object_id == new_note.object_id + assert note.title == new_note.title + assert note.contents == contents + assert note.user_id == self.user.object_id + def test_save_two_new_notes( self, startup = False ): self.login()