Example2

Top  Previous  Next

EXAMPLE 2

 

Items covered in this topic

Description

The Main Form "Form1"

The avlockunit.pas unit

The AVLock variable

The TestData  procedure

The EnterUserData function

The GetRegData function

The GetRegStatus procedure

The Start Trial procedure

The ModuleOk function

The DoRegister procedure

 

Description

This is an example that uses only the advanced OLM. We will see how to handle user data in addition to the registration data. Below we see the forms and units that are part of this example:

 

example2_01

 

The UserData form was added to handle the user data. Form1 is the main form of the application and Regist is the registration form.

 

The Main Form "Form1"

 

As we can see in the picture below, we have 12 buttons for access to 12 different application modules. This the the maximum number of modules that can handle a single registration key in AVLock Simple.  Each of these modules is to access a special application functionality that can be controlled by AVLock.

 

example2_02

 

In the previous version we had developed most of the functions and procedures in the main form of the application, but since you has probably a lot of specific functions of your application there, we placed in the main unit only the essential features. To do so, in this example we have added the avlockunit.pas unit where we moved most of the functions that had previously located on the main unit, so that now for Example 2 we only have the SetModules procedure, the BtnReg button ("Registration form") to access the registration form and two lines of code in the OnCreate event handler. Below is the code from the main unit:

 

 

 

procedure TForm1.SetModules;

begin

 btn1.Enabled  := Moduleok(1);

 btn2.Enabled  := Moduleok(2);

 btn3.Enabled  := Moduleok(3);

 btn4.Enabled  := Moduleok(4);

 btn5.Enabled  := Moduleok(5);

 btn6.Enabled  := Moduleok(6);

 btn7.Enabled  := Moduleok(7);

 btn8.Enabled  := Moduleok(8);

 btn9.Enabled  := Moduleok(9);

 btn10.Enabled := Moduleok(10);

 btn11.Enabled := Moduleok(11);

 btn12.Enabled := Moduleok(12);

end;

 

procedure TForm1.BtnRegClick(Sender: TObject);

begin

 DoRegister(True)

end;

 

procedure TForm1.FormCreate(Sender: TObject);

begin

 DoRegister(False);

 SetModules;

end;

 

 

In the SetModules procedure for each button we call the ModuleOk function using as parameter the module number. The ModuleOk function is implemented in the avlockunit.pas unit.

 

From the BtnReg button we call inconditionally the registration form with the parameter (mode=True). Now the DoRegister procedure is implemented in avlockunit.pas.

 

From the OnCreate event handler we invoke the registration form at conditional way with the line

 

DoRegister(False)

 

Then we call  SetModules to enable/disable the appropriate buttons.

 

The avlockunit.pas unit

 

Most of the functions and procedures associated with AVLock are now in this unit. Below you can see the interface section of this unit:

 

unit avlockunit;

 

interface

 

uses  SysUtils, Controls, Forms, Dialogs, ExtCtrls, AVLockS6;

 

var

AVLock  : TAVLockS6;

 keydata : TKeyData;

 msg1,msg2:string;

 barpos:integer;

 

 

function TestData(name,email:string):boolean;

function EnterUserData(msg:string):boolean;

function GetRegData:string;

procedure GetRegStatus;

procedure StartTrial;

procedure DoRegister(force:boolean);

function Moduleok(m:byte):boolean;

 

 

In the uses clause we include a reference to AVLockS6 component. This is enough to have AVLock ready to work. Also have the procedures TestData, EnterUserData, GetRegData, GetRegStatus, StartTrial, DoRegister and ModuleOk.

 

The variables AVLock, keydata, msg1, msg2 and barpos are declared as global because we will also use them in the registration form. In these variables we hold data and messages related with the registration status to be shown in the registration form later.

 

We begin by explaining the statement AVLock:

 

The AVLock variable

 

AVLock : TAVlockS6;

 

This variable is a reference to the AVLock component that we instantiate as object with the following line:

 

AVLock:=TAVLockS6.Create(nil);

 

