Compare commits

...

100 Commits

Author SHA1 Message Date
n8fr8 e822160b00 udpate gradle depend version to 0.3.4.8-2 2018-10-11 23:10:09 -04:00
n8fr8 b0e62e58cc updated torrc defaults 2018-10-11 23:09:32 -04:00
n8fr8 43b10491a1 updated bridges 2018-10-11 23:08:38 -04:00
n8fr8 c4cf800488 update build files 2018-10-11 16:51:11 -04:00
n8fr8 0417acf570 update version string to 0.3.4.8-openssl1.0.2p-1 for 2nd release of 0.3.4.8 2018-10-11 16:50:58 -04:00
n8fr8 ff7ecbdba9 update version for gradle lib 2018-10-11 09:27:52 -04:00
n8fr8 3e8e5ace65 update armeabi-v7a binary for 0.3.4.8 2018-10-07 09:40:12 -04:00
n8fr8 0fda8f7779 update x86 binary for 0.3.4.8 2018-10-07 09:35:31 -04:00
n8fr8 6548d3630b update tor binary to 0.3.4.8 w/o dirauth module 2018-10-07 08:55:14 -04:00
n8fr8 d1ee65a795 fixes #7 disable dirauth support for tor client only mode 2018-10-07 08:53:38 -04:00
n8fr8 a2fba85a5b update tor binary to 0.3.4.8 2018-10-07 08:45:09 -04:00
n8fr8 6ef0a45050 update to 0.3.4.8 2018-10-04 11:31:32 -04:00
n8fr8 b82b6a4cb1 update tor binary to tor-0.3.4.7-rc 2018-09-30 18:34:56 -04:00
n8fr8 de522e2ec8 tor-0.3.4.7-rc 2018-09-30 18:34:33 -04:00
n8fr8 0756d058f7 set to libevent 2.0.10-stable 2018-09-30 18:33:21 -04:00
n8fr8 b98cad65d4 set to master for libevent 2018-09-30 14:31:08 -04:00
n8fr8 cd678980f9 remove amazon meek bridge 2018-09-30 14:26:41 -04:00
n8fr8 8a66040c4f updated resource string to 0.3.4.8-openssl1.0.2p 2018-09-13 06:09:05 -04:00
n8fr8 75bd78b287 update gradle archive versioning 2018-09-12 17:14:07 -04:00
n8fr8 fa1ed5505d update Makefile to add specific NDK versioning for openssl 2018-09-12 17:11:31 -04:00
n8fr8 84ab10731c update tor to 0.3.4.8 2018-09-12 17:11:25 -04:00
n8fr8 63656611dc update binaries 2018-09-12 17:09:35 -04:00
n8fr8 84d7745cde update binary constants to trigger upgrade 2018-09-05 21:35:54 -04:00
n8fr8 b0e2d4e63b update library to version 34700 2018-09-05 21:34:25 -04:00
n8fr8 e97d5a1016 update binaries for tor-0.3.4.7-rc 2018-09-05 21:26:20 -04:00
n8fr8 0ba24f8ca4 update tor to tor-0.3.4.7-rc 2018-09-05 21:07:07 -04:00
n8fr8 93663355fa update to ensure compression libs are included in binary 2018-09-05 21:06:09 -04:00
n8fr8 63723e06ef update to 0.3.3.5-rc-3 2018-05-14 12:29:12 -04:00
n8fr8 ae61770960 update loader to handle zipped entries in a zip file (like tor.so in the APK) 2018-05-14 12:28:39 -04:00
n8fr8 45ecbcb298 update gradle build to 0.3.3.5-rc-2 2018-05-14 11:35:36 -04:00
n8fr8 d2342ed7ec add split APK support to the sample 2018-05-14 11:27:01 -04:00
n8fr8 549fb14077 update native loader code 2018-05-14 11:17:14 -04:00
n8fr8 5366016c86 add armeabi-v7a optimized build 2018-05-14 11:17:06 -04:00
n8fr8 de630b45cb add simple sample app 2018-05-14 10:38:29 -04:00
n8fr8 292dcda8e0 add additional ways to load native binaries from native libs 2018-05-14 10:38:10 -04:00
n8fr8 87efd233e5 update gradle version to force refetch 0.3.3.5-rc-1 2018-05-12 00:10:41 -04:00
n8fr8 ff59b5595f updating display string to 0.3.3.5-openssl1.0.2o 2018-05-12 00:05:36 -04:00
n8fr8 9e428e1e09 update archive build version to 0.3.3.5-rc 2018-05-11 23:56:50 -04:00
n8fr8 a46fd778b5 update gradle 2018-05-11 23:55:42 -04:00
n8fr8 db82e6b889 update tor binaries 2018-05-11 23:55:31 -04:00
n8fr8 7a9cbe8fc7 update gradle to 3.1.2 2018-05-11 23:54:59 -04:00
n8fr8 d364a5493c update tor to 0.3.3.5-rc 2018-05-11 23:54:37 -04:00
n8fr8 988a87c8ef upload maven build to 0.3.2.10-dev 2018-05-09 13:03:56 -04:00
n8fr8 51c7a076a5 update makefile to copy into proper native lib location 2018-05-09 12:53:26 -04:00
n8fr8 1b1f64d376 update to use faux .so shared library method for loading tor binary 2018-05-09 12:47:25 -04:00
n8fr8 9abac285db update deploy gradle for 0.3.2.10 2018-04-21 22:14:52 -04:00
n8fr8 808f9594f5 update tor x86 to 0.3.2.10 2018-04-21 22:09:25 -04:00
n8fr8 810eafd6e5 update tor 0.3.2.10 2018-04-21 22:01:26 -04:00
n8fr8 c0bca9f762 Merge branch 'master' of https://github.com/n8fr8/tor-android 2018-04-21 21:46:17 -04:00
Nathan Freitas 9897c1208e
Merge pull request #4 from Unpublished/remove_polipo
remove polipo
2018-04-20 00:20:08 -04:00
Nathan Freitas d194eb8064
Merge pull request #3 from Unpublished/a_few_updates
A few updates
2018-04-20 00:19:57 -04:00
Unpublished 97990103aa update tor to 0.3.2.10, OpenSSL to 1.0.2o and libevent to latest 2.0.* branch 2018-04-02 18:46:45 +02:00
Unpublished 8383c1abbc remove polipo 2018-03-16 17:56:33 +01:00
Unpublished d43fbf96b9 update geoip files to Tor Browser 7.5.1 2018-03-16 10:27:14 +01:00
Unpublished 99eb75aeaf update gradle to 4.5.1
includes speed and memory usage improvements
2018-03-16 10:24:18 +01:00
Unpublished 5e0169d762 remove useless stuff and update android gradle plugin to 3.0.1
put google() on top (google recommends it that way)
2018-03-16 10:24:08 +01:00
n8fr8 93f5239bea update library build to 0.3.1.9b 2018-01-03 22:55:37 -05:00
n8fr8 57ba718e75 update gradle build to 3191 0.3.1.9b
update geoip files (fixes issue with install on some devices)
ensure tor binaries are updated to 0.3.1.9
2018-01-03 22:51:22 -05:00
n8fr8 b4cdbff06b update installer for new geoip uncompressed format 2018-01-03 22:49:40 -05:00
n8fr8 b9a30b71d0 updated binaries for 0.3.1.9 2018-01-03 22:49:06 -05:00
n8fr8 3d0e9a93a6 delete old geoip copmressed files 2018-01-03 22:30:33 -05:00
n8fr8 1ebf0a5c2c update geoip files to latest from Tor Browser 2018-01-03 22:30:18 -05:00
n8fr8 3403b02dd8 Merge branch 'igortoliveira-tor-droid-build' 2017-12-07 12:37:13 -05:00
n8fr8 13d0bddc8c update script to build for x86 and armeabi 2017-12-07 12:36:38 -05:00
n8fr8 fa5aff40cc update some strings in the script 2017-12-07 10:53:51 -05:00
Igor Oliveira 1b1c0b9537 Add android tor build script
It is used to help the developer to fetch and build the app.
Initially, three commands were add:
1. fetch: It fetches the external dependencies
2. build: Build the project in release or debug mode
2017-12-07 13:25:56 -02:00
n8fr8 d64f15533f update gradle version 2017-12-03 16:05:13 +05:30
n8fr8 3528afd114 update constant for tor to 0.3.1.9 2017-12-03 16:02:49 +05:30
n8fr8 3b766484bf update README for 0.3.1.9 2017-12-03 10:04:16 +05:30
n8fr8 fc10fb1a9e update binaries and version to tor 0.3.1.9 2017-12-01 22:39:45 +05:30
n8fr8 ae5420426d remove auto of date patches 2017-11-17 12:37:08 -05:00
n8fr8 b85e0b32f2 remove appcompat library 2017-11-17 12:35:22 -05:00
n8fr8 c2189d4a2c Merge branch 'master' of github.com:n8fr8/tor-android 2017-11-17 12:34:31 -05:00
n8fr8 f15c153bf0 update to support building of aar archives 2017-11-17 12:34:06 -05:00
n8fr8 9b8d8719b6 remove jniLibs dir 2017-11-17 12:33:45 -05:00
n8fr8 673e45d60f remove all JNI code (since VPN isn't included her) 2017-11-17 12:33:29 -05:00
n8fr8 498364c25d update tor binary assets for x86 and armeabi 2017-11-17 12:33:09 -05:00
n8fr8 ffb8dd0b55 update package id to use the word "binary" not "native" 2017-11-17 12:32:24 -05:00
Nathan Freitas cdf3180291
Update README 2017-11-17 12:21:14 -05:00
n8fr8 3d951b9dd8 update path to new assets 2017-11-17 10:59:53 -05:00
n8fr8 f8dbfacdb3 more cleanup, and update of classes for installation 2017-11-17 10:58:42 -05:00
n8fr8 17f03d1f42 rename module to tor-android-binary 2017-11-17 10:45:47 -05:00
n8fr8 7e98222e47 change gitignore to allow for assets 2017-11-17 10:44:42 -05:00
n8fr8 f9c1af9127 removing pdnsd and obfs4proxy binaries 2017-11-17 10:44:29 -05:00
n8fr8 85aaff7152 adding in binary assets for gradle dependency build 2017-11-17 10:43:56 -05:00
n8fr8 7fbd72b0c8 remove pluto/obfs4proxy from build 2017-11-17 10:42:44 -05:00
n8fr8 a27480a208 more cleanup, removal of unused items from orbotservice 2017-11-17 10:40:46 -05:00
n8fr8 ff1979643c cleanup, and update project properties 2017-11-16 13:55:17 -05:00
n8fr8 dd51960b24 update README, clean up old ant and eclipse junk 2017-11-16 13:54:05 -05:00
n8fr8 a810a5add9 more cleanup, and removal of old orbot work 2017-11-16 13:52:37 -05:00
n8fr8 91b73b1f6b remove code only used for Orbot 2017-11-16 13:41:18 -05:00
n8fr8 fce5bdede8 add autopoint to dependencies 2017-11-11 08:56:15 -05:00
Nathan Freitas 72c7e0445c
Merge pull request #97 from SpotComms/padding
Expose *ConnectionPadding
2017-11-11 08:53:21 -05:00
Nathan Freitas 8cf412ad62
Merge pull request #98 from goapunk/add-lzma-zstd-as-dependency
Add lzma and zstd
2017-11-11 08:52:22 -05:00
goapunk c1dfc29e02 Update BUILD instructions
Signed-off-by: goapunk <noobie@goapunks.net>
2017-11-10 18:43:19 +01:00
goapunk 9ca36e1bff Add lzma and zstd
Signed-off-by: goapunk <noobie@goapunks.net>
2017-11-10 18:35:08 +01:00
Tad 6e4b700803 Expose *ConnectionPadding 2017-11-03 14:18:01 -04:00
Nathan Freitas 71e3464358
Merge pull request #94 from Unpublished/fix88
remove some transproxy left overs
2017-11-01 12:22:32 -04:00
Unpublished cbffc1d6ca remove some transproxy left overs
- fix typo to actually show transproxy warning only once (fixes issue #88)
2017-11-01 16:09:25 +01:00
n8fr8 1b904125f3 update CHANGELOG 2017-11-01 09:57:40 -04:00
1268 changed files with 208057 additions and 123511 deletions

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
<classpathentry kind="src" path="src">
<attributes>
<attribute name="ignore_optional_problems" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="src" path="gen"/>
<classpathentry kind="output" path="bin/classes"/>
</classpath>

2
.gitignore vendored
View File

@ -66,5 +66,3 @@ app/src/main/jniLibs/
app/src/main/libs/
orbotservice/src/main/libs/
orbotservice/src/main/jniLibs/
orbotservice/src/main/assets/armeabi/
orbotservice/src/main/assets/x86/

28
.gitmodules vendored
View File

@ -6,31 +6,15 @@
path = external/libevent
url = https://github.com/libevent/libevent.git
ignore = dirty
[submodule "external/jtorctl"]
path = external/jtorctl
url = https://github.com/guardianproject/jtorctl
ignore = dirty
[submodule "external/openssl"]
path = external/openssl
url = https://github.com/openssl/openssl.git
ignore = dirty
[submodule "external/iptables"]
path = external/iptables
url = git://git.netfilter.org/iptables
[submodule "external/zstd"]
path = external/zstd
url = https://github.com/facebook/zstd.git
ignore = dirty
[submodule "external/polipo"]
path = external/polipo
url = https://github.com/jech/polipo.git
ignore = dirty
[submodule "external/badvpn"]
path = external/badvpn
url = https://github.com/guardianproject/badvpn.git
ignore = dirty
[submodule "external/pluto"]
path = external/pluto
url = https://github.com/guardianproject/pluto.git
ignore = dirty
[submodule "external/jsocks"]
path = external/jsocks
url = https://github.com/guardianproject/jsocks.git
[submodule "external/xz"]
path = external/xz
url = https://git.tukaani.org/xz.git
ignore = dirty

View File

@ -1,11 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.WebProject">
<attributes>
<attribute name="hide" value="true"/>
</attributes>
</classpathentry>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>

View File

@ -1 +0,0 @@
org.eclipse.wst.jsdt.launching.baseBrowserLibrary

View File

@ -1 +0,0 @@
Window

View File

@ -1,23 +0,0 @@
[main]
host = https://www.transifex.com
lang_map = af_ZA: af-rZA, am_ET: am-rET, ar_AE: ar-rAE, ar_BH: ar-rBH, ar_DZ: ar-rDZ, ar_EG: ar-rEG, ar_IQ: ar-rIQ, ar_JO: ar-rJO, ar_KW: ar-rKW, ar_LB: ar-rLB, ar_LY: ar-rLY, ar_MA: ar-rMA, ar_OM: ar-rOM, ar_QA: ar-rQA, ar_SA: ar-rSA, ar_SY: ar-rSY, ar_TN: ar-rTN, ar_YE: ar-rYE, arn_CL: arn-rCL, as_IN: as-rIN, az_AZ: az-rAZ, ba_RU: ba-rRU, be_BY: be-rBY, bg_BG: bg-rBG, bn_BD: bn-rBD, bn_IN: bn-rIN, bo_CN: bo-rCN, br_FR: br-rFR, bs_BA: bs-rBA, ca_ES: ca-rES, co_FR: co-rFR, cs_CZ: cs-rCZ, cy_GB: cy-rGB, da_DK: da-rDK, de_AT: de-rAT, de_CH: de-rCH, de_DE: de-rDE, de_LI: de-rLI, de_LU: de-rLU, dsb_DE: dsb-rDE, dv_MV: dv-rMV, el_GR: el-rGR, en_AU: en-rAU, en_BZ: en-rBZ, en_CA: en-rCA, en_GB: en-rGB, en_IE: en-rIE, en_IN: en-rIN, en_JM: en-rJM, en_MY: en-rMY, en_NZ: en-rNZ, en_PH: en-rPH, en_SG: en-rSG, en_TT: en-rTT, en_US: en-rUS, en_ZA: en-rZA, en_ZW: en-rZW, es_AR: es-rAR, es_BO: es-rBO, es_CL: es-rCL, es_CO: es-rCO, es_CR: es-rCR, es_DO: es-rDO, es_EC: es-rEC, es_ES: es-rES, es_GT: es-rGT, es_HN: es-rHN, es_MX: es-rMX, es_NI: es-rNI, es_PA: es-rPA, es_PE: es-rPE, es_PR: es-rPR, es_PY: es-rPY, es_SV: es-rSV, es_US: es-rUS, es_UY: es-rUY, es_VE: es-rVE, et_EE: et-rEE, eu_ES: eu-rES, fa_IR: fa-rIR, fi_FI: fi-rFI, fil: tl, fil_PH: tl-rPH, fo_FO: fo-rFO, fr_BE: fr-rBE, fr_CA: fr-rCA, fr_CH: fr-rCH, fr_FR: fr-rFR, fr_LU: fr-rLU, fr_MC: fr-rMC, fy_NL: fy-rNL, ga_IE: ga-rIE, gd_GB: gd-rGB, gl_ES: gl-rES, gsw_FR: gsw-rFR, gu_IN: gu-rIN, ha_NG: ha-rNG, he: iw, he_IL: iw-rIL, hi_IN: hi-rIN, hr_BA: hr-rBA, hr_HR: hr-rHR, hsb_DE: hsb-rDE, hu_HU: hu-rHU, hy_AM: hy-rAM, id: in, id_ID: in-rID, ig_NG: ig-rNG, ii_CN: ii-rCN, is_IS: is-rIS, it_CH: it-rCH, it_IT: it-rIT, iu_CA: iu-rCA, ja_JP: ja-rJP, ka_GE: ka-rGE, kk_KZ: kk-rKZ, kl_GL: kl-rGL, km_KH: km-rKH, kn_IN: kn-rIN, ko_KR: ko-rKR, kok_IN: kok-rIN, ky_KG: ky-rKG, lb_LU: lb-rLU, lo_LA: lo-rLA, lt_LT: lt-rLT, lv_LV: lv-rLV, mi_NZ: mi-rNZ, mk_MK: mk-rMK, ml_IN: ml-rIN, mn_CN: mn-rCN, mn_MN: mn-rMN, moh_CA: moh-rCA, mr_IN: mr-rIN, ms_BN: ms-rBN, ms_MY: ms-rMY, mt_MT: mt-rMT, nb_NO: nb-rNO, ne_NP: ne-rNP, nl_BE: nl-rBE, nl_NL: nl-rNL, nn_NO: nn-rNO, nso_ZA: nso-rZA, oc_FR: oc-rFR, or_IN: or-rIN, pa_IN: pa-rIN, pl_PL: pl-rPL, prs_AF: prs-rAF, ps_AF: ps-rAF, pt_BR: pt-rBR, pt_PT: pt-rPT, qut_GT: qut-rGT, quz_BO: quz-rBO, quz_EC: quz-rEC, quz_PE: quz-rPE, rm_CH: rm-rCH, ro_RO: ro-rRO, ru_RU: ru-rRU, rw_RW: rw-rRW, sa_IN: sa-rIN, sah_RU: sah-rRU, se_FI: se-rFI, se_NO: se-rNO, se_SE: se-rSE, si_LK: si-rLK, sk_SK: sk-rSK, sl_SI: sl-rSI, sma_NO: sma-rNO, sma_SE: sma-rSE, smj_NO: smj-rNO, smj_SE: smj-rSE, smn_FI: smn-rFI, sms_FI: sms-rFI, sq_AL: sq-rAL, sr: sr, sv_FI: sv-rFI, sv_SE: sv-rSE, sw_KE: sw-rKE, syr_SY: syr-rSY, ta_IN: ta-rIN, te_IN: te-rIN, tg_TJ: tg-rTJ, th_TH: th-rTH, tk_TM: tk-rTM, tn_ZA: tn-rZA, tr_TR: tr-rTR, tt_RU: tt-rRU, tzm_DZ: tzm-rDZ, ug_CN: ug-rCN, uk_UA: uk-rUA, ur_PK: ur-rPK, uz_UZ: uz-rUZ, vi_VN: vi-rVN, wo_SN: wo-rSN, xh_ZA: xh-rZA, yo_NG: yo-rNG, zh: zh-rCN, zh_HK: zh-rHK, zh_MO: zh-rMO, zh_SG: zh-rSG, zh_TW: zh-rTW, zu_ZA: zu-rZA
[orbot.stringsxml]
file_filter = res/values-<lang>/strings.xml
host = https://www.transifex.com
source_file = res/values/strings.xml
source_lang = en
type = ANDROID
[orbot.description]
file_filter = description/<lang>.xlf
host = https://www.transifex.com
source_file = description/source.xlf
source_lang = en
type = XLIFF
#[orbot.olddescription]
#file_filter = releases/assets/<lang>-description.txt
#host = https://www.transifex.com
#source_file = releases/assets/description.txt
#source_lang = en

30
BUILD
View File

@ -8,8 +8,6 @@ Orbot includes, in the external directory, git repo submodules of:
- LibEvent
- JTorControl: The Tor Control Library for Java
The Orbot repo also includes the Polipo source code of a recent stable release.
Please install the following prerequisites (instructions for each follows):
ant: http://ant.apache.org/
Android Native Dev Kit or NDK (for C/C++ code):
@ -19,37 +17,19 @@ Please install the following prerequisites (instructions for each follows):
AutoMake and AutoConf tool
sudo apt-get install autotools-dev
sudo apt-get install automake
sudo apt-gen install autogen autoconf libtool
sudo apt-get install autogen autoconf libtool gettext-base autopoint
You will need to run the 'android' command in the SDK to install the necessary
Android platform supports (ICS 4.x or android-15)
Be sure that you have all of the git submodules up-to-date:
git submodule update --init --recursive
./tor-droid-make.sh fetch
To begin building, from the Orbot root directory, you first need to build all
external C/native dependencies:
To begin building, from the Orbot root directory, it builds all submodules and
the project.
export ANDROID_NDK_HOME={PATH TO YOUR NDK INSTALL}
make -C external
At this point, you'll have Tor and Polipo binaries that can be run on an
Android handset. You can verify the ARM binary was properly built using the
following command:
file external/bin/tor external/bin/polipo
You should see something like:
external/bin/tor: ELF 32-bit LSB executable, ARM, version 1 (SYSV),
dynamically linked (uses shared libs), not stripped
external/bin/polipo: ELF 32-bit LSB executable, ARM, version 1 (SYSV),
dynamically linked (uses shared libs), not stripped
This isn't enough though and we'll now sew up the binary into a small package
that will handle basic Tor controlling features.
android update project --name Orbot --target android-15 --path .
./tor-droid-make.sh build
Now build the Android app

1369
CHANGELOG

File diff suppressed because it is too large Load Diff

40
INSTALL
View File

@ -1,40 +0,0 @@
Orbot: Android Onion Routing Robot
***********************************************
Android is a freely licensed open-source application developed for the
Android platform. It acts as a front-end to the Tor binary application,
and also provides an HTTP Proxy for connecting web browsers and other
HTTP client applications into the Tor SOCKS interface.
*** PreReqs ***
You need the Android Developer SDK to compile and build the APK file:
http://developer.android.com/
The project files including in this distribution are meant to be used
with Eclipse: http://eclipse.org/
*** How to use ***
Currently, Orbot will work with any application that supports using
an HTTP or SOCKS Proxy. Once you start Tor using Orbot, you can then
point your application to HTTP port 8118 or SOCKS port 9050 on localhost
IP 127.0.0.1.
If you have root access, and a version of Android with iptables that
supports the netfilter owner module, then Orbot can setup transparent
proxying for any application.
Finally, Firefox on Android is available, and we have released an
add-on named ProxyMob for configuring SOCKS proxy settings for use
with the local Tor socks proxy.
** A Few Notes **
To ensure you are connected to the Tor network, you should browse to
https://check.torproject.org/
The first time you activate Orbot, it may take a while to connect to
Tor. Check the message log to ensure you are "100% Bootstrapped".
***********************************************
/* Copyright (c) 2009,2010,2011, Nathan Freitas, The Guardian Project
* http://guardianproject.info/ */

38
README
View File

@ -1,15 +1,28 @@
Orbot: Android Onion Routing Robot
Tor Android
***********************************************
Orbot is a freely licensed open-source application developed for the
Android platform. It acts as a front-end to the Tor binary application,
and also provides an HTTP Proxy for connecting web browsers and other
HTTP client applications into the Tor SOCKS interface.
This is a project forked from Orbot for building the tor binary for Android
How to Build
***********************************************
Orbot is a component of the Guardian Project, an effort to develop
a secure, anonymous smartphone for use by human rights activists, journalists
and others around the world. Learn more: https://guardianproject.info/
Please see: https://raw.githubusercontent.com/n8fr8/tor-android/master/BUILD
How to Use via Gradle
***********************************************
Add the repository your list as shown:
repositories {
maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" }
}
and then add the dependency, setting it to the latest version (or any version) we have made available, as a release:
dependencies {
compile 'org.torproject:tor-android-binary:0.3.1.9'
}
***********************************************
Tor protects your privacy on the internet by hiding the connection
@ -21,12 +34,3 @@ Tor Frequently Asked Questions:
https://wiki.torproject.org/noreply/TheOnionRouter/TorFAQ
https://www.torproject.org/faq.html.en
***********************************************
/* Copyright (c) 2009-2013, Nathan Freitas, The Guardian Project
* https://guardianproject.info/ */
*****
Some icons thanks to:
https://drslash.com/flat-osx-pack/
FLAT OS by DrSlash.com is licensed under a Creative Commons Attribution NonCommercial 4.0 International License.

View File

@ -1,46 +0,0 @@
<!-- Proguard Properties -->
<property name="obfuscate.dir" value="obf" />
<property name="obfuscate.absolute.dir" location="${obfuscate.dir}" />
<property name="android-jar-preobfuscate" value="${obfuscate.absolute.dir}/original.jar" />
<property name="android-jar-postobfuscate" value="${obfuscate.absolute.dir}/postobf.jar" />
<property name="out.dex.input.absolute.dir" value="${android-jar-postobfuscate}" />
<!-- replaces the post-compile step from ant_rules_r3 -->
<target name="-post-compile" depends="-dex-obfuscate,-dex-no-obfuscate">
</target>
<target name="-dex-no-obfuscate" unless="build.mode.release">
<mkdir dir="${obfuscate.absolute.dir}" />
<jar basedir="${out.dir}/classes" destfile="${android-jar-postobfuscate}" />
</target>
<!-- Converts this project's .class files into .dex files -->
<target name="-dex-obfuscate" if="build.mode.release">
<property name="proguard-jar" value="${proguard.dir}/proguard.jar" />
<property name="proguard-conf.dir" value="" />
<property name="proguard-conf.absolute.dir" location="${proguard-conf.dir}" />
<property name="proguard-conf" value="${proguard-conf.absolute.dir}/procfg.txt" />
<path id="fullclasspath">
<path refid="android.target.classpath"/>
<pathelement path="${external.libs.dir}"/>
</path>
<property name="libraryjarpath" refid="fullclasspath"/>
<!-- Add Proguard Task -->
<taskdef resource="proguard/ant/task.properties" classpath="${proguard-jar}" />
<mkdir dir="${obfuscate.absolute.dir}" />
<delete file="${android-jar-preobfuscate}"/>
<delete file="${android-jar-postobfuscate}"/>
<jar basedir="${out.classes.dir}" destfile="${android-jar-preobfuscate}" />
<proguard>
@${proguard-conf}
-injars ${android-jar-preobfuscate}
-outjars ${android-jar-postobfuscate}
-libraryjars ${libraryjarpath}
-dump ${obfuscate.absolute.dir}/dump.txt
-printseeds ${obfuscate.absolute.dir}/seeds.txt
-printusage ${obfuscate.absolute.dir}/usage.txt
-printmapping ${obfuscate.absolute.dir}/mapping.txt
</proguard>
</target>

View File

@ -1,52 +0,0 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion '26.0.2'
defaultConfig {
applicationId "org.torproject.android"
minSdkVersion 16
targetSdkVersion 25
}
lintOptions {
checkReleaseBuilds false
// Or, if you prefer, you can continue to check for errors in release builds,
// but continue the build even when errors are found:
abortOnError false
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
}
}
flavorDimensions "free"
productFlavors {
minimalperm {
dimension "free"
minSdkVersion 16
applicationId 'org.torproject.android'
targetSdkVersion 23
maxSdkVersion 23
versionCode 15510001
versionName '15.5.1-RC-2-multi-SDK16'
}
fullperm {
dimension "free"
minSdkVersion 23
applicationId 'org.torproject.android'
targetSdkVersion 25
versionCode 15510002
versionName '15.5.1-RC-2-multi-SDK23'
}
}
}
dependencies {
compile project(':orbotservice')
compile 'com.android.support:support-v4:25.3.1'
compile 'com.android.support:appcompat-v7:25.3.1'
compile 'com.android.support:design:25.3.1'
}

