تشریح روشهای قفل گذاری ...
به نظر من یکی از بهترین
روش ها استفاده تواما از چندین روش قفل گذاری می باشد .
یکی از روش
هایی که مدت هاست که مرسوم است استفاده از ریجستری است. البته این روش به
تنهایی قادر به تامین امنیت برنامه نمی باشد.
در این روش اطلاعات کاربر و
رمز ورود و سایر مشخصات مورد نیاز در قسمتی از ریجستری که دور از ذهن باشد به
صورت کد شده نوشته می شود. لازم به ذکر است که یکی از ضعف های این روش این
است که با استفاده از یک برنامه مانیتورینگ پی به محل ذخیره سازی اطلاعات
برد.
یکی دیگر از روش ها نوشتن اطلاعات و مشخصات به صورت کد شده و به
صورت یک رکورد در آخر یک فایل.
این فایل می تواند یک فایل DLL باشد یا هر
فایلی ولی فایل DLL ترجیه داده می شود. این روش نسبت به استفاده از ریجستری
از امنیت بیشتری برخوردار است ولی باز هم کافی نیست.
اما... یکی از
بهترین روش ها استفاده از دو روش مذکور به طور همزمان است.
اطلاعات
کاربر و اطلاعات برنامه در یک رکورد قرار گرفته و این رکورد می تواند در درون
ریجستری و در آخر یک یا چندین فایل مختلف قرار گیرد.
البته به علت
طولانی شدن مبحث (و... ) فقط روش
نوشتن رکورد های ثبت در آخر فایل در زیر توضیح داده شده!
برای مثال
رکوردی مانند این:
TProgTrial=Packed Record
fWinVer:integer ;
fProgVer:integer ;
fRemindTime:TDateTime;
fLastUse:TDateTime;
fTrial:Boolean;
fUserName:string[30];
fUsedDays:cardinal;
end;
TProgAccess=Packed Record
fWinVer:integer ;
fProgVer:integer ;
fUserName:string[30];
fRegistered:Boolean;
fRegTime:TDateTime;
end;
رکورد اولی یعنی TProgTrial زمانی توسط برنامه
نوشته می شه که برنامه زمان دار یا همان Trial است. بعد از هر روز یک عدد به
مقدار fUsedDays افزوده می شود و مقدار fTrial هم true است.علت استفاده از
fTrial هم در پایین توضیح داده شده است.
رکورد دومی یعنی TProgAccess
هم زمانی نوشته می شود که برنامه توسط کاربر به ثبت رسیده باشد. یعنی کاربر
کد ثبت را به درستی وارد کرده و برنامه به طور کامل در اختیار او قرار می
گیرد.
نکته ای که در اینجا مهم است نحوه خواندن رکورد های فوق از آخر
فایل است. برای تعیین محل خواندن اطلاعات باید اندازه فایل را منهای اندازه
رکورد کرد تا محل خواندن اطلاعات مشخص شود.
مثال زیر این نکته را در خط 18
نشان می دهد. البته مثال زیر مربوط به رکورد TProgTrial است:
Function GetFileTrial(fName:String):TProgTrial;
var
fFileStream:TFileStream;
begin
try
If not FileExists(fName) then begin
Result.fWinVer:=0;
Result.fProgVer:=0;
Result.fRemindTime:=0;
Result.fTrial:=false;
Result.fUserName:='';
Result.fUsedDays:=999999;
Result.fLastUse:=0;
exit;
end;
fFileStream:=TFileStream.Create(fName,fmOpenRead or
fmShareDenyWrite);
try
fFileStream.Seek(fFileStream.Size-SizeOf(TProgTrial),soBeginning);
fFileStream.ReadBuffer(result,sizeOf(TProgTrial));
finally
fFileStream.Free;
end;
Result.fWinVer:=(Result.fWinVer);
Result.fprogVer:=((Result.fProgVer));
Result.fUserName:=((Result.fUserName));
except
end;
end;
و این مثال TProgAccess :
Function GetFileAccess(fName:String):TProgAccess;
var
fFileStream:TFileStream;
begin
try
If not FileExists(fName) then begin
Result.fWinVer:=0;
Result.fprogVer:=0;
Result.fRegTime:=0;
Result.fRegistered:=false;
Result.fUserName:='';
exit;
end;
fFileStream:=TFileStream.Create(fName,fmOpenRead or
fmShareDenyWrite);
try
fFileStream.Seek(-sizeOf(TProgAccess),soEnd);
fFileStream.ReadBuffer(result,sizeOf(TProgAccess));
finally
fFileStream.free;
end;
Result.fWinVer:=((Result.fWinVer));
Result.fprogVer:=((Result.fprogVer));
Result.fUserName:=TrimRight((Result.fUserName));
except
end;
end;
و نکته دیگر اینکه باید صحت رکوردها مورد بررسی قرار گیرد. یعنی با اطلاعات برنامه تطابق داده شود. کد های زیر این مطلب را نشان می دهند:
const
sVersion=1;
sRemindUserName='SalarSoftwares';
function AccessFile(fName:
String): Boolean;
var
fProgReg:TProgAccess;
Major,Minor:Cardinal;
begin
try
result:=false;
Major := (DWORD(LOBYTE(LOWORD(GetVersion))));
Minor := (DWORD(HIBYTE(LOWORD(GetVersion))));
fProgReg:=GetFileAccess(fName);
If fProgReg.fRegistered then
result:=true;
If
(fProgReg.fWinVer)<>(Major+Minor) then
Result:=false;
If fProgReg.fprogVer<>sVersion then
result:=false;
Except
Result:=false;
end;
end;
function TimedFile(fName: String): Boolean;
var
fprogRemind:TProgTrial;
Major,Minor:Cardinal;
begin
Result:=false;
try
Major := (DWORD(LOBYTE(LOWORD(GetVersion))));
Minor
:= (DWORD(HIBYTE(LOWORD(GetVersion))));
fprogRemind:=GetFileTrial(fName);
If fprogRemind.fTrial then
result:=true;
If
fprogRemind.fUserName=sRemindUserName then
result:=true;
If (fprogRemind.fWinVer)<>(Major+Minor) then
Result:=false;
If fprogRemind.fprogVer<>sVersion
then
result:=false;
Except
Result:=false;
end;
end;
و نکته دیگر اینکه حتما باید در هنگام خواندن
رکوردها هر دوی این رکوردها خوانده شود. علت کار این است که برای تشخیص اینکه
برنامه به ثبت رسیده یا Trial است لازم می باشد.
کدهای زیر این مطلب را
نشان می دهند:
type
TAccessMode=(amNone,amTimed,amFullAccess,amError);
function
GetAccessMode(filename:Tfilename): TAccessMode;
var
fret1,fret2:Boolean;
begin
try
Result:=amError;
fret1:=AccessFile(filename) ;
fret2:=TrialFile(filename) ;
//fret3:=AccessReg(sRegAddr);
//Define with self
//fret4:=TrialReg(sRegAddr); //Define with
self
If fret2 then
Result:=amTimed;
If fret1 then
Result:=amFullAccess;
If (fret1 and fret2)then //error when fret1=fret2=true
Result:=amError;
If not (fret1 or fret2) then
Result:=amNone;
except
Result:=amError;
end;
end;
در این کد GetAccessMode نوع دسترسی شما به فایل را
نشان می دهد:
amNone: یعنی هیچ کاری بر روی فایل انجام نگرفته است و نه به
ثبت رسیده و نه Trial است.
amTimed: یعنی فایل trial
است.
amFullAccess: یعنی فایل به طور کامل و درست به ثبت رسیده
است.
amError: یعنی اشکالی در ثبت فایل وجود دارد و برنامه نباید به کار
خود ادامه دهد.
وآخرین نکته در این مبحث نحوه نوشتن رکورد ها در فایل
است. به کد های زیر دقت فرمایید.
کدهای زیر این مطلب را نشان می
دهند:
var
Hfile:file;
fBReg:TprogAccess;
Major,Minor:Cardinal;
begin
try
AssignFile(Hfile,fname);
reset(Hfile,1);
try
seek(Hfile,Filesize(Hfile)-SizeOf(TprogAccess));
blockread(Hfile,fBReg,sizeOf(fBReg));
If fBReg.fprogVer<>sVersion then
seek(Hfile,Filesize(Hfile){-SizeOf(TprogAccess)});
Major := (DWORD(LOBYTE(LOWORD(GetVersion))));
Minor := (DWORD(HIBYTE(LOWORD(GetVersion))));
//GetVersionEx(OsVer);
fBReg.fWinVer:=(Major)+(Minor);
fBReg.fprogVer:=(sVersion);
fBReg.fRegTime:=now;
fBReg.fRegistered:=True;
fBReg.fUserName:=(fUser);
blockwrite(Hfile,fBReg,sizeOf(fBReg));
finally
closeFile(Hfile);
Result:=true;
end;
except
Result:=false;
end;
end;
Function GetShortFilename(Const FileName:TFileName):TFilename;
var
Buffer:Array[0..Max_Path-1] of char;
begin
SetString(Result,Buffer,GetShortPathName(Pchar(Filename),Buffer,Max_Path-1));
Result:=lowerCase(Result);
end;
function SetTimedFile(fName: String;fRemindTime,fLastUse:TDateTime;UsedDays:Cardinal): Boolean;
var
hfile:file;
fBRemind:TProgTrial;
Major,Minor:Cardinal;
begin
try
Result:=true;
fname:=GetShortFilename(fname);
If not fileexists(fname) then exit;
AssignFile(hfile,(fname));
reset(hfile,1);
try
seek(hfile,Filesize(hfile)-SizeOf(TProgTrial));
blockread(hfile,fBRemind,sizeOf(fBRemind));
If fBRemind.fprogVer<>sVersion then
begin
seek(hfile,Filesize(hfile){-SizeOf(TprogTimed)});
end
else
begin
seek(hfile,Filesize(hfile)-SizeOf(TProgTrial));
end;
Major := (DWORD(LOBYTE(LOWORD(GetVersion))));
Minor := (DWORD(HIBYTE(LOWORD(GetVersion))));
//GetVersionEx(OsVer);
fBRemind.fLastUse:=fLastUse;
fBRemind.fRemindTime:=fRemindTime;
fBRemind.fWinVer:=(Major)+(Minor);
fBRemind.fprogVer:=(sVersion);
fBRemind.fTrial:=true;
fBRemind.fUserName:=(sRemindUserName);
fBRemind.fUsedDays:=UsedDays;
blockwrite(hfile,fBRemind,sizeOf(fBRemind));
Result:=true;
finally
closeFile(hfile);
end;
except
Result:=false;
end;
end;