2005-01-31 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Novell.Directory.Ldap / Novell.Directory.Ldap.Rfc2251 / RfcIntermediateResponse.cs
1 /******************************************************************************
2  * The MIT License
3  * Copyright (c) 2003 Novell Inc.  www.novell.com
4  * 
5  * Permission is hereby granted, free of charge, to any person obtaining  a copy
6  * of this software and associated documentation files (the Software), to deal
7  * in the Software without restriction, including  without limitation the rights
8  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
9  * copies of the Software, and to  permit persons to whom the Software is 
10  * furnished to do so, subject to the following conditions:
11  * 
12  * The above copyright notice and this permission notice shall be included in 
13  * all copies or substantial portions of the Software.
14  * 
15  * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21  * SOFTWARE.
22  *******************************************************************************/
23 //
24 // Novell.Directory.Ldap.Rfc2251.RfcIntermediateResponse.cs
25 //
26 // Author:
27 //   Anil Bhatia (banil@novell.com)
28 //
29 // (C) 2003 Novell, Inc (http://www.novell.com)
30 //
31
32 using System;
33 using LdapException = Novell.Directory.Ldap.LdapException;
34 using LdapMessage = Novell.Directory.Ldap.LdapMessage;
35 using Novell.Directory.Ldap.Asn1;
36
37 namespace Novell.Directory.Ldap.Rfc2251
38 {
39   /// <summary> 
40   /// Represents an LDAP Intermediate Response.
41   ///
42   ///
43   ///  IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
44   ///         COMPONENTS OF LDAPResult, note: only present on incorrectly 
45   ///  encoded response from 
46   ///                                               pre Falcon-sp1 server 
47   ///               responseName     [10] LDAPOID OPTIONAL,
48   ///               responseValue    [11] OCTET STRING OPTIONAL }
49   /// </summary>
50   ///
51   public class RfcIntermediateResponse : Asn1Sequence,  RfcResponse 
52   {
53     /**
54      * Context-specific TAG for optional responseName.
55      */
56     public const int TAG_RESPONSE_NAME = 0;
57     /**
58      * Context-specific TAG for optional response.
59      */
60     public const int TAG_RESPONSE      = 1;
61
62     private int m_referralIndex;
63     private int m_responseNameIndex;
64     private int m_responseValueIndex;
65         
66
67     //*************************************************************************
68     // Constructors for ExtendedResponse
69     //*************************************************************************
70
71     /**
72      * The only time a client will create a IntermediateResponse is when it is
73      * decoding it from an InputStream. The stream contains the intermediate
74      * response sequence that follows the msgID in the PDU. The intermediate
75      * response draft defines this as:
76      *      IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
77      *             responseName     [0] LDAPOID OPTIONAL,
78      *             responseValue    [1] OCTET STRING OPTIONAL }
79      *
80      * Until post Falcon sp1, the LDAP server was incorrectly encoding
81      * intermediate response as:
82      *      IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
83      *             Components of LDAPResult,
84      *             responseName     [0] LDAPOID OPTIONAL,
85      *             responseValue    [1] OCTET STRING OPTIONAL }
86      *
87      * where the Components of LDAPResult are
88      *               resultCode      ENUMERATED {...}
89      *               matchedDN       LDAPDN,
90      *               errorMessage    LDAPString,
91      *               referral        [3] Referral OPTIONAL }
92      *
93      *
94      * (The components of LDAPResult never have the optional referral.)
95      * This constructor is written to handle both cases.
96      *
97      * The sequence of this intermediate response will have the element
98      * at index m_responseNameIndex set to an RfcLDAPOID containing the
99      * oid of the response. The element at m_responseValueIndex will be set
100      * to an ASN1OctetString containing the value bytes.
101      */
102     [CLSCompliantAttribute(false)]
103     public RfcIntermediateResponse(Asn1Decoder dec, System.IO.Stream in_Renamed, int len) : base(dec, in_Renamed, len)
104       //                throws IOException
105     {
106       //                super(dec, in, len);
107         
108       int i=0;          
109       m_responseNameIndex = m_responseValueIndex = 0;
110
111       // decode optional tagged elements. The parent class constructor will
112       // have decoded these elements as ASN1Tagged objects with the value
113       // stored as an ASN1OctectString object.
114
115       if(size() >= 3) //the incorrectly encoded case, LDAPResult contains 
116         i = 3;        //at least 3 components
117       else
118         i = 0; //correctly encoded case, can have zero components
119
120       for(; i<size(); i++) 
121       {         
122         Asn1Tagged obj = (Asn1Tagged)get_Renamed(i);
123         Asn1Identifier id = obj.getIdentifier();
124         switch(id.Tag) 
125         {
126         case TAG_RESPONSE_NAME:
127           set_Renamed(i, new RfcLdapOID(
128                                         ((Asn1OctetString)obj.taggedValue()).byteValue()));
129           m_responseNameIndex = i;
130           break;
131
132         case TAG_RESPONSE:
133           set_Renamed(i, obj.taggedValue());
134           m_responseValueIndex = i;
135           break;
136         }
137       }
138     }
139
140     public Asn1Enumerated getResultCode()
141     {
142         if ( size() > 3)    
143             return (Asn1Enumerated)get_Renamed(0);
144         else
145             return null;    
146     }
147
148     public RfcLdapDN getMatchedDN()
149     {
150         if ( size() > 3)
151             return new RfcLdapDN(((Asn1OctetString)get_Renamed(1)).byteValue());
152         else
153             return null;    
154     }
155
156     public RfcLdapString getErrorMessage()
157     {
158         if ( size() > 3)
159             return new RfcLdapString(((Asn1OctetString)get_Renamed(2)).byteValue());
160         else
161             return null;
162     }
163
164     public RfcReferral getReferral()
165     {
166       return (size() > 3) ? (RfcReferral)get_Renamed(3) : null;
167     }
168
169     public RfcLdapOID getResponseName()
170     {
171         return (m_responseNameIndex != 0) ? (RfcLdapOID)get_Renamed(m_responseNameIndex)
172                                         : null;
173     }
174
175     public Asn1OctetString getResponse()
176     {
177         return (m_responseValueIndex != 0) ? (Asn1OctetString)get_Renamed(m_responseValueIndex)
178                                     : null;
179     }
180
181     /**
182      * Override getIdentifier to return an application-wide id.
183      */
184     public override Asn1Identifier getIdentifier()
185     {
186         return new Asn1Identifier(Asn1Identifier.APPLICATION, true,
187                                    LdapMessage.INTERMEDIATE_RESPONSE);
188     }
189   }
190 }