Subversion Repositories oidplus

Rev

Rev 739 | Rev 741 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
733 daniel-mar 1
program OIDPLUS;
2
 
3
(************************************************)
4
(* OIDPLUS.PAS                                  *)
5
(* Author:   Daniel Marschall                   *)
734 daniel-mar 6
(* Revision: 2022-02-14                         *)
733 daniel-mar 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
735 daniel-mar 16
  VERSIONINFO            = 'Revision: 2022-02-14';
17
  DEFAULT_STATUSBAR      = '(C)2020-2022 ViaThinkSoft. Licensed under the terms of the Apache 2.0 license.';
740 daniel-mar 18
  TITLEBAR_LEFT_TEXT     = 'OIDplus';
733 daniel-mar 19
  DISKIO_SOUND_DEBUGGING = false;
735 daniel-mar 20
  DISKIO_SOUND_DELAY     = 500;
21
  ASNEDIT_LINES          = 10;
22
  DESCEDIT_LINES         = 10;
23
  DESCEDIT_PADDING       = 3;
24
  ACTIONMENU_SIZE        = 5;
25
  MAINMENU_WIDTH         = 15;
26
  MAINMENU_HEIGHT        = 3;
27
  MAINMENU_ALLOW_ESC     = false;
740 daniel-mar 28
  TREEVIEW_INDENT        = 0;
29
  TREEVIEW_INCLUDE_DESC  = true;
30
  TREEVIEW_WIDTH         = 80;
733 daniel-mar 31
 
32
procedure _WriteOidFile(filename: string; oid: POid);
33
begin
34
  DrawStatusBar('Write file ' + filename + '...');
35
  WriteOidFile(filename, oid);
36
 
37
  if DISKIO_SOUND_DEBUGGING then
38
  begin
39
    Sound(70);
40
    Delay(DISKIO_SOUND_DELAY - 10);
41
    NoSound;
42
    Delay(10);
43
  end;
44
 
45
  DrawStatusBar(DEFAULT_STATUSBAR);
46
end;
47
 
48
procedure _ReadOidFile(filename: string; oid: POid);
49
begin
50
  DrawStatusBar('Read file ' + filename + '...');
51
  ReadOidFile(filename, oid);
52
 
53
  if DISKIO_SOUND_DEBUGGING then
54
  begin
55
    Sound(50);
56
    Delay(DISKIO_SOUND_DELAY - 10);
57
    NoSound;
58
    Delay(10);
59
  end;
60
 
61
  DrawStatusBar(DEFAULT_STATUSBAR);
62
end;
63
 
64
procedure _Pause;
65
var
66
  bakX, bakY: integer;
67
begin
68
  bakX := WhereX;
69
  bakY := WhereY;
70
  DrawStatusBar('Press any key to continue');
71
  GoToXY(bakX, bakY);
72
  ReadKey;
73
  DrawStatusBar(DEFAULT_STATUSBAR);
74
end;
75
 
740 daniel-mar 76
function _ShowASNIds(childOID: POID): string;
733 daniel-mar 77
var
78
  j, jmax: integer;
79
  sTmp: string;
80
begin
81
  sTmp := '';
735 daniel-mar 82
  jmax := ListCount(childOID^.ASNIds)-1;
733 daniel-mar 83
  for j := 0 to jmax do
84
  begin
85
    if j = 0 then sTmp := sTmp + ' (';
735 daniel-mar 86
    sTmp := sTmp + ListGetElement(childOID^.ASNIds, j);
733 daniel-mar 87
    if j = jmax then
88
      sTmp := sTmp + ')'
89
    else
90
      sTmp := sTmp + ', ';
91
  end;
92
  _ShowASNIds := sTmp;
93
end;
94
 
95
function AsnAlreadyExisting(oid: POID; asnid: string): boolean;
96
var
97
  sTmp: string;
98
  i: integer;
99
begin
100
  for i := 0 to ListCount(oid^.AsnIds)-1 do
101
  begin
102
    sTmp := ListGetElement(oid^.AsnIds, i);
103
    if sTmp = asnid then
104
    begin
105
      AsnAlreadyExisting := true;
106
      exit;
107
    end;
108
  end;
109
  AsnAlreadyExisting := false;
110
end;
111
 
112
function AsnEditor(oid: POID): boolean;
113
var
114
  asnList: PStringList;
115
  i: integer;
116
  x, y, w, h: integer;
117
  res: integer;
118
  sInput: string;
735 daniel-mar 119
  menuIdNew, menuIdSave, menuIdExit: integer;