After instantiating the component, it is configured by assigning the properties that we consider suitable for the case. This is done in the initialization section. Below you can see the code for initialization and finalization sections:

 

initialization

 

AVLock:=TAVLockS6.Create(nil);

 with AVLock do begin

   InstallCodeSources := Removable_Disk;

   RegPath        := ExeDir;

   RegFolder      := '';

   AppID          := 12302;

   EncryptionKey  := 'abc123';

   EncryptionKey2 := 'xyz321';

   AppName        := 'MyApp';

   AppVersion     := '1.0.0';

   WebHost        := 'www.av-soft.com';

   TimeHost       := 'time-a.nist.gov';

   OlmPath        := '/olm6';

   OlmBasicScript := 'basicolm.php';

   OlmAdvScript   := 'advolm.php';

   InstancesCtrl  := True;

 end;

 

finalization

 freeandnil(AVLock);

 

 

As in this case Example2 is a different application to Ejemplo1, we use a different AppID = '12302'.

For more infgormation about these properties see the Example1.

 

The TestData procedure

 

Here is the code for this procedure:

 

 

function TestData(name,email:string):boolean;

begin

 result := ((trim(name)<>'') and (trim(email)<>''));

end;

 

 

Receive the name and email parameters and returns True if both are not empty. It is used to verify that the user enter at least the essential data the name and email. You could improve this feature to suit your own needs.

 

The EnterUserData function

 

Here is the code for this function:

 

 

function EnterUserData(msg:string):boolean;

var F: TUserDataForm;

 err:string;

 ok:boolean;

begin

 result:=False;

 F:= TUserDataForm.Create(nil);

 try

 ok:=false;

 while not ok do begin

   F.lmsg.Caption := msg;

   F.EdName.Text := AVLock.UserName;

   F.EdCompany.Text := AVLock.Company;

   F.EdEmail.Text := AVLock.Email;

   F.EdOther.Text := AVLock.OtherCode;

   F.ShowModal;

   if (F.modalresult = mrOk) then begin

     if TestData(F.edname.Text, F.edemail.Text) then begin

       err := AVLock.OnlineSaveUserData(F.edname.Text, F.edcompany.Text, F.edemail.Text, F.edother.Text,0);

       result := (err='00');

       ok := result;

     end else showmessage('You should enter at least the User Name and Email');

   end else begin

     result := TestData(AVLock.UserName, AVLock.email);

     ok :=True;

   end;

 end;

 finally

   Freeandnil(F);

 end;

end;

 

 

This function takes the "msg" parameter which is the text to be displayed at the top of the data entry form. Below we see the form displaying the message "In order to continue You should complete the following form":

 

  example2_03

 

Into a while loop checks the entered data until at least the username and email are entered. If the "Save Data" button is pressed without completing these data the message "You should At Least enter the User Name and Email" is displayed. If you entered the data correctly, it is saved in the OLM and locally with the OnlineSaveUserData function. If "Cancel" is pressed the loop is exited without saving data but verifying that the existing user data within the component AVLock are acceptable. This function is used to enter user data when registering for the first time and also when the user wants to modify their data, so for both situations, when leaving the form, the entered data or existing ones should meet the requirements, returning True if met and False otherwise.

 

The GetRegData function

 

This is the code of this function:

 

 

function GetRegData:string;

var s, key, uname, comp, eml, other:string;

   n:integer;

   arr:TarrStr;

begin

 result:='75'; //Unknown Error

 AVLock.restart;

 s:=trim(AVLock.OnlineSynch0(0));

 if (length(s)>2) then begin

   key:='';

   n := explod('|', s, arr);

   if (n > 0) then key    :=trim(arr[0]);

   if (n > 1) then uname  :=trim(arr[1]);

   if (n > 2) then comp   :=trim(arr[2]);

   if (n > 3) then eml    :=trim(arr[3]);

   if (n > 4) then other  :=trim(arr[4]);

   if (length(key) = 45) then begin

     AVLock.Username := uname;

     AVLock.Company := comp;

     AVLock.Email := eml;

     AVLock.OtherCode := other;

     AVLock.WriteAppData;

     if AVLock.WriteKeyData(key) then result := '00' // No Error

     else result := '01'; // Could not write key data;

   end else result := '57'; //key length mismatch

 end else result := s;