View File

@ -1,71 +0,0 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in /home/n8fr8/dev/android/sdk/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
-optimizationpasses 5
-dontusemixedcaseclassnames
-dontskipnonpubliclibraryclasses
-dontskipnonpubliclibraryclassmembers
-dontpreverify
-verbose
-repackageclasses ''
-allowaccessmodification
-keepattributes *Annotation*
-injars src/main/libs
-outjars bin/classes-processed.jar
-dontwarn javax.naming.**
-dontwarn android.support.**
####
-keep class org.** { *; }
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.app.backup.BackupAgentHelper
-keep public class * extends android.preference.Preference
-keep public class com.android.vending.licensing.ILicensingService
-keepclasseswithmembernames class * {
native <methods>;
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
public void *(android.view.View);
}
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
-keep class * implements android.os.Parcelable {
public static final android.os.Parcelable$Creator *;
}

View File

@ -1,166 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.torproject.android"
android:installLocation="auto">
<uses-sdk
android:minSdkVersion="16"
android:targetSdkVersion="25" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<application
android:name=".OrbotApp"
android:allowBackup="false"
android:allowClearUserData="true"
android:configChanges="locale|orientation|screenSize"
android:description="@string/app_description"
android:hardwareAccelerated="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:largeHeap="false"
android:theme="@style/DefaultTheme">
<activity
android:name=".OrbotMainActivity"
android:excludeFromRecents="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="bridge" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="org.torproject.android.START_TOR" />
</intent-filter>
</activity>
<!-- This is for ensuring the background service still runs when/if the app is swiped away -->
<activity
android:name=".service.util.DummyActivity"
android:allowTaskReparenting="true"
android:alwaysRetainTaskState="false"
android:clearTaskOnLaunch="true"
android:enabled="true"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true"
android:noHistory="true"
android:stateNotNeeded="true"
android:theme="@android:style/Theme.Translucent" />
<activity
android:name=".vpn.VPNEnableActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
android:name=".ui.PromoAppsActivity"
android:exported="false" />
<activity
android:name=".settings.SettingsPreferences"
android:label="@string/app_name" />
<activity
android:name=".ui.AppManagerActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat" />
<service
android:name=".service.TorService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE"
android:stopWithTask="false"></service>
<service
android:name=".service.vpn.TorVpnService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
</service>
<receiver
android:name=".service.StartTorReceiver"
android:exported="true">
<intent-filter>
<action android:name="org.torproject.android.intent.action.START" />
</intent-filter>
</receiver>
<receiver
android:name=".OnBootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<activity
android:name=".ui.hiddenservices.HiddenServicesActivity"
android:label="@string/title_activity_hidden_services"
android:theme="@style/DefaultTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".OrbotMainActivity" />
</activity>
<provider
android:name=".ui.hiddenservices.providers.HSContentProvider"
android:authorities="org.torproject.android.ui.hiddenservices.providers"
android:exported="false" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.torproject.android.ui.hiddenservices.storage"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/hidden_services_paths" />
</provider>
<activity
android:name=".ui.hiddenservices.ClientCookiesActivity"
android:label="@string/client_cookies"
android:theme="@style/DefaultTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".OrbotMainActivity" />
</activity>
<provider
android:name=".ui.hiddenservices.providers.CookieContentProvider"
android:authorities="org.torproject.android.ui.hiddenservices.providers.cookie"
android:exported="false" />
</application>
</manifest>

View File