733 daniel-mar 120
begin
121
  AsnEditor := false;
122
 
123
  repeat
735 daniel-mar 124
    CreateList(asnList);
733 daniel-mar 125
 
126
    for i := 0 to ListCount(oid^.ASNIds)-1 do
127
    begin
128
      ListAppend(asnList, ListGetElement(oid^.ASNIDs, i));
129
    end;
735 daniel-mar 130
    menuIdNew  := ListAppend(asnList, '<NEW>');
131
    menuIdSave := ListAppend(asnList, '<SAVE>');
132
    menuIdExit := ListAppend(asnList, '<CANCEL>');
733 daniel-mar 133
 
134
    DrawStatusBar(DEFAULT_STATUSBAR);
135
    x := SINGLE_LINE_BOX_PADDING;
136
    y := ScreenHeight div 2 - ASNEDIT_LINES div 2;
137
    w := ScreenWidth - (SINGLE_LINE_BOX_PADDING-1)*2;
138
    h := ASNEDIT_LINES;
139
    res := DrawSelectionList(x, y, w, h,
140
                             asnList, true,
141
                             'EDIT ASN.1 IDENTIFIERS',
142
                             2);
735 daniel-mar 143
    FreeList(asnList);
733 daniel-mar 144
 
145
    (* Change double-border to thin-border *)
146
    DrawThinBorder(x-1, y-1, w+2, h+2);
147
    GoToXY(x+1, y-1);
148
    Write('EDIT ASN.1 IDENTIFIERS');
149
 
150
    if res = -1 then
151
    begin
152
      exit;
153
    end
735 daniel-mar 154
    else if res = menuIdNew then
733 daniel-mar 155
    begin
156
      (* "NEW" item was selected *)
157
      sInput := '';
158
      repeat
159
        if QueryVal(sInput,
160
                    SINGLE_LINE_BOX_PADDING_INNER,
161
                    ScreenHeight div 2,
162
                    ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
163
                    1,
164
                    'ADD SINGLE ASN.1 ID',
165
                    2) then
166
        begin
167
          if sInput = '' then continue;
168
          if not ASN1IDValid(sInput) then
169
          begin
170
            ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true);
171
            _Pause;
172
          end
173
          else if AsnAlreadyExisting(oid, sInput) then
174
          begin
175
            ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true);
176
            _Pause;
177
          end
178
          else
179
          begin
180
            ListAppend(oid^.ASNIDs, sInput);
181
            break;
182
          end;
183
        end
184
        else break;
185
      until false;
186
    end
735 daniel-mar 187
    else if res = menuIdSave then
733 daniel-mar 188
    begin
189
      (* "SAVE" item was selected *)
190
      AsnEditor := true;
191
      Exit;
192
    end
735 daniel-mar 193
    else if res = menuIdExit then
733 daniel-mar 194
    begin
195
      (* "CANCEL" item was selected *)
196
      AsnEditor := false;
197
      Exit;
198
    end
199
    else
200
    begin
201
      DrawStatusBar('Note: Remove the text to delete the ASN.1 identifier');
202
      sInput := ListGetElement(oid^.ASNIDs, res);
203
      repeat
204
        if QueryVal(sInput,
205
                    SINGLE_LINE_BOX_PADDING_INNER,
206
                    ScreenHeight div 2,
207
                    ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
208
                    1,
209
                    'EDIT SINGLE ASN.1 ID',
210
                    2) then
211
        begin
212
          if sInput = '' then
213
          begin
214
            (* Empty input = Delete ASN.1 ID *)
737 daniel-mar 215
            ListDeleteElementByIndex(oid^.ASNIDs, res);
733 daniel-mar 216
            break;
217
          end
218
          else if not ASN1IDValid(sInput) then
219
          begin
220
            ShowMessage('Invalid ASN1.ID! (Require -, a..z, A..Z, 0..9, begin with a-z)', 'ERROR', true);
221
            _Pause;
222
          end
223
          else if AsnAlreadyExisting(oid, sInput) and
224
              not (ListGetElement(oid^.ASNIDs, res) = sInput) then
225
          begin
226
            ShowMessage('ASN.1 identifier is already existing on this arc', 'ERROR', true);
227
            _Pause;
228
          end
229
          else
230
          begin
231
            ListSetElement(oid^.ASNIDs, res, sInput);
232
            break;
233
          end;
234
        end
235
        else break;
236
      until false;
237
    end;
238
  until false;
239
end;
240
 
241
function DescEditor(oid: POID): boolean;
242
var
243
  sInput: string;