end;

 

 

This function accesses the advanced OLM and gets the data from the  proper record with OnlineSynch0(0) which returns a string with the data or an error code. If the length of string returned is greater than 2, it is the data, otherwise it is an error code with two digits, in most cases is '66' indicating that the record does not exist in the OLM. If there is data, these are extracted from the string returned by the function explod thus obtaining values for a registration key "key" user name "uname" Company "comp" the email "eml" and other "other" . Then verifies that the key has the correct length and properties of the component are assigned. The user data is locally stored with WriteAppData and the registration key with WriteKeyData. If the operation was correct the code '00' is returned.

 

The GetRegStatus procedure

 

Here is the code for this procedure:

 

 

procedure GetRegStatus;

var s:string;

  day:integer;

  ok:boolean;

begin

 AVLock.GetKeyData(0,KeyData);

 s:='';

 msg1:='';

 msg2:='';

 barpos:=0;

 ok:=False;

 case keydata.Status of

   Unregistered: s:='Not registered';

   Moved       : s:='Moved to another computer';

   Expired     : s:='Expired';

   Registered  : begin

     ok:= (keydata.DaysLeft>0);

     if ok then s:='Registered '

     else begin

       keydata.Status := Expired;

       s:= 'EXPIRED';

     end;

     if (keydata.KeyType = Permanent) then msg1 := 'NEVER EXPIRES'

     else begin

       day:=keydata.Days-keydata.DaysLeft+1;

       barpos:= trunc(day*100/keydata.Days);

       msg1 := 'You are in the day '+inttostr(day)+' of '+inttostr(keydata.Days);

       msg2:=inttostr(keydata.DaysLeft)+' days left';

     end;

     if ok then case keydata.KeyType of

       Trial     : s:=s+'as Trial ';

       Temporal  : s:=s+'as Temporal ';

       Permanent : begin

         s:=s+'as Permanent, no time limit.';

       end;

     end;

   end;

 end;

 keydata.StrStatus := s;

end;

 

 

 

The first line invokes the GetkeyData method which reads the registration data of the application from the *.avr file then assigns them to the fields of the KeyData variable.

 

AVLock.GetKeyData(0,KeyData);

 

GetKeyData takes two parameters (0, KeyData). The first is the index that match with the module in the registration data to be read, normally only is used (index=0) as in our case, except on rare occasions, when for example you want to control more than 12 modules in the implementation would need to record two index, 0 and 1 and also would take two registration keys. In our examples we will use only (index=0).

 

After KeyData fields are analyzed and prepared text messages with details on the registration status to be shown on the registration form. The msg1 and msg2 messages, barpos and KeyData.StrStatus are assigned with a description of the state of registration.

 

The StartTrial procedure

 

Here is the source code for this procedure:

 

 

procedure StartTrial;

var ok:boolean;

begin

 GetRegStatus;

 if (keydata.Status = Unregistered) then

 begin

   AVLock.StartTrialAdv(0,1,1,30,'EA3');

   ok := EnterUserData('The application will be activated for free for 30 days. For that we need you enter your data in the form below:');

   if not ok then application.Terminate;

   GetRegStatus;

 end;

end;

 

 

In this case the trial period is started through the advanced olm with the StartTrialAdv method.  

 

The parameters are (index=0), (users=1), (instances=1), (days=30), (values='EA3').

 

Here we see that the users parameter is only used with the advanced OLM and the Values parameter are managed at different way than the example1.

 

The users parameter. (users=1): indicates how many computers can be registered with the same license key. There is always a parent record in the OLM that corresponds to the computer that is first registered. For example if we have (users = 3) may register 3 computers of which the first will be the primary registration and the remaining 2 generate secondary records. In the example we will use only (users=1) that will generate us a single record in the OLM.

 

