Partially fix YiffStar support
authorNiki Roo <niki@nikiroo.be>
Mon, 27 Feb 2017 04:28:22 +0000 (05:28 +0100)
committerNiki Roo <niki@nikiroo.be>
Mon, 27 Feb 2017 04:28:22 +0000 (05:28 +0100)
- works more or less correctly except login mode
- should not use login mode in final form (yet it should be fixed)

src/be/nikiroo/fanfix/Cache.java
src/be/nikiroo/fanfix/bundles/Config.java
src/be/nikiroo/fanfix/bundles/config.properties
src/be/nikiroo/fanfix/supported/BasicSupport.java
src/be/nikiroo/fanfix/supported/YiffStar.java

index b290756d1bdcb632d22cc66caa7e812cfa26bd9e..8e8392aa12d61795b53ce03d320e591f11b20712 100644 (file)
@@ -6,6 +6,7 @@ import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStreamWriter;
 import java.net.CookieHandler;
 import java.net.CookieManager;
 import java.net.CookiePolicy;
@@ -15,6 +16,7 @@ import java.net.HttpURLConnection;
 import java.net.URISyntaxException;
 import java.net.URL;
 import java.net.URLConnection;
+import java.net.URLEncoder;
 import java.util.Date;
 import java.util.Map;
 import java.util.zip.GZIPInputStream;
@@ -84,6 +86,13 @@ public class Cache {
                CookieHandler.setDefault(cookies);
        }
 
