1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 package org.metricshub.wbem.sblim.cimclient.internal.http;
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 import java.io.BufferedWriter;
60 import java.io.ByteArrayOutputStream;
61 import java.io.IOException;
62 import java.io.InputStream;
63 import java.io.OutputStreamWriter;
64 import java.io.UnsupportedEncodingException;
65 import java.net.URLDecoder;
66 import java.security.AccessController;
67 import java.security.PrivilegedAction;
68 import java.util.BitSet;
69 import java.util.Hashtable;
70 import java.util.Iterator;
71 import java.util.Map.Entry;
72 import java.util.logging.Level;
73 import org.metricshub.wbem.javax.wbem.WBEMException;
74 import org.metricshub.wbem.sblim.cimclient.internal.http.io.ASCIIPrintStream;
75 import org.metricshub.wbem.sblim.cimclient.internal.http.io.TrailerException;
76 import org.metricshub.wbem.sblim.cimclient.internal.logging.LogAndTraceBroker;
77 import org.metricshub.wbem.sblim.cimclient.internal.logging.Messages;
78 import org.metricshub.wbem.sblim.cimclient.internal.util.WBEMConstants;
79
80
81
82
83
84 public class HttpHeader {
85 private static BitSet cDontNeedEncoding;
86
87 private static final String HEX_STR = "0123456789ABCDEF";
88
89 private static String cDfltEncName = null;
90
91 static {
92 cDontNeedEncoding = new BitSet(256);
93 int i;
94 for (i = 'a'; i <= 'z'; i++) {
95 cDontNeedEncoding.set(i);
96 }
97 for (i = 'A'; i <= 'Z'; i++) {
98 cDontNeedEncoding.set(i);
99 }
100 for (i = '0'; i <= '9'; i++) {
101 cDontNeedEncoding.set(i);
102 }
103 cDontNeedEncoding.set(' ');
104 cDontNeedEncoding.set('-');
105 cDontNeedEncoding.set('_');
106 cDontNeedEncoding.set('/');
107 cDontNeedEncoding.set('.');
108 cDontNeedEncoding.set('*');
109 }
110
111 private Hashtable<HeaderEntry, String> iFields = new Hashtable<HeaderEntry, String>();
112
113
114
115
116 public HttpHeader() {
117
118 }
119
120
121
122
123
124
125
126
127 public HttpHeader(InputStream pReader) throws IOException {
128 this(pReader, 0);
129 }
130
131
132
133
134
135
136
137
138
139
140 public HttpHeader(InputStream pReader, long pTimeout) throws IOException {
141 String line = null;
142 long timeStart = System.currentTimeMillis();
143
144 while (((line = HttpMethod.readLine(pReader)) != null) && (line.length() > 0)) {
145
146 if (pTimeout > 0 && (System.currentTimeMillis() - timeStart > pTimeout)) {
147 throw new IOException(WBEMConstants.INDICATION_DOS_EXCEPTION_MESSAGE);
148 }
149 try {
150 int separator;
151 if ((separator = line.indexOf(':')) > -1) {
152 String header;
153 String value;
154 int headerStartIndex = 0;
155
156
157
158 if (line.indexOf('-') == 2 && Character.isDigit(line.charAt(0)) && Character.isDigit(line.charAt(1))) {
159 headerStartIndex = 3;
160 }
161
162 header = line.substring(headerStartIndex, separator);
163 value = line.substring(separator + 1);
164
165
166 if (value.length() > 0 && value.startsWith(" ")) addParsedField(
167 header,
168 value.substring(1)
169 ); else addParsedField(header, value);
170 } else {
171 LogAndTraceBroker.getBroker().message(Messages.HTTP_INVALID_HEADER, line);
172 }
173 } catch (Exception e) {
174 LogAndTraceBroker.getBroker().trace(Level.FINER, "Exception while parsing http header", e);
175 LogAndTraceBroker.getBroker().message(Messages.HTTP_INVALID_HEADER, line);
176 }
177 }
178 return;
179 }
180
181
182
183
184
185
186
187
188
189
190 public void addField(String pName, String pValue) {
191 if (pName == null || pName.length() == 0) return;
192
193 if (pValue != null) {
194 this.iFields.put(new HeaderEntry(pName), pValue);
195 } else {
196 this.iFields.remove(new HeaderEntry(pName));
197 }
198 }
199
200
201
202
203
204
205
206
207
208
209 public void addParsedField(String pName, String pValue) {
210 if (pName == null || pName.length() == 0) return;
211
212 if (pValue != null) {
213 String oldValue = this.iFields.put(new HeaderEntry(pName), pValue);
214 if (oldValue != null) {
215
216
217
218
219 StringBuilder combinedValue = new StringBuilder(oldValue);
220 combinedValue.append(',');
221 combinedValue.append(pValue);
222 this.iFields.put(new HeaderEntry(pName), combinedValue.toString());
223 }
224 } else {
225 this.iFields.remove(new HeaderEntry(pName));
226 }
227 }
228
229
230
231
232 public void clear() {
233 this.iFields.clear();
234 }
235
236
237
238
239
240
241 public Iterator<Entry<HeaderEntry, String>> iterator() {
242 return this.iFields.entrySet().iterator();
243 }
244
245
246
247
248
249
250
251
252 public static HttpHeader parse(String pLine) {
253 int prev = 0;
254 int next = 0;
255 HttpHeader header = new HttpHeader();
256 if (pLine != null && pLine.length() > 0) {
257 next = pLine.indexOf(',');
258 while (next > -1) {
259 String hdr = pLine.substring(prev, next);
260 int separator = hdr.indexOf('=');
261 if (separator > -1) {
262 String key;
263 String value;
264 key = hdr.substring(0, separator);
265 value = hdr.substring(separator + 1);
266
267 header.addParsedField(key, value);
268 } else {
269
270 }
271 prev = next + 1;
272 while (Character.isSpaceChar(pLine.charAt(prev))) prev++;
273 next = pLine.indexOf(',', prev);
274 }
275 String hdr = pLine.substring(prev);
276 int separator = hdr.indexOf('=');
277 if (separator > -1) {
278 header.addParsedField(hdr.substring(0, separator), hdr.substring(separator + 1));
279 }
280 }
281
282 return header;
283 }
284
285 @Override
286 public String toString() {
287 StringBuffer buf = new StringBuffer();
288 int i = 0;
289 Iterator<Entry<HeaderEntry, String>> iterator = this.iFields.entrySet().iterator();
290 while (iterator.hasNext()) {
291 if (i++ > 0) buf.append(',');
292 Entry<HeaderEntry, String> entry = iterator.next();
293 buf.append(entry.getKey().toString());
294 buf.append(": ");
295 buf.append(entry.getValue().toString());
296 }
297 return buf.toString();
298 }
299
300
301
302
303
304
305
306 public void removeField(String pName) {
307 this.iFields.remove(new HeaderEntry(pName));
308 }
309
310
311
312
313
314
315
316
317 public String getField(String pName) {
318 return this.iFields.get(new HeaderEntry(pName));
319 }
320
321
322
323
324
325
326
327 public void write(ASCIIPrintStream pWriter) {
328 Iterator<Entry<HeaderEntry, String>> iterator = this.iFields.entrySet().iterator();
329 while (iterator.hasNext()) {
330 Entry<HeaderEntry, String> entry = iterator.next();
331 pWriter.print(entry.getKey().toString());
332 pWriter.print(": ");
333 pWriter.print(entry.getValue().toString());
334 pWriter.print("\r\n");
335 }
336 pWriter.print("\r\n");
337 }
338
339
340
341
342
343
344
345
346 public static synchronized String encode(byte[] pData) {
347 String str = null;
348 try {
349 if (cDfltEncName == null) cDfltEncName = (String) AccessController.doPrivileged(new GetProperty("file.encoding"));
350 str = encode(pData, cDfltEncName);
351 } catch (UnsupportedEncodingException e) {
352 LogAndTraceBroker.getBroker().trace(Level.FINER, "Exception while encoding http header data", e);
353 }
354 return str;
355 }
356
357
358
359
360
361
362
363
364
365
366
367 public static String encode(byte[] pData, String pEnc) throws UnsupportedEncodingException {
368 int maxBytesPerChar = 10;
369
370 ByteArrayOutputStream buf = new ByteArrayOutputStream(maxBytesPerChar);
371 new BufferedWriter(new OutputStreamWriter(buf, pEnc));
372 StringBuffer out = new StringBuffer(pData.length);
373
374 for (int i = 0; i < pData.length; i++) {
375 int c = pData[i] & 0xFF;
376 if (cDontNeedEncoding.get(c)) {
377 if (c == ' ') {
378 out.append("%20");
379 } else {
380 out.append((char) c);
381 }
382 } else {
383 out.append('%');
384 out.append(HEX_STR.charAt((c >> 4) & 0x0f));
385 out.append(HEX_STR.charAt(c & 0x0f));
386 }
387 }
388
389 return out.toString();
390 }
391
392
393
394
395
396
397
398
399
400
401
402
403
404 public static String encode(String pData, String pSourceEnc, String pTargetEnc) throws UnsupportedEncodingException {
405 return encode(pData.getBytes(pSourceEnc), pTargetEnc);
406 }
407
408
409
410
411
412 public static class HeaderEntry {
413 String iHeader;
414
415 int iHashcode;
416
417
418
419
420
421
422
423 public HeaderEntry(String pName) {
424 this.iHeader = pName;
425 this.iHashcode = pName.toUpperCase().hashCode();
426 }
427
428 @Override
429 public boolean equals(Object obj) {
430 if (obj == null || !(obj instanceof HeaderEntry)) return false;
431 return this.iHeader.equalsIgnoreCase(((HeaderEntry) obj).iHeader);
432 }
433
434 @Override
435 public String toString() {
436 return this.iHeader;
437 }
438
439 @Override
440 public int hashCode() {
441 return this.iHashcode;
442 }
443 }
444
445
446
447
448
449 private static class GetProperty implements PrivilegedAction<Object> {
450 String iPropertyName;
451
452 GetProperty(String propertyName) {
453 this.iPropertyName = propertyName;
454 }
455
456 public Object run() {
457 return System.getProperty(this.iPropertyName);
458 }
459 }
460
461
462
463
464
465
466
467 public void examineTrailer() throws TrailerException {
468 examineTrailer(null);
469 }
470
471
472
473
474
475
476
477
478
479 public void examineTrailer(String pOrigin) throws TrailerException {
480 Iterator<Entry<HeaderEntry, String>> itr = this.iterator();
481 int code = 0, i = 0;
482 String desc = null;
483 StringBuilder hdrs = null;
484 if (LogAndTraceBroker.getBroker().isLoggableTrace(Level.FINER)) hdrs = new StringBuilder();
485 while (itr.hasNext()) {
486 Entry<HeaderEntry, String> ent = itr.next();
487 String keyStr = ent.getKey().toString();
488 if (hdrs != null) {
489 if (i++ > 0) hdrs.append(',');
490 hdrs.append(keyStr);
491 hdrs.append(": ");
492 hdrs.append(this.getField(keyStr));
493 }
494 try {
495 if (keyStr.equalsIgnoreCase(WBEMConstants.HTTP_TRAILER_STATUS_CODE)) {
496 String valStr = URLDecoder.decode(this.getField(keyStr), WBEMConstants.UTF8);
497 try {
498 code = Integer.parseInt(valStr);
499 } catch (NumberFormatException e) {
500 String msg = new String(
501 WBEMConstants.HTTP_TRAILER_STATUS_CODE + " \"" + valStr + "\" invalid, setting to CIM_ERR_FAILED"
502 );
503 LogAndTraceBroker.getBroker().trace(Level.FINER, msg, e);
504 code = WBEMException.CIM_ERR_FAILED;
505 if (desc == null) desc = msg;
506 }
507 } else if (keyStr.equalsIgnoreCase(WBEMConstants.HTTP_TRAILER_STATUS_DESCRIPTION)) {
508 desc = URLDecoder.decode(this.getField(keyStr), WBEMConstants.UTF8);
509 }
510 } catch (UnsupportedEncodingException e) {
511
512 throw new Error(e);
513 }
514 }
515 if (hdrs != null && hdrs.length() > 0) LogAndTraceBroker
516 .getBroker()
517 .trace(Level.FINER, (pOrigin == null ? "Unknown" : pOrigin) + " HTTP Trailer Headers= " + hdrs.toString());
518 if (code > 0) {
519 if (desc != null) {
520 throw new TrailerException(new WBEMException(code, desc));
521 }
522 throw new TrailerException(new WBEMException(code));
523 }
524 }
525 }