Способи збереження і завантаження параметрів програмного забезпечення (документація), Документація, Програмування, статті

У цій статті мова піде про способи збереження і завантаження параметрів програмного забезпечення. Зі свого особистого досвіду я можу твердо сказати, що це не так просто, як здається багатьом. Як Ви вже встигли помітити, великі програмні продукти використовують для зберігання своїх параметрів виключно реєстру. Навпаки, розробники програмного забезпечення, які відносять його до freeware, воліють конфігураційні файли з розширенням “ini” (далі “ini-файли”). Чому ж справа йде саме так? Ми розглянемо два цих способу більш детально, а так само поговоримо про впровадження певних засобів захисту ini-файлів.


Системний реєстр – один з найбільш надійних, але аж ніяк не самий безпечний способів зберігання параметрів. Дані в ньому розташовуються у вигляді ієрархічної структури, що полегшує пошук потрібного розділу, але тим самим збільшує ризик видалення даних. Загрозою втрати даних, що знаходяться в реєстрі, крім необережних дій самих користувачів, можуть бути збої в операційній системі microsoft windows. Але це вже інша історія.


Для роботи з системним реєстром в borland delphi передбачений модуль registry, який містить клас tregistry.
Код: uses registry;
…..
var
r: tregistry;
begin
r := tregistry.create;
…………
r.free;
end;


Розглянемо принципи збереження і завантаження даних, використовуючи системний реєстр, на невеликому прикладі, який буде містити дві процедури getcaption і savecaption.
Код:
procedure getcaption;
var
r: tregistry;
begin
r := tregistry.create;
r.rootkey := hkey_local_machine;
{Відкриття ключа. Параметр true означає,
що за відсутності ключа він автоматично створюється}
r.openkey(“softwaretest”, true)
{Записуємо параметр}
r.writestring(“formcaption”, form1.caption);
{Закриваємо ключ}
r.closekey;
r.free;
end;


Код:
procedure savecaption;
var
r: tregistry;
begin
r := tregistry.create;
r.rootkey := hkey_local_machine;
r.openkey(“softwaretest”, true)
{Встановлюємо заголовок форми, використовуючи раніше збережену рядок}
form1.caption := r.readstring(“formcaption”);
r.closekey;
r.free;
end;
Процедура savecaption зберігає заголовок форми, а процедура getcaption завантажує з реєстру раніше збережену рядок, і встановлює її в якості заголовка.


Розглянемо фрагмент коду, який відповідає за відкриття ключа. В коментарях вже обумовлено, що при установці параметра true у процедурі openkey, ключ автоматично створюється в разі його відсутності. Слід завжди встановлювати значення true, так як при спробі відкрити неіснуючий ключ може статися помилка, яка спричинить за собою аварійне завершення програми.


Варто сказати ще про двох процедурах модуля registry: getkeynames і getvaluenames. Вони дозволяють сканувати реєстр, як звичайні каталоги. При відкритті ключа ви вказуєте початковий шлях пошуку, а далі процедура getkeynames створює список типу tstrings і записує в нього імена всіх знайдених ключів, а процедура getvaluenames складає список з імен параметрів, що знаходяться в заданому ключі.


До появи 32-х розрядних операційних систем, для зберігання параметрів програми використовували виключно конфігураційні файли з розширенням “ini” (далі ini-файли). Але незабаром, ini-файли були забуті, і на зміну їм прийшов системний реєстр. Але до цих пір зустрічаються програми, які активно використовують такий спосіб зберігання параметрів. У чому ж його переваги? Перш за все в стабільності. На відміну від системного реєстру, при збоях в операційній системі з ini-файлом нічого не трапляється, якщо тільки він не знаходиться в системному каталозі. Варто пам’ятати, що ini-файл повинен знаходитися в одному каталозі з програмою. Крім стабільності, важливою перевагою ini-файлів є мобільність програмного коду, в чому ви можете переконатися, подивившись приклад, наведений нижче. Що ж до недоліків, то це простота видалення. ini-файл – це звичайний файл, який можна випадково видалити.


Для роботи з ini-файлами в borland delphi передбачений модуль inifiles.
Код:
uses inifiles;
….
var
inifile: tinifile;
begin
inifile: = tinifile.create (‘ім’я файлу’);
….
….
inifile.free;
end;