244
begin
245
  DescEditor := false;
246
 
247
  DrawStatusBar('Note: Press Ctrl+Return for a line-break.');
248
  sInput := oid^.description;
249
  if QueryVal(sInput,
250
              DESCEDIT_PADDING,
251
              ScreenHeight div 2 - DESCEDIT_LINES div 2,
252
              ScreenWidth - (DESCEDIT_PADDING-1)*2,
253
              DESCEDIT_LINES,
254
              'EDIT DESCRIPTION',
255
              2) then
256
  begin
257
    oid^.description := sInput;
740 daniel-mar 258
    DescEditor := true; (* request caller to save <oid> *)
733 daniel-mar 259
  end;
260
end;
261
 
262
function NextPossibleFileID: string;
263
var
264
  DirInfo: SearchRec;
265
  list: PStringList;
266
  iId: LongInt;
267
  sId: string;
268
begin
269
  (* Put all found files into a list *)
735 daniel-mar 270
  CreateList(list);
733 daniel-mar 271
  FindFirst('????????.OID', Archive, DirInfo);
272
  while DosError = 0 do
273
  begin
274
    sId := Copy(DirInfo.Name, 1, 8);
275
    ListAppend(list, sId);
276
    FindNext(DirInfo);
277
  end;
278
 
279
  (* Search for the first non existing item in the list *)
280
  sId := '';
281
  for iId := 0 to 99999999 do
282
  begin
283
    sId := ZeroPad(iId, 8);
284
    if not ListContains(list, sId) then break;
285
  end;
286
  NextPossibleFileId := sId;
287
  FreeList(list);
288
end;
289
 
290
function NumIdAlreadyExisting(parentOID: POID; sInput: string): boolean;
291
var
292
  searchDotNotation: string;
293
  sTmp: string;
294
  i: integer;
295
begin
296
  if parentOID^.DotNotation = '' then
297
    searchDotNotation := sInput
298
  else
299
    searchDotNotation := parentOID^.DotNotation + '.' + sInput;
300
  for i := 0 to ListCount(parentOID^.SubIds)-1 do
301
  begin
302
    sTmp := ListGetElement(parentOID^.SubIds, i);
735 daniel-mar 303
    if DotNotationPart(sTmp) = searchDotNotation then
733 daniel-mar 304
    begin
305
      NumIdAlreadyExisting := true;
306
      exit;
307
    end;
308
  end;
309
  NumIdAlreadyExisting := false;
310
end;
311
 
312
function NumIdEditor(oid: POID; parentOID: POID): boolean;
313
var
314
  sInput: string;
315
begin
316
  NumIdEditor := false;
317
  sInput := '';
318
 
319
  repeat
320
    if QueryVal(sInput,
321
                SINGLE_LINE_BOX_PADDING_INNER,
322
                ScreenHeight div 2,
323
                ScreenWidth - (SINGLE_LINE_BOX_PADDING_INNER-1)*2,
324
                1,
325
                'ENTER NUMERIC ID',
326
                2) then
327
    begin
328
      if sInput = '' then continue;
739 daniel-mar 329
      if not IsPositiveInteger(sInput) then
733 daniel-mar 330
      begin
331
        ShowMessage('Invalid numeric ID (must be a positive integer)', 'ERROR', true);
332
        _Pause;
333
      end
334
      else if (parentOID^.DotNotation='') and (StrToInt(sInput) > 2) then
335
      begin
336
        ShowMessage('Invalid numeric ID (root arc can only be 0, 1, or 2)', 'ERROR', true);
337
        _Pause;
338
      end
339
      else if ((parentOID^.DotNotation='0') or (parentOID^.DotNotation='1')) and (StrToInt(sInput) > 39) then
340
      begin
341
        ShowMessage('Invalid numeric ID (root 0 and 1 must have sub-arc of 0..39)', 'ERROR', true);
342
        _Pause;
343
      end
344
      else if NumIdAlreadyExisting(parentOID, sInput) then
345
      begin
346
        ShowMessage('This numeric ID is already used in this arc', 'ERROR', true);
347
        _Pause;
348
      end
349
      else
350
      begin
351
        if parentOID^.DotNotation = '' then
352
          oid^.DotNotation := sInput
353
        else
354
          oid^.DotNotation := parentOID^.DotNotation + '.' + sInput;
740 daniel-mar 355
        NumIdEditor := true; (* request caller to save <oid> *)
733 daniel-mar 356
        Exit;
357
      end;
358
    end
359
    else
360
    begin
361
      Exit;
362
    end;
