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
32+ from pgadmin .misc .file_manager import Filemanager
3233
3334MODULE_NAME = 'settings'
3435
@@ -266,8 +267,6 @@ def get_file_format_setting():
266267 info = get_file_type_setting (list (data .values ())))
267268
268269
269-
270-
271270@blueprint .route (
272271 '/save_application_state' ,
273272 methods = ["POST" ], endpoint = 'save_application_state'
@@ -284,10 +283,12 @@ def save_application_state():
284283 tool_data = fernet .encrypt (json .dumps (data ['tool_data' ]).encode ())
285284 connection_info = data ['connection_info' ] \
286285 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
286+ if ('open_file_name' in connection_info and
287+ connection_info ['open_file_name' ]):
288+ file_path = get_file_path (connection_info ['open_file_name' ],
289+ connection_info ['storage' ])
290+ connection_info ['last_saved_file_hash' ] = (
291+ get_last_saved_file_hash (file_path , trans_id ))
291292
292293 try :
293294 data_entry = ApplicationState (
@@ -304,8 +305,28 @@ def save_application_state():
304305 data = {
305306 'status' : True ,
306307 'msg' : 'Success' ,
307- }
308- )
308+ })
309+
310+
311+ def get_last_saved_file_hash (file_path , trans_id ):
312+ result = db .session \
313+ .query (ApplicationState ) \
314+ .filter (ApplicationState .uid == current_user .id ,
315+ ApplicationState .id == trans_id ).all ()
316+ file_hash_update_require = True
317+ last_saved_file_hash = None
318+
319+ for row in result :
320+ connection_info = row .connection_info
321+ if ('open_file_name' in connection_info and
322+ connection_info ['open_file_name' ]):
323+ file_hash_update_require = not connection_info ['is_editor_dirty' ]
324+ last_saved_file_hash = connection_info ['last_saved_file_hash' ]
325+
326+ if file_hash_update_require :
327+ last_saved_file_hash = compute_sha256_large_file (file_path )
328+
329+ return last_saved_file_hash
309330
310331
311332@blueprint .route (
@@ -326,22 +347,19 @@ def get_application_state():
326347 res = []
327348 for row in result :
328349 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' ]
350+ if ('open_file_name' in connection_info and
351+ connection_info ['open_file_name' ]):
352+ file_path = get_file_path (
353+ connection_info ['open_file_name' ], connection_info ['storage' ])
332354 file_deleted = False if os .path .exists (file_path ) else True
333355 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' ])
337356
338-
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
357+ if (not file_deleted and connection_info ['is_editor_dirty' ] and
358+ 'last_saved_file_hash' in connection_info and
359+ connection_info ['last_saved_file_hash' ]):
360+ connection_info ['external_file_changes' ] = \
361+ check_external_file_changes (
362+ file_path , connection_info ['last_saved_file_hash' ])
345363
346364 res .append ({'tool_name' : row .tool_name ,
347365 'connection_info' : connection_info ,
@@ -357,6 +375,36 @@ def get_application_state():
357375 )
358376
359377
378+ def get_file_path (file_name , storage ):
379+
380+ file_path = unquote (file_name )
381+
382+ # get the current storage from request if available
383+ # or get it from last_storage preference.
384+ if storage :
385+ storage_folder = storage
386+ else :
387+ storage_folder = Preferences .module ('file_manager' ).preference (
388+ 'last_storage' ).get ()
389+
390+ # retrieve storage directory path
391+ storage_manager_path = get_storage_directory (
392+ shared_storage = storage_folder )
393+
394+ try :
395+ Filemanager .check_access_permission (storage_manager_path , file_path )
396+ except Exception as e :
397+ return internal_server_error (errormsg = str (e ))
398+
399+ if storage_manager_path :
400+ # generate full path of file
401+ file_path = os .path .join (
402+ storage_manager_path ,
403+ file_path .lstrip ('/' ).lstrip ('\\ ' )
404+ )
405+ return file_path
406+
407+
360408@blueprint .route (
361409 '/delete_application_state/' ,
362410 methods = ["DELETE" ], endpoint = 'delete_application_state' )
@@ -397,60 +445,33 @@ def delete_tool_data(trans_id=None):
397445 return False , str (e )
398446
399447
400- import hashlib
401-
402- def compute_sha256_large_data_in_memory (data ):
448+ def compute_sha256_large_data_in_memory (data , chunk_size = 8192 ):
403449 """Hash large data (in-memory) by processing in chunks."""
404- sha256_hash = hashlib .sha256 ()
450+ md5_hash = hashlib .md5 ()
405451 # Process data in 8 KB chunks
406452 string_data = json .loads (data )
407- chunk_size = 8192
408453 for i in range (0 , len (string_data ), chunk_size ):
409454 chunk = string_data [i :i + chunk_size ]
410- sha256_hash .update (chunk .encode ("utf-8" ))
455+ md5_hash .update (chunk .encode ("utf-8" ))
411456
412- return sha256_hash .hexdigest ()
457+ return md5_hash .hexdigest ()
413458
414459
415- def compute_sha256_large_file (file_path ):
460+ def compute_sha256_large_file (file_path , chunk_size = 8192 ):
416461 """Compute SHA-256 hash for large files by reading in chunks."""
417- sha256_hash = hashlib .sha256 ()
462+ md5_hash = hashlib .md5 ()
418463
419464 # Open the file in binary mode
420465 with open (file_path , "rb" ) as file :
421466 # 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 ()
427-
467+ for chunk in iter (lambda : file .read (chunk_size ), b"" ):
468+ md5_hash .update (chunk )
428469
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
470+ return md5_hash .hexdigest ()
449471
450472
451473def check_external_file_changes (file_path , last_saved_file_hash ):
452474 current_file_hash = compute_sha256_large_file (file_path )
453475 if current_file_hash != last_saved_file_hash :
454476 return True
455477 return False
456-
0 commit comments