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 package org.apache.hc.client5.http.ssl;
29
30 import java.util.ArrayList;
31 import java.util.BitSet;
32 import java.util.List;
33
34 import org.apache.hc.core5.http.NameValuePair;
35 import org.apache.hc.core5.http.message.BasicNameValuePair;
36 import org.apache.hc.core5.util.CharArrayBuffer;
37 import org.apache.hc.core5.util.Tokenizer;
38
39 final class DistinguishedNameParser {
40
41 public final static DistinguishedNameParser INSTANCE = new DistinguishedNameParser();
42
43 private static final BitSet EQUAL_OR_COMMA_OR_PLUS = Tokenizer.INIT_BITSET('=', ',', '+');
44 private static final BitSet COMMA_OR_PLUS = Tokenizer.INIT_BITSET(',', '+');
45
46 private final Tokenizer tokenParser;
47
48 DistinguishedNameParser() {
49 this.tokenParser = new InternalTokenParser();
50 }
51
52 private String parseToken(final CharArrayBuffer buf, final Tokenizer.Cursor cursor, final BitSet delimiters) {
53 return tokenParser.parseToken(buf, cursor, delimiters);
54 }
55
56 private String parseValue(final CharArrayBuffer buf, final Tokenizer.Cursor cursor, final BitSet delimiters) {
57 return tokenParser.parseValue(buf, cursor, delimiters);
58 }
59
60 private NameValuePair parseParameter(final CharArrayBuffer buf, final Tokenizer.Cursor cursor) {
61 final String name = parseToken(buf, cursor, EQUAL_OR_COMMA_OR_PLUS);
62 if (cursor.atEnd()) {
63 return new BasicNameValuePair(name, null);
64 }
65 final int delim = buf.charAt(cursor.getPos());
66 cursor.updatePos(cursor.getPos() + 1);
67 if (delim == ',') {
68 return new BasicNameValuePair(name, null);
69 }
70 final String value = parseValue(buf, cursor, COMMA_OR_PLUS);
71 if (!cursor.atEnd()) {
72 cursor.updatePos(cursor.getPos() + 1);
73 }
74 return new BasicNameValuePair(name, value);
75 }
76
77 List<NameValuePair> parse(final CharArrayBuffer buf, final Tokenizer.Cursor cursor) {
78 final List<NameValuePair> params = new ArrayList<>();
79 tokenParser.skipWhiteSpace(buf, cursor);
80 while (!cursor.atEnd()) {
81 final NameValuePair param = parseParameter(buf, cursor);
82 params.add(param);
83 }
84 return params;
85 }
86
87 List<NameValuePair> parse(final String s) {
88 if (s == null) {
89 return null;
90 }
91 final CharArrayBuffer buffer = new CharArrayBuffer(s.length());
92 buffer.append(s);
93 final Tokenizer.Cursor cursor = new Tokenizer.Cursor(0, s.length());
94 return parse(buffer, cursor);
95 }
96
97 static class InternalTokenParser extends Tokenizer {
98
99 @Override
100 public void copyUnquotedContent(
101 final CharSequence buf,
102 final Tokenizer.Cursor cursor,
103 final BitSet delimiters,
104 final StringBuilder dst) {
105 int pos = cursor.getPos();
106 final int indexFrom = cursor.getPos();
107 final int indexTo = cursor.getUpperBound();
108 boolean escaped = false;
109 for (int i = indexFrom; i < indexTo; i++, pos++) {
110 final char current = buf.charAt(i);
111 if (escaped) {
112 dst.append(current);
113 escaped = false;
114 } else {
115 if ((delimiters != null && delimiters.get(current))
116 || Tokenizer.isWhitespace(current) || current == '\"') {
117 break;
118 } else if (current == '\\') {
119 escaped = true;
120 } else {
121 dst.append(current);
122 }
123 }
124 }
125 cursor.updatePos(pos);
126 }
127 }
128
129 }
130