11import json
22import math
33import os
4+ import re
5+
46import requests
57import cryptography
68major , minor , patch = [int (x , 10 ) for x in cryptography .__version__ .split ('.' )]
1618 UploadFileException , DeletePackageException , KeycodeRequiredException , GetPackageInformationFailedException , \
1719 UploadKeycodeException , AddRecipientFailedException , UpdateRecipientFailedException , UploadMessageException , \
1820 GetPublicKeysFailedException , GetFileInformationException , DeleteFileException , GetPackageMessageException , \
19- AddFileFailedException
21+ AddFileFailedException , MoveFileException , GetDirectoryException , DeleteDirectoryException , \
22+ RenameDirectoryException , UpdatePackageException , MoveDirectoryException , CreateDirectoryException
2023
2124from sendsafely .utilities import _generate_keycode , make_headers , _encrypt_message , _encrypt_file_part , _upload_file_part_to_s3 , \
2225 _calculate_package_checksum , _decrypt_message , _get_upload_urls , _get_download_urls , _update_file_completion_status , _encrypt_keycode , \
@@ -28,7 +31,7 @@ class Package:
2831 To be used in conjunction with it's handler the SendSafely object. Should not be instantiated directly.
2932 """
3033
31- def __init__ (self , sendsafely_instance , package_variables = None ):
34+ def __init__ (self , sendsafely_instance , package_variables = None , workspace = False ):
3235 """
3336 :param sendsafely_instance: The authenticated SendSafely object.
3437 :param package_variables:
@@ -39,7 +42,10 @@ def __init__(self, sendsafely_instance, package_variables=None):
3942 if package_variables is None :
4043 self .client_secret = _generate_keycode ()
4144 self .sendsafely = sendsafely_instance
42- data = {"vdr" : "false" }
45+ if workspace :
46+ data = {"vdr" : "true" }
47+ else :
48+ data = {"vdr" : "false" }
4349 endpoint = "/package"
4450 url = self .sendsafely .BASE_URL + endpoint
4551 headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint ,
@@ -181,7 +187,7 @@ def encrypt_and_upload_file(self, filepath, directory_id=None, progress_instance
181187 progress = progress + 1
182188 part = part + 25
183189 file .close ()
184- response = _update_file_completion_status (self , file_id = file_id , complete = True )
190+ response = _update_file_completion_status (self , file_id = file_id , directory_id = directory_id , complete = True )
185191 response ["fileId" ] = file_id
186192 return response
187193 except Exception as e :
@@ -276,17 +282,20 @@ def _add_file(self, filename, filesize, parts=1, directory_id=None):
276282 raise AddFileFailedException (details = response ["message" ])
277283 return response
278284
279- def delete_file_from_package (self , file_id ):
285+ def delete_file_from_package (self , file_id , directory_id = None ):
280286 """
281287 Deletes the file with the specified id from the package with the specified ID
282288 """
283- endpoint = "/package/" + self .package_id + "/file/" + file_id
289+ if directory_id :
290+ endpoint = "/package/" + self .package_id + "/directory/" + directory_id + "/file/" + file_id
291+ else :
292+ endpoint = "/package/" + self .package_id + "/file/" + file_id
284293 url = self .sendsafely .BASE_URL + endpoint
285294 headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint )
286295 try :
287296 response = requests .delete (url = url , headers = headers ).json ()
288297 except Exception as e :
289- raise DeleteFileException (details = e )
298+ raise DeleteFileException (details = str ( e ) )
290299 if response ["response" ] != "SUCCESS" :
291300 raise DeleteFileException (details = response ["message" ])
292301 return response
@@ -315,6 +324,7 @@ def download_and_decrypt_file(self, file_id, directory_id=None, download_directo
315324 if not file_name :
316325 file_name = file_info ["fileName" ]
317326 total = file_info ["fileParts" ]
327+ file_name = re .sub (r'[<>:\"/\\|?*]' , '_' , file_name )
318328 file_path = download_directory + "/" + file_name
319329 passphrase = self .server_secret + self .client_secret
320330 progress = 1
@@ -338,6 +348,111 @@ def download_and_decrypt_file(self, file_id, directory_id=None, download_directo
338348 except Exception as e :
339349 raise DownloadFileException (details = str (e ))
340350
351+ def update_workspace_name (self , workspace_name ):
352+ """
353+ Rename a Workspace (packageLabel)
354+ """
355+ endpoint = "/package/" + self .package_id
356+ url = self .sendsafely .BASE_URL + endpoint
357+ body = {"label" : workspace_name }
358+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint , request_body = json .dumps (body ))
359+ try :
360+ response = requests .post (url = url , headers = headers , json = body ).json ()
361+ except Exception as e :
362+ raise UpdatePackageException (details = str (e ))
363+
364+ if response ["response" ] != "SUCCESS" :
365+ raise UpdatePackageException (details = response ["message" ])
366+ return response
367+
368+ def move_file (self , file_id , destination_directory_id ):
369+ """
370+ Moves a Workspace file with the specified id to the directory with the specified ID
371+ """
372+ endpoint = "/package/" + self .package_id + "/directory/" + destination_directory_id + "/file/" + file_id
373+ url = self .sendsafely .BASE_URL + endpoint
374+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint )
375+ try :
376+ response = requests .post (url = url , headers = headers ).json ()
377+ except Exception as e :
378+ raise MoveFileException (details = str (e ))
379+
380+ if response ["response" ] != "SUCCESS" :
381+ raise MoveFileException (details = response ["message" ])
382+ return response
383+
384+ def create_directory (self , directory_name , source_directory_id = None ):
385+ if not source_directory_id :
386+ source_directory_id = self .sendsafely .get_package_information (self .package_id )["rootDirectoryId" ]
387+ endpoint = "/package/" + self .package_id + "/directory/" + source_directory_id + "/subdirectory/"
388+ url = self .sendsafely .BASE_URL + endpoint
389+ body = {"directoryName" : directory_name }
390+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint , request_body = json .dumps (body ))
391+ try :
392+ response = requests .put (url = url , headers = headers , json = body ).json ()
393+ except Exception as e :
394+ raise CreateDirectoryException (details = str (e ))
395+
396+ if response ["response" ] != "SUCCESS" :
397+ raise CreateDirectoryException (details = response ["message" ])
398+ return response
399+
400+ def move_directory (self , source_directory_id , target_directory_id ):
401+ """
402+ Moves a Workspace directory with the specified id to the directory with the specified ID
403+ """
404+ endpoint = "/package/" + self .package_id + "/move/" + source_directory_id + "/" + target_directory_id
405+ url = self .sendsafely .BASE_URL + endpoint
406+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint )
407+ try :
408+ response = requests .post (url = url , headers = headers ).json ()
409+ except Exception as e :
410+ raise MoveDirectoryException (details = str (e ))
411+
412+ if response ["response" ] != "SUCCESS" :
413+ raise MoveDirectoryException (details = response ["message" ])
414+ return response
415+
416+ def get_directory_information (self , directory_id ):
417+ endpoint = "/package/" + self .package_id + "/directory/" + directory_id
418+ url = self .sendsafely .BASE_URL + endpoint
419+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint )
420+ try :
421+ response = requests .get (url = url , headers = headers ).json ()
422+ except Exception as e :
423+ raise GetDirectoryException (details = str (e ))
424+
425+ if response ["response" ] != "SUCCESS" :
426+ raise GetDirectoryException (details = response ["message" ])
427+ return response
428+
429+ def delete_directory (self , directory_id ):
430+ endpoint = "/package/" + self .package_id + "/directory/" + directory_id
431+ url = self .sendsafely .BASE_URL + endpoint
432+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint )
433+ try :
434+ response = requests .delete (url = url , headers = headers ).json ()
435+ except Exception as e :
436+ raise DeleteDirectoryException (details = str (e ))
437+
438+ if response ["response" ] != "SUCCESS" :
439+ raise DeleteDirectoryException (details = response ["message" ])
440+ return response
441+
442+ def rename_directory (self , directory_id , directory_name ):
443+ endpoint = "/package/" + self .package_id + "/directory/" + directory_id
444+ url = self .sendsafely .BASE_URL + endpoint
445+ body = {"directoryName" : directory_name }
446+ headers = make_headers (self .sendsafely .API_SECRET , self .sendsafely .API_KEY , endpoint , request_body = json .dumps (body ))
447+ try :
448+ response = requests .post (url , headers = headers , json = body ).json ()
449+ except Exception as e :
450+ raise RenameDirectoryException (details = str (e ))
451+
452+ if response ["response" ] != "SUCCESS" :
453+ raise RenameDirectoryException (details = response ["message" ])
454+ return response
455+
341456 def _block_operation_without_keycode (self ):
342457 if not self .initialized_via_keycode :
343458 raise KeycodeRequiredException ()
@@ -350,3 +465,4 @@ def calculate_progress(self, file_id, current, total, progress_instance):
350465 progress_instance .update_progress (file_id , percent )
351466
352467
468+
0 commit comments