Subversion Repositories oidplus

Rev

Rev 232 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. unit Main;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  7.   StdCtrls, IniFiles, ComCtrls;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     TreeView1: TTreeView;
  12.     PageControl1: TPageControl;
  13.     TabSheet1: TTabSheet;
  14.     TabSheet2: TTabSheet;
  15.     Label1: TLabel;
  16.     Edit3: TEdit;
  17.     Label3: TLabel;
  18.     Memo1: TMemo;
  19.     Edit4: TEdit;
  20.     Label4: TLabel;
  21.     CheckBox1: TCheckBox;
  22.     ComboBox1: TComboBox;
  23.     Label5: TLabel;
  24.     Edit5: TEdit;
  25.     Label6: TLabel;
  26.     Edit6: TEdit;
  27.     Label7: TLabel;
  28.     ListBox1: TListBox;
  29.     Edit7: TEdit;
  30.     Button1: TButton;
  31.     Button3: TButton;
  32.     Button2: TButton;
  33.     Button4: TButton;
  34.     Edit1: TEdit;
  35.     TabSheet3: TTabSheet;
  36.     Button5: TButton;
  37.     Edit2: TEdit;
  38.     TabSheet4: TTabSheet;
  39.     Button6: TButton;
  40.     Edit8: TEdit;
  41.     Button7: TButton;
  42.     Button8: TButton;
  43.     Edit9: TEdit;
  44.     Label2: TLabel;
  45.     Edit10: TEdit;
  46.     Label8: TLabel;
  47.     Edit11: TEdit;
  48.     Label9: TLabel;
  49.     Edit12: TEdit;
  50.     Label10: TLabel;
  51.     Edit13: TEdit;
  52.     Label11: TLabel;
  53.     Button9: TButton;
  54.     Edit14: TEdit;
  55.     Label12: TLabel;
  56.     Label13: TLabel;
  57.     Label14: TLabel;
  58.     Label15: TLabel;
  59.     procedure TreeView1Change(Sender: TObject; Node: TTreeNode);
  60.     procedure FormShow(Sender: TObject);
  61.     procedure Button1Click(Sender: TObject);
  62.     procedure Button3Click(Sender: TObject);
  63.     procedure Button4Click(Sender: TObject);
  64.     procedure Button7Click(Sender: TObject);
  65.     procedure Button6Click(Sender: TObject);
  66.     procedure Button8Click(Sender: TObject);
  67.     procedure Button2Click(Sender: TObject);
  68.     procedure FormCreate(Sender: TObject);
  69.     procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  70.     procedure CheckBox1Click(Sender: TObject);
  71.     procedure Button9Click(Sender: TObject);
  72.     procedure Edit8KeyPress(Sender: TObject; var Key: Char);
  73.     procedure Edit11Change(Sender: TObject);
  74.     procedure ListBox1KeyDown(Sender: TObject; var Key: Word;
  75.       Shift: TShiftState);
  76.     procedure Edit7KeyPress(Sender: TObject; var Key: Char);
  77.     procedure Edit2KeyPress(Sender: TObject; var Key: Char);
  78.     procedure Edit1KeyPress(Sender: TObject; var Key: Char);
  79.     procedure TreeView1KeyDown(Sender: TObject; var Key: Word;
  80.       Shift: TShiftState);
  81.   private
  82.     function ShowOID(oid: string; ini: TIniFile; nod: TTreeNode): integer;
  83.     procedure ShowRA(ini: TIniFile; nod: TTreeNode);
  84.     function DBPath: string;
  85.     function GetAsn1Ids(onlyfirst: boolean): string;
  86.     procedure SaveChangesIfRequired;
  87.     procedure ShowError(msg: string);
  88.   end;
  89.  
  90. var
  91.   Form1: TForm1;
  92.  
  93. implementation
  94.  
  95. {$R *.DFM}
  96.  
  97. uses
  98.   SortStrings;
  99.  
  100. resourcestring
  101.   TITLE_OID = 'Object Identifiers';
  102.   TITLE_RA = 'Registration Authorities';
  103.  
  104. procedure Split(Delimiter: string; Str: string; ListOfStrings: TStrings) ;
  105. var
  106.   p: integer;
  107. begin
  108.   ListOfStrings.Clear;
  109.   p := Pos(Delimiter, Str);
  110.   while p > 0 do
  111.   begin
  112.     ListOfStrings.Add(Copy(Str, 1, p-1));
  113.     Delete(Str, 1, p);
  114.     p := Pos(Delimiter, Str);
  115.   end;
  116.   if Str <> '' then ListOfStrings.Add(Str);
  117. end;
  118.  
  119. function TForm1.ShowOID(oid: string; ini: TIniFile; nod: TTreeNode): integer;
  120. var
  121.   i: integer;
  122.   sectionName: string;
  123.   asn1ids: string;
  124.   sl: TStringList;
  125. begin
  126.   result := 0;
  127.   if oid = 'OID:' then
  128.   begin
  129.     nod := TreeView1.Items.AddChild(nod, TITLE_OID);
  130.   end
  131.   else
  132.   begin
  133.     asn1ids := ini.ReadString(oid, 'asn1id', '');
  134.     if ini.ReadBool(oid, 'draft', false) then
  135.       nod := TreeView1.Items.AddChild(nod, Trim(oid+' '+Copy(asn1ids,1,Pos(',',asn1ids+',')-1))+' [DRAFT]')
  136.     else
  137.       nod := TreeView1.Items.AddChild(nod, Trim(oid+' '+Copy(asn1ids,1,Pos(',',asn1ids+',')-1)));
  138.   end;
  139.   sl := TStringList.Create;
  140.   for i := 1 to ini.ReadInteger(oid, 'delegates', 0) do
  141.   begin
  142.     sectionName := ini.ReadString(oid, 'delegate'+IntToStr(i), '');
  143.     if sectionName = '' then continue;
  144.     sl.Add(sectionName);
  145.     Inc(result);
  146.   end;
  147.   SortSL(sl);
  148.   for i := 0 to sl.Count-1 do
  149.   begin
  150.     sectionName := sl.Strings[i];
  151.     (*result := result + *)ShowOid(sectionName, ini, nod);
  152.   end;
  153.   sl.Free;
  154.   if (oid = 'OID:') or (result < 125) then
  155.     nod.Expand(false);
  156. end;
  157.  
  158. procedure TForm1.ShowRA(ini: TIniFile; nod: TTreeNode);
  159. var
  160.   i: integer;
  161.   sectionName, personname: string;
  162.   sl: TStringList;
  163. begin
  164.   nod := TreeView1.Items.AddChild(nod, TITLE_RA);
  165.   sl := TStringList.Create;
  166.   for i := 1 to ini.ReadInteger('RA:', 'count', 0) do
  167.   begin
  168.     sectionName := ini.ReadString('RA:', 'ra'+IntToStr(i), '');
  169.     if sectionName = '' then continue;
  170.     personname := ini.ReadString(sectionName, 'name', '');
  171.     sl.Add(Trim(sectionName + ' ' + personname));
  172.   end;
  173.   SortSL(sl);
  174.   for i := 0 to sl.Count-1 do
  175.   begin
  176.     sectionName := sl.Strings[i];
  177.     TreeView1.Items.AddChild(nod, sectionName);
  178.     ComboBox1.Items.Add(Copy(sectionName,1,Pos(' ',sectionName+' ')-1));
  179.   end;
  180.   sl.Free;
  181.   nod.Expand(false);
  182. end;
  183.  
  184. procedure TForm1.TreeView1Change(Sender: TObject; Node: TTreeNode);
  185. var
  186.   ini: TIniFile;
  187.   txtFile: string;
  188. begin
  189.   SaveChangesIfRequired;
  190.  
  191.   if Copy(TreeView1.Selected.Text, 1, 4) = 'OID:' then
  192.   begin
  193.     PageControl1.ActivePage := TabSheet1;
  194.     ini := TIniFile.Create(DBPath+'OID.INI');
  195.     try
  196.       Edit4.Text := Copy(TreeView1.Selected.Text, 1, Pos(' ',TreeView1.Selected.Text+' ')-1);
  197.       ListBox1.Items.Clear;
  198.       Split(',', ini.ReadString(Edit4.Text, 'asn1id', ''), ListBox1.Items);
  199.       Edit3.Text := ini.ReadString(Edit4.Text, 'description', '');
  200.       CheckBox1.Checked := ini.ReadBool(Edit4.Text, 'draft', false);
  201.       txtFile := DBPath+ini.ReadString(Edit4.Text, 'information', '');
  202.       if FileExists(txtFile) then
  203.         Memo1.Lines.LoadFromFile(txtFile)
  204.       else
  205.         Memo1.Lines.Clear;
  206.       Memo1.Modified := false;
  207.       ComboBox1.ItemIndex := ComboBox1.Items.IndexOf(ini.ReadString(Edit4.Text, 'ra', ''));
  208.       Edit5.Text := ini.ReadString(Edit4.Text, 'createdate', '');
  209.       Edit6.Text := ini.ReadString(Edit4.Text, 'updatedate', '');
  210.       Edit7.Text := '';
  211.     finally
  212.       ini.Free;
  213.     end;
  214.   end;
  215.   if Copy(TreeView1.Selected.Text, 1, 3) = 'RA:' then
  216.   begin
  217.     PageControl1.ActivePage := TabSheet2;
  218.     ini := TIniFile.Create(DBPath+'RA.INI');
  219.     try
  220.       Edit9.Text := Copy(TreeView1.Selected.Text, 1, Pos(' ',TreeView1.Selected.Text+' ')-1);
  221.       Edit10.Text := ini.ReadString(Edit9.Text, 'createdate', '');
  222.       Edit11.Text := ini.ReadString(Edit9.Text, 'name', '');
  223.       Edit12.Text := ini.ReadString(Edit9.Text, 'email', '');
  224.       Edit13.Text := ini.ReadString(Edit9.Text, 'phone', '');
  225.       Edit14.Text := ini.ReadString(Edit9.Text, 'updatedate', '');
  226.     finally
  227.       ini.Free;
  228.     end;
  229.     Edit1.Text := '';
  230.   end;
  231.   if TreeView1.Selected.Text = TITLE_OID then
  232.   begin
  233.     PageControl1.ActivePage := TabSheet3;
  234.     Edit2.Text := '';
  235.   end;
  236.   if TreeView1.Selected.Text = TITLE_RA then
  237.   begin
  238.     PageControl1.ActivePage := TabSheet4;
  239.     Edit8.Text := '';
  240.   end;
  241. end;
  242.  
  243. procedure TForm1.FormShow(Sender: TObject);
  244. var
  245.   nod, raroot: TTreeNode;
  246.   ini: TIniFile;
  247. begin
  248.   ComboBox1.Clear;
  249.   TreeView1.Items.Clear;
  250.   nod := TTreeNode.Create(Treeview1.Items);
  251.  
  252.   ini := TIniFile.Create(DBPath+'OID.INI');
  253.   try
  254.     ShowOID('OID:', ini, nod);
  255.   finally
  256.     ini.Free;
  257.   end;
  258.  
  259.   ini := TIniFile.Create(DBPath+'RA.INI');
  260.   try
  261.     ShowRa(ini, nod);
  262.   finally
  263.     ini.Free;
  264.   end;
  265. end;
  266.  
  267. function Asn1IdValid(asn1id: string): boolean;
  268. var
  269.   i: integer;
  270. begin
  271.   if asn1id = '' then
  272.   begin
  273.     result := false;
  274.     exit;
  275.   end;
  276.  
  277.   if not (asn1id[1] in ['a'..'z']) then
  278.   begin
  279.     result := false;
  280.     exit;
  281.   end;
  282.  
  283.   for i := 2 to Length(asn1id) do
  284.   begin
  285.     if not (asn1id[1] in ['a'..'z', 'A'..'Z', '0'..'9', '-']) then
  286.     begin
  287.       result := false;
  288.       exit;
  289.     end;
  290.   end;
  291.  
  292.   result := true;
  293. end;
  294.  
  295. procedure TForm1.Button1Click(Sender: TObject);
  296. var
  297.   asn1id: string;
  298.   i: integer;
  299. begin
  300.   asn1id := Edit7.Text;
  301.   if asn1id = '' then exit;
  302.   for i := 0 to ListBox1.Items.Count-1 do
  303.   begin
  304.     if ListBox1.Items.Strings[i] = asn1id then ShowError('Item already exists');
  305.   end;
  306.   if not Asn1IdValid(asn1id) then ShowError('Invalid alphanumeric identifier');
  307.   ListBox1.Items.Add(asn1id);
  308.   TreeView1.Selected.Text := Trim(Edit4.Text + ' ' + GetAsn1Ids(true));
  309.   Edit7.Text := '';
  310. end;
  311.  
  312. procedure TForm1.Button3Click(Sender: TObject);
  313. begin
  314.   if (ListBox1.Items.Count > 0) and ListBox1.Selected[ListBox1.ItemIndex] then
  315.   begin
  316.     ListBox1.Items.Delete(ListBox1.ItemIndex);
  317.   end;
  318.   TreeView1.Selected.Text := Trim(Edit4.Text + ' ' + GetAsn1Ids(true));
  319. end;
  320.  
  321. function IsPositiveNumber(str: string): boolean;
  322. var
  323.   i: integer;
  324. begin
  325.   if (str = '') then
  326.   begin
  327.     result := false;
  328.     exit;
  329.   end;
  330.  
  331.   result := true;
  332.   for i := 1 to Length(str) do
  333.   begin
  334.     if not (str[i] in ['0'..'9']) then
  335.     begin
  336.       result := false;
  337.       exit;
  338.     end;
  339.   end;
  340.  
  341.   if (str[1] = '0') and (str <> '0') then
  342.   begin
  343.     result := false;
  344.     exit;
  345.   end;
  346. end;
  347.  
  348. procedure TForm1.Button4Click(Sender: TObject);
  349. var
  350.   ini: TIniFile;
  351.   i, di: integer;
  352.   oid, parent_oid, new_value: string;
  353.   nod: TTreeNode;
  354.   candidate: string;
  355. begin
  356.   if PageControl1.ActivePage = TabSheet1 then new_value := Edit1.Text;
  357.   if PageControl1.ActivePage = TabSheet3 then new_value := Edit2.Text;
  358.  
  359.   new_value := Trim(new_value);
  360.   if new_value = '' then exit;
  361.  
  362.   if not IsPositiveNumber(new_value) then ShowError('Not a valid number');
  363.  
  364.   if PageControl1.ActivePage = TabSheet1 then
  365.   begin
  366.     oid := Edit4.Text + '.' + new_value;
  367.     parent_oid := Edit4.Text;
  368.   end
  369.   else
  370.   begin
  371.     oid := 'OID:' + new_value;
  372.     parent_oid := 'OID:';
  373.   end;
  374.  
  375.   for i := 0 to TreeView1.Selected.Count-1 do
  376.   begin
  377.     candidate := Copy(TreeView1.Selected.Item[i].Text, 1, Pos(' ',TreeView1.Selected.Item[i].Text+' ')-1);
  378.     if oid = candidate then ShowError('Item already exists');
  379.   end;
  380.  
  381.   if (parent_oid = 'OID:') and (StrToInt(new_value) > 2) then ShowError('Number must not exceed 2');
  382.   if (parent_oid = 'OID:0') and (StrToInt(new_value) > 39) then ShowError('Number must not exceed 39');
  383.   if (parent_oid = 'OID:1') and (StrToInt(new_value) > 39) then ShowError('Number must not exceed 39');
  384.  
  385.   ini := TIniFile.Create(DBPath+'OID.INI');
  386.   try
  387.     nod := TreeView1.Items.AddChild(TreeView1.Selected, oid);
  388.     ComboBox1.Text := ini.ReadString(parent_oid, 'ra', '');
  389.  
  390.     di := ini.ReadInteger(parent_oid, 'delegates', 0);
  391.     ini.WriteInteger(parent_oid, 'delegates', di+1);
  392.     ini.WriteString(parent_oid, 'delegate'+IntToStr(di+1), oid);
  393.  
  394.     ini.WriteString(oid, 'createdate', DateToStr(date));
  395.     ini.WriteString(oid, 'ra', ComboBox1.Text);
  396.  
  397.     if PageControl1.ActivePage = TabSheet1 then Edit1.Text := '';
  398.     if PageControl1.ActivePage = TabSheet3 then Edit2.Text := '';
  399.  
  400.     TreeView1.Selected := nod;
  401.  
  402.     ini.UpdateFile;
  403.   finally
  404.     ini.Free;
  405.   end;
  406.  
  407.   ShowMessage('Created: ' + oid);
  408. end;
  409.  
  410. procedure TForm1.Button7Click(Sender: TObject);
  411. var
  412.   ini: TIniFile;
  413.   di: integer;
  414.   nod: TTreeNode;
  415.   sectionName, new_value, candidate: string;
  416.   i: integer;
  417. begin
  418.   ini := TIniFile.Create(DBPath+'RA.INI');
  419.   try
  420.     new_value := Edit8.Text;
  421.     new_value := Trim(new_value);
  422.     if new_value = '' then exit;
  423.  
  424.     sectionName := 'RA:'+new_value;
  425.  
  426.     for i := 0 to TreeView1.Selected.Count-1 do
  427.     begin
  428.       candidate := TreeView1.Selected.Item[i].Text;
  429.       if sectionName = candidate then ShowError('Item already exists');
  430.     end;
  431.  
  432.     di := ini.ReadInteger('RA:', 'count', 0);
  433.     ini.WriteInteger('RA:', 'count', di+1);
  434.     ini.WriteString('RA:', 'ra'+IntToStr(di+1), sectionName);
  435.  
  436.     nod := TreeView1.Items.AddChild(TreeView1.Selected, sectionName);
  437.  
  438.     ini.WriteString(sectionName, 'createdate', DateToStr(date));
  439.  
  440.     Edit8.Text := '';
  441.  
  442.     TreeView1.Selected := nod;
  443.  
  444.     ini.WriteString(sectionName, 'createdate', DateToStr(date));
  445.  
  446.     ini.UpdateFile;
  447.   finally
  448.     ini.Free;
  449.   end;
  450.  
  451.   ComboBox1.Items.Add(sectionName);
  452.  
  453.   ShowMessage('Created: ' + sectionName);
  454. end;
  455.  
  456. procedure TForm1.Button6Click(Sender: TObject);
  457. var
  458.   ini: TIniFile;
  459.   nod: TTreeNode;
  460.   parent_oid, this_oid: string;
  461.   i: integer;
  462.   sl: TStringList;
  463. begin
  464.   if MessageDlg('Are you sure?', mtConfirmation, mbYesNoCancel, 0) <> idYes then exit;
  465.  
  466.   ini := TIniFile.Create(DBPath+'OID.INI');
  467.   try
  468.     this_oid := Edit4.Text;
  469.     if TreeView1.Selected.Parent.Text = TITLE_OID then
  470.       parent_oid := 'OID:'
  471.     else
  472.       parent_oid := Copy(TreeView1.Selected.Parent.Text, 1, Pos(' ', TreeView1.Selected.Parent.Text+' ')-1);
  473.  
  474.     nod := TreeView1.Selected;
  475.     TreeView1.Selected := nod.Parent;
  476.     TreeView1.Items.Delete(nod);
  477.  
  478.     ini.EraseSection(this_oid);
  479.  
  480.     sl := TStringList.Create;
  481.     ini.ReadSections(sl);
  482.     for i := 0 to sl.Count-1 do
  483.     begin
  484.       if Copy(sl.Strings[i], 1, Length(this_oid)+1) = this_oid+'.' then
  485.       begin
  486.         ini.EraseSection(sl.Strings[i]);
  487.       end;
  488.     end;
  489.     sl.Free;
  490.  
  491.     for i := 1 to ini.ReadInteger(parent_oid, 'delegates', 0) do
  492.     begin
  493.       if ini.ReadString(parent_oid, 'delegate'+IntToStr(i), '') = this_oid then
  494.       begin
  495.         ini.WriteString(parent_oid, 'delegate'+IntToStr(i), '');
  496.       end;
  497.     end;
  498.  
  499.     ini.UpdateFile;
  500.   finally
  501.     ini.Free;
  502.   end;
  503. end;
  504.  
  505. procedure TForm1.Button8Click(Sender: TObject);
  506. var
  507.   ini: TIniFile;
  508.   nod: TTreeNode;
  509.   parent_ra, this_ra: string;
  510.   i: integer;
  511. begin
  512.   if MessageDlg('Are you sure?', mtConfirmation, mbYesNoCancel, 0) <> idYes then exit;
  513.  
  514.   ini := TIniFile.Create(DBPath+'RA.INI');
  515.   try
  516.     this_ra := Copy(Treeview1.Selected.Text, 1, Pos(' ',Treeview1.Selected.Text+' ')-1);
  517.     if TreeView1.Selected.Parent.Text = TITLE_RA then
  518.       parent_ra := 'RA:'
  519.     else
  520.       parent_ra := Copy(TreeView1.Selected.Parent.Text, 1, Pos(' ', TreeView1.Selected.Parent.Text+' ')-1);
  521.  
  522.     nod := TreeView1.Selected;
  523.     TreeView1.Selected := nod.Parent;
  524.     TreeView1.Items.Delete(nod);
  525.  
  526.     ini.EraseSection(this_ra);
  527.  
  528.     for i := 1 to ini.ReadInteger(parent_ra, 'count', 0) do
  529.     begin
  530.       if ini.ReadString(parent_ra, 'ra'+IntToStr(i), '') = this_ra then
  531.       begin
  532.         ini.WriteString(parent_ra, 'ra'+IntToStr(i), '');
  533.       end;
  534.     end;
  535.  
  536.     ComboBox1.Items.Delete(ComboBox1.Items.IndexOf(this_ra));
  537.  
  538.     ini.UpdateFile;
  539.   finally
  540.     ini.Free;
  541.   end;
  542. end;
  543.  
  544. function RandomStr(len: integer): string;
  545. var
  546.   i: integer;
  547. begin
  548.   result := '';
  549.   for i := 1 to len do
  550.   begin
  551.     result := result + Chr(ord('A') + Random(26));
  552.   end;
  553. end;
  554.  
  555. procedure TForm1.Button2Click(Sender: TObject);
  556. var
  557.   ini: TIniFile;
  558.   txtFile, asn1s: string;
  559.   modified: boolean;
  560. begin
  561.   // Attention: Do not rely on TreeView1.Selected.Text, because Button2.Click
  562.   // will be called in TreeView1OnChange()!
  563.  
  564.   ini := TIniFile.Create(DBPath+'OID.INI');
  565.   try
  566.     modified := false;
  567.  
  568.     if ini.ReadString(Edit4.Text, 'ra', '') <> ComboBox1.Text then
  569.     begin
  570.       modified := true;
  571.       ini.WriteString(Edit4.Text, 'ra', ComboBox1.Text);
  572.     end;
  573.  
  574.     if ini.ReadString(Edit4.Text, 'description', '') <> Edit3.Text then
  575.     begin
  576.       modified := true;
  577.       ini.WriteString(Edit4.Text, 'description', Edit3.Text);
  578.     end;
  579.  
  580.     if ini.ReadBool(Edit4.Text, 'draft', false) <> CheckBox1.Checked then
  581.     begin
  582.       modified := true;
  583.       ini.WriteBool(Edit4.Text, 'draft', CheckBox1.Checked);
  584.     end;
  585.  
  586.     if Memo1.Modified then
  587.     begin
  588.       modified := true;
  589.       if Trim(Memo1.Lines.Text) = '' then
  590.       begin
  591.         txtFile := ini.ReadString(Edit4.Text, 'information', '');
  592.         if FileExists(DBPath+txtFile) then
  593.         begin
  594.           DeleteFile(DBPath+txtFile);
  595.         end;
  596.         if txtFile <> '' then
  597.         begin
  598.           ini.WriteString(Edit4.Text, 'information', '')
  599.         end;
  600.       end
  601.       else
  602.       begin
  603.         txtFile := ini.ReadString(Edit4.Text, 'information', '');
  604.         if txtFile = '' then
  605.         begin
  606.           repeat
  607.             txtFile := RandomStr(8) + '.TXT';
  608.           until not FileExists(DBPath+txtFile);
  609.           ini.WriteString(Edit4.Text, 'information', txtFile);
  610.         end;
  611.  
  612.         Memo1.Lines.SaveToFile(DBPath+txtFile);
  613.         Memo1.Modified := false;
  614.       end;
  615.     end;
  616.  
  617.     asn1s := GetAsn1Ids(false);
  618.     if ini.ReadString(Edit4.Text, 'asn1id', '') <> asn1s then
  619.     begin
  620.       modified := true;
  621.       ini.WriteString(Edit4.Text, 'asn1id', asn1s);
  622.     end;
  623.  
  624.     if modified then
  625.     begin
  626.       ini.WriteString(Edit4.Text, 'updatedate', DateToStr(Date));
  627.       ini.Updatefile;
  628.     end;
  629.   finally
  630.     ini.Free;
  631.   end;
  632. end;
  633.  
  634. function TForm1.GetAsn1Ids(onlyfirst: boolean): string;
  635. var
  636.   i: integer;
  637. begin
  638.   result := '';
  639.   for i := 0 to ListBox1.Items.Count-1 do
  640.   begin
  641.     if result = '' then
  642.       result := ListBox1.Items.Strings[i]
  643.     else if not onlyfirst then
  644.       result := result + ',' + ListBox1.Items.Strings[i];
  645.   end;
  646. end;
  647.  
  648. function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean; // Source: Delphi 10.3.3
  649. var
  650.   Code: Cardinal;
  651.   Handle: THandle;
  652.   LastError: Cardinal;
  653. const
  654.   faSymLink = $00000400; // Available on POSIX and Vista and above
  655.   INVALID_FILE_ATTRIBUTES = DWORD($FFFFFFFF);
  656. begin
  657.   Result := False;
  658.   Code := GetFileAttributes(PChar(Directory));
  659.  
  660.   if Code <> INVALID_FILE_ATTRIBUTES then
  661.   begin
  662.     if faSymLink and Code = 0 then
  663.       Result := faDirectory and Code <> 0
  664.     else
  665.     begin
  666.       if FollowLink then
  667.       begin
  668.         Handle := CreateFile(PChar(Directory), GENERIC_READ, FILE_SHARE_READ, nil,
  669.           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  670.         if Handle <> INVALID_HANDLE_VALUE then
  671.         begin
  672.           CloseHandle(Handle);
  673.           Result := faDirectory and Code <> 0;
  674.         end;
  675.       end
  676.       else if faDirectory and Code <> 0 then
  677.         Result := True
  678.       else
  679.       begin
  680.         Handle := CreateFile(PChar(Directory), GENERIC_READ, FILE_SHARE_READ, nil,
  681.           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  682.         if Handle <> INVALID_HANDLE_VALUE then
  683.         begin
  684.           CloseHandle(Handle);
  685.           Result := False;
  686.         end
  687.         else
  688.           Result := True;
  689.       end;
  690.     end;
  691.   end
  692.   else
  693.   begin
  694.     LastError := GetLastError;
  695.     Result := (LastError <> ERROR_FILE_NOT_FOUND) and
  696.       (LastError <> ERROR_PATH_NOT_FOUND) and
  697.       (LastError <> ERROR_BAD_PATHNAME) and
  698.       (LastError <> ERROR_INVALID_NAME) and
  699.       (LastError <> ERROR_BAD_NETPATH) and
  700.       (LastError <> ERROR_NOT_READY) and
  701.       (LastError <> ERROR_BAD_NET_NAME);
  702.   end;
  703. end;
  704.  
  705. function TForm1.DBPath: string;
  706. var
  707.   ini: TIniFile;
  708. begin
  709.   ini := TIniFile.Create('.\OIDPLUS.INI');
  710.   try
  711.     if not ini.ValueExists('SETTINGS', 'DATA') then
  712.     begin
  713.       result := 'DB\';
  714.       ini.WriteString('SETTINGS', 'DATA', result);
  715.       ini.UpdateFile;
  716.     end
  717.     else
  718.     begin
  719.       result := ini.ReadString('SETTINGS', 'DATA', 'DB\');
  720.     end;
  721.     if not DirectoryExists(result) then MkDir(result);
  722.     if not DirectoryExists(result) then
  723.     begin
  724.       ShowError('Cannot create database directory '+result);
  725.     end;
  726.   finally
  727.     ini.Free;
  728.   end;
  729. end;
  730.  
  731. procedure TForm1.FormCreate(Sender: TObject);
  732. begin
  733.   PageControl1.ActivePage := TabSheet3;
  734.   Randomize;
  735. end;
  736.  
  737. procedure TForm1.SaveChangesIfRequired;
  738. begin
  739.   if PageControl1.ActivePage = TabSheet1 then Button2.Click; // Save changes
  740.   if PageControl1.ActivePage = TabSheet2 then Button9.Click; // Save changes
  741. end;
  742.  
  743. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  744. begin
  745.   SaveChangesIfRequired;
  746.   CanClose := true;
  747. end;
  748.  
  749. procedure TForm1.CheckBox1Click(Sender: TObject);
  750. begin
  751.   if CheckBox1.Checked then
  752.     TreeView1.Selected.Text := Trim(Edit4.Text+' '+GetAsn1Ids(true))+' [DRAFT]'
  753.   else
  754.     TreeView1.Selected.Text := Trim(Edit4.Text+' '+GetAsn1Ids(true));
  755. end;
  756.  
  757. procedure TForm1.ShowError(msg: string);
  758. begin
  759.   MessageDlg(msg, mtError, [mbOk], 0);
  760.   Abort;
  761. end;
  762.  
  763. procedure TForm1.Button9Click(Sender: TObject);
  764. var
  765.   ini: TIniFile;
  766.   txtFile, asn1s: string;
  767.   modified: boolean;
  768. begin
  769.   // Attention: Do not rely on TreeView1.Selected.Text, because Button9.Click
  770.   // will be called in TreeView1OnChange()!
  771.  
  772.   ini := TIniFile.Create(DBPath+'RA.INI');
  773.   try
  774.     modified := false;
  775.     if ini.ReadString(Edit9.Text, 'name', '') <> Edit11.Text then
  776.     begin
  777.       modified := true;
  778.       ini.WriteString(Edit9.Text, 'name', Edit11.Text);
  779.     end;
  780.     if ini.ReadString(Edit9.Text, 'email', '') <> Edit12.Text then
  781.     begin
  782.       modified := true;
  783.       ini.WriteString(Edit9.Text, 'email', Edit12.Text);
  784.     end;
  785.     if ini.ReadString(Edit9.Text, 'phone', '') <> Edit13.Text then
  786.     begin
  787.       modified := true;
  788.       ini.WriteString(Edit9.Text, 'phone', Edit13.Text);
  789.     end;
  790.     if modified then
  791.     begin
  792.       ini.WriteString(Edit9.Text, 'updatedate', DateToStr(Date));
  793.       ini.Updatefile;
  794.     end;
  795.   finally
  796.     ini.Free;
  797.   end;
  798. end;
  799.  
  800. procedure TForm1.Edit8KeyPress(Sender: TObject; var Key: Char);
  801. begin
  802.   if Key = #13 then
  803.   begin
  804.     Button7.Click;
  805.     Key := #0;
  806.     Exit;
  807.   end;
  808.   if Key = #8(*backspace*) then exit;
  809.   if Key in ['a'..'z'] then Key := UpCase(Key);
  810.   if not (Key in ['A'..'Z', '-']) then
  811.   begin
  812.     Beep;
  813.     Key := #0;
  814.   end;
  815. end;
  816.  
  817. procedure TForm1.Edit11Change(Sender: TObject);
  818. begin
  819.   TreeView1.Selected.Text := Trim(Edit9.Text + ' ' + Edit11.Text);
  820. end;
  821.  
  822. procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
  823.   Shift: TShiftState);
  824. begin
  825.   If Key = 46(*DEL*) then
  826.   begin
  827.     Button3.Click;
  828.     Key := 0;
  829.   end;
  830. end;
  831.  
  832. procedure TForm1.Edit7KeyPress(Sender: TObject; var Key: Char);
  833. begin
  834.   if Key = #13 then
  835.   begin
  836.     Button1.Click;
  837.     Key := #0;
  838.   end;
  839. end;
  840.  
  841. procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
  842. begin
  843.   if Key = #13 then
  844.   begin
  845.     Button5.Click;
  846.     Key := #0;
  847.   end;
  848. end;
  849.  
  850. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  851. begin
  852.   if Key = #13 then
  853.   begin
  854.     Button4.Click;
  855.     Key := #0;
  856.   end;
  857. end;
  858.  
  859. procedure TForm1.TreeView1KeyDown(Sender: TObject; var Key: Word;
  860.   Shift: TShiftState);
  861. begin
  862.   if Key = 46(*DEL*) then
  863.   begin
  864.     if Copy(TreeView1.Selected.Text, 1, 4) = 'OID:' then
  865.     begin
  866.       Button6.Click;
  867.     end
  868.     else if Copy(TreeView1.Selected.Text, 1, 3) = 'RA:' then
  869.     begin
  870.       Button8.Click;
  871.     end
  872.     else
  873.     begin
  874.       Beep;
  875.     end;
  876.  
  877.     Key := 0;
  878.   end;
  879. end;
  880.  
  881. end.
  882.