@ -1,158 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.torproject.android"
android:installLocation="auto">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
<application
android:name=".OrbotApp"
android:allowBackup="false"
android:allowClearUserData="true"
android:configChanges="locale|orientation|screenSize"
android:description="@string/app_description"
android:hardwareAccelerated="false"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:largeHeap="false"
android:theme="@style/DefaultTheme">
<activity
android:name=".OrbotMainActivity"
android:excludeFromRecents="true"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="bridge" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="org.torproject.android.REQUEST_HS_PORT" />
</intent-filter>
<intent-filter>
<category android:name="android.intent.category.DEFAULT" />
<action android:name="org.torproject.android.START_TOR" />
</intent-filter>
</activity>
<!-- This is for ensuring the background service still runs when/if the app is swiped away -->
<activity
android:name=".service.util.DummyActivity"
android:allowTaskReparenting="true"
android:alwaysRetainTaskState="false"
android:clearTaskOnLaunch="true"
android:enabled="true"
android:excludeFromRecents="true"
android:finishOnTaskLaunch="true"
android:noHistory="true"
android:stateNotNeeded="true"
android:theme="@android:style/Theme.Translucent" />
<activity
android:name=".vpn.VPNEnableActivity"
android:exported="false"
android:label="@string/app_name" />
<activity
android:name=".ui.PromoAppsActivity"
android:exported="false" />
<activity
android:name=".settings.SettingsPreferences"
android:label="@string/app_name" />
<activity
android:name=".ui.AppManagerActivity"
android:label="@string/app_name"
android:theme="@style/Theme.AppCompat" />
<service
android:name=".service.TorService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE"
android:stopWithTask="false"></service>
<service
android:name=".service.vpn.TorVpnService"
android:enabled="true"
android:permission="android.permission.BIND_VPN_SERVICE">
<intent-filter>
<action android:name="android.net.VpnService" />
</intent-filter>
</service>
<receiver
android:name=".service.StartTorReceiver"
android:exported="true">
<intent-filter>
<action android:name="org.torproject.android.intent.action.START" />
</intent-filter>
</receiver>
<receiver
android:name=".OnBootReceiver"
android:enabled="true"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MEDIA_MOUNTED" />
<category android:name="android.intent.category.HOME" />
</intent-filter>
</receiver>
<activity
android:name=".ui.hiddenservices.HiddenServicesActivity"
android:label="@string/title_activity_hidden_services"
android:theme="@style/DefaultTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".OrbotMainActivity" />
</activity>
<provider
android:name=".ui.hiddenservices.providers.HSContentProvider"
android:authorities="org.torproject.android.ui.hiddenservices.providers"
android:exported="false" />
<provider
android:name="android.support.v4.content.FileProvider"
android:authorities="org.torproject.android.ui.hiddenservices.storage"
android:exported="false"
android:grantUriPermissions="true">
<meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/hidden_services_paths" />
</provider>
<activity
android:name=".ui.hiddenservices.ClientCookiesActivity"
android:label="@string/client_cookies"
android:theme="@style/DefaultTheme">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value=".OrbotMainActivity" />
</activity>
<provider
android:name=".ui.hiddenservices.providers.CookieContentProvider"
android:authorities="org.torproject.android.ui.hiddenservices.providers.cookie"
android:exported="false" />
</application>
</manifest>

View File

@ -1 +0,0 @@
../../../../LICENSE

View File

@ -1,506 +0,0 @@
/*
* Copyright 2009 ZXing authors
*
* 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.google.zxing.integration.android;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Fragment;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
/**
* <p>A utility class which helps ease integration with Barcode Scanner via {@link Intent}s. This is a simple
* way to invoke barcode scanning and receive the result, without any need to integrate, modify, or learn the
* project's source code.</p>
*
* <h2>Initiating a barcode scan</h2>
*
* <p>To integrate, create an instance of {@code IntentIntegrator} and call {@link #initiateScan()} and wait
* for the result in your app.</p>
*
* <p>It does require that the Barcode Scanner (or work-alike) application is installed. The
* {@link #initiateScan()} method will prompt the user to download the application, if needed.</p>
*
* <p>There are a few steps to using this integration. First, your {@link Activity} must implement
* the method {@link Activity#onActivityResult(int, int, Intent)} and include a line of code like this:</p>
*
* <pre>{@code
* public void onActivityResult(int requestCode, int resultCode, Intent intent) {
* IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent);
* if (scanResult != null) {
* // handle scan result
* }
* // else continue with any other code you need in the method
* ...
* }
* }</pre>
*
* <p>This is where you will handle a scan result.</p>
*
* <p>Second, just call this in response to a user action somewhere to begin the scan process:</p>
*
* <pre>{@code
* IntentIntegrator integrator = new IntentIntegrator(yourActivity);
* integrator.initiateScan();
* }</pre>
*
* <p>Note that {@link #initiateScan()} returns an {@link AlertDialog} which is non-null if the
* user was prompted to download the application. This lets the calling app potentially manage the dialog.
* In particular, ideally, the app dismisses the dialog if it's still active in its {@link Activity#onPause()}
* method.</p>
*
* <p>You can use {@link #setTitle(String)} to customize the title of this download prompt dialog (or, use
* {@link #setTitleByID(int)} to set the title by string resource ID.) Likewise, the prompt message, and
* yes/no button labels can be changed.</p>
*
* <p>Finally, you can use {@link #addExtra(String, Object)} to add more parameters to the Intent used
* to invoke the scanner. This can be used to set additional options not directly exposed by this
* simplified API.</p>
*
* <p>By default, this will only allow applications that are known to respond to this intent correctly
* do so. The apps that are allowed to response can be set with {@link #setTargetApplications(List)}.
* For example, set to {@link #TARGET_BARCODE_SCANNER_ONLY} to only target the Barcode Scanner app itself.</p>
*
* <h2>Sharing text via barcode</h2>
*
* <p>To share text, encoded as a QR Code on-screen, similarly, see {@link #shareText(CharSequence)}.</p>
*
* <p>Some code, particularly download integration, was contributed from the Anobiit application.</p>
*
* <h2>Enabling experimental barcode formats</h2>
*
* <p>Some formats are not enabled by default even when scanning with {@link #ALL_CODE_TYPES}, such as
* PDF417. Use {@link #initiateScan(java.util.Collection)} with
* a collection containing the names of formats to scan for explicitly, like "PDF_417", to use such
* formats.</p>
*
* @author Sean Owen
* @author Fred Lin
* @author Isaac Potoczny-Jones
* @author Brad Drehmer
* @author gcstang
*/
public class IntentIntegrator {
public static final int REQUEST_CODE = 0x0000c0de; // Only use bottom 16 bits
private static final String TAG = IntentIntegrator.class.getSimpleName();
public static final String DEFAULT_TITLE = "Install Barcode Scanner?";
public static final String DEFAULT_MESSAGE =
"This application requires Barcode Scanner. Would you like to install it?";
public static final String DEFAULT_YES = "Yes";
public static final String DEFAULT_NO = "No";
private static final String BS_PACKAGE = "com.google.zxing.client.android";
private static final String BSPLUS_PACKAGE = "com.srowen.bs.android";
// supported barcode formats
public static final Collection<String> PRODUCT_CODE_TYPES = list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "RSS_14");
public static final Collection<String> ONE_D_CODE_TYPES =
list("UPC_A", "UPC_E", "EAN_8", "EAN_13", "CODE_39", "CODE_93", "CODE_128",
"ITF", "RSS_14", "RSS_EXPANDED");
public static final Collection<String> QR_CODE_TYPES = Collections.singleton("QR_CODE");
public static final Collection<String> DATA_MATRIX_TYPES = Collections.singleton("DATA_MATRIX");
public static final Collection<String> ALL_CODE_TYPES = null;
public static final List<String> TARGET_BARCODE_SCANNER_ONLY = Collections.singletonList(BS_PACKAGE);
public static final List<String> TARGET_ALL_KNOWN = list(
BSPLUS_PACKAGE, // Barcode Scanner+
BSPLUS_PACKAGE + ".simple", // Barcode Scanner+ Simple
BS_PACKAGE // Barcode Scanner
// What else supports this intent?
);
private final Activity activity;
private final Fragment fragment;
private String title;
private String message;
private String buttonYes;
private String buttonNo;
private List<String> targetApplications;
private final Map<String,Object> moreExtras = new HashMap<String,Object>(3);
/**
* @param activity {@link Activity} invoking the integration
*/
public IntentIntegrator(Activity activity) {
this.activity = activity;
this.fragment = null;
initializeConfiguration();
}
/**
* @param fragment {@link Fragment} invoking the integration.
* {@link #startActivityForResult(Intent, int)} will be called on the {@link Fragment} instead
* of an {@link Activity}
*/
public IntentIntegrator(Fragment fragment) {
this.activity = fragment.getActivity();
this.fragment = fragment;
initializeConfiguration();
}
private void initializeConfiguration() {
title = DEFAULT_TITLE;
message = DEFAULT_MESSAGE;
buttonYes = DEFAULT_YES;
buttonNo = DEFAULT_NO;
targetApplications = TARGET_ALL_KNOWN;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public void setTitleByID(int titleID) {
title = activity.getString(titleID);
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public void setMessageByID(int messageID) {
message = activity.getString(messageID);
}
public String getButtonYes() {
return buttonYes;
}
public void setButtonYes(String buttonYes) {
this.buttonYes = buttonYes;
}
public void setButtonYesByID(int buttonYesID) {
buttonYes = activity.getString(buttonYesID);
}
public String getButtonNo() {
return buttonNo;
}
public void setButtonNo(String buttonNo) {
this.buttonNo = buttonNo;
}
public void setButtonNoByID(int buttonNoID) {
buttonNo = activity.getString(buttonNoID);
}
public Collection<String> getTargetApplications() {
return targetApplications;
}
public final void setTargetApplications(List<String> targetApplications) {
if (targetApplications.isEmpty()) {
throw new IllegalArgumentException("No target applications");
}
this.targetApplications = targetApplications;
}
public void setSingleTargetApplication(String targetApplication) {
this.targetApplications = Collections.singletonList(targetApplication);
}
public Map<String,?> getMoreExtras() {
return moreExtras;
}
public final void addExtra(String key, Object value) {
moreExtras.put(key, value);
}
/**
* Initiates a scan for all known barcode types with the default camera.
*
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan() {
return initiateScan(ALL_CODE_TYPES, -1);
}
/**
* Initiates a scan for all known barcode types with the specified camera.
*
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(int cameraId) {
return initiateScan(ALL_CODE_TYPES, cameraId);
}
/**
* Initiates a scan, using the default camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise.
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats) {
return initiateScan(desiredBarcodeFormats, -1);
}
/**
* Initiates a scan, using the specified camera, only for a certain set of barcode types, given as strings corresponding
* to their names in ZXing's {@code BarcodeFormat} class like "UPC_A". You can supply constants
* like {@link #PRODUCT_CODE_TYPES} for example.
*
* @param desiredBarcodeFormats names of {@code BarcodeFormat}s to scan for
* @param cameraId camera ID of the camera to use. A negative value means "no preference".
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public final AlertDialog initiateScan(Collection<String> desiredBarcodeFormats, int cameraId) {
Intent intentScan = new Intent(BS_PACKAGE + ".SCAN");
intentScan.addCategory(Intent.CATEGORY_DEFAULT);
// check which types of codes to scan for
if (desiredBarcodeFormats != null) {
// set the desired barcode types
StringBuilder joinedByComma = new StringBuilder();
for (String format : desiredBarcodeFormats) {
if (joinedByComma.length() > 0) {
joinedByComma.append(',');
}
joinedByComma.append(format);
}
intentScan.putExtra("SCAN_FORMATS", joinedByComma.toString());
}
// check requested camera ID
if (cameraId >= 0) {
intentScan.putExtra("SCAN_CAMERA_ID", cameraId);
}
String targetAppPackage = findTargetAppPackage(intentScan);
if (targetAppPackage == null) {
return showDownloadDialog();
}
intentScan.setPackage(targetAppPackage);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intentScan.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intentScan);
startActivityForResult(intentScan, REQUEST_CODE);
return null;
}
/**
* Start an activity. This method is defined to allow different methods of activity starting for
* newer versions of Android and for compatibility library.
*
* @param intent Intent to start.
* @param code Request code for the activity
* @see android.app.Activity#startActivityForResult(Intent, int)
* @see android.app.Fragment#startActivityForResult(Intent, int)
*/
protected void startActivityForResult(Intent intent, int code) {
if (fragment == null) {
activity.startActivityForResult(intent, code);
} else {
fragment.startActivityForResult(intent, code);
}
}
private String findTargetAppPackage(Intent intent) {
PackageManager pm = activity.getPackageManager();
List<ResolveInfo> availableApps = pm.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
if (availableApps != null) {
for (String targetApp : targetApplications) {
if (contains(availableApps, targetApp)) {
return targetApp;
}
}
}
return null;
}
private static boolean contains(Iterable<ResolveInfo> availableApps, String targetApp) {
for (ResolveInfo availableApp : availableApps) {
String packageName = availableApp.activityInfo.packageName;
if (targetApp.equals(packageName)) {
return true;
}
}
return false;
}
private AlertDialog showDownloadDialog() {
AlertDialog.Builder downloadDialog = new AlertDialog.Builder(activity);
downloadDialog.setTitle(title);
downloadDialog.setMessage(message);
downloadDialog.setPositiveButton(buttonYes, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String packageName;
if (targetApplications.contains(BS_PACKAGE)) {
// Prefer to suggest download of BS if it's anywhere in the list
packageName = BS_PACKAGE;
} else {
// Otherwise, first option:
packageName = targetApplications.get(0);
}
Uri uri = Uri.parse("market://details?id=" + packageName);
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
try {
if (fragment == null) {
activity.startActivity(intent);
} else {
fragment.startActivity(intent);
}
} catch (ActivityNotFoundException anfe) {
// Hmm, market is not installed
Log.w(TAG, "Google Play is not installed; cannot install " + packageName);
}
}
});
downloadDialog.setNegativeButton(buttonNo, null);
downloadDialog.setCancelable(true);
return downloadDialog.show();
}
/**
* <p>Call this from your {@link Activity}'s
* {@link Activity#onActivityResult(int, int, Intent)} method.</p>
*
* @param requestCode request code from {@code onActivityResult()}
* @param resultCode result code from {@code onActivityResult()}
* @param intent {@link Intent} from {@code onActivityResult()}
* @return null if the event handled here was not related to this class, or
* else an {@link IntentResult} containing the result of the scan. If the user cancelled scanning,
* the fields will be null.
*/
public static IntentResult parseActivityResult(int requestCode, int resultCode, Intent intent) {
if (requestCode == REQUEST_CODE) {
if (resultCode == Activity.RESULT_OK) {
String contents = intent.getStringExtra("SCAN_RESULT");
String formatName = intent.getStringExtra("SCAN_RESULT_FORMAT");
byte[] rawBytes = intent.getByteArrayExtra("SCAN_RESULT_BYTES");
int intentOrientation = intent.getIntExtra("SCAN_RESULT_ORIENTATION", Integer.MIN_VALUE);
Integer orientation = intentOrientation == Integer.MIN_VALUE ? null : intentOrientation;
String errorCorrectionLevel = intent.getStringExtra("SCAN_RESULT_ERROR_CORRECTION_LEVEL");
return new IntentResult(contents,
formatName,
rawBytes,
orientation,
errorCorrectionLevel);
}
return new IntentResult();
}
return null;
}
/**
* Defaults to type "TEXT_TYPE".
*
* @param text the text string to encode as a barcode
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
* @see #shareText(CharSequence, CharSequence)
*/
public final AlertDialog shareText(CharSequence text) {
return shareText(text, "TEXT_TYPE");
}
/**
* Shares the given text by encoding it as a barcode, such that another user can
* scan the text off the screen of the device.
*
* @param text the text string to encode as a barcode
* @param type type of data to encode. See {@code com.google.zxing.client.android.Contents.Type} constants.
* @return the {@link AlertDialog} that was shown to the user prompting them to download the app
* if a prompt was needed, or null otherwise
*/
public final AlertDialog shareText(CharSequence text, CharSequence type) {
Intent intent = new Intent();
intent.addCategory(Intent.CATEGORY_DEFAULT);
intent.setAction(BS_PACKAGE + ".ENCODE");
intent.putExtra("ENCODE_TYPE", type);
intent.putExtra("ENCODE_DATA", text);
String targetAppPackage = findTargetAppPackage(intent);
if (targetAppPackage == null) {
return showDownloadDialog();
}
intent.setPackage(targetAppPackage);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
attachMoreExtras(intent);
if (fragment == null) {
activity.startActivity(intent);
} else {
fragment.startActivity(intent);
}
return null;
}
private static List<String> list(String... values) {
return Collections.unmodifiableList(Arrays.asList(values));
}
private void attachMoreExtras(Intent intent) {
for (Map.Entry<String,Object> entry : moreExtras.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
// Kind of hacky
if (value instanceof Integer) {
intent.putExtra(key, (Integer) value);
} else if (value instanceof Long) {
intent.putExtra(key, (Long) value);
} else if (value instanceof Boolean) {
intent.putExtra(key, (Boolean) value);
} else if (value instanceof Double) {
intent.putExtra(key, (Double) value);
} else if (value instanceof Float) {
intent.putExtra(key, (Float) value);
} else if (value instanceof Bundle) {
intent.putExtra(key, (Bundle) value);
} else {
intent.putExtra(key, value.toString());
}
}
}
}

View File

