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 }