363
  until false;
364
end;
365
 
366
function NewOidEditor(oid: POID): boolean;
367
var
368
  newfilename: string;
735 daniel-mar 369
  newOID: POID;
733 daniel-mar 370
begin
371
  NewOidEditor := false;
372
 
735 daniel-mar 373
  CreateOidDef(newOID);
374
  newOID^.FileId := NextPossibleFileID;
375
  newOID^.Parent := oid^.FileId + oid^.DotNotation;
376
  if NumIdEditor(newOID, oid) and
377
     AsnEditor(newOID) and
378
     DescEditor(newOID) then
734 daniel-mar 379
  begin
735 daniel-mar 380
    newfilename := newOID^.FileId + '.OID';
381
    _WriteOidFile(newfilename, newOID);
733 daniel-mar 382
 
734 daniel-mar 383
    (* Add link to original file and enable the saving of it *)
735 daniel-mar 384
    ListAppend(oid^.SubIds, newOID^.FileId + newOID^.DotNotation);
740 daniel-mar 385
    NewOidEditor := true; (* request caller to save <oid> *)
734 daniel-mar 386
  end;
735 daniel-mar 387
  FreeOidDef(newOID);
733 daniel-mar 388
end;
389
 
390
procedure DeleteChildrenRecursive(oid: POID);
391
var
392
  i: integer;
735 daniel-mar 393
  childOID: POID;
733 daniel-mar 394
  filenameChild: string;
395
begin
396
  for i := 0 to ListCount(oid^.SubIds)-1 do
397
  begin
735 daniel-mar 398
    filenameChild := FileIdPart(ListGetElement(oid^.SubIds, i)) + '.OID';
740 daniel-mar 399
    if FileExists(filenameChild) then
400
    begin
401
      CreateOidDef(childOID);
402
      _ReadOidFile(filenameChild, childOID);
403
      DeleteChildrenRecursive(childOID);
404
      FreeOidDef(childOID);
405
      DeleteFile(filenameChild);
406
    end;
733 daniel-mar 407
  end;
408
  ListClear(oid^.SubIds);
409
end;
410
 
411
procedure DeleteOidRecursive(selfOID: POID);
412
var
413
  i: integer;
735 daniel-mar 414
  parentOID: POID;
733 daniel-mar 415
  filenameSelf, filenameParent: string;
416
begin
417
  (* Remove all children and their files recursively *)
418
  DeleteChildrenRecursive(selfOID);
419
 
420
  (* Remove forward reference in parent OID *)
735 daniel-mar 421
  filenameParent := FileIdPart(selfOID^.Parent) + '.OID';
740 daniel-mar 422
  if FileExists(filenameParent) then
733 daniel-mar 423
  begin
740 daniel-mar 424
    CreateOidDef(parentOID);
425
    _ReadOidFile(filenameParent, parentOID);
426
    if ListDeleteElementByValue(parentOID^.SubIds, selfOID^.FileId + selfOID^.DotNotation) then
427
    begin
428
      _WriteOidFile(filenameParent, parentOID);
429
    end;
430
    FreeOidDef(parentOID);
733 daniel-mar 431
  end;
432
 
433
  (* Delete own file *)
737 daniel-mar 434
  filenameSelf := selfOID^.FileId + '.OID';
740 daniel-mar 435
  if FileExists(filenameSelf) then
436
  begin
437
    DeleteFile(filenameSelf);
438
  end;
733 daniel-mar 439
end;
440
 
735 daniel-mar 441
function _DeleteConfirmation: boolean;
442
var
443
  sc: Char;
444
begin
445
  repeat
446
    ShowMessage('Are you sure you want to delete this OID? (Y/N)', 'DELETE OID', true);
737 daniel-mar 447
    DrawStatusBar('Y=Yes, N=No');
735 daniel-mar 448
 
449
    sc := ReadKey;
450
    if sc = #0 then
451
    begin
452
      (* Extended key. Nothing we care about. *)
453
      ReadKey;
454
      continue;
455
    end;
456
 
457
    if UpCase(sc) = 'Y' then
458
    begin
459
      _DeleteConfirmation := true;
460
      break;
737 daniel-mar 461
    end
462
    else if UpCase(sc) = 'N' then
735 daniel-mar 463
    begin
464
      _DeleteConfirmation := false;
465
      break;
466
    end;
467
  until false;
468
end;
469
 
737 daniel-mar 470
procedure _DrawOidTitleBar(filename: string; oid: POID);
471
begin
472
  if oid^.DotNotation = '' then