Принципи роботи ini-файлів і системного реєстру схожі між собою. Змінимо попередню програму, яка зберігала і змінювала заголовок форми, використовуючи системний реєстр.
Код:
procedure savecaption;
var
inifile: tinifile;
begin
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
inifile.writestring(“mainoptions”, “formcaption”, form1.caption);
inifile.free;
end;


Код:
procedure getcaption;
var
inifile: tinifile;
begin
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
form1.caption := inifile.readstring(“mainoptions”, “formcaption”, “”);
inifile.free;
end;


Як бачите, у порівнянні з попередньою програмою, спостерігається зменшення програмного коду. Та й помилок при роботі з ini-файлами виникає так же набагато менше, ніж з системним реєстром.
А тепер, поговоримо про засоби захисту. Операційна система надає можливість закриття доступу до певних файлів. Але, на жаль, закриття доступу триває тільки під час роботи програми. Після того, як програма буде закрита, доступ буде повністю відкритий. Наприклад, можна обмежити доступ до ini-файлу. Для реалізації даної можливості, серед безлічі функцій winapi існує функція openfile. Давайте спробуємо написати програму, яка закривала б доступ до ini-файлу.
Код:
var
form1: tform1;
hinilockedfile: cardinal;
ofstruct : _ofstruct;
implementation
{$r *.dfm}
procedure savecaption;
var
inifile: tinifile;
begin
{Відключаємо захист файла}
closehandle(hinilockedfile);
{Резервний час для оключенія}
sleep(1000);
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
inifile.writestring(“mainoptions”, “formcaption”, form1.caption);
inifile.free;
{Після збереження, заново ставимо захист}
hinilockedfile := openfile(pchar(extractfiledir(application.exename) + “test.ini”), ofstruct, of_share_exclusive);
end;


Код:
procedure getcaption;
var
inifile: tinifile;
begin
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
form1.caption := inifile.readstring(“mainoptions”, “formcaption”, “”);
inifile.free;
{Встановлюємо захист}
hinilockedfile := openfile(pchar(extractfiledir(application.exename) + “test.ini”), ofstruct, of_share_exclusive);
end;


При запуску програми, з ini-файлу зчитується інформація, після чого він блокується для подальших операцій роботи з ним: копіювання, видалення, редагування і т.д. При збереженні параметрів, захист тимчасово знімається, а незабаром заново відновлюється.


Обмеження доступу до файлу test.ini


Уважний читач може заперечити, що ніякого сенсу в цьому захисті немає. Адже після завершення роботи програми, користувач може легко змінити вміст файлу. І він буде абсолютно правий. Тому, необхідно додати ще одну функцію безпеки – кодування тексту.


При завершенні роботи програми, захист автоматично знімається, і далі йде шифровка тексту. При наступних запусках програми, файл розшифровується, і вже на розшифрований файл ставиться захист, що тим самим повністю перекриває доступ до нього.


Слід досить серйозно ставитися до стандартів шифрування. Найпростіші способи найчастіше відомі багатьом. Будь-яка людина, використовуючи схожий алгоритм шифрування, може легко розшифрувати зашифрований раніше файл.


Я написав дві найпростіші процедури кодування та декодування тексту. На їхньому прикладі ми і розглянемо роботу нашої програми.
Код:
var
form1: tform1;
hinilockedfile: cardinal;
ofstruct : _ofstruct;
const
cscryptfirst = 20;
cscryptsecond = 230;
cscryptheader = “crypted”;


type
ecrypterror = class(exception);
implementation
{$r *.dfm}
function cryptstring(str:string):string;
var
i : integer;
clen : integer;
begin
clen := length(cscryptheader);
setlength(result, length(str)+clen);
move(cscryptheader[1], result[1], clen);
for i := 1 to length(str) do
begin
if i mod 2 = 0 then
result[i+clen] := chr(ord(str[i]) xor cscryptfirst)
else
result[i+clen] := chr(ord(str[i]) xor cscryptsecond);
end;
end;


function uncryptstring(str:string):string;
var
i : integer;
clen : integer;
begin
clen := length(cscryptheader);
setlength(result, length(str)-clen);
if copy(str, 1, clen) <> cscryptheader then
raise ecrypterror.create (“Файл пошкоджений!”);
for i := 1 to length(str)-clen do
begin
if (i) mod 2 = 0 then
result[i] := chr(ord(str[i+clen]) xor cscryptfirst)
else
result[i] := chr(ord(str[i+clen]) xor cscryptsecond);
end;
end;


