From 1fe7500251ee9ce7d49eed25f7aeeb9743de93c7 Mon Sep 17 00:00:00 2001 From: seven332 Date: Mon, 21 Mar 2016 20:37:57 +0800 Subject: [PATCH] Add hath proxy --- .../java/com/hippo/ehviewer/Settings.java | 66 ++++++ .../com/hippo/ehviewer/client/EhConfig.java | 8 +- .../preference/HatHProxyPreference.java | 197 ++++++++++++++++++ .../java/com/hippo/network/InetValidator.java | 66 ++++++ .../layout/preference_dialog_hath_proxy.xml | 74 +++++++ app/src/main/res/values-zh-rCN/strings.xml | 12 ++ app/src/main/res/values-zh-rHK/strings.xml | 12 ++ app/src/main/res/values-zh-rTW/strings.xml | 12 ++ app/src/main/res/values/strings.xml | 12 ++ app/src/main/res/xml/eh_settings.xml | 4 + 10 files changed, 460 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java create mode 100644 app/src/main/java/com/hippo/network/InetValidator.java create mode 100644 app/src/main/res/layout/preference_dialog_hath_proxy.xml diff --git a/app/src/main/java/com/hippo/ehviewer/Settings.java b/app/src/main/java/com/hippo/ehviewer/Settings.java index 785a3eedc..e16c93ada 100644 --- a/app/src/main/java/com/hippo/ehviewer/Settings.java +++ b/app/src/main/java/com/hippo/ehviewer/Settings.java @@ -298,6 +298,72 @@ public class Settings { putString(KEY_EXCLUDED_LANGUAGES, value); } + private static final String KEY_HATH_PROXY = "hath_proxy"; + private static final boolean DEFAULT_HATH_PROXY = false; + + public static boolean getHathProxy() { + return getBoolean(KEY_HATH_PROXY, DEFAULT_HATH_PROXY); + } + + public static void putHathProxy(boolean value) { + if (value) { + sEhConfig.hahClientIp = Settings.getHathIp(); + sEhConfig.hahClientPort = Settings.getHathPort(); + sEhConfig.hahClientPasskey = Settings.getHathPasskey(); + } else { + sEhConfig.hahClientIp = DEFAULT_HATH_IP; + sEhConfig.hahClientPort = DEFAULT_HATH_PORT; + sEhConfig.hahClientPasskey = DEFAULT_HATH_PASSKEY; + } + sEhConfig.setDirty(); + putBoolean(KEY_HATH_PROXY, value); + } + + private static final String KEY_HATH_IP = "hath_ip"; + private static final String DEFAULT_HATH_IP = null; + + public static String getHathIp() { + return getString(KEY_HATH_IP, DEFAULT_HATH_IP); + } + + public static void putHathIp(String value) { + if (Settings.getHathProxy()) { + sEhConfig.hahClientIp = value; + sEhConfig.setDirty(); + } + putString(KEY_HATH_IP, value); + } + + private static final String KEY_HATH_PORT = "hath_port"; + private static final int DEFAULT_HATH_PORT = -1; + + public static int getHathPort() { + return getInt(KEY_HATH_PORT, DEFAULT_HATH_PORT); + } + + public static void putHathPort(int value) { + if (Settings.getHathProxy()) { + sEhConfig.hahClientPort = value; + sEhConfig.setDirty(); + } + putInt(KEY_HATH_PORT, value); + } + + private static final String KEY_HATH_PASSKEY = "hath_passkey"; + private static final String DEFAULT_HATH_PASSKEY = null; + + public static String getHathPasskey() { + return getString(KEY_HATH_PASSKEY, DEFAULT_HATH_PASSKEY); + } + + public static void putHathPasskey(String value) { + if (Settings.getHathProxy()) { + sEhConfig.hahClientPasskey = value; + sEhConfig.setDirty(); + } + putString(KEY_HATH_PASSKEY, value); + } + /******************** ****** Read ********************/ diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhConfig.java b/app/src/main/java/com/hippo/ehviewer/client/EhConfig.java index dd4e0c651..792913306 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhConfig.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhConfig.java @@ -16,7 +16,7 @@ package com.hippo.ehviewer.client; -import android.text.TextUtils; +import com.hippo.network.InetValidator; /** * Some configurable stuff about EH. It ends up cookie. @@ -623,8 +623,10 @@ public class EhConfig implements Cloneable { } private void updateUconfig() { - String hahClientIpPort = (TextUtils.isEmpty(hahClientIp) || hahClientPort == -1) ? - "" : hahClientIp + "%3A" + hahClientPort; + String hahClientIpPort = (InetValidator.isValidInet4Address(hahClientIp) && + InetValidator.isValidInetPort(hahClientPort)) ? + hahClientIp + "%3A" + hahClientPort : ""; + String hahClientPasskey = null == this.hahClientPasskey ? "" : this.hahClientPasskey; mUconfig = KEY_LOAD_FROM_HAH + "_" + loadFromHAH + "-" + KEY_SCALE_WIDTH + "_" + scaleWidth + "-" + KEY_SCALE_HEIGHT + "_" + scaleHeight + "-" + diff --git a/app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java b/app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java new file mode 100644 index 000000000..8f745ef2d --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/preference/HatHProxyPreference.java @@ -0,0 +1,197 @@ +/* + * Copyright 2016 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.ehviewer.preference; + +import android.annotation.SuppressLint; +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.support.annotation.Nullable; +import android.support.design.widget.TextInputLayout; +import android.support.v7.app.AlertDialog; +import android.support.v7.widget.SwitchCompat; +import android.util.AttributeSet; +import android.view.View; +import android.widget.EditText; + +import com.hippo.ehviewer.R; +import com.hippo.ehviewer.Settings; +import com.hippo.network.InetValidator; +import com.hippo.preference.DialogPreference; +import com.hippo.yorozuya.ViewUtils; + +public class HatHProxyPreference extends DialogPreference implements View.OnClickListener { + + @Nullable + private SwitchCompat mEnable; + @Nullable + private TextInputLayout mIpInputLayout; + @Nullable + private EditText mIp; + @Nullable + private TextInputLayout mPortInputLayout; + @Nullable + private EditText mPort; + @Nullable + private TextInputLayout mPasskeyInputLayout; + @Nullable + private EditText mPasskey; + + public HatHProxyPreference(Context context) { + super(context); + init(); + } + + public HatHProxyPreference(Context context, AttributeSet attrs) { + super(context, attrs); + init(); + } + + public HatHProxyPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(); + } + + public HatHProxyPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(); + } + + private void init() { + setDialogLayoutResource(R.layout.preference_dialog_hath_proxy); + updateSummary(Settings.getHathProxy(), Settings.getHathIp(), Settings.getHathPort()); + } + + private void updateSummary(boolean hathProxy, String hathIp, int hathPort) { + if (InetValidator.isValidInet4Address(hathIp) && InetValidator.isValidInetPort(hathPort)) { + Context context = getContext(); + setSummary(context.getString(R.string.settings_eh_hath_proxy_summary_1, + context.getString(hathProxy ? R.string.enabled : R.string.disabled), hathIp, hathPort)); + } else { + setSummary(R.string.settings_eh_hath_proxy_summary_2); + } + } + + @Override + protected void onPrepareDialogBuilder(AlertDialog.Builder builder) { + super.onPrepareDialogBuilder(builder); + builder.setPositiveButton(android.R.string.ok, null); + } + + @Override + @SuppressLint("SetTextI18n") + protected void onDialogCreated(AlertDialog dialog) { + super.onDialogCreated(dialog); + + dialog.getButton(DialogInterface.BUTTON_POSITIVE).setOnClickListener(this); + + mEnable = (SwitchCompat) ViewUtils.$$(dialog, R.id.enable); + mIpInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.ip_input_layout); + mIp = (EditText) ViewUtils.$$(dialog, R.id.ip); + mPortInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.port_input_layout); + mPort = (EditText) ViewUtils.$$(dialog, R.id.port); + mPasskeyInputLayout = (TextInputLayout) ViewUtils.$$(dialog, R.id.passkey_input_layout); + mPasskey = (EditText) ViewUtils.$$(dialog, R.id.passkey); + + mEnable.setChecked(Settings.getHathProxy()); + String ip = Settings.getHathIp(); + if (!InetValidator.isValidInet4Address(ip)) { + ip = null; + } + String portString; + int port = Settings.getHathPort(); + if (!InetValidator.isValidInetPort(port)) { + portString = null; + } else { + portString = Integer.toString(Settings.getHathPort()); + } + mIp.setText(ip); + mPort.setText(portString); + mPasskey.setText(Settings.getHathPasskey()); + } + + @Override + protected void onDialogClosed(boolean positiveResult) { + super.onDialogClosed(positiveResult); + mEnable = null; + mIpInputLayout = null; + mIp = null; + mPortInputLayout = null; + mPort = null; + mPasskeyInputLayout = null; + mPasskey = null; + } + + @Override + public void onClick(View v) { + Dialog dialog = getDialog(); + Context context = getContext(); + if (null == dialog || null == context || null == mEnable || + null == mIpInputLayout || null == mIp || + null == mPortInputLayout || null == mPort || + null == mPasskeyInputLayout || null == mPasskey) { + return; + } + + boolean enable = mEnable.isChecked(); + + String ip = mIp.getText().toString().trim(); + if (ip.isEmpty()) { + if (enable) { + mIpInputLayout.setError(context.getString(R.string.text_is_empty)); + return; + } + } else if (!InetValidator.isValidInet4Address(ip)) { + mIpInputLayout.setError(context.getString(R.string.domain_not_supported)); + return; + } else { + mIpInputLayout.setError(null); + } + + int port; + String portString = mPort.getText().toString().trim(); + if (portString.isEmpty()) { + if (enable) { + mPortInputLayout.setError(context.getString(R.string.text_is_empty)); + return; + } else { + port = -1; + } + } else { + try { + port = Integer.parseInt(portString); + } catch (NumberFormatException e) { + port = -1; + } + if (!InetValidator.isValidInetPort(port)) { + mPortInputLayout.setError(context.getString(R.string.invalid_port)); + return; + } + } + + String passkey = mPasskey.getText().toString(); + + Settings.putHathProxy(enable); + Settings.putHathIp(ip); + Settings.putHathPort(port); + Settings.putHathPasskey(passkey); + + updateSummary(enable, ip, port); + + dialog.dismiss(); + } +} diff --git a/app/src/main/java/com/hippo/network/InetValidator.java b/app/src/main/java/com/hippo/network/InetValidator.java new file mode 100644 index 000000000..540f3a105 --- /dev/null +++ b/app/src/main/java/com/hippo/network/InetValidator.java @@ -0,0 +1,66 @@ +/* + * Copyright 2016 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.network; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public final class InetValidator { + + private static final String IPV4_REGEX = + "^(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})$"; + + private static final Pattern IPV4_PATTERN = Pattern.compile(IPV4_REGEX); + + public static boolean isValidInet4Address(String inet4Address) { + if (null == inet4Address) { + return false; + } + + Matcher matcher = IPV4_PATTERN.matcher(inet4Address); + if (!matcher.find()) { + return false; + } + + // verify that address subgroups are legal + for (int i = 1; i <= 4; i++) { + String ipSegment = matcher.group(i); + if (ipSegment == null || ipSegment.length() == 0) { + return false; + } + int iIpSegment; + try { + iIpSegment = Integer.parseInt(ipSegment); + } catch(NumberFormatException e) { + return false; + } + if (iIpSegment > 255) { + return false; + } + if (ipSegment.length() > 1 && ipSegment.startsWith("0")) { + return false; + } + } + return true; + } + + public static boolean isValidInetPort(int inetPort) { + return inetPort >= 0 && inetPort <= 65535; + } + + private InetValidator() {} +} diff --git a/app/src/main/res/layout/preference_dialog_hath_proxy.xml b/app/src/main/res/layout/preference_dialog_hath_proxy.xml new file mode 100644 index 000000000..7f22fee42 --- /dev/null +++ b/app/src/main/res/layout/preference_dialog_hath_proxy.xml @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 461b08d9c..0d01fbda5 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -332,6 +332,9 @@ 在默认搜索中排除指定标签组 排除语言 在主页与搜索中隐藏指定语言的画廊 + H@H + %1$s %2$s:%3$d + 未设置 显示日文标题 尝试显示日文标题。这会使获取画廊列表花费更多时间 显示默认标题。一般是英文标题 @@ -438,6 +441,15 @@ N/A 其他 + 启用 + 已启用 + 未启用 + IP + 端口 + 密钥 + 不支持域名 + 无效的端口 + 开源许可 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 4fa4ac74a..ae9b2c795 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -332,6 +332,9 @@ 在默認搜索中排除指定標籤組 排除語言 在主頁與搜索中隱藏指定語言的畫廊 + H@H + %1$s %2$s:%3$d + 未設置 顯示日文標題 嘗試顯示日文標題。這會使獲取畫廊列表花費更多時間 顯示默認標題。一般是英文標題 @@ -438,6 +441,15 @@ N/A 其他 + 啟用 + 已啟用 + 未啟用 + IP + 端口 + 密鑰 + 不支持域名 + 無效的端口 + 開源許可 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index f22d57077..92ce36173 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -332,6 +332,9 @@ 在預設搜尋中排除指定標籤組 排除語言 在主頁與搜尋中隱藏指定語言的畫廊 + H@H + %1$s %2$s:%3$d + 未設定 顯示日文標題 嘗試顯示日文標題。這會使獲取畫廊列表花費更多時間 顯示預設標題。一般是英文標題 @@ -438,6 +441,15 @@ N/A 其他 + 啟用 + 已啟用 + 未啟用 + IP + 埠 + 金鑰 + 不支援域名 + 無效的埠 + 開源許可 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 57e156436..8943d9c0b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -374,6 +374,9 @@ Hide galleries in certain languages from the gallery list and searches Excluded tag namespaces Exclude certain namespaces from a default tag search + H@H proxy + %1$s %2$s:%3$d + None Show Japanese title Try to show Japanese title. It takes more time to get gallery list Show default title. It is usually English title @@ -458,6 +461,15 @@ Beta update channel Beta release might be broken on your devices + Enable + Enabled + Disabled + IP + Port + Passkey + Domain is not supported + Invalid port + Excluded languages All diff --git a/app/src/main/res/xml/eh_settings.xml b/app/src/main/res/xml/eh_settings.xml index 5e27d84da..1f35c943a 100644 --- a/app/src/main/res/xml/eh_settings.xml +++ b/app/src/main/res/xml/eh_settings.xml @@ -56,6 +56,10 @@ android:summary="@string/settings_eh_excluded_languages_summary" app:activity="com.hippo.ehviewer.ui.ExcludedLanguagesActivity"/> + +