control.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. // Copyright 2011 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ldap
  5. import (
  6. "strings"
  7. "fmt"
  8. "github.com/nmcclain/asn1-ber"
  9. )
  10. const (
  11. ControlTypePaging = "1.2.840.113556.1.4.319"
  12. )
  13. var ControlTypeMap = map[string]string{
  14. ControlTypePaging: "Paging",
  15. }
  16. type Control interface {
  17. GetControlType() string
  18. Encode() *ber.Packet
  19. String() string
  20. }
  21. type ControlString struct {
  22. ControlType string
  23. Criticality bool
  24. ControlValue string
  25. }
  26. func (c *ControlString) GetControlType() string {
  27. return c.ControlType
  28. }
  29. func (c *ControlString) Encode() *ber.Packet {
  30. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
  31. packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlType, "Control Type ("+ControlTypeMap[c.ControlType]+")"))
  32. if c.Criticality {
  33. packet.AppendChild(ber.NewBoolean(ber.ClassUniversal, ber.TypePrimitive, ber.TagBoolean, c.Criticality, "Criticality"))
  34. }
  35. if strings.TrimSpace(c.ControlValue) != "" {
  36. packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, c.ControlValue, "Control Value"))
  37. }
  38. return packet
  39. }
  40. func (c *ControlString) String() string {
  41. return fmt.Sprintf("Control Type: %s (%q) Criticality: %t Control Value: %s", ControlTypeMap[c.ControlType], c.ControlType, c.Criticality, c.ControlValue)
  42. }
  43. type ControlPaging struct {
  44. PagingSize uint32
  45. Cookie []byte
  46. }
  47. func (c *ControlPaging) GetControlType() string {
  48. return ControlTypePaging
  49. }
  50. func (c *ControlPaging) Encode() *ber.Packet {
  51. packet := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control")
  52. packet.AppendChild(ber.NewString(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, ControlTypePaging, "Control Type ("+ControlTypeMap[ControlTypePaging]+")"))
  53. p2 := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Control Value (Paging)")
  54. seq := ber.Encode(ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value")
  55. seq.AppendChild(ber.NewInteger(ber.ClassUniversal, ber.TypePrimitive, ber.TagInteger, uint64(c.PagingSize), "Paging Size"))
  56. cookie := ber.Encode(ber.ClassUniversal, ber.TypePrimitive, ber.TagOctetString, nil, "Cookie")
  57. cookie.Value = c.Cookie
  58. cookie.Data.Write(c.Cookie)
  59. seq.AppendChild(cookie)
  60. p2.AppendChild(seq)
  61. packet.AppendChild(p2)
  62. return packet
  63. }
  64. func (c *ControlPaging) String() string {
  65. return fmt.Sprintf(
  66. "Control Type: %s (%q) Criticality: %t PagingSize: %d Cookie: %q",
  67. ControlTypeMap[ControlTypePaging],
  68. ControlTypePaging,
  69. false,
  70. c.PagingSize,
  71. c.Cookie)
  72. }
  73. func (c *ControlPaging) SetCookie(cookie []byte) {
  74. c.Cookie = cookie
  75. }
  76. func FindControl(controls []Control, controlType string) Control {
  77. for _, c := range controls {
  78. if c.GetControlType() == controlType {
  79. return c
  80. }
  81. }
  82. return nil
  83. }
  84. func DecodeControl(packet *ber.Packet) Control {
  85. ControlType := packet.Children[0].Value.(string)
  86. packet.Children[0].Description = "Control Type (" + ControlTypeMap[ControlType] + ")"
  87. c := new(ControlString)
  88. c.ControlType = ControlType
  89. c.Criticality = false
  90. if len(packet.Children) > 1 {
  91. value := packet.Children[1]
  92. if len(packet.Children) == 3 {
  93. value = packet.Children[2]
  94. packet.Children[1].Description = "Criticality"
  95. c.Criticality = packet.Children[1].Value.(bool)
  96. }
  97. value.Description = "Control Value"
  98. switch ControlType {
  99. case ControlTypePaging:
  100. value.Description += " (Paging)"
  101. c := new(ControlPaging)
  102. if value.Value != nil {
  103. valueChildren := ber.DecodePacket(value.Data.Bytes())
  104. value.Data.Truncate(0)
  105. value.Value = nil
  106. value.AppendChild(valueChildren)
  107. }
  108. value = value.Children[0]
  109. value.Description = "Search Control Value"
  110. value.Children[0].Description = "Paging Size"
  111. value.Children[1].Description = "Cookie"
  112. c.PagingSize = uint32(value.Children[0].Value.(uint64))
  113. c.Cookie = value.Children[1].Data.Bytes()
  114. value.Children[1].Value = c.Cookie
  115. return c
  116. }
  117. c.ControlValue = value.Value.(string)
  118. }
  119. return c
  120. }
  121. func NewControlString(controlType string, criticality bool, controlValue string) *ControlString {
  122. return &ControlString{
  123. ControlType: controlType,
  124. Criticality: criticality,
  125. ControlValue: controlValue,
  126. }
  127. }
  128. func NewControlPaging(pagingSize uint32) *ControlPaging {
  129. return &ControlPaging{PagingSize: pagingSize}
  130. }
  131. func encodeControls(controls []Control) *ber.Packet {
  132. packet := ber.Encode(ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls")
  133. for _, control := range controls {
  134. packet.AppendChild(control.Encode())
  135. }
  136. return packet
  137. }