@ -1,95 +0,0 @@
/*
* Copyright 2009 ZXing authors
*
* 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.google.zxing.integration.android;
/**
* <p>Encapsulates the result of a barcode scan invoked through {@link IntentIntegrator}.</p>
*
* @author Sean Owen
*/
public final class IntentResult {
private final String contents;
private final String formatName;
private final byte[] rawBytes;
private final Integer orientation;
private final String errorCorrectionLevel;
IntentResult() {
this(null, null, null, null, null);
}
IntentResult(String contents,
String formatName,
byte[] rawBytes,
Integer orientation,
String errorCorrectionLevel) {
this.contents = contents;
this.formatName = formatName;
this.rawBytes = rawBytes;
this.orientation = orientation;
this.errorCorrectionLevel = errorCorrectionLevel;
}
/**
* @return raw content of barcode
*/
public String getContents() {
return contents;
}
/**
* @return name of format, like "QR_CODE", "UPC_A". See {@code BarcodeFormat} for more format names.
*/
public String getFormatName() {
return formatName;
}
/**
* @return raw bytes of the barcode content, if applicable, or null otherwise
*/
public byte[] getRawBytes() {
return rawBytes;
}
/**
* @return rotation of the image, in degrees, which resulted in a successful scan. May be null.
*/
public Integer getOrientation() {
return orientation;
}
/**
* @return name of the error correction level used in the barcode, if applicable
*/
public String getErrorCorrectionLevel() {
return errorCorrectionLevel;
}
@Override
public String toString() {
StringBuilder dialogText = new StringBuilder(100);
dialogText.append("Format: ").append(formatName).append('\n');
dialogText.append("Contents: ").append(contents).append('\n');
int rawBytesLength = rawBytes == null ? 0 : rawBytes.length;
dialogText.append("Raw bytes: (").append(rawBytesLength).append(" bytes)\n");
dialogText.append("Orientation: ").append(orientation).append('\n');
dialogText.append("EC level: ").append(errorCorrectionLevel).append('\n');
return dialogText.toString();
}
}

View File

@ -1,49 +0,0 @@
package org.torproject.android;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.torproject.android.service.util.Prefs;
import org.torproject.android.service.TorService;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.vpn.VPNEnableActivity;
public class OnBootReceiver extends BroadcastReceiver {
private static boolean sReceivedBoot = false;
@Override
public void onReceive(Context context, Intent intent) {
if (Prefs.startOnBoot() && (!sReceivedBoot))
{
if (Prefs.useVpn())
startVpnService(context); //VPN will start Tor once it is done
else
startService(TorServiceConstants.ACTION_START, context);
sReceivedBoot = true;
}
}
public void startVpnService (final Context context)
{
Intent intent = new Intent(context,VPNEnableActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
private void startService (String action, Context context)
{
Intent torService = new Intent(context, TorService.class);
torService.setAction(action);
context.startService(torService);
}
}

View File

@ -1,111 +0,0 @@
package org.torproject.android;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.Application;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.net.VpnService;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import android.widget.RemoteViews;
import org.torproject.android.service.OrbotConstants;
import org.torproject.android.service.TorEventHandler;
import org.torproject.android.service.TorService;
import org.torproject.android.service.util.Prefs;
import org.torproject.android.settings.Languages;
import java.util.Locale;
import java.util.Set;
public class OrbotApp extends Application implements OrbotConstants
{
private Locale locale;
@Override
public void onCreate() {
super.onCreate();
Prefs.setContext(this);
Languages.setup(OrbotMainActivity.class, R.string.menu_settings);
Languages.setLanguage(this, Prefs.getDefaultLocale(), true);
checkTransparentProxyingLegacy();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
Log.i(TAG, "onConfigurationChanged " + newConfig.locale.getLanguage());
Languages.setLanguage(this, Prefs.getDefaultLocale(), true);
}
public static void forceChangeLanguage(Activity activity) {
Intent intent = activity.getIntent();
if (intent == null) // when launched as LAUNCHER
intent = new Intent(activity, OrbotMainActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
activity.finish();
activity.overridePendingTransition(0, 0);
activity.startActivity(intent);
activity.overridePendingTransition(0, 0);
}
public static Languages getLanguages(Activity activity) {
return Languages.get(activity);
}
private void checkTransparentProxyingLegacy ()
{
if (Prefs.useTransparentProxying())
{
showToolbarNotification(getString(R.string.no_transproxy_warning_short),getString(R.string.no_transproxy_warning), 9999, org.torproject.android.service.R.drawable.ic_stat_notifyerr);
}
}
@SuppressLint("NewApi")
protected void showToolbarNotification (String shortMsg, String notifyMsg, int notifyId, int icon)
{
NotificationCompat.Builder notifyBuilder;
//Reusable code.
PackageManager pm = getPackageManager();
Intent intent = pm.getLaunchIntentForPackage(getPackageName());
PendingIntent pendIntent = PendingIntent.getActivity(this, 0, intent, 0);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notifyBuilder = new NotificationCompat.Builder(this)
.setContentTitle(getString(org.torproject.android.service.R.string.app_name));
notifyBuilder.setContentIntent(pendIntent);
notifyBuilder.setContentText(shortMsg);
notifyBuilder.setSmallIcon(icon);
notifyBuilder.setTicker(notifyMsg);
notifyBuilder.setOngoing(false);
notifyBuilder.setStyle(new NotificationCompat.BigTextStyle()
.bigText(notifyMsg).setBigContentTitle(getString(org.torproject.android.service.R.string.app_name)));
Notification notification = notifyBuilder.build();
notificationManager.notify(notifyId, notification);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,232 +0,0 @@
package org.torproject.android.settings;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ContextWrapper;
import android.content.Intent;
import android.content.res.AssetManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils;
import android.util.DisplayMetrics;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class Languages {
public static final String TAG = "Languages";
public static final Locale defaultLocale;
public static final Locale TIBETAN = new Locale("bo");
static final Locale localesToTest[] = {
Locale.ENGLISH, Locale.FRENCH, Locale.GERMAN,
Locale.ITALIAN, Locale.JAPANESE, Locale.KOREAN,
Locale.TRADITIONAL_CHINESE, Locale.SIMPLIFIED_CHINESE,
TIBETAN, new Locale("af"), new Locale("am"),
new Locale("ar"), new Locale("az"), new Locale("bg"),
new Locale("bn"), new Locale("ca"), new Locale("cs"),
new Locale("da"), new Locale("el"), new Locale("es"),
new Locale("et"), new Locale("eu"), new Locale("fa"),
new Locale("fi"), new Locale("gl"), new Locale("hi"),
new Locale("hr"), new Locale("hu"), new Locale("hy"),
new Locale("in"), new Locale("hy"), new Locale("in"),
new Locale("is"), new Locale("it"), new Locale("iw"),
new Locale("ka"), new Locale("kk"), new Locale("km"),
new Locale("kn"), new Locale("ky"), new Locale("lo"),
new Locale("lt"), new Locale("lv"), new Locale("mk"),
new Locale("ml"), new Locale("mn"), new Locale("mr"),
new Locale("ms"), new Locale("my"), new Locale("nb"),
new Locale("ne"), new Locale("nl"), new Locale("pl"),
new Locale("pt"), new Locale("rm"), new Locale("ro"),
new Locale("ru"), new Locale("si"), new Locale("sk"),
new Locale("sl"), new Locale("sn"), new Locale("sr"),
new Locale("sv"), new Locale("sw"), new Locale("ta"),
new Locale("te"), new Locale("th"), new Locale("tl"),
new Locale("tr"), new Locale("uk"), new Locale("ur"),
new Locale("uz"), new Locale("vi"), new Locale("zu"),
};
private static final String USE_SYSTEM_DEFAULT = "";
private static final String defaultString = "Use System Default";
private static Locale locale;
private static Languages singleton;
private static Class<?> clazz;
private static int resId;
private static Map<String, String> tmpMap = new TreeMap<String, String>();
private static Map<String, String> nameMap;
static {
defaultLocale = Locale.getDefault();
}
private Languages(Activity activity) {
AssetManager assets = activity.getAssets();
Configuration config = activity.getResources().getConfiguration();
// Resources() requires DisplayMetrics, but they are only needed for drawables
DisplayMetrics ignored = new DisplayMetrics();
activity.getWindowManager().getDefaultDisplay().getMetrics(ignored);
Resources resources;
Set<Locale> localeSet = new LinkedHashSet<Locale>();
for (Locale locale : localesToTest) {
config.locale = locale;
resources = new Resources(assets, ignored, config);
if (!TextUtils.equals(defaultString, resources.getString(resId))
|| locale.equals(Locale.ENGLISH))
localeSet.add(locale);
}
for (Locale locale : localeSet) {
if (locale.equals(TIBETAN)) {
// include English name for devices without Tibetan font support
tmpMap.put(TIBETAN.getLanguage(), "Tibetan བོད་སྐད།"); // Tibetan
} else if (locale.equals(Locale.SIMPLIFIED_CHINESE)) {
tmpMap.put(Locale.SIMPLIFIED_CHINESE.toString(), "中文 (中国)"); // Chinese (China)
} else if (locale.equals(Locale.TRADITIONAL_CHINESE)) {
tmpMap.put(Locale.TRADITIONAL_CHINESE.toString(), "中文 (台灣)"); // Chinese (Taiwan)
} else {
tmpMap.put(locale.getLanguage(), locale.getDisplayLanguage(locale));
}
}
/* USE_SYSTEM_DEFAULT is a fake one for displaying in a chooser menu. */
localeSet.add(null);
tmpMap.put(USE_SYSTEM_DEFAULT, activity.getString(resId));
nameMap = Collections.unmodifiableMap(tmpMap);
}
/**
* Get the instance of {@link Languages} to work with, providing the
* {@link Activity} that is will be working as part of, as well as the
* {@code resId} that has the exact string "Use System Default",
* i.e. {@code R.string.use_system_default}.
* <p/>
* That string resource {@code resId} is also used to find the supported
* translations: if an included translation has a translated string that
* matches that {@code resId}, then that language will be included as a
* supported language.
*
* @param clazz the {@link Class} of the default {@code Activity},
* usually the main {@code Activity} from where the
* Settings is launched from.
* @param resId the string resource ID to for the string "Use System Default",
* e.g. {@code R.string.use_system_default}
* @return
*/
public static void setup(Class<?> clazz, int resId) {
if (Languages.clazz == null) {
Languages.clazz = clazz;
Languages.resId = resId;
} else {
throw new RuntimeException("Languages singleton was already initialized, duplicate call to Languages.setup()!");
}
}
/**
* Get the singleton to work with.
*
* @param activity the {@link Activity} this is working as part of
* @return
*/
public static Languages get(Activity activity) {
if (singleton == null) {
singleton = new Languages(activity);
}
return singleton;
}
//@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR1)
@SuppressLint("NewApi")
public static void setLanguage(final ContextWrapper contextWrapper, String language, boolean refresh) {
if (locale != null && TextUtils.equals(locale.getLanguage(), language) && (!refresh)) {
return; // already configured
} else if (language == null || language == USE_SYSTEM_DEFAULT) {
locale = defaultLocale;
} else {
/* handle locales with the country in it, i.e. zh_CN, zh_TW, etc */
String localeSplit[] = language.split("_");
if (localeSplit.length > 1) {
locale = new Locale(localeSplit[0], localeSplit[1]);
} else {
locale = new Locale(language);
}
}
final Resources resources = contextWrapper.getBaseContext().getResources();
Configuration config = resources.getConfiguration();
if (Build.VERSION.SDK_INT >= 17) {
config.setLocale(locale);
} else {
config.locale = locale;
}
resources.updateConfiguration(config, resources.getDisplayMetrics());
Locale.setDefault(locale);
}
/**
* Force reload the {@link Activity to make language changes take effect.}
*
* @param activity the {@code Activity} to force reload
*/
public static void forceChangeLanguage(Activity activity) {
Intent intent = activity.getIntent();
if (intent == null) // when launched as LAUNCHER
return;
intent.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION);
activity.finish();
activity.overridePendingTransition(0, 0);
activity.startActivity(intent);
activity.overridePendingTransition(0, 0);
}
/**
* Return the name of the language based on the locale.
*
* @param locale
* @return
*/
public String getName(String locale) {
String ret = nameMap.get(locale);
// if no match, try to return a more general name (i.e. English for
// en_IN)
if (ret == null && locale.contains("_"))
ret = nameMap.get(locale.split("_")[0]);
return ret;
}
/**
* Return an array of the names of all the supported languages, sorted to
* match what is returned by {@link Languages#getSupportedLocales()}.
*
* @return
*/
public String[] getAllNames() {
return nameMap.values().toArray(new String[nameMap.size()]);
}
public int getPosition(Locale locale) {
String localeName = locale.getLanguage();
int i = 0;
for (String key : nameMap.keySet())
if (TextUtils.equals(key, localeName))
return i;
else
i++;
return -1;
}
/**
* Get sorted list of supported locales.
*
* @return
*/
public String[] getSupportedLocales() {
Set<String> keys = nameMap.keySet();
return keys.toArray(new String[keys.size()]);
}
}

View File

@ -1,74 +0,0 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.settings;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
import android.preference.PreferenceActivity;
import org.torproject.android.OrbotApp;
import org.torproject.android.R;
import org.torproject.android.service.util.TorServiceUtils;
import java.util.Locale;
public class SettingsPreferences
extends PreferenceActivity implements OnPreferenceClickListener {
private static final String TAG = "SettingsPreferences";
private ListPreference prefLocale = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.preferences);
getPreferenceManager().setSharedPreferencesMode(Context.MODE_MULTI_PROCESS);
SharedPreferences prefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
prefLocale = (ListPreference) findPreference("pref_default_locale");
prefLocale.setOnPreferenceClickListener(this);
Languages languages = Languages.get(this);
prefLocale.setEntries(languages.getAllNames());
prefLocale.setEntryValues(languages.getSupportedLocales());
prefLocale.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
String language = (String) newValue;
if (preference == prefLocale) {
SharedPreferences settings = TorServiceUtils
.getSharedPrefs(getApplicationContext());
String lang = settings.getString("pref_default_locale",
Locale.getDefault().getLanguage());
OrbotApp app = (OrbotApp) getApplication();
Languages.setLanguage(app, language, true);
lang = settings.getString("pref_default_locale",
Locale.getDefault().getLanguage());
OrbotApp.forceChangeLanguage(SettingsPreferences.this);
}
return false;
}
});
}
public boolean onPreferenceClick(Preference preference) {
setResult(RESULT_OK);
return true;
}
}

View File

