| 1 | {==============================================================================|
|
|---|
| 2 | | Project : Ararat Synapse | 001.004.004 |
|
|---|
| 3 | |==============================================================================|
|
|---|
| 4 | | Content: support for ASN.1 BER coding and decoding |
|
|---|
| 5 | |==============================================================================|
|
|---|
| 6 | | Copyright (c)1999-2003, Lukas Gebauer |
|
|---|
| 7 | | All rights reserved. |
|
|---|
| 8 | | |
|
|---|
| 9 | | Redistribution and use in source and binary forms, with or without |
|
|---|
| 10 | | modification, are permitted provided that the following conditions are met: |
|
|---|
| 11 | | |
|
|---|
| 12 | | Redistributions of source code must retain the above copyright notice, this |
|
|---|
| 13 | | list of conditions and the following disclaimer. |
|
|---|
| 14 | | |
|
|---|
| 15 | | Redistributions in binary form must reproduce the above copyright notice, |
|
|---|
| 16 | | this list of conditions and the following disclaimer in the documentation |
|
|---|
| 17 | | and/or other materials provided with the distribution. |
|
|---|
| 18 | | |
|
|---|
| 19 | | Neither the name of Lukas Gebauer nor the names of its contributors may |
|
|---|
| 20 | | be used to endorse or promote products derived from this software without |
|
|---|
| 21 | | specific prior written permission. |
|
|---|
| 22 | | |
|
|---|
| 23 | | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
|
|---|
| 24 | | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
|---|
| 25 | | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
|---|
| 26 | | ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR |
|
|---|
| 27 | | ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
|---|
| 28 | | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
|
|---|
| 29 | | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
|
|---|
| 30 | | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
|---|
| 31 | | LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
|---|
| 32 | | OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH |
|
|---|
| 33 | | DAMAGE. |
|
|---|
| 34 | |==============================================================================|
|
|---|
| 35 | | The Initial Developer of the Original Code is Lukas Gebauer (Czech Republic).|
|
|---|
| 36 | | Portions created by Lukas Gebauer are Copyright (c) 1999-2003 |
|
|---|
| 37 | | Portions created by Hernan Sanchez are Copyright (c) 2000. |
|
|---|
| 38 | | All Rights Reserved. |
|
|---|
| 39 | |==============================================================================|
|
|---|
| 40 | | Contributor(s): |
|
|---|
| 41 | | Hernan Sanchez (hernan.sanchez@iname.com) |
|
|---|
| 42 | |==============================================================================|
|
|---|
| 43 | | History: see HISTORY.HTM from distribution package |
|
|---|
| 44 | | (Found at URL: http://www.ararat.cz/synapse/) |
|
|---|
| 45 | |==============================================================================}
|
|---|
| 46 |
|
|---|
| 47 | {: @abstract(Utilities for handling ASN.1 BER encoding)
|
|---|
| 48 | By this unit you can parse ASN.1 BER encoded data to elements or build back any
|
|---|
| 49 | elements to ASN.1 BER encoded buffer. You can dump ASN.1 BER encoded data to
|
|---|
| 50 | human readable form for easy debugging, too.
|
|---|
| 51 |
|
|---|
| 52 | Supported element types are: ASN1_BOOL, ASN1_INT, ASN1_OCTSTR, ASN1_NULL,
|
|---|
| 53 | ASN1_OBJID, ASN1_ENUM, ASN1_SEQ, ASN1_SETOF, ASN1_IPADDR, ASN1_COUNTER,
|
|---|
| 54 | ASN1_GAUGE, ASN1_TIMETICKS, ASN1_OPAQUE
|
|---|
| 55 |
|
|---|
| 56 | For sample of using, look to @link(TSnmpSend) or @link(TLdapSend)class.
|
|---|
| 57 | }
|
|---|
| 58 |
|
|---|
| 59 | {$Q-}
|
|---|
| 60 | {$H+}
|
|---|
| 61 | {$IFDEF FPC}
|
|---|
| 62 | {$MODE DELPHI}
|
|---|
| 63 | {$ENDIF}
|
|---|
| 64 |
|
|---|
| 65 | {$IFDEF UNICODE}
|
|---|
| 66 | {$WARN IMPLICIT_STRING_CAST OFF}
|
|---|
| 67 | {$WARN IMPLICIT_STRING_CAST_LOSS OFF}
|
|---|
| 68 | {$ENDIF}
|
|---|
| 69 |
|
|---|
| 70 | unit asn1util;
|
|---|
| 71 |
|
|---|
| 72 | interface
|
|---|
| 73 |
|
|---|
| 74 | uses
|
|---|
| 75 | SysUtils, Classes, synautil;
|
|---|
| 76 |
|
|---|
| 77 | const
|
|---|
| 78 | ASN1_BOOL = $01;
|
|---|
| 79 | ASN1_INT = $02;
|
|---|
| 80 | ASN1_OCTSTR = $04;
|
|---|
| 81 | ASN1_NULL = $05;
|
|---|
| 82 | ASN1_OBJID = $06;
|
|---|
| 83 | ASN1_ENUM = $0a;
|
|---|
| 84 | ASN1_SEQ = $30;
|
|---|
| 85 | ASN1_SETOF = $31;
|
|---|
| 86 | ASN1_IPADDR = $40;
|
|---|
| 87 | ASN1_COUNTER = $41;
|
|---|
| 88 | ASN1_GAUGE = $42;
|
|---|
| 89 | ASN1_TIMETICKS = $43;
|
|---|
| 90 | ASN1_OPAQUE = $44;
|
|---|
| 91 |
|
|---|
| 92 | {:Encodes OID item to binary form.}
|
|---|
| 93 | function ASNEncOIDItem(Value: Integer): AnsiString;
|
|---|
| 94 |
|
|---|
| 95 | {:Decodes an OID item of the next element in the "Buffer" from the "Start"
|
|---|
| 96 | position.}
|
|---|
| 97 | function ASNDecOIDItem(var Start: Integer; const Buffer: AnsiString): Integer;
|
|---|
| 98 |
|
|---|
| 99 | {:Encodes the length of ASN.1 element to binary.}
|
|---|
| 100 | function ASNEncLen(Len: Integer): AnsiString;
|
|---|
| 101 |
|
|---|
| 102 | {:Decodes length of next element in "Buffer" from the "Start" position.}
|
|---|
| 103 | function ASNDecLen(var Start: Integer; const Buffer: AnsiString): Integer;
|
|---|
| 104 |
|
|---|
| 105 | {:Encodes a signed integer to ASN.1 binary}
|
|---|
| 106 | function ASNEncInt(Value: Integer): AnsiString;
|
|---|
| 107 |
|
|---|
| 108 | {:Encodes unsigned integer into ASN.1 binary}
|
|---|
| 109 | function ASNEncUInt(Value: Integer): AnsiString;
|
|---|
| 110 |
|
|---|
| 111 | {:Encodes ASN.1 object to binary form.}
|
|---|
| 112 | function ASNObject(const Data: AnsiString; ASNType: Integer): AnsiString;
|
|---|
| 113 |
|
|---|
| 114 | {:Beginning with the "Start" position, decode the ASN.1 item of the next element
|
|---|
| 115 | in "Buffer". Type of item is stored in "ValueType."}
|
|---|
| 116 | function ASNItem(var Start: Integer; const Buffer: AnsiString;
|
|---|
| 117 | var ValueType: Integer): AnsiString;
|
|---|
| 118 |
|
|---|
| 119 | {:Encodes an MIB OID string to binary form.}
|
|---|
| 120 | function MibToId(Mib: String): AnsiString;
|
|---|
| 121 |
|
|---|
| 122 | {:Decodes MIB OID from binary form to string form.}
|
|---|
| 123 | function IdToMib(const Id: AnsiString): String;
|
|---|
| 124 |
|
|---|
| 125 | {:Encodes an one number from MIB OID to binary form. (used internally from
|
|---|
| 126 | @link(MibToId))}
|
|---|
| 127 | function IntMibToStr(const Value: AnsiString): AnsiString;
|
|---|
| 128 |
|
|---|
| 129 | {:Convert ASN.1 BER encoded buffer to human readable form for debugging.}
|
|---|
| 130 | function ASNdump(const Value: AnsiString): AnsiString;
|
|---|
| 131 |
|
|---|
| 132 | implementation
|
|---|
| 133 |
|
|---|
| 134 | {==============================================================================}
|
|---|
| 135 | function ASNEncOIDItem(Value: Integer): AnsiString;
|
|---|
| 136 | var
|
|---|
| 137 | x, xm: Integer;
|
|---|
| 138 | b: Boolean;
|
|---|
| 139 | begin
|
|---|
| 140 | x := Value;
|
|---|
| 141 | b := False;
|
|---|
| 142 | Result := '';
|
|---|
| 143 | repeat
|
|---|
| 144 | xm := x mod 128;
|
|---|
| 145 | x := x div 128;
|
|---|
| 146 | if b then
|
|---|
| 147 | xm := xm or $80;
|
|---|
| 148 | if x > 0 then
|
|---|
| 149 | b := True;
|
|---|
| 150 | Result := AnsiChar(xm) + Result;
|
|---|
| 151 | until x = 0;
|
|---|
| 152 | end;
|
|---|
| 153 |
|
|---|
| 154 | {==============================================================================}
|
|---|
| 155 | function ASNDecOIDItem(var Start: Integer; const Buffer: AnsiString): Integer;
|
|---|
| 156 | var
|
|---|
| 157 | x: Integer;
|
|---|
| 158 | b: Boolean;
|
|---|
| 159 | begin
|
|---|
| 160 | Result := 0;
|
|---|
| 161 | repeat
|
|---|
| 162 | Result := Result * 128;
|
|---|
| 163 | x := Ord(Buffer[Start]);
|
|---|
| 164 | Inc(Start);
|
|---|
| 165 | b := x > $7F;
|
|---|
| 166 | x := x and $7F;
|
|---|
| 167 | Result := Result + x;
|
|---|
| 168 | until not b;
|
|---|
| 169 | end;
|
|---|
| 170 |
|
|---|
| 171 | {==============================================================================}
|
|---|
| 172 | function ASNEncLen(Len: Integer): AnsiString;
|
|---|
| 173 | var
|
|---|
| 174 | x, y: Integer;
|
|---|
| 175 | begin
|
|---|
| 176 | if Len < $80 then
|
|---|
| 177 | Result := AnsiChar(Len)
|
|---|
| 178 | else
|
|---|
| 179 | begin
|
|---|
| 180 | x := Len;
|
|---|
| 181 | Result := '';
|
|---|
| 182 | repeat
|
|---|
| 183 | y := x mod 256;
|
|---|
| 184 | x := x div 256;
|
|---|
| 185 | Result := AnsiChar(y) + Result;
|
|---|
| 186 | until x = 0;
|
|---|
| 187 | y := Length(Result);
|
|---|
| 188 | y := y or $80;
|
|---|
| 189 | Result := AnsiChar(y) + Result;
|
|---|
| 190 | end;
|
|---|
| 191 | end;
|
|---|
| 192 |
|
|---|
| 193 | {==============================================================================}
|
|---|
| 194 | function ASNDecLen(var Start: Integer; const Buffer: AnsiString): Integer;
|
|---|
| 195 | var
|
|---|
| 196 | x, n: Integer;
|
|---|
| 197 | begin
|
|---|
| 198 | x := Ord(Buffer[Start]);
|
|---|
| 199 | Inc(Start);
|
|---|
| 200 | if x < $80 then
|
|---|
| 201 | Result := x
|
|---|
| 202 | else
|
|---|
| 203 | begin
|
|---|
| 204 | Result := 0;
|
|---|
| 205 | x := x and $7F;
|
|---|
| 206 | for n := 1 to x do
|
|---|
| 207 | begin
|
|---|
| 208 | Result := Result * 256;
|
|---|
| 209 | x := Ord(Buffer[Start]);
|
|---|
| 210 | Inc(Start);
|
|---|
| 211 | Result := Result + x;
|
|---|
| 212 | end;
|
|---|
| 213 | end;
|
|---|
| 214 | end;
|
|---|
| 215 |
|
|---|
| 216 | {==============================================================================}
|
|---|
| 217 | function ASNEncInt(Value: Integer): AnsiString;
|
|---|
| 218 | var
|
|---|
| 219 | x, y: Cardinal;
|
|---|
| 220 | neg: Boolean;
|
|---|
| 221 | begin
|
|---|
| 222 | neg := Value < 0;
|
|---|
| 223 | x := Abs(Value);
|
|---|
| 224 | if neg then
|
|---|
| 225 | x := not (x - 1);
|
|---|
| 226 | Result := '';
|
|---|
| 227 | repeat
|
|---|
| 228 | y := x mod 256;
|
|---|
| 229 | x := x div 256;
|
|---|
| 230 | Result := AnsiChar(y) + Result;
|
|---|
| 231 | until x = 0;
|
|---|
| 232 | if (not neg) and (Result[1] > #$7F) then
|
|---|
| 233 | Result := #0 + Result;
|
|---|
| 234 | end;
|
|---|
| 235 |
|
|---|
| 236 | {==============================================================================}
|
|---|
| 237 | function ASNEncUInt(Value: Integer): AnsiString;
|
|---|
| 238 | var
|
|---|
| 239 | x, y: Integer;
|
|---|
| 240 | neg: Boolean;
|
|---|
| 241 | begin
|
|---|
| 242 | neg := Value < 0;
|
|---|
| 243 | x := Value;
|
|---|
| 244 | if neg then
|
|---|
| 245 | x := x and $7FFFFFFF;
|
|---|
| 246 | Result := '';
|
|---|
| 247 | repeat
|
|---|
| 248 | y := x mod 256;
|
|---|
| 249 | x := x div 256;
|
|---|
| 250 | Result := AnsiChar(y) + Result;
|
|---|
| 251 | until x = 0;
|
|---|
| 252 | if neg then
|
|---|
| 253 | Result[1] := AnsiChar(Ord(Result[1]) or $80);
|
|---|
| 254 | end;
|
|---|
| 255 |
|
|---|
| 256 | {==============================================================================}
|
|---|
| 257 | function ASNObject(const Data: AnsiString; ASNType: Integer): AnsiString;
|
|---|
| 258 | begin
|
|---|
| 259 | Result := AnsiChar(ASNType) + ASNEncLen(Length(Data)) + Data;
|
|---|
| 260 | end;
|
|---|
| 261 |
|
|---|
| 262 | {==============================================================================}
|
|---|
| 263 | function ASNItem(var Start: Integer; const Buffer: AnsiString;
|
|---|
| 264 | var ValueType: Integer): AnsiString;
|
|---|
| 265 | var
|
|---|
| 266 | ASNType: Integer;
|
|---|
| 267 | ASNSize: Integer;
|
|---|
| 268 | y, n: Integer;
|
|---|
| 269 | x: byte;
|
|---|
| 270 | s: AnsiString;
|
|---|
| 271 | c: AnsiChar;
|
|---|
| 272 | neg: Boolean;
|
|---|
| 273 | l: Integer;
|
|---|
| 274 | begin
|
|---|
| 275 | Result := '';
|
|---|
| 276 | ValueType := ASN1_NULL;
|
|---|
| 277 | l := Length(Buffer);
|
|---|
| 278 | if l < (Start + 1) then
|
|---|
| 279 | Exit;
|
|---|
| 280 | ASNType := Ord(Buffer[Start]);
|
|---|
| 281 | ValueType := ASNType;
|
|---|
| 282 | Inc(Start);
|
|---|
| 283 | ASNSize := ASNDecLen(Start, Buffer);
|
|---|
| 284 | if (Start + ASNSize - 1) > l then
|
|---|
| 285 | Exit;
|
|---|
| 286 | if (ASNType and $20) > 0 then
|
|---|
| 287 | // Result := '$' + IntToHex(ASNType, 2)
|
|---|
| 288 | Result := Copy(Buffer, Start, ASNSize)
|
|---|
| 289 | else
|
|---|
| 290 | case ASNType of
|
|---|
| 291 | ASN1_INT, ASN1_ENUM, ASN1_BOOL:
|
|---|
| 292 | begin
|
|---|
| 293 | y := 0;
|
|---|
| 294 | neg := False;
|
|---|
| 295 | for n := 1 to ASNSize do
|
|---|
| 296 | begin
|
|---|
| 297 | x := Ord(Buffer[Start]);
|
|---|
| 298 | if (n = 1) and (x > $7F) then
|
|---|
| 299 | neg := True;
|
|---|
| 300 | if neg then
|
|---|
| 301 | x := not x;
|
|---|
| 302 | y := y * 256 + x;
|
|---|
| 303 | Inc(Start);
|
|---|
| 304 | end;
|
|---|
| 305 | if neg then
|
|---|
| 306 | y := -(y + 1);
|
|---|
| 307 | Result := IntToStr(y);
|
|---|
| 308 | end;
|
|---|
| 309 | ASN1_COUNTER, ASN1_GAUGE, ASN1_TIMETICKS:
|
|---|
| 310 | begin
|
|---|
| 311 | y := 0;
|
|---|
| 312 | for n := 1 to ASNSize do
|
|---|
| 313 | begin
|
|---|
| 314 | y := y * 256 + Ord(Buffer[Start]);
|
|---|
| 315 | Inc(Start);
|
|---|
| 316 | end;
|
|---|
| 317 | Result := IntToStr(y);
|
|---|
| 318 | end;
|
|---|
| 319 | ASN1_OCTSTR, ASN1_OPAQUE:
|
|---|
| 320 | begin
|
|---|
| 321 | for n := 1 to ASNSize do
|
|---|
| 322 | begin
|
|---|
| 323 | c := AnsiChar(Buffer[Start]);
|
|---|
| 324 | Inc(Start);
|
|---|
| 325 | s := s + c;
|
|---|
| 326 | end;
|
|---|
| 327 | Result := s;
|
|---|
| 328 | end;
|
|---|
| 329 | ASN1_OBJID:
|
|---|
| 330 | begin
|
|---|
| 331 | for n := 1 to ASNSize do
|
|---|
| 332 | begin
|
|---|
| 333 | c := AnsiChar(Buffer[Start]);
|
|---|
| 334 | Inc(Start);
|
|---|
| 335 | s := s + c;
|
|---|
| 336 | end;
|
|---|
| 337 | Result := IdToMib(s);
|
|---|
| 338 | end;
|
|---|
| 339 | ASN1_IPADDR:
|
|---|
| 340 | begin
|
|---|
| 341 | s := '';
|
|---|
| 342 | for n := 1 to ASNSize do
|
|---|
| 343 | begin
|
|---|
| 344 | if (n <> 1) then
|
|---|
| 345 | s := s + '.';
|
|---|
| 346 | y := Ord(Buffer[Start]);
|
|---|
| 347 | Inc(Start);
|
|---|
| 348 | s := s + IntToStr(y);
|
|---|
| 349 | end;
|
|---|
| 350 | Result := s;
|
|---|
| 351 | end;
|
|---|
| 352 | ASN1_NULL:
|
|---|
| 353 | begin
|
|---|
| 354 | Result := '';
|
|---|
| 355 | Start := Start + ASNSize;
|
|---|
| 356 | end;
|
|---|
| 357 | else // unknown
|
|---|
| 358 | begin
|
|---|
| 359 | for n := 1 to ASNSize do
|
|---|
| 360 | begin
|
|---|
| 361 | c := AnsiChar(Buffer[Start]);
|
|---|
| 362 | Inc(Start);
|
|---|
| 363 | s := s + c;
|
|---|
| 364 | end;
|
|---|
| 365 | Result := s;
|
|---|
| 366 | end;
|
|---|
| 367 | end;
|
|---|
| 368 | end;
|
|---|
| 369 |
|
|---|
| 370 | {==============================================================================}
|
|---|
| 371 | function MibToId(Mib: String): AnsiString;
|
|---|
| 372 | var
|
|---|
| 373 | x: Integer;
|
|---|
| 374 |
|
|---|
| 375 | function WalkInt(var s: String): Integer;
|
|---|
| 376 | var
|
|---|
| 377 | x: Integer;
|
|---|
| 378 | t: AnsiString;
|
|---|
| 379 | begin
|
|---|
| 380 | x := Pos('.', s);
|
|---|
| 381 | if x < 1 then
|
|---|
| 382 | begin
|
|---|
| 383 | t := s;
|
|---|
| 384 | s := '';
|
|---|
| 385 | end
|
|---|
| 386 | else
|
|---|
| 387 | begin
|
|---|
| 388 | t := Copy(s, 1, x - 1);
|
|---|
| 389 | s := Copy(s, x + 1, Length(s) - x);
|
|---|
| 390 | end;
|
|---|
| 391 | Result := StrToIntDef(t, 0);
|
|---|
| 392 | end;
|
|---|
| 393 |
|
|---|
| 394 | begin
|
|---|
| 395 | Result := '';
|
|---|
| 396 | x := WalkInt(Mib);
|
|---|
| 397 | x := x * 40 + WalkInt(Mib);
|
|---|
| 398 | Result := ASNEncOIDItem(x);
|
|---|
| 399 | while Mib <> '' do
|
|---|
| 400 | begin
|
|---|
| 401 | x := WalkInt(Mib);
|
|---|
| 402 | Result := Result + ASNEncOIDItem(x);
|
|---|
| 403 | end;
|
|---|
| 404 | end;
|
|---|
| 405 |
|
|---|
| 406 | {==============================================================================}
|
|---|
| 407 | function IdToMib(const Id: AnsiString): String;
|
|---|
| 408 | var
|
|---|
| 409 | x, y, n: Integer;
|
|---|
| 410 | begin
|
|---|
| 411 | Result := '';
|
|---|
| 412 | n := 1;
|
|---|
| 413 | while Length(Id) + 1 > n do
|
|---|
| 414 | begin
|
|---|
| 415 | x := ASNDecOIDItem(n, Id);
|
|---|
| 416 | if (n - 1) = 1 then
|
|---|
| 417 | begin
|
|---|
| 418 | y := x div 40;
|
|---|
| 419 | x := x mod 40;
|
|---|
| 420 | Result := IntToStr(y);
|
|---|
| 421 | end;
|
|---|
| 422 | Result := Result + '.' + IntToStr(x);
|
|---|
| 423 | end;
|
|---|
| 424 | end;
|
|---|
| 425 |
|
|---|
| 426 | {==============================================================================}
|
|---|
| 427 | function IntMibToStr(const Value: AnsiString): AnsiString;
|
|---|
| 428 | var
|
|---|
| 429 | n, y: Integer;
|
|---|
| 430 | begin
|
|---|
| 431 | y := 0;
|
|---|
| 432 | for n := 1 to Length(Value) - 1 do
|
|---|
| 433 | y := y * 256 + Ord(Value[n]);
|
|---|
| 434 | Result := IntToStr(y);
|
|---|
| 435 | end;
|
|---|
| 436 |
|
|---|
| 437 | {==============================================================================}
|
|---|
| 438 | function ASNdump(const Value: AnsiString): AnsiString;
|
|---|
| 439 | var
|
|---|
| 440 | i, at, x, n: integer;
|
|---|
| 441 | s, indent: AnsiString;
|
|---|
| 442 | il: TStringList;
|
|---|
| 443 | begin
|
|---|
| 444 | il := TStringList.Create;
|
|---|
| 445 | try
|
|---|
| 446 | Result := '';
|
|---|
| 447 | i := 1;
|
|---|
| 448 | indent := '';
|
|---|
| 449 | while i < Length(Value) do
|
|---|
| 450 | begin
|
|---|
| 451 | for n := il.Count - 1 downto 0 do
|
|---|
| 452 | begin
|
|---|
| 453 | x := StrToIntDef(il[n], 0);
|
|---|
| 454 | if x <= i then
|
|---|
| 455 | begin
|
|---|
| 456 | il.Delete(n);
|
|---|
| 457 | Delete(indent, 1, 2);
|
|---|
| 458 | end;
|
|---|
| 459 | end;
|
|---|
| 460 | s := ASNItem(i, Value, at);
|
|---|
| 461 | Result := Result + indent + '$' + IntToHex(at, 2);
|
|---|
| 462 | if (at and $20) > 0 then
|
|---|
| 463 | begin
|
|---|
| 464 | x := Length(s);
|
|---|
| 465 | Result := Result + ' constructed: length ' + IntToStr(x);
|
|---|
| 466 | indent := indent + ' ';
|
|---|
| 467 | il.Add(IntToStr(x + i - 1));
|
|---|
| 468 | end
|
|---|
| 469 | else
|
|---|
| 470 | begin
|
|---|
| 471 | case at of
|
|---|
| 472 | ASN1_BOOL:
|
|---|
| 473 | Result := Result + ' BOOL: ';
|
|---|
| 474 | ASN1_INT:
|
|---|
| 475 | Result := Result + ' INT: ';
|
|---|
| 476 | ASN1_ENUM:
|
|---|
| 477 | Result := Result + ' ENUM: ';
|
|---|
| 478 | ASN1_COUNTER:
|
|---|
| 479 | Result := Result + ' COUNTER: ';
|
|---|
| 480 | ASN1_GAUGE:
|
|---|
| 481 | Result := Result + ' GAUGE: ';
|
|---|
| 482 | ASN1_TIMETICKS:
|
|---|
| 483 | Result := Result + ' TIMETICKS: ';
|
|---|
| 484 | ASN1_OCTSTR:
|
|---|
| 485 | Result := Result + ' OCTSTR: ';
|
|---|
| 486 | ASN1_OPAQUE:
|
|---|
| 487 | Result := Result + ' OPAQUE: ';
|
|---|
| 488 | ASN1_OBJID:
|
|---|
| 489 | Result := Result + ' OBJID: ';
|
|---|
| 490 | ASN1_IPADDR:
|
|---|
| 491 | Result := Result + ' IPADDR: ';
|
|---|
| 492 | ASN1_NULL:
|
|---|
| 493 | Result := Result + ' NULL: ';
|
|---|
| 494 | else // other
|
|---|
| 495 | Result := Result + ' unknown: ';
|
|---|
| 496 | end;
|
|---|
| 497 | if IsBinaryString(s) then
|
|---|
| 498 | s := DumpExStr(s);
|
|---|
| 499 | Result := Result + s;
|
|---|
| 500 | end;
|
|---|
| 501 | Result := Result + #$0d + #$0a;
|
|---|
| 502 | end;
|
|---|
| 503 | finally
|
|---|
| 504 | il.Free;
|
|---|
| 505 | end;
|
|---|
| 506 | end;
|
|---|
| 507 |
|
|---|
| 508 | {==============================================================================}
|
|---|
| 509 |
|
|---|
| 510 | end.
|
|---|