View Javadoc
1   /*
2     (C) Copyright IBM Corp. 2005, 2010
3   
4     THIS FILE IS PROVIDED UNDER THE TERMS OF THE ECLIPSE PUBLIC LICENSE
5     ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THIS FILE
6     CONSTITUTES RECIPIENTS ACCEPTANCE OF THE AGREEMENT.
7   
8     You can obtain a current copy of the Eclipse Public License from
9     http://www.opensource.org/licenses/eclipse-1.0.php
10  
11    @author : Roberto Pineiro, IBM, roberto.pineiro@us.ibm.com
12   * @author : Chung-hao Tan, IBM, chungtan@us.ibm.com
13   * 
14   * 
15   * Change History
16   * Flag       Date        Prog         Description
17   *------------------------------------------------------------------------------- 
18   * 1535756    2006-08-07  lupusalex    Make code warning free
19   * 1565892    2006-11-28  lupusalex    Make SBLIM client JSR48 compliant
20   * 2003590    2008-06-30  blaschke-oss Change licensing from CPL to EPL
21   * 2524131    2009-01-21  raman_arora  Upgrade client to JDK 1.5 (Phase 1)
22   * 2531371    2009-02-10  raman_arora  Upgrade client to JDK 1.5 (Phase 2)
23   * 2750520    2009-04-10  blaschke-oss Code cleanup from empty statement et al
24   * 3001353    2010-05-18  blaschke-oss HttpHeaderParser ignores return value of toLowerCase()
25   */
26  
27  package org.metricshub.wbem.sblim.cimclient.internal.http;
28  
29  /*-
30   * ╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲
31   * WBEM Java Client
32   * ჻჻჻჻჻჻
33   * Copyright 2023 - 2025 MetricsHub
34   * ჻჻჻჻჻჻
35   * Licensed under the Apache License, Version 2.0 (the "License");
36   * you may not use this file except in compliance with the License.
37   * You may obtain a copy of the License at
38   *
39   *      http://www.apache.org/licenses/LICENSE-2.0
40   *
41   * Unless required by applicable law or agreed to in writing, software
42   * distributed under the License is distributed on an "AS IS" BASIS,
43   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
44   * See the License for the specific language governing permissions and
45   * limitations under the License.
46   * ╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱╲╱
47   */
48  
49  import java.util.Vector;
50  
51  /**
52   * Class HttpHeaderParser parses http headers
53   *
54   */
55  public class HttpHeaderParser {
56  	String iRaw;
57  
58  	Vector<String[]> iNameValuePair;
59  
60  	/**
61  	 * Ctor.
62  	 *
63  	 * @param pHeader
64  	 *            The header block
65  	 */
66  	public HttpHeaderParser(String pHeader) {
67  		this.iRaw = pHeader;
68  		this.iNameValuePair = new Vector<String[]>();
69  		if (this.iRaw != null) {
70  			this.iRaw = this.iRaw.trim();
71  			char charArray[] = this.iRaw.toCharArray();
72  			int startPosValue = 0;
73  			int currentPos = 0;
74  			boolean isName = true;
75  			boolean withinQuote = false;
76  			int len = charArray.length;
77  			String nvp[] = new String[2];
78  			do {
79  				char c = charArray[currentPos];
80  				if (c == '=') {
81  					nvp[0] = (new String(charArray, startPosValue, currentPos - startPosValue)).toLowerCase();
82  					isName = false;
83  					startPosValue = ++currentPos;
84  				} else if (c == '"') {
85  					if (withinQuote) {
86  						nvp[1] = new String(charArray, startPosValue, currentPos - startPosValue);
87  						this.iNameValuePair.add(nvp);
88  						nvp = new String[2];
89  						withinQuote = false;
90  						while (
91  							++currentPos < len &&
92  							(charArray[currentPos] == ' ' || charArray[currentPos] == ',' || charArray[currentPos] == ';')
93  						) {
94  							// ignore spaces and preceding comma
95  						}
96  						isName = true;
97  						startPosValue = currentPos;
98  					} else {
99  						withinQuote = true;
100 						startPosValue = ++currentPos;
101 					}
102 				} else if (c == ' ' || c == ',' || c == ';') {
103 					if (withinQuote) {
104 						currentPos++;
105 					} else {
106 						if (isName) {
107 							nvp[0] = (new String(charArray, startPosValue, currentPos - startPosValue)).toLowerCase();
108 							this.iNameValuePair.add(nvp);
109 							nvp = new String[2];
110 						} else {
111 							nvp[1] = new String(charArray, startPosValue, currentPos - startPosValue);
112 							this.iNameValuePair.add(nvp);
113 							nvp = new String[2];
114 						}
115 
116 						while (
117 							++currentPos < len &&
118 							(charArray[currentPos] == ' ' || charArray[currentPos] == ',' || charArray[currentPos] == ';')
119 						) {
120 							// ignore spaces and preceding comma
121 						}
122 						isName = true;
123 						startPosValue = currentPos;
124 					}
125 				} else {
126 					currentPos++;
127 				}
128 			} while (currentPos < len);
129 
130 			if (--currentPos > startPosValue) {
131 				if (!isName) {
132 					if (charArray[currentPos] == '"') {
133 						nvp[1] = new String(charArray, startPosValue, currentPos - startPosValue);
134 						this.iNameValuePair.add(nvp);
135 						nvp = new String[2];
136 					} else {
137 						nvp[1] = new String(charArray, startPosValue, (currentPos - startPosValue) + 1);
138 						this.iNameValuePair.add(nvp);
139 						nvp = new String[2];
140 					}
141 				} else {
142 					nvp[0] = (new String(charArray, startPosValue, (currentPos - startPosValue) + 1)).toLowerCase();
143 				}
144 				this.iNameValuePair.add(nvp);
145 			} else if (currentPos == startPosValue) {
146 				if (!isName) {
147 					if (charArray[currentPos] == '"') {
148 						nvp[1] = String.valueOf(charArray[currentPos - 1]);
149 						this.iNameValuePair.add(nvp);
150 						nvp = new String[2];
151 					} else {
152 						nvp[1] = String.valueOf(charArray[currentPos]);
153 						this.iNameValuePair.add(nvp);
154 						nvp = new String[2];
155 					}
156 				} else {
157 					nvp[0] = String.valueOf(charArray[currentPos]).toLowerCase();
158 				}
159 				this.iNameValuePair.add(nvp);
160 			}
161 		}
162 	}
163 
164 	/**
165 	 * Returns the header field at a given index
166 	 *
167 	 * @param pIndex
168 	 *            The index
169 	 * @return The field name
170 	 */
171 	public String getField(int pIndex) {
172 		if (pIndex < 0 || pIndex > this.iNameValuePair.size()) return null;
173 		return this.iNameValuePair.elementAt(pIndex)[0];
174 	}
175 
176 	/**
177 	 * Returns the value of a header field at a given index
178 	 *
179 	 * @param pIndex
180 	 * @return The value
181 	 */
182 	public String getValue(int pIndex) {
183 		if (pIndex < 0 || pIndex > this.iNameValuePair.size()) return null;
184 		return this.iNameValuePair.elementAt(pIndex)[1];
185 	}
186 
187 	/**
188 	 * Returns the value of a header field for a given name
189 	 *
190 	 * @param pName
191 	 *            The name
192 	 * @return The value
193 	 */
194 	public String getValue(String pName) {
195 		return getValue(pName, null);
196 	}
197 
198 	/**
199 	 * Returns the value of a header field for a given name specifying a
200 	 * default.
201 	 *
202 	 * @param pName
203 	 *            The name of the header field
204 	 * @param pDefault
205 	 *            The value returned if no field of the given name exists
206 	 * @return The value
207 	 */
208 	public String getValue(String pName, String pDefault) {
209 		if (pName == null) return pDefault;
210 		pName = pName.toLowerCase();
211 		for (int i = 0; i < this.iNameValuePair.size(); i++) {
212 			if (this.iNameValuePair.elementAt(i)[0] == null) return pDefault;
213 			if (pName.equals(this.iNameValuePair.elementAt(i)[0])) return this.iNameValuePair.elementAt(i)[1];
214 		}
215 		return pDefault;
216 	}
217 
218 	/**
219 	 * Returns the value of a numeric header field for a given name specifying a
220 	 * default.
221 	 *
222 	 * @param pName
223 	 *            The name of the header field
224 	 * @param pDefault
225 	 *            The value returned if no field of the given name exists
226 	 * @return The value
227 	 */
228 	public int getIntValue(String pName, int pDefault) {
229 		try {
230 			return Integer.parseInt(getValue(pName, String.valueOf(pDefault)));
231 		} catch (Exception e) {
232 			return pDefault;
233 		}
234 	}
235 
236 	@Override
237 	public String toString() {
238 		return "raw:" + this.iRaw;
239 	}
240 }