procedure cryptinifile;
var
s: tstringlist;
i: integer;
begin
s := tstringlist.create;
s.loadfromfile(extractfiledir(application.exename) + “test.ini”);
for i := 0 to s.count – 1 do
s.strings[i] := cryptstring(s.strings[i]);
s.savetofile(extractfiledir(application.exename) + “test.ini”);
end;


procedure decryptinifile;
var
s: tstringlist;
i: integer;
begin
if not fileexists(extractfiledir(application.exename) + “test.ini”) then exit;
s := tstringlist.create;
s.loadfromfile(extractfiledir(application.exename) + “test.ini”);
for i := 0 to s.count – 1 do
s.strings[i] := uncryptstring(s.strings[i]);
s.savetofile(extractfiledir(application.exename) + “test.ini”);
end;


procedure savecaption;
var
inifile: tinifile;
begin
{Відключаємо захист файла}
closehandle(hinilockedfile);
{Резервний час для оключенія}
sleep(1000);
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
inifile.writestring(“mainoptions”, “formcaption”, form1.caption);
inifile.free;
{Після збереження, заново ставимо захист}
hinilockedfile := openfile(pchar(extractfiledir(application.exename) + “test.ini”), ofstruct, of_share_exclusive);
end;


procedure getcaption;
var
inifile: tinifile;
begin
{Расшірофка конфігураційного файлу}
decryptinifile;
sleep(1000);
inifile := tinifile.create(extractfilepath(application.exename) + “test.ini”);
form1.caption := inifile.readstring(“mainoptions”, “formcaption”, “”);
inifile.free;
{Встановлюємо захист}
hinilockedfile := openfile(pchar(extractfiledir(application.exename) + “test.ini”), ofstruct, of_share_exclusive);
end;


procedure tform1.formcreate(sender: tobject);
begin
getcaption;
end;


procedure tform1.formclose(sender: tobject; var action: tcloseaction);
begin
savecaption;
closehandle(hinilockedfile);
cryptinifile;
end;


Це один з найефективніших способів захисту. Як бачите, за своїми якостями ini-файли є більш надійним способом зберігання даних, ніж системний реєстр. До файлів, що входять в нього, неможливо заблокувати доступ. Написані мною процедури шифрування можна використовувати і при роботі з системним реєстром, але в будь-який момент користувач може з легкістю змінити навіть зашифровані дані, що може привести до сумних наслідків.


Слід сказати пару слів про самих алгоритмах кодування і декодування тексту. В якості ознаки того, що файл вже був закодований, використовується звичайна текстова рядок «crypted», якій відповідає константа cscryptheader. Вона слід спочатку кожної зашифрованою строчки. Перед шифруванням, визначається довжина рядка cscryptheader, після чого збільшується довжина майбутньої рядка, який дорівнює довжині шіфруемой рядки і довжині рядка cscryptheader. Далі, простим перебором, відбувається заміна кожного символу шіфруемой рядка. Це здійснюється за допомогою функції chr, яка за згенеровані програмою числу повертає відповідний символ. При заміні символів, слід враховувати певні параметри, які визначає логічна операція. В нашому прикладі, в залежності від того, чи ділиться порядковий номер рядка на два без залишку, використовуються різні параметри, що ускладнює подальшу дешифрування тексту.


При дешифрування тексту визначається його реальна довжина, що досягається вирахуванням з довжини дешіфруемой рядки довжини рядка cscryptheader. Для того, щоб визначити, пошкоджений файл чи ні, програма шукає в закодованої рядку заголовок, в нашому прикладі це «crypted», і якщо він відсутній, то дешифрування припиняється і виникає помилка. Якщо ж все гаразд, далі йде розшифровка тексту, алгоритм якої повністю протилежний алгоритму шифрування.


Отже, всі способи, освітлені в статті, були детально розібрані і обумовлені. Тепер вибір за вами. Спробуйте описані в цій статті способи на своїй практиці. Імпровізуйте, намагаючись створити щось досконале, і рішення у виборі між системним реєстром і ini-файлами прийде до вас.


Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*