Hello Antonio,
Here is a sample program on how I use the MacAdress to protect my program. The only thing I can't get to work is to calculate the days since the program is first opened. Normally I could calculate this by puting the first date in the registration key and when the program is opened again, get DATE()-Firstdate. The number that comes out of this calculation is not what I expect, it is a long number instead of the number of days.
Code: Select all | Expand
#include "FiveMac.ch"#define CR_LF Chr
(13) + Chr
(10)/*
With this example we can build a protected program. The user must enter a registration key the first time he uses the program
This key is based on the MacAdres of the computer, every computer has at least one unique MacAdres
When the user gives his program to someone else, the key given is not working anymore
*/FUNCTION Main
() PUBLIC cVarFile
PUBLIC oWnd && the main
window PUBLIC cPath := ResPath
() PUBLIC cRegKey :=
'' PUBLIC nVersion :=
0 PUBLIC lContinue := .F.
PUBLIC nDays :=
0 cVarFile := cPath +
'/registration.plist' RK_LoadVariables
() MsgInfo(cRegKey
) lContinue := RK_CheckKey
()DEFINE WINDOW oWnd
TITLE 'testing registration' ;
FROM 0,
0 TO 600,
600IF lContinue
@
400,
20 BUTTON 'Success, version: ' + ALLTRIM
(STR
(nVersion
)) OF oWnd
ELSE@
500,
20 BUTTON 'Register, days to go: ' + ALLTRIM
(STR
(nDays
)) OF oWnd ;
ACTION RK_Register
() SIZE 200,
25 ENDIFACTIVATE WINDOW oWnd ;
RETURN NIL*************************************************
FUNCTION RK_LoadVariables
()*all variables are saved in a .plist file
*date:
13-11-2016 LOCAL oPList := TPList
():
New( cVarFile
) cRegKey := oPList:
GetItemByName( 'RegistrationKey' )RETURN*************************************************
FUNCTION RK_SaveVariables
()*all variables are saved in a .plist file
*date:
13-11-2016 LOCAL oPList := TPList
():
New( cVarFile
) oPList:
SetItemByName( 'RegistrationKey', cRegKey, .T.
) RETURN*************************************************
FUNCTION RK_CheckKey
()*
to check the registration key
*date:
15-11-2016LOCAL cMacAdres
LOCAL cCode1 :=
'', cCode2 :=
'', dDate
LOCAL nVersion :=
0IF LEN
(cRegKey
) ==
0 &&
if there is not a registration yet
cRegKey :=
'#'+DtoC
(Date
()) +
'1' RETURN .F.
ELSEIF
SUBSTR(cRegKey,
1,
1) ==
'#' &&
if first opening is more than
30 days ago, this is not working correct....
dDate := CToD
(SUBSTR(cRegKey,
2,
8)) nDays := nDays-
(DATE
()-dDate
) RETURN .F.
ELSE && check
if the key is correct
cMacAdres := GetMacAddress
() cCode1 :=
SUBSTR(cMacAdres,
1,
2) +
SUBSTR(cMacAdres,
4,
2) cCode2 :=
SUBSTR(cMacAdres,
7,
2) +
SUBSTR(cMacAdres,
10,
2) cRegKode1 :=
SUBSTR(cRegKey,
1,
1) +
SUBSTR(cRegKey,
3,
1) +
SUBSTR(cRegKey,
5,
1) +
SUBSTR(cRegKey,
7,
1) cRegKode2 :=
SUBSTR(cRegKey,
9,
1) +
SUBSTR(cRegKey,
11,
1) +
SUBSTR(cRegKey,
13,
1) +
SUBSTR(cRegKey,
15,
1) nVersion := VAL
(SUBSTR(cRegKey,
16,
1)) cRegKode7 := CHR
(ASC(SUBSTR(cRegKey,
2,
1))- nVersion
) + ;
CHR
(ASC(SUBSTR(cRegKey,
4,
1))+ nVersion
) + ;
CHR
(ASC(SUBSTR(cRegKey,
6,
1))- nVersion-nVersion
) + ;
CHR
(ASC(SUBSTR(cRegKey,
8,
1))+ nVersion+nVersion
) cRegKode8 := CHR
(ASC(SUBSTR(cRegKey,
10,
1))- nVersion
) + ;
CHR
(ASC(SUBSTR(cRegKey,
12,
1))+ nVersion
) + ;
CHR
(ASC(SUBSTR(cRegKey,
14,
1))- nVersion-nVersion
) IF hb_HexToNum
(cCode1
)+hb_HexToNum
(cRegKode1
) ==
65535 .AND. hb_HexToNum
(cCode2
)+hb_HexToNum
(cRegKode2
) ==
65535 .AND. cRegKode7 + cRegKode8 ==
'PLANTEN' RETURN .T.
ELSE MsgInfo('The registration code you have entered is not correct,'+CR_LF+
'Please inform us'+CR_LF+
'You can do this via info@plantenkennis.com.',
'error') RETURN .F.
ENDIFENDIFRETURN .F.
*************************************************
FUNCTION RK_Register
() LOCAL oDlg, oGet1, oGet2, cGet3:=
'', cGet4:=
'', cGet5:=
'', cGet6:=
'' LOCAL cMacAdres := GetMacAddress
() LOCAL cCode1 :=
SUBSTR(cMacAdres,
1,
2) +
SUBSTR(cMacAdres,
4,
2) LOCAL cCode2 :=
SUBSTR(cMacAdres,
7,
2) +
SUBSTR(cMacAdres,
10,
2) DEFINE DIALOG oDlg
TITLE "registration code" PANELED
FROM 0,
0 TO 300,
400 @
200,
100 GET oGet1
VAR cCode1
of oDlg
SIZE 75,
25 @
200,
200 GET oGet2
VAR cCode2
of oDlg
SIZE 75,
25 @
100,
10 GET oGet3
VAR cGet3
of oDlg
SIZE 75,
25 @
100,
90 GET oGet4
VAR cGet4
of oDlg
SIZE 75,
25 @
100,
170 GET oGet5
VAR cGet5
of oDlg
SIZE 75,
25 @
100,
250 GET oGet6
VAR cGet6
of oDlg
SIZE 75,
25 @
23,
20 BUTTON "OK" OF oDlg
ACTION (cRegKey := cGet3+cGet4+cGet5+cGet6,
IF(RK_CheckKey
(),
MsgInfo('The entered key is correct, close program to continue'),
MsgInfo('Wrong key'))) ACTIVATE DIALOG oDlg
CENTERED;
VALID RK_SaveVariables
()return nil*************************************************
To use this protection the buyer of the program must ask a registration key by me. I have a small program to calculate the registration key. Here is the code for that.
Code: Select all | Expand
#include "FiveMac.ch"
/*
This function is to make a registration code that users can put in there app, so it functions well.
use this sample together with the registration_test.prg.
The radiobuttons I use for different versions of the program, PRO has more options than Standard.....
Created by René Koot, 15-11-2016
*/
function Main()
local oWnd, oRad, nRad := 2
local cGet1 := '', cGet2 := '', cGet3 := ''
DEFINE WINDOW oWnd TITLE "creating registration code" PANELED FROM 0, 0 TO 400, 400
@ 300, 100 GET cGet1 of oWnd SIZE 75, 25
@ 300, 200 GET cGet2 of oWnd SIZE 75, 25
@ 250, 130 RADIO oRad VAR nRad ITEMS { "Standard", "PRO", "PRO[+]" } OF oWnd
@ 100, 10 GET oGet3 VAR cGet3 of oWnd SIZE 300, 25
@ 23, 20 BUTTON "Create" OF oWnd ACTION RK_MakeRegistrationCode( cGet1, cGet2, nRad )
@ 23, 120 BUTTON "Cancel" OF oWnd ACTION oWnd:End()
ACTIVATE WINDOW oWnd CENTERED
return nil
*************************************************
FUNCTION RK_MakeRegistrationCode(cCode1, cCode2, nRad)
*for creating the registration code
*date: 15-11-2016
LOCAL aLet := {'P', 'L', 'A', 'N', 'T', 'E', 'N'} &&you can change this array, but use the same array in your program
LOCAL cRegKode1 := hb_NumToHex(65535 - hb_HexToNum(cCode1))
LOCAL cRegKode2 := hb_NumToHex(65535 - hb_HexToNum(cCode2))
LOCAL cRegKode3 := ''
LOCAL cRegKode4 := ''
LOCAL cRegKode5 := ''
LOCAL cRegKode6 := ''
IF LEN(cRegkode1) == 3
cRegkode1 := '0' + cRegkode1
ENDIF
IF LEN(cRegkode2) == 3
cRegkode2 := '0' + cRegkode2
ENDIF
cRegKode3 := SUBSTR(cRegKode1, 1, 1) + CHR(ASC(aLet[1])+ nRad) + SUBSTR(cRegKode1, 2, 1) + CHR(ASC(aLet[2])- nRad)
cRegKode4 := SUBSTR(cRegKode1, 3, 1) + CHR(ASC(aLet[3])+ nRad+nRad) + SUBSTR(cRegKode1, 4, 1) + CHR(ASC(aLet[4])- nRad-nRad)
cRegKode5 := SUBSTR(cRegKode2, 1, 1) + CHR(ASC(aLet[5])+ nRad) + SUBSTR(cRegKode2, 2, 1) + CHR(ASC(aLet[6])- nRad)
cRegKode6 := SUBSTR(cRegKode2, 3, 1) + CHR(ASC(aLet[7])+ nRad+nRad) + SUBSTR(cRegKode2, 4, 1) + ALLTRIM(STR(nRad))
oGet3:SetText(cRegKode3 + ' ' + cRegKode4 + ' ' + cRegKode5 + ' ' + cRegKode6)
RETURN NIL
I hope this code is useful
Rene