1 28 29 package HTTPClient; 30 31 32 import java.io.IOException ; 33 import java.net.ProtocolException ; 34 import java.util.Vector ; 35 import java.util.Hashtable ; 36 import java.util.Enumeration ; 37 38 39 88 89 public class AuthorizationInfo implements GlobalConstants, Cloneable 90 { 91 93 94 private static Hashtable CntxtList = new Hashtable (); 95 96 97 private static AuthorizationHandler 98 AuthHandler = new DefaultAuthHandler(); 99 100 static 101 { 102 CntxtList.put(HTTPConnection.getDefaultContext(), new Hashtable ()); 103 } 104 105 106 108 109 private String host; 110 111 112 private int port; 113 114 117 private String scheme; 118 119 120 private String realm; 121 122 124 private String cookie; 125 126 127 private NVPair[] auth_params = new NVPair[0]; 128 129 130 private Object extra_info = null; 131 132 133 private String [] paths = new String [0]; 134 135 136 138 144 AuthorizationInfo(String host, int port) 145 { 146 this.host = host.trim().toLowerCase(); 147 this.port = port; 148 } 149 150 151 162 public AuthorizationInfo(String host, int port, String scheme, 163 String realm, NVPair params[], Object info) 164 { 165 this.scheme = scheme.trim(); 166 this.host = host.trim().toLowerCase(); 167 this.port = port; 168 this.realm = realm; 169 this.cookie = null; 170 171 if (params != null) 172 auth_params = Util.resizeArray(params, params.length); 173 174 this.extra_info = info; 175 } 176 177 178 191 public AuthorizationInfo(String host, int port, String scheme, 192 String realm, String cookie) 193 { 194 this.scheme = scheme.trim(); 195 this.host = host.trim().toLowerCase(); 196 this.port = port; 197 this.realm = realm; 198 if (cookie != null) 199 this.cookie = cookie.trim(); 200 else 201 this.cookie = null; 202 } 203 204 205 210 AuthorizationInfo(AuthorizationInfo templ) 211 { 212 this.scheme = templ.scheme; 213 this.host = templ.host; 214 this.port = templ.port; 215 this.realm = templ.realm; 216 this.cookie = templ.cookie; 217 218 this.auth_params = 219 Util.resizeArray(templ.auth_params, templ.auth_params.length); 220 221 this.extra_info = templ.extra_info; 222 } 223 224 225 227 242 public static AuthorizationHandler 243 setAuthHandler(AuthorizationHandler handler) 244 { 245 AuthorizationHandler tmp = AuthHandler; 246 AuthHandler = handler; 247 248 return tmp; 249 } 250 251 252 258 public static AuthorizationHandler getAuthHandler() 259 { 260 return AuthHandler; 261 } 262 263 264 274 public static AuthorizationInfo getAuthorization( 275 String host, int port, 276 String scheme, String realm) 277 { 278 return getAuthorization(host, port, scheme, realm, 279 HTTPConnection.getDefaultContext()); 280 } 281 282 283 294 public static synchronized AuthorizationInfo getAuthorization( 295 String host, int port, 296 String scheme, String realm, 297 Object context) 298 { 299 Hashtable AuthList = Util.getList(CntxtList, context); 300 301 AuthorizationInfo auth_info = 302 new AuthorizationInfo(host.trim(), port, scheme.trim(), 303 realm, (NVPair[]) null, null); 304 305 return (AuthorizationInfo) AuthList.get(auth_info); 306 } 307 308 309 322 static AuthorizationInfo queryAuthHandler(AuthorizationInfo auth_info, 323 RoRequest req, RoResponse resp) 324 throws AuthSchemeNotImplException 325 { 326 if (AuthHandler == null) 327 return null; 328 329 AuthorizationInfo new_info = 330 AuthHandler.getAuthorization(auth_info, req, resp); 331 if (new_info != null) 332 { 333 if (req != null) 334 addAuthorization((AuthorizationInfo) new_info.clone(), 335 req.getConnection().getContext()); 336 else 337 addAuthorization((AuthorizationInfo) new_info.clone(), 338 HTTPConnection.getDefaultContext()); 339 } 340 341 return new_info; 342 } 343 344 345 357 static synchronized AuthorizationInfo getAuthorization( 358 AuthorizationInfo auth_info, RoRequest req, 359 RoResponse resp, boolean query_auth_h) 360 throws AuthSchemeNotImplException 361 { 362 Hashtable AuthList; 363 if (req != null) 364 AuthList = Util.getList(CntxtList, req.getConnection().getContext()); 365 else 366 AuthList = Util.getList(CntxtList, HTTPConnection.getDefaultContext()); 367 368 AuthorizationInfo new_info = 369 (AuthorizationInfo) AuthList.get(auth_info); 370 371 if (new_info == null && query_auth_h) 372 new_info = queryAuthHandler(auth_info, req, resp); 373 374 return new_info; 375 } 376 377 378 390 static AuthorizationInfo getAuthorization(String host, int port, 391 String scheme, String realm, 392 boolean query_auth_h) 393 throws AuthSchemeNotImplException 394 { 395 return getAuthorization(new AuthorizationInfo(host.trim(), port, 396 scheme.trim(), realm, (NVPair[]) null, null), 397 null, null, query_auth_h); 398 } 399 400 401 408 public static void addAuthorization(AuthorizationInfo auth_info) 409 { 410 addAuthorization(auth_info, HTTPConnection.getDefaultContext()); 411 } 412 413 414 422 public static void addAuthorization(AuthorizationInfo auth_info, 423 Object context) 424 { 425 Hashtable AuthList = Util.getList(CntxtList, context); 426 427 AuthorizationInfo old_info = 429 (AuthorizationInfo) AuthList.get(auth_info); 430 if (old_info != null) 431 { 432 int ol = old_info.paths.length, 433 al = auth_info.paths.length; 434 435 if (al == 0) 436 auth_info.paths = old_info.paths; 437 else 438 { 439 auth_info.paths = Util.resizeArray(auth_info.paths, al+ol); 440 System.arraycopy(old_info.paths, 0, auth_info.paths, al, ol); 441 } 442 } 443 444 AuthList.put(auth_info, auth_info); 445 } 446 447 448 461 public static void addAuthorization(String host, int port, String scheme, 462 String realm, String cookie, 463 NVPair params[], Object info) 464 { 465 addAuthorization(host, port, scheme, realm, cookie, params, info, 466 HTTPConnection.getDefaultContext()); 467 } 468 469 470 484 public static void addAuthorization(String host, int port, String scheme, 485 String realm, String cookie, 486 NVPair params[], Object info, 487 Object context) 488 { 489 AuthorizationInfo auth = 490 new AuthorizationInfo(host, port, scheme, realm, cookie); 491 if (params != null && params.length > 0) 492 auth.auth_params = Util.resizeArray(params, params.length); 493 auth.extra_info = info; 494 495 addAuthorization(auth, context); 496 } 497 498 499 510 public static void addBasicAuthorization(String host, int port, 511 String realm, String user, 512 String passwd) 513 { 514 addAuthorization(host, port, "Basic", realm, 515 Codecs.base64Encode(user + ":" + passwd), 516 (NVPair[]) null, null); 517 } 518 519 520 532 public static void addBasicAuthorization(String host, int port, 533 String realm, String user, 534 String passwd, Object context) 535 { 536 addAuthorization(host, port, "Basic", realm, 537 Codecs.base64Encode(user + ":" + passwd), 538 (NVPair[]) null, null, context); 539 } 540 541 542 553 public static void addDigestAuthorization(String host, int port, 554 String realm, String user, 555 String passwd) 556 { 557 addDigestAuthorization(host, port, realm, user, passwd, 558 HTTPConnection.getDefaultContext()); 559 } 560 561 562 574 public static void addDigestAuthorization(String host, int port, 575 String realm, String user, 576 String passwd, Object context) 577 { 578 AuthorizationInfo prev = 579 getAuthorization(host, port, "Digest", realm, context); 580 NVPair[] params; 581 582 if (prev == null) 583 { 584 params = new NVPair[4]; 585 params[0] = new NVPair("username", user); 586 params[1] = new NVPair("uri", ""); 587 params[2] = new NVPair("nonce", ""); 588 params[3] = new NVPair("response", ""); 589 } 590 else 591 { 592 params = prev.getParams(); 593 for (int idx=0; idx<params.length; idx++) 594 { 595 if (params[idx].getName().equalsIgnoreCase("username")) 596 { 597 params[idx] = new NVPair("username", user); 598 break; 599 } 600 } 601 } 602 603 String [] extra = { new MD5(user + ":" + realm + ":" + passwd).asHex(), 604 null }; 605 606 addAuthorization(host, port, "Digest", realm, null, params, extra, 607 context); 608 } 609 610 611 618 public static void removeAuthorization(AuthorizationInfo auth_info) 619 { 620 removeAuthorization(auth_info, HTTPConnection.getDefaultContext()); 621 } 622 623 624 631 public static void removeAuthorization(AuthorizationInfo auth_info, 632 Object context) 633 { 634 Hashtable AuthList = Util.getList(CntxtList, context); 635 AuthList.remove(auth_info); 636 } 637 638 639 649 public static void removeAuthorization(String host, int port, String scheme, 650 String realm) 651 { 652 removeAuthorization( 653 new AuthorizationInfo(host, port, scheme, realm, (NVPair[]) null, 654 null)); 655 } 656 657 658 668 public static void removeAuthorization(String host, int port, String scheme, 669 String realm, Object context) 670 { 671 removeAuthorization( 672 new AuthorizationInfo(host, port, scheme, realm, (NVPair[]) null, 673 null), context); 674 } 675 676 677 687 static AuthorizationInfo findBest(RoRequest req) 688 { 689 String path = Util.getPath(req.getRequestURI()); 690 String host = req.getConnection().getHost(); 691 int port = req.getConnection().getPort(); 692 693 694 696 Hashtable AuthList = 697 Util.getList(CntxtList, req.getConnection().getContext()); 698 Enumeration list = AuthList.elements(); 699 while (list.hasMoreElements()) 700 { 701 AuthorizationInfo info = (AuthorizationInfo) list.nextElement(); 702 703 if (!info.host.equals(host) || info.port != port) 704 continue; 705 706 String [] paths = info.paths; 707 for (int idx=0; idx<paths.length; idx++) 708 { 709 if (path.equals(paths[idx])) 710 return info; 711 } 712 } 713 714 715 717 AuthorizationInfo best = null; 718 String base = path.substring(0, path.lastIndexOf('/')+1); 719 int min = Integer.MAX_VALUE; 720 721 list = AuthList.elements(); 722 while (list.hasMoreElements()) 723 { 724 AuthorizationInfo info = (AuthorizationInfo) list.nextElement(); 725 726 if (!info.host.equals(host) || info.port != port) 727 continue; 728 729 String [] paths = info.paths; 730 for (int idx=0; idx<paths.length; idx++) 731 { 732 String ibase = 734 paths[idx].substring(0, paths[idx].lastIndexOf('/')+1); 735 736 if (base.equals(ibase)) 737 return info; 738 739 if (base.startsWith(ibase)) { 741 int num_seg = 0, pos = ibase.length()-1; 742 while ((pos = base.indexOf('/', pos+1)) != -1) num_seg++; 743 744 if (num_seg < min) 745 { 746 min = num_seg; 747 best = info; 748 } 749 } 750 else if (ibase.startsWith(base)) { 752 int num_seg = 0, pos = base.length(); 753 while ((pos = ibase.indexOf('/', pos+1)) != -1) num_seg++; 754 755 if (num_seg < min) 756 { 757 min = num_seg; 758 best = info; 759 } 760 } 761 } 762 } 763 764 return best; 765 } 766 767 768 774 public synchronized void addPath(String resource) 775 { 776 String path = Util.getPath(resource); 777 778 for (int idx=0; idx<paths.length; idx++) 780 if (paths[idx].equals(path)) return; 781 782 paths = Util.resizeArray(paths, paths.length+1); 784 paths[paths.length-1] = path; 785 } 786 787 788 799 static AuthorizationInfo[] parseAuthString(String challenge, RoRequest req, 800 RoResponse resp) 801 throws ProtocolException 802 { 803 int beg = 0, 804 end = 0; 805 char[] buf = challenge.toCharArray(); 806 char ch; 807 int len = buf.length; 808 809 AuthorizationInfo auth_arr[] = new AuthorizationInfo[0], 810 curr; 811 812 while (Character.isSpace(buf[len-1])) len--; 813 814 while (true) { 816 beg = Util.skipSpace(buf, beg); 818 if (beg == len) break; 819 820 end = Util.findSpace(buf, beg+1); 821 822 int sts; 823 try 824 { sts = resp.getStatusCode(); } 825 catch (IOException ioe) 826 { throw new ProtocolException (ioe.toString()); } 827 if (sts == 401) 828 curr = new AuthorizationInfo(req.getConnection().getHost(), 829 req.getConnection().getPort()); 830 else 831 curr = new AuthorizationInfo(req.getConnection().getProxyHost(), 832 req.getConnection().getProxyPort()); 833 curr.scheme = challenge.substring(beg, end); 834 835 boolean first = true; 837 Vector params = new Vector (); 838 while (true) 839 { 840 beg = Util.skipSpace(buf, end); 841 if (beg == len) break; 842 843 if (!first) { 845 if (buf[beg] != ',') 846 throw new ProtocolException ("Bad Authentication header " 847 + "format: '" + challenge + 848 "'\nExpected \",\" at position "+ 849 beg); 850 851 beg = Util.skipSpace(buf, beg+1); if (beg == len) break; 853 if (buf[beg] == ',') { 855 end = beg; 856 continue; 857 } 858 } 859 860 int pstart = beg; 861 862 end = beg + 1; 864 while (end < len && !Character.isSpace(buf[end]) && 865 buf[end] != '=' && buf[end] != ',') 866 end++; 867 868 if (first && 870 (end == len || buf[end] == '=' && 871 (end+1 == len || (buf[end+1] == '=' && end+2 == len)))) 872 { 873 curr.cookie = challenge.substring(beg, len); 874 beg = len; 875 break; 876 } 877 878 String param_name = challenge.substring(beg, end), 879 param_value; 880 881 beg = Util.skipSpace(buf, end); 883 if (beg < len && buf[beg] != '=' && buf[beg] != ',') 884 { beg = pstart; 886 break; 887 } 888 889 890 if (buf[beg] == '=') { 892 beg = Util.skipSpace(buf, beg+1); 893 if (beg == len) 894 throw new ProtocolException ("Bad Authentication header " 895 + "format: " + challenge + 896 "\nUnexpected EOL after token" + 897 " at position " + (end-1)); 898 if (buf[beg] != '"') { 900 end = Util.skipToken(buf, beg); 901 if (end == beg) 902 throw new ProtocolException ("Bad Authentication header " 903 + "format: " + challenge + "\nToken expected at " + 904 "position " + beg); 905 param_value = challenge.substring(beg, end); 906 } 907 else { 909 end = beg++; 910 do 911 end = challenge.indexOf('"', end+1); 912 while (end != -1 && challenge.charAt(end-1) == '\\'); 913 if (end == -1) 914 throw new ProtocolException ("Bad Authentication header " 915 + "format: " + challenge + "\nClosing <\"> for " 916 + "quoted-string starting at position " + beg 917 + " not found"); 918 param_value = 919 Util.dequoteString(challenge.substring(beg, end)); 920 end++; 921 } 922 } 923 else param_value = null; 925 926 if (param_name.equalsIgnoreCase("realm")) 927 curr.realm = param_value; 928 else 929 params.addElement(new NVPair(param_name, param_value)); 930 931 first = false; 932 } 933 934 if (!params.isEmpty()) 935 { 936 curr.auth_params = new NVPair[params.size()]; 937 params.copyInto(curr.auth_params); 938 } 939 940 if (curr.realm == null) 941 947 curr.realm = ""; 948 949 auth_arr = Util.resizeArray(auth_arr, auth_arr.length+1); 950 auth_arr[auth_arr.length-1] = curr; 951 } 952 953 return auth_arr; 954 } 955 956 957 959 964 public final String getHost() 965 { 966 return host; 967 } 968 969 970 975 public final int getPort() 976 { 977 return port; 978 } 979 980 981 986 public final String getScheme() 987 { 988 return scheme; 989 } 990 991 992 997 public final String getRealm() 998 { 999 return realm; 1000 } 1001 1002 1003 1009 public final String getCookie() 1010 { 1011 return cookie; 1012 } 1013 1014 1015 1021 public final void setCookie(String cookie) 1022 { 1023 this.cookie = cookie; 1024 } 1025 1026 1027 1032 public final NVPair[] getParams() 1033 { 1034 return Util.resizeArray(auth_params, auth_params.length); 1035 } 1036 1037 1038 1043 public final void setParams(NVPair[] params) 1044 { 1045 if (params != null) 1046 auth_params = Util.resizeArray(params, params.length); 1047 else 1048 auth_params = new NVPair[0]; 1049 } 1050 1051 1052 1057 public final Object getExtraInfo() 1058 { 1059 return extra_info; 1060 } 1061 1062 1063 1068 public final void setExtraInfo(Object info) 1069 { 1070 extra_info = info; 1071 } 1072 1073 1074 1080 public String toString() 1081 { 1082 StringBuffer field = new StringBuffer (100); 1083 1084 field.append(scheme); 1085 field.append(" "); 1086 1087 if (cookie != null) 1088 { 1089 field.append(cookie); 1090 } 1091 else 1092 { 1093 if (realm.length() > 0) 1094 { 1095 field.append("realm=\""); 1096 field.append(Util.quoteString(realm, "\\\"")); 1097 field.append('"'); 1098 } 1099 1100 for (int idx=0; idx<auth_params.length; idx++) 1101 { 1102 field.append(','); 1103 field.append(auth_params[idx].getName()); 1104 field.append("=\""); 1105 field.append( 1106 Util.quoteString(auth_params[idx].getValue(), "\\\"")); 1107 field.append('"'); 1108 } 1109 } 1110 1111 return field.toString(); 1112 } 1113 1114 1115 1122 public int hashCode() 1123 { 1124 return (host+scheme.toLowerCase()+realm).hashCode(); 1125 } 1126 1127 1137 public boolean equals(Object obj) 1138 { 1139 if ((obj != null) && (obj instanceof AuthorizationInfo)) 1140 { 1141 AuthorizationInfo auth = (AuthorizationInfo) obj; 1142 if (host.equals(auth.host) && 1143 (port == auth.port) && 1144 scheme.equalsIgnoreCase(auth.scheme) && 1145 realm.equals(auth.realm)) 1146 return true; 1147 } 1148 return false; 1149 } 1150 1151 1152 1155 public Object clone() 1156 { 1157 AuthorizationInfo ai; 1158 try 1159 { 1160 ai = (AuthorizationInfo) super.clone(); 1161 ai.auth_params = Util.resizeArray(auth_params, auth_params.length); 1162 try 1163 { 1164 ai.extra_info = extra_info.getClass().getMethod("clone", null). 1166 invoke(extra_info, null); 1167 } 1168 catch (Throwable t) 1169 { } 1170 ai.paths = new String [paths.length]; 1171 System.arraycopy(paths, 0, ai.paths, 0, paths.length); 1172 } 1173 catch (CloneNotSupportedException cnse) 1174 { throw new InternalError (cnse.toString()); } 1175 1176 return ai; 1177 } 1178} 1179 1180 | Popular Tags |