View Javadoc

1   /*
2    * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/auth/AuthChallengeParser.java,v 1.4.2.2 2004/02/22 18:21:14 olegk Exp $
3    * $Revision: 1.4.2.2 $
4    * $Date: 2004/02/22 18:21:14 $
5    *
6    * ====================================================================
7    *
8    *  Copyright 2002-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   * [Additional notices, if required by prior licensing conditions]
29   *
30   */
31  
32  package org.apache.commons.httpclient.auth;
33  
34  import java.util.Map;
35  import java.util.HashMap;
36  
37  /***
38   * This class provides utility methods for parsing HTTP www and proxy authentication 
39   * challenges.
40   * 
41   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
42   * 
43   * @since 2.0beta1
44   */
45  public final class AuthChallengeParser {
46      /*** 
47       * Extracts authentication scheme from the given authentication 
48       * challenge.
49       *
50       * @param challengeStr the authentication challenge string
51       * @return authentication scheme
52       * 
53       * @throws MalformedChallengeException when the authentication challenge string
54       *  is malformed
55       * 
56       * @since 2.0beta1
57       */
58      public static String extractScheme(final String challengeStr) 
59        throws MalformedChallengeException {
60          if (challengeStr == null) {
61              throw new IllegalArgumentException("Challenge may not be null"); 
62          }
63          int i = challengeStr.indexOf(' ');
64          String s = null; 
65          if (i == -1) {
66              s = challengeStr;
67          } else {
68              s = challengeStr.substring(0, i);
69          }
70          if (s.equals("")) {
71              throw new MalformedChallengeException("Invalid challenge: " + challengeStr);
72          }
73          return s.toLowerCase();
74      }
75  
76      /*** 
77       * Extracts a map of challenge parameters from an authentication challenge.
78       * Keys in the map are lower-cased
79       *
80       * @param challengeStr the authentication challenge string
81       * @return a map of authentication challenge parameters
82       * @throws MalformedChallengeException when the authentication challenge string
83       *  is malformed
84       * 
85       * @since 2.0beta1
86       */
87      public static Map extractParams(final String challengeStr)
88        throws MalformedChallengeException {
89          if (challengeStr == null) {
90              throw new IllegalArgumentException("Challenge may not be null"); 
91          }
92          int i = challengeStr.indexOf(' ');
93          if (i == -1) {
94              throw new MalformedChallengeException("Invalid challenge: " + challengeStr);
95          }
96  
97          Map elements = new HashMap();
98  
99          i++;
100         int len = challengeStr.length();
101 
102         String name = null;
103         String value = null;
104 
105         StringBuffer buffer = new StringBuffer();
106 
107         boolean parsingName = true;
108         boolean inQuote = false;
109         boolean gotIt = false;
110 
111         while (i < len) {
112             // Parse one char at a time 
113             char ch = challengeStr.charAt(i);
114             i++;
115             // Process the char
116             if (parsingName) {
117                 // parsing name
118                 if (ch == '=') {
119                     name = buffer.toString().trim();
120                     parsingName = false;
121                     buffer.setLength(0);
122                 } else if (ch == ',') {
123                     name = buffer.toString().trim();
124                     value = null;
125                     gotIt = true;
126                     buffer.setLength(0);
127                 } else {
128                     buffer.append(ch);
129                 }
130                 // Have I reached the end of the challenge string?
131                 if (i == len) {
132                     name = buffer.toString().trim();
133                     value = null;
134                     gotIt = true;
135                 }
136             } else {
137                 //parsing value
138                 if (!inQuote) {
139                     // Value is not quoted or not found yet
140                     if (ch == ',') {
141                         value = buffer.toString().trim();
142                         gotIt = true;
143                         buffer.setLength(0);
144                     } else {
145                         // no value yet
146                         if (buffer.length() == 0) {
147                             if (ch == ' ') {
148                                 //discard
149                             } else if (ch == '\t') {
150                                 //discard
151                             } else if (ch == '\n') {
152                                 //discard
153                             } else if (ch == '\r') {
154                                 //discard
155                             } else {
156                                 // otherwise add to the buffer
157                                 buffer.append(ch);
158                                 if (ch == '"') {
159                                     inQuote = true;
160                                 }
161                             }
162                         } else {
163                             // already got something
164                             // just keep on adding to the buffer
165                             buffer.append(ch);
166                         }
167                     }
168                 } else {
169                     // Value is quoted
170                     // Keep on adding until closing quote is encountered
171                     buffer.append(ch);
172                     if (ch == '"') {
173                         inQuote = false;
174                     }
175                 }
176                 // Have I reached the end of the challenge string?
177                 if (i == len) {
178                     value = buffer.toString().trim();
179                     gotIt = true;
180                 }
181             }
182             if (gotIt) {
183                 // Got something
184                 if ((name == null) || (name.equals(""))) {
185                     throw new MalformedChallengeException("Invalid challenge: " + challengeStr);
186                 }
187                 // Strip quotes when present
188                 if ((value != null) && (value.length() > 1)) {
189                     if ((value.charAt(0) == '"') 
190                      && (value.charAt(value.length() - 1) == '"')) {
191                         value = value.substring(1, value.length() - 1);  
192                      }
193                 }
194                 
195                 elements.put(name.toLowerCase(), value);
196                 parsingName = true;
197                 gotIt = false;
198             }
199         }
200         return elements;
201     }
202 }