738 daniel-mar 473
    DrawTitleBar('OID ROOT', TITLEBAR_LEFT_TEXT, filename)
737 daniel-mar 474
  else
738 daniel-mar 475
    DrawTitleBar('OID ' + oid^.DotNotation, TITLEBAR_LEFT_TEXT, filename);
737 daniel-mar 476
end;
477
 
733 daniel-mar 478
procedure DisplayOIDFile(filename: string);
479
var
480
  isRoot: boolean;
740 daniel-mar 481
  oid, tmpOID: POID;
733 daniel-mar 482
  i, menuX, menuY: integer;
483
  linesLeft, linesRequired: integer;
484
  sTmp, subfile: string;
485
  subsel, subfiles: PStringList;
486
  subselres: integer;
735 daniel-mar 487
  exitRequest: boolean;
488
  menuIdExit, menuIdAsnEdit, menuIdDescEdit, menuIdAdd, menuIdDelete: integer;
733 daniel-mar 489
begin
735 daniel-mar 490
  exitRequest := false;
733 daniel-mar 491
  repeat
740 daniel-mar 492
    if not FileExists(filename) then
493
    begin
494
      ShowMessage('File ' + filename + ' not found', 'ERROR', true);
495
      _Pause;
496
      exit;
497
    end;
498
 
735 daniel-mar 499
    CreateOidDef(oid);
500
    _ReadOidFile(filename, oid);
733 daniel-mar 501
 
502
    (* Print OID information *)
503
 
504
    ClrScr;
737 daniel-mar 505
    _DrawOidTitleBar(filename, oid);
733 daniel-mar 506
    DrawStatusBar(DEFAULT_STATUSBAR);
507
    GotoXY(1,2);
508
 
735 daniel-mar 509
    if oid^.DotNotation <> '' then
733 daniel-mar 510
    begin
511
      WriteLn('Dot-Notation:');
735 daniel-mar 512
      WriteLn(oid^.DotNotation);
733 daniel-mar 513
      WriteLn('');
514
    end;
515
 
735 daniel-mar 516
    if Trim(oid^.Description) <> '' then
733 daniel-mar 517
    begin
518
      WriteLn('Description:');
735 daniel-mar 519
      WriteLn(oid^.Description);
733 daniel-mar 520
      WriteLn('');
521
    end;
522
 
523
    menuX := WhereX + 1;
735 daniel-mar 524
    menuY := ScreenHeight - ACTIONMENU_SIZE - 1;
733 daniel-mar 525
 
735 daniel-mar 526
    if ListCount(oid^.ASNIDs) > 0 then
733 daniel-mar 527
    begin
528
      linesLeft := menuY - WhereY - 1;
735 daniel-mar 529
      linesRequired := 1 + ListCount(oid^.ASNIds);
733 daniel-mar 530
 
531
      if LinesLeft < LinesRequired then
532
      begin
533
        (* Compact display of ASN.1 identifiers *)
534
        Write('ASN.1-Identifiers: ');
735 daniel-mar 535
        for i := 0 to ListCount(oid^.ASNIds)-1 do
733 daniel-mar 536
        begin
537
          if i > 0 then Write(', ');
735 daniel-mar 538
          Write(ListGetElement(oid^.ASNIds, i));
733 daniel-mar 539
        end;
540
        WriteLn('');
541
      end
542
      else
543
      begin
544
        (* Long display of ASN.1 identifiers *)
545
        WriteLn('ASN.1-Identifiers:');
735 daniel-mar 546
        for i := 0 to ListCount(oid^.ASNIds)-1 do
733 daniel-mar 547
        begin
735 daniel-mar 548
          WriteLn('- '+ListGetElement(oid^.ASNIds, i));
733 daniel-mar 549
        end;
550
        WriteLn('');
551
      end;
552
    end;
553
 
554
    (* Now prepare the menu entries *)
555
 
737 daniel-mar 556
    CreateList(subsel);   (* Contains the human readable OID name *)
557
    CreateList(subfiles); (* Contains the file name               *)
733 daniel-mar 558
 
735 daniel-mar 559
    if oid^.Parent = '' then
733 daniel-mar 560
    begin
561
      isRoot := true;
562
    end
563
    else
564
    begin
735 daniel-mar 565
      isRoot := DotNotationPart(oid^.Parent) = oid^.DotNotation;
733 daniel-mar 566
    end;
567
 
735 daniel-mar 568
    if (oid^.Parent <> '') and not isRoot then
733 daniel-mar 569
    begin
735 daniel-mar 570
      sTmp := oid^.Parent;
