Subversion Repositories oidplus

Rev

Rev 234 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | RSS feed

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