diff --git a/cryptlex/lexfloatclient/__init__.py b/cryptlex/lexfloatclient/__init__.py index 2a0e3db..6d85a8c 100644 --- a/cryptlex/lexfloatclient/__init__.py +++ b/cryptlex/lexfloatclient/__init__.py @@ -1 +1 @@ -from cryptlex.lexfloatclient.lexfloatclient import LexFloatClient, LexFloatStatusCodes, LexFloatClientException +from cryptlex.lexfloatclient.lexfloatclient import LexFloatClient, LexFloatStatusCodes, LexFloatClientException, PermissionFlags diff --git a/cryptlex/lexfloatclient/lexfloatclient.py b/cryptlex/lexfloatclient/lexfloatclient.py index 9f6c0cc..7499943 100644 --- a/cryptlex/lexfloatclient/lexfloatclient.py +++ b/cryptlex/lexfloatclient/lexfloatclient.py @@ -1,10 +1,14 @@ import ctypes +import json from cryptlex.lexfloatclient import lexfloatclient_native as LexFloatClientNative from cryptlex.lexfloatclient.lexfloatstatus_codes import LexFloatStatusCodes from cryptlex.lexfloatclient.lexfloatclient_exception import LexFloatClientException callback_list = [] +class PermissionFlags: + LF_USER = 10 + LF_ALL_USERS = 11 class HostLicenseMeterAttribute(object): def __init__(self, name, allowed_uses, total_uses, gross_uses): @@ -19,6 +23,11 @@ def __init__(self, name, enabled, data): self.enabled = enabled self.data = data +class HostConfig(object): + def __init__(self, max_offline_lease_duration): + self.max_offline_lease_duration = max_offline_lease_duration + + class LexFloatClient: @staticmethod def SetHostProductId(product_id): @@ -100,6 +109,30 @@ def SetFloatingClientMetadata(key, value): cstring_key, cstring_value) if LexFloatStatusCodes.LF_OK != status: raise LexFloatClientException(status) + + @staticmethod + def SetPermissionFlag(flag): + """Sets the permission flag. + + This function must be called on every start of your program after SetHostProductId() + function in case the application allows borrowing of licenses or system wide activation. + + Args: + flags : depending on your application's requirements, choose one of + the following values: LF_USER, LF_ALL_USERS. + + LF_USER: This flag indicates that the application does not require + admin or root permissions to run. + + LF_ALL_USERS: This flag is specifically designed for Windows and should be used + for system-wide activations. + + Raises: + LexFloatClientException + """ + status = LexFloatClientNative.SetPermissionFlag(flag) + if LexFloatStatusCodes.LF_OK != status: + raise LexFloatClientException(status) @staticmethod def GetFloatingClientLibraryVersion(): @@ -117,7 +150,30 @@ def GetFloatingClientLibraryVersion(): status = LexFloatClientNative.GetFloatingClientLibraryVersion(buffer,buffer_size) if status != LexFloatStatusCodes.LF_OK: raise LexFloatClientException(status) - return LexFloatClientNative.byte_to_string(buffer.value) + return LexFloatClientNative.byte_to_string(buffer.value) + + @staticmethod + def GetHostConfig(): + """This function sends a network request to LexFloatServer to get the configuration details. + + Raises: + LexFloatClientException + + Returns: + HostConfig: host configuration. + """ + buffer_size = 1024 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetHostConfig(buffer, buffer_size) + if status == LexFloatStatusCodes.LF_OK: + host_config_json = LexFloatClientNative.byte_to_string(buffer.value) + if not host_config_json.strip(): + return None + else: + host_config = json.loads(host_config_json) + return HostConfig(host_config["maxOfflineLeaseDuration"]) + else: + raise LexFloatClientException(status) @staticmethod def GetHostProductVersionName(): @@ -244,6 +300,24 @@ def GetHostLicenseExpiryDate(): return expiry_date.value else: raise LexFloatClientException(status) + + @staticmethod + def GetFloatingClientLeaseExpiryDate(): + """Gets the lease expiry date timestamp of the floating client. + + Raises: + LexFloatClientException + + Returns: + int: the timestamp + """ + leaseExpiryDate = ctypes.c_uint() + status = LexFloatClientNative.GetFloatingClientLeaseExpiryDate( + ctypes.byref(leaseExpiryDate)) + if status == LexFloatStatusCodes.LF_OK: + return leaseExpiryDate.value + else: + raise LexFloatClientException(status) @staticmethod def GetFloatingClientMeterAttributeUses(name): @@ -266,6 +340,45 @@ def GetFloatingClientMeterAttributeUses(name): return uses.value else: raise LexFloatClientException(status) + + @staticmethod + def GetFloatingLicenseMode(): + """Gets the mode of the floating license (online or offline). + + Raises: + LexActivatorException + + Returns: + ActivationMode: mode of floating license. + """ + buffer_size = 256 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetFloatingLicenseMode(buffer,buffer_size) + if status != LexFloatStatusCodes.LF_OK: + raise LexFloatClientException(status) + return LexFloatClientNative.byte_to_string(buffer.value) + + @staticmethod + def GetFloatingClientMetadata(key): + """Gets the value of the floating client metadata. + + Args: + key (str): metadata key to retrieve the value + + Raises: + LexFloatClientException + + Returns: + str: value of the floating client metadata + """ + cstring_key = LexFloatClientNative.get_ctype_string(key) + buffer_size = 4096 + buffer = LexFloatClientNative.get_ctype_string_buffer(buffer_size) + status = LexFloatClientNative.GetFloatingClientMetadata( + cstring_key, buffer, buffer_size) + if status != LexFloatStatusCodes.LF_OK: + raise LexFloatClientException(status) + return LexFloatClientNative.byte_to_string(buffer.value) @staticmethod def RequestFloatingLicense(): @@ -278,6 +391,20 @@ def RequestFloatingLicense(): if LexFloatStatusCodes.LF_OK != status: raise LexFloatClientException(status) + @staticmethod + def RequestOfflineFloatingLicense(lease_duration): + """Sends the request to lease the license from the LexFloatServer for offline usage. + + Args: + leaseDuration (int): seconds for which the lease should be obtained. + + Raises: + LexFloatClientException + """ + status = LexFloatClientNative.RequestOfflineFloatingLicense(lease_duration) + if LexFloatStatusCodes.LF_OK != status: + raise LexFloatClientException(status) + @staticmethod def DropFloatingLicense(): """Sends the request to the LexFloatServer to free the license. diff --git a/cryptlex/lexfloatclient/lexfloatclient_exception.py b/cryptlex/lexfloatclient/lexfloatclient_exception.py index 391efca..4c15166 100644 --- a/cryptlex/lexfloatclient/lexfloatclient_exception.py +++ b/cryptlex/lexfloatclient/lexfloatclient_exception.py @@ -64,4 +64,20 @@ def get_error_message(code): return 'The server license has been suspended.' if code == LexFloatStatusCodes.LF_E_SERVER_LICENSE_GRACE_PERIOD_OVER: return 'The grace period for server license is over.' + if code == LexFloatStatusCodes.LF_E_SYSTEM_PERMISSION: + return 'Insufficient system permissions.' + if code == LexFloatStatusCodes.LF_E_INVALID_PERMISSION_FLAG: + return 'Invalid permission flag.' + if code == LexFloatStatusCodes.LF_E_OFFLINE_FLOATING_LICENSE_NOT_ALLOWED: + return 'Offline floating license is not allowed for per-instance leasing strategy.' + if code == LexFloatStatusCodes.LF_E_MAX_OFFLINE_LEASE_DURATION_EXCEEDED: + return 'Maximum offline lease duration exceeded.' + if code == LexFloatStatusCodes.LF_E_ALLOWED_OFFLINE_FLOATING_CLIENTS_LIMIT_REACHED: + return 'Allowed offline floating clients limit reached.' + if code == LexFloatStatusCodes.LF_E_WMIC: + return "Fingerprint couldn't be generated because Windows Management Instrumentation (WMI) service has been disabled. This error is specific to Windows only." + if code == LexFloatStatusCodes.LF_E_MACHINE_FINGERPRINT: + return 'Machine fingerprint has changed since activation.' + if code == LexFloatStatusCodes.LF_E_PROXY_NOT_TRUSTED: + return 'Request blocked due to untrusted proxy.' return 'Unknown error!' diff --git a/cryptlex/lexfloatclient/lexfloatclient_native.py b/cryptlex/lexfloatclient/lexfloatclient_native.py index e116d62..f424326 100644 --- a/cryptlex/lexfloatclient/lexfloatclient_native.py +++ b/cryptlex/lexfloatclient/lexfloatclient_native.py @@ -127,6 +127,10 @@ def byte_to_string(input): SetFloatingClientMetadata.argtypes = [CSTRTYPE, CSTRTYPE] SetFloatingClientMetadata.restype = c_int +SetPermissionFlag = library.SetPermissionFlag +SetPermissionFlag.argtypes = [c_uint32] +SetPermissionFlag.restype = c_int + GetFloatingClientLibraryVersion = library.GetFloatingClientLibraryVersion GetFloatingClientLibraryVersion.argtypes = [STRTYPE, c_uint32] GetFloatingClientLibraryVersion.restype = c_int @@ -139,10 +143,18 @@ def byte_to_string(input): GetHostProductVersionDisplayName.argtypes = [STRTYPE, c_uint32] GetHostProductVersionDisplayName.restype = c_int +GetFloatingLicenseMode = library.GetFloatingLicenseMode +GetFloatingLicenseMode.argtypes = [STRTYPE, c_uint32] +GetFloatingLicenseMode.restype = c_int + GetHostProductVersionFeatureFlag = library.GetHostProductVersionFeatureFlag GetHostProductVersionFeatureFlag.argtypes = [CSTRTYPE, POINTER(c_uint32), STRTYPE, c_uint32] GetHostProductVersionFeatureFlag.restype = c_int +GetHostConfig = library.GetHostConfigInternal +GetHostConfig.argtypes = [STRTYPE, c_uint32] +GetHostConfig.restype = c_int + GetHostLicenseMetadata = library.GetHostLicenseMetadata GetHostLicenseMetadata.argtypes = [CSTRTYPE, STRTYPE, c_uint32] GetHostLicenseMetadata.restype = c_int @@ -155,14 +167,26 @@ def byte_to_string(input): GetHostLicenseExpiryDate.argtypes = [POINTER(c_uint32)] GetHostLicenseExpiryDate.restype = c_int +GetFloatingClientLeaseExpiryDate = library.GetFloatingClientLeaseExpiryDate +GetFloatingClientLeaseExpiryDate.argtypes = [POINTER(c_uint32)] +GetFloatingClientLeaseExpiryDate.restype = c_int + GetFloatingClientMeterAttributeUses = library.GetFloatingClientMeterAttributeUses GetFloatingClientMeterAttributeUses.argtypes = [CSTRTYPE, POINTER(c_uint32)] GetFloatingClientMeterAttributeUses.restype = c_int +GetFloatingClientMetadata = library.GetFloatingClientMetadata +GetFloatingClientMetadata.argtypes = [CSTRTYPE, STRTYPE, c_uint32] +GetFloatingClientMetadata.restype = c_int + RequestFloatingLicense = library.RequestFloatingLicense RequestFloatingLicense.argtypes = [] RequestFloatingLicense.restype = c_int +RequestOfflineFloatingLicense = library.RequestOfflineFloatingLicense +RequestOfflineFloatingLicense.argtypes = [c_uint32] +RequestOfflineFloatingLicense.restype = c_int + DropFloatingLicense = library.DropFloatingLicense DropFloatingLicense.argtypes = [] DropFloatingLicense.restype = c_int diff --git a/cryptlex/lexfloatclient/lexfloatstatus_codes.py b/cryptlex/lexfloatclient/lexfloatstatus_codes.py index d8bacad..a30a4da 100644 --- a/cryptlex/lexfloatclient/lexfloatstatus_codes.py +++ b/cryptlex/lexfloatclient/lexfloatstatus_codes.py @@ -39,10 +39,26 @@ class LexFloatStatusCodes: LF_E_METER_ATTRIBUTE_USES_LIMIT_REACHED = 56 LF_E_PRODUCT_VERSION_NOT_LINKED = 57 - + LF_E_FEATURE_FLAG_NOT_FOUND = 58 + + LF_E_SYSTEM_PERMISSION = 59 LF_E_IP = 60 + + LF_E_INVALID_PERMISSION_FLAG = 61 + + LF_E_OFFLINE_FLOATING_LICENSE_NOT_ALLOWED = 62 + + LF_E_MAX_OFFLINE_LEASE_DURATION_EXCEEDED = 63 + + LF_E_ALLOWED_OFFLINE_FLOATING_CLIENTS_LIMIT_REACHED = 64 + + LF_E_WMIC = 65 + + LF_E_MACHINE_FINGERPRINT = 66 + + LF_E_PROXY_NOT_TRUSTED = 67 LF_E_CLIENT = 70