571
      subfile := FileIdPart(sTmp) + '.OID';
740 daniel-mar 572
      if FileExists(subfile) then
573
      begin
574
        CreateOidDef(tmpOID);
575
        _ReadOidFile(subfile, tmpOID);
576
        ListAppend(subsel, 'Go to parent ' + DotNotationPart(sTmp) + _ShowASNIds(tmpOID));
577
        FreeOidDef(tmpOID);
578
      end
579
      else
580
      begin
581
        ListAppend(subsel, 'Go to parent ' + DotNotationPart(sTmp) + ' (FILE NOT FOUND)');
582
      end;
733 daniel-mar 583
      ListAppend(subfiles, subfile);
584
    end;
585
 
586
    if isRoot then
587
    begin
735 daniel-mar 588
      menuIdExit := ListAppend(subsel, 'Back to main menu');
589
      ListAppend(subfiles, '');
590
    end
591
    else menuIdExit := -99;
733 daniel-mar 592
 
735 daniel-mar 593
    for i := 0 to ListCount(oid^.SubIds)-1 do
733 daniel-mar 594
    begin
735 daniel-mar 595
      sTmp := ListGetElement(oid^.SubIds, i);
596
      subfile := FileIdPart(sTmp) + '.OID';
740 daniel-mar 597
      if FileExists(subfile) then
598
      begin
599
        CreateOidDef(tmpOID);
600
        _ReadOidFile(subfile, tmpOID);
601
        ListAppend(subsel, 'Go to child  ' + DotNotationPart(sTmp) + _ShowASNIds(tmpOID));
602
        FreeOidDef(tmpOID);
603
      end
604
      else
605
      begin
606
        ListAppend(subsel, 'Go to child  ' + DotNotationPart(sTmp) + ' (FILE NOT FOUND)');
607
      end;
733 daniel-mar 608
      ListAppend(subfiles, subfile);
609
    end;
610
 
735 daniel-mar 611
    if oid^.DotNotation <> '' then
733 daniel-mar 612
    begin
735 daniel-mar 613
      menuIdAsnEdit := ListAppend(subsel, 'Edit ASN.1 identifiers');
614
      ListAppend(subfiles, '');
615
    end
616
    else menuIdAsnEdit := -99;
733 daniel-mar 617
 
735 daniel-mar 618
    menuIdDescEdit := ListAppend(subsel, 'Edit description');
619
    ListAppend(subfiles, '');
733 daniel-mar 620
 
735 daniel-mar 621
    menuIdAdd := ListAppend(subsel, 'Add child');
622
    ListAppend(subfiles, '');
733 daniel-mar 623
 
624
    if not isRoot then
625
    begin
735 daniel-mar 626
      menuIdDelete := ListAppend(subsel, 'Delete OID');
627
      ListAppend(subfiles, '');
628
    end
629
    else menuIdDelete := -99;
733 daniel-mar 630
 
734 daniel-mar 631
    (* Show menu *)
632
 
733 daniel-mar 633
    subselres := DrawSelectionList(menuX, menuY,
634
                                   ScreenWidth-2,
735 daniel-mar 635
                                   ACTIONMENU_SIZE,
733 daniel-mar 636
                                   subsel,
637
                                   true,
638
                                   'SELECT ACTION',
639
                                   1);
734 daniel-mar 640
 
641
    (* Process user selection *)
642
 
733 daniel-mar 643
    if subselres = -1 then
644
    begin
735 daniel-mar 645
      exitRequest := true;
733 daniel-mar 646
    end
735 daniel-mar 647
    else if subselres = menuIdAsnEdit then
733 daniel-mar 648
    begin
735 daniel-mar 649
      if AsnEditor(oid) then
650
        _WriteOidFile(filename, oid);
651
    end
652
    else if subselres = menuIdDescEdit then
653
    begin
654
      if DescEditor(oid) then
655
        _WriteOidFile(filename, oid);
656
    end
657
    else if subselres = menuIdAdd then
658
    begin
659
      if NewOidEditor(oid) then
660
        _WriteOidFile(filename, oid);
661
    end
662
    else if subselres = menuIdDelete then
663
    begin
664
      if _DeleteConfirmation then
733 daniel-mar 665
      begin
740 daniel-mar 666
        sTmp := FileIdPart(oid^.Parent) + '.OID';
735 daniel-mar 667
        DeleteOidRecursive(oid);
740 daniel-mar 668
        if FileExists(sTmp) then
669
        begin
670
          filename := sTmp;
671
        end
672
        else
673
        begin