The values parameter. (values='EA3'): In the example1 we had used '101' to indicate the active modules, but this way we can only handle a maximum of 3 modules in the application as the values field has a maximum of 3 characters. In example2 we have to handle 12 modules, so we must use another method. As the values field allows to enter hexadecimal numbers, this allows us to handle up to 4 modules for each position. Each hexadecimal character is called a nibble in computer jargon, see http://es.wikipedia.org/wiki/Nibble.

To better understand this let's use the Windows calculator in programmer mode, we select Hex and write EA3 as you can see in the picture below:

 

calc_01

 

Then we select Bin and see the hex number EA3 converted to binary:

 

calc_02

 

the idea is to use each of the 12 bits to control the modules.

If we run the example2 the trial period will start and see the main form with the active modules in accordance with (values = 'EA3').

 

example2_06

Below we can see the correlation between 'EA3' and the active modules:

 

example2_07

 

example2_05

 

The KeyGen utility and DevPanel Allows you to set the key to be applied according to this concept.

 

In KeyGen:

 

example2_08

 

In DevPanel

 

example2_09

 

The ModuleOk function

 

Here is the code of this function:

 

 

function Moduleok(m:byte):boolean;

var n,k:byte;

begin

 result:=False;

 if not (m in [1..12]) then exit;

 if (keydata.Status <> Registered) then exit;

 m:=m-1;

 k:=m mod 4;

 n:=3-(m div 4); //nibble

 result:= isvalueon(keydata.Values,n,k);

end;

 

 

This take as parameter a module number and returns a boolean value: True/False that determines whether the module should be active or not. This function is used in the main form for the SetModules procedure to set the active modules.

 

The DoRegister procedure

 

This is its source code:

 

 

procedure DoRegister(force:boolean);

var F :TRegForm;

   s,err :string;

   ok :boolean;

begin

 if not AVLock.IsLocal then begin

   showmessage('Not Allowed from a remote drive');

   exit;

 end;

 err := GetRegData;

 if (err = '66') then AVLock.EraseReg;

 GetRegStatus;

 if (keydata.Status = Registered) then begin

   ok:=TestUserData;

   if not ok then ok:=EnterUserData('In order to continue you should complete the following form.');

   if not ok then begin

     showmessage('You should enter at least the User Name and Email. Please try again');

     application.Terminate;

   end;

 end;

 

 StartTrial;

 if AVLock.IsLocal and (force or (keydata.DaysLeft < 15)) then

 begin

   F:=TRegForm.Create(nil); //Create the registration Form

   F.EdIcode.Text := AVLock.InstallCode;

   F.lstatus.Caption := keydata.strstatus;

   try

     F.ShowModal;

   finally

     FreeAndNil(F);

   end;

   GetRegStatus;

 end;

 if (keydata.Status <> Registered) then begin

   showmessage('Not Registered');

   Application.Terminate;

 end;

 if (keydata.TooManyInstances) then begin

   showmessage('No more instances allowed');

   application.Terminate;

 end;

 

end;

 

 

 

This procedure allows the user access to the registration form to see the current status and proceed to the registration of the application.

 

The condition not AVLock.IsLocal avoid the form were accessed remotely.

 

In addition to the existing functionality in the example1 here we added code to handle the user data.

 

It may be that we want to present this form automatically when the app starts in the case the application is in a state Non-Registered or the trial period is about to expire or has expired. But we would also like to invoke unconditionally, for example from a button. So we've placed the force parameter that allows us to do. If we have (force=True) the registration form is displayed directly without seeing the state of registration, but if (force=False) the registration form will be displayed only if the condition satisfies the following line:

 

if (force or (keydata.DaysLeft < 15)) then

 

The condition (keydata.DaysLeft <15) makes the form is displayed when there are less than 15 days to expire, also if the application is not registered or expired, the remaining days will be zero and the condition will be fulfilled.

 

After finished the trial period

 

The user

.