99
1010"""Utility functions for storing and retrieving user configuration settings."""
1111import os
12- import traceback
1312import json
1413
1514from flask import Response , request , render_template , url_for , current_app
1615from flask_babel import gettext
1716from flask_login import current_user
18- from selenium .webdriver .support .expected_conditions import \
19- element_selection_state_to_be
20- from sqlalchemy import false
2117
2218from pgadmin .user_login_check import pga_login_required
2319from pgadmin .utils import PgAdminModule
2925from pgadmin .utils .constants import MIMETYPE_APP_JS
3026from .utils import get_dialog_type , get_file_type_setting
3127from cryptography .fernet import Fernet
28+ import hashlib
29+ from urllib .parse import unquote
30+ from pgadmin .utils .preferences import Preferences
31+ from pgadmin .utils import get_storage_directory
3232
3333MODULE_NAME = 'settings'
3434
@@ -266,8 +266,6 @@ def get_file_format_setting():
266266 info = get_file_type_setting (list (data .values ())))
267267
268268
269-
270-
271269@blueprint .route (
272270 '/save_application_state' ,
273271 methods = ["POST" ], endpoint = 'save_application_state'
@@ -284,10 +282,12 @@ def save_application_state():
284282 tool_data = fernet .encrypt (json .dumps (data ['tool_data' ]).encode ())
285283 connection_info = data ['connection_info' ] \
286284 if 'connection_info' in data else None
287- if 'open_file_name' in connection_info and connection_info ['open_file_name' ] and 'is_editor_dirty' in connection_info and connection_info ['is_editor_dirty' ]:
288- last_saved_file_hash = compute_sha256_large_file (connection_info ['open_file_name' ])
289- print (last_saved_file_hash )
290- connection_info ['last_saved_file_hash' ] = last_saved_file_hash
285+ if ('open_file_name' in connection_info and
286+ connection_info ['open_file_name' ]):
287+ file_path = get_file_path (connection_info ['open_file_name' ],
288+ connection_info ['storage' ])
289+ connection_info ['last_saved_file_hash' ] = (
290+ get_last_saved_file_hash (file_path , trans_id ))
291291
292292 try :
293293 data_entry = ApplicationState (
@@ -304,8 +304,28 @@ def save_application_state():
304304 data = {
305305 'status' : True ,
306306 'msg' : 'Success' ,
307- }
308- )
307+ })
308+
309+
310+ def get_last_saved_file_hash (file_path , trans_id ):
311+ result = db .session \
312+ .query (ApplicationState ) \
313+ .filter (ApplicationState .uid == current_user .id ,
314+ ApplicationState .id == trans_id ).all ()
315+ file_hash_update_require = True
316+ last_saved_file_hash = None
317+
318+ for row in result :
319+ connection_info = row .connection_info
320+ if ('open_file_name' in connection_info and
321+ connection_info ['open_file_name' ]):
322+ file_hash_update_require = not connection_info ['is_editor_dirty' ]
323+ last_saved_file_hash = connection_info ['last_saved_file_hash' ]
324+
325+ if file_hash_update_require :
326+ last_saved_file_hash = compute_sha256_large_file (file_path )
327+
328+ return last_saved_file_hash
309329
310330
311331@blueprint .route (
@@ -326,22 +346,19 @@ def get_application_state():
326346 res = []
327347 for row in result :
328348 connection_info = row .connection_info
329- print (connection_info )
330- if 'open_file_name' in connection_info and connection_info ['open_file_name' ]:
331- file_path = connection_info ['open_file_name' ]
349+ if ('open_file_name' in connection_info and
350+ connection_info ['open_file_name' ]):
351+ file_path = get_file_path (
352+ connection_info ['open_file_name' ], connection_info ['storage' ])
332353 file_deleted = False if os .path .exists (file_path ) else True
333354 connection_info ['file_deleted' ] = file_deleted
334- if not file_deleted and connection_info ['is_editor_dirty' ]:
335- if 'last_saved_file_hash' in connection_info and connection_info ['last_saved_file_hash' ]:
336- connection_info ['external_file_changes' ] = check_external_file_changes (file_path , connection_info ['last_saved_file_hash' ])
337-
338355
339- # if 'open_file_name' in connection_info and connection_info['open_file_name']:
340- # initial_file_hash = connection_info['initial_file_hash']
341- # file_deleted, file_modified_in_pgadmin, file_modified_externally = detect_file_change( connection_info['open_file_name'], tool_data, initial_file_hash )
342- # connection_info['file_deleted '] = file_deleted
343- # connection_info['file_modified_in_pgadmin'] = file_modified_in_pgadmin
344- # connection_info['file_modified_externally'] = file_modified_externally
356+ if ( not file_deleted and connection_info ['is_editor_dirty' ] and
357+ 'last_saved_file_hash' in connection_info and
358+ connection_info ['last_saved_file_hash' ]):
359+ connection_info ['external_file_changes ' ] = \
360+ check_external_file_changes (
361+ file_path , connection_info ['last_saved_file_hash' ])
345362
346363 res .append ({'tool_name' : row .tool_name ,
347364 'connection_info' : connection_info ,
@@ -357,6 +374,31 @@ def get_application_state():
357374 )
358375
359376
377+ def get_file_path (file_name , storage ):
378+
379+ file_path = unquote (file_name )
380+
381+ # get the current storage from request if available
382+ # or get it from last_storage preference.
383+ if storage :
384+ storage_folder = storage
385+ else :
386+ storage_folder = Preferences .module ('file_manager' ).preference (
387+ 'last_storage' ).get ()
388+
389+ # retrieve storage directory path
390+ storage_manager_path = get_storage_directory (
391+ shared_storage = storage_folder )
392+
393+ if storage_manager_path :
394+ # generate full path of file
395+ file_path = os .path .join (
396+ storage_manager_path ,
397+ file_path .lstrip ('/' ).lstrip ('\\ ' )
398+ )
399+ return file_path
400+
401+
360402@blueprint .route (
361403 '/delete_application_state/' ,
362404 methods = ["DELETE" ], endpoint = 'delete_application_state' )
@@ -397,60 +439,33 @@ def delete_tool_data(trans_id=None):
397439 return False , str (e )
398440
399441
400- import hashlib
401-
402- def compute_sha256_large_data_in_memory (data ):
442+ def compute_sha256_large_data_in_memory (data , chunk_size = 8192 ):
403443 """Hash large data (in-memory) by processing in chunks."""
404- sha256_hash = hashlib .sha256 ()
444+ md5_hash = hashlib .md5 ()
405445 # Process data in 8 KB chunks
406446 string_data = json .loads (data )
407- chunk_size = 8192
408447 for i in range (0 , len (string_data ), chunk_size ):
409448 chunk = string_data [i :i + chunk_size ]
410- sha256_hash .update (chunk .encode ("utf-8" ))
449+ md5_hash .update (chunk .encode ("utf-8" ))
411450
412- return sha256_hash .hexdigest ()
451+ return md5_hash .hexdigest ()
413452
414453
415- def compute_sha256_large_file (file_path ):
454+ def compute_sha256_large_file (file_path , chunk_size = 8192 ):
416455 """Compute SHA-256 hash for large files by reading in chunks."""
417- sha256_hash = hashlib .sha256 ()
456+ md5_hash = hashlib .md5 ()
418457
419458 # Open the file in binary mode
420459 with open (file_path , "rb" ) as file :
421460 # Read and hash in 8 KB chunks (can adjust the chunk size if needed)
422- for chunk in iter (lambda : file .read (8192 ), b"" ):
423- print (chunk )
424- sha256_hash .update (chunk )
425-
426- return sha256_hash .hexdigest ()
461+ for chunk in iter (lambda : file .read (chunk_size ), b"" ):
462+ md5_hash .update (chunk )
427463
428-
429- def detect_file_change (file_path , data , initial_file_hash ):
430- file_deleted = False
431- file_modified_in_pgadmin = False
432- file_modified_externally = False
433- if os .path .exists (file_path ):
434- current_file_hash = compute_sha256_large_file (file_path )
435- stored_data_hash = compute_sha256_large_data_in_memory (data )
436- if stored_data_hash != current_file_hash :
437- if stored_data_hash != initial_file_hash :
438- # file changes in pgadmin
439- file_modified_in_pgadmin = True
440-
441- if current_file_hash != initial_file_hash :
442- # file is changed externally
443- file_modified_externally = True
444-
445- else :
446- file_deleted = True
447- file_modified_in_pgadmin = True
448- return file_deleted , file_modified_in_pgadmin , file_modified_externally
464+ return md5_hash .hexdigest ()
449465
450466
451467def check_external_file_changes (file_path , last_saved_file_hash ):
452468 current_file_hash = compute_sha256_large_file (file_path )
453469 if current_file_hash != last_saved_file_hash :
454470 return True
455471 return False
456-
0 commit comments