OLD | NEW |
1 // Copyright 2009 The Go Authors. All rights reserved. | 1 // Copyright 2009 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package asn1 | 5 package asn1 |
6 | 6 |
7 import ( | 7 import ( |
8 "bytes" | 8 "bytes" |
| 9 "errors" |
9 "fmt" | 10 "fmt" |
10 "io" | 11 "io" |
11 "math/big" | 12 "math/big" |
12 "reflect" | 13 "reflect" |
13 "time" | 14 "time" |
| 15 "unicode/utf8" |
14 ) | 16 ) |
15 | 17 |
16 // A forkableWriter is an in-memory buffer that can be | 18 // A forkableWriter is an in-memory buffer that can be |
17 // 'forked' to create new forkableWriters that bracket the | 19 // 'forked' to create new forkableWriters that bracket the |
18 // original. After | 20 // original. After |
19 // pre, post := w.fork(); | 21 // pre, post := w.fork(); |
20 // the overall sequence of bytes represented is logically w+pre+post. | 22 // the overall sequence of bytes represented is logically w+pre+post. |
21 type forkableWriter struct { | 23 type forkableWriter struct { |
22 *bytes.Buffer | 24 *bytes.Buffer |
23 pre, post *forkableWriter | 25 pre, post *forkableWriter |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
273 for _, c := range b { | 275 for _, c := range b { |
274 if c > 127 { | 276 if c > 127 { |
275 return StructuralError{"IA5String contains invalid chara
cter"} | 277 return StructuralError{"IA5String contains invalid chara
cter"} |
276 } | 278 } |
277 } | 279 } |
278 | 280 |
279 _, err = out.Write(b) | 281 _, err = out.Write(b) |
280 return | 282 return |
281 } | 283 } |
282 | 284 |
| 285 func marshalUTF8String(out *forkableWriter, s string) (err error) { |
| 286 _, err = out.Write([]byte(s)) |
| 287 return |
| 288 } |
| 289 |
283 func marshalTwoDigits(out *forkableWriter, v int) (err error) { | 290 func marshalTwoDigits(out *forkableWriter, v int) (err error) { |
284 err = out.WriteByte(byte('0' + (v/10)%10)) | 291 err = out.WriteByte(byte('0' + (v/10)%10)) |
285 if err != nil { | 292 if err != nil { |
286 return | 293 return |
287 } | 294 } |
288 return out.WriteByte(byte('0' + v%10)) | 295 return out.WriteByte(byte('0' + v%10)) |
289 } | 296 } |
290 | 297 |
291 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { | 298 func marshalUTCTime(out *forkableWriter, t time.Time) (err error) { |
292 utc := t.UTC() | 299 utc := t.UTC() |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
439 for i := 0; i < v.Len(); i++ { | 446 for i := 0; i < v.Len(); i++ { |
440 var pre *forkableWriter | 447 var pre *forkableWriter |
441 pre, out = out.fork() | 448 pre, out = out.fork() |
442 err = marshalField(pre, v.Index(i), params) | 449 err = marshalField(pre, v.Index(i), params) |
443 if err != nil { | 450 if err != nil { |
444 return | 451 return |
445 } | 452 } |
446 } | 453 } |
447 return | 454 return |
448 case reflect.String: | 455 case reflect.String: |
449 » » if params.stringType == tagIA5String { | 456 » » switch params.stringType { |
| 457 » » case tagIA5String: |
450 return marshalIA5String(out, v.String()) | 458 return marshalIA5String(out, v.String()) |
451 » » } else { | 459 » » case tagPrintableString: |
452 return marshalPrintableString(out, v.String()) | 460 return marshalPrintableString(out, v.String()) |
| 461 default: |
| 462 return marshalUTF8String(out, v.String()) |
453 } | 463 } |
454 return | 464 return |
455 } | 465 } |
456 | 466 |
457 return StructuralError{"unknown Go type"} | 467 return StructuralError{"unknown Go type"} |
458 } | 468 } |
459 | 469 |
460 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
(err error) { | 470 func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
(err error) { |
461 // If the field is an interface{} then recurse into it. | 471 // If the field is an interface{} then recurse into it. |
462 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { | 472 if v.Kind() == reflect.Interface && v.Type().NumMethod() == 0 { |
(...skipping 22 matching lines...) Expand all Loading... |
485 return | 495 return |
486 } | 496 } |
487 | 497 |
488 tag, isCompound, ok := getUniversalType(v.Type()) | 498 tag, isCompound, ok := getUniversalType(v.Type()) |
489 if !ok { | 499 if !ok { |
490 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type(
))} | 500 err = StructuralError{fmt.Sprintf("unknown Go type: %v", v.Type(
))} |
491 return | 501 return |
492 } | 502 } |
493 class := classUniversal | 503 class := classUniversal |
494 | 504 |
495 » if params.stringType != 0 { | 505 » if params.stringType != 0 && tag != tagPrintableString { |
496 » » if tag != tagPrintableString { | 506 » » return StructuralError{"Explicit string type given to non-string
member"} |
497 » » » return StructuralError{"Explicit string type given to no
n-string member"} | 507 » } |
| 508 |
| 509 » if tag == tagPrintableString { |
| 510 » » if params.stringType == 0 { |
| 511 » » » // This is a string without an explicit string type. We'
ll use |
| 512 » » » // a PrintableString if the character set in the string
is |
| 513 » » » // sufficiently limited, otherwise we'll use a UTF8Strin
g. |
| 514 » » » for _, r := range v.String() { |
| 515 » » » » if r >= utf8.RuneSelf || !isPrintable(byte(r)) { |
| 516 » » » » » if !utf8.ValidString(v.String()) { |
| 517 » » » » » » return errors.New("asn1: string
not valid UTF-8") |
| 518 » » » » » } |
| 519 » » » » » tag = tagUTF8String |
| 520 » » » » » break |
| 521 » » » » } |
| 522 » » » } |
| 523 » » } else { |
| 524 » » » tag = params.stringType |
498 } | 525 } |
499 tag = params.stringType | |
500 } | 526 } |
501 | 527 |
502 if params.set { | 528 if params.set { |
503 if tag != tagSequence { | 529 if tag != tagSequence { |
504 return StructuralError{"Non sequence tagged as set"} | 530 return StructuralError{"Non sequence tagged as set"} |
505 } | 531 } |
506 tag = tagSet | 532 tag = tagSet |
507 } | 533 } |
508 | 534 |
509 tags, body := out.fork() | 535 tags, body := out.fork() |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
548 var out bytes.Buffer | 574 var out bytes.Buffer |
549 v := reflect.ValueOf(val) | 575 v := reflect.ValueOf(val) |
550 f := newForkableWriter() | 576 f := newForkableWriter() |
551 err := marshalField(f, v, fieldParameters{}) | 577 err := marshalField(f, v, fieldParameters{}) |
552 if err != nil { | 578 if err != nil { |
553 return nil, err | 579 return nil, err |
554 } | 580 } |
555 _, err = f.writeTo(&out) | 581 _, err = f.writeTo(&out) |
556 return out.Bytes(), nil | 582 return out.Bytes(), nil |
557 } | 583 } |
OLD | NEW |