Skip to content

Commit

Permalink
Add trial_callback to the example, and the callback parameter to th…
Browse files Browse the repository at this point in the history
…e ta.use_trial() function.

Code improvements. Remove some dead code.
  • Loading branch information
wyattoday committed May 27, 2021
1 parent c7a20e1 commit b905958
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 16 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

All notable changes to this project are documented in this file.

## 4.4.4.1 - 2021-05-27

* Add `trial_callback` to the example, and the callback parameter to the ta.use_trial() function.
* Code improvements. Remove some dead code.

## 4.4.4 - 2021-05-06

* Remove unused "sandbox" flag and error code. Sandboxes are VMs.
Expand Down
29 changes: 27 additions & 2 deletions example.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
TurboActivateError,
TurboActivateTrialExpiredError,
TA_USER,
TA_SYSTEM
TA_SYSTEM,
TA_CB_EXPIRED,
TA_CB_EXPIRED_FRAUD
)

import sys
Expand All @@ -20,6 +22,29 @@
DAYS_BETWEEN_CHECKS = 90
GRACE_PERIOD_LENGTH = 14

'''
This function will be called by a separate background thread to notify
your app of trial expiration (either naturally, or because of customer fraud).
That means if you're displaying UI to your users you must ensure
that any windows (or any resource sharing for that matter) are
created in the right thread context or bad things might happen.
Test this behavior well before releasing to your end-users.
'''
def trial_callback(status, unused):

if status == TA_CB_EXPIRED:
# TODO: disallow any features in your app.
print("The app trial period has expired")

elif status == TA_CB_EXPIRED_FRAUD:
# TODO: disallow any features in your app.
print("The lease has been dropped due to computer sleeping.")

else:
print("The app trial callback returned an unexpected status: ", status)


if __name__ == "__main__":

# support both Python 2 and 3
Expand Down Expand Up @@ -105,7 +130,7 @@
# Start or re-validate the trial if it has already started.
# This need to be called at least once before you can use
# any other trial functions.
ta.use_trial(verified_trial)
ta.use_trial(verified_trial, "", trial_callback)

# Get the number of trial days remaining.
trial_days = ta.trial_days_remaining(verified_trial)
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from distutils.core import setup

setup(name="turboactivate",
version="4.4.4",
version="4.4.4.1",
description="Python integration for the LimeLM TurboActivate library. This lets you add hardware-locked licensing (a.k.a. node-locked licensing) to your Python app.",
url="https://wyday.com/limelm/help/using-turboactivate-with-python/",
download_url="https://github.com/wyday/python-turboactivate",
Expand Down
28 changes: 17 additions & 11 deletions turboactivate/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

from ctypes import pointer, sizeof, c_uint32
from ctypes import pointer, sizeof, c_uint32, c_void_p

from turboactivate.c_wrapper import *

Expand Down Expand Up @@ -133,17 +133,14 @@ def get_pkey(self):

def deactivate(self, erase_p_key=False):
"""
Deactivates the product on this computer. Set erasePkey to 1 to erase the stored
product key, 0 to keep the product key around. If you're using deactivate to let
a user move between computers it's almost always best to *not* erase the product
key. This way you can just use TA_Activate() when the user wants to reactivate
instead of forcing the user to re-enter their product key over-and-over again.
Deactivates the product on this computer. Set erasePkey to 1 to erase the stored
product key, 0 to keep the product key around. If you're using deactivate to let
a user move between computers it's almost always best to *not* erase the product
key. This way you can just use TA_Activate() when the user wants to reactivate
instead of forcing the user to re-enter their product key over-and-over again.
"""

if erase_p_key is True:
args = 1
else:
args = 0
args = 1 if erase_p_key else 0

self._lib.TA_Deactivate(self._handle, args)

Expand Down Expand Up @@ -304,7 +301,7 @@ def is_genuine_ex(self, days_between_checks, grace_days_on_inet_err, skip_offlin

# Trial

def use_trial(self, verified=True, extra_data=""):
def use_trial(self, verified=True, extra_data="", callback = None):
"""
Begins the trial the first time it's called. Calling it again will validate the trial
data hasn't been tampered with.
Expand All @@ -318,6 +315,14 @@ def use_trial(self, verified=True, extra_data=""):
else:
args.append(None)

# Set the trial callback
if callback is not None:
# "cast" the native python function to TrialCallback type
# save it locally so that it acutally works when it's called
# back
self._callback = TrialCallback(callback)
self._lib.TA_SetTrialCallback(self._handle, self._callback, c_void_p(0))

self._lib.TA_UseTrial(self._handle, *args)

def trial_days_remaining(self, verified=True):
Expand Down Expand Up @@ -425,3 +430,4 @@ def _set_restype(self):
self._lib.TA_IsDateValid.restype = validate_result
self._lib.TA_SetCustomProxy.restype = validate_result
self._lib.TA_SetCustomActDataPath.restype = validate_result
self._lib.TA_SetTrialCallback.restype = validate_result
22 changes: 20 additions & 2 deletions turboactivate/c_wrapper.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-
#
# Copyright 2013, 2014 Develer S.r.l. (https://www.develer.com/)
# Copyright 2018 wyDay, LLC (https://wyday.com/)
# Copyright 2021 wyDay, LLC (https://wyday.com/)
#
# Current Author / maintainer:
#
Expand Down Expand Up @@ -36,11 +36,14 @@
from ctypes import (
cdll,
c_uint,
c_uint32,
c_void_p,
c_char_p,
c_wchar_p,
Structure,
create_string_buffer,
create_unicode_buffer
create_unicode_buffer,
CFUNCTYPE
)

# Utilities
Expand Down Expand Up @@ -166,6 +169,19 @@ def __init__(self, string):
TA_HAS_NOT_EXPIRED = 0x00000001


# Possible callback statuses from the TrialCallbackType function:

'''
Callback-status value used when the trial has expired.
'''
TA_CB_EXPIRED = 0x00000000

'''
Callback-status value used when the trial has expired due to date/time fraud.
'''
TA_CB_EXPIRED_FRAUD = 0x00000001


class GENUINE_OPTIONS(Structure):
_fields_ = [
("nLength", c_uint),
Expand All @@ -182,6 +198,8 @@ class ACTIVATE_OPTIONS(Structure):
]


TrialCallback = CFUNCTYPE(None, c_uint32, c_void_p)

def load_library(path):

if sys.platform == 'win32' or sys.platform == 'cygwin':
Expand Down

0 comments on commit b905958

Please sign in to comment.