4 * License : The MIT License
5 * Copyright(c) 2008 olyutorskii
8 package jp.sfjp.jindolf.net;
10 import java.net.HttpURLConnection;
12 import java.net.URISyntaxException;
15 * 人狼BBSアカウント管理用のCookie。
16 * <p>JRE1.6 java.net.HttpCookie の代用品。
17 * <p>人狼BBSではCookieヘッダに"Set-Cookie"が用いられる。
19 * <p>人狼BBSではCookieの寿命管理に"Expires"が用いられる。(Max-Ageではない)
20 * <p>人狼BBSではセッション管理のCookie名に"login"が用いられる。
21 * @see <a href="http://www.ietf.org/rfc/rfc6265.txt">RFC6265</a>
23 class AccountCookie{ // TODO JRE 1.6対応とともにHttpCookieへ移行予定
25 private static final String HEADER_COOKIE = "Set-Cookie";
26 private static final String SEPARATOR = ";";
27 private static final String COOKIE_PATH = "Path";
28 private static final String COOKIE_EXPIRES = "Expires";
29 private static final String BBS_IDENTITY = "login";
32 private final String loginData;
33 private final URI pathURI;
34 private final long expireDate;
38 * @param loginData 認証データ
39 * @param path Cookieパス
40 * @param expireDate expire日付
41 * @throws java.lang.NullPointerException 引数がnull
42 * @throws java.lang.IllegalArgumentException パスが変
44 public AccountCookie(String loginData, String path, long expireDate)
45 throws NullPointerException, IllegalArgumentException{
48 if(loginData == null || path == null){
49 throw new NullPointerException();
52 this.loginData = loginData;
54 this.pathURI = new URI(path);
55 }catch(URISyntaxException e){
56 throw new IllegalArgumentException(path, e);
58 this.expireDate = expireDate;
64 * 文字列両端に連続するWSP(空白もしくはタブ)を取り除く。
66 * @return 取り除いた結果。引数がnullならnull
68 static String chopWsp(String txt){
69 if(txt == null) return null;
74 int len = txt.length();
75 for(int idx = 0; idx < len; idx++){
76 char ch = txt.charAt(idx);
77 if(ch != '\u0020' && ch != '\t'){
78 if(startPt < 0) startPt = idx;
83 if(startPt < 0) startPt = 0;
84 if(endPt < 0) endPt = 0;
86 String result = txt.substring(startPt, endPt);
93 * '='が無い属性(例:Secure)は値がnullになり、=付き空文字列とは区別される。
95 * @param pair '='を挟む名前と値のペア。
96 * @return [0]名前 [1]値 ※空文字列の名前およびnullな値がありうる。
98 static String[] splitPair(String pair){
99 String[] result = new String[2];
101 String[] split = pair.split("=", 2);
103 if(split.length >= 1){
104 result[0] = chopWsp(split[0]);
107 if(split.length >= 2){
108 result[1] = chopWsp(split[1]);
115 * 人狼BBS用ログインデータを抽出する。
117 * @param nameValue '='で区切られたCookie name-value構造
118 * @return 人狼BBS用ログインデータ。見つからなければnull
120 private static String parseLoginData(String nameValue){
121 String[] nvPair = splitPair(nameValue);
122 String name = nvPair[0];
123 String value = nvPair[1];
124 if(name.length() <= 0) return null; // 名前なし
125 if(value == null) return null; // '=' なし
127 if( ! BBS_IDENTITY.equals(name) ) return null;
134 * @param cookieSource HTTPヘッダ 「Set-Cookie」の値
137 public static AccountCookie createCookie(String cookieSource){
138 String[] cookiePart = cookieSource.split(SEPARATOR);
140 String login = parseLoginData(cookiePart[0]);
142 String expires = null;
144 int partNo = cookiePart.length;
145 for(int idx = 0 + 1; idx < partNo; idx++){
146 String pair = cookiePart[idx];
147 String[] attr = splitPair(pair);
148 String attrName = attr[0];
149 String attrValue = attr[1];
151 if(COOKIE_PATH.equalsIgnoreCase(attrName)){
153 }else if(COOKIE_EXPIRES.equalsIgnoreCase(attrName)){
158 if(login == null) return null;
159 if(path == null) return null;
160 if(expires == null) return null;
162 long expTime = CookieDateParser.parseToEpoch(expires);
163 if(expTime < 0L) return null;
165 AccountCookie cookie = new AccountCookie(login, path, expTime);
172 * @param connection HTTP接続
175 public static AccountCookie createCookie(HttpURLConnection connection){
176 String cookieHeader = connection.getHeaderField(HEADER_COOKIE);
177 if(cookieHeader == null) return null;
178 AccountCookie cookie = createCookie(cookieHeader);
184 * 取り扱い注意!人狼BBSでは機密情報だよ!
187 public String getLoginData(){
188 return this.loginData;
195 public URI getPathURI(){
200 * Cookie期限をエポック時刻で返す。
201 * @return Cookieが期限切れを起こす日時。(msec)
203 public long getExpiredTime(){
204 return this.expireDate;
208 * Cookie期限が切れてないか判定する。
209 * @param nowMs 比較時刻(msec)
210 * @return 期限が切れていたらtrue
212 public boolean hasExpired(long nowMs){
213 long expireMs = getExpiredTime();
214 if(expireMs < nowMs) return true;
219 * 現時点でCookie期限が切れてないか判定する。
220 * @return 期限が切れていたらtrue
222 public boolean hasExpired(){
223 long nowMs = System.currentTimeMillis();
224 boolean result = hasExpired(nowMs);