674
          ShowMessage('Parent file ' + filename + ' not found', 'ERROR', true);
675
          _Pause;
676
          exitRequest := true;
677
        end;
733 daniel-mar 678
      end;
735 daniel-mar 679
    end
680
    else if subselres = menuIdExit then
681
    begin
682
      exitRequest := true;
683
    end
684
    else
685
    begin
686
      (* Normal OID *)
740 daniel-mar 687
      sTmp := ListGetElement(subfiles, subselres);
688
      if FileExists(sTmp) then
689
      begin
690
        filename := sTmp;
691
      end
692
      else
693
      begin
694
        ShowMessage('File ' + filename + ' not found', 'ERROR', true);
695
        (* TODO: With PatchCRT, there will be an infinite loop here *)
696
        _Pause;
697
      end;
733 daniel-mar 698
    end;
699
    FreeList(subsel);
700
    FreeList(subfiles);
701
 
735 daniel-mar 702
    FreeOidDef(oid);
703
  until exitRequest;
733 daniel-mar 704
end;
705
 
706
procedure CreateInitOIDFile(filename: string);
707
var
735 daniel-mar 708
  oid: POID;
733 daniel-mar 709
begin
735 daniel-mar 710
  CreateOidDef(oid);
711
  oid^.Description := 'This is the root of the OID tree.' +#13#10 +
712
                      #13#10 +
713
                      'Valid subsequent arcs are per definition:' + #13#10 +
714
                      '- 0 (itu-t)' + #13#10 +
715
                      '- 1 (iso)' + #13#10 +
716
                      '- 2 (joint-iso-itu-t)';
737 daniel-mar 717
  oid^.FileId      := ZeroPad(0, 8);
735 daniel-mar 718
  oid^.DotNotation := '';
737 daniel-mar 719
  oid^.Parent      := ZeroPad(0, 8);
735 daniel-mar 720
  _WriteOidFile(filename, oid);
721
  FreeOidDef(oid);
733 daniel-mar 722
end;
723
 
740 daniel-mar 724
function _GetInitFile: string;
735 daniel-mar 725
var
726
  initFile: string;
733 daniel-mar 727
begin
735 daniel-mar 728
  initFile := ZeroPad(0, 8) + '.OID';
729
  if not FileExists(initFile) then
733 daniel-mar 730
  begin
735 daniel-mar 731
    CreateInitOIDFile(initFile);
733 daniel-mar 732
  end;
740 daniel-mar 733
  _GetInitFile := initFile;
733 daniel-mar 734
end;
735
 
740 daniel-mar 736
procedure OP_ManageOIDs;
737
begin
738
  ClrScr;
739
  DrawTitleBar('Manage Object Identifiers', TITLEBAR_LEFT_TEXT, '');
740
  DrawStatusBar('Loading data... please wait...');
741
 
742
  DisplayOIDFile(_GetInitFile);
743
end;
744
 
733 daniel-mar 745
procedure OP_ManageRAs;
746
begin
747
  ClrScr;
738 daniel-mar 748
  DrawTitleBar('Manage Registration Authorities', TITLEBAR_LEFT_TEXT, '');
733 daniel-mar 749
  DrawStatusBar('');
750
 
751
  (* TODO: Implement "Manage RAs" feature *)
752
end;
753
 
754
procedure OP_ReturnToMSDOS;
755
begin
756
  ClrScr;
757
end;
758
 
740 daniel-mar 759
function _GetExportLine(oid: POID; indent: integer): string;
760
var
761
  i: integer;
762
  sTmp: string;
763
begin
764
  (* Build line *)
765
  sTmp := RepeatStr(' ', indent*TREEVIEW_INDENT);
766
  if oid^.DotNotation = '' then
767
    sTmp := sTmp + 'Object Identifiers'
768
  else
769
    sTmp := sTmp + oid^.DotNotation;
770
  sTmp := sTmp + _ShowAsnIds(oid);
771
  if TREEVIEW_INCLUDE_DESC then
772
  begin
773
    if Trim(oid^.Description) <> '' then
774
    begin
775
      sTmp := sTmp + ': ' + oid^.Description;
776
    end;
777
  end;
778
  for i := 1 to Length(sTmp) do
779
  begin