+       /**
+        * Clear all the cookies currently in the jar.
+        */
+       public void clearCookies() {
+               cookies.getCookieStore().removeAll();
+       }
+
        /**
         * Open a resource (will load it from the cache if possible, or save it into
         * the cache after downloading if not).
@@ -150,6 +159,108 @@ public class Cache {
                }
        }
 
+       /**
+        * Open the given {@link URL} without using the cache, but still using and
+        * updating the cookies.
+        * 
+        * @param url
+        *            the {@link URL} to open
+        * @param support
+        *            the {@link BasicSupport} used for the cookies
+        * 
+        * @return the {@link InputStream} of the opened page
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public InputStream openNoCache(URL url, BasicSupport support)
+                       throws IOException {
+               return openNoCache(url, support, url, null);
+       }
+
+       /**
+        * Open the given {@link URL} without using the cache, but still using and
+        * updating the cookies.
+        * 
+        * @param url
+        *            the {@link URL} to open
+        * @param support
+        *            the {@link BasicSupport} used for the cookies
+        * @param postParams
+        *            the POST parameters
+        * 
+        * @return the {@link InputStream} of the opened page
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public InputStream openNoCache(URL url, BasicSupport support,
+                       Map<String, String> postParams) throws IOException {
+               return openNoCache(url, support, url, postParams);
+       }
+
+       /**
+        * Open the given {@link URL} without using the cache, but still using and
+        * updating the cookies.
+        * 
+        * @param url
+        *            the {@link URL} to open
+        * @param support
+        *            the {@link BasicSupport} used for the cookies
+        * @param originalUrl
+        *            the original {@link URL} before any redirection occurs
+        * @param postParams
+        *            the POST parameters
+        * 
+        * @return the {@link InputStream} of the opened page
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       private InputStream openNoCache(URL url, BasicSupport support,
+                       final URL originalUrl, Map<String, String> postParams)
+                       throws IOException {
+
+               URLConnection conn = openConnectionWithCookies(url, support);
+               if (postParams != null) {
+                       StringBuilder postData = new StringBuilder();
+                       for (Map.Entry<String, String> param : postParams.entrySet()) {
+                               if (postData.length() != 0)
+                                       postData.append('&');
+                               postData.append(URLEncoder.encode(param.getKey(), "UTF-8"));
+                               postData.append('=');
+                               postData.append(URLEncoder.encode(
+                                               String.valueOf(param.getValue()), "UTF-8"));
+                       }
+
+                       conn.setDoOutput(true);
+
+                       OutputStreamWriter writer = new OutputStreamWriter(
+                                       conn.getOutputStream());
+
+                       writer.write(postData.toString());
+                       writer.flush();
+                       writer.close();
+               }
+
+               conn.connect();
+
+               // Check if redirect
+               if (conn instanceof HttpURLConnection
+                               && ((HttpURLConnection) conn).getResponseCode() / 100 == 3) {
+                       String newUrl = conn.getHeaderField("Location");
+                       return openNoCache(new URL(newUrl), support, originalUrl,
+                                       postParams);
+               }
+
+               InputStream in = conn.getInputStream();
+               if ("gzip".equals(conn.getContentEncoding())) {
+                       in = new GZIPInputStream(in);
+               }
+
+               return in;
+       }
+
        /**
         * Refresh the resource into cache if needed.
         * 
@@ -295,33 +406,7 @@ public class Cache {
         */
        private void save(URL url, BasicSupport support, URL originalUrl)
                        throws IOException {
-               URLConnection conn = url.openConnection();
-
-               conn.setRequestProperty("User-Agent", UA);
-               conn.setRequestProperty("Cookie", generateCookies(support));
-               conn.setRequestProperty("Accept-Encoding", "gzip");
-               if (support != null && support.getCurrentReferer() != null) {
-                       conn.setRequestProperty("Referer", support.getCurrentReferer()
-                                       .toString());
-                       conn.setRequestProperty("Host", support.getCurrentReferer()
-                                       .getHost());
-               }
-
-               conn.connect();
-
-               // Check if redirect
-               if (conn instanceof HttpURLConnection
-                               && ((HttpURLConnection) conn).getResponseCode() / 100 == 3) {
-                       String newUrl = conn.getHeaderField("Location");
-                       save(new URL(newUrl), support, originalUrl);
-                       return;
-               }
-
-               InputStream in = conn.getInputStream();
-               if ("gzip".equals(conn.getContentEncoding())) {
-                       in = new GZIPInputStream(in);
-               }
-
+               InputStream in = openNoCache(url, support, originalUrl, null);
                try {
                        File cached = getCached(originalUrl);
                        BufferedOutputStream out = new BufferedOutputStream(
@@ -340,6 +425,37 @@ public class Cache {
                }
        }
 
+       /**
+        * Open a connection on the given {@link URL}, and manage the cookies that
+        * come with it.
+        * 
+        * @param url
+        *            the {@link URL} to open
+        * @param support
+        *            the {@link BasicSupport} to use for cookie generation
+        * 
+        * @return the connection
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       private URLConnection openConnectionWithCookies(URL url,
+                       BasicSupport support) throws IOException {
+               URLConnection conn = url.openConnection();
+
+               conn.setRequestProperty("User-Agent", UA);
+               conn.setRequestProperty("Cookie", generateCookies(support));
+               conn.setRequestProperty("Accept-Encoding", "gzip");
+               if (support != null && support.getCurrentReferer() != null) {
+                       conn.setRequestProperty("Referer", support.getCurrentReferer()
+                                       .toString());
+                       conn.setRequestProperty("Host", support.getCurrentReferer()
+                                       .getHost());
+               }
+
+               return conn;
+       }
+
        /**
         * Check if the {@link File} is too old according to
         * {@link Cache#tooOldChanging}.
@@ -409,14 +525,18 @@ public class Cache {
                }
 
                if (support != null) {
-                       for (Map.Entry<String, String> set : support.getCookies()
-                                       .entrySet()) {
-                               if (builder.length() > 0) {
-                                       builder.append(';');
+                       try {
+                               for (Map.Entry<String, String> set : support.getCookies()
+                                               .entrySet()) {
+                                       if (builder.length() > 0) {
+                                               builder.append(';');
+                                       }
+                                       builder.append(set.getKey());
+                                       builder.append('=');
+                                       builder.append(set.getValue());
                                }
-                               builder.append(set.getKey());
-                               builder.append('=');
-                               builder.append(set.getValue());
+                       } catch (IOException e) {
+                               Instance.syserr(e);
                        }
                }
 
index ca35733ba49fe46ccf421843c5214d0a44be9d74..7cc7bee42134c1054e2938104a6cfd95e4905a6a 100644 (file)
@@ -44,4 +44,8 @@ public enum Config {
        CHAPTER_EN, //
        @Meta(what = "Chapter identification string", where = "", format = "", info = "used to identify a starting chapter in text mode")
        CHAPTER_FR, //
+       @Meta(what = "Login information", where = "", format = "", info = "used to login on YiffStar to have access to all the stories")
+       LOGIN_YIFFSTAR_USER, //
+       @Meta(what = "Login information", where = "", format = "", info = "used to login on YiffStar to have access to all the stories")
+       LOGIN_YIFFSTAR_PASS, //
 }
index 0b1d0ac62b42b1e9a786dc4ff0d3de11e11cc1eb..4148f66e1400d5ed34ff9da6868db9e5ce77782b 100644 (file)
@@ -56,3 +56,9 @@ CHAPTER_EN = Chapter
 # (WHAT: Chapter identification string)
 # used to identify a starting chapter in text mode
 CHAPTER_FR = Chapitre
+# (WHAT: Login information)
+# used to login on YiffStar to have access to all the stories
+LOGIN_YIFFSTAR_USER = 
+# (WHAT: Login information)
+# used to login on YiffStar to have access to all the stories
+LOGIN_YIFFSTAR_PASS = 
index 129182208f29f0ce70d46ffb70053231d0792a30..b528cac819acea887acfc28f861b9c32221d1971 100644 (file)
@@ -243,6 +243,16 @@ public abstract class BasicSupport {
        protected abstract String getChapterContent(URL source, InputStream in,
                        int number) throws IOException;
 
+       /**
+        * Log into the support (can be a no-op depending upon the support).
+        * 
+        * @throws IOException
+        *             in case of I/O error
+        */
+       public void login() throws IOException {
+
+       }
+
        /**
         * Return the list of cookies (values included) that must be used to
         * correctly fetch the resources.
@@ -251,8 +261,11 @@ public abstract class BasicSupport {
         * it.
         * 
         * @return the cookies
+        * 
+        * @throws IOException
+        *             in case of I/O error
         */
-       public Map<String, String> getCookies() {
+       public Map<String, String> getCookies() throws IOException {
                return new HashMap<String, String>();
        }
 
@@ -304,6 +317,8 @@ public abstract class BasicSupport {
         */
        protected Story processMeta(URL url, boolean close, boolean getDesc)
                        throws IOException {
+               login();
+
                url = getCanonicalUrl(url);
 
                setCurrentReferer(url);
index e9c10c9f06eb4d2d333976e039d09e8adfb37305..4f4e8d693271814bb645eb9c9a6ae3b81b1b5f7e 100644 (file)
@@ -5,12 +5,14 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.net.URL;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
 import java.util.Scanner;
 
 import be.nikiroo.fanfix.Instance;
+import be.nikiroo.fanfix.bundles.Config;
 import be.nikiroo.fanfix.data.MetaData;
 import be.nikiroo.utils.StringUtils;
 
@@ -65,12 +67,21 @@ class YiffStar extends BasicSupport {
        }
 
        @Override
-       public Map<String, String> getCookies() {
-               // TODO
-               // Cookies will actually be retained by the cache manager once logged in
-               // But we need to connect here and notify the cache manager
+       public void login() throws IOException {
+               Map<String, String> post = new HashMap<String, String>();
+               post.put("LoginForm[sfLoginUsername]",
+                               Instance.getConfig().getString(Config.LOGIN_YIFFSTAR_USER));
+               post.put("LoginForm[sfLoginPassword]",
+                               Instance.getConfig().getString(Config.LOGIN_YIFFSTAR_PASS));
+               post.put("YII_CSRF_TOKEN", "");
 
-               return super.getCookies();
+               // Cookies will actually be retained by the cache manager once logged in
+               // TODO: not working yet, once fixed can be removed (adding "/guest" to
+               // URLs fix the access problem!):
+               /*
+                * Instance.getCache() .openNoCache(new
+                * URL("https://www.sofurry.com/user/login"), this, post).close();
+                */
        }
 
        @Override
@@ -78,11 +89,13 @@ class YiffStar extends BasicSupport {
                if (source.getPath().startsWith("/view")) {
                        InputStream in = Instance.getCache().open(source, this, false);
                        String line = getLine(in, "/browse/folder/", 0);
-                       String[] tab = line.split("\"");
-                       if (tab.length > 1) {
-                               String groupUrl = source.getProtocol() + "://"
-                                               + source.getHost() + tab[1];
-                               return new URL(groupUrl);
+                       if (line != null) {
+                               String[] tab = line.split("\"");
+                               if (tab.length > 1) {
+                                       String groupUrl = source.getProtocol() + "://"
+                                                       + source.getHost() + tab[1];
+                                       return new URL(groupUrl);
+                               }
                        }
                }