@ -1,361 +0,0 @@
/* Copyright (c) 2009, Nathan Freitas, Orbot / The Guardian Project - http://openideals.com/guardian */
/* See LICENSE for licensing information */
package org.torproject.android.ui;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.StringTokenizer;
import org.torproject.android.service.OrbotConstants;
import org.torproject.android.R;
import org.torproject.android.service.util.TorServiceUtils;
import org.torproject.android.service.vpn.TorifiedApp;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.GridView;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.TextView;
public class AppManagerActivity extends AppCompatActivity implements OnClickListener, OrbotConstants {
private GridView listApps;
private ListAdapter adapterApps;
private final static String TAG = "Orbot";
PackageManager pMgr = null;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
pMgr = getPackageManager();
this.setContentView(R.layout.layout_apps);
setTitle(R.string.apps_mode);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (item.getItemId() == android.R.id.home)
{
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onResume() {
super.onResume();
listApps = (GridView) findViewById(R.id.applistview);
mPrefs = TorServiceUtils.getSharedPrefs(getApplicationContext());
new AsyncTask<Void, Void, Void>() {
private ProgressDialog dialog;
protected void onPreExecute() {
// Pre Code
dialog = new ProgressDialog(AppManagerActivity.this, android.support.v4.app.DialogFragment.STYLE_NO_TITLE);
dialog.show();
}
protected Void doInBackground(Void... unused) {
loadApps(mPrefs);
return null;
}
protected void onPostExecute(Void unused) {
listApps.setAdapter(adapterApps);
dialog.cancel();
}
}.execute();
}
SharedPreferences mPrefs = null;
ArrayList<TorifiedApp> mApps = null;
private void loadApps (SharedPreferences prefs)
{
mApps = getApps(getApplicationContext(), prefs);
Collections.sort(mApps,new Comparator<TorifiedApp>() {
public int compare(TorifiedApp o1, TorifiedApp o2) {
if (o1.isTorified() == o2.isTorified()) return o1.getName().compareTo(o2.getName());
if (o1.isTorified()) return -1;
return 1;
}
});
final LayoutInflater inflater = getLayoutInflater();
adapterApps = new ArrayAdapter<TorifiedApp>(this, R.layout.layout_apps_item, R.id.itemtext,mApps) {
public View getView(int position, View convertView, ViewGroup parent) {
ListEntry entry = null;
if (convertView == null)
convertView = inflater.inflate(R.layout.layout_apps_item, parent, false);
else
entry = (ListEntry) convertView.getTag();
if (entry == null) {
// Inflate a new view
entry = new ListEntry();
entry.icon = (ImageView) convertView.findViewById(R.id.itemicon);
entry.box = (CheckBox) convertView.findViewById(R.id.itemcheck);
entry.text = (TextView) convertView.findViewById(R.id.itemtext);
convertView.setTag(entry);
}
final TorifiedApp app = mApps.get(position);
if (entry.icon != null) {
try {
entry.icon.setImageDrawable(pMgr.getApplicationIcon(app.getPackageName()));
entry.icon.setOnClickListener(AppManagerActivity.this);
entry.icon.setTag(entry.box);
}
catch (Exception e)
{
e.printStackTrace();
}
}
if (entry.text != null) {
entry.text.setText(app.getName());
entry.text.setOnClickListener(AppManagerActivity.this);
entry.text.setTag(entry.box);
}
if (entry.box != null) {
entry.box.setOnClickListener(AppManagerActivity.this);
entry.box.setChecked(app.isTorified());
entry.box.setTag(app);
}
return convertView;
}
};
}
private static class ListEntry {
private CheckBox box;
private TextView text;
private ImageView icon;
}
/* (non-Javadoc)
* @see android.app.Activity#onStop()
*/
@Override
protected void onStop() {
super.onStop();
}
public ArrayList<TorifiedApp> getApps (Context context, SharedPreferences prefs)
{
String tordAppString = prefs.getString(PREFS_KEY_TORIFIED, "");
String[] tordApps;
StringTokenizer st = new StringTokenizer(tordAppString,"|");
tordApps = new String[st.countTokens()];
int tordIdx = 0;
while (st.hasMoreTokens())
{
tordApps[tordIdx++] = st.nextToken();
}
Arrays.sort(tordApps);
//else load the apps up
List<ApplicationInfo> lAppInfo = pMgr.getInstalledApplications(0);
Iterator<ApplicationInfo> itAppInfo = lAppInfo.iterator();
ArrayList<TorifiedApp> apps = new ArrayList<TorifiedApp>();
ApplicationInfo aInfo = null;
int appIdx = 0;
TorifiedApp app = null;
while (itAppInfo.hasNext())
{
aInfo = itAppInfo.next();
app = new TorifiedApp();
try {
PackageInfo pInfo = pMgr.getPackageInfo(aInfo.packageName, PackageManager.GET_PERMISSIONS);
if (pInfo != null && pInfo.requestedPermissions != null)
{
for (String permInfo:pInfo.requestedPermissions)
{
if (permInfo.equals("android.permission.INTERNET"))
{
app.setUsesInternet(true);
}
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
/**
if ((aInfo.flags & ApplicationInfo.FLAG_SYSTEM) == 1)
{
//System app
app.setUsesInternet(true);
}**/
try
{
app.setName(pMgr.getApplicationLabel(aInfo).toString());
}
catch (Exception e)
{
// no name
continue; //we only show apps with names
}
if (!app.usesInternet())
continue;
else
{
apps.add(app);
}
app.setEnabled(aInfo.enabled);
app.setUid(aInfo.uid);
app.setUsername(pMgr.getNameForUid(app.getUid()));
app.setProcname(aInfo.processName);
app.setPackageName(aInfo.packageName);
// check if this application is allowed
if (Arrays.binarySearch(tordApps, app.getUsername()) >= 0) {
app.setTorified(true);
}
else
{
app.setTorified(false);
}
appIdx++;
}
Collections.sort(apps);
return apps;
}
public void saveAppSettings (Context context)
{
StringBuilder tordApps = new StringBuilder();
Intent response = new Intent();
for (TorifiedApp tApp:mApps)
{
if (tApp.isTorified())
{
tordApps.append(tApp.getUsername());
tordApps.append("|");
response.putExtra(tApp.getUsername(),true);
}
}
Editor edit = mPrefs.edit();
edit.putString(PREFS_KEY_TORIFIED, tordApps.toString());
edit.commit();
setResult(RESULT_OK,response);
}
/**
* Called an application is check/unchecked
*/
/**
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final TorifiedApp app = (TorifiedApp) buttonView.getTag();
if (app != null) {
app.setTorified(isChecked);
}
saveAppSettings(this);
}**/
public void onClick(View v) {
CheckBox cbox = null;
if (v instanceof CheckBox)
cbox = (CheckBox)v;
else if (v.getTag() instanceof CheckBox)
cbox = (CheckBox)v.getTag();
if (cbox != null) {
final TorifiedApp app = (TorifiedApp) cbox.getTag();
if (app != null) {
app.setTorified(!app.isTorified());
cbox.setChecked(app.isTorified());
}
saveAppSettings(this);
}
}
}

View File

@ -1,5 +0,0 @@
package org.torproject.android.ui;
public class BridgeSetupActivity {
}

View File

@ -1,78 +0,0 @@
package org.torproject.android.ui;
import java.util.Random;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
public class ImageProgressView extends ImageView
{
private Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
private float progress = 0f; // 0 to 1
private RectF circle;
public ImageProgressView(Context context) {
super(context);
// TODO Auto-generated constructor stub
init();
}
public ImageProgressView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ImageProgressView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init();
}
private void init(){
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
paint.setAntiAlias(true);
paint.setStrokeWidth(20);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
MeasureSpec.getSize(heightMeasureSpec));
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (circle == null)
{
circle = new RectF(getWidth()/2,getHeight()/2+getHeight()/8, getWidth()/3,getHeight()/3);
}
float sweepAngle = 360f * progress;
canvas.drawArc(circle, 0, sweepAngle, true, paint);
}
}

View File

@ -1,328 +0,0 @@
package org.torproject.android.ui;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.torproject.android.R;
import org.torproject.android.service.util.TorResourceInstaller;
import org.torproject.android.service.TorServiceConstants;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.StatFs;
import android.text.format.Formatter;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;
public class OrbotDiagnosticsActivity extends Activity {
private TextView mTextView = null;
private final static String TAG = "OrbotDiag";
private StringBuffer log = new StringBuffer();
Process mProcess;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_diag);
mTextView = (TextView)findViewById(R.id.diaglog);
}
private String getFreeStorage ()
{
File path = Environment.getDataDirectory();
StatFs stat = new StatFs(path.getPath());
long blockSize = stat.getBlockSize();
long availableBlocks = stat.getAvailableBlocks();
return Formatter.formatFileSize(this, availableBlocks * blockSize);
}
@Override
protected void onPause() {
super.onPause();
stopTor();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private void stopTor ()
{
File appBinHome = this.getDir("bin", Context.MODE_PRIVATE);
File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY);
if (mProcess != null)
mProcess.destroy();
}
@Override
protected void onResume() {
super.onResume();
log("Hello, Orbot!");
try
{
log(android.os.Build.DEVICE);
log(android.os.Build.HARDWARE);
log(android.os.Build.MANUFACTURER);
log(android.os.Build.MODEL);
log(android.os.Build.VERSION.CODENAME);
log(android.os.Build.VERSION.RELEASE);
}
catch (Exception e)
{
log("error getting device info");
}
showFileTree ();
runTorTest();
}
private void runTorTest ()
{
try
{
File appBinHome = this.getDir("bin", Context.MODE_PRIVATE);
File appDataHome = this.getDir("data", Context.MODE_PRIVATE);
File fileTor= new File(appBinHome, TorServiceConstants.TOR_ASSET_KEY);
enableBinExec (fileTor, appBinHome);
InputStream is = getResources().openRawResource(R.raw.torrc);
File fileTorrc = new File(appBinHome, TorServiceConstants.TORRC_ASSET_KEY + "diag");
TorResourceInstaller.streamToFile(is,fileTorrc, false, false);
/**
ArrayList<String> alEnv = new ArrayList<String>();
alEnv.add("HOME=" + appBinHome.getAbsolutePath());
Shell shell = Shell.startShell(alEnv,appBinHome.getAbsolutePath());
SimpleCommand cmdTor = new SimpleCommand(fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath());
shell.add(cmdTor);
**/
String cmd = fileTor.getAbsolutePath() + " DataDirectory " + appDataHome.getAbsolutePath() + " -f " + fileTorrc.getAbsolutePath();
log ("Executing command> " + cmd);
mProcess = Runtime.getRuntime().exec(cmd);
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getInputStream()));
StreamGobbler sg = new StreamGobbler();
sg.reader = bufferedReader;
sg.process = mProcess;
new Thread(sg).start();
if (mProcess.getErrorStream() != null)
{
bufferedReader = new BufferedReader(new InputStreamReader(mProcess.getErrorStream()));
sg = new StreamGobbler();
sg.reader = bufferedReader;
sg.process = mProcess;
new Thread(sg).start();
}
}
catch (Exception e)
{
Log.d(TAG,"runTorTest exception",e);
}
}
class StreamGobbler implements Runnable
{
BufferedReader reader;
Process process;
public void run ()
{
String line = null;
try {
while ( (line = reader.readLine()) != null)
{
Message msg = mHandler.obtainMessage(0);
msg.getData().putString("log", line);
mHandler.sendMessage(msg);
}
} catch (IOException e) {
Log.d(TAG, "error reading line",e);
}
//log("Tor exit code=" + process.exitValue() + ";");
}
}
private boolean enableBinExec (File fileBin, File appBinHome) throws Exception
{
log(fileBin.getName() + ": PRE: Is binary exec? " + fileBin.canExecute());
if (!fileBin.canExecute())
{
log("(re)Setting permission on binary: " + fileBin.getAbsolutePath());
Runtime.getRuntime().exec("chmod " + TorServiceConstants.CHMOD_EXE_VALUE + ' ' + fileBin.getAbsolutePath()).waitFor();
File fileTest = new File(fileBin.getAbsolutePath());
log(fileTest.getName() + ": POST: Is binary exec? " + fileTest.canExecute());
}
return fileBin.canExecute();
}
private void showFileTree ()
{
File fileDir = this.getDir("bin", Context.MODE_PRIVATE);
if (fileDir.exists())
{
log("checking file tree: " + fileDir.getAbsolutePath());
printDir (fileDir.getName(), fileDir);
}
else
{
log("app_bin does not exist");
}
fileDir = this.getDir("data", Context.MODE_PRIVATE);
if (fileDir.exists())
{
log("checking file tree: " + fileDir.getAbsolutePath());
printDir (fileDir.getName(), fileDir);
}
else
{
log ("app_data does not exist");
}
}
private void printDir (String path, File fileDir)
{
File[] files = fileDir.listFiles();
if (files != null && files.length > 0)
{
for (File file : files)
{
try
{
if (file.isDirectory())
{
printDir(path + '/' + file.getName(), file);
}
else
{
log(path + '/' + file.getName() + " len:" + file.length() + " exec:" + file.canExecute());
}
}
catch (Exception e)
{
log("problem printing out file information");
}
}
}
}
Handler mHandler = new Handler ()
{
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
String logMsg = msg.getData().getString("log");
log(logMsg);
}
};
private void log (String msg)
{
Log.d(TAG, msg);
mTextView.append(msg + '\n');
log.append(msg + '\n');
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu resource file.
getMenuInflater().inflate(R.menu.share_menu, menu);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.menu_item_share);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.menu_item_share:
sendLog();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void sendLog ()
{
int maxLength = 5000;
String logShare = null;
if (log.length() > maxLength)
logShare = log.substring(0, maxLength);
else
logShare = log.toString();
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, logShare);
sendIntent.setType("text/plain");
startActivity(sendIntent);
}
}

View File

@ -1,216 +0,0 @@
package org.torproject.android.ui;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import org.torproject.android.service.OrbotConstants;
import org.torproject.android.R;
import org.torproject.android.service.TorServiceConstants;
import java.util.List;
public class PromoAppsActivity extends Activity implements OrbotConstants {
final static String MARKET_URI = "market://details?id=";
final static String FDROID_APP_URI = "https://f-droid.org/repository/browse/?fdid=";
final static String PLAY_APP_URI = "https://play.google.com/store/apps/details?id=";
final static String FDROID_URI = "https://f-droid.org/repository/browse/?fdfilter=info.guardianproject";
final static String PLAY_URI = "https://play.google.com/store/apps/developer?id=The+Guardian+Project";
private final static String FDROID_PACKAGE_NAME = "org.fdroid.fdroid";
private final static String PLAY_PACKAGE_NAME = "com.android.vending";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
}
@Override
protected void onStart() {
super.onStart();
setContentView(R.layout.layout_promo_apps);
stepFive();
}
@Override
protected void onResume() {
super.onResume();
}
void stepFive(){
String title = getString(R.string.wizard_tips_title);
setTitle(title);
Button btnLink = (Button)findViewById(R.id.WizardRootButtonInstallGibberbot);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
startActivity(getInstallIntent("info.guardianproject.otr.app.im",PromoAppsActivity.this));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonInstallOrweb);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
startActivity(getInstallIntent(TorServiceConstants.BROWSER_APP_USERNAME,PromoAppsActivity.this));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonInstallDuckgo);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
startActivity(getInstallIntent("com.duckduckgo.mobile.android",PromoAppsActivity.this));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonInstallTwitter);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
String url = getString(R.string.twitter_setup_url);
finish();
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonInstallStoryMaker);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
startActivity(getInstallIntent("info.guardianproject.mrapp",PromoAppsActivity.this));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonInstallMartus);
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
finish();
startActivity(getInstallIntent("org.martus.android",PromoAppsActivity.this));
}
});
btnLink = (Button)findViewById(R.id.WizardRootButtonGooglePlay);
PackageManager pm = getPackageManager();
final Intent intent = new Intent(Intent.ACTION_VIEW);
// change text and icon based on which app store is installed (or not)
try {
if (isAppInstalled(pm, FDROID_PACKAGE_NAME)) {
Drawable icon = pm.getApplicationIcon(FDROID_PACKAGE_NAME);
btnLink.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
btnLink.setText(R.string.wizard_tips_fdroid);
intent.setPackage(FDROID_PACKAGE_NAME);
intent.setData(Uri.parse(FDROID_URI));
} else if (isAppInstalled(pm, PLAY_PACKAGE_NAME)) {
Drawable icon = pm.getApplicationIcon(PLAY_PACKAGE_NAME);
btnLink.setCompoundDrawablesWithIntrinsicBounds(icon, null, null, null);
btnLink.setText(R.string.wizard_tips_play);
intent.setPackage(PLAY_PACKAGE_NAME);
intent.setData(Uri.parse(PLAY_URI));
}
} catch (NameNotFoundException e) {
e.printStackTrace();
btnLink.setText(R.string.wizard_tips_fdroid_org);
intent.setData(Uri.parse(FDROID_URI));
}
btnLink.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View view) {
startActivity(intent);
}
});
Button next = ((Button)findViewById(R.id.btnWizard2));
next.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
finish();
}
});
}
public static boolean isAppInstalled(PackageManager pm, String packageName) {
try {
pm.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES);
return true;
} catch (PackageManager.NameNotFoundException e) {
return false;
}
}
public static Intent getInstallIntent(String packageName, Context context) {
final Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setData(Uri.parse(MARKET_URI + packageName));
PackageManager pm = context.getPackageManager();
List<ResolveInfo> resInfos = pm.queryIntentActivities(intent, 0);
String foundPackageName = null;
for (ResolveInfo r : resInfos) {
Log.i(TAG, "market: " + r.activityInfo.packageName);
if (TextUtils.equals(r.activityInfo.packageName, FDROID_PACKAGE_NAME)
|| TextUtils.equals(r.activityInfo.packageName, PLAY_PACKAGE_NAME)) {
foundPackageName = r.activityInfo.packageName;
break;
}
}
if (foundPackageName == null) {
intent.setData(Uri.parse(FDROID_APP_URI + packageName));
} else {
intent.setPackage(foundPackageName);
}
return intent;
}
}

View File

@ -1,76 +0,0 @@
package org.torproject.android.ui;
import android.graphics.Camera;
import android.graphics.Matrix;
import android.view.animation.Animation;
import android.view.animation.Transformation;
/**
* An animation that rotates the view on the Y axis between two specified angles.
* This animation also adds a translation on the Z axis (depth) to improve the effect.
*/
public class Rotate3dAnimation extends Animation {
private final float mFromDegrees;
private final float mToDegrees;
private final float mCenterX;
private final float mCenterY;
private final float mDepthZ;
private final boolean mReverse;
private Camera mCamera;
/**
* Creates a new 3D rotation on the Y axis. The rotation is defined by its
* start angle and its end angle. Both angles are in degrees. The rotation
* is performed around a center point on the 2D space, definied by a pair
* of X and Y coordinates, called centerX and centerY. When the animation
* starts, a translation on the Z axis (depth) is performed. The length
* of the translation can be specified, as well as whether the translation
* should be reversed in time.
*
* @param fromDegrees the start angle of the 3D rotation
* @param toDegrees the end angle of the 3D rotation
* @param centerX the X center of the 3D rotation
* @param centerY the Y center of the 3D rotation
* @param reverse true if the translation should be reversed, false otherwise
*/
public Rotate3dAnimation(float fromDegrees, float toDegrees,
float centerX, float centerY, float depthZ, boolean reverse) {
mFromDegrees = fromDegrees;
mToDegrees = toDegrees;
mCenterX = centerX;
mCenterY = centerY;
mDepthZ = depthZ;
mReverse = reverse;
}
@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
super.initialize(width, height, parentWidth, parentHeight);
mCamera = new Camera();
}
@Override
protected void applyTransformation(float interpolatedTime, Transformation t) {
final float fromDegrees = mFromDegrees;
float degrees = fromDegrees + ((mToDegrees - fromDegrees) * interpolatedTime);
final float centerX = mCenterX;
final float centerY = mCenterY;
final Camera camera = mCamera;
final Matrix matrix = t.getMatrix();
camera.save();
if (mReverse) {
camera.translate(0.0f, 0.0f, mDepthZ * interpolatedTime);
} else {
camera.translate(0.0f, 0.0f, mDepthZ * (1.0f - interpolatedTime));
}
camera.rotateY(degrees);
camera.getMatrix(matrix);
camera.restore();
matrix.preTranslate(-centerX, -centerY);
matrix.postTranslate(centerX, centerY);
}
}

