| 
 1 | 
  
 |  | 
| 
 2 | 
  
 |  | 
| 
 3 | 
  
 |  | 
| 
 4 | 
  
 |  | 
| 
 5 | 
  
 |  | 
| 
 6 | 
  
 |  | 
| 
 7 | 
  
 |  | 
| 
 8 | 
  
 |  | 
| 
 9 | 
  
 |  | 
| 
 10 | 
  
 |  | 
| 
 11 | 
  
 |  | 
| 
 12 | 
  
 |  | 
| 
 13 | 
  
 |  | 
| 
 14 | 
  
 |  | 
| 
 15 | 
  
 |  | 
| 
 16 | 
  
 |  | 
| 
 17 | 
  
 |  | 
| 
 18 | 
  
 | package javax.mail.internet; | 
| 
 19 | 
  
 |  | 
| 
 20 | 
  
 | import java.io.UnsupportedEncodingException; | 
| 
 21 | 
  
 | import java.lang.reflect.Array; | 
| 
 22 | 
  
 | import java.util.ArrayList; | 
| 
 23 | 
  
 | import java.util.List; | 
| 
 24 | 
  
 |  | 
| 
 25 | 
  
 | class AddressParser { | 
| 
 26 | 
  
 |  | 
| 
 27 | 
  
 |      | 
| 
 28 | 
  
 |     static public final int NONSTRICT = 0; | 
| 
 29 | 
  
 |     static public final int PARSE_HEADER = 1; | 
| 
 30 | 
  
 |     static public final int STRICT = 2; | 
| 
 31 | 
  
 |  | 
| 
 32 | 
  
 |      | 
| 
 33 | 
  
 |     static protected final int UNKNOWN = 0; | 
| 
 34 | 
  
 |     static protected final int ROUTE_ADDR = 1; | 
| 
 35 | 
  
 |     static protected final int GROUP_ADDR = 2; | 
| 
 36 | 
  
 |     static protected final int SIMPLE_ADDR = 3; | 
| 
 37 | 
  
 |  | 
| 
 38 | 
  
 |      | 
| 
 39 | 
  
 |     static protected final int END_OF_TOKENS = '\0'; | 
| 
 40 | 
  
 |     static protected final int PERIOD = '.'; | 
| 
 41 | 
  
 |     static protected final int LEFT_ANGLE = '<'; | 
| 
 42 | 
  
 |     static protected final int RIGHT_ANGLE = '>'; | 
| 
 43 | 
  
 |     static protected final int COMMA = ','; | 
| 
 44 | 
  
 |     static protected final int AT_SIGN = '@'; | 
| 
 45 | 
  
 |     static protected final int SEMICOLON = ';'; | 
| 
 46 | 
  
 |     static protected final int COLON = ':'; | 
| 
 47 | 
  
 |     static protected final int QUOTED_LITERAL = '"'; | 
| 
 48 | 
  
 |     static protected final int DOMAIN_LITERAL = '['; | 
| 
 49 | 
  
 |     static protected final int COMMENT = '('; | 
| 
 50 | 
  
 |     static protected final int ATOM = 'A'; | 
| 
 51 | 
  
 |     static protected final int WHITESPACE = ' '; | 
| 
 52 | 
  
 |  | 
| 
 53 | 
  
 |  | 
| 
 54 | 
  
 |      | 
| 
 55 | 
  
 |     private String addresses; | 
| 
 56 | 
  
 |      | 
| 
 57 | 
  
 |     private int    position; | 
| 
 58 | 
  
 |      | 
| 
 59 | 
  
 |     private int    end; | 
| 
 60 | 
  
 |      | 
| 
 61 | 
  
 |     private int validationLevel; | 
| 
 62 | 
  
 |  | 
| 
 63 | 
 326
 |     public AddressParser(String addresses, int validation) {
 | 
| 
 64 | 
 326
 |         this.addresses = addresses;
 | 
| 
 65 | 
 326
 |         validationLevel = validation;
 | 
| 
 66 | 
  
 |     } | 
| 
 67 | 
  
 |  | 
| 
 68 | 
  
 |  | 
| 
 69 | 
  
 |      | 
| 
 70 | 
  
 |  | 
| 
 71 | 
  
 |  | 
| 
 72 | 
  
 |  | 
| 
 73 | 
  
 |  | 
| 
 74 | 
  
 |  | 
| 
 75 | 
  
 |  | 
| 
 76 | 
 187
 |     public InternetAddress[] parseAddressList() throws AddressException
 | 
| 
 77 | 
  
 |     { | 
| 
 78 | 
  
 |          | 
| 
 79 | 
 187
 |         TokenStream tokens = tokenizeAddress();
 | 
| 
 80 | 
  
 |  | 
| 
 81 | 
  
 |          | 
| 
 82 | 
 179
 |         ArrayList addressList = new ArrayList();
 | 
| 
 83 | 
  
 |  | 
| 
 84 | 
  
 |          | 
| 
 85 | 
 179
 |         while (true) {
 | 
| 
 86 | 
  
 |              | 
| 
 87 | 
  
 |              | 
| 
 88 | 
  
 |              | 
| 
 89 | 
 199
 |             addressList.addAll(parseSingleAddress(tokens, false));
 | 
| 
 90 | 
  
 |              | 
| 
 91 | 
  
 |              | 
| 
 92 | 
 189
 |             AddressToken token = tokens.nextToken();
 | 
| 
 93 | 
 189
 |             if (token.type == END_OF_TOKENS) {
 | 
| 
 94 | 
 169
 |                 break;
 | 
| 
 95 | 
  
 |             } | 
| 
 96 | 
  
 |         } | 
| 
 97 | 
  
 |  | 
| 
 98 | 
 169
 |         return (InternetAddress [])addressList.toArray(new InternetAddress[0]);
 | 
| 
 99 | 
  
 |     } | 
| 
 100 | 
  
 |  | 
| 
 101 | 
  
 |  | 
| 
 102 | 
  
 |      | 
| 
 103 | 
  
 |  | 
| 
 104 | 
  
 |  | 
| 
 105 | 
  
 |  | 
| 
 106 | 
  
 |  | 
| 
 107 | 
  
 |  | 
| 
 108 | 
 107
 |     public InternetAddress parseAddress() throws AddressException
 | 
| 
 109 | 
  
 |     { | 
| 
 110 | 
  
 |          | 
| 
 111 | 
 107
 |         TokenStream tokens = tokenizeAddress();
 | 
| 
 112 | 
  
 |  | 
| 
 113 | 
  
 |          | 
| 
 114 | 
  
 |          | 
| 
 115 | 
  
 |          | 
| 
 116 | 
 107
 |         List addressList = parseSingleAddress(tokens, false);
 | 
| 
 117 | 
  
 |          | 
| 
 118 | 
 107
 |         if (addressList.isEmpty()) {
 | 
| 
 119 | 
 0
 |             throw new AddressException("Null address", addresses, 0);
 | 
| 
 120 | 
  
 |         } | 
| 
 121 | 
  
 |          | 
| 
 122 | 
 107
 |         if (addressList.size() > 1) {
 | 
| 
 123 | 
 0
 |             throw new AddressException("Illegal Address", addresses, 0);
 | 
| 
 124 | 
  
 |         } | 
| 
 125 | 
  
 |  | 
| 
 126 | 
  
 |          | 
| 
 127 | 
 107
 |         AddressToken token = tokens.nextToken();
 | 
| 
 128 | 
 107
 |         if (token.type != END_OF_TOKENS) {
 | 
| 
 129 | 
 0
 |             illegalAddress("Illegal Address", token);
 | 
| 
 130 | 
  
 |         } | 
| 
 131 | 
  
 |  | 
| 
 132 | 
 107
 |         return (InternetAddress)addressList.get(0);
 | 
| 
 133 | 
  
 |     } | 
| 
 134 | 
  
 |  | 
| 
 135 | 
  
 |  | 
| 
 136 | 
  
 |      | 
| 
 137 | 
  
 |  | 
| 
 138 | 
  
 |  | 
| 
 139 | 
  
 |  | 
| 
 140 | 
  
 |  | 
| 
 141 | 
  
 |  | 
| 
 142 | 
  
 |  | 
| 
 143 | 
 18
 |     public void validateAddress() throws AddressException
 | 
| 
 144 | 
  
 |     { | 
| 
 145 | 
  
 |          | 
| 
 146 | 
 18
 |         TokenStream tokens = tokenizeAddress();
 | 
| 
 147 | 
  
 |  | 
| 
 148 | 
  
 |          | 
| 
 149 | 
  
 |          | 
| 
 150 | 
  
 |          | 
| 
 151 | 
 17
 |         List addressList = parseSingleAddress(tokens, false);
 | 
| 
 152 | 
 11
 |         if (addressList.isEmpty()) {
 | 
| 
 153 | 
 0
 |             throw new AddressException("Null address", addresses, 0);
 | 
| 
 154 | 
  
 |         } | 
| 
 155 | 
  
 |  | 
| 
 156 | 
  
 |          | 
| 
 157 | 
 11
 |         if (addressList.size() > 1) {
 | 
| 
 158 | 
 0
 |             throw new AddressException("Illegal Address", addresses, 0);
 | 
| 
 159 | 
  
 |         } | 
| 
 160 | 
  
 |  | 
| 
 161 | 
 11
 |         InternetAddress address = (InternetAddress)addressList.get(0);
 | 
| 
 162 | 
  
 |  | 
| 
 163 | 
  
 |          | 
| 
 164 | 
  
 |          | 
| 
 165 | 
 11
 |         if (address.personal != null) {
 | 
| 
 166 | 
 0
 |             throw new AddressException("Illegal Address", addresses, 0);
 | 
| 
 167 | 
  
 |         } | 
| 
 168 | 
  
 |          | 
| 
 169 | 
 11
 |         AddressToken token = tokens.nextToken();
 | 
| 
 170 | 
 11
 |         if (token.type != END_OF_TOKENS) {
 | 
| 
 171 | 
 0
 |             illegalAddress("Illegal Address", token);
 | 
| 
 172 | 
  
 |         } | 
| 
 173 | 
  
 |     } | 
| 
 174 | 
  
 |  | 
| 
 175 | 
  
 |  | 
| 
 176 | 
  
 |      | 
| 
 177 | 
  
 |  | 
| 
 178 | 
  
 |  | 
| 
 179 | 
  
 |  | 
| 
 180 | 
  
 |  | 
| 
 181 | 
  
 |  | 
| 
 182 | 
 14
 |     public InternetAddress[] extractGroupList() throws AddressException
 | 
| 
 183 | 
  
 |     { | 
| 
 184 | 
  
 |          | 
| 
 185 | 
 14
 |         TokenStream tokens = tokenizeAddress();
 | 
| 
 186 | 
  
 |  | 
| 
 187 | 
  
 |          | 
| 
 188 | 
 14
 |         ArrayList addresses = new ArrayList();
 | 
| 
 189 | 
  
 |  | 
| 
 190 | 
 14
 |         AddressToken token = tokens.nextToken();
 | 
| 
 191 | 
  
 |  | 
| 
 192 | 
  
 |          | 
| 
 193 | 
  
 |          | 
| 
 194 | 
 14
 |         while (token.type != COLON) {
 | 
| 
 195 | 
 14
 |             if (token.type == END_OF_TOKENS) {
 | 
| 
 196 | 
 0
 |                 illegalAddress("Missing ':'", token);
 | 
| 
 197 | 
  
 |             } | 
| 
 198 | 
 14
 |             token = tokens.nextToken();
 | 
| 
 199 | 
  
 |         } | 
| 
 200 | 
  
 |  | 
| 
 201 | 
  
 |          | 
| 
 202 | 
 14
 |         while (true) {
 | 
| 
 203 | 
  
 |              | 
| 
 204 | 
  
 |              | 
| 
 205 | 
  
 |              | 
| 
 206 | 
 26
 |             addresses.addAll(parseSingleAddress(tokens, true));
 | 
| 
 207 | 
  
 |              | 
| 
 208 | 
  
 |              | 
| 
 209 | 
 26
 |             token = tokens.nextToken();
 | 
| 
 210 | 
 26
 |             if (token.type == SEMICOLON) {
 | 
| 
 211 | 
 14
 |                 break;
 | 
| 
 212 | 
  
 |             } | 
| 
 213 | 
 12
 |             else if (token.type == END_OF_TOKENS) {
 | 
| 
 214 | 
 0
 |                 illegalAddress("Missing ';'", token);
 | 
| 
 215 | 
  
 |             } | 
| 
 216 | 
  
 |         } | 
| 
 217 | 
  
 |  | 
| 
 218 | 
 14
 |         return (InternetAddress [])addresses.toArray(new InternetAddress[0]);
 | 
| 
 219 | 
  
 |     } | 
| 
 220 | 
  
 |  | 
| 
 221 | 
  
 |  | 
| 
 222 | 
  
 |      | 
| 
 223 | 
  
 |  | 
| 
 224 | 
  
 |  | 
| 
 225 | 
  
 |  | 
| 
 226 | 
  
 |  | 
| 
 227 | 
  
 |  | 
| 
 228 | 
  
 |  | 
| 
 229 | 
  
 |  | 
| 
 230 | 
  
 |  | 
| 
 231 | 
  
 |  | 
| 
 232 | 
  
 |  | 
| 
 233 | 
  
 |  | 
| 
 234 | 
 349
 |     private List parseSingleAddress(TokenStream tokens, boolean inGroup) throws AddressException
 | 
| 
 235 | 
  
 |     { | 
| 
 236 | 
 349
 |         List parsedAddresses = new ArrayList();
 | 
| 
 237 | 
  
 |  | 
| 
 238 | 
  
 |          | 
| 
 239 | 
 349
 |         AddressToken personalStart = null;
 | 
| 
 240 | 
 349
 |         AddressToken personalEnd = null;
 | 
| 
 241 | 
  
 |  | 
| 
 242 | 
  
 |          | 
| 
 243 | 
 349
 |         AddressToken addressStart = null;
 | 
| 
 244 | 
 349
 |         AddressToken addressEnd = null;
 | 
| 
 245 | 
  
 |  | 
| 
 246 | 
  
 |          | 
| 
 247 | 
  
 |          | 
| 
 248 | 
  
 |          | 
| 
 249 | 
 349
 |         boolean nonStrictRules = true;
 | 
| 
 250 | 
  
 |  | 
| 
 251 | 
  
 |          | 
| 
 252 | 
 349
 |         int addressType = UNKNOWN;
 | 
| 
 253 | 
  
 |  | 
| 
 254 | 
  
 |          | 
| 
 255 | 
  
 |          | 
| 
 256 | 
  
 |          | 
| 
 257 | 
  
 |          | 
| 
 258 | 
  
 |  | 
| 
 259 | 
  
 |          | 
| 
 260 | 
  
 |          | 
| 
 261 | 
  
 |          | 
| 
 262 | 
 349
 |         AddressToken first = tokens.nextToken();
 | 
| 
 263 | 
  
 |          | 
| 
 264 | 
 349
 |         tokens.pushToken(first);
 | 
| 
 265 | 
  
 |  | 
| 
 266 | 
  
 |          | 
| 
 267 | 
 349
 |         while (addressType == UNKNOWN) {
 | 
| 
 268 | 
  
 |  | 
| 
 269 | 
 1458
 |             AddressToken token = tokens.nextToken();
 | 
| 
 270 | 
 1458
 |             switch (token.type) {
 | 
| 
 271 | 
  
 |                  | 
| 
 272 | 
  
 |                  | 
| 
 273 | 
  
 |                  | 
| 
 274 | 
 53
 |                 case COMMENT:
 | 
| 
 275 | 
  
 |                      | 
| 
 276 | 
 53
 |                     nonStrictRules = false;
 | 
| 
 277 | 
 53
 |                     break;
 | 
| 
 278 | 
  
 |  | 
| 
 279 | 
  
 |                  | 
| 
 280 | 
  
 |                  | 
| 
 281 | 
 14
 |                 case SEMICOLON:
 | 
| 
 282 | 
 14
 |                     if (inGroup) {
 | 
| 
 283 | 
  
 |                          | 
| 
 284 | 
 14
 |                         tokens.pushToken(token);
 | 
| 
 285 | 
  
 |                          | 
| 
 286 | 
  
 |                          | 
| 
 287 | 
 14
 |                         if (addressStart == null) {
 | 
| 
 288 | 
  
 |                              | 
| 
 289 | 
 2
 |                             return parsedAddresses;
 | 
| 
 290 | 
  
 |                         } | 
| 
 291 | 
  
 |                          | 
| 
 292 | 
 12
 |                         addressEnd = tokens.previousToken(token);
 | 
| 
 293 | 
  
 |                          | 
| 
 294 | 
  
 |                          | 
| 
 295 | 
 12
 |                         personalStart = null;
 | 
| 
 296 | 
  
 |                          | 
| 
 297 | 
 12
 |                         addressType = SIMPLE_ADDR;
 | 
| 
 298 | 
 12
 |                         break;
 | 
| 
 299 | 
  
 |                     } | 
| 
 300 | 
  
 |  | 
| 
 301 | 
  
 |                  | 
| 
 302 | 
  
 |  | 
| 
 303 | 
  
 |                  | 
| 
 304 | 
  
 |                  | 
| 
 305 | 
  
 |                  | 
| 
 306 | 
 25
 |                 case DOMAIN_LITERAL:
 | 
| 
 307 | 
 42
 |                 case QUOTED_LITERAL:
 | 
| 
 308 | 
  
 |                      | 
| 
 309 | 
 67
 |                     nonStrictRules = false;
 | 
| 
 310 | 
  
 |  | 
| 
 311 | 
 615
 |                 case ATOM:
 | 
| 
 312 | 
 169
 |                 case AT_SIGN:
 | 
| 
 313 | 
 205
 |                 case PERIOD:
 | 
| 
 314 | 
  
 |                      | 
| 
 315 | 
  
 |                      | 
| 
 316 | 
 1056
 |                     if (addressStart == null) {
 | 
| 
 317 | 
 275
 |                         if (personalStart == null) {
 | 
| 
 318 | 
 275
 |                             personalStart = token;
 | 
| 
 319 | 
  
 |                         } | 
| 
 320 | 
  
 |                          | 
| 
 321 | 
  
 |                          | 
| 
 322 | 
  
 |                          | 
| 
 323 | 
  
 |                          | 
| 
 324 | 
 275
 |                         addressStart = token;
 | 
| 
 325 | 
  
 |                     } | 
| 
 326 | 
 1056
 |                     break;
 | 
| 
 327 | 
  
 |  | 
| 
 328 | 
  
 |                  | 
| 
 329 | 
  
 |                  | 
| 
 330 | 
 102
 |                 case LEFT_ANGLE:
 | 
| 
 331 | 
  
 |                      | 
| 
 332 | 
 102
 |                     nonStrictRules = false;
 | 
| 
 333 | 
  
 |                      | 
| 
 334 | 
 102
 |                     addressType = ROUTE_ADDR;
 | 
| 
 335 | 
  
 |                      | 
| 
 336 | 
  
 |                      | 
| 
 337 | 
 102
 |                     addressStart = tokens.nextRealToken();
 | 
| 
 338 | 
  
 |                      | 
| 
 339 | 
 102
 |                     tokens.pushToken(addressStart);
 | 
| 
 340 | 
  
 |                      | 
| 
 341 | 
 102
 |                     if (personalStart != null) {
 | 
| 
 342 | 
 45
 |                         personalEnd = tokens.previousToken(token);
 | 
| 
 343 | 
  
 |                     } | 
| 
 344 | 
  
 |                      | 
| 
 345 | 
 102
 |                     addressEnd = scanRouteAddress(tokens, false);
 | 
| 
 346 | 
 100
 |                     break;
 | 
| 
 347 | 
  
 |  | 
| 
 348 | 
  
 |                  | 
| 
 349 | 
 35
 |                 case COLON:
 | 
| 
 350 | 
  
 |                      | 
| 
 351 | 
 35
 |                     nonStrictRules = false;
 | 
| 
 352 | 
  
 |                      | 
| 
 353 | 
  
 |                      | 
| 
 354 | 
 35
 |                     if (inGroup) {
 | 
| 
 355 | 
 0
 |                         illegalAddress("Nested group element", token);
 | 
| 
 356 | 
  
 |                     } | 
| 
 357 | 
 35
 |                     addressType = GROUP_ADDR;
 | 
| 
 358 | 
  
 |                      | 
| 
 359 | 
 35
 |                     personalStart = null;
 | 
| 
 360 | 
  
 |                      | 
| 
 361 | 
 35
 |                     addressStart = first;
 | 
| 
 362 | 
 35
 |                     addressEnd = scanGroupAddress(tokens);
 | 
| 
 363 | 
 32
 |                     break;
 | 
| 
 364 | 
  
 |  | 
| 
 365 | 
  
 |                  | 
| 
 366 | 
  
 |  | 
| 
 367 | 
  
 |  | 
| 
 368 | 
  
 |                  | 
| 
 369 | 
  
 |                  | 
| 
 370 | 
 177
 |                 case END_OF_TOKENS:
 | 
| 
 371 | 
  
 |                      | 
| 
 372 | 
  
 |                      | 
| 
 373 | 
 177
 |                     if (inGroup) {
 | 
| 
 374 | 
 0
 |                         illegalAddress("Missing ';'", token);
 | 
| 
 375 | 
  
 |                     } | 
| 
 376 | 
  
 |  | 
| 
 377 | 
  
 |                      | 
| 
 378 | 
  
 |  | 
| 
 379 | 
  
 |                  | 
| 
 380 | 
 21
 |                 case COMMA:
 | 
| 
 381 | 
  
 |                      | 
| 
 382 | 
 198
 |                     tokens.pushToken(token);
 | 
| 
 383 | 
  
 |                      | 
| 
 384 | 
  
 |                      | 
| 
 385 | 
 198
 |                     if (addressStart == null) {
 | 
| 
 386 | 
  
 |                          | 
| 
 387 | 
 14
 |                         return parsedAddresses;
 | 
| 
 388 | 
  
 |                     } | 
| 
 389 | 
  
 |                      | 
| 
 390 | 
 184
 |                     addressEnd = tokens.previousToken(token);
 | 
| 
 391 | 
  
 |                      | 
| 
 392 | 
  
 |                      | 
| 
 393 | 
 184
 |                     personalStart = null;
 | 
| 
 394 | 
  
 |                      | 
| 
 395 | 
 184
 |                     addressType = SIMPLE_ADDR;
 | 
| 
 396 | 
 184
 |                     break;
 | 
| 
 397 | 
  
 |  | 
| 
 398 | 
  
 |                  | 
| 
 399 | 
  
 |                  | 
| 
 400 | 
 0
 |                 case RIGHT_ANGLE:
 | 
| 
 401 | 
 0
 |                     illegalAddress("Unexpected '>'", token);
 | 
| 
 402 | 
  
 |  | 
| 
 403 | 
  
 |             } | 
| 
 404 | 
  
 |         } | 
| 
 405 | 
  
 |  | 
| 
 406 | 
 328
 |         String personal = null;
 | 
| 
 407 | 
  
 |  | 
| 
 408 | 
  
 |          | 
| 
 409 | 
 328
 |         if (personalStart != null) {
 | 
| 
 410 | 
 44
 |             TokenStream personalTokens = tokens.section(personalStart, personalEnd);
 | 
| 
 411 | 
 44
 |             personal = personalToString(personalTokens);
 | 
| 
 412 | 
  
 |         } | 
| 
 413 | 
  
 |          | 
| 
 414 | 
  
 |          | 
| 
 415 | 
  
 |         else { | 
| 
 416 | 
 284
 |             if (addressType == SIMPLE_ADDR && first.type == COMMENT) {
 | 
| 
 417 | 
 19
 |                 personal = first.value;
 | 
| 
 418 | 
  
 |             } | 
| 
 419 | 
  
 |         } | 
| 
 420 | 
  
 |  | 
| 
 421 | 
 328
 |         TokenStream addressTokens = tokens.section(addressStart, addressEnd);
 | 
| 
 422 | 
  
 |  | 
| 
 423 | 
  
 |          | 
| 
 424 | 
  
 |          | 
| 
 425 | 
  
 |          | 
| 
 426 | 
 328
 |         if (validationLevel != PARSE_HEADER) {
 | 
| 
 427 | 
 308
 |             switch (addressType) {
 | 
| 
 428 | 
 31
 |                 case GROUP_ADDR:
 | 
| 
 429 | 
 31
 |                     validateGroup(addressTokens);
 | 
| 
 430 | 
 30
 |                     break;
 | 
| 
 431 | 
  
 |  | 
| 
 432 | 
 91
 |                 case ROUTE_ADDR:
 | 
| 
 433 | 
 91
 |                     validateRouteAddr(addressTokens, false);
 | 
| 
 434 | 
 90
 |                     break;
 | 
| 
 435 | 
  
 |  | 
| 
 436 | 
 186
 |                 case SIMPLE_ADDR:
 | 
| 
 437 | 
  
 |                      | 
| 
 438 | 
 186
 |                     validateSimpleAddress(addressTokens);
 | 
| 
 439 | 
 177
 |                     break;
 | 
| 
 440 | 
  
 |             } | 
| 
 441 | 
  
 |         } | 
| 
 442 | 
  
 |  | 
| 
 443 | 
  
 |          | 
| 
 444 | 
  
 |          | 
| 
 445 | 
 317
 |         if (validationLevel != NONSTRICT || addressType != SIMPLE_ADDR || !nonStrictRules) {
 | 
| 
 446 | 
  
 |              | 
| 
 447 | 
  
 |              | 
| 
 448 | 
 302
 |             addressTokens.reset();
 | 
| 
 449 | 
 302
 |             String address = addressToString(addressTokens);
 | 
| 
 450 | 
  
 |  | 
| 
 451 | 
  
 |              | 
| 
 452 | 
 302
 |             InternetAddress result = new InternetAddress();
 | 
| 
 453 | 
 302
 |             result.setAddress(address);
 | 
| 
 454 | 
 302
 |             try {
 | 
| 
 455 | 
 302
 |                 result.setPersonal(personal);
 | 
| 
 456 | 
  
 |             } catch (UnsupportedEncodingException e) { | 
| 
 457 | 
  
 |             } | 
| 
 458 | 
  
 |              | 
| 
 459 | 
  
 |              | 
| 
 460 | 
 302
 |             parsedAddresses.add(result);
 | 
| 
 461 | 
 302
 |             return parsedAddresses;
 | 
| 
 462 | 
  
 |         } | 
| 
 463 | 
  
 |         else { | 
| 
 464 | 
 15
 |             addressTokens.reset();
 | 
| 
 465 | 
  
 |  | 
| 
 466 | 
 15
 |             TokenStream nextAddress = addressTokens.getBlankDelimitedToken();
 | 
| 
 467 | 
 15
 |             while (nextAddress != null) {
 | 
| 
 468 | 
 15
 |                 String address = addressToString(nextAddress);
 | 
| 
 469 | 
  
 |                  | 
| 
 470 | 
 15
 |                 InternetAddress result = new InternetAddress();
 | 
| 
 471 | 
 15
 |                 result.setAddress(address);
 | 
| 
 472 | 
 15
 |                 parsedAddresses.add(result);
 | 
| 
 473 | 
 15
 |                 nextAddress = addressTokens.getBlankDelimitedToken();
 | 
| 
 474 | 
  
 |             } | 
| 
 475 | 
 15
 |             return parsedAddresses;
 | 
| 
 476 | 
  
 |         } | 
| 
 477 | 
  
 |     } | 
| 
 478 | 
  
 |  | 
| 
 479 | 
  
 |  | 
| 
 480 | 
  
 |      | 
| 
 481 | 
  
 |  | 
| 
 482 | 
  
 |  | 
| 
 483 | 
  
 |  | 
| 
 484 | 
  
 |  | 
| 
 485 | 
  
 |  | 
| 
 486 | 
  
 |  | 
| 
 487 | 
  
 |  | 
| 
 488 | 
  
 |  | 
| 
 489 | 
  
 |  | 
| 
 490 | 
  
 |  | 
| 
 491 | 
 114
 |     private AddressToken scanRouteAddress(TokenStream tokens, boolean inGroup) throws AddressException {
 | 
| 
 492 | 
  
 |          | 
| 
 493 | 
 114
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 494 | 
  
 |          | 
| 
 495 | 
  
 |          | 
| 
 496 | 
  
 |  | 
| 
 497 | 
 114
 |         AddressToken previous = null;
 | 
| 
 498 | 
  
 |  | 
| 
 499 | 
  
 |          | 
| 
 500 | 
  
 |          | 
| 
 501 | 
 114
 |         boolean inRoute = token.type == AT_SIGN;
 | 
| 
 502 | 
  
 |  | 
| 
 503 | 
  
 |          | 
| 
 504 | 
 114
 |         while (true) {
 | 
| 
 505 | 
 927
 |             switch (token.type) {
 | 
| 
 506 | 
  
 |                  | 
| 
 507 | 
 437
 |                 case ATOM:
 | 
| 
 508 | 
 4
 |                 case QUOTED_LITERAL:
 | 
| 
 509 | 
 7
 |                 case DOMAIN_LITERAL:
 | 
| 
 510 | 
 191
 |                 case PERIOD:
 | 
| 
 511 | 
 143
 |                 case AT_SIGN:
 | 
| 
 512 | 
 782
 |                     break;
 | 
| 
 513 | 
  
 |  | 
| 
 514 | 
 22
 |                 case COLON:
 | 
| 
 515 | 
  
 |                      | 
| 
 516 | 
 22
 |                     if (!inRoute) {
 | 
| 
 517 | 
 0
 |                         illegalAddress("Unexpected ':'", token);
 | 
| 
 518 | 
  
 |                     } | 
| 
 519 | 
  
 |                      | 
| 
 520 | 
 22
 |                     inRoute = false;
 | 
| 
 521 | 
 22
 |                     break;
 | 
| 
 522 | 
  
 |  | 
| 
 523 | 
 10
 |                 case COMMA:
 | 
| 
 524 | 
  
 |                      | 
| 
 525 | 
 10
 |                     if (!inRoute) {
 | 
| 
 526 | 
 1
 |                         illegalAddress("Unexpected ','", token);
 | 
| 
 527 | 
  
 |                     } | 
| 
 528 | 
 9
 |                     break;
 | 
| 
 529 | 
  
 |  | 
| 
 530 | 
 111
 |                 case RIGHT_ANGLE:
 | 
| 
 531 | 
  
 |                      | 
| 
 532 | 
 111
 |                     if (previous == null) {
 | 
| 
 533 | 
 0
 |                         illegalAddress("Illegal address", token);
 | 
| 
 534 | 
  
 |                     } | 
| 
 535 | 
  
 |                      | 
| 
 536 | 
  
 |                      | 
| 
 537 | 
 111
 |                     token = tokens.nextRealToken();
 | 
| 
 538 | 
  
 |                      | 
| 
 539 | 
 111
 |                     if (inGroup) {
 | 
| 
 540 | 
 11
 |                         if (token.type != COMMA && token.type != SEMICOLON) {
 | 
| 
 541 | 
 0
 |                             illegalAddress("Illegal address", token);
 | 
| 
 542 | 
  
 |                         } | 
| 
 543 | 
  
 |                     } | 
| 
 544 | 
  
 |                      | 
| 
 545 | 
  
 |                     else { | 
| 
 546 | 
 100
 |                         if (token.type != COMMA && token.type != END_OF_TOKENS) {
 | 
| 
 547 | 
 0
 |                             illegalAddress("Illegal address", token);
 | 
| 
 548 | 
  
 |                         } | 
| 
 549 | 
  
 |                     } | 
| 
 550 | 
  
 |                      | 
| 
 551 | 
 111
 |                     tokens.pushToken(token);
 | 
| 
 552 | 
  
 |                      | 
| 
 553 | 
 111
 |                     return previous;
 | 
| 
 554 | 
  
 |  | 
| 
 555 | 
 1
 |                 case END_OF_TOKENS:
 | 
| 
 556 | 
 1
 |                     illegalAddress("Missing '>'", token);
 | 
| 
 557 | 
  
 |  | 
| 
 558 | 
  
 |                  | 
| 
 559 | 
 0
 |                 case SEMICOLON:
 | 
| 
 560 | 
 0
 |                     illegalAddress("Unexpected ';'", token);
 | 
| 
 561 | 
  
 |  | 
| 
 562 | 
 1
 |                 case LEFT_ANGLE:
 | 
| 
 563 | 
 1
 |                     illegalAddress("Unexpected '<'", token);
 | 
| 
 564 | 
  
 |             } | 
| 
 565 | 
  
 |              | 
| 
 566 | 
 813
 |             previous = token;
 | 
| 
 567 | 
 813
 |             token = tokens.nextRealToken();
 | 
| 
 568 | 
  
 |         } | 
| 
 569 | 
  
 |     } | 
| 
 570 | 
  
 |  | 
| 
 571 | 
  
 |  | 
| 
 572 | 
  
 |      | 
| 
 573 | 
  
 |  | 
| 
 574 | 
  
 |  | 
| 
 575 | 
  
 |  | 
| 
 576 | 
  
 |  | 
| 
 577 | 
  
 |  | 
| 
 578 | 
  
 |  | 
| 
 579 | 
  
 |  | 
| 
 580 | 
  
 |  | 
| 
 581 | 
  
 |  | 
| 
 582 | 
 35
 |     private AddressToken scanGroupAddress(TokenStream tokens) throws AddressException {
 | 
| 
 583 | 
  
 |          | 
| 
 584 | 
  
 |          | 
| 
 585 | 
 35
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 586 | 
  
 |  | 
| 
 587 | 
  
 |          | 
| 
 588 | 
 35
 |         while (true) {
 | 
| 
 589 | 
 199
 |             switch (token.type) {
 | 
| 
 590 | 
  
 |                  | 
| 
 591 | 
 83
 |                 case ATOM:
 | 
| 
 592 | 
 0
 |                 case QUOTED_LITERAL:
 | 
| 
 593 | 
 0
 |                 case DOMAIN_LITERAL:
 | 
| 
 594 | 
 25
 |                 case PERIOD:
 | 
| 
 595 | 
 25
 |                 case AT_SIGN:
 | 
| 
 596 | 
 20
 |                 case COMMA:
 | 
| 
 597 | 
 153
 |                     break;
 | 
| 
 598 | 
  
 |  | 
| 
 599 | 
 1
 |                 case COLON:
 | 
| 
 600 | 
 1
 |                      illegalAddress("Nested group", token);
 | 
| 
 601 | 
  
 |  | 
| 
 602 | 
  
 |                  | 
| 
 603 | 
  
 |                  | 
| 
 604 | 
 12
 |                 case LEFT_ANGLE:
 | 
| 
 605 | 
 12
 |                     scanRouteAddress(tokens, true);
 | 
| 
 606 | 
 11
 |                     break;
 | 
| 
 607 | 
  
 |  | 
| 
 608 | 
  
 |                  | 
| 
 609 | 
 1
 |                 case END_OF_TOKENS:
 | 
| 
 610 | 
 1
 |                     illegalAddress("Missing ';'", token);
 | 
| 
 611 | 
  
 |  | 
| 
 612 | 
  
 |                  | 
| 
 613 | 
 32
 |                 case SEMICOLON:
 | 
| 
 614 | 
  
 |                      | 
| 
 615 | 
 32
 |                     AddressToken next = tokens.nextRealToken();
 | 
| 
 616 | 
 32
 |                     if (next.type != COMMA && next.type != END_OF_TOKENS) {
 | 
| 
 617 | 
 0
 |                         illegalAddress("Illegal address", token);
 | 
| 
 618 | 
  
 |                     } | 
| 
 619 | 
  
 |                      | 
| 
 620 | 
 32
 |                     tokens.pushToken(next);
 | 
| 
 621 | 
 32
 |                     return token;
 | 
| 
 622 | 
  
 |  | 
| 
 623 | 
 0
 |                 case RIGHT_ANGLE:
 | 
| 
 624 | 
 0
 |                     illegalAddress("Unexpected '>'", token);
 | 
| 
 625 | 
  
 |             } | 
| 
 626 | 
 164
 |             token = tokens.nextRealToken();
 | 
| 
 627 | 
  
 |         } | 
| 
 628 | 
  
 |     } | 
| 
 629 | 
  
 |  | 
| 
 630 | 
  
 |  | 
| 
 631 | 
  
 |      | 
| 
 632 | 
  
 |  | 
| 
 633 | 
  
 |  | 
| 
 634 | 
  
 |  | 
| 
 635 | 
  
 |  | 
| 
 636 | 
  
 |  | 
| 
 637 | 
  
 |  | 
| 
 638 | 
 326
 |     private TokenStream tokenizeAddress() throws AddressException {
 | 
| 
 639 | 
  
 |  | 
| 
 640 | 
  
 |          | 
| 
 641 | 
 326
 |         TokenStream tokens = new TokenStream();
 | 
| 
 642 | 
  
 |  | 
| 
 643 | 
 326
 |         end = addresses.length();    
 | 
| 
 644 | 
  
 |  | 
| 
 645 | 
  
 |          | 
| 
 646 | 
 326
 |         while (moreCharacters()) {
 | 
| 
 647 | 
 2624
 |             char ch = currentChar();
 | 
| 
 648 | 
  
 |  | 
| 
 649 | 
 2624
 |             switch (ch) {
 | 
| 
 650 | 
  
 |                  | 
| 
 651 | 
 55
 |                 case '(':
 | 
| 
 652 | 
 55
 |                     scanComment(tokens);
 | 
| 
 653 | 
 53
 |                     break;
 | 
| 
 654 | 
  
 |                  | 
| 
 655 | 
 0
 |                 case ')':
 | 
| 
 656 | 
 0
 |                     syntaxError("Unexpected ')'", position);
 | 
| 
 657 | 
  
 |  | 
| 
 658 | 
  
 |  | 
| 
 659 | 
  
 |                  | 
| 
 660 | 
 48
 |                 case '"':
 | 
| 
 661 | 
 48
 |                     scanQuotedLiteral(tokens);
 | 
| 
 662 | 
 46
 |                     break;
 | 
| 
 663 | 
  
 |                  | 
| 
 664 | 
 37
 |                 case '[':
 | 
| 
 665 | 
 37
 |                     scanDomainLiteral(tokens);
 | 
| 
 666 | 
 32
 |                     break;
 | 
| 
 667 | 
  
 |  | 
| 
 668 | 
  
 |                  | 
| 
 669 | 
 0
 |                 case ']':
 | 
| 
 670 | 
 0
 |                     syntaxError("Unexpected ']'", position);
 | 
| 
 671 | 
  
 |  | 
| 
 672 | 
  
 |                  | 
| 
 673 | 
 119
 |                 case '<':
 | 
| 
 674 | 
 119
 |                     tokens.addToken(new AddressToken(LEFT_ANGLE, position));
 | 
| 
 675 | 
 119
 |                     nextChar();
 | 
| 
 676 | 
 119
 |                     break;
 | 
| 
 677 | 
  
 |  | 
| 
 678 | 
  
 |                  | 
| 
 679 | 
  
 |                  | 
| 
 680 | 
 112
 |                 case '>':
 | 
| 
 681 | 
 112
 |                     tokens.addToken(new AddressToken(RIGHT_ANGLE, position));
 | 
| 
 682 | 
 112
 |                     nextChar();
 | 
| 
 683 | 
 112
 |                     break;
 | 
| 
 684 | 
 72
 |                 case ':':
 | 
| 
 685 | 
 72
 |                     tokens.addToken(new AddressToken(COLON, position));
 | 
| 
 686 | 
 72
 |                     nextChar();
 | 
| 
 687 | 
 72
 |                     break;
 | 
| 
 688 | 
 62
 |                 case ',':
 | 
| 
 689 | 
 62
 |                     tokens.addToken(new AddressToken(COMMA, position));
 | 
| 
 690 | 
 62
 |                     nextChar();
 | 
| 
 691 | 
 62
 |                     break;
 | 
| 
 692 | 
 424
 |                 case '.':
 | 
| 
 693 | 
 424
 |                     tokens.addToken(new AddressToken(PERIOD, position));
 | 
| 
 694 | 
 424
 |                     nextChar();
 | 
| 
 695 | 
 424
 |                     break;
 | 
| 
 696 | 
 49
 |                 case ';':
 | 
| 
 697 | 
 49
 |                     tokens.addToken(new AddressToken(SEMICOLON, position));
 | 
| 
 698 | 
 49
 |                     nextChar();
 | 
| 
 699 | 
 49
 |                     break;
 | 
| 
 700 | 
 345
 |                 case '@':
 | 
| 
 701 | 
 345
 |                     tokens.addToken(new AddressToken(AT_SIGN, position));
 | 
| 
 702 | 
 345
 |                     nextChar();
 | 
| 
 703 | 
 345
 |                     break;
 | 
| 
 704 | 
  
 |  | 
| 
 705 | 
  
 |                  | 
| 
 706 | 
  
 |                  | 
| 
 707 | 
  
 |                  | 
| 
 708 | 
 138
 |                 case ' ':
 | 
| 
 709 | 
 0
 |                 case '\t':
 | 
| 
 710 | 
 0
 |                 case '\r':
 | 
| 
 711 | 
 0
 |                 case '\n':
 | 
| 
 712 | 
  
 |                      | 
| 
 713 | 
 138
 |                     tokens.addToken(new AddressToken(WHITESPACE, position));
 | 
| 
 714 | 
  
 |  | 
| 
 715 | 
 138
 |                     nextChar();
 | 
| 
 716 | 
  
 |                      | 
| 
 717 | 
  
 |                      | 
| 
 718 | 
 138
 |                     while (moreCharacters()) {
 | 
| 
 719 | 
 138
 |                         char nextChar = currentChar();
 | 
| 
 720 | 
 138
 |                         if (nextChar == ' ' || nextChar == '\t' || nextChar == '\r' || nextChar == '\n') {
 | 
| 
 721 | 
 0
 |                             nextChar();
 | 
| 
 722 | 
  
 |                         } | 
| 
 723 | 
  
 |                         else { | 
| 
 724 | 
 138
 |                             break;
 | 
| 
 725 | 
  
 |                         } | 
| 
 726 | 
  
 |                     } | 
| 
 727 | 
 138
 |                     break;
 | 
| 
 728 | 
  
 |  | 
| 
 729 | 
  
 |                  | 
| 
 730 | 
  
 |                  | 
| 
 731 | 
 1163
 |                 default:
 | 
| 
 732 | 
 1163
 |                     if (ch < 040 || ch >= 0177) {
 | 
| 
 733 | 
 0
 |                         syntaxError("Illegal character in address", position);
 | 
| 
 734 | 
  
 |                     } | 
| 
 735 | 
  
 |  | 
| 
 736 | 
 1163
 |                     scanAtom(tokens);
 | 
| 
 737 | 
 1163
 |                     break;
 | 
| 
 738 | 
  
 |             } | 
| 
 739 | 
  
 |         } | 
| 
 740 | 
  
 |  | 
| 
 741 | 
  
 |          | 
| 
 742 | 
 317
 |         tokens.addToken(new AddressToken(END_OF_TOKENS, addresses.length()));
 | 
| 
 743 | 
 317
 |         return tokens;
 | 
| 
 744 | 
  
 |     } | 
| 
 745 | 
  
 |  | 
| 
 746 | 
  
 |  | 
| 
 747 | 
  
 |      | 
| 
 748 | 
  
 |  | 
| 
 749 | 
  
 |  | 
| 
 750 | 
 7401
 |     private void nextChar() {
 | 
| 
 751 | 
 7401
 |         position++;
 | 
| 
 752 | 
  
 |     } | 
| 
 753 | 
  
 |  | 
| 
 754 | 
  
 |  | 
| 
 755 | 
  
 |      | 
| 
 756 | 
  
 |  | 
| 
 757 | 
  
 |  | 
| 
 758 | 
  
 |  | 
| 
 759 | 
  
 |  | 
| 
 760 | 
 8556
 |     private char currentChar() {
 | 
| 
 761 | 
 8556
 |         return addresses.charAt(position);
 | 
| 
 762 | 
  
 |     } | 
| 
 763 | 
  
 |  | 
| 
 764 | 
  
 |      | 
| 
 765 | 
  
 |  | 
| 
 766 | 
  
 |  | 
| 
 767 | 
  
 |  | 
| 
 768 | 
  
 |  | 
| 
 769 | 
 9028
 |     private boolean moreCharacters() {
 | 
| 
 770 | 
 9028
 |         return position < end;
 | 
| 
 771 | 
  
 |     } | 
| 
 772 | 
  
 |  | 
| 
 773 | 
  
 |  | 
| 
 774 | 
  
 |      | 
| 
 775 | 
  
 |  | 
| 
 776 | 
  
 |  | 
| 
 777 | 
  
 |  | 
| 
 778 | 
  
 |  | 
| 
 779 | 
 48
 |     private void scanQuotedLiteral(TokenStream tokens) throws AddressException {
 | 
| 
 780 | 
 48
 |         StringBuffer value = new StringBuffer();
 | 
| 
 781 | 
  
 |  | 
| 
 782 | 
  
 |          | 
| 
 783 | 
 48
 |         int startPosition = position;
 | 
| 
 784 | 
  
 |          | 
| 
 785 | 
 48
 |         nextChar();
 | 
| 
 786 | 
  
 |  | 
| 
 787 | 
 48
 |         while (moreCharacters()) {
 | 
| 
 788 | 
 292
 |             char ch = currentChar();
 | 
| 
 789 | 
  
 |  | 
| 
 790 | 
  
 |              | 
| 
 791 | 
 292
 |             if (ch == '\\') {
 | 
| 
 792 | 
  
 |                  | 
| 
 793 | 
 13
 |                 nextChar();
 | 
| 
 794 | 
 13
 |                 if (!moreCharacters()) {
 | 
| 
 795 | 
 0
 |                     syntaxError("Missing '\"'", position);
 | 
| 
 796 | 
  
 |                 } | 
| 
 797 | 
 13
 |                 value.append(currentChar());
 | 
| 
 798 | 
  
 |             } | 
| 
 799 | 
  
 |              | 
| 
 800 | 
 279
 |             else if (ch == '"') {
 | 
| 
 801 | 
  
 |                  | 
| 
 802 | 
 46
 |                 tokens.addToken(new AddressToken(value.toString(), QUOTED_LITERAL, position));
 | 
| 
 803 | 
  
 |                  | 
| 
 804 | 
 46
 |                 nextChar();
 | 
| 
 805 | 
 46
 |                 return;
 | 
| 
 806 | 
  
 |             } | 
| 
 807 | 
  
 |              | 
| 
 808 | 
 233
 |             else if (ch == '\r') {
 | 
| 
 809 | 
 1
 |                 syntaxError("Illegal line end in literal", position);
 | 
| 
 810 | 
  
 |             } | 
| 
 811 | 
  
 |             else | 
| 
 812 | 
  
 |             { | 
| 
 813 | 
 232
 |                 value.append(ch);
 | 
| 
 814 | 
  
 |             } | 
| 
 815 | 
 245
 |             nextChar();
 | 
| 
 816 | 
  
 |         } | 
| 
 817 | 
  
 |          | 
| 
 818 | 
 1
 |         syntaxError("Missing '\"'", position);
 | 
| 
 819 | 
  
 |     } | 
| 
 820 | 
  
 |  | 
| 
 821 | 
  
 |  | 
| 
 822 | 
  
 |      | 
| 
 823 | 
  
 |  | 
| 
 824 | 
  
 |  | 
| 
 825 | 
  
 |  | 
| 
 826 | 
  
 |  | 
| 
 827 | 
 37
 |     private void scanDomainLiteral(TokenStream tokens) throws AddressException {
 | 
| 
 828 | 
 37
 |         StringBuffer value = new StringBuffer();
 | 
| 
 829 | 
  
 |  | 
| 
 830 | 
 37
 |         int startPosition = position;
 | 
| 
 831 | 
  
 |          | 
| 
 832 | 
 37
 |         nextChar();
 | 
| 
 833 | 
  
 |  | 
| 
 834 | 
 37
 |         while (moreCharacters()) {
 | 
| 
 835 | 
 223
 |             char ch = currentChar();
 | 
| 
 836 | 
  
 |  | 
| 
 837 | 
  
 |              | 
| 
 838 | 
 223
 |             if (ch == '\\') {
 | 
| 
 839 | 
  
 |                  | 
| 
 840 | 
  
 |                  | 
| 
 841 | 
  
 |                  | 
| 
 842 | 
 3
 |                 value.append(currentChar());
 | 
| 
 843 | 
  
 |                  | 
| 
 844 | 
 3
 |                 nextChar();
 | 
| 
 845 | 
 3
 |                 if (!moreCharacters()) {
 | 
| 
 846 | 
 0
 |                     syntaxError("Missing '\"'", position);
 | 
| 
 847 | 
  
 |                 } | 
| 
 848 | 
 3
 |                 value.append(currentChar());
 | 
| 
 849 | 
  
 |             } | 
| 
 850 | 
  
 |              | 
| 
 851 | 
 220
 |             else if (ch == ']') {
 | 
| 
 852 | 
  
 |                  | 
| 
 853 | 
 32
 |                 tokens.addToken(new AddressToken(value.toString(), DOMAIN_LITERAL, startPosition));
 | 
| 
 854 | 
  
 |                  | 
| 
 855 | 
 32
 |                 nextChar();
 | 
| 
 856 | 
 32
 |                 return;
 | 
| 
 857 | 
  
 |             } | 
| 
 858 | 
  
 |              | 
| 
 859 | 
 188
 |             else if (ch == '[') {
 | 
| 
 860 | 
 1
 |                 syntaxError("Unexpected '['", position);
 | 
| 
 861 | 
  
 |             } | 
| 
 862 | 
  
 |              | 
| 
 863 | 
 187
 |             else if (ch == '\r') {
 | 
| 
 864 | 
 1
 |                 syntaxError("Illegal line end in domain literal", position);
 | 
| 
 865 | 
  
 |             } | 
| 
 866 | 
  
 |             else | 
| 
 867 | 
  
 |             { | 
| 
 868 | 
 186
 |                 value.append(ch);
 | 
| 
 869 | 
  
 |             } | 
| 
 870 | 
 189
 |             nextChar();
 | 
| 
 871 | 
  
 |         } | 
| 
 872 | 
  
 |          | 
| 
 873 | 
 3
 |         syntaxError("Missing ']'", position);
 | 
| 
 874 | 
  
 |     } | 
| 
 875 | 
  
 |  | 
| 
 876 | 
  
 |      | 
| 
 877 | 
  
 |  | 
| 
 878 | 
  
 |  | 
| 
 879 | 
  
 |  | 
| 
 880 | 
  
 |  | 
| 
 881 | 
  
 |  | 
| 
 882 | 
 1163
 |     private void scanAtom(TokenStream tokens) throws AddressException {
 | 
| 
 883 | 
 1163
 |         int start = position;
 | 
| 
 884 | 
 1163
 |         nextChar();
 | 
| 
 885 | 
 1163
 |         while (moreCharacters()) {
 | 
| 
 886 | 
  
 |  | 
| 
 887 | 
 4943
 |             char ch = currentChar();
 | 
| 
 888 | 
 4943
 |             if (isAtom(ch)) {
 | 
| 
 889 | 
 3933
 |                 nextChar();
 | 
| 
 890 | 
  
 |             } | 
| 
 891 | 
  
 |             else { | 
| 
 892 | 
 1010
 |                 break;
 | 
| 
 893 | 
  
 |             } | 
| 
 894 | 
  
 |         } | 
| 
 895 | 
  
 |  | 
| 
 896 | 
  
 |          | 
| 
 897 | 
 1163
 |         tokens.addToken(new AddressToken(addresses.substring(start, position), ATOM, start));
 | 
| 
 898 | 
  
 |     } | 
| 
 899 | 
  
 |  | 
| 
 900 | 
  
 |  | 
| 
 901 | 
  
 |      | 
| 
 902 | 
  
 |  | 
| 
 903 | 
  
 |  | 
| 
 904 | 
  
 |  | 
| 
 905 | 
  
 |  | 
| 
 906 | 
  
 |  | 
| 
 907 | 
 55
 |     private void scanComment(TokenStream tokens) throws AddressException {
 | 
| 
 908 | 
 55
 |         StringBuffer value = new StringBuffer();
 | 
| 
 909 | 
  
 |  | 
| 
 910 | 
 55
 |         int startPosition = position;
 | 
| 
 911 | 
  
 |          | 
| 
 912 | 
 55
 |         nextChar();
 | 
| 
 913 | 
  
 |  | 
| 
 914 | 
  
 |          | 
| 
 915 | 
 55
 |         int nest = 1;
 | 
| 
 916 | 
  
 |  | 
| 
 917 | 
  
 |          | 
| 
 918 | 
 55
 |         while (moreCharacters()) {
 | 
| 
 919 | 
 315
 |             char ch = currentChar();
 | 
| 
 920 | 
  
 |              | 
| 
 921 | 
 315
 |             if (ch == '\\') {
 | 
| 
 922 | 
  
 |                  | 
| 
 923 | 
  
 |                  | 
| 
 924 | 
 2
 |                 nextChar();
 | 
| 
 925 | 
 2
 |                 if (!moreCharacters()) {
 | 
| 
 926 | 
 0
 |                     syntaxError("Missing ')'", position);
 | 
| 
 927 | 
  
 |                 } | 
| 
 928 | 
 2
 |                 value.append(currentChar());
 | 
| 
 929 | 
  
 |             } | 
| 
 930 | 
  
 |              | 
| 
 931 | 
 313
 |             else if (ch == '(') {
 | 
| 
 932 | 
  
 |                  | 
| 
 933 | 
  
 |                  | 
| 
 934 | 
 1
 |                 nest++;
 | 
| 
 935 | 
 1
 |                 value.append(ch);
 | 
| 
 936 | 
  
 |             } | 
| 
 937 | 
  
 |              | 
| 
 938 | 
 312
 |             else if (ch == ')') {
 | 
| 
 939 | 
  
 |                  | 
| 
 940 | 
  
 |                  | 
| 
 941 | 
 54
 |                 nest--;
 | 
| 
 942 | 
 54
 |                 if (nest > 0) {
 | 
| 
 943 | 
 1
 |                     value.append(ch);
 | 
| 
 944 | 
  
 |                 } | 
| 
 945 | 
  
 |                 else { | 
| 
 946 | 
  
 |                      | 
| 
 947 | 
  
 |                      | 
| 
 948 | 
  
 |                      | 
| 
 949 | 
 53
 |                     nextChar();
 | 
| 
 950 | 
 53
 |                     tokens.addToken(new AddressToken(value.toString(), COMMENT, startPosition));
 | 
| 
 951 | 
 53
 |                     return;
 | 
| 
 952 | 
  
 |                 } | 
| 
 953 | 
  
 |             } | 
| 
 954 | 
 258
 |             else if (ch == '\r') {
 | 
| 
 955 | 
 1
 |                 syntaxError("Illegal line end in comment", position);
 | 
| 
 956 | 
  
 |             } | 
| 
 957 | 
  
 |             else { | 
| 
 958 | 
 257
 |                 value.append(ch);
 | 
| 
 959 | 
  
 |             } | 
| 
 960 | 
  
 |              | 
| 
 961 | 
 261
 |             nextChar();
 | 
| 
 962 | 
  
 |         } | 
| 
 963 | 
  
 |          | 
| 
 964 | 
 1
 |         syntaxError("Missing ')'", position);
 | 
| 
 965 | 
  
 |     } | 
| 
 966 | 
  
 |  | 
| 
 967 | 
  
 |  | 
| 
 968 | 
  
 |      | 
| 
 969 | 
  
 |  | 
| 
 970 | 
  
 |  | 
| 
 971 | 
  
 |  | 
| 
 972 | 
  
 |  | 
| 
 973 | 
  
 |  | 
| 
 974 | 
  
 |  | 
| 
 975 | 
 31
 |     private void validateGroup(TokenStream tokens) throws AddressException {
 | 
| 
 976 | 
  
 |          | 
| 
 977 | 
  
 |          | 
| 
 978 | 
  
 |  | 
| 
 979 | 
 31
 |         int phraseCount = 0;
 | 
| 
 980 | 
  
 |  | 
| 
 981 | 
 31
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 982 | 
  
 |          | 
| 
 983 | 
 31
 |         while (token.type != COLON) {
 | 
| 
 984 | 
  
 |              | 
| 
 985 | 
 40
 |             if (token.type != ATOM && token.type != QUOTED_LITERAL) {
 | 
| 
 986 | 
 0
 |                 invalidToken(token);
 | 
| 
 987 | 
  
 |             } | 
| 
 988 | 
 40
 |             phraseCount++;
 | 
| 
 989 | 
 40
 |             token = tokens.nextRealToken();
 | 
| 
 990 | 
  
 |         } | 
| 
 991 | 
  
 |  | 
| 
 992 | 
  
 |  | 
| 
 993 | 
  
 |          | 
| 
 994 | 
 31
 |         if (phraseCount == 0) {
 | 
| 
 995 | 
 1
 |             illegalAddress("Missing group identifier phrase", token);
 | 
| 
 996 | 
  
 |         } | 
| 
 997 | 
  
 |  | 
| 
 998 | 
  
 |          | 
| 
 999 | 
  
 |          | 
| 
 1000 | 
  
 |  | 
| 
 1001 | 
  
 |          | 
| 
 1002 | 
 30
 |         while (true) {
 | 
| 
 1003 | 
  
 |              | 
| 
 1004 | 
  
 |              | 
| 
 1005 | 
 48
 |             validateGroupMailbox(tokens);
 | 
| 
 1006 | 
  
 |  | 
| 
 1007 | 
 48
 |             token = tokens.nextRealToken();
 | 
| 
 1008 | 
  
 |  | 
| 
 1009 | 
  
 |              | 
| 
 1010 | 
 48
 |             if (token.type == SEMICOLON) {
 | 
| 
 1011 | 
 30
 |                 token = tokens.nextRealToken();
 | 
| 
 1012 | 
 30
 |                 if (token.type != END_OF_TOKENS) {
 | 
| 
 1013 | 
 0
 |                     illegalAddress("Illegal group address", token);
 | 
| 
 1014 | 
  
 |                 } | 
| 
 1015 | 
 30
 |                 return;
 | 
| 
 1016 | 
  
 |             } | 
| 
 1017 | 
  
 |  | 
| 
 1018 | 
  
 |              | 
| 
 1019 | 
 18
 |             else if (token.type != COMMA) {
 | 
| 
 1020 | 
 0
 |                 illegalAddress("Illegal group address", token);
 | 
| 
 1021 | 
  
 |             } | 
| 
 1022 | 
  
 |         } | 
| 
 1023 | 
  
 |     } | 
| 
 1024 | 
  
 |  | 
| 
 1025 | 
  
 |  | 
| 
 1026 | 
  
 |      | 
| 
 1027 | 
  
 |  | 
| 
 1028 | 
  
 |  | 
| 
 1029 | 
  
 |  | 
| 
 1030 | 
  
 |  | 
| 
 1031 | 
  
 |  | 
| 
 1032 | 
  
 |  | 
| 
 1033 | 
 48
 |     private void validateGroupMailbox(TokenStream tokens) throws AddressException {
 | 
| 
 1034 | 
 48
 |         AddressToken first = tokens.nextRealToken();
 | 
| 
 1035 | 
  
 |          | 
| 
 1036 | 
 48
 |         if (first.type == COMMA || first.type == SEMICOLON) {
 | 
| 
 1037 | 
 14
 |             tokens.pushToken(first);
 | 
| 
 1038 | 
 14
 |             return;
 | 
| 
 1039 | 
  
 |         } | 
| 
 1040 | 
  
 |  | 
| 
 1041 | 
  
 |          | 
| 
 1042 | 
 34
 |         AddressToken token = first;
 | 
| 
 1043 | 
  
 |  | 
| 
 1044 | 
  
 |  | 
| 
 1045 | 
  
 |          | 
| 
 1046 | 
 62
 |         while (first != null) {
 | 
| 
 1047 | 
 62
 |             switch (token.type) {
 | 
| 
 1048 | 
  
 |                  | 
| 
 1049 | 
 0
 |                 case QUOTED_LITERAL:
 | 
| 
 1050 | 
 28
 |                 case ATOM:
 | 
| 
 1051 | 
 28
 |                     break;
 | 
| 
 1052 | 
  
 |  | 
| 
 1053 | 
  
 |                  | 
| 
 1054 | 
  
 |                  | 
| 
 1055 | 
 11
 |                 case LEFT_ANGLE:
 | 
| 
 1056 | 
 11
 |                     tokens.pushToken(first);
 | 
| 
 1057 | 
 11
 |                     validatePhrase(tokens, false);
 | 
| 
 1058 | 
 11
 |                     validateRouteAddr(tokens, true);
 | 
| 
 1059 | 
 11
 |                     return;
 | 
| 
 1060 | 
  
 |  | 
| 
 1061 | 
  
 |                  | 
| 
 1062 | 
  
 |                  | 
| 
 1063 | 
 0
 |                 case PERIOD:
 | 
| 
 1064 | 
  
 |                  | 
| 
 1065 | 
  
 |                  | 
| 
 1066 | 
 21
 |                 case AT_SIGN:
 | 
| 
 1067 | 
 21
 |                     tokens.pushToken(first);
 | 
| 
 1068 | 
 21
 |                     validateAddressSpec(tokens);
 | 
| 
 1069 | 
 21
 |                     return;
 | 
| 
 1070 | 
  
 |  | 
| 
 1071 | 
  
 |                  | 
| 
 1072 | 
  
 |                  | 
| 
 1073 | 
 1
 |                 case COMMA:
 | 
| 
 1074 | 
  
 |                  | 
| 
 1075 | 
 1
 |                 case SEMICOLON:
 | 
| 
 1076 | 
 2
 |                     tokens.pushToken(first);
 | 
| 
 1077 | 
 2
 |                     validateAddressSpec(tokens);
 | 
| 
 1078 | 
 2
 |                     return;
 | 
| 
 1079 | 
  
 |  | 
| 
 1080 | 
 0
 |                 case END_OF_TOKENS:
 | 
| 
 1081 | 
 0
 |                     illegalAddress("Missing ';'", token);
 | 
| 
 1082 | 
  
 |  | 
| 
 1083 | 
  
 |             } | 
| 
 1084 | 
 28
 |             token = tokens.nextRealToken();
 | 
| 
 1085 | 
  
 |         } | 
| 
 1086 | 
  
 |     } | 
| 
 1087 | 
  
 |  | 
| 
 1088 | 
  
 |  | 
| 
 1089 | 
  
 |      | 
| 
 1090 | 
  
 |  | 
| 
 1091 | 
  
 |  | 
| 
 1092 | 
  
 |  | 
| 
 1093 | 
  
 |  | 
| 
 1094 | 
  
 |  | 
| 
 1095 | 
  
 |  | 
| 
 1096 | 
  
 |  | 
| 
 1097 | 
 0
 |     private void invalidToken(AddressToken token) throws AddressException {
 | 
| 
 1098 | 
 0
 |         illegalAddress("Unexpected '" + token.type + "'", token);
 | 
| 
 1099 | 
  
 |     } | 
| 
 1100 | 
  
 |  | 
| 
 1101 | 
  
 |  | 
| 
 1102 | 
  
 |      | 
| 
 1103 | 
  
 |  | 
| 
 1104 | 
  
 |  | 
| 
 1105 | 
  
 |  | 
| 
 1106 | 
  
 |  | 
| 
 1107 | 
  
 |  | 
| 
 1108 | 
  
 |  | 
| 
 1109 | 
  
 |  | 
| 
 1110 | 
 9
 |     private void syntaxError(String message, int position) throws AddressException
 | 
| 
 1111 | 
  
 |     { | 
| 
 1112 | 
 9
 |         throw new AddressException(message, addresses, position);
 | 
| 
 1113 | 
  
 |     } | 
| 
 1114 | 
  
 |  | 
| 
 1115 | 
  
 |  | 
| 
 1116 | 
  
 |      | 
| 
 1117 | 
  
 |  | 
| 
 1118 | 
  
 |  | 
| 
 1119 | 
  
 |  | 
| 
 1120 | 
  
 |  | 
| 
 1121 | 
  
 |  | 
| 
 1122 | 
  
 |  | 
| 
 1123 | 
 16
 |     private void illegalAddress(String message, AddressToken token) throws AddressException {
 | 
| 
 1124 | 
 16
 |         throw new AddressException(message, addresses, token.position);
 | 
| 
 1125 | 
  
 |     } | 
| 
 1126 | 
  
 |  | 
| 
 1127 | 
  
 |  | 
| 
 1128 | 
  
 |      | 
| 
 1129 | 
  
 |  | 
| 
 1130 | 
  
 |  | 
| 
 1131 | 
  
 |  | 
| 
 1132 | 
  
 |  | 
| 
 1133 | 
  
 |  | 
| 
 1134 | 
  
 |  | 
| 
 1135 | 
  
 |  | 
| 
 1136 | 
 11
 |     private void validatePhrase(TokenStream tokens, boolean required) throws AddressException {
 | 
| 
 1137 | 
  
 |          | 
| 
 1138 | 
  
 |          | 
| 
 1139 | 
 11
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 1140 | 
 11
 |         if (token.type != ATOM && token.type != QUOTED_LITERAL) {
 | 
| 
 1141 | 
 6
 |             if (required) {
 | 
| 
 1142 | 
 0
 |                 illegalAddress("Missing group phrase", token);
 | 
| 
 1143 | 
  
 |             } | 
| 
 1144 | 
  
 |         } | 
| 
 1145 | 
  
 |  | 
| 
 1146 | 
  
 |          | 
| 
 1147 | 
 11
 |         token = tokens.nextRealToken();
 | 
| 
 1148 | 
 11
 |         while (token.type == ATOM || token.type == QUOTED_LITERAL) {
 | 
| 
 1149 | 
 6
 |             token = tokens.nextRealToken();
 | 
| 
 1150 | 
  
 |         } | 
| 
 1151 | 
  
 |     } | 
| 
 1152 | 
  
 |  | 
| 
 1153 | 
  
 |  | 
| 
 1154 | 
  
 |      | 
| 
 1155 | 
  
 |  | 
| 
 1156 | 
  
 |  | 
| 
 1157 | 
  
 |  | 
| 
 1158 | 
  
 |  | 
| 
 1159 | 
  
 |  | 
| 
 1160 | 
  
 |  | 
| 
 1161 | 
  
 |  | 
| 
 1162 | 
  
 |  | 
| 
 1163 | 
  
 |  | 
| 
 1164 | 
  
 |  | 
| 
 1165 | 
 102
 |     private void validateRouteAddr(TokenStream tokens, boolean ingroup) throws AddressException {
 | 
| 
 1166 | 
  
 |          | 
| 
 1167 | 
 102
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 1168 | 
  
 |          | 
| 
 1169 | 
 102
 |         if (token.type == AT_SIGN) {
 | 
| 
 1170 | 
  
 |              | 
| 
 1171 | 
 20
 |             tokens.pushToken(token);
 | 
| 
 1172 | 
 20
 |             validateRoute(tokens);
 | 
| 
 1173 | 
  
 |         } | 
| 
 1174 | 
  
 |         else { | 
| 
 1175 | 
  
 |              | 
| 
 1176 | 
 82
 |             tokens.pushToken(token);
 | 
| 
 1177 | 
  
 |         } | 
| 
 1178 | 
  
 |  | 
| 
 1179 | 
  
 |          | 
| 
 1180 | 
 102
 |         validateAddressSpec(tokens);
 | 
| 
 1181 | 
  
 |  | 
| 
 1182 | 
 101
 |         token = tokens.nextRealToken();
 | 
| 
 1183 | 
 101
 |         if (ingroup) {
 | 
| 
 1184 | 
  
 |              | 
| 
 1185 | 
  
 |              | 
| 
 1186 | 
 11
 |             if (token.type != RIGHT_ANGLE) {
 | 
| 
 1187 | 
 0
 |                 illegalAddress("Missing '>'", token);
 | 
| 
 1188 | 
  
 |             } | 
| 
 1189 | 
  
 |         } | 
| 
 1190 | 
  
 |         else { | 
| 
 1191 | 
  
 |              | 
| 
 1192 | 
  
 |              | 
| 
 1193 | 
 90
 |             if (token.type != END_OF_TOKENS) {
 | 
| 
 1194 | 
 0
 |                 illegalAddress("Illegal Address", token);
 | 
| 
 1195 | 
  
 |             } | 
| 
 1196 | 
  
 |         } | 
| 
 1197 | 
  
 |     } | 
| 
 1198 | 
  
 |  | 
| 
 1199 | 
  
 |  | 
| 
 1200 | 
  
 |  | 
| 
 1201 | 
  
 |      | 
| 
 1202 | 
  
 |  | 
| 
 1203 | 
  
 |  | 
| 
 1204 | 
  
 |  | 
| 
 1205 | 
  
 |  | 
| 
 1206 | 
 186
 |     private void validateSimpleAddress(TokenStream tokens) throws AddressException {
 | 
| 
 1207 | 
  
 |  | 
| 
 1208 | 
  
 |          | 
| 
 1209 | 
  
 |          | 
| 
 1210 | 
  
 |          | 
| 
 1211 | 
 186
 |         validateAddressSpec(tokens);
 | 
| 
 1212 | 
  
 |  | 
| 
 1213 | 
  
 |          | 
| 
 1214 | 
 183
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 1215 | 
 183
 |         if (token.type != END_OF_TOKENS) {
 | 
| 
 1216 | 
 6
 |             illegalAddress("Illegal Address", token);
 | 
| 
 1217 | 
  
 |         } | 
| 
 1218 | 
  
 |     } | 
| 
 1219 | 
  
 |  | 
| 
 1220 | 
  
 |      | 
| 
 1221 | 
  
 |  | 
| 
 1222 | 
  
 |  | 
| 
 1223 | 
  
 |  | 
| 
 1224 | 
  
 |  | 
| 
 1225 | 
  
 |  | 
| 
 1226 | 
  
 |  | 
| 
 1227 | 
  
 |  | 
| 
 1228 | 
 311
 |     private void validateAddressSpec(TokenStream tokens) throws AddressException {
 | 
| 
 1229 | 
  
 |          | 
| 
 1230 | 
 311
 |         validateLocalPart(tokens);
 | 
| 
 1231 | 
  
 |  | 
| 
 1232 | 
  
 |          | 
| 
 1233 | 
 307
 |         AddressToken token = tokens.nextRealToken();
 | 
| 
 1234 | 
 307
 |         if (token.type == AT_SIGN) {
 | 
| 
 1235 | 
 268
 |             validateDomain(tokens);
 | 
| 
 1236 | 
  
 |         } | 
| 
 1237 | 
  
 |         else { | 
| 
 1238 | 
  
 |              | 
| 
 1239 | 
 39
 |             tokens.pushToken(token);
 | 
| 
 1240 | 
  
 |         } | 
| 
 1241 | 
  
 |  | 
| 
 1242 | 
  
 |     } | 
| 
 1243 | 
  
 |  | 
| 
 1244 | 
  
 |  | 
| 
 1245 | 
  
 |      | 
| 
 1246 | 
  
 |  | 
| 
 1247 | 
  
 |  | 
| 
 1248 | 
  
 |  | 
| 
 1249 | 
  
 |  | 
| 
 1250 | 
  
 |  | 
| 
 1251 | 
 20
 |     private void validateRoute(TokenStream tokens) throws AddressException {
 | 
| 
 1252 | 
 20
 |         while (true) {
 | 
| 
 1253 | 
 56
 |             AddressToken token = tokens.nextRealToken();
 | 
| 
 1254 | 
  
 |              | 
| 
 1255 | 
 56
 |             if (token.type == AT_SIGN) {
 | 
| 
 1256 | 
 28
 |                 validateDomain(tokens);
 | 
| 
 1257 | 
  
 |             } | 
| 
 1258 | 
  
 |              | 
| 
 1259 | 
 28
 |             else if (token.type == COMMA) {
 | 
| 
 1260 | 
 8
 |                 continue;
 | 
| 
 1261 | 
  
 |             } | 
| 
 1262 | 
  
 |              | 
| 
 1263 | 
 20
 |             else if (token.type == COLON) {
 | 
| 
 1264 | 
 20
 |                 return;
 | 
| 
 1265 | 
  
 |             } | 
| 
 1266 | 
  
 |              | 
| 
 1267 | 
  
 |             else { | 
| 
 1268 | 
 0
 |                 illegalAddress("Missing ':'", token);
 | 
| 
 1269 | 
  
 |             } | 
| 
 1270 | 
  
 |         } | 
| 
 1271 | 
  
 |     } | 
| 
 1272 | 
  
 |  | 
| 
 1273 | 
  
 |  | 
| 
 1274 | 
  
 |      | 
| 
 1275 | 
  
 |  | 
| 
 1276 | 
  
 |  | 
| 
 1277 | 
  
 |  | 
| 
 1278 | 
 311
 |     private void validateLocalPart(TokenStream tokens) throws AddressException {
 | 
| 
 1279 | 
 311
 |         while (true) {
 | 
| 
 1280 | 
  
 |              | 
| 
 1281 | 
 389
 |             AddressToken token = tokens.nextRealToken();
 | 
| 
 1282 | 
  
 |  | 
| 
 1283 | 
  
 |              | 
| 
 1284 | 
 389
 |             if (token.type != ATOM && token.type != QUOTED_LITERAL) {
 | 
| 
 1285 | 
 4
 |                 illegalAddress("Invalid local part", token);
 | 
| 
 1286 | 
  
 |             } | 
| 
 1287 | 
  
 |  | 
| 
 1288 | 
  
 |              | 
| 
 1289 | 
 385
 |             token = tokens.nextRealToken();
 | 
| 
 1290 | 
  
 |              | 
| 
 1291 | 
 385
 |             if (token.type != PERIOD) {
 | 
| 
 1292 | 
 307
 |                 tokens.pushToken(token);
 | 
| 
 1293 | 
  
 |                  | 
| 
 1294 | 
 307
 |                 return;
 | 
| 
 1295 | 
  
 |             } | 
| 
 1296 | 
  
 |         } | 
| 
 1297 | 
  
 |     } | 
| 
 1298 | 
  
 |  | 
| 
 1299 | 
  
 |  | 
| 
 1300 | 
  
 |  | 
| 
 1301 | 
  
 |      | 
| 
 1302 | 
  
 |  | 
| 
 1303 | 
  
 |  | 
| 
 1304 | 
  
 |  | 
| 
 1305 | 
 296
 |     private void validateDomain(TokenStream tokens) throws AddressException {
 | 
| 
 1306 | 
 296
 |         while (true) {
 | 
| 
 1307 | 
  
 |              | 
| 
 1308 | 
 594
 |             AddressToken token = tokens.nextRealToken();
 | 
| 
 1309 | 
  
 |  | 
| 
 1310 | 
  
 |              | 
| 
 1311 | 
 594
 |             if (token.type != ATOM && token.type != DOMAIN_LITERAL) {
 | 
| 
 1312 | 
 0
 |                 illegalAddress("Invalid domain", token);
 | 
| 
 1313 | 
  
 |             } | 
| 
 1314 | 
  
 |  | 
| 
 1315 | 
  
 |              | 
| 
 1316 | 
 594
 |             token = tokens.nextRealToken();
 | 
| 
 1317 | 
  
 |              | 
| 
 1318 | 
 594
 |             if (token.type != PERIOD) {
 | 
| 
 1319 | 
  
 |                  | 
| 
 1320 | 
 296
 |                 tokens.pushToken(token);
 | 
| 
 1321 | 
 296
 |                 return;
 | 
| 
 1322 | 
  
 |             } | 
| 
 1323 | 
  
 |         } | 
| 
 1324 | 
  
 |     } | 
| 
 1325 | 
  
 |  | 
| 
 1326 | 
  
 |      | 
| 
 1327 | 
  
 |  | 
| 
 1328 | 
  
 |  | 
| 
 1329 | 
  
 |  | 
| 
 1330 | 
  
 |  | 
| 
 1331 | 
  
 |  | 
| 
 1332 | 
  
 |  | 
| 
 1333 | 
  
 |  | 
| 
 1334 | 
  
 |  | 
| 
 1335 | 
  
 |  | 
| 
 1336 | 
  
 |  | 
| 
 1337 | 
  
 |  | 
| 
 1338 | 
  
 |  | 
| 
 1339 | 
  
 |  | 
| 
 1340 | 
  
 |  | 
| 
 1341 | 
  
 |  | 
| 
 1342 | 
  
 |  | 
| 
 1343 | 
  
 |  | 
| 
 1344 | 
  
 |  | 
| 
 1345 | 
  
 |  | 
| 
 1346 | 
  
 |  | 
| 
 1347 | 
  
 |  | 
| 
 1348 | 
  
 |  | 
| 
 1349 | 
  
 |  | 
| 
 1350 | 
  
 |  | 
| 
 1351 | 
  
 |  | 
| 
 1352 | 
  
 |  | 
| 
 1353 | 
  
 |  | 
| 
 1354 | 
  
 |  | 
| 
 1355 | 
  
 |  | 
| 
 1356 | 
  
 |  | 
| 
 1357 | 
  
 |  | 
| 
 1358 | 
  
 |  | 
| 
 1359 | 
  
 |  | 
| 
 1360 | 
  
 |  | 
| 
 1361 | 
  
 |  | 
| 
 1362 | 
  
 |  | 
| 
 1363 | 
  
 |  | 
| 
 1364 | 
  
 |  | 
| 
 1365 | 
  
 |  | 
| 
 1366 | 
 44
 |     private String personalToString(TokenStream tokens) {
 | 
| 
 1367 | 
  
 |  | 
| 
 1368 | 
  
 |          | 
| 
 1369 | 
 44
 |         AddressToken token = tokens.nextToken();
 | 
| 
 1370 | 
  
 |  | 
| 
 1371 | 
 44
 |         if (token.type == END_OF_TOKENS) {
 | 
| 
 1372 | 
 0
 |             return null;
 | 
| 
 1373 | 
  
 |         } | 
| 
 1374 | 
  
 |  | 
| 
 1375 | 
 44
 |         AddressToken next = tokens.nextToken();
 | 
| 
 1376 | 
  
 |  | 
| 
 1377 | 
  
 |          | 
| 
 1378 | 
 44
 |         if (next.type == END_OF_TOKENS) {
 | 
| 
 1379 | 
  
 |              | 
| 
 1380 | 
  
 |              | 
| 
 1381 | 
 27
 |             return token.value;
 | 
| 
 1382 | 
  
 |         } | 
| 
 1383 | 
  
 |  | 
| 
 1384 | 
  
 |          | 
| 
 1385 | 
 17
 |         tokens.pushToken(token);
 | 
| 
 1386 | 
  
 |  | 
| 
 1387 | 
  
 |          | 
| 
 1388 | 
 17
 |         StringBuffer buffer = new StringBuffer();
 | 
| 
 1389 | 
  
 |  | 
| 
 1390 | 
  
 |          | 
| 
 1391 | 
 17
 |         token = tokens.nextToken();
 | 
| 
 1392 | 
 17
 |         addTokenValue(token, buffer);
 | 
| 
 1393 | 
  
 |  | 
| 
 1394 | 
 17
 |         token = tokens.nextToken();
 | 
| 
 1395 | 
 17
 |         while (token.type != END_OF_TOKENS) {
 | 
| 
 1396 | 
  
 |              | 
| 
 1397 | 
 18
 |             buffer.append(' ');
 | 
| 
 1398 | 
  
 |              | 
| 
 1399 | 
 18
 |             addTokenValue(token, buffer);
 | 
| 
 1400 | 
 18
 |             token = tokens.nextToken();
 | 
| 
 1401 | 
  
 |         } | 
| 
 1402 | 
  
 |          | 
| 
 1403 | 
 17
 |         return buffer.toString();
 | 
| 
 1404 | 
  
 |     } | 
| 
 1405 | 
  
 |  | 
| 
 1406 | 
  
 |  | 
| 
 1407 | 
  
 |      | 
| 
 1408 | 
  
 |  | 
| 
 1409 | 
  
 |  | 
| 
 1410 | 
  
 |  | 
| 
 1411 | 
  
 |  | 
| 
 1412 | 
  
 |  | 
| 
 1413 | 
  
 |  | 
| 
 1414 | 
  
 |  | 
| 
 1415 | 
 317
 |     private String addressToString(TokenStream tokens) {
 | 
| 
 1416 | 
 317
 |         StringBuffer buffer = new StringBuffer();
 | 
| 
 1417 | 
  
 |  | 
| 
 1418 | 
  
 |          | 
| 
 1419 | 
  
 |          | 
| 
 1420 | 
  
 |          | 
| 
 1421 | 
  
 |          | 
| 
 1422 | 
 317
 |         boolean spaceRequired = false;
 | 
| 
 1423 | 
  
 |  | 
| 
 1424 | 
  
 |          | 
| 
 1425 | 
 317
 |         AddressToken token = tokens.nextToken();
 | 
| 
 1426 | 
  
 |  | 
| 
 1427 | 
  
 |          | 
| 
 1428 | 
 317
 |         while (token.type != END_OF_TOKENS) {
 | 
| 
 1429 | 
 1944
 |             switch (token.type) {
 | 
| 
 1430 | 
  
 |                  | 
| 
 1431 | 
  
 |                  | 
| 
 1432 | 
 1038
 |                 case ATOM:
 | 
| 
 1433 | 
 21
 |                 case QUOTED_LITERAL:
 | 
| 
 1434 | 
  
 |                      | 
| 
 1435 | 
 1059
 |                     if (spaceRequired) {
 | 
| 
 1436 | 
 11
 |                         buffer.append(' ');
 | 
| 
 1437 | 
  
 |                     } | 
| 
 1438 | 
 1059
 |                     addTokenValue(token, buffer);
 | 
| 
 1439 | 
  
 |                      | 
| 
 1440 | 
 1059
 |                     spaceRequired = true;
 | 
| 
 1441 | 
 1059
 |                     break;
 | 
| 
 1442 | 
  
 |  | 
| 
 1443 | 
  
 |                  | 
| 
 1444 | 
  
 |                  | 
| 
 1445 | 
  
 |                  | 
| 
 1446 | 
 11
 |                 case LEFT_ANGLE:
 | 
| 
 1447 | 
 11
 |                 case RIGHT_ANGLE:
 | 
| 
 1448 | 
 27
 |                 case COMMA:
 | 
| 
 1449 | 
 53
 |                 case COLON:
 | 
| 
 1450 | 
 319
 |                 case AT_SIGN:
 | 
| 
 1451 | 
 31
 |                 case SEMICOLON:
 | 
| 
 1452 | 
 403
 |                 case PERIOD:
 | 
| 
 1453 | 
 855
 |                     buffer.append((char)token.type);
 | 
| 
 1454 | 
  
 |                      | 
| 
 1455 | 
 855
 |                     spaceRequired = false;
 | 
| 
 1456 | 
 855
 |                     break;
 | 
| 
 1457 | 
  
 |  | 
| 
 1458 | 
  
 |                  | 
| 
 1459 | 
 30
 |                 case DOMAIN_LITERAL:
 | 
| 
 1460 | 
 30
 |                     addTokenValue(token, buffer);
 | 
| 
 1461 | 
 30
 |                     spaceRequired = false;
 | 
| 
 1462 | 
 30
 |                     break;
 | 
| 
 1463 | 
  
 |  | 
| 
 1464 | 
  
 |                  | 
| 
 1465 | 
 0
 |                 case COMMENT:
 | 
| 
 1466 | 
 0
 |                     addTokenValue(token, buffer);
 | 
| 
 1467 | 
 0
 |                     spaceRequired = false;
 | 
| 
 1468 | 
 0
 |                     break;
 | 
| 
 1469 | 
  
 |             } | 
| 
 1470 | 
 1944
 |             token = tokens.nextToken();
 | 
| 
 1471 | 
  
 |         } | 
| 
 1472 | 
 317
 |         return buffer.toString();
 | 
| 
 1473 | 
  
 |     } | 
| 
 1474 | 
  
 |  | 
| 
 1475 | 
  
 |  | 
| 
 1476 | 
  
 |      | 
| 
 1477 | 
  
 |  | 
| 
 1478 | 
  
 |  | 
| 
 1479 | 
  
 |  | 
| 
 1480 | 
  
 |  | 
| 
 1481 | 
  
 |  | 
| 
 1482 | 
  
 |  | 
| 
 1483 | 
 1124
 |     private void addTokenValue(AddressToken token, StringBuffer buffer) {
 | 
| 
 1484 | 
  
 |          | 
| 
 1485 | 
 1124
 |         if (token.type == ATOM) {
 | 
| 
 1486 | 
 1064
 |             buffer.append(token.value);
 | 
| 
 1487 | 
  
 |         } | 
| 
 1488 | 
  
 |          | 
| 
 1489 | 
 60
 |         else if (token.type == QUOTED_LITERAL) {
 | 
| 
 1490 | 
 29
 |             buffer.append(formatQuotedString(token.value));
 | 
| 
 1491 | 
  
 |         } | 
| 
 1492 | 
  
 |          | 
| 
 1493 | 
 31
 |         else if (token.type == DOMAIN_LITERAL) {
 | 
| 
 1494 | 
 30
 |             buffer.append('[');
 | 
| 
 1495 | 
 30
 |             buffer.append(token.value);
 | 
| 
 1496 | 
 30
 |             buffer.append(']');
 | 
| 
 1497 | 
  
 |         } | 
| 
 1498 | 
  
 |          | 
| 
 1499 | 
 1
 |         else if (token.type == COMMENT) {
 | 
| 
 1500 | 
 1
 |             buffer.append('(');
 | 
| 
 1501 | 
 1
 |             buffer.append(token.value);
 | 
| 
 1502 | 
 1
 |             buffer.append(')');
 | 
| 
 1503 | 
  
 |         } | 
| 
 1504 | 
  
 |     } | 
| 
 1505 | 
  
 |  | 
| 
 1506 | 
  
 |  | 
| 
 1507 | 
  
 |  | 
| 
 1508 | 
  
 |     private static final byte[] CHARMAP = { | 
| 
 1509 | 
  
 |         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  0x06, 0x02, 0x06, 0x02, 0x02, 0x06, 0x02, 0x02, | 
| 
 1510 | 
  
 |         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,  0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, | 
| 
 1511 | 
  
 |         0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,  0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, | 
| 
 1512 | 
  
 |         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, | 
| 
 1513 | 
  
 |  | 
| 
 1514 | 
  
 |         0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
| 
 1515 | 
  
 |         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, | 
| 
 1516 | 
  
 |         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 
| 
 1517 | 
  
 |         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, | 
| 
 1518 | 
  
 |     }; | 
| 
 1519 | 
  
 |  | 
| 
 1520 | 
  
 |     private static final byte FLG_SPECIAL = 1; | 
| 
 1521 | 
  
 |     private static final byte FLG_CONTROL = 2; | 
| 
 1522 | 
  
 |     private static final byte FLG_SPACE = 4; | 
| 
 1523 | 
  
 |  | 
| 
 1524 | 
 0
 |     private static boolean isSpace(char ch) {
 | 
| 
 1525 | 
 0
 |         if (ch > '\u007f') {
 | 
| 
 1526 | 
 0
 |             return false;
 | 
| 
 1527 | 
  
 |         } else { | 
| 
 1528 | 
 0
 |             return (CHARMAP[ch] & FLG_SPACE) != 0;
 | 
| 
 1529 | 
  
 |         } | 
| 
 1530 | 
  
 |     } | 
| 
 1531 | 
  
 |  | 
| 
 1532 | 
  
 |      | 
| 
 1533 | 
  
 |  | 
| 
 1534 | 
  
 |  | 
| 
 1535 | 
  
 |  | 
| 
 1536 | 
  
 |  | 
| 
 1537 | 
  
 |  | 
| 
 1538 | 
  
 |  | 
| 
 1539 | 
  
 |  | 
| 
 1540 | 
  
 |  | 
| 
 1541 | 
 5158
 |     public static boolean isAtom(char ch) {
 | 
| 
 1542 | 
 5158
 |         if (ch > '\u007f') {
 | 
| 
 1543 | 
 0
 |             return false;
 | 
| 
 1544 | 
  
 |         } | 
| 
 1545 | 
 5158
 |         else if (ch == ' ') {
 | 
| 
 1546 | 
 57
 |             return false;
 | 
| 
 1547 | 
  
 |         } | 
| 
 1548 | 
  
 |         else { | 
| 
 1549 | 
 5101
 |             return (CHARMAP[ch] & (FLG_SPECIAL | FLG_CONTROL)) == 0;
 | 
| 
 1550 | 
  
 |         } | 
| 
 1551 | 
  
 |     } | 
| 
 1552 | 
  
 |  | 
| 
 1553 | 
  
 |      | 
| 
 1554 | 
  
 |  | 
| 
 1555 | 
  
 |  | 
| 
 1556 | 
  
 |  | 
| 
 1557 | 
  
 |  | 
| 
 1558 | 
  
 |  | 
| 
 1559 | 
  
 |  | 
| 
 1560 | 
  
 |  | 
| 
 1561 | 
  
 |  | 
| 
 1562 | 
 173
 |     public static boolean containsCharacters(String s, String chars)
 | 
| 
 1563 | 
  
 |     { | 
| 
 1564 | 
 173
 |         for (int i = 0; i < s.length(); i++) {
 | 
| 
 1565 | 
 2100
 |             if (chars.indexOf(s.charAt(i)) >= 0) {
 | 
| 
 1566 | 
 62
 |                 return true;
 | 
| 
 1567 | 
  
 |             } | 
| 
 1568 | 
  
 |         } | 
| 
 1569 | 
 111
 |         return false;
 | 
| 
 1570 | 
  
 |     } | 
| 
 1571 | 
  
 |  | 
| 
 1572 | 
  
 |  | 
| 
 1573 | 
  
 |      | 
| 
 1574 | 
  
 |  | 
| 
 1575 | 
  
 |  | 
| 
 1576 | 
  
 |  | 
| 
 1577 | 
  
 |  | 
| 
 1578 | 
  
 |  | 
| 
 1579 | 
  
 |  | 
| 
 1580 | 
  
 |  | 
| 
 1581 | 
  
 |  | 
| 
 1582 | 
  
 |  | 
| 
 1583 | 
 46
 |     public static boolean containsSpecials(String s)
 | 
| 
 1584 | 
  
 |     { | 
| 
 1585 | 
 46
 |         for (int i = 0; i < s.length(); i++) {
 | 
| 
 1586 | 
 242
 |             char ch = s.charAt(i);
 | 
| 
 1587 | 
  
 |              | 
| 
 1588 | 
 242
 |             if (ch == ' ' || isAtom(ch)) {
 | 
| 
 1589 | 
 239
 |                 continue;
 | 
| 
 1590 | 
  
 |             } | 
| 
 1591 | 
  
 |             else { | 
| 
 1592 | 
 3
 |                 return true;
 | 
| 
 1593 | 
  
 |             } | 
| 
 1594 | 
  
 |         } | 
| 
 1595 | 
 43
 |         return false;
 | 
| 
 1596 | 
  
 |     } | 
| 
 1597 | 
  
 |  | 
| 
 1598 | 
  
 |  | 
| 
 1599 | 
  
 |      | 
| 
 1600 | 
  
 |  | 
| 
 1601 | 
  
 |  | 
| 
 1602 | 
  
 |  | 
| 
 1603 | 
  
 |  | 
| 
 1604 | 
  
 |  | 
| 
 1605 | 
  
 |  | 
| 
 1606 | 
  
 |  | 
| 
 1607 | 
  
 |  | 
| 
 1608 | 
  
 |  | 
| 
 1609 | 
 0
 |     public static boolean isAtom(String s)
 | 
| 
 1610 | 
  
 |     { | 
| 
 1611 | 
 0
 |         for (int i = 0; i < s.length(); i++) {
 | 
| 
 1612 | 
 0
 |             char ch = s.charAt(i);
 | 
| 
 1613 | 
  
 |              | 
| 
 1614 | 
 0
 |             if (!isAtom(ch)) {
 | 
| 
 1615 | 
 0
 |                 return false;
 | 
| 
 1616 | 
  
 |             } | 
| 
 1617 | 
  
 |         } | 
| 
 1618 | 
 0
 |         return true;
 | 
| 
 1619 | 
  
 |     } | 
| 
 1620 | 
  
 |  | 
| 
 1621 | 
  
 |      | 
| 
 1622 | 
  
 |  | 
| 
 1623 | 
  
 |  | 
| 
 1624 | 
  
 |  | 
| 
 1625 | 
  
 |  | 
| 
 1626 | 
  
 |  | 
| 
 1627 | 
  
 |  | 
| 
 1628 | 
  
 |  | 
| 
 1629 | 
  
 |  | 
| 
 1630 | 
  
 |  | 
| 
 1631 | 
  
 |  | 
| 
 1632 | 
 63
 |     public static String quoteString(String s) {
 | 
| 
 1633 | 
  
 |  | 
| 
 1634 | 
  
 |          | 
| 
 1635 | 
  
 |          | 
| 
 1636 | 
 63
 |         if (s.indexOf('\\') == -1 && s.indexOf('"') == -1) {
 | 
| 
 1637 | 
  
 |              | 
| 
 1638 | 
 46
 |             if (!containsSpecials(s)) {
 | 
| 
 1639 | 
 43
 |                 return s;
 | 
| 
 1640 | 
  
 |             } | 
| 
 1641 | 
 3
 |             StringBuffer buffer = new StringBuffer(s.length() + 2);
 | 
| 
 1642 | 
 3
 |             buffer.append('"');
 | 
| 
 1643 | 
 3
 |             buffer.append(s);
 | 
| 
 1644 | 
 3
 |             buffer.append('"');
 | 
| 
 1645 | 
 3
 |             return buffer.toString();
 | 
| 
 1646 | 
  
 |         } | 
| 
 1647 | 
  
 |  | 
| 
 1648 | 
  
 |          | 
| 
 1649 | 
  
 |          | 
| 
 1650 | 
 17
 |         StringBuffer buffer = new StringBuffer(s.length() + 10);
 | 
| 
 1651 | 
 17
 |         buffer.append('"');
 | 
| 
 1652 | 
  
 |  | 
| 
 1653 | 
  
 |          | 
| 
 1654 | 
 17
 |         for (int i = 0; i < s.length(); i++) {
 | 
| 
 1655 | 
 143
 |             char ch = s.charAt(i);
 | 
| 
 1656 | 
  
 |              | 
| 
 1657 | 
 143
 |             if (ch == '\\' || ch == '"') {
 | 
| 
 1658 | 
  
 |                  | 
| 
 1659 | 
 26
 |                 buffer.append('\\');
 | 
| 
 1660 | 
  
 |             } | 
| 
 1661 | 
  
 |              | 
| 
 1662 | 
 143
 |             buffer.append(ch);
 | 
| 
 1663 | 
  
 |         } | 
| 
 1664 | 
 17
 |         buffer.append('"');
 | 
| 
 1665 | 
 17
 |         return buffer.toString();
 | 
| 
 1666 | 
  
 |     } | 
| 
 1667 | 
  
 |  | 
| 
 1668 | 
  
 |      | 
| 
 1669 | 
  
 |  | 
| 
 1670 | 
  
 |  | 
| 
 1671 | 
  
 |  | 
| 
 1672 | 
  
 |  | 
| 
 1673 | 
  
 |  | 
| 
 1674 | 
  
 |  | 
| 
 1675 | 
  
 |  | 
| 
 1676 | 
  
 |  | 
| 
 1677 | 
  
 |  | 
| 
 1678 | 
 29
 |     public static String formatQuotedString(String s) {
 | 
| 
 1679 | 
  
 |          | 
| 
 1680 | 
  
 |          | 
| 
 1681 | 
 29
 |         if (s.indexOf('\\') == -1 && s.indexOf('"') == -1) {
 | 
| 
 1682 | 
 29
 |             StringBuffer buffer = new StringBuffer(s.length() + 2);
 | 
| 
 1683 | 
 29
 |             buffer.append('"');
 | 
| 
 1684 | 
 29
 |             buffer.append(s);
 | 
| 
 1685 | 
 29
 |             buffer.append('"');
 | 
| 
 1686 | 
 29
 |             return buffer.toString();
 | 
| 
 1687 | 
  
 |         } | 
| 
 1688 | 
  
 |  | 
| 
 1689 | 
  
 |          | 
| 
 1690 | 
  
 |          | 
| 
 1691 | 
 0
 |         StringBuffer buffer = new StringBuffer(s.length() + 10);
 | 
| 
 1692 | 
 0
 |         buffer.append('"');
 | 
| 
 1693 | 
  
 |  | 
| 
 1694 | 
  
 |          | 
| 
 1695 | 
 0
 |         for (int i = 0; i < s.length(); i++) {
 | 
| 
 1696 | 
 0
 |             char ch = s.charAt(i);
 | 
| 
 1697 | 
  
 |              | 
| 
 1698 | 
 0
 |             if (ch == '\\' || ch == '"') {
 | 
| 
 1699 | 
  
 |                  | 
| 
 1700 | 
 0
 |                 buffer.append('\\');
 | 
| 
 1701 | 
  
 |             } | 
| 
 1702 | 
  
 |              | 
| 
 1703 | 
 0
 |             buffer.append(ch);
 | 
| 
 1704 | 
  
 |         } | 
| 
 1705 | 
 0
 |         buffer.append('"');
 | 
| 
 1706 | 
 0
 |         return buffer.toString();
 | 
| 
 1707 | 
  
 |     } | 
| 
 1708 | 
  
 |  | 
| 
 1709 | 
  
 |     public class TokenStream { | 
| 
 1710 | 
  
 |          | 
| 
 1711 | 
  
 |         private List tokens; | 
| 
 1712 | 
  
 |  | 
| 
 1713 | 
  
 |          | 
| 
 1714 | 
  
 |         int currentToken = 0; | 
| 
 1715 | 
  
 |  | 
| 
 1716 | 
  
 |  | 
| 
 1717 | 
  
 |          | 
| 
 1718 | 
  
 |  | 
| 
 1719 | 
  
 |  | 
| 
 1720 | 
  
 |  | 
| 
 1721 | 
  
 |  | 
| 
 1722 | 
  
 |  | 
| 
 1723 | 
 326
 |         public TokenStream() {
 | 
| 
 1724 | 
 326
 |             tokens = new ArrayList();
 | 
| 
 1725 | 
  
 |         } | 
| 
 1726 | 
  
 |  | 
| 
 1727 | 
  
 |  | 
| 
 1728 | 
  
 |          | 
| 
 1729 | 
  
 |  | 
| 
 1730 | 
  
 |  | 
| 
 1731 | 
  
 |  | 
| 
 1732 | 
  
 |  | 
| 
 1733 | 
  
 |  | 
| 
 1734 | 
 387
 |         public TokenStream(List tokens) {
 | 
| 
 1735 | 
 387
 |             this.tokens = tokens;
 | 
| 
 1736 | 
 387
 |             tokens.add(new AddressToken(END_OF_TOKENS, -1));
 | 
| 
 1737 | 
  
 |         } | 
| 
 1738 | 
  
 |  | 
| 
 1739 | 
  
 |          | 
| 
 1740 | 
  
 |  | 
| 
 1741 | 
  
 |  | 
| 
 1742 | 
  
 |  | 
| 
 1743 | 
  
 |  | 
| 
 1744 | 
 2932
 |         public void addToken(AddressToken token) {
 | 
| 
 1745 | 
 2932
 |             tokens.add(token);
 | 
| 
 1746 | 
  
 |         } | 
| 
 1747 | 
  
 |  | 
| 
 1748 | 
  
 |          | 
| 
 1749 | 
  
 |  | 
| 
 1750 | 
  
 |  | 
| 
 1751 | 
  
 |  | 
| 
 1752 | 
  
 |  | 
| 
 1753 | 
  
 |  | 
| 
 1754 | 
 8904
 |         public AddressToken nextToken() {
 | 
| 
 1755 | 
 8904
 |             AddressToken token = (AddressToken)tokens.get(currentToken++);
 | 
| 
 1756 | 
  
 |              | 
| 
 1757 | 
  
 |              | 
| 
 1758 | 
 8904
 |             while (token.type == WHITESPACE) {
 | 
| 
 1759 | 
 255
 |                 token = (AddressToken)tokens.get(currentToken++);
 | 
| 
 1760 | 
  
 |             } | 
| 
 1761 | 
 8904
 |             return token;
 | 
| 
 1762 | 
  
 |         } | 
| 
 1763 | 
  
 |  | 
| 
 1764 | 
  
 |  | 
| 
 1765 | 
  
 |          | 
| 
 1766 | 
  
 |  | 
| 
 1767 | 
  
 |  | 
| 
 1768 | 
  
 |  | 
| 
 1769 | 
  
 |  | 
| 
 1770 | 
  
 |  | 
| 
 1771 | 
 97
 |         public AddressToken currentToken() {
 | 
| 
 1772 | 
  
 |              | 
| 
 1773 | 
 97
 |             return (AddressToken)tokens.get(currentToken);
 | 
| 
 1774 | 
  
 |         } | 
| 
 1775 | 
  
 |  | 
| 
 1776 | 
  
 |  | 
| 
 1777 | 
  
 |          | 
| 
 1778 | 
  
 |  | 
| 
 1779 | 
  
 |  | 
| 
 1780 | 
  
 |  | 
| 
 1781 | 
  
 |  | 
| 
 1782 | 
  
 |  | 
| 
 1783 | 
 4335
 |         public AddressToken nextRealToken()
 | 
| 
 1784 | 
  
 |         { | 
| 
 1785 | 
 4335
 |             AddressToken token = nextToken();
 | 
| 
 1786 | 
 4335
 |             if (token.type == COMMENT) {
 | 
| 
 1787 | 
 0
 |                 token = nextToken();
 | 
| 
 1788 | 
  
 |             } | 
| 
 1789 | 
 4335
 |             return token;
 | 
| 
 1790 | 
  
 |         } | 
| 
 1791 | 
  
 |  | 
| 
 1792 | 
  
 |          | 
| 
 1793 | 
  
 |  | 
| 
 1794 | 
  
 |  | 
| 
 1795 | 
  
 |  | 
| 
 1796 | 
  
 |  | 
| 
 1797 | 
  
 |  | 
| 
 1798 | 
 1615
 |         public void pushToken(AddressToken token) {
 | 
| 
 1799 | 
  
 |              | 
| 
 1800 | 
 1615
 |             currentToken = tokenIndex(token);
 | 
| 
 1801 | 
  
 |         } | 
| 
 1802 | 
  
 |  | 
| 
 1803 | 
  
 |          | 
| 
 1804 | 
  
 |  | 
| 
 1805 | 
  
 |  | 
| 
 1806 | 
  
 |  | 
| 
 1807 | 
  
 |  | 
| 
 1808 | 
  
 |  | 
| 
 1809 | 
  
 |  | 
| 
 1810 | 
  
 |  | 
| 
 1811 | 
 0
 |         public AddressToken nextToken(AddressToken token) {
 | 
| 
 1812 | 
 0
 |             return (AddressToken)tokens.get(tokenIndex(token) + 1);
 | 
| 
 1813 | 
  
 |         } | 
| 
 1814 | 
  
 |  | 
| 
 1815 | 
  
 |  | 
| 
 1816 | 
  
 |          | 
| 
 1817 | 
  
 |  | 
| 
 1818 | 
  
 |  | 
| 
 1819 | 
  
 |  | 
| 
 1820 | 
  
 |  | 
| 
 1821 | 
  
 |  | 
| 
 1822 | 
  
 |  | 
| 
 1823 | 
 241
 |         public AddressToken previousToken(AddressToken token) {
 | 
| 
 1824 | 
 241
 |             return (AddressToken)tokens.get(tokenIndex(token) - 1);
 | 
| 
 1825 | 
  
 |         } | 
| 
 1826 | 
  
 |  | 
| 
 1827 | 
  
 |  | 
| 
 1828 | 
  
 |          | 
| 
 1829 | 
  
 |  | 
| 
 1830 | 
  
 |  | 
| 
 1831 | 
  
 |  | 
| 
 1832 | 
  
 |  | 
| 
 1833 | 
 0
 |         public AddressToken getToken(int index)
 | 
| 
 1834 | 
  
 |         { | 
| 
 1835 | 
 0
 |             return (AddressToken)tokens.get(index);
 | 
| 
 1836 | 
  
 |         } | 
| 
 1837 | 
  
 |  | 
| 
 1838 | 
  
 |  | 
| 
 1839 | 
  
 |          | 
| 
 1840 | 
  
 |  | 
| 
 1841 | 
  
 |  | 
| 
 1842 | 
  
 |  | 
| 
 1843 | 
  
 |  | 
| 
 1844 | 
  
 |  | 
| 
 1845 | 
  
 |  | 
| 
 1846 | 
  
 |  | 
| 
 1847 | 
 2630
 |         public int tokenIndex(AddressToken token) {
 | 
| 
 1848 | 
 2630
 |             return tokens.indexOf(token);
 | 
| 
 1849 | 
  
 |         } | 
| 
 1850 | 
  
 |  | 
| 
 1851 | 
  
 |  | 
| 
 1852 | 
  
 |          | 
| 
 1853 | 
  
 |  | 
| 
 1854 | 
  
 |  | 
| 
 1855 | 
  
 |  | 
| 
 1856 | 
  
 |  | 
| 
 1857 | 
  
 |  | 
| 
 1858 | 
  
 |  | 
| 
 1859 | 
  
 |  | 
| 
 1860 | 
  
 |  | 
| 
 1861 | 
 387
 |         public TokenStream section(AddressToken start, AddressToken end) {
 | 
| 
 1862 | 
 387
 |             int startIndex = tokenIndex(start);
 | 
| 
 1863 | 
 387
 |             int endIndex = tokenIndex(end);
 | 
| 
 1864 | 
  
 |  | 
| 
 1865 | 
  
 |              | 
| 
 1866 | 
  
 |              | 
| 
 1867 | 
  
 |              | 
| 
 1868 | 
 387
 |             ArrayList list = new ArrayList(endIndex - startIndex + 2);
 | 
| 
 1869 | 
  
 |  | 
| 
 1870 | 
 387
 |             for (int i = startIndex; i <= endIndex; i++) {
 | 
| 
 1871 | 
 2222
 |                 list.add(tokens.get(i));
 | 
| 
 1872 | 
  
 |             } | 
| 
 1873 | 
 387
 |             return new TokenStream(list);
 | 
| 
 1874 | 
  
 |         } | 
| 
 1875 | 
  
 |  | 
| 
 1876 | 
  
 |  | 
| 
 1877 | 
  
 |          | 
| 
 1878 | 
  
 |  | 
| 
 1879 | 
  
 |  | 
| 
 1880 | 
  
 |  | 
| 
 1881 | 
 317
 |         public void reset() {
 | 
| 
 1882 | 
 317
 |             currentToken = 0;
 | 
| 
 1883 | 
  
 |         } | 
| 
 1884 | 
  
 |  | 
| 
 1885 | 
  
 |          | 
| 
 1886 | 
  
 |  | 
| 
 1887 | 
  
 |  | 
| 
 1888 | 
  
 |  | 
| 
 1889 | 
  
 |  | 
| 
 1890 | 
 30
 |         public AddressToken getNonBlank()
 | 
| 
 1891 | 
  
 |         { | 
| 
 1892 | 
 30
 |             AddressToken token = currentToken();
 | 
| 
 1893 | 
 30
 |             while (token.type == WHITESPACE) {
 | 
| 
 1894 | 
 0
 |                 currentToken++;
 | 
| 
 1895 | 
 0
 |                 token = currentToken();
 | 
| 
 1896 | 
  
 |             } | 
| 
 1897 | 
 30
 |             return token;
 | 
| 
 1898 | 
  
 |         } | 
| 
 1899 | 
  
 |  | 
| 
 1900 | 
  
 |  | 
| 
 1901 | 
  
 |          | 
| 
 1902 | 
  
 |  | 
| 
 1903 | 
  
 |  | 
| 
 1904 | 
  
 |  | 
| 
 1905 | 
  
 |  | 
| 
 1906 | 
  
 |  | 
| 
 1907 | 
  
 |  | 
| 
 1908 | 
 30
 |         public TokenStream getBlankDelimitedToken()
 | 
| 
 1909 | 
  
 |         { | 
| 
 1910 | 
  
 |              | 
| 
 1911 | 
 30
 |             AddressToken first = getNonBlank();
 | 
| 
 1912 | 
  
 |              | 
| 
 1913 | 
 30
 |             if (first.type == END_OF_TOKENS) {
 | 
| 
 1914 | 
 15
 |                 return null;
 | 
| 
 1915 | 
  
 |             } | 
| 
 1916 | 
  
 |  | 
| 
 1917 | 
 15
 |             AddressToken last = first;
 | 
| 
 1918 | 
  
 |  | 
| 
 1919 | 
  
 |              | 
| 
 1920 | 
  
 |              | 
| 
 1921 | 
 15
 |             currentToken++;
 | 
| 
 1922 | 
  
 |  | 
| 
 1923 | 
 15
 |             AddressToken token = currentToken();
 | 
| 
 1924 | 
 15
 |             while (true) {
 | 
| 
 1925 | 
  
 |                  | 
| 
 1926 | 
 67
 |                 if (token.type == END_OF_TOKENS || token.type == WHITESPACE) {
 | 
| 
 1927 | 
 15
 |                     return section(first, last);
 | 
| 
 1928 | 
  
 |                 } | 
| 
 1929 | 
 52
 |                 last = token;
 | 
| 
 1930 | 
 52
 |                 currentToken++;
 | 
| 
 1931 | 
  
 |                  | 
| 
 1932 | 
 52
 |                 token = currentToken();
 | 
| 
 1933 | 
  
 |             } | 
| 
 1934 | 
  
 |         } | 
| 
 1935 | 
  
 |  | 
| 
 1936 | 
  
 |          | 
| 
 1937 | 
  
 |  | 
| 
 1938 | 
  
 |  | 
| 
 1939 | 
  
 |  | 
| 
 1940 | 
  
 |  | 
| 
 1941 | 
 0
 |         public int currentIndex() {
 | 
| 
 1942 | 
 0
 |             return currentToken;
 | 
| 
 1943 | 
  
 |         } | 
| 
 1944 | 
  
 |  | 
| 
 1945 | 
 0
 |         public void dumpTokens()
 | 
| 
 1946 | 
  
 |         { | 
| 
 1947 | 
 0
 |             System.out.println(">>>>>>>>> Start dumping TokenStream tokens");
 | 
| 
 1948 | 
 0
 |             for (int i = 0; i < tokens.size(); i++) {
 | 
| 
 1949 | 
 0
 |                 System.out.println("-------- Token: " + tokens.get(i));
 | 
| 
 1950 | 
  
 |             } | 
| 
 1951 | 
  
 |  | 
| 
 1952 | 
 0
 |             System.out.println("++++++++ cursor position=" + currentToken);
 | 
| 
 1953 | 
 0
 |             System.out.println(">>>>>>>>> End dumping TokenStream tokens");
 | 
| 
 1954 | 
  
 |         } | 
| 
 1955 | 
  
 |     } | 
| 
 1956 | 
  
 |  | 
| 
 1957 | 
  
 |  | 
| 
 1958 | 
  
 |      | 
| 
 1959 | 
  
 |  | 
| 
 1960 | 
  
 |  | 
| 
 1961 | 
  
 |     public class AddressToken { | 
| 
 1962 | 
  
 |  | 
| 
 1963 | 
  
 |          | 
| 
 1964 | 
  
 |         int type; | 
| 
 1965 | 
  
 |  | 
| 
 1966 | 
  
 |          | 
| 
 1967 | 
  
 |         String value; | 
| 
 1968 | 
  
 |  | 
| 
 1969 | 
  
 |          | 
| 
 1970 | 
  
 |         int position; | 
| 
 1971 | 
  
 |  | 
| 
 1972 | 
 2025
 |         AddressToken(int type, int position)
 | 
| 
 1973 | 
  
 |         { | 
| 
 1974 | 
 2025
 |             this.type = type;
 | 
| 
 1975 | 
 2025
 |             this.value = null;
 | 
| 
 1976 | 
 2025
 |             this.position = position;
 | 
| 
 1977 | 
  
 |         } | 
| 
 1978 | 
  
 |  | 
| 
 1979 | 
 1294
 |         AddressToken(String value, int type, int position)
 | 
| 
 1980 | 
  
 |         { | 
| 
 1981 | 
 1294
 |             this.type = type;
 | 
| 
 1982 | 
 1294
 |             this.value = value;
 | 
| 
 1983 | 
 1294
 |             this.position = position;
 | 
| 
 1984 | 
  
 |         } | 
| 
 1985 | 
  
 |  | 
| 
 1986 | 
 0
 |         public String toString()
 | 
| 
 1987 | 
  
 |         { | 
| 
 1988 | 
 0
 |             if (type == END_OF_TOKENS) {
 | 
| 
 1989 | 
 0
 |                 return "AddressToken:  type=END_OF_TOKENS";
 | 
| 
 1990 | 
  
 |             } | 
| 
 1991 | 
 0
 |             if (value == null) {
 | 
| 
 1992 | 
 0
 |                 return "AddressToken:  type=" + (char)type;
 | 
| 
 1993 | 
  
 |             } | 
| 
 1994 | 
  
 |             else { | 
| 
 1995 | 
 0
 |                 return "AddressToken:  type=" + (char)type + " value=" + value;
 | 
| 
 1996 | 
  
 |             } | 
| 
 1997 | 
  
 |         } | 
| 
 1998 | 
  
 |     } | 
| 
 1999 | 
  
 | } | 
| 
 2000 | 
  
 |  |