780
    if (sTmp[i]=#13) or (sTmp[i]=#10) then sTmp[i] := ' ';
781
  end;
782
  if Length(sTmp) > TREEVIEW_WIDTH then
783
  begin
784
    sTmp := Copy(sTmp, 1, TREEVIEW_WIDTH-3) + '...';
785
  end;
786
  _GetExportLine := sTmp;
787
end;
788
 
789
procedure _RecTreeExport(oid: POID; var F: Text; indent: integer);
790
var
791
  i: integer;
792
  sTmp: string;
793
  suboid: POID;
794
  childFilename: string;
795
begin
796
  sTmp := _GetExportLine(oid, indent);
797
  sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH);
798
  WriteLn(F, sTmp);
799
 
800
  (* Recursively call children *)
801
  for i := 0 to ListCount(oid^.SubIds)-1 do
802
  begin
803
    sTmp := ListGetElement(oid^.SubIds, i);
804
    CreateOidDef(suboid);
805
    childFilename := FileIdPart(sTmp) + '.OID';
806
    if FileExists(childFilename) then
807
    begin
808
      _ReadOidFile(childFilename, suboid);
809
      _RecTreeExport(suboid, F, indent+1);
810
      FreeOidDef(suboid);
811
    end
812
    else
813
    begin
814
      sTmp := 'ERROR: FILE ' + childFilename + ' CONTAINING CHILD OID ' + DotNotationPart(sTmp) + ' WAS NOT FOUND!';
815
      sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH);
816
      WriteLn(F, sTmp);
817
    end;
818
  end;
819
end;
820
 
821
procedure OP_TreeView;
822
var
823
  F: Text;
824
  rootoid: POID;
825
begin
826
  ClrScr;
827
  DrawTitleBar('TreeView Export', TITLEBAR_LEFT_TEXT, '');
828
  DrawStatusBar('Exporting data... please wait...');
829
 
830
  Assign(F, 'OIDTREE.TXT');
831
  Rewrite(F);
832
 
833
  CreateOidDef(rootoid);
834
  _ReadOidFile(_GetInitFile, rootoid);
835
  _RecTreeExport(rootoid, F, 0);
836
  FreeOidDef(rootoid);
837
 
838
  DrawStatusBar(DEFAULT_STATUSBAR);
839
  ShowMessage('TreeView successfully exported as OIDTREE.TXT', 'TREEVIEW EXPORT', true);
840
  _Pause;
841
 
842
  Close(F);
843
end;
844
 
733 daniel-mar 845
procedure OP_MainMenu;
846
var
847
  menu: PStringList;
848
  menuRes, menuLeft, menuTop: integer;
740 daniel-mar 849
  menuIdOID, menuIdRA, menuIdTree, menuIdExit: integer;
733 daniel-mar 850
begin
851
  repeat
852
    ClrScr;
853
 
738 daniel-mar 854
    DrawTitleBar('Welcome to OIDplus for DOS', '', '');
733 daniel-mar 855
    DrawStatusBar(DEFAULT_STATUSBAR);
856
    GoToXY(ScreenWidth-Length(VERSIONINFO), ScreenHeight-1);
857
    Write(VERSIONINFO);
858
 
735 daniel-mar 859
    CreateList(menu);
860
 
861
    menuIdOID  := ListAppend(menu, 'Manage OIDs');
862
    menuIdRA   := -99; (*ListAppend(menu, 'Manage RAs');*)
740 daniel-mar 863
    menuIdTree := ListAppend(menu, 'Export TreeView');
735 daniel-mar 864
    menuIdExit := ListAppend(menu, 'Return to DOS');
865
 
866
    menuLeft := round(ScreenWidth/2 -MAINMENU_WIDTH/2);
867
    menuTop  := round(ScreenHeight/2-MAINMENU_HEIGHT/2);
868
    menuRes  := DrawSelectionList(menuLeft, menuTop,
869
                                  MAINMENU_WIDTH, MAINMENU_HEIGHT,
870
                                  menu, true, 'MAIN MENU', 2);
733 daniel-mar 871
    FreeList(menu);
872
 
735 daniel-mar 873
    if menuRes = menuIdOID then
733 daniel-mar 874
    begin
875
      OP_ManageOIDs;
735 daniel-mar 876
    end
877
    else if menuRes = menuIdRA then
733 daniel-mar 878
    begin
879
      OP_ManageRAs;
740 daniel-mar 880
    end
881
    else if menuRes = menuIdTree then
882
    begin
883
      OP_Treeview;
733 daniel-mar 884
    end;
735 daniel-mar 885
  until (menuRes = menuIdExit) or (MAINMENU_ALLOW_ESC and (menuRes = -1));
733 daniel-mar 886
 
887
  OP_ReturnToMSDOS;
888
end;
889
 
890
begin
891
  OP_MainMenu;
892
end.