diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java index d10fe5edf..294f92ebc 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhEngine.java @@ -38,6 +38,7 @@ import com.hippo.ehviewer.client.parser.ForumsParser; import com.hippo.ehviewer.client.parser.GalleryApiParser; import com.hippo.ehviewer.client.parser.GalleryDetailParser; import com.hippo.ehviewer.client.parser.GalleryListParser; +import com.hippo.ehviewer.client.parser.GalleryPageApiParser; import com.hippo.ehviewer.client.parser.GalleryPageParser; import com.hippo.ehviewer.client.parser.GalleryTokenApiParser; import com.hippo.ehviewer.client.parser.ProfileParser; @@ -988,4 +989,41 @@ public class EhEngine { throw e; } } + + public static GalleryPageApiParser.Result getGalleryPageApi(@Nullable EhClient.Task task, + OkHttpClient okHttpClient, long gid, int index, String pToken, String showKey) throws Throwable { + final JSONObject json = new JSONObject(); + json.put("method", "showpage"); + json.put("gid", gid); + json.put("page", index + 1); + json.put("imgkey", pToken); + json.put("showkey", showKey); + final RequestBody requestBody = RequestBody.create(MEDIA_TYPE_JSON, json.toString()); + String url = EhUrl.getApiUrl(); + Log.d(TAG, url); + Request request = new EhRequestBuilder(url, null != task ? task.getEhConfig() : Settings.getEhConfig()) + .post(requestBody) + .build(); + Call call = okHttpClient.newCall(request); + + // Put call + if (null != task) { + task.setCall(call); + } + + String body = null; + Headers headers = null; + int code = -1; + try { + Response response = call.execute(); + code = response.code(); + headers = response.headers(); + body = response.body().string(); + return GalleryPageApiParser.parse(body); + } catch (Throwable e) { + ExceptionUtils.throwIfFatal(e); + throwException(call, code, headers, body, e); + throw e; + } + } } diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java index 7a72ed4c3..5e492a28c 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java @@ -42,6 +42,7 @@ import com.hippo.ehviewer.client.data.PreviewSet; import com.hippo.ehviewer.client.exception.Image509Exception; import com.hippo.ehviewer.client.exception.ParseException; import com.hippo.ehviewer.client.parser.GalleryDetailParser; +import com.hippo.ehviewer.client.parser.GalleryPageApiParser; import com.hippo.ehviewer.client.parser.GalleryPageParser; import com.hippo.ehviewer.client.parser.GalleryPageUrlParser; import com.hippo.ehviewer.gallery.GalleryProvider2; @@ -162,6 +163,9 @@ public final class SpiderQueen implements Runnable { private final AtomicInteger mDownloadedPages = new AtomicInteger(0); private final AtomicInteger mFinishedPages = new AtomicInteger(0); + private AtomicReference showKey = new AtomicReference<>(); + private final Object showKeyLock = new Object(); + // Store page error private final ConcurrentHashMap mPageErrorMap = new ConcurrentHashMap<>(); // Store page download percent @@ -1035,7 +1039,7 @@ public final class SpiderQueen implements Runnable { return pageUrl; } - private GalleryPageParser.Result getImageUrl(int index, String pageUrl) throws Throwable { + private GalleryPageParser.Result fetchPageResultFromHtml(int index, String pageUrl) throws Throwable { GalleryPageParser.Result result = EhEngine.getGalleryPage(null, mHttpClient, pageUrl); if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) { // Get 509 @@ -1047,71 +1051,127 @@ public final class SpiderQueen implements Runnable { return result; } + private GalleryPageApiParser.Result fetchPageResultFromApi(long gid, int index, String pToken, String showKey) throws Throwable { + GalleryPageApiParser.Result result = EhEngine.getGalleryPageApi(null, mHttpClient, gid, index, pToken, showKey); + if (StringUtils.endsWith(result.imageUrl, URL_509_SUFFIX_ARRAY)) { + // Get 509 + // Notify listeners + notifyGet509(index); + throw new Image509Exception(); + } + + return result; + } + // false for stop private boolean downloadImage(long gid, int index, String pToken, boolean force) { - List skipHathKeys = new ArrayList<>(5); String skipHathKey = null; - String imageUrl; - String error = null; + List skipHathKeys = new ArrayList<>(5); + String originImageUrl = null; String pageUrl = null; + String error = null; + boolean forceHtml = false; boolean interrupt = false; boolean leakSkipHathKey = false; - Log.d("TAG", "index = " + index); - - // Try twice for (int i = 0; i < 5; i++) { - if (leakSkipHathKey) { - break; - } + String imageUrl = null; + String localShowKey; - pageUrl = getPageUrl(gid, index, pToken, pageUrl, skipHathKey); + // Check show key + synchronized (showKeyLock) { + localShowKey = showKey.get(); + if (localShowKey == null || forceHtml) { + if (leakSkipHathKey) { + error = "No more new SkipHathKey"; + break; + } - GalleryPageParser.Result result = null; - try { - result = getImageUrl(index, pageUrl); - } catch (Image509Exception e) { - error = GetText.getString(R.string.error_509); - } catch (Throwable e) { - ExceptionUtils.throwIfFatal(e); - error = ExceptionUtils.getReadableString(e); - } - if (result == null) { - // Get image url failed - break; - } - // Check interrupted - if (Thread.currentThread().isInterrupted()) { - error = "Interrupted"; - interrupt = true; - break; - } + // Try to get show key + pageUrl = getPageUrl(gid, index, pToken, pageUrl, skipHathKey); + try { + GalleryPageParser.Result result = fetchPageResultFromHtml(index, pageUrl); + imageUrl = result.imageUrl; + skipHathKey = result.skipHathKey; + originImageUrl = result.originImageUrl; + localShowKey = result.showKey; - if (Settings.getDownloadOriginImage() && !TextUtils.isEmpty(result.originImageUrl)) { - imageUrl = result.originImageUrl; - } else { - imageUrl = result.imageUrl; - } - skipHathKey = result.skipHathKey; - if (!TextUtils.isEmpty(skipHathKey)) { - if (skipHathKeys.contains(skipHathKey)) { - // Duplicate skip hath key, don't run next turn - leakSkipHathKey = true; - } else { - skipHathKeys.add(skipHathKey); + if (!TextUtils.isEmpty(skipHathKey)) { + if (skipHathKeys.contains(skipHathKey)) { + // Duplicate skip hath key + leakSkipHathKey = true; + } else { + skipHathKeys.add(skipHathKey); + } + } else { + leakSkipHathKey = true; + } + + showKey.lazySet(result.showKey); + } catch (Image509Exception e) { + error = GetText.getString(R.string.error_509); + break; + } catch (Throwable e) { + ExceptionUtils.throwIfFatal(e); + error = ExceptionUtils.getReadableString(e); + break; + } + + // Check interrupted + if (Thread.currentThread().isInterrupted()) { + error = "Interrupted"; + interrupt = true; + break; + } } - } else { - // No skip hath key, don't run next turn - leakSkipHathKey = true; } - // If it is force request, skip first image - //if (force && i == 0) { - // continue; - //} + if (imageUrl == null) { + if (localShowKey == null) { + error = "ShowKey error"; + break; + } + try { + GalleryPageApiParser.Result result = fetchPageResultFromApi(gid, index, pToken, localShowKey); + imageUrl = result.imageUrl; + skipHathKey = result.skipHathKey; + originImageUrl = result.originImageUrl; + } catch (Image509Exception e) { + error = GetText.getString(R.string.error_509); + break; + } catch (Throwable e) { + if (e instanceof ParseException && "Key mismatch".equals(e.getMessage())) { + // Show key is wrong, enter a new loop to get the new show key + showKey.compareAndSet(localShowKey, null); + continue; + } else { + ExceptionUtils.throwIfFatal(e); + error = ExceptionUtils.getReadableString(e); + break; + } + } + + // Check interrupted + if (Thread.currentThread().isInterrupted()) { + error = "Interrupted"; + interrupt = true; + break; + } + } + + String targetImageUrl; + if (Settings.getDownloadOriginImage() && !TextUtils.isEmpty(originImageUrl)) { + targetImageUrl = originImageUrl; + } else { + targetImageUrl = imageUrl; + } + if (targetImageUrl == null) { + error = "TargetImageUrl error"; + break; + } if (DEBUG_LOG) { - Log.d(TAG, imageUrl); + Log.d(TAG, targetImageUrl); } // Download image @@ -1122,7 +1182,7 @@ public final class SpiderQueen implements Runnable { Log.d(TAG, "Start download image " + index); } - Call call = mHttpClient.newCall(new EhRequestBuilder(imageUrl).build()); + Call call = mHttpClient.newCall(new EhRequestBuilder(targetImageUrl).build()); Response response = call.execute(); ResponseBody responseBody = response.body(); @@ -1130,11 +1190,13 @@ public final class SpiderQueen implements Runnable { // Maybe 404 response.close(); error = "Bad code: " + response.code(); + forceHtml = true; continue; } if (responseBody == null) { error = "Empty response body"; + forceHtml = true; continue; } @@ -1188,6 +1250,7 @@ public final class SpiderQueen implements Runnable { if (receivedSize < contentLength) { Log.e(TAG, "Can't download all of image data"); error = "Incomplete"; + forceHtml = true; continue; } else if (receivedSize > contentLength) { Log.w(TAG, "Received data is more than contentLength"); @@ -1211,6 +1274,7 @@ public final class SpiderQueen implements Runnable { } catch (IOException e) { e.printStackTrace(); error = GetText.getString(R.string.error_socket); + forceHtml = true; } finally { IOUtils.closeQuietly(is); if (null != pipe) {