Rev 740 | Rev 742 | 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 | |||
701 | procedure CreateInitOIDFile(filename: string); |
||
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 | |||
740 | daniel-mar | 719 | function _GetInitFile: string; |
735 | daniel-mar | 720 | var |
721 | initFile: string; |
||
733 | daniel-mar | 722 | begin |
735 | daniel-mar | 723 | initFile := ZeroPad(0, 8) + '.OID'; |
724 | if not FileExists(initFile) then |
||
733 | daniel-mar | 725 | begin |
735 | daniel-mar | 726 | CreateInitOIDFile(initFile); |
733 | daniel-mar | 727 | end; |
740 | daniel-mar | 728 | _GetInitFile := initFile; |
733 | daniel-mar | 729 | end; |
730 | |||
740 | daniel-mar | 731 | procedure OP_ManageOIDs; |
732 | begin |
||
733 | ClrScr; |
||
734 | DrawTitleBar('Manage Object Identifiers', TITLEBAR_LEFT_TEXT, ''); |
||
735 | DrawStatusBar('Loading data... please wait...'); |
||
736 | |||
737 | DisplayOIDFile(_GetInitFile); |
||
738 | end; |
||
739 | |||
733 | daniel-mar | 740 | procedure OP_ManageRAs; |
741 | begin |
||
742 | ClrScr; |
||
738 | daniel-mar | 743 | DrawTitleBar('Manage Registration Authorities', TITLEBAR_LEFT_TEXT, ''); |
733 | daniel-mar | 744 | DrawStatusBar(''); |
745 | |||
746 | (* TODO: Implement "Manage RAs" feature *) |
||
747 | end; |
||
748 | |||
749 | procedure OP_ReturnToMSDOS; |
||
750 | begin |
||
751 | ClrScr; |
||
741 | daniel-mar | 752 | WriteLn('Thank you for using OIDplus for DOS.'); |
753 | WRiteLn(''); |
||
733 | daniel-mar | 754 | end; |
755 | |||
741 | daniel-mar | 756 | function _GetTreeViewLine(oid: POID; indent: integer): string; |
740 | daniel-mar | 757 | var |
758 | i: integer; |
||
759 | sTmp: string; |
||
760 | begin |
||
761 | (* Build line *) |
||
762 | sTmp := RepeatStr(' ', indent*TREEVIEW_INDENT); |
||
763 | if oid^.DotNotation = '' then |
||
764 | sTmp := sTmp + 'Object Identifiers' |
||
765 | else |
||
766 | sTmp := sTmp + oid^.DotNotation; |
||
767 | sTmp := sTmp + _ShowAsnIds(oid); |
||
768 | if TREEVIEW_INCLUDE_DESC then |
||
769 | begin |
||
770 | if Trim(oid^.Description) <> '' then |
||
771 | begin |
||
772 | sTmp := sTmp + ': ' + oid^.Description; |
||
773 | end; |
||
774 | end; |
||
775 | for i := 1 to Length(sTmp) do |
||
776 | begin |
||
777 | if (sTmp[i]=#13) or (sTmp[i]=#10) then sTmp[i] := ' '; |
||
778 | end; |
||
779 | if Length(sTmp) > TREEVIEW_WIDTH then |
||
780 | begin |
||
781 | sTmp := Copy(sTmp, 1, TREEVIEW_WIDTH-3) + '...'; |
||
782 | end; |
||
741 | daniel-mar | 783 | _GetTreeViewLine := sTmp; |
740 | daniel-mar | 784 | end; |
785 | |||
786 | procedure _RecTreeExport(oid: POID; var F: Text; indent: integer); |
||
787 | var |
||
788 | i: integer; |
||
789 | sTmp: string; |
||
790 | suboid: POID; |
||
791 | childFilename: string; |
||
792 | begin |
||
741 | daniel-mar | 793 | sTmp := _GetTreeViewLine(oid, indent); |
740 | daniel-mar | 794 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
795 | WriteLn(F, sTmp); |
||
796 | |||
797 | (* Recursively call children *) |
||
798 | for i := 0 to ListCount(oid^.SubIds)-1 do |
||
799 | begin |
||
800 | sTmp := ListGetElement(oid^.SubIds, i); |
||
801 | CreateOidDef(suboid); |
||
802 | childFilename := FileIdPart(sTmp) + '.OID'; |
||
803 | if FileExists(childFilename) then |
||
804 | begin |
||
805 | _ReadOidFile(childFilename, suboid); |
||
806 | _RecTreeExport(suboid, F, indent+1); |
||
807 | FreeOidDef(suboid); |
||
808 | end |
||
809 | else |
||
810 | begin |
||
811 | sTmp := 'ERROR: FILE ' + childFilename + ' CONTAINING CHILD OID ' + DotNotationPart(sTmp) + ' WAS NOT FOUND!'; |
||
812 | sTmp := TrimLineToWidth(sTmp, TREEVIEW_WIDTH); |
||
813 | WriteLn(F, sTmp); |
||
814 | end; |
||
815 | end; |
||
816 | end; |
||
817 | |||
818 | procedure OP_TreeView; |
||
819 | var |
||
820 | F: Text; |
||
821 | rootoid: POID; |
||
822 | begin |
||
823 | ClrScr; |
||
824 | DrawTitleBar('TreeView Export', TITLEBAR_LEFT_TEXT, ''); |
||
825 | DrawStatusBar('Exporting data... please wait...'); |
||
826 | |||
827 | Assign(F, 'OIDTREE.TXT'); |
||
828 | Rewrite(F); |
||
829 | |||
830 | CreateOidDef(rootoid); |
||
831 | _ReadOidFile(_GetInitFile, rootoid); |
||
832 | _RecTreeExport(rootoid, F, 0); |
||
833 | FreeOidDef(rootoid); |
||
834 | |||
835 | DrawStatusBar(DEFAULT_STATUSBAR); |
||
836 | ShowMessage('TreeView successfully exported as OIDTREE.TXT', 'TREEVIEW EXPORT', true); |
||
837 | _Pause; |
||
838 | |||
839 | Close(F); |
||
840 | end; |
||
841 | |||
733 | daniel-mar | 842 | procedure OP_MainMenu; |
843 | var |
||
844 | menu: PStringList; |
||
845 | menuRes, menuLeft, menuTop: integer; |
||
740 | daniel-mar | 846 | menuIdOID, menuIdRA, menuIdTree, menuIdExit: integer; |
733 | daniel-mar | 847 | begin |
848 | repeat |
||
849 | ClrScr; |
||
850 | |||
738 | daniel-mar | 851 | DrawTitleBar('Welcome to OIDplus for DOS', '', ''); |
733 | daniel-mar | 852 | DrawStatusBar(DEFAULT_STATUSBAR); |
853 | GoToXY(ScreenWidth-Length(VERSIONINFO), ScreenHeight-1); |
||
854 | Write(VERSIONINFO); |
||
855 | |||
735 | daniel-mar | 856 | CreateList(menu); |
857 | |||
858 | menuIdOID := ListAppend(menu, 'Manage OIDs'); |
||
859 | menuIdRA := -99; (*ListAppend(menu, 'Manage RAs');*) |
||
740 | daniel-mar | 860 | menuIdTree := ListAppend(menu, 'Export TreeView'); |
735 | daniel-mar | 861 | menuIdExit := ListAppend(menu, 'Return to DOS'); |
862 | |||
863 | menuLeft := round(ScreenWidth/2 -MAINMENU_WIDTH/2); |
||
864 | menuTop := round(ScreenHeight/2-MAINMENU_HEIGHT/2); |
||
865 | menuRes := DrawSelectionList(menuLeft, menuTop, |
||
866 | MAINMENU_WIDTH, MAINMENU_HEIGHT, |
||
867 | menu, true, 'MAIN MENU', 2); |
||
733 | daniel-mar | 868 | FreeList(menu); |
869 | |||
735 | daniel-mar | 870 | if menuRes = menuIdOID then |
733 | daniel-mar | 871 | begin |
872 | OP_ManageOIDs; |
||
735 | daniel-mar | 873 | end |
874 | else if menuRes = menuIdRA then |
||
733 | daniel-mar | 875 | begin |
876 | OP_ManageRAs; |
||
740 | daniel-mar | 877 | end |
878 | else if menuRes = menuIdTree then |
||
879 | begin |
||
880 | OP_Treeview; |
||
733 | daniel-mar | 881 | end; |
735 | daniel-mar | 882 | until (menuRes = menuIdExit) or (MAINMENU_ALLOW_ESC and (menuRes = -1)); |
733 | daniel-mar | 883 | |
884 | OP_ReturnToMSDOS; |
||
885 | end; |
||
886 | |||
887 | begin |
||
888 | OP_MainMenu; |
||
889 | end. |