Subversion Repositories oidplus

Rev

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

  1. program OIDPLUS;
  2.  
  3. (************************************************)
  4. (* OIDPLUS.PAS                                  *)
  5. (* Author:   Daniel Marschall                   *)
  6. (* Revision: 2022-02-14                         *)
  7. (* License:  Apache 2.0                         *)
  8. (* This file contains:                          *)
  9. (* - "OIDplus for DOS" program                  *)
  10. (************************************************)
  11.  
  12. uses
  13.   Dos, Crt, StrList, VtsFuncs, VtsCui, OidFile, OidUtils;
  14.  
  15. const
  16.   VERSIONINFO = 'Revision: 2022-02-14';
  17.   DEFAULT_STATUSBAR = '(C)2020-2022 ViaThinkSoft. Licensed under the terms of the Apache 2.0 license.';
  18.   DISKIO_SOUND_DEBUGGING = false;
  19.   DISKIO_SOUND_DELAY = 500;
  20.   ASNEDIT_LINES = 10;
  21.   DESCEDIT_LINES = 10;
  22.   DESCEDIT_PADDING = 3;
  23.  
  24. procedure _WriteOidFile(filename: string; oid: POid);
  25. begin
  26.   DrawStatusBar('Write file ' + filename + '...');
  27.   WriteOidFile(filename, oid);
  28.  
  29.   if DISKIO_SOUND_DEBUGGING then
  30.   begin
  31.     Sound(70);
  32.     Delay(DISKIO_SOUND_DELAY - 10);
  33.     NoSound;
  34.     Delay(10);
  35.   end;
  36.  
  37.   DrawStatusBar(DEFAULT_STATUSBAR);
  38. end;
  39.  
  40. procedure _ReadOidFile(filename: string; oid: POid);
  41. begin
  42.   DrawStatusBar('Read file ' + filename + '...');
  43.   ReadOidFile(filename, oid);
  44.  
  45.   if DISKIO_SOUND_DEBUGGING then
  46.   begin
  47.     Sound(50);
  48.     Delay(DISKIO_SOUND_DELAY - 10);
  49.     NoSound;
  50.     Delay(10);
  51.   end;
  52.  
  53.   DrawStatusBar(DEFAULT_STATUSBAR);
  54. end;
  55.  
  56. procedure _Pause;
  57. var
  58.   bakX, bakY: integer;
  59. begin
  60.   bakX := WhereX;
  61.   bakY := WhereY;
  62.   DrawStatusBar('Press any key to continue');
  63.   GoToXY(bakX, bakY);
  64.   ReadKey;
  65.   DrawStatusBar(DEFAULT_STATUSBAR);
  66. end;
  67.  
  68. function _ShowASNIds(subfile: string): string;
  69. var
  70.   coid: TOID;
  71.   j, jmax: integer;
  72.   sTmp: string;
  73. begin
  74.   sTmp := '';
  75.   InitOidDef(@coid);
  76.   _ReadOidFile(subfile, @coid);
  77.   jmax := ListCount(coid.ASNIds)-1;
  78.   for j := 0 to jmax do
  79.   begin
  80.     if j = 0 then sTmp := sTmp + ' (';
  81.     sTmp := sTmp + ListGetElement(coid.ASNIds, j);
  82.     if j = jmax then
  83.       sTmp := sTmp + ')'
  84.     else
  85.       sTmp := sTmp + ', ';
  86.   end;
  87.   FreeOidDef(@coid);
  88.   _ShowASNIds := sTmp;
  89. end;
  90.  
  91. function AsnAlreadyExisting(oid: POID; asnid: string): boolean;
  92. var
  93.   sTmp: string;
  94.   i: integer;
  95. begin
  96.   for i := 0 to ListCount(oid^.AsnIds)-1 do
  97.   begin
  98.     sTmp := ListGetElement(oid^.AsnIds, i);
  99.     if sTmp = asnid then
  100.     begin
  101.       AsnAlreadyExisting := true;
  102.       exit;
  103.     end;
  104.   end;
  105.   AsnAlreadyExisting := false;
  106. end;
  107.  
  108. function AsnEditor(oid: POID): boolean;
  109. var
  110.   asnList: PStringList;
  111.   i: integer;
  112.   x, y, w, h: integer;
  113.   res: integer;
  114.   sInput: string;
  115. begin
  116.   AsnEditor := false;
  117.  
  118.   repeat
  119.     InitList(asnList);
  120.  
  121.     for i := 0 to ListCount(oid^.ASNIds)-1 do
  122.     begin
  123.       ListAppend(asnList, ListGetElement(oid^.ASNIDs, i));
  124.     end;
  125.     ListAppend(asnList, '<NEW>');
  126.     ListAppend(asnList, '<SAVE>');
  127.     ListAppend(asnList, '<CANCEL>');
  128.  
  129.     DrawStatusBar(DEFAULT_STATUSBAR);
  130.     x := SINGLE_LINE_BOX_PADDING;
  131.     y := ScreenHeight div 2 - ASNEDIT_LINES div 2;
  132.     w := ScreenWidth - (SINGLE_LINE_BOX_PADDING-1)*2;
  133.     h := ASNEDIT_LINES;
  134.     res := DrawSelectionList(x, y, w, h,
  135.                              asnList, true,
  136.                              'EDIT ASN.1 IDENTIFIERS',
  137.                              2);
  138.  
  139.     (* Change double-border to thin-border *)
  140.     DrawThinBorder(x-1, y-1, w+2, h+2);
  141.     GoToXY(x+1, y-1);
  142.     Write('EDIT ASN.1 IDENTIFIERS');
  143.  
  144.     if res = -1 then
  145.     begin
  146.       exit;
  147.     end
  148.     else if res = ListCount(oid^.ASNIDs) then
  149.     begin
  150.       (* "NEW" item was selected *)
  151.       sInput := '';
  152.       repeat
  153.         if QueryVal(sInput,
  154.                     SINGLE_LINE_BOX_PADDING_INNER,
  155.                     ScreenHeight div 2,
  156.                     ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
  157.                     1,
  158.                     'ADD SINGLE ASN.1 ID',
  159.                     2) then
  160.         begin
  161.           if sInput = '' then continue;
  162.           if not ASN1IDValid(sInput) then
  163.           begin
  164.             ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true);
  165.             _Pause;
  166.           end
  167.           else if AsnAlreadyExisting(oid, sInput) then
  168.           begin
  169.             ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true);
  170.             _Pause;
  171.           end
  172.           else
  173.           begin
  174.             ListAppend(oid^.ASNIDs, sInput);
  175.             break;
  176.           end;
  177.         end
  178.         else break;
  179.       until false;
  180.     end
  181.     else if res = ListCount(oid^.ASNIDs)+1 then
  182.     begin
  183.       (* "SAVE" item was selected *)
  184.       AsnEditor := true;
  185.       Exit;
  186.     end
  187.     else if res = ListCount(oid^.ASNIDs)+2 then
  188.     begin
  189.       (* "CANCEL" item was selected *)
  190.       AsnEditor := false;
  191.       Exit;
  192.     end
  193.     else
  194.     begin
  195.       DrawStatusBar('Note: Remove the text to delete the ASN.1 identifier');
  196.       sInput := ListGetElement(oid^.ASNIDs, res);
  197.       repeat
  198.         if QueryVal(sInput,
  199.                     SINGLE_LINE_BOX_PADDING_INNER,
  200.                     ScreenHeight div 2,
  201.                     ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
  202.                     1,
  203.                     'EDIT SINGLE ASN.1 ID',
  204.                     2) then
  205.         begin
  206.           if sInput = '' then
  207.           begin
  208.             (* Empty input = Delete ASN.1 ID *)
  209.             ListDeleteElement(oid^.ASNIDs, res);
  210.             break;
  211.           end
  212.           else if not ASN1IDValid(sInput) then
  213.           begin
  214.             ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true);
  215.             _Pause;
  216.           end
  217.           else if AsnAlreadyExisting(oid, sInput) and
  218.               not (ListGetElement(oid^.ASNIDs, res) = sInput) then
  219.           begin
  220.             ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true);
  221.             _Pause;
  222.           end
  223.           else
  224.           begin
  225.             ListSetElement(oid^.ASNIDs, res, sInput);
  226.             break;
  227.           end;
  228.         end
  229.         else break;
  230.       until false;
  231.     end;
  232.   until false;
  233. end;
  234.  
  235. function DescEditor(oid: POID): boolean;
  236. var
  237.   sInput: string;
  238. begin
  239.   DescEditor := false;
  240.  
  241.   DrawStatusBar('Note: Press Ctrl+Return for a line-break.');
  242.   sInput := oid^.description;
  243.   if QueryVal(sInput,
  244.               DESCEDIT_PADDING,
  245.               ScreenHeight div 2 - DESCEDIT_LINES div 2,
  246.               ScreenWidth - (DESCEDIT_PADDING-1)*2,
  247.               DESCEDIT_LINES,
  248.               'EDIT DESCRIPTION',
  249.               2) then
  250.   begin
  251.     oid^.description := sInput;
  252.     DescEditor := true; (* request caller to save @oid *)
  253.   end;
  254. end;
  255.  
  256. function NextPossibleFileID: string;
  257. var
  258.   DirInfo: SearchRec;
  259.   list: PStringList;
  260.   iId: LongInt;
  261.   sId: string;
  262. begin
  263.   (* Put all found files into a list *)
  264.   InitList(list);
  265.   FindFirst('????????.OID', Archive, DirInfo);
  266.   while DosError = 0 do
  267.   begin
  268.     sId := Copy(DirInfo.Name, 1, 8);
  269.     ListAppend(list, sId);
  270.     FindNext(DirInfo);
  271.   end;
  272.  
  273.   (* Search for the first non existing item in the list *)
  274.   sId := '';
  275.   for iId := 0 to 99999999 do
  276.   begin
  277.     sId := ZeroPad(iId, 8);
  278.     if not ListContains(list, sId) then break;
  279.   end;
  280.   NextPossibleFileId := sId;
  281.   FreeList(list);
  282. end;
  283.  
  284. function NumIdAlreadyExisting(parentOID: POID; sInput: string): boolean;
  285. var
  286.   searchDotNotation: string;
  287.   sTmp: string;
  288.   i: integer;
  289. begin
  290.   if parentOID^.DotNotation = '' then
  291.     searchDotNotation := sInput
  292.   else
  293.     searchDotNotation := parentOID^.DotNotation + '.' + sInput;
  294.   for i := 0 to ListCount(parentOID^.SubIds)-1 do
  295.   begin
  296.     sTmp := ListGetElement(parentOID^.SubIds, i);
  297.     Delete(sTmp, 1, 8);
  298.     if sTmp = searchDotNotation then
  299.     begin
  300.       NumIdAlreadyExisting := true;
  301.       exit;
  302.     end;
  303.   end;
  304.   NumIdAlreadyExisting := false;
  305. end;
  306.  
  307. function NumIdEditor(oid: POID; parentOID: POID): boolean;
  308. var
  309.   sInput: string;
  310. begin
  311.   NumIdEditor := false;
  312.   sInput := '';
  313.  
  314.   repeat
  315.     if QueryVal(sInput,
  316.                 SINGLE_LINE_BOX_PADDING_INNER,
  317.                 ScreenHeight div 2,
  318.                 ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
  319.                 1,
  320.                 'ENTER NUMERIC ID',
  321.                 2) then
  322.     begin
  323.       if sInput = '' then continue;
  324.       if not IsNumeric(sInput) then
  325.       begin
  326.         ShowMessage('Invalid numeric ID (must be a positive integer)', 'ERROR', true);
  327.         _Pause;
  328.       end
  329.       else if (parentOID^.DotNotation='') and (StrToInt(sInput) > 2) then
  330.       begin
  331.         ShowMessage('Invalid numeric ID (root arc can only be 0, 1, or 2)', 'ERROR', true);
  332.         _Pause;
  333.       end
  334.       else if ((parentOID^.DotNotation='0') or (parentOID^.DotNotation='1')) and (StrToInt(sInput) > 39) then
  335.       begin
  336.         ShowMessage('Invalid numeric ID (root 0 and 1 must have sub-arc of 0..39)', 'ERROR', true);
  337.         _Pause;
  338.       end
  339.       else if NumIdAlreadyExisting(parentOID, sInput) then
  340.       begin
  341.         ShowMessage('This numeric ID is already used in this arc', 'ERROR', true);
  342.         _Pause;
  343.       end
  344.       else
  345.       begin
  346.         if parentOID^.DotNotation = '' then
  347.           oid^.DotNotation := sInput
  348.         else
  349.           oid^.DotNotation := parentOID^.DotNotation + '.' + sInput;
  350.         NumIdEditor := true; (* request caller to save @oid *)
  351.         Exit;
  352.       end;
  353.     end
  354.     else
  355.     begin
  356.       Exit;
  357.     end;
  358.   until false;
  359. end;
  360.  
  361. function NewOidEditor(oid: POID): boolean;
  362. var
  363.   newfilename: string;
  364.   newoid: TOID;
  365. begin
  366.   NewOidEditor := false;
  367.  
  368.   InitOidDef(@newoid);
  369.   newoid.FileId := NextPossibleFileID;
  370.   newoid.Parent := oid^.FileId + oid^.DotNotation;
  371.   if NumIdEditor(@newoid, oid) and
  372.      AsnEditor(@newoid) and
  373.      DescEditor(@newoid) then
  374.   begin
  375.     newfilename := newoid.FileId + '.OID';
  376.     _WriteOidFile(newfilename, @newoid);
  377.  
  378.     (* Add link to original file and enable the saving of it *)
  379.     ListAppend(oid^.SubIds, newoid.FileId + newoid.DotNotation);
  380.     NewOidEditor := true; (* request caller to save @oid *)
  381.   end;
  382.   FreeOidDef(@newoid);
  383. end;
  384.  
  385. procedure DeleteChildrenRecursive(oid: POID);
  386. var
  387.   i: integer;
  388.   childOID: TOID;
  389.   filenameChild: string;
  390. begin
  391.   for i := 0 to ListCount(oid^.SubIds)-1 do
  392.   begin
  393.     filenameChild := Copy(ListGetElement(oid^.SubIds, i), 1, 8) + '.OID';
  394.     InitOidDef(@childOID);
  395.     _ReadOidFile(filenameChild, @childOID);
  396.     DeleteChildrenRecursive(@childOID);
  397.     FreeOidDef(@childOID);
  398.     DeleteFile(filenameChild);
  399.   end;
  400.   ListClear(oid^.SubIds);
  401. end;
  402.  
  403. procedure DeleteOidRecursive(selfOID: POID);
  404. var
  405.   i: integer;
  406.   parentOID: TOID;
  407.   filenameSelf, filenameParent: string;
  408.   fileIdToDelete: string;
  409. begin
  410.   (* Remove all children and their files recursively *)
  411.   DeleteChildrenRecursive(selfOID);
  412.  
  413.   (* Remove forward reference in parent OID *)
  414.   filenameParent := Copy(selfOID^.Parent, 1, 8)+'.OID';
  415.   InitOidDef(@parentOID);
  416.   _ReadOidFile(filenameParent, @parentOID);
  417.   for i := 0 to ListCount(parentOID.SubIds)-1 do
  418.   begin
  419.     if Copy(ListGetElement(parentOID.SubIds, i), 1, 8) = selfOID^.FileId then
  420.     begin
  421.       ListDeleteElement(parentOID.SubIds, i);
  422.       _WriteOidFile(filenameParent, @parentOID);
  423.       break;
  424.     end;
  425.   end;
  426.   FreeOidDef(@parentOID);
  427.  
  428.   (* Delete own file *)
  429.   fileIdToDelete := selfOID^.FileId;
  430.   filenameSelf := fileIdToDelete+'.OID';
  431.   DeleteFile(filenameSelf);
  432. end;
  433.  
  434. procedure DisplayOIDFile(filename: string);
  435. const
  436.   ID_EXIT     = '?EXIT';
  437.   ID_ASNEDIT  = '?ASN1';
  438.   ID_DESCEDIT = '?DESC';
  439.   ID_ADDCHILD = '?ADDC';
  440.   ID_DELETE   = '?DELE';
  441.   NAVBAR_SIZE = 5;
  442. var
  443.   isRoot: boolean;
  444.   f: Text;
  445.   line, cmd: string;
  446.   oid: TOID;
  447.   i, menuX, menuY: integer;
  448.   linesLeft, linesRequired: integer;
  449.   sTmp, subfile: string;
  450.   sAsn: string;
  451.   subsel, subfiles: PStringList;
  452.   subselres: integer;
  453.   sTmp1: string;
  454. begin
  455.   repeat
  456.     InitOidDef(@oid);
  457.     _ReadOidFile(filename, @oid);
  458.  
  459.     (* Print OID information *)
  460.  
  461.     ClrScr;
  462.  
  463.     if oid.DotNotation = '' then
  464.       DrawTitleBar('OID ROOT')
  465.     else
  466.       DrawTitleBar('OID ' + oid.DotNotation);
  467.     GotoXY(ScreenWidth-Length(filename)+1,1);
  468.     TextBackground(White);
  469.     TextColor(Black);
  470.     WriteLn(filename);
  471.     TextBackground(Black);
  472.     TextColor(White);
  473.     DrawStatusBar(DEFAULT_STATUSBAR);
  474.     GotoXY(1,2);
  475.  
  476.     if oid.DotNotation <> '' then
  477.     begin
  478.       WriteLn('Dot-Notation:');
  479.       WriteLn(oid.DotNotation);
  480.       WriteLn('');
  481.     end;
  482.  
  483.     if Trim(oid.Description) <> '' then
  484.     begin
  485.       WriteLn('Description:');
  486.       WriteLn(oid.Description);
  487.       WriteLn('');
  488.     end;
  489.  
  490.     menuX := WhereX + 1;
  491.     menuY := ScreenHeight - NAVBAR_SIZE - 1;
  492.  
  493.     if ListCount(oid.ASNIDs) > 0 then
  494.     begin
  495.       linesLeft := menuY - WhereY - 1;
  496.       linesRequired := 1 + ListCount(oid.ASNIds);
  497.  
  498.       if LinesLeft < LinesRequired then
  499.       begin
  500.         (* Compact display of ASN.1 identifiers *)
  501.         Write('ASN.1-Identifiers: ');
  502.         for i := 0 to ListCount(oid.ASNIds)-1 do
  503.         begin
  504.           if i > 0 then Write(', ');
  505.           Write(ListGetElement(oid.ASNIds, i));
  506.         end;
  507.         WriteLn('');
  508.       end
  509.       else
  510.       begin
  511.         (* Long display of ASN.1 identifiers *)
  512.         WriteLn('ASN.1-Identifiers:');
  513.         for i := 0 to ListCount(oid.ASNIds)-1 do
  514.         begin
  515.           WriteLn('- '+ListGetElement(oid.ASNIds, i));
  516.         end;
  517.         WriteLn('');
  518.       end;
  519.     end;
  520.  
  521.     (* Now prepare the menu entries *)
  522.  
  523.     InitList(subsel);
  524.     InitList(subfiles);
  525.  
  526.     sTmp := oid.Parent;
  527.     if sTmp = '' then
  528.     begin
  529.       isRoot := true;
  530.     end
  531.     else
  532.     begin
  533.       Delete(sTmp, 1, 8);
  534.       isRoot := sTmp = oid.DotNotation;
  535.     end;
  536.  
  537.     if (oid.Parent <> '') and not isRoot then
  538.     begin
  539.       sTmp := oid.Parent;
  540.       subfile := Copy(sTmp, 1, 8)+'.OID';
  541.       Delete(sTmp, 1, 8);
  542.       sTmp := sTmp + _ShowASNIds(subfile);
  543.       ListAppend(subsel, 'Go to parent ' + sTmp);
  544.       ListAppend(subfiles, subfile);
  545.     end;
  546.  
  547.     if isRoot then
  548.     begin
  549.       ListAppend(subsel, 'Back to main menu');
  550.       ListAppend(subfiles, ID_EXIT);
  551.     end;
  552.  
  553.     for i := 0 to ListCount(oid.SubIds)-1 do
  554.     begin
  555.       sTmp := ListGetElement(oid.SubIds, i);
  556.       subfile := Copy(sTmp, 1, 8)+'.OID';
  557.       Delete(sTmp, 1, 8);
  558.       sTmp := sTmp + _ShowASNIds(subfile);
  559.       ListAppend(subsel, 'Go to child  ' + sTmp);
  560.       ListAppend(subfiles, subfile);
  561.     end;
  562.  
  563.     if oid.DotNotation <> '' then
  564.     begin
  565.       ListAppend(subsel, 'Edit ASN.1 identifiers');
  566.       ListAppend(subfiles, ID_ASNEDIT);
  567.     end;
  568.  
  569.     ListAppend(subsel, 'Edit description');
  570.     ListAppend(subfiles, ID_DESCEDIT);
  571.  
  572.     ListAppend(subsel, 'Add child');
  573.     ListAppend(subfiles, ID_ADDCHILD);
  574.  
  575.     if not isRoot then
  576.     begin
  577.       ListAppend(subsel, 'Delete OID');
  578.       ListAppend(subfiles, ID_DELETE);
  579.     end;
  580.  
  581.     (* Show menu *)
  582.  
  583.     subselres := DrawSelectionList(menuX, menuY,
  584.                                    ScreenWidth-2,
  585.                                    NAVBAR_SIZE,
  586.                                    subsel,
  587.                                    true,
  588.                                    'SELECT ACTION',
  589.                                    1);
  590.  
  591.     (* Process user selection *)
  592.  
  593.     if subselres = -1 then
  594.     begin
  595.       exit;
  596.     end
  597.     else
  598.     begin
  599.       sTmp1 := ListGetElement(subfiles, subselres);
  600.       if sTmp1 = ID_ASNEDIT then
  601.       begin
  602.         if AsnEditor(@oid) then
  603.           _WriteOidFile(filename, @oid);
  604.       end
  605.       else if sTmp1 = ID_DESCEDIT then
  606.       begin
  607.         if DescEditor(@oid) then
  608.           _WriteOidFile(filename, @oid);
  609.       end
  610.       else if sTmp1 = ID_ADDCHILD then
  611.       begin
  612.         if NewOidEditor(@oid) then
  613.         begin
  614.           _WriteOidFile(filename, @oid);
  615.         end;
  616.       end
  617.       else if sTmp1 = ID_DELETE then
  618.       begin
  619.         ShowMessage('Are you sure you want to delete this OID?', 'DELETE OID', true);
  620.         DrawStatusBar('Y = Yes; any other key = No');
  621.         if UpCase(ReadKey) = 'Y' then
  622.         begin
  623.           filename := Copy(oid.Parent,1,8)+'.OID';
  624.           DeleteOidRecursive(@oid);
  625.         end;
  626.       end
  627.       else if sTmp1 = ID_EXIT then
  628.       begin
  629.         exit;
  630.       end
  631.       else
  632.       begin
  633.         filename := sTmp1;
  634.       end;
  635.     end;
  636.     FreeList(subsel);
  637.     FreeList(subfiles);
  638.  
  639.     FreeOidDef(@oid);
  640.   until false;
  641. end;
  642.  
  643. procedure CreateInitOIDFile(filename: string);
  644. var
  645.   oid: TOID;
  646. begin
  647.   InitOidDef(@oid);
  648.   oid.Description := 'This is the root of the OID tree.' +#13#10 +
  649.                      #13#10 +
  650.                      'Valid subsequent arcs are per definition:' + #13#10 +
  651.                      '- 0 (itu-t)' + #13#10 +
  652.                      '- 1 (iso)' + #13#10 +
  653.                      '- 2 (joint-iso-itu-t)';
  654.   oid.FileId      := '00000000';
  655.   oid.DotNotation := '';
  656.   oid.Parent      := '00000000';
  657.   _WriteOidFile(filename, @oid);
  658.   FreeOidDef(@oid);
  659. end;
  660.  
  661. procedure OP_ManageOIDs;
  662. begin
  663.   ClrScr;
  664.   DrawTitleBar('Manage Object Identifiers');
  665.   DrawStatusBar('');
  666.  
  667.   if not FileExists('00000000.OID') then
  668.   begin
  669.     CreateInitOIDFile('00000000.OID');
  670.   end;
  671.   DisplayOIDFile('00000000.OID');
  672. end;
  673.  
  674. procedure OP_ManageRAs;
  675. begin
  676.   ClrScr;
  677.   DrawTitleBar('Manage Registration Authorities');
  678.   DrawStatusBar('');
  679.  
  680.   (* TODO: Implement "Manage RAs" feature *)
  681.   ShowMessage('This feature has not yet been implemented!', 'NOTICE', true);
  682.   _Pause;
  683. end;
  684.  
  685. procedure OP_ReturnToMSDOS;
  686. begin
  687.   ClrScr;
  688. end;
  689.  
  690. procedure OP_MainMenu;
  691. const
  692.   MenuWidth = 15;
  693.   MenuHeight = 3;
  694. var
  695.   menu: PStringList;
  696.   menuRes, menuLeft, menuTop: integer;
  697. begin
  698.   repeat
  699.     ClrScr;
  700.  
  701.     DrawTitleBar('Welcome to OIDplus for DOS');
  702.     DrawStatusBar(DEFAULT_STATUSBAR);
  703.     GoToXY(ScreenWidth-Length(VERSIONINFO), ScreenHeight-1);
  704.     Write(VERSIONINFO);
  705.  
  706.     InitList(menu);
  707.     ListAppend(menu, 'Manage OIDs');
  708.     ListAppend(menu, 'Manage RAs');
  709.     ListAppend(menu, 'Return to DOS');
  710.     menuLeft := round(ScreenWidth/2 -MenuWidth/2);
  711.     menuTop  := round(ScreenHeight/2-MenuHeight/2);
  712.     menuRes  := DrawSelectionList(menuLeft, menuTop, MenuWidth, MenuHeight, menu, true, 'MAIN MENU', 2);
  713.     FreeList(menu);
  714.  
  715.     if menuRes = 0 then
  716.     begin
  717.       OP_ManageOIDs;
  718.     end;
  719.  
  720.     if menuRes = 1 then
  721.     begin
  722.       OP_ManageRAs;
  723.     end;
  724.   until (menuRes = 2) or (menuRes = -1);
  725.  
  726.   OP_ReturnToMSDOS;
  727. end;
  728.  
  729. begin
  730.   OP_MainMenu;
  731. end.
  732.