@@ -64,9 +64,9 @@ def update_backup_location(self):
6464 if not self .backup_dir :
6565 self .backup_dir = "/storage/backup" # Default location
6666
67- # Validate that local path doesn't contain network protocols
68- if self .backup_dir and (self .backup_dir .startswith (('nfs:' , 'smb:' , 'ftp:' , 'sftp:' , 'http:' , 'https:' )) or '://' in self .backup_dir ):
69- xbmc .log (f"Invalid local path detected (contains network protocol): { self .backup_dir } " , xbmc .LOGWARNING )
67+ # Validate that local path doesn't contain network protocols or remote path formats
68+ if self .backup_dir and (self .backup_dir .startswith (('nfs:' , 'smb:' , 'ftp:' , 'sftp:' , 'http:' , 'https:' )) or '://' in self .backup_dir or ':' in self . backup_dir ):
69+ xbmc .log (f"Invalid local path detected (contains network protocol or remote path format ): { self .backup_dir } " , xbmc .LOGWARNING )
7070 # Reset to default if invalid
7171 self .backup_dir = "/storage/backup"
7272 self .addon .setSetting ('backup_location' , self .backup_dir )
@@ -145,13 +145,16 @@ def connect_remote(self):
145145 if self .remote_type == 0 : # SMB
146146 # Use Kodi's built-in SMB support via xbmcvfs
147147 # Construct SMB URL properly
148+ # remote_path is in format: server/share
149+ # Convert to: smb://server/share
150+ smb_path = self .remote_path .replace (':' , '/' ) # Just in case there's still a colon
148151 if self .remote_username and self .remote_password :
149- remote_url = f"smb://{ self .remote_username } :{ urllib .parse .quote (self .remote_password )} @{ self . remote_path } "
152+ remote_url = f"smb://{ self .remote_username } :{ urllib .parse .quote (self .remote_password )} @{ smb_path } "
150153 elif self .remote_username :
151- remote_url = f"smb://{ self .remote_username } @{ self . remote_path } "
154+ remote_url = f"smb://{ self .remote_username } @{ smb_path } "
152155 else :
153- remote_url = f"smb://{ self . remote_path } "
154-
156+ remote_url = f"smb://{ smb_path } "
157+
155158 self .remote_connection = remote_url
156159 # Test connection by trying to list directory
157160 dirs , files = xbmcvfs .listdir (remote_url )
@@ -1287,60 +1290,66 @@ def create_backup(self, backup_name=None):
12871290 def get_all_backups (self ):
12881291 """Get list of all available backup files"""
12891292 self .update_backup_location ()
1290-
1293+
12911294 if self .location_type == 0 : # Local
12921295 backup_pattern = os .path .join (self .backup_dir , 'backup_*.zip' )
12931296 return sorted (glob .glob (backup_pattern ))
12941297 else : # Remote
12951298 try :
12961299 # Connect to remote location
1297- if self .location_type == 1 : # WebDAV
1298- if not self .webdav :
1299- self .webdav = self .connect_webdav ()
1300- if not self .webdav :
1301- return []
1302-
1303- # List files from WebDAV
1304- xbmc .log (f"Listing WebDAV files from: { self .webdav_url } " , xbmc .LOGINFO )
1305- xbmc .log (f"Using WebDAV credentials: username={ self .webdav_username } , password=****************" , xbmc .LOGINFO )
1306-
1307- try :
1308- response = self .webdav .list (self .webdav_path )
1309- xbmc .log (f"WebDAV PROPFIND response status: { response .status_code } " , xbmc .LOGINFO )
1310- xbmc .log (f"WebDAV response headers: { response .headers } " , xbmc .LOGINFO )
1311- xbmc .log (f"WebDAV response text: { response .text } " , xbmc .LOGINFO )
1312-
1313- if response .status_code == 207 : # Multi-status
1314- files = []
1315- # Parse XML response
1316- for line in response .text .split ('\n ' ):
1317- if '<D:href>' in line :
1318- href = line .strip ().replace ('<D:href>' , '' ).replace ('</D:href>' , '' )
1319- if href .endswith ('.zip' ):
1320- files .append (href )
1321- elif '<D:displayname>' in line :
1322- name = line .strip ().replace ('<D:displayname>' , '' ).replace ('</D:displayname>' , '' )
1323- if name .endswith ('.zip' ):
1324- xbmc .log (f"Found backup file: { name } " , xbmc .LOGINFO )
1325- files .append (name )
1326-
1327- # Remove duplicates and sort
1328- files = sorted (list (set (files )))
1329- xbmc .log (f"Final list of backup files found: { files } " , xbmc .LOGINFO )
1330- xbmc .log (f"Found { len (files )} backup files via WebDAV" , xbmc .LOGINFO )
1331- return files
1332- else :
1333- xbmc .log (f"WebDAV PROPFIND failed with status: { response .status_code } " , xbmc .LOGERROR )
1334- return []
1335-
1336- except Exception as e :
1337- xbmc .log (f"Error listing WebDAV files: { str (e )} " , xbmc .LOGERROR )
1338- return []
1300+ if not self .connect_remote ():
1301+ xbmc .log ("Failed to connect to remote location for listing backups" , xbmc .LOGERROR )
1302+ return []
1303+
1304+ # List files based on remote type
1305+ files = self .list_remote_files ()
1306+
1307+ # Filter for backup files (backup_*.zip)
1308+ backup_files = [f for f in files if f .startswith ('backup_' ) and f .endswith ('.zip' )]
1309+
1310+ # Sort by modification time (newest first) if possible
1311+ try :
1312+ backup_files_with_time = []
1313+ for f in backup_files :
1314+ # Get file info if available
1315+ try :
1316+ if self .remote_type == 0 : # SMB
1317+ # For SMB, we can't easily get timestamps via xbmcvfs
1318+ backup_files_with_time .append ((f , 0 ))
1319+ elif self .remote_type == 1 : # NFS
1320+ stat = os .stat (os .path .join (self .remote_connection , f ))
1321+ backup_files_with_time .append ((f , stat .st_mtime ))
1322+ elif self .remote_type == 2 : # FTP
1323+ # FTP doesn't provide easy timestamp access
1324+ backup_files_with_time .append ((f , 0 ))
1325+ elif self .remote_type == 3 : # SFTP
1326+ stat = self .remote_connection .stat (f )
1327+ backup_files_with_time .append ((f , stat .st_mtime ))
1328+ elif self .remote_type == 4 : # WebDAV
1329+ # WebDAV timestamps are complex, use 0
1330+ backup_files_with_time .append ((f , 0 ))
1331+ except :
1332+ backup_files_with_time .append ((f , 0 ))
1333+
1334+ # Sort by timestamp (newest first)
1335+ backup_files_with_time .sort (key = lambda x : x [1 ], reverse = True )
1336+ backup_files = [f [0 ] for f in backup_files_with_time ]
1337+ except Exception as e :
1338+ xbmc .log (f"Error sorting backup files by time: { str (e )} " , xbmc .LOGWARNING )
1339+ # Fall back to alphabetical sorting
1340+ backup_files .sort (reverse = True )
1341+
1342+ xbmc .log (f"Found { len (backup_files )} backup files: { backup_files } " , xbmc .LOGINFO )
1343+ return backup_files
1344+
13391345 except Exception as e :
13401346 xbmc .log (f"Error getting remote backups: { str (e )} " , xbmc .LOGERROR )
13411347 import traceback
13421348 xbmc .log (f"Traceback: { traceback .format_exc ()} " , xbmc .LOGERROR )
13431349 return []
1350+ finally :
1351+ # Disconnect from remote location
1352+ self .disconnect_remote ()
13441353
13451354 def show_rotation_warning (self ):
13461355 """Show warning dialog when enabling backup rotation"""
0 commit comments