Subversion Repositories oidplus

Rev

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