summaryrefslogblamecommitdiffstats
path: root/control.go
blob: af145b2ae7ec688c9504644ef1942bade6bbf38b (plain) (tree)




























































































































































                                                                                                                                                                               
// Copyright 2011 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This package provides LDAP client functions.
package ldap

import (
   "github.com/mmitton/asn1-ber"
   "fmt"
)

const (
   ControlTypePaging = "1.2.840.113556.1.4.319"
)

var ControlTypeMap = map[ string ] string {
   ControlTypePaging : "Paging",
}

type Control interface {
   GetControlType() string
   Encode() *ber.Packet
   String() string
}

type ControlString struct {
   ControlType string
   Criticality bool
   ControlValue string
}

func (c *ControlString) GetControlType() string {
   return c.ControlType
}

func (c *ControlString) Encode() (p *ber.Packet) {
   p = ber.Encode( ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control" )
   p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, c.ControlType, "Control Type (" + ControlTypeMap[ c.ControlType ] + ")" ) )
   if c.Criticality {
      p.AppendChild( ber.NewBoolean( ber.ClassUniversal, ber.TypePrimative, ber.TagBoolean, c.Criticality, "Criticality" ) )
   }
   p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, c.ControlValue, "Control Value" ) )
   return
}

func (c *ControlString) String() string {
   return fmt.Sprintf( "Control Type: %s (%q)  Criticality: %s  Control Value: %s", ControlTypeMap[ c.ControlType ], c.ControlType, c.Criticality, c.ControlValue )
}

type ControlPaging struct {
   PagingSize uint32
   Cookie []byte
}

func (c *ControlPaging) GetControlType() string {
   return ControlTypePaging
}

func (c *ControlPaging) Encode() (p *ber.Packet) {
   p = ber.Encode( ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Control" )
   p.AppendChild( ber.NewString( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, ControlTypePaging, "Control Type (" + ControlTypeMap[ ControlTypePaging ] + ")" ) )

   p2 := ber.Encode( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, nil, "Control Value (Paging)" )
   seq := ber.Encode( ber.ClassUniversal, ber.TypeConstructed, ber.TagSequence, nil, "Search Control Value" )
   seq.AppendChild( ber.NewInteger( ber.ClassUniversal, ber.TypePrimative, ber.TagInteger, uint64(c.PagingSize), "Paging Size" ) )
   cookie := ber.Encode( ber.ClassUniversal, ber.TypePrimative, ber.TagOctetString, nil, "Cookie" )
   cookie.Value = c.Cookie
   cookie.Data.Write( c.Cookie )
   seq.AppendChild( cookie )
   p2.AppendChild( seq )

   p.AppendChild( p2 )
   return
}

func (c *ControlPaging) String() string {
   return fmt.Sprintf(
      "Control Type: %s (%q)  Criticality: %s  PagingSize: %d  Cookie: %q",
      ControlTypeMap[ ControlTypePaging ],
      ControlTypePaging,
      false,
      c.PagingSize,
      c.Cookie )
}

func (c *ControlPaging) SetCookie( Cookie []byte ) {
   c.Cookie = Cookie
}

func FindControl( Controls []Control, ControlType string ) Control {
   for _, c := range Controls {
      if c.GetControlType() == ControlType {
         return c
      }
   }
   return nil
}

func DecodeControl( p *ber.Packet ) Control {
   ControlType := p.Children[ 0 ].Value.(string)
   Criticality := false

   p.Children[ 0 ].Description = "Control Type (" + ControlTypeMap[ ControlType ] + ")"
   value := p.Children[ 1 ]
   if len( p.Children ) == 3 {
      value = p.Children[ 2 ]
      p.Children[ 1 ].Description = "Criticality"
      Criticality = p.Children[ 1 ].Value.(bool)
   }

   value.Description = "Control Value"
   switch ControlType {
      case ControlTypePaging:
         value.Description += " (Paging)"
         c := new( ControlPaging )
         if value.Value != nil {
            value_children := ber.DecodePacket( value.Data.Bytes() )
            value.Data.Truncate( 0 )
            value.Value = nil
            value.AppendChild( value_children )
         }
         value = value.Children[ 0 ]
         value.Description = "Search Control Value"
         value.Children[ 0 ].Description = "Paging Size"
         value.Children[ 1 ].Description = "Cookie"
         c.PagingSize = uint32( value.Children[ 0 ].Value.(uint64) )
         c.Cookie = value.Children[ 1 ].Data.Bytes()
         value.Children[ 1 ].Value = c.Cookie
         return c
   }
   c := new( ControlString )
   c.ControlType = ControlType
   c.Criticality = Criticality
   c.ControlValue = value.Value.(string)
   return c
}

func NewControlString( ControlType string, Criticality bool, ControlValue string ) *ControlString {
   return &ControlString{
      ControlType: ControlType,
      Criticality: Criticality,
      ControlValue: ControlValue,
   }
}

func NewControlPaging( PagingSize uint32 ) *ControlPaging {
   return &ControlPaging{ PagingSize: PagingSize }
}

func encodeControls( Controls []Control ) *ber.Packet {
   p := ber.Encode( ber.ClassContext, ber.TypeConstructed, 0, nil, "Controls" )
   for _, control := range Controls {
      p.AppendChild( control.Encode() )
   }
   return p
}