View File

@ -1,5 +0,0 @@
package org.torproject.android.ui;
public class VPNSetupActivity {
}

View File

@ -1,199 +0,0 @@
package org.torproject.android.ui.hiddenservices;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import org.json.JSONException;
import org.json.JSONObject;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.adapters.ClientCookiesAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.AddCookieDialog;
import org.torproject.android.ui.hiddenservices.dialogs.CookieActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectCookieBackupDialog;
import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class ClientCookiesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR = 3;
private ContentResolver mResolver;
private ClientCookiesAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_activity_client_cookies);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mResolver = getContentResolver();
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
AddCookieDialog dialog = new AddCookieDialog();
dialog.show(getSupportFragmentManager(), "AddCookieDialog");
}
});
mAdapter = new ClientCookiesAdapter(
this,
mResolver.query(CookieContentProvider.CONTENT_URI, CookieContentProvider.PROJECTION, null, null, null)
, 0);
mResolver.registerContentObserver(
CookieContentProvider.CONTENT_URI, true, new HSObserver(new Handler())
);
ListView cookies = (ListView) findViewById(R.id.clien_cookies_list);
cookies.setAdapter(mAdapter);
cookies.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor item = (Cursor) parent.getItemAtPosition(position);
Bundle arguments = new Bundle();
arguments.putInt(
"_id", item.getInt(item.getColumnIndex(CookieContentProvider.ClientCookie._ID))
);
arguments.putString(
"domain", item.getString(item.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN))
);
arguments.putString(
"auth_cookie_value", item.getString(item.getColumnIndex(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE))
);
arguments.putInt(
"enabled", item.getInt(item.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED))
);
CookieActionsDialog dialog = new CookieActionsDialog();
dialog.setArguments(arguments);
dialog.show(getSupportFragmentManager(), "CookieActionsDialog");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.cookie_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.cookie_restore_backup) {
if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) {
PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR);
return true;
}
SelectCookieBackupDialog dialog = new SelectCookieBackupDialog();
dialog.show(getSupportFragmentManager(), "SelectCookieBackupDialog");
} else if (id == R.id.cookie_from_qr) {
IntentIntegrator integrator = new IntentIntegrator(ClientCookiesActivity.this);
integrator.initiateScan();
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (grantResults.length < 1
|| grantResults[0] != PackageManager.PERMISSION_GRANTED) {
return;
}
switch (requestCode) {
case WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTIONBAR: {
SelectCookieBackupDialog dialog = new SelectCookieBackupDialog();
dialog.show(getSupportFragmentManager(), "SelectCookieBackupDialog");
break;
}
case CookieActionsDialog.WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG: {
Toast.makeText(this, R.string.click_again_for_backup, Toast.LENGTH_LONG).show();
break;
}
}
}
@Override
protected void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
IntentResult scanResult = IntentIntegrator.parseActivityResult(request, response, data);
if (scanResult == null) return;
String results = scanResult.getContents();
if (results == null || results.length() < 1) return;
try {
JSONObject savedValues = new JSONObject(results);
ContentValues fields = new ContentValues();
fields.put(
CookieContentProvider.ClientCookie.DOMAIN,
savedValues.getString(CookieContentProvider.ClientCookie.DOMAIN)
);
fields.put(
CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE,
savedValues.getString(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE)
);
mResolver.insert(CookieContentProvider.CONTENT_URI, fields);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(this, R.string.error, Toast.LENGTH_LONG).show();
}
}
class HSObserver extends ContentObserver {
HSObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
mAdapter.changeCursor(mResolver.query(
CookieContentProvider.CONTENT_URI, CookieContentProvider.PROJECTION, null, null, null
));
}
}
}

View File

@ -1,214 +0,0 @@
package org.torproject.android.ui.hiddenservices;
import android.content.ContentResolver;
import android.content.pm.PackageManager;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
import android.support.v4.view.MenuItemCompat;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.adapters.OnionListAdapter;
import org.torproject.android.ui.hiddenservices.dialogs.HSActionsDialog;
import org.torproject.android.ui.hiddenservices.dialogs.HSDataDialog;
import org.torproject.android.ui.hiddenservices.dialogs.SelectHSBackupDialog;
import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
public class HiddenServicesActivity extends AppCompatActivity {
public final int WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR = 1;
private ContentResolver mResolver;
private OnionListAdapter mAdapter;
private FloatingActionButton fab;
private String mWhere = HSContentProvider.HiddenService.CREATED_BY_USER + "=1";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_hs_list_view);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mResolver = getContentResolver();
fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
HSDataDialog dialog = new HSDataDialog();
dialog.show(getSupportFragmentManager(), "HSDataDialog");
}
});
mAdapter = new OnionListAdapter(
this,
mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null
),
0
);
mResolver.registerContentObserver(
HSContentProvider.CONTENT_URI, true, new HSObserver(new Handler())
);
ListView onion_list = (ListView) findViewById(R.id.onion_list);
onion_list.setAdapter(mAdapter);
onion_list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Cursor item = (Cursor) parent.getItemAtPosition(position);
Bundle arguments = new Bundle();
arguments.putInt(
"_id", item.getInt(item.getColumnIndex(HSContentProvider.HiddenService._ID))
);
arguments.putString(
"port", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.PORT))
);
arguments.putString(
"onion", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
);
arguments.putInt(
"auth_cookie", item.getInt(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
);
arguments.putString(
"auth_cookie_value", item.getString(item.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
);
HSActionsDialog dialog = new HSActionsDialog();
dialog.setArguments(arguments);
dialog.show(getSupportFragmentManager(), "HSActionsDialog");
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.hs_menu, menu);
MenuItem item = menu.findItem(R.id.hs_type);
Spinner spinner = (Spinner) MenuItemCompat.getActionView(item);
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
this, R.array.array_hs_types, android.R.layout.simple_spinner_item);
adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> arg0, View v, int pos, long id) {
if (pos == 0) {
mWhere = HSContentProvider.HiddenService.CREATED_BY_USER + "=1";
fab.show();
} else {
mWhere = HSContentProvider.HiddenService.CREATED_BY_USER + "=0";
fab.hide();
}
mAdapter.changeCursor(mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null
));
}
@Override
public void onNothingSelected(AdapterView<?> arg0) {
// Do nothing
}
});
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.menu_restore_backup) {
if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(this)) {
PermissionManager.requestExternalWritePermissions(this, WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR);
return true;
}
SelectHSBackupDialog dialog = new SelectHSBackupDialog();
dialog.show(getSupportFragmentManager(), "SelectHSBackupDialog");
}
return super.onOptionsItemSelected(item);
}
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
if (grantResults.length < 1
|| grantResults[0] != PackageManager.PERMISSION_GRANTED) {
return;
}
switch (requestCode) {
case WRITE_EXTERNAL_STORAGE_FROM_ACTIONBAR: {
SelectHSBackupDialog dialog = new SelectHSBackupDialog();
dialog.show(getSupportFragmentManager(), "SelectHSBackupDialog");
break;
}
case HSActionsDialog.WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG: {
Toast.makeText(this, R.string.click_again_for_backup, Toast.LENGTH_LONG).show();
break;
}
}
}
class HSObserver extends ContentObserver {
HSObserver(Handler handler) {
super(handler);
}
@Override
public void onChange(boolean selfChange) {
mAdapter.changeCursor(mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, mWhere, null, null
));
if (PermissionManager.isLollipopOrHigher()) {
Cursor active = mResolver.query(
HSContentProvider.CONTENT_URI, HSContentProvider.PROJECTION, HSContentProvider.HiddenService.ENABLED + "=1", null, null
);
if (active == null) return;
if (active.getCount() > 0) // Call only if there running services
PermissionManager.requestBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext());
else // Drop whe not needed
PermissionManager.requestDropBatteryPermmssions(HiddenServicesActivity.this, getApplicationContext());
active.close();
}
}
}
}

View File

@ -1,50 +0,0 @@
package org.torproject.android.ui.hiddenservices.adapters;
import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import org.torproject.android.R;
import java.io.File;
import java.util.List;
public class BackupAdapter extends ArrayAdapter<File> {
private int mResource;
public BackupAdapter(Context context, int resource) {
super(context, resource);
mResource = resource;
}
public BackupAdapter(Context context, int resource, List<File> zips) {
super(context, resource, zips);
mResource = resource;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi;
vi = LayoutInflater.from(getContext());
v = vi.inflate(mResource, null);
}
File p = getItem(position);
if (p != null) {
TextView name = (TextView) v.findViewById(R.id.backup_name);
if (name != null)
name.setText(p.getName());
}
return v;
}
}

View File

@ -1,64 +0,0 @@
package org.torproject.android.ui.hiddenservices.adapters;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class ClientCookiesAdapter extends CursorAdapter {
private LayoutInflater cursorInflater;
public ClientCookiesAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
cursorInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final Context mContext = context;
int id = cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie._ID));
final String where = CookieContentProvider.ClientCookie._ID + "=" + id;
TextView domain = (TextView) view.findViewById(R.id.cookie_onion);
domain.setText(cursor.getString(cursor.getColumnIndex(CookieContentProvider.ClientCookie.DOMAIN)));
Switch enabled = (Switch) view.findViewById(R.id.cookie_switch);
enabled.setChecked(
cursor.getInt(cursor.getColumnIndex(CookieContentProvider.ClientCookie.ENABLED)) == 1
);
enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ContentResolver resolver = mContext.getContentResolver();
ContentValues fields = new ContentValues();
fields.put(CookieContentProvider.ClientCookie.ENABLED, isChecked);
resolver.update(
CookieContentProvider.CONTENT_URI, fields, where, null
);
Toast.makeText(
mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
}
});
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return cursorInflater.inflate(R.layout.layout_client_cookie_list_item, parent, false);
}
}

View File

@ -1,68 +0,0 @@
package org.torproject.android.ui.hiddenservices.adapters;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.support.v4.widget.CursorAdapter;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
public class OnionListAdapter extends CursorAdapter {
private LayoutInflater cursorInflater;
public OnionListAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
cursorInflater = (LayoutInflater) context.getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void bindView(View view, Context context, Cursor cursor) {
final Context mContext = context;
int id = cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService._ID));
final String where = HSContentProvider.HiddenService._ID + "=" + id;
TextView port = (TextView) view.findViewById(R.id.hs_port);
port.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.PORT)));
TextView name = (TextView) view.findViewById(R.id.hs_name);
name.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.NAME)));
TextView domain = (TextView) view.findViewById(R.id.hs_onion);
domain.setText(cursor.getString(cursor.getColumnIndex(HSContentProvider.HiddenService.DOMAIN)));
Switch enabled = (Switch) view.findViewById(R.id.hs_switch);
enabled.setChecked(
cursor.getInt(cursor.getColumnIndex(HSContentProvider.HiddenService.ENABLED)) == 1
);
enabled.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ContentResolver resolver = mContext.getContentResolver();
ContentValues fields = new ContentValues();
fields.put(HSContentProvider.HiddenService.ENABLED, isChecked);
resolver.update(
HSContentProvider.CONTENT_URI, fields, where, null
);
Toast.makeText(
mContext, R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
}
});
}
@Override
public View newView(Context context, Cursor cursor, ViewGroup parent) {
return cursorInflater.inflate(R.layout.layout_hs_list_item, parent, false);
}
}

View File

@ -1,336 +0,0 @@
package org.torproject.android.ui.hiddenservices.backup;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.ParcelFileDescriptor;
import android.widget.Toast;
import org.json.JSONException;
import org.json.JSONObject;
import org.torproject.android.R;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
public class BackupUtils {
private final String configFileName = "config.json";
private Context mContext;
private ContentResolver mResolver;
public BackupUtils(Context context) {
mContext = context;
mResolver = mContext.getContentResolver();
}
public String createZipBackup(Integer port) {
File mHSBasePath = new File(
mContext.getFilesDir().getAbsolutePath(),
TorServiceConstants.HIDDEN_SERVICES_DIR
);
String configFilePath = mHSBasePath + "/hs" + port + "/" + configFileName;
String hostnameFilePath = mHSBasePath + "/hs" + port + "/hostname";
String keyFilePath = mHSBasePath + "/hs" + port + "/private_key";
File storage_path = ExternalStorage.getOrCreateBackupDir();
if (storage_path == null)
return null;
Cursor portData = mResolver.query(
HSContentProvider.CONTENT_URI,
HSContentProvider.PROJECTION,
HSContentProvider.HiddenService.PORT + "=" + port,
null,
null
);
JSONObject config = new JSONObject();
try {
if (portData == null || portData.getCount() != 1)
return null;
portData.moveToNext();
config.put(
HSContentProvider.HiddenService.NAME,
portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.NAME))
);
config.put(
HSContentProvider.HiddenService.PORT,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.PORT))
);
config.put(
HSContentProvider.HiddenService.ONION_PORT,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.ONION_PORT))
);
config.put(
HSContentProvider.HiddenService.DOMAIN,
portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.DOMAIN))
);
config.put(
HSContentProvider.HiddenService.AUTH_COOKIE,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE))
);
config.put(
HSContentProvider.HiddenService.AUTH_COOKIE_VALUE,
portData.getString(portData.getColumnIndex(HSContentProvider.HiddenService.AUTH_COOKIE_VALUE))
);
config.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.CREATED_BY_USER))
);
config.put(
HSContentProvider.HiddenService.ENABLED,
portData.getInt(portData.getColumnIndex(HSContentProvider.HiddenService.ENABLED))
);
} catch (JSONException e) {
e.printStackTrace();
return null;
} catch (NullPointerException e) {
e.printStackTrace();
return null;
}
portData.close();
try {
FileWriter file = new FileWriter(configFilePath);
file.write(config.toString());
file.close();
} catch (IOException e) {
e.printStackTrace();
return null;
}
String zip_path = storage_path.getAbsolutePath() + "/hs" + port + ".zip";
String files[] = {hostnameFilePath, keyFilePath, configFilePath};
ZipIt zip = new ZipIt(files, zip_path);
if (!zip.zip())
return null;
return zip_path;
}
public void restoreZipBackup(File backup) {
File mHSBasePath = new File(
mContext.getFilesDir().getAbsolutePath(),
TorServiceConstants.HIDDEN_SERVICES_DIR
);
int port;
Cursor service;
String backupName = backup.getName();
String hsDir = backupName.substring(0, backupName.lastIndexOf('.'));
String configFilePath = mHSBasePath + "/" + hsDir + "/" + configFileName;
String jString = null;
File hsPath = new File(mHSBasePath.getAbsolutePath(), hsDir);
if (!hsPath.isDirectory())
hsPath.mkdirs();
ZipIt zip = new ZipIt(null, backup.getAbsolutePath());
zip.unzip(hsPath.getAbsolutePath());
File config = new File(configFilePath);
FileInputStream stream;
try {
stream = new FileInputStream(config);
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
jString = Charset.defaultCharset().decode(bb).toString();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
if (jString == null)
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
try {
JSONObject savedValues = new JSONObject(jString);
ContentValues fields = new ContentValues();
fields.put(
HSContentProvider.HiddenService.NAME,
savedValues.getString(HSContentProvider.HiddenService.NAME)
);
fields.put(
HSContentProvider.HiddenService.ONION_PORT,
savedValues.getInt(HSContentProvider.HiddenService.ONION_PORT)
);
fields.put(
HSContentProvider.HiddenService.DOMAIN,
savedValues.getString(HSContentProvider.HiddenService.DOMAIN)
);
fields.put(
HSContentProvider.HiddenService.AUTH_COOKIE,
savedValues.getInt(HSContentProvider.HiddenService.AUTH_COOKIE)
);
fields.put(
HSContentProvider.HiddenService.CREATED_BY_USER,
savedValues.getInt(HSContentProvider.HiddenService.CREATED_BY_USER)
);
fields.put(
HSContentProvider.HiddenService.ENABLED,
savedValues.getInt(HSContentProvider.HiddenService.ENABLED)
);
port = savedValues.getInt(HSContentProvider.HiddenService.PORT);
fields.put(HSContentProvider.HiddenService.PORT, port);
service = mResolver.query(
HSContentProvider.CONTENT_URI,
HSContentProvider.PROJECTION,
HSContentProvider.HiddenService.PORT + "=" + port,
null,
null
);
if (service == null || service.getCount() == 0) {
mResolver.insert(HSContentProvider.CONTENT_URI, fields);
} else {
mResolver.update(
HSContentProvider.CONTENT_URI,
fields,
HSContentProvider.HiddenService.PORT + "=" + port,
null
);
service.close();
}
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
}
Toast.makeText(mContext, R.string.backup_restored, Toast.LENGTH_LONG).show();
}
public void restoreKeyBackup(int hsPort, Uri hsKeyPath) {
File mHSBasePath = new File(
mContext.getFilesDir().getAbsolutePath(),
TorServiceConstants.HIDDEN_SERVICES_DIR
);
File serviceDir = new File(mHSBasePath, "hs" + hsPort);
if (!serviceDir.isDirectory())
serviceDir.mkdirs();
try {
ParcelFileDescriptor mInputPFD = mContext.getContentResolver().openFileDescriptor(hsKeyPath, "r");
InputStream fileStream = new FileInputStream(mInputPFD.getFileDescriptor());
OutputStream file = new FileOutputStream(serviceDir.getAbsolutePath() + "/private_key");
byte[] buffer = new byte[1024];
int length;
while ((length = fileStream.read(buffer)) > 0) {
file.write(buffer, 0, length);
}
file.close();
} catch (IOException | NullPointerException e) {
e.printStackTrace();
}
}
public void restoreCookieBackup(File p) {
File config = new File(p.getAbsolutePath());
FileInputStream stream;
String jString = null;
try {
stream = new FileInputStream(config);
FileChannel fc = stream.getChannel();
MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
jString = Charset.defaultCharset().decode(bb).toString();
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
if (jString == null)
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
try {
JSONObject savedValues = new JSONObject(jString);
ContentValues fields = new ContentValues();
fields.put(
CookieContentProvider.ClientCookie.DOMAIN,
savedValues.getString(CookieContentProvider.ClientCookie.DOMAIN)
);
fields.put(
CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE,
savedValues.getString(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE)
);
fields.put(
CookieContentProvider.ClientCookie.ENABLED,
savedValues.getInt(CookieContentProvider.ClientCookie.ENABLED)
);
mResolver.insert(CookieContentProvider.CONTENT_URI, fields);
} catch (JSONException e) {
e.printStackTrace();
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
}
Toast.makeText(mContext, R.string.backup_restored, Toast.LENGTH_LONG).show();
}
public String createCookieBackup(String domain, String cookie, Integer enabled) {
File storage_path = ExternalStorage.getOrCreateBackupDir();
String backupFile = storage_path.getAbsolutePath() + '/' + domain.replace(".onion", ".json");
JSONObject backup = new JSONObject();
try {
backup.put(CookieContentProvider.ClientCookie.DOMAIN, domain);
backup.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, cookie);
backup.put(CookieContentProvider.ClientCookie.ENABLED, enabled);
FileWriter file = new FileWriter(backupFile);
file.write(backup.toString());
file.close();
} catch (JSONException | IOException e) {
e.printStackTrace();
return null;
}
return backupFile;
}
}

