Subversion Repositories oidplus

Rev

Go to most recent revision | 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.   end;
  230.   if TreeView1.Selected.Text = TITLE_OID then PageControl1.ActivePage := TabSheet3;
  231.   if TreeView1.Selected.Text = TITLE_RA then PageControl1.ActivePage := TabSheet4;
  232. end;
  233.  
  234. procedure TForm1.FormShow(Sender: TObject);
  235. var
  236.   nod, raroot: TTreeNode;
  237.   ini: TIniFile;
  238. begin
  239.   ComboBox1.Clear;
  240.   TreeView1.Items.Clear;
  241.   nod := TTreeNode.Create(Treeview1.Items);
  242.  
  243.   ini := TIniFile.Create(DBPath+'OID.INI');
  244.   try
  245.     ShowOID('OID:', ini, nod);
  246.   finally
  247.     ini.Free;
  248.   end;
  249.  
  250.   ini := TIniFile.Create(DBPath+'RA.INI');
  251.   try
  252.     ShowRa(ini, nod);
  253.   finally
  254.     ini.Free;
  255.   end;
  256. end;
  257.  
  258. function Asn1IdValid(asn1id: string): boolean;
  259. var
  260.   i: integer;
  261. begin
  262.   if asn1id = '' then
  263.   begin
  264.     result := false;
  265.     exit;
  266.   end;
  267.  
  268.   if not (asn1id[1] in ['a'..'z']) then
  269.   begin
  270.     result := false;
  271.     exit;
  272.   end;
  273.  
  274.   for i := 2 to Length(asn1id) do
  275.   begin
  276.     if not (asn1id[1] in ['a'..'z', 'A'..'Z', '0'..'9', '-']) then
  277.     begin
  278.       result := false;
  279.       exit;
  280.     end;
  281.   end;
  282.  
  283.   result := true;
  284. end;
  285.  
  286. procedure TForm1.Button1Click(Sender: TObject);
  287. var
  288.   asn1id: string;
  289.   i: integer;
  290. begin
  291.   asn1id := Edit7.Text;
  292.   if asn1id = '' then exit;
  293.   for i := 0 to ListBox1.Items.Count-1 do
  294.   begin
  295.     if ListBox1.Items.Strings[i] = asn1id then ShowError('Item already exists');
  296.   end;
  297.   if not Asn1IdValid(asn1id) then ShowError('Invalid alphanumeric identifier');
  298.   ListBox1.Items.Add(asn1id);
  299.   TreeView1.Selected.Text := Trim(Edit4.Text + ' ' + GetAsn1Ids(true));
  300.   Edit7.Text := '';
  301. end;
  302.  
  303. procedure TForm1.Button3Click(Sender: TObject);
  304. begin
  305.   if (ListBox1.Items.Count > 0) and ListBox1.Selected[ListBox1.ItemIndex] then
  306.   begin
  307.     ListBox1.Items.Delete(ListBox1.ItemIndex);
  308.   end;
  309.   TreeView1.Selected.Text := Trim(Edit4.Text + ' ' + GetAsn1Ids(true));
  310. end;
  311.  
  312. function IsPositiveNumber(str: string): boolean;
  313. var
  314.   i: integer;
  315. begin
  316.   if (str = '') then
  317.   begin
  318.     result := false;
  319.     exit;
  320.   end;
  321.  
  322.   result := true;
  323.   for i := 1 to Length(str) do
  324.   begin
  325.     if not (str[i] in ['0'..'9']) then
  326.     begin
  327.       result := false;
  328.       exit;
  329.     end;
  330.   end;
  331.  
  332.   if (str[1] = '0') and (str <> '0') then
  333.   begin
  334.     result := false;
  335.     exit;
  336.   end;
  337. end;
  338.  
  339. procedure TForm1.Button4Click(Sender: TObject);
  340. var
  341.   ini: TIniFile;
  342.   i, di: integer;
  343.   oid, parent_oid, new_value: string;
  344.   nod: TTreeNode;
  345.   candidate: string;
  346. begin
  347.   if PageControl1.ActivePage = TabSheet1 then new_value := Edit1.Text;
  348.   if PageControl1.ActivePage = TabSheet3 then new_value := Edit2.Text;
  349.  
  350.   new_value := Trim(new_value);
  351.   if new_value = '' then exit;
  352.  
  353.   if not IsPositiveNumber(new_value) then ShowError('Not a valid number');
  354.  
  355.   if PageControl1.ActivePage = TabSheet1 then
  356.   begin
  357.     oid := Edit4.Text + '.' + new_value;
  358.     parent_oid := Edit4.Text;
  359.   end
  360.   else
  361.   begin
  362.     oid := 'OID:' + new_value;
  363.     parent_oid := 'OID:';
  364.   end;
  365.  
  366.   for i := 0 to TreeView1.Selected.Count-1 do
  367.   begin
  368.     candidate := Copy(TreeView1.Selected.Item[i].Text, 1, Pos(' ',TreeView1.Selected.Item[i].Text+' ')-1);
  369.     if oid = candidate then ShowError('Item already exists');
  370.   end;
  371.  
  372.   if (parent_oid = 'OID:') and (StrToInt(new_value) > 2) then ShowError('Number must not exceed 2');
  373.   if (parent_oid = 'OID:0') and (StrToInt(new_value) > 39) then ShowError('Number must not exceed 39');
  374.   if (parent_oid = 'OID:1') and (StrToInt(new_value) > 39) then ShowError('Number must not exceed 39');
  375.  
  376.   ini := TIniFile.Create(DBPath+'OID.INI');
  377.   try
  378.     nod := TreeView1.Items.AddChild(TreeView1.Selected, oid);
  379.     ComboBox1.Text := ini.ReadString(parent_oid, 'ra', '');
  380.  
  381.     di := ini.ReadInteger(parent_oid, 'delegates', 0);
  382.     ini.WriteInteger(parent_oid, 'delegates', di+1);
  383.     ini.WriteString(parent_oid, 'delegate'+IntToStr(di+1), oid);
  384.  
  385.     ini.WriteString(oid, 'createdate', DateToStr(date));
  386.     ini.WriteString(oid, 'ra', ComboBox1.Text);
  387.  
  388.     if PageControl1.ActivePage = TabSheet1 then Edit1.Text := '';
  389.     if PageControl1.ActivePage = TabSheet3 then Edit2.Text := '';
  390.  
  391.     TreeView1.Selected := nod;
  392.  
  393.     ini.UpdateFile;
  394.   finally
  395.     ini.Free;
  396.   end;
  397.  
  398.   ShowMessage('Created: ' + oid);
  399. end;
  400.  
  401. procedure TForm1.Button7Click(Sender: TObject);
  402. var
  403.   ini: TIniFile;
  404.   di: integer;
  405.   nod: TTreeNode;
  406.   sectionName, new_value, candidate: string;
  407.   i: integer;
  408. begin
  409.   ini := TIniFile.Create(DBPath+'RA.INI');
  410.   try
  411.     new_value := Edit8.Text;
  412.     new_value := Trim(new_value);
  413.     if new_value = '' then exit;
  414.  
  415.     sectionName := 'RA:'+new_value;
  416.  
  417.     for i := 0 to TreeView1.Selected.Count-1 do
  418.     begin
  419.       candidate := TreeView1.Selected.Item[i].Text;
  420.       if sectionName = candidate then ShowError('Item already exists');
  421.     end;
  422.  
  423.     di := ini.ReadInteger('RA:', 'count', 0);
  424.     ini.WriteInteger('RA:', 'count', di+1);
  425.     ini.WriteString('RA:', 'ra'+IntToStr(di+1), sectionName);
  426.  
  427.     nod := TreeView1.Items.AddChild(TreeView1.Selected, sectionName);
  428.  
  429.     ini.WriteString(sectionName, 'createdate', DateToStr(date));
  430.  
  431.     Edit8.Text := '';
  432.  
  433.     TreeView1.Selected := nod;
  434.  
  435.     ini.WriteString(sectionName, 'createdate', DateToStr(date));
  436.  
  437.     ini.UpdateFile;
  438.   finally
  439.     ini.Free;
  440.   end;
  441.  
  442.   ComboBox1.Items.Add(sectionName);
  443.  
  444.   ShowMessage('Created: ' + sectionName);
  445. end;
  446.  
  447. procedure TForm1.Button6Click(Sender: TObject);
  448. var
  449.   ini: TIniFile;
  450.   nod: TTreeNode;
  451.   parent_oid, this_oid: string;
  452.   i: integer;
  453.   sl: TStringList;
  454. begin
  455.   if MessageDlg('Are you sure?', mtConfirmation, mbYesNoCancel, 0) <> idYes then exit;
  456.  
  457.   ini := TIniFile.Create(DBPath+'OID.INI');
  458.   try
  459.     this_oid := Edit4.Text;
  460.     if TreeView1.Selected.Parent.Text = TITLE_OID then
  461.       parent_oid := 'OID:'
  462.     else
  463.       parent_oid := Copy(TreeView1.Selected.Parent.Text, 1, Pos(' ', TreeView1.Selected.Parent.Text+' ')-1);
  464.  
  465.     nod := TreeView1.Selected;
  466.     TreeView1.Selected := nod.Parent;
  467.     TreeView1.Items.Delete(nod);
  468.  
  469.     ini.EraseSection(this_oid);
  470.  
  471.     sl := TStringList.Create;
  472.     ini.ReadSections(sl);
  473.     for i := 0 to sl.Count-1 do
  474.     begin
  475.       if Copy(sl.Strings[i], 1, Length(this_oid)+1) = this_oid+'.' then
  476.       begin
  477.         ini.EraseSection(sl.Strings[i]);
  478.       end;
  479.     end;
  480.     sl.Free;
  481.  
  482.     for i := 1 to ini.ReadInteger(parent_oid, 'delegates', 0) do
  483.     begin
  484.       if ini.ReadString(parent_oid, 'delegate'+IntToStr(i), '') = this_oid then
  485.       begin
  486.         ini.WriteString(parent_oid, 'delegate'+IntToStr(i), '');
  487.       end;
  488.     end;
  489.  
  490.     ini.UpdateFile;
  491.   finally
  492.     ini.Free;
  493.   end;
  494. end;
  495.  
  496. procedure TForm1.Button8Click(Sender: TObject);
  497. var
  498.   ini: TIniFile;
  499.   nod: TTreeNode;
  500.   parent_ra, this_ra: string;
  501.   i: integer;
  502. begin
  503.   if MessageDlg('Are you sure?', mtConfirmation, mbYesNoCancel, 0) <> idYes then exit;
  504.  
  505.   ini := TIniFile.Create(DBPath+'RA.INI');
  506.   try
  507.     this_ra := Copy(Treeview1.Selected.Text, 1, Pos(' ',Treeview1.Selected.Text+' ')-1);
  508.     if TreeView1.Selected.Parent.Text = TITLE_RA then
  509.       parent_ra := 'RA:'
  510.     else
  511.       parent_ra := Copy(TreeView1.Selected.Parent.Text, 1, Pos(' ', TreeView1.Selected.Parent.Text+' ')-1);
  512.  
  513.     nod := TreeView1.Selected;
  514.     TreeView1.Selected := nod.Parent;
  515.     TreeView1.Items.Delete(nod);
  516.  
  517.     ini.EraseSection(this_ra);
  518.  
  519.     for i := 1 to ini.ReadInteger(parent_ra, 'count', 0) do
  520.     begin
  521.       if ini.ReadString(parent_ra, 'ra'+IntToStr(i), '') = this_ra then
  522.       begin
  523.         ini.WriteString(parent_ra, 'ra'+IntToStr(i), '');
  524.       end;
  525.     end;
  526.  
  527.     ComboBox1.Items.Delete(ComboBox1.Items.IndexOf(this_ra));
  528.  
  529.     ini.UpdateFile;
  530.   finally
  531.     ini.Free;
  532.   end;
  533. end;
  534.  
  535. function RandomStr(len: integer): string;
  536. var
  537.   i: integer;
  538. begin
  539.   result := '';
  540.   for i := 1 to len do
  541.   begin
  542.     result := result + Chr(ord('A') + Random(26));
  543.   end;
  544. end;
  545.  
  546. procedure TForm1.Button2Click(Sender: TObject);
  547. var
  548.   ini: TIniFile;
  549.   txtFile, asn1s: string;
  550.   modified: boolean;
  551. begin
  552.   // Attention: Do not rely on TreeView1.Selected.Text, because Button2.Click
  553.   // will be called in TreeView1OnChange()!
  554.  
  555.   ini := TIniFile.Create(DBPath+'OID.INI');
  556.   try
  557.     modified := false;
  558.  
  559.     if ini.ReadString(Edit4.Text, 'ra', '') <> ComboBox1.Text then
  560.     begin
  561.       modified := true;
  562.       ini.WriteString(Edit4.Text, 'ra', ComboBox1.Text);
  563.     end;
  564.  
  565.     if ini.ReadString(Edit4.Text, 'description', '') <> Edit3.Text then
  566.     begin
  567.       modified := true;
  568.       ini.WriteString(Edit4.Text, 'description', Edit3.Text);
  569.     end;
  570.  
  571.     if ini.ReadBool(Edit4.Text, 'draft', false) <> CheckBox1.Checked then
  572.     begin
  573.       modified := true;
  574.       ini.WriteBool(Edit4.Text, 'draft', CheckBox1.Checked);
  575.     end;
  576.  
  577.     if Memo1.Modified then
  578.     begin
  579.       modified := true;
  580.       if Trim(Memo1.Lines.Text) = '' then
  581.       begin
  582.         txtFile := ini.ReadString(Edit4.Text, 'information', '');
  583.         if FileExists(DBPath+txtFile) then
  584.         begin
  585.           DeleteFile(DBPath+txtFile);
  586.         end;
  587.         if txtFile <> '' then
  588.         begin
  589.           ini.WriteString(Edit4.Text, 'information', '')
  590.         end;
  591.       end
  592.       else
  593.       begin
  594.         txtFile := ini.ReadString(Edit4.Text, 'information', '');
  595.         if txtFile = '' then
  596.         begin
  597.           repeat
  598.             txtFile := RandomStr(8) + '.TXT';
  599.           until not FileExists(DBPath+txtFile);
  600.           ini.WriteString(Edit4.Text, 'information', txtFile);
  601.         end;
  602.  
  603.         Memo1.Lines.SaveToFile(DBPath+txtFile);
  604.         Memo1.Modified := false;
  605.       end;
  606.     end;
  607.  
  608.     asn1s := GetAsn1Ids(false);
  609.     if ini.ReadString(Edit4.Text, 'asn1id', '') <> asn1s then
  610.     begin
  611.       modified := true;
  612.       ini.WriteString(Edit4.Text, 'asn1id', asn1s);
  613.     end;
  614.  
  615.     if modified then
  616.     begin
  617.       ini.WriteString(Edit4.Text, 'updatedate', DateToStr(Date));
  618.       ini.Updatefile;
  619.     end;
  620.   finally
  621.     ini.Free;
  622.   end;
  623. end;
  624.  
  625. function TForm1.GetAsn1Ids(onlyfirst: boolean): string;
  626. var
  627.   i: integer;
  628. begin
  629.   result := '';
  630.   for i := 0 to ListBox1.Items.Count-1 do
  631.   begin
  632.     if result = '' then
  633.       result := ListBox1.Items.Strings[i]
  634.     else if not onlyfirst then
  635.       result := result + ',' + ListBox1.Items.Strings[i];
  636.   end;
  637. end;
  638.  
  639. function DirectoryExists(const Directory: string; FollowLink: Boolean = True): Boolean; // Source: Delphi 10.3.3
  640. var
  641.   Code: Cardinal;
  642.   Handle: THandle;
  643.   LastError: Cardinal;
  644. const
  645.   faSymLink = $00000400; // Available on POSIX and Vista and above
  646.   INVALID_FILE_ATTRIBUTES = DWORD($FFFFFFFF);
  647. begin
  648.   Result := False;
  649.   Code := GetFileAttributes(PChar(Directory));
  650.  
  651.   if Code <> INVALID_FILE_ATTRIBUTES then
  652.   begin
  653.     if faSymLink and Code = 0 then
  654.       Result := faDirectory and Code <> 0
  655.     else
  656.     begin
  657.       if FollowLink then
  658.       begin
  659.         Handle := CreateFile(PChar(Directory), GENERIC_READ, FILE_SHARE_READ, nil,
  660.           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  661.         if Handle <> INVALID_HANDLE_VALUE then
  662.         begin
  663.           CloseHandle(Handle);
  664.           Result := faDirectory and Code <> 0;
  665.         end;
  666.       end
  667.       else if faDirectory and Code <> 0 then
  668.         Result := True
  669.       else
  670.       begin
  671.         Handle := CreateFile(PChar(Directory), GENERIC_READ, FILE_SHARE_READ, nil,
  672.           OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0);
  673.         if Handle <> INVALID_HANDLE_VALUE then
  674.         begin
  675.           CloseHandle(Handle);
  676.           Result := False;
  677.         end
  678.         else
  679.           Result := True;
  680.       end;
  681.     end;
  682.   end
  683.   else
  684.   begin
  685.     LastError := GetLastError;
  686.     Result := (LastError <> ERROR_FILE_NOT_FOUND) and
  687.       (LastError <> ERROR_PATH_NOT_FOUND) and
  688.       (LastError <> ERROR_BAD_PATHNAME) and
  689.       (LastError <> ERROR_INVALID_NAME) and
  690.       (LastError <> ERROR_BAD_NETPATH) and
  691.       (LastError <> ERROR_NOT_READY) and
  692.       (LastError <> ERROR_BAD_NET_NAME);
  693.   end;
  694. end;
  695.  
  696. function TForm1.DBPath: string;
  697. var
  698.   ini: TIniFile;
  699. begin
  700.   ini := TIniFile.Create('.\OIDPLUS.INI');
  701.   try
  702.     if not ini.ValueExists('SETTINGS', 'DATA') then
  703.     begin
  704.       result := 'DB\';
  705.       ini.WriteString('SETTINGS', 'DATA', result);
  706.       ini.UpdateFile;
  707.     end
  708.     else
  709.     begin
  710.       result := ini.ReadString('SETTINGS', 'DATA', 'DB\');
  711.     end;
  712.     if not DirectoryExists(result) then MkDir(result);
  713.     if not DirectoryExists(result) then
  714.     begin
  715.       ShowError('Cannot create database directory '+result);
  716.     end;
  717.   finally
  718.     ini.Free;
  719.   end;
  720. end;
  721.  
  722. procedure TForm1.FormCreate(Sender: TObject);
  723. begin
  724.   PageControl1.ActivePage := TabSheet3;
  725.   Randomize;
  726. end;
  727.  
  728. procedure TForm1.SaveChangesIfRequired;
  729. begin
  730.   if PageControl1.ActivePage = TabSheet1 then Button2.Click; // Save changes
  731.   if PageControl1.ActivePage = TabSheet2 then Button9.Click; // Save changes
  732. end;
  733.  
  734. procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  735. begin
  736.   SaveChangesIfRequired;
  737.   CanClose := true;
  738. end;
  739.  
  740. procedure TForm1.CheckBox1Click(Sender: TObject);
  741. begin
  742.   if CheckBox1.Checked then
  743.     TreeView1.Selected.Text := Trim(Edit4.Text+' '+GetAsn1Ids(true))+' [DRAFT]'
  744.   else
  745.     TreeView1.Selected.Text := Trim(Edit4.Text+' '+GetAsn1Ids(true));
  746. end;
  747.  
  748. procedure TForm1.ShowError(msg: string);
  749. begin
  750.   MessageDlg(msg, mtError, [mbOk], 0);
  751.   Abort;
  752. end;
  753.  
  754. procedure TForm1.Button9Click(Sender: TObject);
  755. var
  756.   ini: TIniFile;
  757.   txtFile, asn1s: string;
  758.   modified: boolean;
  759. begin
  760.   // Attention: Do not rely on TreeView1.Selected.Text, because Button9.Click
  761.   // will be called in TreeView1OnChange()!
  762.  
  763.   ini := TIniFile.Create(DBPath+'RA.INI');
  764.   try
  765.     modified := false;
  766.     if ini.ReadString(Edit9.Text, 'name', '') <> Edit11.Text then
  767.     begin
  768.       modified := true;
  769.       ini.WriteString(Edit9.Text, 'name', Edit11.Text);
  770.     end;
  771.     if ini.ReadString(Edit9.Text, 'email', '') <> Edit12.Text then
  772.     begin
  773.       modified := true;
  774.       ini.WriteString(Edit9.Text, 'email', Edit12.Text);
  775.     end;
  776.     if ini.ReadString(Edit9.Text, 'phone', '') <> Edit13.Text then
  777.     begin
  778.       modified := true;
  779.       ini.WriteString(Edit9.Text, 'phone', Edit13.Text);
  780.     end;
  781.     if modified then
  782.     begin
  783.       ini.WriteString(Edit9.Text, 'updatedate', DateToStr(Date));
  784.       ini.Updatefile;
  785.     end;
  786.   finally
  787.     ini.Free;
  788.   end;
  789. end;
  790.  
  791. procedure TForm1.Edit8KeyPress(Sender: TObject; var Key: Char);
  792. begin
  793.   if Key = #13 then
  794.   begin
  795.     Button7.Click;
  796.     Key := #0;
  797.     Exit;
  798.   end;
  799.   if Key = #8(*backspace*) then exit;
  800.   if Key in ['a'..'z'] then Key := UpCase(Key);
  801.   if not (Key in ['A'..'Z', '-']) then
  802.   begin
  803.     Beep;
  804.     Key := #0;
  805.   end;
  806. end;
  807.  
  808. procedure TForm1.Edit11Change(Sender: TObject);
  809. begin
  810.   TreeView1.Selected.Text := Trim(Edit9.Text + ' ' + Edit11.Text);
  811. end;
  812.  
  813. procedure TForm1.ListBox1KeyDown(Sender: TObject; var Key: Word;
  814.   Shift: TShiftState);
  815. begin
  816.   If Key = 46(*DEL*) then
  817.   begin
  818.     Button3.Click;
  819.     Key := 0;
  820.   end;
  821. end;
  822.  
  823. procedure TForm1.Edit7KeyPress(Sender: TObject; var Key: Char);
  824. begin
  825.   if Key = #13 then
  826.   begin
  827.     Button1.Click;
  828.     Key := #0;
  829.   end;
  830. end;
  831.  
  832. procedure TForm1.Edit2KeyPress(Sender: TObject; var Key: Char);
  833. begin
  834.   if Key = #13 then
  835.   begin
  836.     Button5.Click;
  837.     Key := #0;
  838.   end;
  839. end;
  840.  
  841. procedure TForm1.Edit1KeyPress(Sender: TObject; var Key: Char);
  842. begin
  843.   if Key = #13 then
  844.   begin
  845.     Button4.Click;
  846.     Key := #0;
  847.   end;
  848. end;
  849.  
  850. procedure TForm1.TreeView1KeyDown(Sender: TObject; var Key: Word;
  851.   Shift: TShiftState);
  852. begin
  853.   if Key = 46(*DEL*) then
  854.   begin
  855.     if Copy(TreeView1.Selected.Text, 1, 4) = 'OID:' then
  856.     begin
  857.       Button6.Click;
  858.     end
  859.     else if Copy(TreeView1.Selected.Text, 1, 3) = 'RA:' then
  860.     begin
  861.       Button8.Click;
  862.     end
  863.     else
  864.     begin
  865.       Beep;
  866.     end;
  867.  
  868.     Key := 0;
  869.   end;
  870. end;
  871.  
  872. end.
  873.