OSDN Git Service

Merge commit webブラウザとのセッション情報共有機能
authoryukihane <yukihane.feather@gmail.com>
Sun, 18 Sep 2011 03:28:59 +0000 (12:28 +0900)
committeryukihane <yukihane.feather@gmail.com>
Sun, 18 Sep 2011 03:28:59 +0000 (12:28 +0900)
13 files changed:
frontend/src/saccubus/net/Cookie.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieDefault.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieWinChromium.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieWinCrome.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieWinFirefox3.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieWinMsIe.java [new file with mode: 0644]
frontend/src/saccubus/net/CookieWinOpera.java [new file with mode: 0644]
frontend/src/saccubus/worker/impl/download/Download.java
frontend/src/saccubus/worker/profile/LoginProfile.java
frontend/src/yukihane/inqubus/config/Config.java
frontend/src/yukihane/inqubus/config/ConfigLoginProfile.java
frontend/src/yukihane/inqubus/gui/ConfigDialog.java
frontend/src/yukihane/inqubus/saccubus/prompt/DownloadProfileImpl.java

diff --git a/frontend/src/saccubus/net/Cookie.java b/frontend/src/saccubus/net/Cookie.java
new file mode 100644 (file)
index 0000000..cc6dc63
--- /dev/null
@@ -0,0 +1,115 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * ニコニコ動画のクッキーを扱うための基本クラスです.
+ * @author yuki
+ */
+public abstract class Cookie {
+
+    private static final Logger logger = LoggerFactory.getLogger(Cookie.class);
+    private static final Pattern USER_SESSION_PATTERN = Pattern.compile("(user_session_[\\d_]+)");
+
+    public enum BrowserType {
+
+        MSIE, FIREFOX, CHROME, CHROMIUM, OPERA, OTHER
+    }
+
+    public static Cookie create(BrowserType type, String dir) {
+        switch (type) {
+            case MSIE:
+                return new CookieWinMsIe();
+            case FIREFOX:
+                return new CookieWinFirefox();
+            case CHROME:
+                return new CookieWinCrome();
+            case CHROMIUM:
+                return new CookieWinChromium();
+            case OPERA:
+                return new CookieWinOpera();
+            default:
+                final File f = new File(dir);
+                return new CookieDefault(f);
+        }
+    }
+
+    /**
+     * cookieをmapで返します.
+     * @return cookie.
+     */
+    public Map<String, String> get() {
+        final Map<String, String> map = new HashMap<>();
+        try {
+            final String userSessionStr = getNicoUserSession();
+            if (StringUtils.isNotEmpty(userSessionStr)) {
+                map.put("user_session", userSessionStr);
+            }
+        } catch (IOException ex) {
+            logger.warn("cookieファイル読み込み失敗", ex);
+        }
+        return map;
+    }
+
+    /**
+     * ニコニコ動画ユーザセッション文字列を取得します.
+     * @return ユーザセッション文字列. 無ければ空文字列.
+     * @throws IOException cookie読み込み中のエラー.
+     */
+    protected abstract String getNicoUserSession() throws IOException;
+
+    /**
+     * クッキーファイルを見つけて user_session を返す.
+     * @param cookieFileOrDirs cookieが保存されたディレクトリの候補, あるいはcookieファイルの候補.
+     * @return ユーザセッション文字列. 無ければ空文字列.
+     */
+    protected final String getUserSession(String charsetName, File... cookieFileOrDirs) throws IOException {
+        for (File file : cookieFileOrDirs) {
+            if (file.isDirectory()) {
+                File[] files = file.listFiles();
+                for (File cookieFile : files) {
+                    if (cookieFile.isFile()) {
+                        final String userSession = cutUserSession(cookieFile, charsetName);
+                        if (StringUtils.isNotEmpty(userSession)) {
+                            return userSession;
+                        }
+                    }
+                }
+            } else if (file.isFile()) {
+                final String userSession = cutUserSession(file, charsetName);
+                if (StringUtils.isNotEmpty(userSession)) {
+                    return userSession;
+                }
+            }
+        }
+
+        return "";
+    }
+
+    /**
+     * 文字列から user_session_ で始まる文字列を切り出して返す。数字とアンダーバー以外の文字で切れる。
+     * @param cookieStr 切り出す対象文字列
+     * @return user_session 文字列。見つからない場合は空文字列。
+     */
+    protected final String getUserSession(final String cookieStr) {
+        final Matcher mather = USER_SESSION_PATTERN.matcher(cookieStr);
+        if (mather.find()) {
+            return mather.group(1);
+        }
+        return "";
+    }
+
+    private String cutUserSession(File cookieFile, String charsetName) throws IOException {
+        final String str = FileUtils.readFileToString(cookieFile, charsetName);
+        return getUserSession(str);
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieDefault.java b/frontend/src/saccubus/net/CookieDefault.java
new file mode 100644 (file)
index 0000000..deabf50
--- /dev/null
@@ -0,0 +1,22 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+
+/**
+ * 指定されたディレクトリのcookieを扱います.
+ * @author yuki
+ */
+class CookieDefault extends Cookie {
+
+    private final File fileOrDir;
+
+    CookieDefault(File fileOrDir) {
+        this.fileOrDir = fileOrDir;
+    }
+
+    @Override
+    protected String getNicoUserSession() throws IOException {
+        return getUserSession("UTF-8", fileOrDir);
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieWinChromium.java b/frontend/src/saccubus/net/CookieWinChromium.java
new file mode 100644 (file)
index 0000000..d385b80
--- /dev/null
@@ -0,0 +1,39 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Windows ChromiumのCookieディレクトリを決め打ちして扱います.
+ * @author orz (saccubus)
+ * @author yuki
+ */
+class CookieWinChromium extends Cookie {
+
+    private static final String CHROMIUM_PATH = "/Chromium/User Data/Default/Cookies";
+
+    @Override
+    protected String getNicoUserSession() throws IOException {
+        final String localAppData = System.getenv("LOCALAPPDATA");
+        if (StringUtils.isNotEmpty(localAppData)) {
+            // Win7 32bit
+            final File cookieFile = new File(localAppData + CHROMIUM_PATH);
+            if (cookieFile.isFile()) {
+                return getUserSession("UTF-8", cookieFile);
+            }
+        }
+
+        final String userProfile = System.getenv("USERPROFILE");
+        if (StringUtils.isNotEmpty(userProfile)) {
+            // XP 32bit
+            final File cookieFile = new File(userProfile + "/Local Settings/Application Data" + CHROMIUM_PATH);
+            if (cookieFile.isFile()) {
+                return getUserSession("UTF-8", cookieFile);
+            }
+        }
+
+        return "";
+
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieWinCrome.java b/frontend/src/saccubus/net/CookieWinCrome.java
new file mode 100644 (file)
index 0000000..66e1bea
--- /dev/null
@@ -0,0 +1,53 @@
+package saccubus.net;
+
+import static org.apache.commons.lang.StringUtils.*;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * WindowsのChrome cookie ディレクトリを決め打ちして扱います.
+ * @author rankingloid (nicorank)
+ * @author hazychill (nicorank)
+ * @author orz (saccubus)
+ * @author yuki
+ */
+class CookieWinCrome extends Cookie {
+
+    private static final Logger logger = LoggerFactory.getLogger(CookieWinCrome.class);
+    private static final String COOKIE_PATH = "/Google/Chrome/User Data/Default/Cookies";
+
+    /** <p>
+     *  Chrome から user_session を取得。エラーが起こった場合、例外を投げずに空文字を返す
+     *  </p>
+     *  @return user_session
+     */
+    @Override
+    protected String getNicoUserSession() throws IOException {
+        final List<File> alters = new ArrayList<>();
+
+        // Win7
+        final String localAppData = System.getenv("LOCALAPPDATA");
+        if (isNotEmpty(localAppData)) {
+            alters.add(new File(localAppData + COOKIE_PATH));
+        }
+
+        // WinXP
+        final String userProfile = System.getenv("USERPROFILE");
+        if (isNotEmpty(userProfile)) {
+            alters.add(new File(userProfile + "/Local Settings/Application Data" + COOKIE_PATH));
+        }
+
+        // ??? just try
+        final String appData = System.getenv("APPDATA");
+        if (isNotEmpty(appData)) {
+            alters.add(new File(appData + COOKIE_PATH));
+        }
+
+        return getUserSession("UTF-8", alters.toArray(new File[0]));
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieWinFirefox3.java b/frontend/src/saccubus/net/CookieWinFirefox3.java
new file mode 100644 (file)
index 0000000..2bfb77c
--- /dev/null
@@ -0,0 +1,38 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * WindowsのFirefox3 cookie ディレクトリを決め打ちして扱います.
+ * @author rankingloid (nicorank)
+ * @author hazychill (nicorank)
+ * @author orz (saccubus)
+ * @author yuki
+ * @deprecated ユーザプロファイルを切り替える設定を行っている場合にはおそらくうまく動きません.
+ */
+@Deprecated
+class CookieWinFirefox3 extends Cookie {
+
+    /**
+     * Firefox3 から user_session を取得。
+     * @return ユーザセッション文字列.
+     * @throws IOException 取得失敗.
+     */
+    @Override
+    protected String getNicoUserSession() throws IOException {
+        final String appData = System.getenv("APPDATA");
+        if (StringUtils.isNotEmpty(appData)) {
+            File sqlist_filename = new File(appData + "/Mozilla/Firefox/Profiles/cookies.sqlite");
+            if (sqlist_filename.isFile()) {
+                final String userSession = getUserSession("US-ASCII", sqlist_filename);
+                if (StringUtils.isNotEmpty(userSession)) {
+                    return userSession;
+                }
+            }
+        }
+
+        return "";
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieWinMsIe.java b/frontend/src/saccubus/net/CookieWinMsIe.java
new file mode 100644 (file)
index 0000000..26e9388
--- /dev/null
@@ -0,0 +1,41 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.List;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * WindowsのMS IE(7以降)のcookieを扱います.
+ * @author rankingloid (nicorank)
+ * @author hazychill (nicorank)
+ * @author orz (saccubus)
+ * @author yuki
+ */
+class CookieWinMsIe extends Cookie {
+
+    /** <p>
+     *  IE7/IE8/IE9 から user_session を取得。<br/>
+     *  エラーが起こった場合、例外を投げずに空文字を返す
+     *  </p>
+     *  @return user_session
+     */
+    @Override
+    protected String getNicoUserSession() throws IOException {
+
+        final String userProfile = System.getenv("USERPROFILE");
+
+        if (StringUtils.isNotEmpty(userProfile)) {
+            final List<File> searchDirs = new ArrayList<>();
+            // http://msdn.microsoft.com/en-us/library/aa385326(v=VS.85).aspx
+            searchDirs.add(new File(userProfile + "/AppData/Roaming/Microsoft/Windows/Cookies/Low/"));
+            searchDirs.add(new File(userProfile + "/AppData/Roaming/Microsoft/Windows/Cookies/"));
+            // これは何だ?
+            searchDirs.add(new File(userProfile + "/Cookies/"));
+
+            return getUserSession("MS932", searchDirs.toArray(new File[0]));
+        }
+        return "";
+    }
+}
diff --git a/frontend/src/saccubus/net/CookieWinOpera.java b/frontend/src/saccubus/net/CookieWinOpera.java
new file mode 100644 (file)
index 0000000..d320f66
--- /dev/null
@@ -0,0 +1,32 @@
+package saccubus.net;
+
+import java.io.File;
+import java.io.IOException;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * WindowsのOpera cookie ディレクトリを決め打ちして扱います.
+ * @author rankingloid (nicorank)
+ * @author hazychill (nicorank)
+ * @author orz (saccubus)
+ * @author yuki
+ */
+class CookieWinOpera extends Cookie {
+
+    /**
+     * Opera から user_session を取得。
+     * @return ユーザセッション文字列.
+     * @throws IOException 取得失敗.
+     */
+    @Override
+    protected String getNicoUserSession() throws IOException {
+        final String appData = System.getenv("APPDATA");
+
+        if (StringUtils.isNotEmpty(appData)) {
+            final File cookieFile = new File(appData + "/Opera/Opera/cookies4.dat");
+            return getUserSession("UTF-8", cookieFile);
+        }
+
+        return "";
+    }
+}
index 8a67234..898b7db 100644 (file)
@@ -102,7 +102,7 @@ public class Download extends Worker<DownloadResult, DownloadProgress> {
             final File file = new File(profile.getCommentProfile().getDir(), name);
 
             final EnumSet<DownloadCommentType> commentSet = EnumSet.of(DownloadCommentType.OWNER);
-            if(profile.getCommentProfile().isDisablePerMinComment()) {
+            if (profile.getCommentProfile().isDisablePerMinComment()) {
                 commentSet.add(DownloadCommentType.COMMENT_OLD);
             } else {
                 commentSet.add(DownloadCommentType.COMMENT);
@@ -149,10 +149,15 @@ public class Download extends Worker<DownloadResult, DownloadProgress> {
      */
     private NicoHttpClient createClientAndLogin() throws IOException, InterruptedException {
         final NicoHttpClient client = createClient(profile.getProxyProfile());
+        if (profile.getLoginProfile().needsLogin()) {
 
-        final boolean hasLogin = client.login(profile.getLoginProfile().getMail(), profile.getLoginProfile().getPassword());
-        if (!hasLogin) {
-            throw new IOException("login fail");
+            final boolean hasLogin = client.login(profile.getLoginProfile().getMail(), profile.getLoginProfile().
+                    getPassword());
+            if (!hasLogin) {
+                throw new IOException("login fail");
+            }
+        } else {
+            client.addCookie(profile.getLoginProfile().getCookies());
         }
 
         return client;
index 7f37bb5..3079e8d 100644 (file)
@@ -1,14 +1,25 @@
 package saccubus.worker.profile;
 
+import java.util.Map;
+
 /**
  * ニコニコ動画サービスへのログイン情報を保持するためのプロファイルです.
  * @author yuki
  */
 public interface LoginProfile {
 
+    /** @return ログイン情報を使用してログインする場合はtrue, cookieを使用する場合はfalse. */
+    boolean needsLogin();
+
     /** @return ログインID(メールアドレス). */
-    public String getMail();
+    String getMail();
 
     /** @return ログインパスワード. */
-    public String getPassword();
+    String getPassword();
+
+    /**
+     * @return 追加のCookie.
+     * {@link #needsLogin()} がfalseの場合, ここにユーザセッション情報を含める必要があります.
+     */
+    Map<String, String> getCookies();
 }
index 9499567..1b94606 100644 (file)
@@ -5,10 +5,54 @@ import java.util.ArrayList;
 import java.util.List;
 import org.apache.commons.configuration.ConfigurationException;
 import org.apache.commons.configuration.XMLConfiguration;
+import saccubus.net.Cookie.BrowserType;
 
 public enum Config {
 
     INSTANCE;
+
+    public enum CookieBrowser {
+
+        MSIE {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.MSIE;
+            }
+        }, FIREFOX {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.FIREFOX;
+            }
+        }, CHROME {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.CHROME;
+            }
+        }, CHROMIUM {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.CHROMIUM;
+            }
+        }, OPERA {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.OPERA;
+            }
+        }, OTHER {
+
+            @Override
+            public BrowserType toBrowserType() {
+                return BrowserType.OTHER;
+            }
+        };
+
+        public abstract BrowserType toBrowserType();
+    }
     private final XMLConfiguration config = new XMLConfiguration();
 
     void clear() {
@@ -18,6 +62,15 @@ public enum Config {
     /*
      * ネットワーク - アカウント
      */
+    private static final String LOGIN_NEED = "network.login";
+
+    public boolean getNeedsLogin() {
+        return config.getBoolean(LOGIN_NEED, true);
+    }
+
+    public void setNeedsLogin(boolean s) {
+        config.setProperty(LOGIN_NEED, s);
+    }
     private static final String ACCOUNT_ID = "network.account.id";
 
     public String getId() {
@@ -36,7 +89,25 @@ public enum Config {
     public void setPassword(String s) {
         config.setProperty(ACCOUNT_PASSWORD, s);
     }
+    private static final String COOKIE_BROWSER = "network.cookie.browser";
+
+    public CookieBrowser getCookieBrowser() {
+        final String str = config.getString(COOKIE_BROWSER, CookieBrowser.MSIE.name());
+        return CookieBrowser.valueOf(str);
+    }
 
+    public void setCookieBrowser(CookieBrowser s) {
+        config.setProperty(COOKIE_BROWSER, s.name());
+    }
+    private static final String COOKIE_DIR = "network.cookie.dir";
+
+    public String getCookieDir() {
+        return config.getString(COOKIE_DIR, "");
+    }
+
+    public void setCookieDir(String s) {
+        config.setProperty(COOKIE_DIR, s);
+    }
     /*
      * ネットワーク - プロキシ
      */
index 29cdbf2..8b4191c 100644 (file)
@@ -1,7 +1,11 @@
 package yukihane.inqubus.config;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.apache.commons.lang.builder.ToStringBuilder;
+import saccubus.net.Cookie;
 import saccubus.worker.profile.LoginProfile;
+import yukihane.inqubus.config.Config.CookieBrowser;
 
 /**
  * コンフィグに設定された値を基にしたLoginProfile実装.
@@ -9,13 +13,26 @@ import saccubus.worker.profile.LoginProfile;
  */
 public class ConfigLoginProfile implements LoginProfile {
 
+    private final boolean login;
     private final String mail;
     private final String password;
+    private final Map<String, String> cookies;
 
     public ConfigLoginProfile() {
         final Config p = Config.INSTANCE;
+        this.login = p.getNeedsLogin();
         this.mail = p.getId();
         this.password = p.getPassword();
+
+        final CookieBrowser cookieBrowser = p.getCookieBrowser();
+        final String cookieDir = p.getCookieDir();
+        final Cookie cookie = Cookie.create(cookieBrowser.toBrowserType(), cookieDir);
+        this.cookies = new HashMap<>(cookie.get());
+    }
+
+    @Override
+    public boolean needsLogin() {
+        return this.login;
     }
 
     @Override
@@ -29,6 +46,11 @@ public class ConfigLoginProfile implements LoginProfile {
     }
 
     @Override
+    public Map<String, String> getCookies() {
+        return new HashMap<>(this.cookies);
+    }
+
+    @Override
     public String toString() {
         return ToStringBuilder.reflectionToString(this);
     }
index ab1bbf0..ea338f9 100644 (file)
@@ -15,6 +15,7 @@ import java.util.List;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
 import javax.swing.ComboBoxModel;
 import javax.swing.DefaultComboBoxModel;
 import javax.swing.GroupLayout;
@@ -28,6 +29,7 @@ import javax.swing.JFrame;
 import javax.swing.JLabel;
 import javax.swing.JPanel;
 import javax.swing.JPasswordField;
+import javax.swing.JRadioButton;
 import javax.swing.JSpinner;
 import javax.swing.JTabbedPane;
 import javax.swing.JTextField;
@@ -36,6 +38,7 @@ import javax.swing.SpinnerNumberModel;
 import javax.swing.WindowConstants;
 import org.apache.commons.configuration.ConfigurationException;
 import yukihane.inqubus.config.Config;
+import yukihane.inqubus.config.Config.CookieBrowser;
 
 /**
  *
@@ -57,10 +60,8 @@ public class ConfigDialog extends JDialog {
         final JTabbedPane tabbedPane = new JTabbedPane();
         final JPanel pnlNetwork = new JPanel();
         final JPanel pnlAccount = new JPanel();
-        final JLabel lblMail = new JLabel();
         fldMail = new JTextField();
         fldPassword.setEchoChar('*');
-        final JLabel lblPassword = new JLabel();
         final JPanel pnlProxy = new JPanel();
         cbProxyUse = new JCheckBox();
         final JLabel lblProxyHost = new JLabel();
@@ -104,29 +105,34 @@ public class ConfigDialog extends JDialog {
 
         pnlAccount.setBorder(BorderFactory.createTitledBorder("アカウント"));
 
-        lblMail.setText("ID(メールアドレス)");
-
-        lblPassword.setText("パスワード");
+        final JLabel lblMail = new JLabel("ID(メールアドレス)");
+        final JLabel lblPassword = new JLabel("パスワード");
 
         GroupLayout gl_pnlAccount = new GroupLayout(pnlAccount);
         pnlAccount.setLayout(gl_pnlAccount);
-        gl_pnlAccount.setHorizontalGroup(
-            gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.LEADING)
+        gl_pnlAccount.setHorizontalGroup(gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.LEADING)
+            .addComponent(btnAccount)
             .addGroup(gl_pnlAccount.createSequentialGroup()
                 .addContainerGap()
+                .addGap(10)
                 .addGroup(gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.LEADING)
                     .addComponent(lblMail)
-                    .addComponent(lblPassword))
+                    .addComponent(lblPassword)
+                )
                 .addPreferredGap(ComponentPlacement.RELATED)
                 .addGroup(gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.LEADING)
                     .addComponent(fldPassword, GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE)
-                    .addComponent(fldMail, GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE))
-                .addContainerGap())
+                    .addComponent(fldMail, GroupLayout.DEFAULT_SIZE, 306, Short.MAX_VALUE)
+                )
+                .addContainerGap()
+            )
         );
         gl_pnlAccount.setVerticalGroup(
             gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.LEADING)
             .addGroup(gl_pnlAccount.createSequentialGroup()
                 .addContainerGap()
+                .addComponent(btnAccount)
+                .addPreferredGap(ComponentPlacement.RELATED)
                 .addGroup(gl_pnlAccount.createParallelGroup(GroupLayout.Alignment.BASELINE)
                     .addComponent(lblMail)
                     .addComponent(fldMail, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
@@ -137,6 +143,63 @@ public class ConfigDialog extends JDialog {
                 .addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
         );
 
+
+        final JButton btnCookie = new JButton("...");
+        btnCookie.addActionListener(new FileChooseActionListener(this, JFileChooser.DIRECTORIES_ONLY, fldCookie));
+
+        final ButtonGroup grpLoginType = new ButtonGroup();
+        grpLoginType.add(btnAccount);
+        grpLoginType.add(btnLoginCookie);
+
+        final ButtonGroup grpCookie = new ButtonGroup();
+        grpCookie.add(btnCookieIe);
+        grpCookie.add(btnCookieFirefox);
+        grpCookie.add(btnCookieChrome);
+        grpCookie.add(btnCookieChromium);
+        grpCookie.add(btnCookieOpera);
+        grpCookie.add(btnCookieOther);
+
+        final JPanel pnlCookie = new JPanel();
+        pnlCookie.setBorder(BorderFactory.createTitledBorder("cookie"));
+        final GroupLayout glCookie = new GroupLayout(pnlCookie);
+        pnlCookie.setLayout(glCookie);
+        glCookie.setAutoCreateContainerGaps(true);
+        glCookie.setAutoCreateGaps(true);
+
+        glCookie.setHorizontalGroup(glCookie.createParallelGroup()
+            .addComponent(btnLoginCookie)
+            .addGroup(glCookie.createSequentialGroup()
+                .addGap(10)
+                .addGroup(glCookie.createParallelGroup()
+                    .addComponent(btnCookieIe)
+                    .addComponent(btnCookieFirefox)
+                    .addComponent(btnCookieChrome)
+                    .addComponent(btnCookieChromium)
+                    .addComponent(btnCookieOpera)
+                    .addComponent(btnCookieOther)
+                    .addGroup(glCookie.createSequentialGroup()
+                        .addComponent(fldCookie)
+                        .addComponent(btnCookie)
+                    )
+                )
+            )
+        );
+
+        glCookie.setVerticalGroup(glCookie.createSequentialGroup()
+            .addComponent(btnLoginCookie)
+            .addComponent(btnCookieIe)
+            .addComponent(btnCookieFirefox)
+            .addComponent(btnCookieChrome)
+            .addComponent(btnCookieChromium)
+            .addComponent(btnCookieOpera)
+            .addComponent(btnCookieOther)
+            .addGroup(glCookie.createParallelGroup(Alignment.BASELINE)
+                .addComponent(fldCookie)
+                .addComponent(btnCookie)
+            )
+        );
+
+
         pnlProxy.setBorder(BorderFactory.createTitledBorder("プロキシ"));
 
         cbProxyUse.setText("プロキシを使用する");
@@ -176,9 +239,10 @@ public class ConfigDialog extends JDialog {
                 .addGroup(gl_pnlProxy.createParallelGroup(GroupLayout.Alignment.BASELINE)
                     .addComponent(lblProxyPort)
                     .addComponent(fldProxyPort, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE))
-                .addContainerGap(39, Short.MAX_VALUE))
+                .addContainerGap())
         );
 
+
         GroupLayout gl_pnlNetwork = new GroupLayout(pnlNetwork);
         pnlNetwork.setLayout(gl_pnlNetwork);
         gl_pnlNetwork.setHorizontalGroup(
@@ -186,8 +250,10 @@ public class ConfigDialog extends JDialog {
             .addGroup(GroupLayout.Alignment.TRAILING, gl_pnlNetwork.createSequentialGroup()
                 .addContainerGap()
                 .addGroup(gl_pnlNetwork.createParallelGroup(GroupLayout.Alignment.TRAILING)
+                    .addComponent(pnlAccount, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+                    .addComponent(pnlCookie, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                     .addComponent(pnlProxy, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
-                    .addComponent(pnlAccount, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+                )
                 .addContainerGap())
         );
         gl_pnlNetwork.setVerticalGroup(
@@ -196,8 +262,11 @@ public class ConfigDialog extends JDialog {
                 .addContainerGap()
                 .addComponent(pnlAccount, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
                 .addPreferredGap(ComponentPlacement.RELATED)
+                .addComponent(pnlCookie, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
+                .addPreferredGap(ComponentPlacement.RELATED)
                 .addComponent(pnlProxy, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE)
-                .addContainerGap(178, Short.MAX_VALUE))
+                .addContainerGap()
+            )
         );
 
         tabbedPane.addTab("ネットワーク", pnlNetwork);
@@ -758,8 +827,18 @@ public class ConfigDialog extends JDialog {
 
     // ネットワーク
     // ネットワーク - アカウント
+    final JRadioButton btnAccount = new JRadioButton("次の情報を使用してログインする");
     private final JTextField fldMail;
     private final JPasswordField fldPassword = new JPasswordField();
+    // ネットワーク - cookie
+    final JRadioButton btnLoginCookie = new JRadioButton("ブラウザのログイン情報を使用してアクセスする");
+    final JRadioButton btnCookieIe = new JRadioButton("IE(7以降) (Windows)");
+    final JRadioButton btnCookieFirefox = new JRadioButton("Firefox(4以降) (Windows)");
+    final JRadioButton btnCookieChrome = new JRadioButton("Google Chrome (Windows)");
+    final JRadioButton btnCookieChromium = new JRadioButton("Chrome派生ブラウザ (Windows)");
+    final JRadioButton btnCookieOpera = new JRadioButton("Opera (Windows)");
+    final JRadioButton btnCookieOther = new JRadioButton("上記以外 - cookie保存ディレクトリを次に入力");
+    final JTextField fldCookie = new JTextField();
     // ネットワーク - プロキシ
     private final JCheckBox cbProxyUse;
     private final JTextField fldProxyHost = new JTextField();
@@ -829,10 +908,42 @@ public class ConfigDialog extends JDialog {
         /*
          * ネットワーク - アカウント
          */
+        btnAccount.setSelected(p.getNeedsLogin());
         fldMail.setText(p.getId());
         fldPassword.setText(p.getPassword());
 
         /*
+         * ネットワーク - cookie
+         */
+        btnLoginCookie.setSelected(!p.getNeedsLogin());
+        final CookieBrowser cookieBrowser = p.getCookieBrowser();
+        final JRadioButton enabledBrowser;
+        switch(cookieBrowser){
+            case MSIE:
+                enabledBrowser = btnCookieIe;
+                break;
+            case FIREFOX:
+                enabledBrowser = btnCookieFirefox;
+                break;
+            case CHROME:
+                enabledBrowser = btnCookieChrome;
+                break;
+            case CHROMIUM:
+                enabledBrowser = btnCookieChromium;
+                break;
+            case OPERA:
+                enabledBrowser = btnCookieOpera;
+                break;
+            case OTHER:
+                enabledBrowser = btnCookieOther;
+                break;
+            default:
+                throw new UnsupportedOperationException();
+        }
+        enabledBrowser.setSelected(true);
+        fldCookie.setText(p.getCookieDir());
+
+        /*
          * ネットワーク - プロキシ
          */
         cbProxyUse.setSelected(p.getProxyUse());
@@ -935,11 +1046,33 @@ public class ConfigDialog extends JDialog {
         /*
          * ネットワーク - アカウント
          */
-
+        p.setNeedsLogin(btnAccount.isSelected());
         p.setId(fldMail.getText());
         p.setPassword(String.valueOf(fldPassword.getPassword()));
 
         /*
+         * ネットワーク - cookie
+         */
+        final CookieBrowser cookieBrowser;
+        if(btnCookieIe.isSelected()) {
+            cookieBrowser = CookieBrowser.MSIE;
+        } else if(btnCookieFirefox.isSelected()) {
+            cookieBrowser = CookieBrowser.FIREFOX;
+        } else if (btnCookieChrome.isSelected()) {
+            cookieBrowser = CookieBrowser.CHROME;
+        } else if (btnCookieChromium.isSelected()) {
+            cookieBrowser = CookieBrowser.CHROMIUM;
+        } else if(btnCookieOpera.isSelected()) {
+            cookieBrowser = CookieBrowser.OPERA;
+        } else if(btnCookieOther.isSelected()) {
+            cookieBrowser = CookieBrowser.OTHER;
+        } else {
+            throw new UnsupportedOperationException();
+        }
+        p.setCookieBrowser(cookieBrowser);
+        p.setCookieDir(fldCookie.getText());
+
+        /*
          * ネットワーク - プロキシ
          */
         p.setProxyUse(cbProxyUse.isSelected());
index 85bd525..4e32de2 100644 (file)
@@ -4,6 +4,7 @@ import saccubus.worker.profile.CommentProfile;
 import saccubus.worker.profile.LoginProfile;
 import yukihane.inqubus.config.ConfigCommentProfile;
 import yukihane.inqubus.config.ConfigDownloadProfile;
+import yukihane.inqubus.config.ConfigLoginProfile;
 
 /**
  * さきゅばすのコマンドプロンプト仕様にあわせるためのDownloadProfile実装
@@ -15,7 +16,7 @@ class DownloadProfileImpl extends ConfigDownloadProfile {
     private final CommentProfile commentProfile;
 
     DownloadProfileImpl(final String mail, final String pass, final long time) {
-        this.loginProfile = new LoginProfile() {
+        this.loginProfile = new ConfigLoginProfile() {
 
             @Override
             public String getMail() {