View File

@ -1,101 +0,0 @@
package org.torproject.android.ui.hiddenservices.backup;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class ZipIt {
private static final int BUFFER = 2048;
private String[] _files;
private String _zipFile;
public ZipIt(@Nullable String[] files, @NonNull String zipFile) {
_files = files;
_zipFile = zipFile;
}
public boolean zip() {
try {
BufferedInputStream origin;
FileOutputStream dest = new FileOutputStream(_zipFile);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
for (String _file : _files) {
FileInputStream fi = new FileInputStream(_file);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_file.substring(_file.lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch (Exception e) {
return false;
}
return true;
}
public boolean unzip(String output_path) {
InputStream is;
ZipInputStream zis;
try {
String filename;
is = new FileInputStream(_zipFile);
zis = new ZipInputStream(new BufferedInputStream(is));
ZipEntry ze;
byte[] buffer = new byte[1024];
int count;
while ((ze = zis.getNextEntry()) != null) {
// zapis do souboru
filename = ze.getName();
// Need to create directories if not exists, or
// it will generate an Exception...
if (ze.isDirectory()) {
File fmd = new File(output_path + "/" + filename);
fmd.mkdirs();
continue;
}
FileOutputStream fout = new FileOutputStream(output_path + "/" + filename);
// cteni zipu a zapis
while ((count = zis.read(buffer)) != -1) {
fout.write(buffer, 0, count);
}
fout.close();
zis.closeEntry();
}
zis.close();
} catch (IOException e) {
e.printStackTrace();
return false;
}
return true;
}
}

View File

@ -1,47 +0,0 @@
package org.torproject.android.ui.hiddenservices.database;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class HSDatabase extends SQLiteOpenHelper {
public static final String HS_DATA_TABLE_NAME = "hs_data";
public static final String HS_CLIENT_COOKIE_TABLE_NAME = "hs_client_cookie";
private static final int DATABASE_VERSION = 2;
private static final String DATABASE_NAME = "hidden_services";
private static final String HS_DATA_TABLE_CREATE =
"CREATE TABLE " + HS_DATA_TABLE_NAME + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"name TEXT, " +
"domain TEXT, " +
"onion_port INTEGER, " +
"auth_cookie INTEGER DEFAULT 0, " +
"auth_cookie_value TEXT, " +
"created_by_user INTEGER DEFAULT 0, " +
"enabled INTEGER DEFAULT 1, " +
"port INTEGER);";
private static final String HS_CLIENT_COOKIE_TABLE_CREATE =
"CREATE TABLE " + HS_CLIENT_COOKIE_TABLE_NAME + " (" +
"_id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"domain TEXT, " +
"auth_cookie_value TEXT, " +
"enabled INTEGER DEFAULT 1);";
public HSDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(HS_DATA_TABLE_CREATE);
db.execSQL(HS_CLIENT_COOKIE_TABLE_CREATE);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}

View File

@ -1,84 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class AddCookieDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_add_client_cookie_dialog, null);
final AlertDialog addCookieDialog = new AlertDialog.Builder(getActivity())
.setView(dialog_view)
.setTitle(R.string.client_cookies)
.create();
Button save = (Button) dialog_view.findViewById(R.id.cookie_dialog_save);
save.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String onion = ((EditText) dialog_view.findViewById(R.id.cookie_onion)).getText().toString();
String cookie = ((EditText) dialog_view.findViewById(R.id.cookie_value)).getText().toString();
if (checkInput(onion, cookie)) {
saveData(onion, cookie);
Toast.makeText(
v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
addCookieDialog.dismiss();
}
}
});
Button cancel = (Button) dialog_view.findViewById(R.id.cookie_dialog_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
addCookieDialog.cancel();
}
});
return addCookieDialog;
}
private boolean checkInput(String onion, String cookie) {
boolean is_set = ((onion != null && onion.length() > 0) && (cookie != null && cookie.length() > 0));
if (!is_set) {
Toast.makeText(getContext(), R.string.fields_can_t_be_empty, Toast.LENGTH_SHORT).show();
return false;
}
if (!onion.matches("([a-z0-9]{16})\\.onion")) {
Toast.makeText(getContext(), R.string.invalid_onion_address, Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
private void saveData(String domain, String cookie) {
ContentValues fields = new ContentValues();
fields.put(CookieContentProvider.ClientCookie.DOMAIN, domain);
fields.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, cookie);
ContentResolver cr = getContext().getContentResolver();
cr.insert(CookieContentProvider.CONTENT_URI, fields);
}
}

View File

@ -1,95 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class CookieActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG = 4;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_cookie_actions, null);
final AlertDialog actionDialog = new AlertDialog.Builder(getActivity())
.setView(dialog_view)
.setTitle(R.string.client_cookies)
.create();
Button backup = (Button) dialog_view.findViewById(R.id.btn_cookie_backup);
backup.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context mContext = v.getContext();
if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) {
PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_COOKIE_ACTION_DIALOG);
return;
}
BackupUtils backup_utils = new BackupUtils(mContext);
String backupPath = backup_utils.createCookieBackup(
arguments.getString("domain"),
arguments.getString("auth_cookie_value"),
arguments.getInt("enabled")
);
if (backupPath == null || backupPath.length() < 1) {
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
actionDialog.dismiss();
return;
}
Toast.makeText(mContext, R.string.backup_saved_at_external_storage, Toast.LENGTH_LONG).show();
Uri selectedUri = Uri.parse(backupPath.substring(0, backupPath.lastIndexOf("/")));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(selectedUri, "resource/folder");
if (intent.resolveActivityInfo(mContext.getPackageManager(), 0) != null) {
startActivity(intent);
} else {
Toast.makeText(mContext, R.string.filemanager_not_available, Toast.LENGTH_LONG).show();
}
actionDialog.dismiss();
}
});
Button delete = (Button) dialog_view.findViewById(R.id.btn_cookie_delete);
delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
CookieDeleteDialog dialog = new CookieDeleteDialog();
dialog.setArguments(arguments);
dialog.show(getFragmentManager(), "CookieDeleteDialog");
actionDialog.dismiss();
}
});
Button cancel = (Button) dialog_view.findViewById(R.id.btn_cookie_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
actionDialog.dismiss();
}
});
return actionDialog;
}
}

View File

@ -1,50 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class CookieDeleteDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final Context context = getContext();
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
// Delete from db
context.getContentResolver().delete(
CookieContentProvider.CONTENT_URI,
CookieContentProvider.ClientCookie._ID + "=" + arguments.getInt("_id"),
null
);
break;
case DialogInterface.BUTTON_NEGATIVE:
// Do nothing
break;
}
}
};
return new AlertDialog.Builder(context)
.setMessage(R.string.confirm_cookie_deletion)
.setPositiveButton(R.string.btn_okay, dialogClickListener)
.setNegativeButton(R.string.btn_cancel, dialogClickListener)
.create();
}
}

View File

@ -1,130 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.permissions.PermissionManager;
public class HSActionsDialog extends DialogFragment {
public static final int WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG = 2;
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_actions, null);
final AlertDialog actionDialog = new AlertDialog.Builder(getActivity())
.setView(dialog_view)
.setTitle(R.string.hidden_services)
.create();
Button backup = (Button) dialog_view.findViewById(R.id.btn_hs_backup);
backup.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context mContext = v.getContext();
if (PermissionManager.isLollipopOrHigher()
&& !PermissionManager.hasExternalWritePermission(mContext)) {
PermissionManager.requestExternalWritePermissions(
getActivity(), WRITE_EXTERNAL_STORAGE_FROM_ACTION_DIALOG);
return;
}
BackupUtils hsutils = new BackupUtils(mContext);
String backupPath = hsutils.createZipBackup(Integer.parseInt(arguments.getString("port")));
if (backupPath == null || backupPath.length() < 1) {
Toast.makeText(mContext, R.string.error, Toast.LENGTH_LONG).show();
actionDialog.dismiss();
return;
}
Toast.makeText(mContext, R.string.backup_saved_at_external_storage, Toast.LENGTH_LONG).show();
Uri selectedUri = Uri.parse(backupPath.substring(0, backupPath.lastIndexOf("/")));
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(selectedUri, "resource/folder");
if (intent.resolveActivityInfo(mContext.getPackageManager(), 0) != null) {
startActivity(intent);
} else {
Toast.makeText(mContext, R.string.filemanager_not_available, Toast.LENGTH_LONG).show();
}
actionDialog.dismiss();
}
});
Button copy = (Button) dialog_view.findViewById(R.id.btn_hs_clipboard);
copy.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context mContext = v.getContext();
ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("onion", arguments.getString("onion"));
clipboard.setPrimaryClip(clip);
Toast.makeText(mContext, R.string.done, Toast.LENGTH_LONG).show();
actionDialog.dismiss();
}
});
Button showAuth = (Button) dialog_view.findViewById(R.id.bt_hs_show_auth);
showAuth.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String auth_cookie_value = arguments.getString("auth_cookie_value");
if (arguments.getInt("auth_cookie") == 1) {
if (auth_cookie_value == null || auth_cookie_value.length() < 1) {
Toast.makeText(
v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
} else {
HSCookieDialog dialog = new HSCookieDialog();
dialog.setArguments(arguments);
dialog.show(getFragmentManager(), "HSCookieDialog");
}
} else {
Toast.makeText(
v.getContext(), R.string.auth_cookie_was_not_configured, Toast.LENGTH_LONG
).show();
}
actionDialog.dismiss();
}
});
Button delete = (Button) dialog_view.findViewById(R.id.btn_hs_delete);
delete.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
HSDeleteDialog dialog = new HSDeleteDialog();
dialog.setArguments(arguments);
dialog.show(getFragmentManager(), "HSDeleteDialog");
actionDialog.dismiss();
}
});
Button cancel = (Button) dialog_view.findViewById(R.id.btn_hs_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
actionDialog.dismiss();
}
});
return actionDialog;
}
}

View File

@ -1,81 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.ClipData;
import android.content.ClipboardManager;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import com.google.zxing.integration.android.IntentIntegrator;
import org.json.JSONException;
import org.json.JSONObject;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.CookieContentProvider;
public class HSCookieDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_cookie, null);
final Bundle arguments = getArguments();
final String auth_cookie_value = arguments.getString("auth_cookie_value");
final AlertDialog cookieDialog = new AlertDialog.Builder(getActivity())
.setView(dialog_view)
.create();
TextView cookie = (TextView) dialog_view.findViewById(R.id.hs_cookie);
cookie.setText(auth_cookie_value);
Button clipboard = (Button) dialog_view.findViewById(R.id.hs_cookie_to_clipboard);
clipboard.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
Context mContext = v.getContext();
ClipboardManager clipboard = (ClipboardManager) mContext.getSystemService(Context.CLIPBOARD_SERVICE);
ClipData clip = ClipData.newPlainText("cookie", auth_cookie_value);
clipboard.setPrimaryClip(clip);
Toast.makeText(mContext, R.string.done, Toast.LENGTH_LONG).show();
cookieDialog.dismiss();
}
});
Button shareQR = (Button) dialog_view.findViewById(R.id.hs_cookie_to_qr);
shareQR.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
try {
JSONObject backup = new JSONObject();
backup.put(CookieContentProvider.ClientCookie.DOMAIN, arguments.getString("onion"));
backup.put(CookieContentProvider.ClientCookie.AUTH_COOKIE_VALUE, arguments.getString("auth_cookie_value"));
IntentIntegrator integrator = new IntentIntegrator(getActivity());
integrator.shareText(backup.toString());
} catch (JSONException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cookieDialog.dismiss();
}
});
Button cancel = (Button) dialog_view.findViewById(R.id.hs_cookie_cancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
cookieDialog.dismiss();
}
});
return cookieDialog;
}
}

View File

@ -1,102 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
public class HSDataDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Get the layout
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_data_dialog, null);
// Use the Builder class for convenient dialog construction
final AlertDialog serviceDataDialog = new AlertDialog.Builder(getActivity())
.setView(dialog_view)
.setTitle(R.string.hidden_services)
.create();
// Buttons action
Button save = (Button) dialog_view.findViewById(R.id.HSDialogSave);
save.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
String serverName = ((EditText) dialog_view.findViewById(R.id.hsName)).getText().toString();
Integer localPort = Integer.parseInt(
((EditText) dialog_view.findViewById(R.id.hsLocalPort)).getText().toString()
);
Integer onionPort = Integer.parseInt(
((EditText) dialog_view.findViewById(R.id.hsOnionPort)).getText().toString()
);
Boolean authCookie = ((CheckBox) dialog_view.findViewById(R.id.hsAuth)).isChecked();
if (checkInput(serverName, localPort, onionPort)) {
saveData(serverName, localPort, onionPort, authCookie);
Toast.makeText(
v.getContext(), R.string.please_restart_Orbot_to_enable_the_changes, Toast.LENGTH_LONG
).show();
serviceDataDialog.dismiss();
}
}
});
Button cancel = (Button) dialog_view.findViewById(R.id.HSDialogCancel);
cancel.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
serviceDataDialog.cancel();
}
});
return serviceDataDialog;
}
private boolean checkInput(String serverName, Integer local, Integer remote) {
boolean is_ok = true;
Integer error_msg = 0;
if ((local < 1 || local > 65535) || (remote < 1 || remote > 65535)) {
error_msg = R.string.invalid_port;
is_ok = false;
}
if (serverName == null || serverName.length() < 1) {
error_msg = R.string.name_can_t_be_empty;
is_ok = false;
}
if (!is_ok) {
Toast.makeText(getContext(), error_msg, Toast.LENGTH_SHORT).show();
}
return is_ok;
}
private void saveData(String name, Integer local, Integer remote, Boolean authCookie) {
ContentValues fields = new ContentValues();
fields.put(HSContentProvider.HiddenService.NAME, name);
fields.put(HSContentProvider.HiddenService.PORT, local);
fields.put(HSContentProvider.HiddenService.ONION_PORT, remote);
fields.put(HSContentProvider.HiddenService.AUTH_COOKIE, authCookie);
fields.put(HSContentProvider.HiddenService.CREATED_BY_USER, 1);
ContentResolver cr = getContext().getContentResolver();
cr.insert(HSContentProvider.CONTENT_URI, fields);
}
}

View File

@ -1,65 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import org.torproject.android.R;
import org.torproject.android.service.TorServiceConstants;
import org.torproject.android.ui.hiddenservices.providers.HSContentProvider;
import java.io.File;
public class HSDeleteDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
final Bundle arguments = getArguments();
final Context context = getContext();
DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
switch (which) {
case DialogInterface.BUTTON_POSITIVE:
// Delete from db
context.getContentResolver().delete(
HSContentProvider.CONTENT_URI,
HSContentProvider.HiddenService._ID + "=" + arguments.getInt("_id"),
null
);
// Delete from interal storage
String base = context.getFilesDir().getAbsolutePath() + "/" + TorServiceConstants.HIDDEN_SERVICES_DIR;
File dir = new File(base, "hs" + arguments.getString("port"));
if (dir.isDirectory()) {
String[] children = dir.list();
for (String aChildren : children) {
new File(dir, aChildren).delete();
}
dir.delete();
}
break;
case DialogInterface.BUTTON_NEGATIVE:
// Do nothing
break;
}
}
};
return new AlertDialog.Builder(context)
.setMessage(R.string.confirm_service_deletion)
.setPositiveButton(R.string.btn_okay, dialogClickListener)
.setNegativeButton(R.string.btn_cancel, dialogClickListener)
.create();
}
}

View File

@ -1,84 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.adapters.BackupAdapter;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SelectCookieBackupDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder cookieBackupDialog = new AlertDialog.Builder(getActivity());
cookieBackupDialog.setTitle(R.string.restore_backup);
File backupDir = ExternalStorage.getOrCreateBackupDir();
File[] files = null;
try {
files = backupDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".json");
}
});
} catch (NullPointerException e) {
// Silent block
}
if (files == null || files.length < 1) {
cookieBackupDialog.setMessage(R.string.create_a_backup_first);
cookieBackupDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return cookieBackupDialog.create();
}
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
cookieBackupDialog.setView(dialog_view);
cookieBackupDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
List<File> json_backups = new ArrayList<>();
Collections.addAll(json_backups, files);
backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, json_backups));
backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BackupUtils backupUtils = new BackupUtils(view.getContext().getApplicationContext());
File p = (File) parent.getItemAtPosition(position);
backupUtils.restoreCookieBackup(p);
}
});
return cookieBackupDialog.create();
}
}

View File

@ -1,84 +0,0 @@
package org.torproject.android.ui.hiddenservices.dialogs;
import android.app.Dialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.DialogFragment;
import android.support.v7.app.AlertDialog;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import org.torproject.android.R;
import org.torproject.android.ui.hiddenservices.adapters.BackupAdapter;
import org.torproject.android.ui.hiddenservices.backup.BackupUtils;
import org.torproject.android.ui.hiddenservices.storage.ExternalStorage;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
public class SelectHSBackupDialog extends DialogFragment {
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
AlertDialog.Builder backupsDialog = new AlertDialog.Builder(getActivity());
backupsDialog.setTitle(R.string.restore_backup);
File backupDir = ExternalStorage.getOrCreateBackupDir();
File[] files = null;
try {
files = backupDir.listFiles(new FilenameFilter() {
@Override
public boolean accept(File dir, String name) {
return name.toLowerCase().endsWith(".zip");
}
});
} catch (NullPointerException e) {
// Silent block
}
if (files == null || files.length < 1) {
backupsDialog.setMessage(R.string.create_a_backup_first);
backupsDialog.setNegativeButton(R.string.btn_cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
return backupsDialog.create();
}
final View dialog_view = getActivity().getLayoutInflater().inflate(R.layout.layout_hs_backups_list, null);
backupsDialog.setView(dialog_view);
backupsDialog.setPositiveButton(R.string.btn_okay, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
dialog.dismiss();
}
});
ListView backups = (ListView) dialog_view.findViewById(R.id.listview_hs_backups);
List<File> zips = new ArrayList<>();
Collections.addAll(zips, files);
backups.setAdapter(new BackupAdapter(getContext(), R.layout.layout_hs_backups_list_item, zips));
backups.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
BackupUtils backupUtils = new BackupUtils(view.getContext().getApplicationContext());
File p = (File) parent.getItemAtPosition(position);
backupUtils.restoreZipBackup(p);
}
});
return backupsDialog.create();
}
}

View File

@ -1,103 +0,0 @@
package org.torproject.android.ui.hiddenservices.permissions;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.PowerManager;
import android.provider.Settings;
import android.support.design.widget.Snackbar;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.FragmentActivity;
import android.view.View;
import org.torproject.android.R;
public class PermissionManager {
public static int VERY_LONG_LENGTH = 6000;
public static boolean isLollipopOrHigher() {
return (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP);
}
@SuppressLint("NewApi")
public static boolean hasExternalWritePermission(Context context) {
return (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED);
}
public static void requestExternalWritePermissions(FragmentActivity activity, int action) {
final int mAction = action;
final FragmentActivity mActivity = activity;
if (ActivityCompat.shouldShowRequestPermissionRationale
(mActivity, Manifest.permission.WRITE_EXTERNAL_STORAGE)) {
Snackbar.make(mActivity.findViewById(android.R.id.content),
R.string.please_grant_permissions_for_external_storage,
Snackbar.LENGTH_INDEFINITE).setAction(R.string.activate,
new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
mAction);
}
}).show();
} else {
ActivityCompat.requestPermissions(mActivity,
new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE},
mAction);
}
}
@TargetApi(Build.VERSION_CODES.M)
public static void requestBatteryPermmssions(FragmentActivity activity, Context context) {
final Context mContext = context;
final String packageName = mContext.getPackageName();
PowerManager pm = (PowerManager) mContext.getSystemService(Context.POWER_SERVICE);
if (pm.isIgnoringBatteryOptimizations(packageName))
return;
Snackbar.make(activity.findViewById(android.R.id.content),
R.string.consider_disable_battery_optimizations,
VERY_LONG_LENGTH).setAction(R.string.disable,
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
intent.setData(Uri.parse("package:" + packageName));
mContext.startActivity(intent);
}
}).show();
}
@TargetApi(Build.VERSION_CODES.M)
public static void requestDropBatteryPermmssions(FragmentActivity activity, Context context) {
final Context mContext = context;
final String packageName = context.getPackageName();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
if (!pm.isIgnoringBatteryOptimizations(packageName))
return;
Snackbar.make(activity.findViewById(android.R.id.content),
R.string.consider_enable_battery_optimizations,
VERY_LONG_LENGTH).setAction(R.string.enable,
new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
mContext.startActivity(intent);
}
}).show();
}
}

View File

@ -1,134 +0,0 @@
package org.torproject.android.ui.hiddenservices.providers;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.BaseColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.torproject.android.ui.hiddenservices.database.HSDatabase;
public class CookieContentProvider extends ContentProvider {
public static final String[] PROJECTION = new String[]{
ClientCookie._ID,
ClientCookie.DOMAIN,
ClientCookie.AUTH_COOKIE_VALUE,
ClientCookie.ENABLED
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers.cookie";
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTH + "/cookie");
//UriMatcher
private static final int COOKIES = 1;
private static final int COOKIE_ID = 2;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTH, "hs", COOKIES);
uriMatcher.addURI(AUTH, "hs/#", COOKIE_ID);
}
private HSDatabase mServervices;
private Context mContext;
@Override
public boolean onCreate() {
mContext = getContext();
mServervices = new HSDatabase(mContext);
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
String where = selection;
if (uriMatcher.match(uri) == COOKIE_ID) {
where = "_id=" + uri.getLastPathSegment();
}
SQLiteDatabase db = mServervices.getReadableDatabase();
return db.query(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, projection, where,
selectionArgs, null, null, sortOrder);
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
int match = uriMatcher.match(uri);
switch (match) {
case COOKIES:
return "vnd.android.cursor.dir/vnd.torproject.cookies";
case COOKIE_ID:
return "vnd.android.cursor.item/vnd.torproject.cookie";
default:
return null;
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
long regId;
SQLiteDatabase db = mServervices.getWritableDatabase();
regId = db.insert(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, null, values);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return ContentUris.withAppendedId(CONTENT_URI, regId);
}
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
String where = selection;
if (uriMatcher.match(uri) == COOKIE_ID) {
where = "_id=" + uri.getLastPathSegment();
}
SQLiteDatabase db = mServervices.getWritableDatabase();
Integer rows = db.delete(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, where, selectionArgs);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return rows;
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = mServervices.getWritableDatabase();
String where = selection;
if (uriMatcher.match(uri) == COOKIE_ID) {
where = "_id=" + uri.getLastPathSegment();
}
Integer rows = db.update(HSDatabase.HS_CLIENT_COOKIE_TABLE_NAME, values, where, null);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return rows;
}
public static final class ClientCookie implements BaseColumns {
public static final String DOMAIN = "domain";
public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String ENABLED = "enabled";
private ClientCookie() {
}
}
}

View File

@ -1,144 +0,0 @@
package org.torproject.android.ui.hiddenservices.providers;
import android.content.ContentProvider;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.UriMatcher;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.net.Uri;
import android.provider.BaseColumns;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import org.torproject.android.ui.hiddenservices.database.HSDatabase;
public class HSContentProvider extends ContentProvider {
public static final String[] PROJECTION = new String[]{
HiddenService._ID,
HiddenService.NAME,
HiddenService.PORT,
HiddenService.DOMAIN,
HiddenService.ONION_PORT,
HiddenService.AUTH_COOKIE,
HiddenService.AUTH_COOKIE_VALUE,
HiddenService.CREATED_BY_USER,
HiddenService.ENABLED
};
private static final String AUTH = "org.torproject.android.ui.hiddenservices.providers";
public static final Uri CONTENT_URI =
Uri.parse("content://" + AUTH + "/hs");
//UriMatcher
private static final int ONIONS = 1;
private static final int ONION_ID = 2;
private static final UriMatcher uriMatcher;
static {
uriMatcher = new UriMatcher(UriMatcher.NO_MATCH);
uriMatcher.addURI(AUTH, "hs", ONIONS);
uriMatcher.addURI(AUTH, "hs/#", ONION_ID);
}
private HSDatabase mServervices;
private Context mContext;
@Override
public boolean onCreate() {
mContext = getContext();
mServervices = new HSDatabase(mContext);
return true;
}
@Nullable
@Override
public Cursor query(@NonNull Uri uri, String[] projection, String selection, String[] selectionArgs, String sortOrder) {
String where = selection;
if (uriMatcher.match(uri) == ONION_ID) {
where = "_id=" + uri.getLastPathSegment();
}
SQLiteDatabase db = mServervices.getReadableDatabase();
return db.query(HSDatabase.HS_DATA_TABLE_NAME, projection, where,
selectionArgs, null, null, sortOrder);
}
@Nullable
@Override
public String getType(@NonNull Uri uri) {
int match = uriMatcher.match(uri);
switch (match) {
case ONIONS:
return "vnd.android.cursor.dir/vnd.torproject.onions";
case ONION_ID:
return "vnd.android.cursor.item/vnd.torproject.onion";
default:
return null;
}
}
@Nullable
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
long regId;
SQLiteDatabase db = mServervices.getWritableDatabase();
regId = db.insert(HSDatabase.HS_DATA_TABLE_NAME, null, values);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return ContentUris.withAppendedId(CONTENT_URI, regId);
}
@Override
public int delete(@NonNull Uri uri, String selection, String[] selectionArgs) {
String where = selection;
if (uriMatcher.match(uri) == ONION_ID) {
where = "_id=" + uri.getLastPathSegment();
}
SQLiteDatabase db = mServervices.getWritableDatabase();
Integer rows = db.delete(HSDatabase.HS_DATA_TABLE_NAME, where, selectionArgs);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return rows;
}
@Override
public int update(@NonNull Uri uri, ContentValues values, String selection, String[] selectionArgs) {
SQLiteDatabase db = mServervices.getWritableDatabase();
String where = selection;
if (uriMatcher.match(uri) == ONION_ID) {
where = "_id=" + uri.getLastPathSegment();
}
Integer rows = db.update(HSDatabase.HS_DATA_TABLE_NAME, values, where, null);
mContext.getContentResolver().notifyChange(CONTENT_URI, null);
return rows;
}
public static final class HiddenService implements BaseColumns {
public static final String NAME = "name";
public static final String PORT = "port";
public static final String ONION_PORT = "onion_port";
public static final String DOMAIN = "domain";
public static final String AUTH_COOKIE = "auth_cookie";
public static final String AUTH_COOKIE_VALUE = "auth_cookie_value";
public static final String CREATED_BY_USER = "created_by_user";
public static final String ENABLED = "enabled";
private HiddenService() {
}
}
}

View File

@ -1,34 +0,0 @@
package org.torproject.android.ui.hiddenservices.storage;
import android.os.Environment;
import java.io.File;
public class ExternalStorage {
private static final String ORBOT_BACKUPS_DIR = "Orbot";
public static File getOrCreateBackupDir() {
if (!isExternalStorageWritable())
return null;
File dir = new File(Environment.getExternalStorageDirectory(), ORBOT_BACKUPS_DIR);
if (!dir.isDirectory() && !dir.mkdirs())
return null;
return dir;
}
/* Checks if external storage is available for read and write */
public static boolean isExternalStorageWritable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state);
}
/* Checks if external storage is available to at least read */
public static boolean isExternalStorageReadable() {
String state = Environment.getExternalStorageState();
return Environment.MEDIA_MOUNTED.equals(state) ||
Environment.MEDIA_MOUNTED_READ_ONLY.equals(state);
}
}

View File

@ -1,163 +0,0 @@
package org.torproject.android.vpn;
import org.torproject.android.R;
import org.torproject.android.service.util.Prefs;
import org.torproject.android.service.TorService;
import org.torproject.android.service.TorServiceConstants;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.VpnService;
import android.os.Bundle;
import android.os.Handler;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.Window;
/*
* To combat background service being stopped/swiped
*/
@TargetApi(14)
public class VPNEnableActivity extends AppCompatActivity {
private final static int REQUEST_VPN = 7777;
private Intent intent = null;
private boolean checkVpn = true;
private Handler h = new Handler();
@Override
public void onCreate( Bundle icicle ) {
requestWindowFeature(Window.FEATURE_NO_TITLE);
//getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate( icicle );
Log.d("VPNEnableActivity","prompting user to start Orbot VPN");
}
public void onResume ()
{
super.onResume();
if (checkVpn)
{
intent = VpnService.prepare(this);
if (intent != null)
promptStartVpnService();
else
startVpnService ();
checkVpn = false;
}
}
public void promptStartVpnService ()
{
AlertDialog dialog = new AlertDialog.Builder(this)
.setTitle(getString(R.string.app_name) + ' ' + getString(R.string.apps_mode))
.setMessage(getString(R.string.you_can_enable_all_apps_on_your_device_to_run_through_the_tor_network_using_the_vpn_feature_of_android_))
.setPositiveButton(R.string.activate, new Dialog.OnClickListener ()
{
@Override
public void onClick(DialogInterface dialog, int which) {
Prefs.putUseVpn(true);
startVpnService();
}
})
.setNegativeButton(R.string.btn_cancel, new Dialog.OnClickListener ()
{
@Override
public void onClick(DialogInterface dialog, int which) {
h.postDelayed(new Runnable () {
public void run ()
{
VPNEnableActivity.this.finish();
}
}, 100);
}
}).create();
dialog.show();
}
private void startVpnService ()
{
if (intent == null)
{
Log.d("VPNEnableActivity","VPN enabled, starting Tor...");
sendIntentToService(TorServiceConstants.CMD_VPN);
Handler h = new Handler();
h.postDelayed(new Runnable () {
public void run ()
{
sendIntentToService(TorServiceConstants.ACTION_START);
finish();
}
}, 100);
}
else
{
Log.w("VPNEnableActivity","prompt for VPN");
startActivityForResult(intent,REQUEST_VPN);
}
}
@Override
protected void onActivityResult(int request, int response, Intent data) {
super.onActivityResult(request, response, data);
if (request == REQUEST_VPN && response == RESULT_OK)
{
sendIntentToService(TorServiceConstants.CMD_VPN);
h.postDelayed(new Runnable () {
public void run ()
{
sendIntentToService(TorServiceConstants.ACTION_START);
finish();
}
}, 1000);
}
}
private void sendIntentToService(String action) {
Intent torService = new Intent(this, TorService.class);
torService.setAction(action);
startService(torService);
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 480 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 802 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 744 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 967 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 713 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 553 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 232 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 221 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 852 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 990 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 294 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 390 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 342 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 358 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 319 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 647 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 517 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 607 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 458 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 475 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 364 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 369 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 198 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 163 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 883 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 535 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 618 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Some files were not shown because too many files have changed in this diff Show More