88 Commits

Author SHA1 Message Date
idk
f5ec1672ab remake index 2022-02-14 16:22:24 -05:00
idk
b231ea0329 Merge branch 'embed-i2pd' into 'main'
don't quit the app on a failed conditional host I2P launch anymore, wait until...

See merge request idk/i2p.plugins.tor-manager!1
2022-02-14 18:43:29 +00:00
idk
c64a7fa866 Set torlauncer.start-tor true in i2p.firefox profile so we can use it as an outproxy even when we're not in long-running mode 2022-02-14 13:42:41 -05:00
idk
8ec37c0536 Fix broken links in the github readme 2022-02-14 13:40:20 -05:00
idk
064731ef36 Fix broken links in the github readme 2022-02-14 13:36:39 -05:00
idk
fbcf10dcdc don't quit the app on a failed conditional host I2P launch anymore, wait until after we've tried i2pd 2022-02-13 20:27:59 -05:00
idk
ef30907184 Document differences between this and similar projects 2022-02-13 13:27:46 -05:00
idk
5401e600ea Document differences between this and similar projects 2022-02-13 13:26:37 -05:00
idk
8f4339f2e2 Enable embedded i2pd router 2022-02-13 12:41:58 -05:00
idk
35f8586bf3 Embed an i2pd router, and launch it as a last resort. 2022-02-13 02:19:46 -05:00
idk
9e9e63d215 Embed an i2pd router, and launch it as a last resort. 2022-02-13 02:13:22 -05:00
idk
a081be6a27 pages 2022-02-12 00:15:47 -05:00
idk
5cbee7c23b pages 2022-02-12 00:12:14 -05:00
idk
a830c8b846 pages 2022-02-12 00:09:41 -05:00
idk
32cf9b82b3 pages 2022-02-12 00:06:44 -05:00
idk
d9945c4f52 pages 2022-02-12 00:06:07 -05:00
idk
cb18068ea4 set default page equal to trailing argument 0 if there is at least one trailing argument. 2022-02-11 23:57:15 -05:00
idk
ee6d46f50b Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 23:06:19 -05:00
idk
47f29d7207 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 23:06:05 -05:00
idk
2733a3a613 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 23:05:12 -05:00
idk
e4130a3b2b Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 23:01:05 -05:00
idk
3950c0aa61 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 23:00:27 -05:00
idk
f2e2d3dad2 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 22:52:19 -05:00
idk
ab9f597610 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 22:48:47 -05:00
idk
84b91cf4b8 Add Firefox mode, Work offline docs update, custom profile paths 2022-02-11 22:48:28 -05:00
idk
ff1e3b30dc re-enable Debian package, mostly 2022-02-11 00:42:21 -05:00
idk
72e134fd7f Add some new options, commented out. 2022-02-10 23:39:31 -05:00
idk
3c2ebcbd55 Add additional extensions and documentation of why 2022-02-10 23:24:24 -05:00
idk
e3d37a2a0b Add additional extensions and documentation of why 2022-02-10 23:23:28 -05:00
idk
c5680ab9eb Add additional extensions and documentation of why 2022-02-10 23:19:00 -05:00
idk
28179953b8 Create shortcuts on OSX, return AMD64 on M1 Mac 2022-02-10 20:20:02 -05:00
idk
049180c2da plugin download links 2022-02-08 21:55:33 -05:00
idk
49fe7bb450 plugin download links 2022-02-08 21:55:15 -05:00
idk
0d688601a1 fix error catching in main. don't swallow them, report them. 2022-02-08 20:30:33 -05:00
idk
e60da2ab18 Bump 2022-02-08 20:04:55 -05:00
idk
776a3c1528 Fix pluginization. 2022-02-08 19:51:18 -05:00
idk
e88e54f472 Fix pluginization. 2022-02-08 19:49:36 -05:00
idk
55dedbe7ea Fix pluginization. 2022-02-08 19:47:04 -05:00
idk
52b4abfe7d improve how it manages Firefox processes 2022-02-08 19:40:20 -05:00
idk
cfdfc5a092 Make OSX work! 2022-02-08 18:31:32 -05:00
idk
c85e5b1cb8 OSX fixes 2022-02-08 01:23:30 -05:00
idk
746d8edab5 update Windows description 2022-02-07 21:42:48 -05:00
idk
5e9361fa16 add AWO extension 2022-02-07 21:38:54 -05:00
idk
79571c19e7 add an -offline(work offline) flag 2022-02-07 21:17:05 -05:00
idk
749aafbb45 add an -offline(work offline) flag 2022-02-07 21:09:43 -05:00
idk
791e9467a7 Add Firefox help when --help flag is set 2022-02-07 16:57:13 -05:00
idk
45f5fc8fc1 TODO 2022-02-07 16:46:36 -05:00
idk
5ed90883f5 Add Firefox help when --help flag is set 2022-02-07 16:18:55 -05:00
idk
adabb76aef Only wait for I2P proxy if I2PBrowser is true 2022-02-07 15:54:51 -05:00
idk
921cd89be6 Only wait for I2P proxy if I2PBrowser is true 2022-02-07 15:53:16 -05:00
idk
5bbd38ccb3 Make target change 2022-02-07 15:48:51 -05:00
idk
67cf6886df Fix all the linter errors I care about 2022-02-07 15:44:06 -05:00
idk
1367cea3a3 Fix all the linter errors I care about 2022-02-07 15:34:45 -05:00
idk
c9a77dc123 add the ability to manage a Firefox browser too. 2022-02-07 14:29:04 -05:00
idk
5a1ac883a5 add config profile 2022-02-06 16:58:09 -05:00
idk
d83bd7b231 add config mode 2022-02-06 16:57:30 -05:00
idk
1bac06a43b Fix some path determination stuff 2022-02-03 02:06:39 -05:00
idk
edb4ce1670 If a router isn't started, start one. If an HTTP proxy isn't started, start one. 2022-01-31 16:24:15 -05:00
idk
23ba452669 If a router isn't started, start one. If an HTTP proxy isn't started, start one. 2022-01-31 16:14:30 -05:00
idk
8ba510557b closes #1 2022-01-31 02:14:28 -05:00
idk
e32d28f1c4 Add apparmor profile generation and default apparmor profiles 2022-01-31 02:13:04 -05:00
idk
240e135097 Add apparmor profile generation and default apparmor profiles 2022-01-31 02:09:02 -05:00
idk
0fc85bd8d7 Update screenshots 2022-01-30 18:43:08 -05:00
idk
cdc9637b23 Give it the ability to make it's own shortcuts 2022-01-30 16:47:26 -05:00
idk
fc842f8a63 Give it the ability to make it's own shortcuts 2022-01-30 16:45:50 -05:00
idk
6de17ef74a Windows release 2022-01-30 04:20:53 -05:00
idk
c69b0d6c2d Remake page 2022-01-30 03:54:35 -05:00
idk eyedeekay
025b372e41 Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:51:53 -05:00
idk eyedeekay
0f0caa7eea Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:50:48 -05:00
idk eyedeekay
80971e209b Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:40:15 -05:00
idk eyedeekay
eb49ddd784 Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:24:08 -05:00
idk eyedeekay
54b47d8f0f Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:22:55 -05:00
idk eyedeekay
93583ab435 Windows fixes for launching Tor and/or Tor Browser 2022-01-30 03:17:08 -05:00
idk
15cdc02440 Use path instead of filepath for referencing embeds 2022-01-30 02:41:45 -05:00
idk eyedeekay
bd23b2a253 Checkin Windows fixes from the Windows machine 2022-01-30 02:05:31 -05:00
idk
200663e273 Set verbosity earlier. Don't bother manual mirror hostname setting yet. 2022-01-30 01:50:53 -05:00
idk
868ae5ec38 More logging, make it nicer on Windows 2022-01-30 01:41:23 -05:00
idk
6cba86277f More logging, make it nicer on Windows 2022-01-30 01:33:40 -05:00
idk
a948f597df Create directories automatically, mirror Tor Browser and our profile too, allow customizing the ports. Some probably unnecessary defensive coding. 2022-01-29 01:19:31 -05:00
idk
d92a5b2369 Create directories automatically, mirror Tor Browser and our profile too, allow customizing the ports. Some probably unnecessary defensive coding. 2022-01-29 01:18:37 -05:00
idk
b1f6205675 make external template 2022-01-28 01:46:35 -05:00
idk
a068a6f726 make external template 2022-01-28 01:21:17 -05:00
idk
bc1b89a8a7 make external template 2022-01-28 01:07:44 -05:00
idk
42651d99b5 Add icons 2022-01-28 00:19:21 -05:00
idk
6cbf35cb9d Add icons 2022-01-28 00:17:38 -05:00
idk
0015446f89 Add icons 2022-01-28 00:15:03 -05:00
idk
98af452cd8 Add desktop files 2022-01-28 00:09:18 -05:00
idk
b30558e664 add desktop file 2022-01-27 23:08:20 -05:00
68 changed files with 4472 additions and 291 deletions

1
.gitignore vendored
View File

@@ -8,3 +8,4 @@ i2p.plugins.tor-manager*
*.su3
*-zip
pluginunpack
_build

12
FIREFOX.md Normal file
View File

@@ -0,0 +1,12 @@
Running in Clearnet Mode
========================
Tor Browser is configured to run without Tor, and will now use the non-anonymous
web. It is also configured to use uBlock Origin. This allows you to use a hardened
web browser for your non-anonymous tasks.
- To get started, perhaps try [DuckDuckGo](https://duckduckgo.com)
- or [PrivacyGuides](https://privacyguides.org/)
This wrapper has been developed for use with the I2P project. To learn more about I2P,
visit [Get I2P](https://geti2p.net)

139
Makefile
View File

@@ -1,6 +1,6 @@
VERSION=0.0.2
VERSION=0.0.4
CGO_ENABLED=0
export CGO_ENABLED=0
#export CGO_ENABLED=0
GOOS?=$(shell uname -s | tr A-Z a-z)
GOARCH?="amd64"
@@ -18,17 +18,27 @@ PREFIX?=/usr/local
binary:
go build $(ARG) -tags="netgo" -o $(BINARY)-$(GOOS)-$(GOARCH) .
lint:
golint supervise/*.go
golint get/*.go
golint serve/*.go
install-binary: binary
cp -v $(BINARY)-$(GOOS)-$(GOARCH) $(PLUGIN)/lib
install:
mkdir -p /var/lib/i2pbrowser/icons
install -m755 -v $(BINARY)-$(GOOS)-$(GOARCH) $(PREFIX)/bin/$(BINARY)-$(GOOS)-$(GOARCH)
ln -sf $(PREFIX)/bin/$(BINARY)-$(GOOS)-$(GOARCH) $(PREFIX)/bin/i2pbrowser
ln -sf $(PREFIX)/bin/$(BINARY)-$(GOOS)-$(GOARCH) $(PREFIX)/bin/torbrowser
install i2ptorbrowser.desktop /usr/share/applications/i2ptorbrowser.desktop
install torbrowser.desktop /usr/share/applications/torbrowser.desktop
install garliconion.png /var/lib/i2pbrowser/icons/garliconion.png
install onion.png /var/lib/i2pbrowser/icons/onion.png
build: dep binary
p: dep binary make su3
p: dep binary su3
clean:
rm -f $(BINARY)-plugin plugin $(BINARY)-*zip -r $(BINARY)-$(GOOS)-$(GOARCH) $(BINARY)-$(GOOS)-$(GOARCH).exe tmp tor-browser/torbrowser-*.* $(BINARY) $(BINARY).exe
@@ -55,7 +65,7 @@ bsd:
# GOOS=openbsd GOARCH=amd64 make build su3
dep:
cp "$(HOME)/Workspace/GIT_WORK/i2p.i2p/build/shellservice.jar" tor-browser/lib/shellservice.jar -v
cp "$(HOME)/build/shellservice.jar" tor-browser/lib/shellservice.jar -v
su3:
i2p.plugin.native -name=$(BINARY)-$(GOOS)-$(GOARCH) \
@@ -63,9 +73,8 @@ su3:
-version "$(VERSION)" \
-author=$(SIGNER) \
-autostart=true \
-clientname=$(BINARY)-$(GOOS)-$(GOARCH) \
-clientname=$(BINARY) \
-consolename="$(BINARY) - $(CONSOLEPOSTNAME)" \
-name="$(BINARY)-$(GOOS)-$(GOARCH)" \
-delaystart="1" \
-desc="`cat desc`" \
-exename=$(BINARY)-$(GOOS)-$(GOARCH) \
@@ -121,11 +130,11 @@ download-su3s:
download-single-su3:
wget -N -c "https://github.com/$(USER_GH)/$(BINARY)/releases/download/$(VERSION)/$(BINARY)-$(GOOS)-$(GOARCH).su3"
linux-release: clean linux version upload-linux
early-release: clean linux windows version upload-linux upload-windows
release: clean all version upload-all
index:
index: index-clearnet index-offline index-usage
@echo "<!DOCTYPE html>" > index.html
@echo "<html>" >> index.html
@echo "<head>" >> index.html
@@ -133,10 +142,41 @@ index:
@echo " <link rel=\"stylesheet\" type=\"text/css\" href =\"/style.css\" />" >> index.html
@echo "</head>" >> index.html
@echo "<body>" >> index.html
pandoc README.md >> index.html
sed 's|https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/||g' README.md | \
sed "s|$(VERSION)||g" | pandoc >> index.html
@echo "</body>" >> index.html
@echo "</html>" >> index.html
index-clearnet:
@echo "<!DOCTYPE html>" > firefox.html
@echo "<html>" >> firefox.html
@echo "<head>" >> firefox.html
@echo " <title>$(BINARY) - $(CONSOLEPOSTNAME)</title>" >> firefox.html
@echo " <link rel=\"stylesheet\" type=\"text/css\" href =\"/style.css\" />" >> firefox.html
@echo "</head>" >> firefox.html
@echo "<body>" >> firefox.html
pandoc FIREFOX.md >> firefox.html
@echo "</body>" >> firefox.html
@echo "</html>" >> firefox.html
index-offline:
@echo "<!DOCTYPE html>" > offline.html
@echo "<html>" >> offline.html
@echo "<head>" >> offline.html
@echo " <title>$(BINARY) - $(CONSOLEPOSTNAME)</title>" >> offline.html
@echo " <link rel=\"stylesheet\" type=\"text/css\" href =\"/style.css\" />" >> offline.html
@echo "</head>" >> offline.html
@echo "<body>" >> offline.html
pandoc OFFLINE.md >> offline.html
@echo "</body>" >> offline.html
@echo "</html>" >> offline.html
tor-browser/unpack/i2p.firefox:
@echo "TODO"
tor-browser/unpack/i2p.firefox.config:
@echo "TODO"
refresh-tor-keys: clean-tor-keys tor-browser/TPO-signing-key.pub
tor-keys: tor-browser/TPO-signing-key.pub
@@ -151,7 +191,7 @@ deb: clean
mv "hankhill19580_at_gmail.com.crl" ../; true
mv "hankhill19580_at_gmail.com.crt" ../; true
mv "hankhill19580_at_gmail.com.pem" ../; true
rm ../i2p.plugins.tor-manager_$(VERSION).orig.tar.gz
rm ../i2p.plugins.tor-manager_$(VERSION).orig.tar.gz -f
tar --exclude=".git" \
--exclude="hankhill19580_at_gmail.com.crl" \
--exclude="hankhill19580_at_gmail.com.crt" \
@@ -169,7 +209,7 @@ debsrc: clean
mv "hankhill19580_at_gmail.com.crl" ../; true
mv "hankhill19580_at_gmail.com.crt" ../; true
mv "hankhill19580_at_gmail.com.pem" ../; true
rm ../i2p.plugins.tor-manager_$(VERSION).orig.tar.gz
rm ../i2p.plugins.tor-manager_$(VERSION).orig.tar.gz -f
tar --exclude=".git" \
--exclude="hankhill19580_at_gmail.com.crl" \
--exclude="hankhill19580_at_gmail.com.crt" \
@@ -181,4 +221,79 @@ debsrc: clean
debuild -S
mv "../hankhill19580_at_gmail.com.crl" ./
mv "../hankhill19580_at_gmail.com.crt" ./
mv "../hankhill19580_at_gmail.com.pem" ./
mv "../hankhill19580_at_gmail.com.pem" ./
DATE=`date +%Y/%m/%d`
usage:
./i2p.plugins.tor-manager --help
usagemd:
@echo "Tor(And sometimes Firefox) Manager for I2P" | tee USAGE.md
@echo "===========================================" | tee -a USAGE.md
@echo "" | tee -a USAGE.md
@echo "## Usage: $(BINARY) [options]" | tee -a USAGE.md
@echo "" | tee -a USAGE.md
@echo "### Options:" | tee -a USAGE.md
@echo "" | tee -a USAGE.md
@echo '```sh' | tee -a USAGE.md
./i2p.plugins.tor-manager --help 2>&1 | grep -v $(DATE) | grep -v $(HOME) | tee -a USAGE.md
@echo '```' | tee -a USAGE.md
@echo "" | tee -a USAGE.md
index-usage:
@echo "<!DOCTYPE html>" > usage.html
@echo "<html>" >> usage.html
@echo "<head>" >> usage.html
@echo " <title>$(BINARY) - $(CONSOLEPOSTNAME)</title>" >> usage.html
@echo " <link rel=\"stylesheet\" type=\"text/css\" href =\"/style.css\" />" >> usage.html
@echo "</head>" >> usage.html
@echo "<body>" >> usage.html
pandoc USAGE.md >> usage.html
@echo "</body>" >> usage.html
@echo "</html>" >> usage.html
#GO111MODULE=off
#export GO111MODULE=off
i2pd_prerelease_version=c-wrapper-libi2pd-api
i2pd_release_version=2.40.0
export GOPATH=$(HOME)/go
export USE_STATIC=yes
USE_STATIC=yes
export LDFLAGS=-static
LDFLAGS=-static
GXXFLAGS=-static
export GXXFLAGS=-static
CXXFLAGS=-static
export CXXFLAGS=-static
CGO_GXXFLAGS=-static
export CGO_GXXFLAGS=-static
CGO_CFLAGS=-static
export CGO_CFLAGS=-static
CGO_CXXFLAGS=-static
export CGO_CXXFLAGS=-static
CGO_CPPFLAGS=-static
export CGO_CPPFLAGS=-static
#CGO_LDFLAGS=-static
#export CGO_LDFLAGS=-static
#Trying to achieve fully-static builds, this doesn't work yet.
FLAGS=/usr/lib/x86_64-linux-gnu/libboost_system.a /usr/lib/x86_64-linux-gnu/libboost_date_time.a /usr/lib/x86_64-linux-gnu/libboost_filesystem.a /usr/lib/x86_64-linux-gnu/libboost_program_options.a /usr/lib/x86_64-linux-gnu/libssl.a /usr/lib/x86_64-linux-gnu/libcrypto.a /usr/lib/x86_64-linux-gnu/libz.a
example:
go build -x -v --tags=netgo \
-ldflags '-w -linkmode=external -extldflags "-static -ldl $(FLAGS)"'

12
OFFLINE.md Normal file
View File

@@ -0,0 +1,12 @@
Running in Offline Mode
========================
Tor Browser is configured to run without *any* access to the clearnet, and will now
only use local services running on this device. This uses a different mechanism than
Firefox's normal work offline mode and cannot be canceled.
- Visit the [I2P Router Console](http://127.0.0.1:7657)
- Visit the [Freenet FProxy](http://127.0.0.1:8888)
This wrapper has been developed for use with the I2P project. To learn more about I2P,
visit [Get I2P](https://geti2p.net)

7
PLUGINS.md Normal file
View File

@@ -0,0 +1,7 @@
[./i2p.plugins.tor-manager-linux-386.su3](./i2p.plugins.tor-manager-linux-386.su3)
[./i2p.plugins.tor-manager-windows-amd64.su3](./i2p.plugins.tor-manager-windows-amd64.su3)
[./i2p.plugins.tor-manager-darwin-arm64.su3](./i2p.plugins.tor-manager-darwin-arm64.su3)
[./i2p.plugins.tor-manager-linux-arm64.su3](./i2p.plugins.tor-manager-linux-arm64.su3)
[./i2p.plugins.tor-manager-linux-amd64.su3](./i2p.plugins.tor-manager-linux-amd64.su3)
[./i2p.plugins.tor-manager-windows-386.su3](./i2p.plugins.tor-manager-windows-386.su3)
[./i2p.plugins.tor-manager-darwin-amd64.su3](./i2p.plugins.tor-manager-darwin-amd64.su3)

129
PREMISE.md Normal file
View File

@@ -0,0 +1,129 @@
Rationale for Non-Standard modifications to Tor Browser for I2P Browsing and Local Administration
=================================================================================================
This system prefers the Tor Browser for browsing the I2P network because any sane assessment of the
situation indicates that Tor Browser is the best choice for browsing HTTP/S services(web sites) in
a secure and private way at this time. However, we must make non-recommended changes to the Tor Browser
to make it work with I2P. This document concerns those changes and why they make sense for I2P Browsing,
Mixed I2P/Tor browsing, and I2P/Outproxy browsing.
The Basics:
-----------
The bare-minimum requirement to browse I2P using the Tor Browser is to add the following items to the
`user.js` file in your profile directory.
```javascript
user_pref("network.proxy.no_proxies_on", "127.0.0.1:7657,localhost:7657,127.0.0.1:7662,localhost:7662,127.0.0.1:7669,localhost:7669");
user_pref("extensions.torbutton.use_nontor_proxy", true);
user_pref("extensions.torlauncher.start_tor", false);
user_pref("extensions.torlauncher.prompt_at_startup", false);
user_pref("network.proxy.type", 1);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 4444);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 4444);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 4444);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 4444);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("browser.startup.homepage", "about:blank");
```
However, to do so would then break your Tor Browser's ability to connect to Tor in normal, non-I2P cirumstances.
This is not desirable, so instead we place a `user.js` and `prefs.js` file in a fresh profile directory, in advance
of the user starting the Tor Browser. Which brings us to the most important thing:
### RULE ZERO: Preserve Normal Tor Browser Functionality when the user requests Tor Browser
If the user requests Tor Browser, we do not interfere in any way. We just start Tor Browser normally. I2P operation
is always separated to it's own profile.
Beside that, we make the remaining changes which are specified in the [i2p.firefox](https://i2pgit.org/i2p-hackers/i2p.firefox)
`user.js` and `prefs.js` file. This is a decision made to match the `i2p.firefox` profile as closely as possible,
however it may not be advisable. The question is "When running in I2P mode, are we trying to look like Tor Browser?"
If so, then we need to cut the user.js down to *just this section* but if not, then we should probably leave it alone.
IMO, it is not feasible to make our modifications to Tor Browser entirely invisible. I2P
Defending from Attacks Unique to Mixed Tor/I2P Environment:
-----------------------------------------------------------
The major risk with using I2P and Tor together in the same browser is that the identify of a user on one network
may leak across the networks, i.e. an onion site learns the identify of an I2P client tunnel or an I2P site learns
the identity of a Tor client. This can mean A) Cryptographic identity or B) ISP identity. ISP identity is largely
defended against by Tor Browser's extensive attention to proxy obedience, but we must be careful not to break this.
Cryptographic identity, as presented by `X-I2P-*` headers in I2P for example, is easier for an attacker to gain.
In order to defend against these kinds of attacks, when running in I2P mode this system adds several extensions to
the Tor Browser. In addition to NoScript and HTTPS Everywhere, which are offered by Tor Browser, in I2P mode the
following extensions will be added:
1. I2P in Private Browsing
2. Onion in Container Browsing
3. JS Restrictor
4. uBlock Origin
5. LocalCDN - Fork of Decentraleyes
and optionally,
6. Actually Work Offline
#### Extensions? Isn't it bad to add extensions to Tor Browser?
> Well yes, if you're browsing Tor or the Web, and you're sure that you are starting with a common fingerprint.
However I2P has a *"fragmented"* fingerprint, and mixed Tor/I2P browsing creates an intrinsically *uncommon*
fingerprint. We can only benefit, in terms of security, from unifying upon a configuration(and thus a common
fingerprint).
> The danger in adding extensions to Tor Browser lies in the fact that you become a unique character among Tor
Browser users for using that extension. If *everyone* in your anonymity set, i.e. mixed Tor/I2P users uses the
same extensions when browsing I2P in Tor Browser, then you are not more unique for using the extensions.
> This experimental extension set is therefore designed to prevent known attacks on mixed I2P/Tor Browser users
and optimize Tor Browser running in Mixed Tor/I2P mode for I2P use. You should assume that it makes you look
like other users of this configuration, **not** like the Tor Browser.
### Protecting Network Boundaries:
I2P is normally administered via a WebUI(The "Router Console"), which the user sometimes views in the same
browser they use to visit remote sites. It is essential to prevent sites from being able to access information
from this WebUI and other locally running sites.
Clearnet sites will remain in the `firefox-default` container, but as soon as the firefox-default container
requests a `*.onion` or `*.i2p` site, it will be instantly containerized. Tor Browser's identity management
tooling controls clearnet tabs, and they are proxied using the default I2P outproxy or outproxy plugin.
#### Implemented in Extensions:
- JS Restrictor: Prevents any non-local host from using Javascript to connect to the localhost.
- I2P in Private Browsing: Places I2P browsing into it's own Container Tab where requests to `*.onion` resources
are automatically dropped.
- Onion in Container Tabs: Places .onion browsing into it's own Container Tab where requests to `*.i2p` resources
are automatically dropped.
### Limiting Clearnet Accesses
I2P has been designed primarily with an in-network approach. It therefore makes sense to limit the use
of a "Backup" clearnet access like Tor or an outproxy. This should have the added benefit of an improved UX for
I2P browser users by blocking ads and speeding up access to resources that would normally be hosted by CDN's.
#### Implemented in Extensions
- uBlock Origin: Block ads, and by extension much malvertising. Reduce the potential of an attacker using an
advertising network to deliver an attack to I2P users. Prevent ad networks from using their reach to build
profiles of I2P users. And there's no point serving ads to I2P users through an outproxy.
- LocalCDN - Fork of Decentraleyes: LocalCDN is an extension in your browsing that acts as a cache of resources
which would normally be provided by CDN's operated by companies that operate on the clearnet. Using LocalCDN
for our browsing prevents a malfunctioning outproxy from affecting site functionality, decreases the load on
outproxy operators, and improves UX by making sites load faster.
- Actually Work Offline: It is possible to pass the `-offline` flag `-i2pconfig` flag to load an additonal
extension wherein *all non-localhost requests* are immediately dropped and the browser cannot reach remote sites
until restarted.
Other Reasons to put Extensions in Tor Browser for Our Purposes
---------------------------------------------------------------
- Announce our non-default configuration loudly to the user by making changes to the UI.
* Unrelated to extensions: Additionally, apply the environment variable: `TOR_HIDE_BROWSER_LOGO=1` for all non-Tor
uses.

157
README.md
View File

@@ -1,69 +1,172 @@
# i2p.plugins.tor-updater
A Tor package updater and runner as an I2P Plugin. This plugin is
still being changed rapidly but it should be usable on most Linux
distributions as of 23 Jan, 2022.
usable on Windows, Linux, and OSX, as is the freestanding binary.
This also functions as a freestanding update for the Tor Browser
Bundle and is capable of configuring Tor Browser from the terminal
and updating it without running it, should the user choose to operate
this way.
Usage:
------
```sh
Usage of ./i2p.plugins.tor-manager-linux-amd64:
-arch string
OS/arch to download (default "64")
-i2pbrowser
Open I2P in Tor Browser
-lang string
Language to download
-os string
OS/arch to download (default "linux")
-torbrowser
Open Tor Browser
```
See [Usage](USAGE.md) for command-line usage. When used from the Terminal,
it acts as a cross-platform Tor Browser installer and wrapper, which adds
non-Tor specific options.
[HTML version](usage.html)
Plugin:
-------
Clearnet visitor? You'll need to use the [Github Releases Mirror](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/).
- [i2p.plugins.tor-manager-linux-386](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-linux-386.su3)
- [i2p.plugins.tor-manager-windows-amd64](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-windows-amd64.su3)
- [i2p.plugins.tor-manager-darwin-arm64](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-darwin-arm64.su3)
- [i2p.plugins.tor-manager-linux-amd64](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-linux-amd64.su3)
- [i2p.plugins.tor-manager-windows-386](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-windows-386.su3)
- [i2p.plugins.tor-manager-darwin-amd64](https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/download/0.0.4/i2p.plugins.tor-manager-darwin-amd64.su3)
Status:
-------
![Screenshot 2](screenshot-console.png)
Linux: Usable, most things work.
Windows: Unstable, mostly usable, does not work in some important cirumstances, cannot run from a flash drive
OSX: Unstable, untested, not usable, WIP.
Linux: Usable, everything implemented works.
Windows: Usable, everything implemented works.
OSX: Usable, everything implemented works.
Other systems are not targeted and should use a Tor binary built from source,
provided by TPO or, their prefered package management system and not this plugin.
The plugin will not start a Tor instance if a SOCKS proxy is open on port 9050.
![Screenshot](screenshot.png)
![Screenshot](screenshot-i2pbrowser.png)
### Primary Goals
1. Ship known-good public keys, download a current Tor for the platform in the background, authenticate it, and launch it only if necessary.
- Works on Windows, Linux, probably also OSX
- Works on Windows, Linux, OSX
2. Supervise Tor as a ShellService plugin to I2P
- Works on Linux
- Works on Linux, Windows, OSX
3. Keep Tor up-to-date
- Works on Windows, Linux, probably also OSX
- Works on Windows, Linux, OSX
4. Work as an I2P Plugin OR as a freestanding app to be compatible with all I2P distributions
- Works on Linux, probably works on Windows
- Works on Linux, Windows, OSX
5. Download Tor Browser from an in-I2P mirror(or one of a network of in-I2P mirrors)
- Not done
### Secondary Goals:
1. Launch Tor Browser
- Works on Linux
- Works on Linux, Windows, OSX
2. Configure and launch Tor browser for use with I2P
- Works on Linux, probably also Windows, probably not OSX yet.
- Works on Linux, Windows, OSX
#### Optional Features I might add if there is interest
1. Mirror the files which it downloads to an I2P Site
- Works on Windows, Linux, OSX
2. Mirror the files which it downloads to I2P torrents
- Not done
3. Set up an onion site which announces an I2P mirror exists
- Not done
4. Use Bittorrent-over-I2P to download the Tor Browser software
- Not Done
5. Import libi2pd and offer the use of an embedded i2pd router.
- Not done.
6. Option to use BRB in a thread as an in-I2P replacement for `mibbit` IRC client.
- Not done.
### Usage as a Library
[More information at the GoDoc](https://pkg.go.dev/i2pgit.org/idk/i2p.plugins.tor-manager)
This is also useful as a library for downloading a Tor Browser Bundle. This API
isn't really stable, more "stabilizing." Feel free to use it, but it may still
change a little.
To create a new instance, use:
``` Go
client, err = tbserve.NewClient(*verbose, *lang, *system, *arch, &content)
```
Customize the client using the exposed variables and methods:
``` Go
client.Host = *host
client.Port = *port
client.TBS.Profile = &content
client.TBS.PassThroughArgs = flag.Args()
```
And serve the controller:
``` Go
if err := client.Serve(); err != nil {
log.Fatal(err)
}
```
### Similar Projects:
- https://github.com/micahflee/torbrowser-launcher
- https://github.com/whonix/tb-updater
- [https://github.com/micahflee/torbrowser-launcher](https://github.com/micahflee/torbrowser-launcher)
- [https://github.com/whonix/tb-updater](https://github.com/whonix/tb-updater)
- Probably about 200 or so bespoke scripts written and abandoned by hackers over the years, search github
#### Why this is Better than those projects(A.K.A Why didn't you just use...)
##### [TorBrowser Launcher](https://github.com/micahfleee/torbrowser-launcher)
i2p.plugins.tor-manager is in many ways a clone of Tor Browser Launcher by Micah Lee,
it reproduces all of TBL's functionality for downloading, verifying, and running
Tor Browser. In particular Micah's project deserves credit for the AppArmor profiles,
which were used in the apparmor profile generator functionality and will probably
continue to be the upstream example which I use in my code. Micah's also already got
a PPA, a FlatPak, a Snap, an `.rpm` and a bunch of other stuff that provides, through
packaging, a better way to deal with updates to his software and a better way to deal
with the supply chain for many users. There is no reason that `i2p.plugins.tor-manager`
cannot do this, in fact it's easier for us than it is for Micah, but this project is
about a month and a half old and his is several years old. I haven't done a bunch of
packages yet.
Improvements on Tor Browser Launcher include:
- Does not require GPG to be in the `$PATH` or on the system at all
- Capable of managing a long-running Tor service without also running the Tor Browser
- Works everywhere Tor Browser does, not just Linux. Including:
Linux, Mac, Windows, AMD64, X86, and M1
- Embeds all required resources into a single binary which unpacks itself to a directory
of the user's choice. Never touches any other directory.
- Easy to package by placing a single static binary into a boilerplate package.
- Automatically generate an AppArmor profile which works for custom installation directory
- Accepts a custom profile argument without interfering with normal Tor Browser
functionality.
- Bundles a "Extra" profiles for I2P browsing, non-Anonymous browsing, and
offline/localhost-only browsing.
- Automatically organize multiple Tor Browser profiles for different networks(I2P,
Clearnet) and discourage accidental mixing.
- Optional TAILS mode, adds uBlock Origin to Tor Browser
- Embeds an i2pd router in case the host system doesn't have an I2P router
- No python. Language wars are stupid, but so is python.
#### [TB-Updater(Whonix)](https://github.com/whonix/tb-updater)
tb-updater is generally only useful on Linux systems and especially Debian-based systems,
and only recieves serious testing within the Whonix system itself. It's a highly specialized
tool in some ways, depending on packages which must be installed and repositories which must
be configured. For their purposes, this is probably a good thing, Whonix's raison d'etre is
to carefully configure every aspect of their system to be as anonymous and secure as possible,
and their approach deals with supply-chain issues which `i2p.plugins.tor-manager` can only
deal with in **packaging** and not by adding features to the launcher itself. Therefore, while
most of the improvements on Tor Browser Launcher also apply to TB-Updater, the
`i2p.plugins.tor-manager` and `tb-launcher` are actually less directly comparable.
<a href="https://www.flaticon.com/free-icons/garlic" title="garlic icons">Garlic icons created by Icongeek26 - Flaticon</a>
<a href="https://www.flaticon.com/free-icons/onion" title="onion icons">Onion icons created by Freepik - Flaticon</a>
### More Screenshots:
- ![Screenshot](screenshot.png)
- ![Screenshot](screenshot-dark.png)

115
USAGE.md Normal file
View File

@@ -0,0 +1,115 @@
Tor(And sometimes Firefox) Manager for I2P
===========================================
## Usage: i2p.plugins.tor-manager [options]
### Options:
```sh
Usage: i2p.plugins.tor-manager [options]
Downloads, verifies and unpacks Tor Browser. Manages the Tor Browser
system in environments where Tor is not in use.
Options:
Usage of ./i2p.plugins.tor-manager:
-apparmor
Generate apparmor rules
-arch string
OS/arch to download (default "64")
-bemirror
Act as an in-I2P mirror when you're done downloading
-clearnet
Use clearnet (no Tor or I2P)
-directory string
Directory operate in
-help
Print help
-host string
Host to serve on (default "127.0.0.1")
-i2pbrowser
Open I2P in Tor Browser
-i2pconfig
Open I2P routerconsole in Tor Browser with javscript enabled and non-routerconsole sites disabled
-lang string
Language to download
-offline
Work offline. Differs from Firefox's offline mode in that cannot be disabled until the browser is closed.
-os string
OS/arch to download (default "linux")
-port int
Port to serve on (default 7695)
-profile string
use a custom profile path, normally blank
-shortcuts
Create desktop shortcuts
-torbrowser
Open Tor Browser
-verbose
Verbose output
-watch-profiles string
Monitor and control these Firefox profiles. Temporarily Unused.
Usage: ./firefox.real [ options ... ] [URL]
where options include:
X11 options
--display=DISPLAY X display to use
--sync Make X calls synchronous
--g-fatal-warnings Make all warnings fatal
Firefox options
-h or --help Print this message.
-v or --version Print Firefox version.
--full-version Print Firefox version, build and platform build ids.
-P <profile> Start with <profile>.
--profile <path> Start with profile at <path>.
--migration Start with migration wizard.
--ProfileManager Start with ProfileManager.
--no-remote (default) Do not accept or send remote commands; implies
--new-instance.
--allow-remote Accept and send remote commands.
--new-instance Open new instance, not a new window in running instance.
--safe-mode Disables extensions and themes for this session.
--MOZ_LOG=<modules> Treated as MOZ_LOG=<modules> environment variable,
overrides it.
--MOZ_LOG_FILE=<file> Treated as MOZ_LOG_FILE=<file> environment variable,
overrides it. If MOZ_LOG_FILE is not specified as an
argument or as an environment variable, logging will be
written to stdout.
--headless Run without a GUI.
--browser Open a browser window.
--new-window <url> Open <url> in a new window.
--new-tab <url> Open <url> in a new tab.
--private-window <url> Open <url> in a new private window.
--preferences Open Preferences dialog.
--screenshot [<path>] Save screenshot to <path> or in working directory.
--window-size width[,height] Width and optionally height of screenshot.
--search <term> Search <term> with your default search engine.
--setDefaultBrowser Set this app as the default browser.
--first-startup Run post-install actions before opening a new window.
--kiosk Start the browser in kiosk mode.
--jsconsole Open the Browser Console.
--jsdebugger [<path>] Open the Browser Toolbox. Defaults to the local build
but can be overridden by a firefox path.
--wait-for-jsdebugger Spin event loop until JS debugger connects.
Enables debugging (some) application startup code paths.
Only has an effect when `--jsdebugger` is also supplied.
--devtools Open DevTools on initial load.
--start-debugger-server [ws:][ <port> | <path> ] Start the devtools server on
a TCP port or Unix domain socket path. Defaults to TCP port
6000. Use WebSocket protocol if ws: prefix is specified.
--recording <file> Record drawing for a given URL.
--recording-output <file> Specify destination file for a drawing recording.
--remote-debugging-port [<port>] Start the Firefox remote agent,
which is a low-level debugging interface based on the CDP protocol.
Defaults to listen on localhost:9222.
Tor Browser Script Options
--verbose Display Tor and Firefox output in the terminal
--log [file] Record Tor and Firefox output in file (default: tor-browser.log)
--detach Detach from terminal and run Tor Browser in the background.
--register-app Register Tor Browser as a desktop app for this user
--unregister-app Unregister Tor Browser as a desktop app for this user
```

325
apparmor_linux.go Normal file
View File

@@ -0,0 +1,325 @@
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
tbget "i2pgit.org/idk/i2p.plugins.tor-manager/get"
)
// Generates files corresponding to:
// https://github.com/micahflee/torbrowser-launcher/blob/develop/apparmor/tunables/torbrowser
func generateTunables() (string, error) {
var returnable string
userHome, err := os.UserHomeDir()
if err != nil {
return "", err
}
if *verbose {
log.Println("Generating tunables for apparmor")
}
installDir := strings.Replace(client.TBD.BrowserDir(), userHome, "@{HOME}", 1)
returnable += "@{torbrowser_installation_dir} = " + installDir + "\n"
returnable += "@{torbrowser_home_dir} = " + installDir + "/Browser\n"
return returnable, nil
}
func generateTorProfile() (string, error) {
var returnable string
userHome, err := os.UserHomeDir()
if err != nil {
return "", err
}
if *verbose {
log.Println("Generating Tor profile for apparmor")
}
torBrowserExecutable := strings.Replace(filepath.Join(client.TBD.BrowserDir(), "Browser", "TorBrowser", "Tor", "tor"), userHome, "@{HOME}", 1)
returnable += `#include <tunables/global>
#include <tunables/torbrowser>
@{torbrowser_tor_executable} = ` + torBrowserExecutable + `
profile torbrowser_tor @{torbrowser_tor_executable} {
#include <abstractions/base>
network netlink raw,
network tcp,
network udp,
/etc/host.conf r,
/etc/nsswitch.conf r,
/etc/passwd r,
/etc/resolv.conf r,
owner @{torbrowser_home_dir}/TorBrowser/Tor/tor mr,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/ rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/** rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/lock rwk,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so.* mr,
# Support some of the included pluggable transports
owner @{torbrowser_home_dir}/TorBrowser/Tor/PluggableTransports/** rix,
@{PROC}/sys/net/core/somaxconn r,
#include <abstractions/ssl_certs>
# Silence file_inherit logs
deny @{torbrowser_home_dir}/{browser/,}omni.ja r,
deny @{torbrowser_home_dir}/{browser/,}features/*.xpi r,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/.parentlock rw,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/extensions/*.xpi r,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/startupCache/* r,
# Silence logs from included pluggable transports
deny /etc/hosts r,
deny /etc/services r,
@{PROC}/sys/kernel/random/uuid r,
/sys/devices/system/cpu/ r,
# OnionShare compatibility
/tmp/onionshare/** rw,
#include <local/torbrowser.Tor.tor>
}`
return returnable, nil
}
func generateFirefoxProfile() (string, error) {
var returnable string
userHome, err := os.UserHomeDir()
if err != nil {
return "", err
}
if *verbose {
log.Println("Generating Firefox profile for apparmor")
}
firefoxBrowserExecutable := strings.Replace(filepath.Join(client.TBD.BrowserDir(), "Browser", "firefox.real"), userHome, "@{HOME}", 1)
returnable += `#include <tunables/global>
#include <tunables/torbrowser>
@{i2pbrowser_home_dir} = ` + strings.Replace(filepath.Join(tbget.UNPACK_PATH(), "i2p.firefox"), userHome, "@{HOME}", 1) + `
@{torbrowser_firefox_executable} = ` + firefoxBrowserExecutable + `
profile torbrowser_firefox @{torbrowser_firefox_executable} {
#include <abstractions/audio>
#include <abstractions/dri-enumerate>
#include <abstractions/gnome>
#include <abstractions/ibus>
#include <abstractions/mesa>
#include <abstractions/opencl>
#include if exists <abstractions/vulkan>
# Uncomment the following lines if you want to give the Tor Browser read-write
# access to most of your personal files.
# #include <abstractions/user-download>
# @{HOME}/ r,
# Audio support
/{,usr/}bin/pulseaudio Pixr,
#dbus,
network netlink raw,
network tcp,
ptrace (trace) peer=@{profile_name},
signal (receive, send) set=("term") peer=@{profile_name},
deny /etc/host.conf r,
deny /etc/hosts r,
deny /etc/nsswitch.conf r,
deny /etc/os-release r,
deny /etc/resolv.conf r,
deny /etc/passwd r,
deny /etc/group r,
deny /etc/mailcap r,
/etc/osxhine-id r,
/var/lib/dbus/osxhine-id r,
/dev/ r,
/dev/shm/ r,
owner @{PROC}/@{pid}/cgroup r,
owner @{PROC}/@{pid}/environ r,
owner @{PROC}/@{pid}/fd/ r,
owner @{PROC}/@{pid}/mountinfo r,
owner @{PROC}/@{pid}/stat r,
owner @{PROC}/@{pid}/status r,
owner @{PROC}/@{pid}/task/*/stat r,
@{PROC}/sys/kernel/random/uuid r,
owner @{torbrowser_installation_dir}/ r,
owner @{torbrowser_installation_dir}/* r,
owner @{torbrowser_installation_dir}/.** rwk,
owner @{torbrowser_installation_dir}/update.test/ rwk,
owner @{torbrowser_home_dir}/.** rwk,
owner @{torbrowser_home_dir}/ rw,
owner @{torbrowser_home_dir}/** rwk,
owner @{torbrowser_home_dir}.bak/ rwk,
owner @{torbrowser_home_dir}.bak/** rwk,
owner @{torbrowser_home_dir}/*.so mr,
owner @{torbrowser_home_dir}/.cache/fontconfig/ rwk,
owner @{torbrowser_home_dir}/.cache/fontconfig/** rwkl,
owner @{torbrowser_home_dir}/browser/** r,
owner @{torbrowser_home_dir}/{,browser/}components/*.so mr,
owner @{torbrowser_home_dir}/Downloads/ rwk,
owner @{torbrowser_home_dir}/Downloads/** rwk,
owner @{torbrowser_home_dir}/firefox rix,
owner @{torbrowser_home_dir}/{,TorBrowser/UpdateInfo/}updates/[0-9]*/* rw,
owner @{torbrowser_home_dir}/{,TorBrowser/UpdateInfo/}updates/[0-9]*/{,MozUpdater/bgupdate/}updater ix,
owner @{torbrowser_home_dir}/updater ix,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/.parentwritetest rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/profiles.ini r,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/{,**} rwk,
owner @{torbrowser_home_dir}/TorBrowser/Data/fontconfig/fonts.conf r,
owner @{torbrowser_home_dir}/fonts/* l,
owner @{torbrowser_home_dir}/TorBrowser/Tor/tor px,
owner @{torbrowser_home_dir}/TorBrowser/Tor/ r,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so.* mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/libstdc++/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/libstdc++/*.so.* mr,
owner @{i2pbrowser_home_dir}/i2p.firefox/{,**} rwk,
# parent Firefox process when restarting after upgrade, Web Content processes
owner @{torbrowser_firefox_executable} pxmr -> torbrowser_firefox,
/etc/mailcap r,
/etc/mime.types r,
/usr/share/ r,
/usr/share/glib-2.0/schemas/gschemas.compiled r,
/usr/share/mime/ r,
/usr/share/themes/ r,
/usr/share/applications/** rk,
/usr/share/gnome/applications/ r,
/usr/share/gnome/applications/kde4/ r,
/usr/share/poppler/cMap/ r,
# Distribution homepage
/usr/share/homepage/ r,
/usr/share/homepage/** r,
/sys/bus/pci/devices/ r,
@{sys}/devices/pci[0-9]*/**/irq r,
/sys/devices/system/cpu/ r,
/sys/devices/system/cpu/present r,
/sys/devices/system/node/ r,
/sys/devices/system/node/node[0-9]*/meminfo r,
/sys/fs/cgroup/cpu,cpuacct/{,user.slice/}cpu.cfs_quota_us r,
deny /sys/devices/virtual/block/*/uevent r,
# Should use abstractions/gstreamer instead once merged upstream
/etc/udev/udev.conf r,
/run/udev/data/+pci:* r,
/sys/devices/pci[0-9]*/**/uevent r,
owner /{dev,run}/shm/shmfd-* rw,
# Required for multiprocess Firefox (aka Electrolysis, i.e. e10s)
owner /{dev,run}/shm/org.chromium.* rw,
owner /dev/shm/org.mozilla.ipc.[0-9]*.[0-9]* rw, # for Chromium IPC
# Required for Wayland display protocol support
owner /dev/shm/wayland.mozilla.ipc.[0-9]* rw,
# Silence denial logs about permissions we don't need
deny @{HOME}/.cache/fontconfig/ rw,
deny @{HOME}/.cache/fontconfig/** rw,
deny @{HOME}/.config/gtk-2.0/ rw,
deny @{HOME}/.config/gtk-2.0/** rw,
deny @{PROC}/@{pid}/net/route r,
deny /sys/devices/system/cpu/cpufreq/policy[0-9]*/cpuinfo_max_freq r,
deny /sys/devices/system/cpu/*/cache/index[0-9]*/size r,
deny /run/user/[0-9]*/dconf/user rw,
deny /usr/bin/lsb_release x,
# Silence denial logs about PulseAudio
deny /etc/pulse/client.conf r,
deny /usr/bin/pulseaudio x,
# KDE 4
owner @{HOME}/.kde/share/config/* r,
# Xfce4
/etc/xfce4/defaults.list r,
/usr/share/xfce4/applications/ r,
# u2f (tested with Yubikey 4)
/sys/class/ r,
/sys/bus/ r,
/sys/class/hidraw/ r,
/run/udev/data/c24{5,7,9}:* r,
/dev/hidraw* rw,
# Yubikey NEO also needs this:
/sys/devices/**/hidraw/hidraw*/uevent r,
# Needed for Firefox sandboxing via unprivileged user namespaces
capability sys_admin,
capability sys_chroot,
owner @{PROC}/@{pid}/{gid,uid}_map w,
owner @{PROC}/@{pid}/setgroups w,
# Remove these rules once we can assume abstractions/vulkan is recent enough
# to include them
/etc/glvnd/egl_vendor.d/{*,.json} r,
/usr/share/glvnd/egl_vendor.d/{,*.json} r,
#include <local/torbrowser.Browser.firefox>
}
`
return returnable, nil
}
func GenerateAppArmor() error {
if tunables, err := generateTunables(); err == nil {
path := filepath.Join(tbget.UNPACK_PATH(), "tunables.torbrowser.apparmor")
if *verbose {
fmt.Printf("Writing %s\n", path)
}
if err := ioutil.WriteFile(path, []byte(tunables), 0644); err != nil {
return err
}
if *verbose {
fmt.Printf("%s", tunables)
}
} else {
return err
}
if torProfile, err := generateTorProfile(); err == nil {
path := filepath.Join(tbget.UNPACK_PATH(), "torbrowser.Tor.tor.apparmor")
if *verbose {
fmt.Printf("Writing %s\n", path)
}
if err := ioutil.WriteFile(path, []byte(torProfile), 0644); err != nil {
return err
}
if *verbose {
fmt.Printf("%s", torProfile)
}
} else {
return err
}
if firefoxProfile, err := generateFirefoxProfile(); err == nil {
path := filepath.Join(tbget.UNPACK_PATH(), "torbrowser.Browser.firefox.apparmor")
if *verbose {
fmt.Printf("Writing %s\n", path)
}
if err := ioutil.WriteFile(path, []byte(firefoxProfile), 0644); err != nil {
return err
}
if *verbose {
fmt.Printf("%s", firefoxProfile)
}
} else {
return err
}
return nil
}

12
debian/changelog vendored
View File

@@ -1,3 +1,15 @@
i2p.plugins.tor-manager (0.0.5-1) UNRELEASED; urgency=medium
* Re-Enable Debian Package
-- idk <hankhill19580@gmail.com> Fri, 11 Feb 2022 00:2:06 -0500
i2p.plugins.tor-manager (0.0.3-1) UNRELEASED; urgency=medium
* Capability/User-friendliness enhancements
-- idk <hankhill19580@gmail.com> Thu, 29 Jan 2022 01:21:22 -0500
i2p.plugins.tor-manager (0.0.2-1) UNRELEASED; urgency=medium
* Initial release

View File

@@ -0,0 +1,4 @@
i2ptorbrowser.desktop /usr/share/applications/i2ptorbrowser.desktop
torbrowser.desktop /usr/share/applications/torbrowser.desktop
garliconion.png /var/lib/i2pbrowser/icons/garliconion.png
onion.png /var/lib/i2pbrowser/icons/onion.png

4
debian/rules vendored
View File

@@ -1,6 +1,8 @@
#!/usr/bin/make -f
export DH_GOLANG_INSTALL_EXTRA := tor-browser/TPO-signing-key.pub tor-browser/unpack/i2p.firefox ../../../github.com/jchavannes/go-pgp/pgp ../../../github.com/justinas/nosurf
export DH_GOLANG_INSTALL_EXTRA := tor-browser/TPO-signing-key.pub tor-browser/unpack/awo@eyedeekay.github.io.xpi tor-browser/unpack/i2p.firefox tor-browser/unpack/i2p.firefox.config onion.png garliconion.png i2ptorbrowser.desktop torbrowser.desktop vendor
export DH_GOLANG_INSTALL_EXTRA += ../../../github.com/jchavannes/go-pgp/pgp ../../../github.com/justinas/nosurf ../../../github.com/eyedeekay/sam3 ../../../github.com/eyedeekay/goSam ../../../github.com/eyedeekay/checki2cp ../../../github.com/eyedeekay/go-i2cp ../../../github.com/eyedeekay/sam-forwarder ../../../github.com/eyedeekay/httptunnel ../../../github.com/itchio/damage ../../../github.com/itchio/headway ../../../github.com/otiai10/copy ../../../github.com/gtank/cryptopasta ../../../github.com/boreq/friendlyhash ../../../github.com/phayes/freeport ../../../github.com/mwitkow/go-http-dialer ../../../github.com/zieckey/goini ../../../howett.net/plist/
#
%:

View File

@@ -2,5 +2,21 @@ tor-browser/lib/shellservice.jar
tor-browser/unpack/i2p.firefox/extensions/https-everywhere-eff@eff.org.xpi
tor-browser/unpack/i2p.firefox/extensions/i2ppb@eyedeekay.github.io.xpi
tor-browser/unpack/i2p.firefox/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi
tor-browser/unpack/i2p.firefox/extensions/onioncbt@eyedeekay.github.io.xpi
tor-browser/unpack/i2p.firefox/extensions/uBlock0@raymondhill.net.xpi
tor-browser/unpack/i2p.firefox/extensions/{b86e4813-687a-43e6-ab65-0bde4ab75758}.xpi
tor-browser/unpack/i2p.firefox/extensions/jsr@javascriptrestrictor.xpi
tor-browser/unpack/i2p.firefox/storage-sync.sqlite
tor-browser/unpack/i2p.firefox.config/extensions/https-everywhere-eff@eff.org.xpi
tor-browser/unpack/i2p.firefox.config/extensions/i2ppb@eyedeekay.github.io.xpi
tor-browser/unpack/i2p.firefox.config/extensions/{73a6fe31-595d-460b-a920-fcc0f8843232}.xpi
tor-browser/unpack/i2p.firefox.config/storage-sync.sqlite
tor-browser/unpack/awo@eyedeekay.github.io.xpi
tor-browser/TPO-signing-key.pub
onion.png
icon/icon.png
garliconion.png
screenshot.png
screenshot-dark.png
screenshot-console.png
screenshot-i2pbrowser.png

View File

@@ -0,0 +1,174 @@
#include <tunables/global>
#include <tunables/torbrowser>
@{i2pbrowser_home_dir} = @{HOME}/.i2p/plugins/i2p.plugins.tor-manager/unpack/i2p.firefox
@{torbrowser_firefox_executable} = @{HOME}/.i2p/plugins/i2p.plugins.tor-manager/unpack/tor-browser_en-US/Browser/firefox.real
profile torbrowser_firefox @{torbrowser_firefox_executable} {
#include <abstractions/audio>
#include <abstractions/dri-enumerate>
#include <abstractions/gnome>
#include <abstractions/ibus>
#include <abstractions/mesa>
#include <abstractions/opencl>
#include if exists <abstractions/vulkan>
# Uncomment the following lines if you want to give the Tor Browser read-write
# access to most of your personal files.
# #include <abstractions/user-download>
# @{HOME}/ r,
# Audio support
/{,usr/}bin/pulseaudio Pixr,
#dbus,
network netlink raw,
network tcp,
ptrace (trace) peer=@{profile_name},
signal (receive, send) set=("term") peer=@{profile_name},
deny /etc/host.conf r,
deny /etc/hosts r,
deny /etc/nsswitch.conf r,
deny /etc/os-release r,
deny /etc/resolv.conf r,
deny /etc/passwd r,
deny /etc/group r,
deny /etc/mailcap r,
/etc/machine-id r,
/var/lib/dbus/machine-id r,
/dev/ r,
/dev/shm/ r,
owner @{PROC}/@{pid}/cgroup r,
owner @{PROC}/@{pid}/environ r,
owner @{PROC}/@{pid}/fd/ r,
owner @{PROC}/@{pid}/mountinfo r,
owner @{PROC}/@{pid}/stat r,
owner @{PROC}/@{pid}/status r,
owner @{PROC}/@{pid}/task/*/stat r,
@{PROC}/sys/kernel/random/uuid r,
owner @{torbrowser_installation_dir}/ r,
owner @{torbrowser_installation_dir}/* r,
owner @{torbrowser_installation_dir}/.** rwk,
owner @{torbrowser_installation_dir}/update.test/ rwk,
owner @{torbrowser_home_dir}/.** rwk,
owner @{torbrowser_home_dir}/ rw,
owner @{torbrowser_home_dir}/** rwk,
owner @{torbrowser_home_dir}.bak/ rwk,
owner @{torbrowser_home_dir}.bak/** rwk,
owner @{torbrowser_home_dir}/*.so mr,
owner @{torbrowser_home_dir}/.cache/fontconfig/ rwk,
owner @{torbrowser_home_dir}/.cache/fontconfig/** rwkl,
owner @{torbrowser_home_dir}/browser/** r,
owner @{torbrowser_home_dir}/{,browser/}components/*.so mr,
owner @{torbrowser_home_dir}/Downloads/ rwk,
owner @{torbrowser_home_dir}/Downloads/** rwk,
owner @{torbrowser_home_dir}/firefox rix,
owner @{torbrowser_home_dir}/{,TorBrowser/UpdateInfo/}updates/[0-9]*/* rw,
owner @{torbrowser_home_dir}/{,TorBrowser/UpdateInfo/}updates/[0-9]*/{,MozUpdater/bgupdate/}updater ix,
owner @{torbrowser_home_dir}/updater ix,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/.parentwritetest rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/profiles.ini r,
owner @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/{,**} rwk,
owner @{torbrowser_home_dir}/TorBrowser/Data/fontconfig/fonts.conf r,
owner @{torbrowser_home_dir}/fonts/* l,
owner @{torbrowser_home_dir}/TorBrowser/Tor/tor px,
owner @{torbrowser_home_dir}/TorBrowser/Tor/ r,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so.* mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/libstdc++/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/libstdc++/*.so.* mr,
owner @{i2pbrowser_home_dir}/i2p.firefox/{,**} rwk,
# parent Firefox process when restarting after upgrade, Web Content processes
owner @{torbrowser_firefox_executable} pxmr -> torbrowser_firefox,
/etc/mailcap r,
/etc/mime.types r,
/usr/share/ r,
/usr/share/glib-2.0/schemas/gschemas.compiled r,
/usr/share/mime/ r,
/usr/share/themes/ r,
/usr/share/applications/** rk,
/usr/share/gnome/applications/ r,
/usr/share/gnome/applications/kde4/ r,
/usr/share/poppler/cMap/ r,
# Distribution homepage
/usr/share/homepage/ r,
/usr/share/homepage/** r,
/sys/bus/pci/devices/ r,
@{sys}/devices/pci[0-9]*/**/irq r,
/sys/devices/system/cpu/ r,
/sys/devices/system/cpu/present r,
/sys/devices/system/node/ r,
/sys/devices/system/node/node[0-9]*/meminfo r,
/sys/fs/cgroup/cpu,cpuacct/{,user.slice/}cpu.cfs_quota_us r,
deny /sys/devices/virtual/block/*/uevent r,
# Should use abstractions/gstreamer instead once merged upstream
/etc/udev/udev.conf r,
/run/udev/data/+pci:* r,
/sys/devices/pci[0-9]*/**/uevent r,
owner /{dev,run}/shm/shmfd-* rw,
# Required for multiprocess Firefox (aka Electrolysis, i.e. e10s)
owner /{dev,run}/shm/org.chromium.* rw,
owner /dev/shm/org.mozilla.ipc.[0-9]*.[0-9]* rw, # for Chromium IPC
# Required for Wayland display protocol support
owner /dev/shm/wayland.mozilla.ipc.[0-9]* rw,
# Silence denial logs about permissions we don't need
deny @{HOME}/.cache/fontconfig/ rw,
deny @{HOME}/.cache/fontconfig/** rw,
deny @{HOME}/.config/gtk-2.0/ rw,
deny @{HOME}/.config/gtk-2.0/** rw,
deny @{PROC}/@{pid}/net/route r,
deny /sys/devices/system/cpu/cpufreq/policy[0-9]*/cpuinfo_max_freq r,
deny /sys/devices/system/cpu/*/cache/index[0-9]*/size r,
deny /run/user/[0-9]*/dconf/user rw,
deny /usr/bin/lsb_release x,
# Silence denial logs about PulseAudio
deny /etc/pulse/client.conf r,
deny /usr/bin/pulseaudio x,
# KDE 4
owner @{HOME}/.kde/share/config/* r,
# Xfce4
/etc/xfce4/defaults.list r,
/usr/share/xfce4/applications/ r,
# u2f (tested with Yubikey 4)
/sys/class/ r,
/sys/bus/ r,
/sys/class/hidraw/ r,
/run/udev/data/c24{5,7,9}:* r,
/dev/hidraw* rw,
# Yubikey NEO also needs this:
/sys/devices/**/hidraw/hidraw*/uevent r,
# Needed for Firefox sandboxing via unprivileged user namespaces
capability sys_admin,
capability sys_chroot,
owner @{PROC}/@{pid}/{gid,uid}_map w,
owner @{PROC}/@{pid}/setgroups w,
# Remove these rules once we can assume abstractions/vulkan is recent enough
# to include them
/etc/glvnd/egl_vendor.d/{*,.json} r,
/usr/share/glvnd/egl_vendor.d/{,*.json} r,
#include <local/torbrowser.Browser.firefox>
}

View File

@@ -0,0 +1,46 @@
#include <tunables/global>
#include <tunables/torbrowser>
@{torbrowser_tor_executable} = @{HOME}/.i2p/plugins/i2p.plugins.tor-manager/unpack/tor-browser_en-US/Browser/TorBrowser/Tor/tor
profile torbrowser_tor @{torbrowser_tor_executable} {
#include <abstractions/base>
network netlink raw,
network tcp,
network udp,
/etc/host.conf r,
/etc/nsswitch.conf r,
/etc/passwd r,
/etc/resolv.conf r,
owner @{torbrowser_home_dir}/TorBrowser/Tor/tor mr,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/ rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/** rw,
owner @{torbrowser_home_dir}/TorBrowser/Data/Tor/lock rwk,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so mr,
owner @{torbrowser_home_dir}/TorBrowser/Tor/*.so.* mr,
# Support some of the included pluggable transports
owner @{torbrowser_home_dir}/TorBrowser/Tor/PluggableTransports/** rix,
@{PROC}/sys/net/core/somaxconn r,
#include <abstractions/ssl_certs>
# Silence file_inherit logs
deny @{torbrowser_home_dir}/{browser/,}omni.ja r,
deny @{torbrowser_home_dir}/{browser/,}features/*.xpi r,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/.parentlock rw,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/extensions/*.xpi r,
deny @{torbrowser_home_dir}/TorBrowser/Data/Browser/profile.default/startupCache/* r,
# Silence logs from included pluggable transports
deny /etc/hosts r,
deny /etc/services r,
@{PROC}/sys/kernel/random/uuid r,
/sys/devices/system/cpu/ r,
# OnionShare compatibility
/tmp/onionshare/** rw,
#include <local/torbrowser.Tor.tor>
}

View File

@@ -0,0 +1,2 @@
@{torbrowser_installation_dir} = @{HOME}/.i2p/plugins/i2p.plugins.tor-manager/unpack/tor-browser_en-US
@{torbrowser_home_dir} = @{HOME}/.i2p/plugins/i2p.plugins.tor-manager/unpack/tor-browser_en-US/Browser

16
firefox.html Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>i2p.plugins.tor-manager - Tor Binary Manager</title>
<link rel="stylesheet" type="text/css" href ="/style.css" />
</head>
<body>
<h1 id="running-in-clearnet-mode">Running in Clearnet Mode</h1>
<p>Tor Browser is configured to run without Tor, and will now use the non-anonymous web. It is also configured to use uBlock Origin. This allows you to use a hardened web browser for your non-anonymous tasks.</p>
<ul>
<li>To get started, perhaps try <a href="https://duckduckgo.com">DuckDuckGo</a></li>
<li>or <a href="https://privacyguides.org/">PrivacyGuides</a></li>
</ul>
<p>This wrapper has been developed for use with the I2P project. To learn more about I2P, visit <a href="https://geti2p.net">Get I2P</a></p>
</body>
</html>

BIN
garliconion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@@ -8,31 +8,67 @@ import (
"io"
"io/ioutil"
"log"
"net"
"net/http"
"net/url"
"os"
"os/exec"
"path"
"path/filepath"
"runtime"
"strings"
"time"
"github.com/cloudfoundry/jibber_jabber"
sam "github.com/eyedeekay/sam3/helper"
"github.com/itchio/damage"
"github.com/itchio/damage/hdiutil"
"github.com/itchio/headway/state"
"github.com/ulikunitz/xz"
"github.com/jchavannes/go-pgp/pgp"
"golang.org/x/crypto/openpgp"
)
var wd, _ = os.Getwd()
// WORKING_DIR is the working directory for the application.
var WORKING_DIR = ""
var UNPACK_PATH = filepath.Join(wd, "unpack")
var DOWNLOAD_PATH = filepath.Join(wd, "tor-browser")
// DefaultDir returns the default directory for the application.
func DefaultDir() string {
if WORKING_DIR == "" {
WORKING_DIR, _ = os.Getwd()
}
if !FileExists(WORKING_DIR) {
os.MkdirAll(WORKING_DIR, 0755)
}
wd, err := filepath.Abs(WORKING_DIR)
if err != nil {
log.Fatal(err)
}
return wd
}
// UNPACK_PATH returns the path to the unpacked files.
func UNPACK_PATH() string {
var UNPACK_PATH = filepath.Join(DefaultDir(), "unpack")
return UNPACK_PATH
}
// DOWNLOAD_PATH returns the path to the downloads.
func DOWNLOAD_PATH() string {
var DOWNLOAD_PATH = filepath.Join(DefaultDir(), "tor-browser")
return DOWNLOAD_PATH
}
// TOR_UPDATES_URL is the URL of the Tor Browser update list.
const TOR_UPDATES_URL string = "https://aus1.torproject.org/torbrowser/update_3/release/downloads.json"
var (
// DefaultIETFLang is the default language for the TBDownloader.
DefaultIETFLang, _ = jibber_jabber.DetectIETF()
)
// TBDownloader is a struct which manages browser updates
type TBDownloader struct {
UnpackPath string
DownloadPath string
@@ -42,14 +78,20 @@ type TBDownloader struct {
Profile *embed.FS
}
// OS is the operating system of the TBDownloader.
var OS = "linux"
// ARCH is the architecture of the TBDownloader.
var ARCH = "64"
// NewTBDownloader returns a new TBDownloader with the given language, using the TBDownloader's OS/ARCH pair
func NewTBDownloader(lang string, os, arch string, content *embed.FS) *TBDownloader {
OS = os
ARCH = arch
return &TBDownloader{
Lang: lang,
DownloadPath: DOWNLOAD_PATH,
UnpackPath: UNPACK_PATH,
DownloadPath: DOWNLOAD_PATH(),
UnpackPath: UNPACK_PATH(),
OS: os,
ARCH: arch,
Verbose: false,
@@ -57,6 +99,33 @@ func NewTBDownloader(lang string, os, arch string, content *embed.FS) *TBDownloa
}
}
// ServeHTTP serves the DOWNLOAD_PATH as a mirror
func (t *TBDownloader) ServeHTTP(w http.ResponseWriter, r *http.Request) {
r.URL.Path = strings.Replace(r.URL.Path, "..", "", -1)
ext := filepath.Ext(r.URL.Path)
if ext == ".json" {
w.Header().Set("Content-Type", "application/json")
if FileExists(filepath.Join(t.DownloadPath, "mirror.json")) {
http.ServeFile(w, r, filepath.Join(t.DownloadPath, "mirror.json"))
}
}
if FileExists(filepath.Join(t.DownloadPath, r.URL.Path)) {
http.ServeFile(w, r, filepath.Join(t.DownloadPath, r.URL.Path))
return
}
}
// Serve runs ServeHTTP on an I2P listener
func (t *TBDownloader) Serve() {
samlistener, err := sam.I2PListener("tor-mirror", "127.0.0.1:7656", "tor-mirror")
if err != nil {
log.Fatal(err)
}
defer samlistener.Close()
http.Serve(samlistener, t)
}
// GetRuntimePair returns the runtime.GOOS and runtime.GOARCH pair.
func (t *TBDownloader) GetRuntimePair() string {
if t.OS != "" && t.ARCH != "" {
return fmt.Sprintf("%s%s", t.OS, t.ARCH)
@@ -79,80 +148,138 @@ func (t *TBDownloader) GetRuntimePair() string {
default:
t.ARCH = "unknown"
}
return fmt.Sprintf("%s%s", t.OS, t.ARCH)
if t.OS != "osx" {
return fmt.Sprintf("%s%s", t.OS, t.ARCH)
}
return t.OS
}
// GetUpdater returns the updater for the given language, using the TBDownloader's OS/ARCH pair
// and only the defaults. It returns the URL of the updater and the detatched signature, or an error if one is not found.
func (t *TBDownloader) GetUpdater() (string, string, error) {
return t.GetUpdaterForLang(t.Lang)
}
// GetUpdaterForLang returns the updater for the given language, using the TBDownloader's OS/ARCH pair
// it expects ietf to be a language. It returns the URL of the updater and the detatched signature, or an error if one is not found.
func (t *TBDownloader) GetUpdaterForLang(ietf string) (string, string, error) {
jsonText, err := http.Get(TOR_UPDATES_URL)
if err != nil {
return "", "", fmt.Errorf("t.GetUpdaterForLang: %s", err)
}
defer jsonText.Body.Close()
return t.GetUpdaterForLangFromJson(jsonText.Body, ietf)
return t.GetUpdaterForLangFromJSON(jsonText.Body, ietf)
}
func (t *TBDownloader) GetUpdaterForLangFromJson(body io.ReadCloser, ietf string) (string, string, error) {
// GetUpdaterForLangFromJSON returns the updater for the given language, using the TBDownloader's OS/ARCH pair
// it expects body to be a valid json reader and ietf to be a language. It returns the URL of the updater and
// the detatched signature, or an error if one is not found.
func (t *TBDownloader) GetUpdaterForLangFromJSON(body io.ReadCloser, ietf string) (string, string, error) {
jsonBytes, err := io.ReadAll(body)
if err != nil {
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJson: %s", err)
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJSON: %s", err)
}
t.MakeTBDirectory()
if err = ioutil.WriteFile(filepath.Join(t.DownloadPath, "downloads.json"), jsonBytes, 0644); err != nil {
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJson: %s", err)
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJSON: %s", err)
}
return t.GetUpdaterForLangFromJsonBytes(jsonBytes, ietf)
return t.GetUpdaterForLangFromJSONBytes(jsonBytes, ietf)
}
// Log logs things if Verbose is true.
func (t *TBDownloader) Log(function, message string) {
if t.Verbose {
log.Println(fmt.Sprintf("%s: %s", function, message))
}
}
// MakeTBDirectory creates the tor-browser directory if it doesn't exist. It also unpacks a local copy of the TPO signing key.
func (t *TBDownloader) MakeTBDirectory() {
os.MkdirAll(t.DownloadPath, 0755)
path := filepath.Join("", "tor-browser", "TPO-signing-key.pub")
if !FileExists(path) {
bytes, err := t.Profile.ReadFile(path)
empath := path.Join("tor-browser", "TPO-signing-key.pub")
opath := filepath.Join(t.DownloadPath, "TPO-signing-key.pub")
if !FileExists(opath) {
t.Log("MakeTBDirectory()", "Initial TPO signing key not found, using the one embedded in the executable")
bytes, err := t.Profile.ReadFile(empath)
if err != nil {
log.Fatal(err)
}
ioutil.WriteFile(filepath.Join(t.DownloadPath, "TPO-signing-key.pub"), bytes, 0644)
t.Log("MakeTBDirectory()", "Writing TPO signing key to disk")
err = ioutil.WriteFile(opath, bytes, 0644)
if err != nil {
log.Fatal(err)
}
t.Log("MakeTBDirectory()", "Writing TPO signing key to disk complete")
}
empath = path.Join("tor-browser", "unpack", "awo@eyedeekay.github.io.xpi")
dpath := filepath.Join(t.DownloadPath, "awo@eyedeekay.github.io.xpi")
opath = filepath.Join(t.UnpackPath, "awo@eyedeekay.github.io.xpi")
if !FileExists(opath) {
t.Log("MakeTBDirectory()", "Initial TAWO XPI not found, using the one embedded in the executable")
bytes, err := t.Profile.ReadFile(empath)
if err != nil {
log.Fatal(err)
}
os.MkdirAll(filepath.Dir(dpath), 0755)
os.MkdirAll(filepath.Dir(opath), 0755)
t.Log("MakeTBDirectory()", "Writing AWO XPI to disk")
err = ioutil.WriteFile(opath, bytes, 0644)
if err != nil {
log.Fatal(err)
}
err = ioutil.WriteFile(dpath, bytes, 0644)
if err != nil {
log.Fatal(err)
}
t.Log("MakeTBDirectory()", "Writing AWO XPI disk complete")
}
}
func (t *TBDownloader) GetUpdaterForLangFromJsonBytes(jsonBytes []byte, ietf string) (string, string, error) {
// GetUpdaterForLangFromJSONBytes returns the updater for the given language, using the TBDownloader's OS/ARCH pair
// it expects jsonBytes to be a valid json string and ietf to be a language. It returns the URL of the updater and
// the detatched signature, or an error if one is not found.
func (t *TBDownloader) GetUpdaterForLangFromJSONBytes(jsonBytes []byte, ietf string) (string, string, error) {
t.MakeTBDirectory()
var dat map[string]interface{}
t.Log("GetUpdaterForLangFromJSONBytes()", "Parsing JSON")
if err := json.Unmarshal(jsonBytes, &dat); err != nil {
return "", "", fmt.Errorf("func (t *TBDownloader)Name: %s", err)
}
t.Log("GetUpdaterForLangFromJSONBytes()", "Parsing JSON complete")
if platform, ok := dat["downloads"]; ok {
rtp := t.GetRuntimePair()
if updater, ok := platform.(map[string]interface{})[rtp]; ok {
if langUpdater, ok := updater.(map[string]interface{})[ietf]; ok {
t.Log("GetUpdaterForLangFromJSONBytes()", "Found updater for language")
return langUpdater.(map[string]interface{})["binary"].(string), langUpdater.(map[string]interface{})["sig"].(string), nil
}
// If we didn't find the language, try splitting at the hyphen
lang := strings.Split(ietf, "-")[0]
if langUpdater, ok := updater.(map[string]interface{})[lang]; ok {
t.Log("GetUpdaterForLangFromJSONBytes()", "Found updater for backup language")
return langUpdater.(map[string]interface{})["binary"].(string), langUpdater.(map[string]interface{})["sig"].(string), nil
}
// If we didn't find the language after splitting at the hyphen, try the default
return t.GetUpdaterForLangFromJsonBytes(jsonBytes, t.Lang)
} else {
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJsonBytes: no updater for platform %s", rtp)
t.Log("GetUpdaterForLangFromJSONBytes()", "Last attempt, trying default language")
return t.GetUpdaterForLangFromJSONBytes(jsonBytes, t.Lang)
}
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJSONBytes: no updater for platform %s", rtp)
}
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJsonBytes: %s", ietf)
return "", "", fmt.Errorf("t.GetUpdaterForLangFromJSONBytes: %s", ietf)
}
// SingleFileDownload downloads a single file from the given URL to the given path.
// it returns the path to the downloaded file, or an error if one is encountered.
func (t *TBDownloader) SingleFileDownload(url, name string) (string, error) {
t.MakeTBDirectory()
path := filepath.Join(t.DownloadPath, name)
t.Log("SingleFileDownload()", fmt.Sprintf("Checking for updates %s to %s", url, path))
if !t.BotherToDownload(url, name) {
fmt.Printf("No updates required, skipping download of %s\n", name)
t.Log("SingleFileDownload()", "File already exists, skipping download")
return path, nil
}
t.Log("SingleFileDownload()", "Downloading file")
file, err := http.Get(url)
if err != nil {
return "", fmt.Errorf("SingleFileDownload: %s", err)
@@ -164,59 +291,58 @@ func (t *TBDownloader) SingleFileDownload(url, name string) (string, error) {
}
defer outFile.Close()
io.Copy(outFile, file.Body)
t.Log("SingleFileDownload()", "Downloading file complete")
return path, nil
}
// FileExists returns true if the given file exists. It will return true if used on an existing directory.
func FileExists(path string) bool {
_, err := os.Stat(path)
return !os.IsNotExist(err)
}
// BotherToDownload returns true if we need to download a file because we don't have an up-to-date
// version yet.
func (t *TBDownloader) BotherToDownload(url, name string) bool {
path := filepath.Join(t.DownloadPath, name)
if !FileExists(path) {
return true
}
defer ioutil.WriteFile(filepath.Join(t.DownloadPath, name+".last-url"), []byte(url), 0644)
lastUrl, err := ioutil.ReadFile(filepath.Join(t.DownloadPath, name+".last-url"))
lastURL, err := ioutil.ReadFile(filepath.Join(t.DownloadPath, name+".last-url"))
if err != nil {
return true
}
if string(lastUrl) == url {
if string(lastURL) == url {
return false
}
return true
}
// NamePerPlatform returns the name of the updater for the given platform with appropriate extensions.
func (t *TBDownloader) NamePerPlatform(ietf string) string {
extension := "tar.xz"
windowsonly := ""
switch runtime.GOOS {
case "darwin":
switch t.OS {
case "osx":
extension = "dmg"
case "windows":
windowsonly = "-installer-"
case "win":
windowsonly = "-installer"
extension = "exe"
}
return fmt.Sprintf("torbrowser%s-%s-%s.%s", windowsonly, t.GetRuntimePair(), ietf, extension)
}
// DownloadUpdater downloads the updater for the t.Lang. It returns
// the path to the downloaded updater and the downloaded detatched signature,
// or an error if one is encountered.
func (t *TBDownloader) DownloadUpdater() (string, string, error) {
binary, sig, err := t.GetUpdater()
if err != nil {
return "", "", fmt.Errorf("DownloadUpdater: %s", err)
}
sigpath, err := t.SingleFileDownload(sig, t.NamePerPlatform(t.Lang)+".asc")
if err != nil {
return "", "", fmt.Errorf("DownloadUpdater: %s", err)
}
binpath, err := t.SingleFileDownload(binary, t.NamePerPlatform(t.Lang))
if err != nil {
return "", sigpath, fmt.Errorf("DownloadUpdater: %s", err)
}
return binpath, sigpath, nil
return t.DownloadUpdaterForLang(t.Lang)
}
// DownloadUpdaterForLang downloads the updater for the given language, overriding
// t.Lang. It returns the path to the downloaded updater and the downloaded
// detatched signature, or an error if one is encountered.
func (t *TBDownloader) DownloadUpdaterForLang(ietf string) (string, string, error) {
binary, sig, err := t.GetUpdaterForLang(ietf)
if err != nil {
@@ -234,44 +360,71 @@ func (t *TBDownloader) DownloadUpdaterForLang(ietf string) (string, string, erro
return binpath, sigpath, nil
}
func (t *TBDownloader) UnpackUpdater(binpath string) (string, error) {
// BrowserDir returns the path to the directory where the browser is installed.
func (t *TBDownloader) BrowserDir() string {
return filepath.Join(t.UnpackPath, "tor-browser_"+t.Lang)
}
// UnpackUpdater unpacks the updater to the given path.
// it returns the path or an erorr if one is encountered.
func (t *TBDownloader) UnpackUpdater(binpath string) (string, error) {
t.Log("UnpackUpdater()", fmt.Sprintf("Unpacking %s", binpath))
if t.OS == "win" {
cmd := exec.Command("cmd", "/c", "start", "\""+t.UnpackPath+"\"", "\""+binpath+" /SD /D="+t.UnpackPath+"\"")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("UnpackUpdater: windows exec fail %s", err)
installPath := t.BrowserDir()
if !FileExists(installPath) {
t.Log("UnpackUpdater()", "Windows updater, running silent NSIS installer")
t.Log("UnpackUpdater()", fmt.Sprintf("Running %s %s %s", binpath, "/S", "/D="+installPath))
cmd := exec.Command(binpath, "/S", "/D="+installPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("UnpackUpdater: windows exec fail %s", err)
}
}
return installPath, nil
}
if t.OS == "osx" {
cmd := exec.Command("open", "-W", "-n", "-a", "\""+t.UnpackPath+"\"", "\""+binpath+"\"")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("UnpackUpdater: osx open/mount fail %s", err)
binpath = "tor-browser/torbrowser-osx64-en-US.dmg"
log.Println("hdiutil", "mount", "\""+binpath+"\"")
//cmd := exec.Command("open", "-W", "-n", "-a", "\""+binpath+"\"")
//cmd := exec.Command("hdiutil", "attach", "\""+binpath+"\"")
consumer := &state.Consumer{
OnMessage: func(lvl string, msg string) {
log.Printf("[%s] %s", lvl, msg)
},
}
host := hdiutil.NewHost(consumer)
if !FileExists(t.BrowserDir()) {
_, err := damage.Mount(host, binpath, t.BrowserDir())
if err != nil {
return "", fmt.Errorf("UnpackUpdater: osx open/mount fail %s", err)
}
}
//cmd.Stdout = os.Stdout
//cmd.Stderr = os.Stderr
//err := cmd.Run()
//TODO: this might just need to be a hardcoded app path
return t.BrowserDir(), nil
}
if FileExists(filepath.Join(t.UnpackPath, "tor-browser_"+t.Lang)) {
return filepath.Join(t.UnpackPath, "tor-browser_"+t.Lang), nil
if FileExists(t.BrowserDir()) {
return t.BrowserDir(), nil
}
fmt.Printf("Unpacking %s %s\n", binpath, t.UnpackPath)
os.MkdirAll(t.UnpackPath, 0755)
UNPACK_DIRECTORY, err := os.Open(t.UnpackPath)
if err != nil {
return "", fmt.Errorf("UnpackUpdater: %s", err)
return "", fmt.Errorf("UnpackUpdater: directory error %s", err)
}
defer UNPACK_DIRECTORY.Close()
xzfile, err := os.Open(binpath)
if err != nil {
return "", fmt.Errorf("UnpackUpdater: %s", err)
return "", fmt.Errorf("UnpackUpdater: XZFile error %s", err)
}
defer xzfile.Close()
xzReader, err := xz.NewReader(xzfile)
if err != nil {
return "", fmt.Errorf("UnpackUpdater: %s", err)
return "", fmt.Errorf("UnpackUpdater: XZReader error %s", err)
}
tarReader := tar.NewReader(xzReader)
for {
@@ -280,7 +433,7 @@ func (t *TBDownloader) UnpackUpdater(binpath string) (string, error) {
break
}
if err != nil {
return "", fmt.Errorf("UnpackUpdater: %s", err)
return "", fmt.Errorf("UnpackUpdater: Tar looper Error %s", err)
}
if header.Typeflag == tar.TypeDir {
os.MkdirAll(filepath.Join(UNPACK_DIRECTORY.Name(), header.Name), 0755)
@@ -289,7 +442,7 @@ func (t *TBDownloader) UnpackUpdater(binpath string) (string, error) {
filename := filepath.Join(UNPACK_DIRECTORY.Name(), header.Name)
file, err := os.Create(filename)
if err != nil {
return "", fmt.Errorf("UnpackUpdater: %s", err)
return "", fmt.Errorf("UnpackUpdater: Tar unpacker error %s", err)
}
defer file.Close()
io.Copy(file, tarReader)
@@ -300,9 +453,12 @@ func (t *TBDownloader) UnpackUpdater(binpath string) (string, error) {
fmt.Printf("Unpacked %s\n", header.Name)
}
}
return filepath.Join(t.UnpackPath, "tor-browser_"+t.Lang), nil
return t.BrowserDir(), nil
}
// CheckSignature checks the signature of the updater.
// it returns an error if one is encountered. If not, it
// runs the updater and returns an error if one is encountered.
func (t *TBDownloader) CheckSignature(binpath, sigpath string) (string, error) {
var pkBytes []byte
var pk *openpgp.Entity
@@ -329,7 +485,84 @@ func (t *TBDownloader) CheckSignature(binpath, sigpath string) (string, error) {
return "", fmt.Errorf("CheckSignature: %s", err)
}
// BoolCheckSignature turns CheckSignature into a bool.
func (t *TBDownloader) BoolCheckSignature(binpath, sigpath string) bool {
_, err := t.CheckSignature(binpath, sigpath)
return err == nil
}
// TestHTTPDefaultProxy returns true if the I2P proxy is up or blocks until it is.
func TestHTTPDefaultProxy() bool {
return TestHTTPProxy("127.0.0.1", "4444")
}
// Seconds increments the seconds and displays the number of seconds every 10 seconds
func Seconds(now int) int {
time.Sleep(time.Second)
if now == 10 {
return 0
}
return now + 1
}
// TestHTTPBackupProxy returns true if the I2P backup proxy is up or blocks until it is.
func TestHTTPBackupProxy() bool {
now := 0
limit := 0
for {
_, err := net.Listen("tcp", "127.0.0.1:4444")
if err != nil {
log.Println("SAM HTTP proxy is open", err)
return true
} else {
if now == 0 {
log.Println("Waiting for HTTP Proxy", (10 - limit), "remaining attempts")
limit++
}
now = Seconds(now)
}
if limit == 10 {
break
}
}
return false
}
// TestHTTPProxy returns true if the proxy at host:port is up or blocks until it is.
func TestHTTPProxy(host, port string) bool {
now := 0
limit := 0
for {
proxy := hTTPProxy(host, port)
if proxy {
return true
} else {
if now == 0 {
log.Println("Waiting for HTTP Proxy", (10 - limit), "remaining attempts")
limit++
}
now = Seconds(now)
}
if limit == 10 {
break
}
}
return false
}
func hTTPProxy(host, port string) bool {
proxyURL, err := url.Parse("http://" + host + ":" + port)
if err != nil {
log.Panic(err)
}
myClient := &http.Client{Transport: &http.Transport{Proxy: http.ProxyURL(proxyURL)}}
resp, err := myClient.Get("http://proxy.i2p/")
if err == nil {
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err == nil {
return strings.Contains(string(body), "I2P HTTP proxy OK")
}
}
return false
}

243
get/getffox.go Normal file
View File

@@ -0,0 +1,243 @@
package tbget
import (
"archive/tar"
"fmt"
"io"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"strings"
"github.com/jchavannes/go-pgp/pgp"
"github.com/ulikunitz/xz"
"golang.org/x/crypto/openpgp"
)
// FFOX_UPDATES_URL is the URL to the Firefox updates page
const FFOX_UPDATES_URL string = "https://download.mozilla.org/?product=firefox-latest&os=%s&lang=%s"
// GetLatestFirefoxVersionURL returns the URL to the latest Firefox version for the given os and lang
func (t *TBDownloader) GetLatestFirefoxVersionURL(os, lang string) string {
return fmt.Sprintf(FFOX_UPDATES_URL, t.GetRuntimePair(), lang)
}
// GetLatestFirefoxVersionLinuxSigURL returns the URL to the latest Firefox version detatched signature for the given os and lang
func (t *TBDownloader) GetLatestFirefoxVersionLinuxSigURL(os, lang string) string {
return t.GetLatestFirefoxVersionURL(os, lang) + ".asc"
}
// GetFirefoxUpdater gets the updater URL for the t.Lang. It returns
// the URL, a detatched sig if available for the platform, or an error
func (t *TBDownloader) GetFirefoxUpdater() (string, string, error) {
return t.GetLatestFirefoxVersionURL(t.OS, t.Lang), t.GetLatestFirefoxVersionLinuxSigURL(t.OS, t.Lang), nil
}
// GetFirefoxUpdaterForLang gets the updater URL for the given language, overriding
// the t.Lang. It returns the URL, a detatched sig if available for the platform, or an error
func (t *TBDownloader) GetFirefoxUpdaterForLang(ietf string) (string, string, error) {
return t.GetLatestFirefoxVersionURL(t.OS, ietf), t.GetLatestFirefoxVersionLinuxSigURL(t.OS, ietf), nil
}
// SendFirefoxVersionHEADRequest sends a HEAD request to the Firefox version URL
func (t *TBDownloader) SendFirefoxVersionHEADRequest() (string, error) {
url := t.GetLatestFirefoxVersionURL(t.OS, t.Lang)
req, err := http.NewRequest("HEAD", url, nil)
if err != nil {
return "", fmt.Errorf("t.SendFirefoxVersionHEADRequest: %s", err)
}
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return "", fmt.Errorf("t.SendFirefoxVersionHEADRequest: %s", err)
}
defer resp.Body.Close()
if resp.StatusCode != 200 {
return "", fmt.Errorf("t.SendFirefoxVersionHEADRequest: %s", resp.Status)
}
return resp.Header.Get("Location"), nil
}
// ExtractFirefoxVersion extracts the Firefox version from the updater URL
func (t *TBDownloader) ExtractFirefoxVersion() (string, error) {
url, err := t.SendFirefoxVersionHEADRequest()
if err != nil {
return "", fmt.Errorf("t.ExtractFirefoxVersion: %s", err)
}
// get the last element of the URL
url = strings.Split(url, "/")[len(strings.Split(url, "/"))-1]
// remove all file extensions
url = strings.Replace(url, ".tar.xz", "", -1)
url = strings.Replace(url, ".tar.bz2", "", -1)
url = strings.Replace(url, ".tar.gz", "", -1)
url = strings.Replace(url, ".zip", "", -1)
url = strings.Replace(url, ".exe", "", -1)
url = strings.Replace(url, ".msi", "", -1)
url = strings.Replace(url, ".dmg", "", -1)
return url, nil
}
// NamePerPlatformFirefox returns the name of the Firefox package per platform.
func (t *TBDownloader) NamePerPlatformFirefox(ietf string) string {
extension := "tar.xz"
windowsonly := ""
switch t.OS {
case "osx":
extension = "dmg"
case "win":
windowsonly = "-setup"
extension = "exe"
}
return fmt.Sprintf("firefox%s-%s-%s.%s", windowsonly, t.GetRuntimePair(), ietf, extension)
}
// FirefoxBrowserDir returns the path to the directory where the Firefox browser is installed.
func (t *TBDownloader) FirefoxBrowserDir() string {
return filepath.Join(t.UnpackPath, "firefox_"+t.Lang)
}
// UnpackFirefox unpacks the Firefox package to the t.FirefoxBrowserDir()
func (t *TBDownloader) UnpackFirefox(binpath string) (string, error) {
t.Log("UnpackFirefox()", fmt.Sprintf("Unpacking %s", binpath))
if t.OS == "win" {
installPath := t.FirefoxBrowserDir()
if !FileExists(installPath) {
t.Log("UnpackFirefox()", "Windows updater, running silent NSIS installer")
t.Log("UnpackFirefox()", fmt.Sprintf("Running %s %s %s", binpath, "/S", "/D="+installPath))
cmd := exec.Command(binpath, "/S", "/D="+installPath)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("UnpackFirefox: windows exec fail %s", err)
}
}
return installPath, nil
}
if t.OS == "osx" {
cmd := exec.Command("open", "-W", "-n", "-a", "\""+t.UnpackPath+"\"", "\""+binpath+"\"")
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
if err != nil {
return "", fmt.Errorf("UnpackFirefox: osx open/mount fail %s", err)
}
//TODO: this might just need to be a hardcoded app path
return t.UnpackPath, nil
}
if FileExists(t.FirefoxBrowserDir()) {
return t.FirefoxBrowserDir(), nil
}
fmt.Printf("Unpacking %s %s\n", binpath, t.UnpackPath)
os.MkdirAll(t.UnpackPath, 0755)
UNPACK_DIRECTORY, err := os.Open(t.UnpackPath)
if err != nil {
return "", fmt.Errorf("UnpackFirefox: directory error %s", err)
}
defer UNPACK_DIRECTORY.Close()
xzfile, err := os.Open(binpath)
if err != nil {
return "", fmt.Errorf("UnpackFirefox: XZFile error %s", err)
}
defer xzfile.Close()
xzReader, err := xz.NewReader(xzfile)
if err != nil {
return "", fmt.Errorf("UnpackFirefox: XZReader error %s", err)
}
tarReader := tar.NewReader(xzReader)
for {
header, err := tarReader.Next()
if err == io.EOF {
break
}
if err != nil {
return "", fmt.Errorf("UnpackFirefox: Tar looper Error %s", err)
}
if header.Typeflag == tar.TypeDir {
os.MkdirAll(filepath.Join(UNPACK_DIRECTORY.Name(), header.Name), 0755)
continue
}
filename := filepath.Join(UNPACK_DIRECTORY.Name(), header.Name)
file, err := os.Create(filename)
if err != nil {
return "", fmt.Errorf("UnpackFirefox: Tar unpacker error %s", err)
}
defer file.Close()
io.Copy(file, tarReader)
mode := header.FileInfo().Mode()
//remember to chmod the file afterwards
file.Chmod(mode)
if t.Verbose {
fmt.Printf("Unpacked %s\n", header.Name)
}
}
return t.FirefoxBrowserDir(), nil
}
// DownloadFirefoxUpdater downloads the updater for the t.Lang. It returns
// the path to the downloaded updater and the downloaded detatched signature,
// or an error if one is encountered.
func (t *TBDownloader) DownloadFirefoxUpdater() (string, string, error) {
return t.DownloadFirefoxUpdaterForLang(t.Lang)
}
// DownloadFirefoxUpdaterForLang downloads the updater for the given language, overriding
// t.Lang. It returns the path to the downloaded updater and the downloaded
// detatched signature, or an error if one is encountered.
func (t *TBDownloader) DownloadFirefoxUpdaterForLang(ietf string) (string, string, error) {
binary, sig, err := t.GetFirefoxUpdaterForLang(ietf)
if err != nil {
return "", "", fmt.Errorf("DownloadUpdater: %s", err)
}
sigpath := ""
if t.OS == "linux" {
sigpath, err = t.SingleFileDownload(sig, t.NamePerPlatformFirefox(ietf)+".asc")
if err != nil {
return "", "", fmt.Errorf("DownloadUpdater: %s", err)
}
}
binpath, err := t.SingleFileDownload(binary, t.NamePerPlatformFirefox(ietf))
if err != nil {
return "", "", fmt.Errorf("DownloadUpdater: %s", err)
}
return binpath, sigpath, nil
}
// CheckFirefoxSignature checks the signature of the updater.
// it returns an error if one is encountered. If not, it
// runs the updater and returns an error if one is encountered.
func (t *TBDownloader) CheckFirefoxSignature(binpath, sigpath string) (string, error) {
if t.OS == "linux" {
var pkBytes []byte
var pk *openpgp.Entity
var sig []byte
var bin []byte
var err error
if pkBytes, err = ioutil.ReadFile(filepath.Join(t.DownloadPath, "TPO-signing-key.pub")); err != nil {
return "", fmt.Errorf("CheckSignature pkBytes: %s", err)
}
if pk, err = pgp.GetEntity(pkBytes, nil); err != nil {
return "", fmt.Errorf("CheckSignature pk: %s", err)
}
if bin, err = ioutil.ReadFile(binpath); err != nil {
return "", fmt.Errorf("CheckSignature bin: %s", err)
}
if sig, err = ioutil.ReadFile(sigpath); err != nil {
return "", fmt.Errorf("CheckSignature sig: %s", err)
}
if err = pgp.Verify(pk, sig, bin); err != nil {
return t.UnpackUpdater(binpath)
//return nil
}
}
err := fmt.Errorf("signature check failed")
return "", fmt.Errorf("CheckSignature: %s", err)
}
// BoolCheckFirefoxSignature turns CheckFirefoxSignature into a bool.
func (t *TBDownloader) BoolCheckFirefoxSignature(binpath, sigpath string) bool {
_, err := t.CheckFirefoxSignature(binpath, sigpath)
return err == nil
}

30
go.mod
View File

@@ -3,20 +3,42 @@ module i2pgit.org/idk/i2p.plugins.tor-manager
go 1.17
require (
aead.dev/minisign v0.2.0
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21
github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc
github.com/go-ole/go-ole v1.2.6
github.com/jchavannes/go-pgp v0.0.0-20200131171414-e5978e6d02b4
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce
)
require (
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e // indirect
github.com/eyedeekay/go-i2cp v0.0.0-20190716135428-6d41bed718b0 // indirect
github.com/eyedeekay/goSam v0.32.31-0.20210415231611-c6d9c0e340b8 // indirect
github.com/eyedeekay/sam-forwarder v0.0.0-20190908210105-71ca8cd65fda // indirect
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69 // indirect
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 // indirect
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 // indirect
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26 // indirect
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
)
require (
github.com/eyedeekay/checki2cp v0.0.21
github.com/eyedeekay/httptunnel v0.0.0-20210508193128-6e9606d6eb24
github.com/eyedeekay/sam3 v0.32.32
github.com/itchio/damage v0.0.0-20190703135837-76df725fc766
github.com/itchio/headway v0.0.0-20200301160421-e15721f23905
github.com/justinas/nosurf v1.1.1
github.com/mitchellh/go-ps v1.0.0
github.com/onsi/ginkgo v1.16.5 // indirect
github.com/onsi/gomega v1.17.0 // indirect
github.com/otiai10/copy v1.7.0
github.com/pkg/errors v0.9.1 // indirect
github.com/russross/blackfriday v1.6.0
github.com/ulikunitz/xz v0.5.10 // indirect
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/ulikunitz/xz v0.5.10
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
howett.net/plist v1.0.0 // indirect
)
replace github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc => ./go-i2pd

342
go.sum
View File

@@ -1,14 +1,215 @@
aead.dev/minisign v0.2.0 h1:kAWrq/hBRu4AARY6AlciO83xhNnW9UaC8YipS2uhLPk=
aead.dev/minisign v0.2.0/go.mod h1:zdq6LdSd9TbuSxchxwhpA9zEb9YXcVGoE8JakuiGaIQ=
cloud.google.com/go v0.16.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
crawshaw.io/littleboss v0.0.0-20190317185602-8957d0aedcce/go.mod h1:TIbCAHgttUfOKudw59Il7Z0XIlitzo228/mtwMe4vPM=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/brotli v0.0.0-20190621154722-5f990b63d2d6/go.mod h1:+lx6/Aqd1kLJ1GQfkvOnaZ1WGmLpMpbprPuIOOZX30U=
github.com/andybalholm/brotli v1.0.0/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 h1:DDGfHa7BWjL4YnC6+E63dPcxHo2sUxDIu8g3QgEJdRY=
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869/go.mod h1:Ekp36dRnpXw/yCqJaO+ZrUyxD+3VXMFFr56k5XYrpB4=
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e h1:2q8XPjAYhXX8H71AoAPdgBrCUA3HPhC4ax8XHrTsY6I=
github.com/boreq/friendlyhash v0.0.0-20190522010448-1ca64b3ca69e/go.mod h1:y80zLCg0QS5u3fJKeF2rwpezcyZuCpZpbFcWv6Pn98w=
github.com/bradfitz/gomemcache v0.0.0-20170208213004-1952afaa557d/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21 h1:tuijfIjZyjZaHq9xDUh0tNitwXshJpbLkqMOJv4H3do=
github.com/cloudfoundry/jibber_jabber v0.0.0-20151120183258-bcc4c8345a21/go.mod h1:po7NpZ/QiTKzBKyrsEAxwnTamCoh8uDk/egRpQ7siIc=
github.com/d5/tengo v1.24.3/go.mod h1:VhLq8Q2QFhCIJO3NhvM934qOThykMqJi9y9Siqd1ocQ=
github.com/danfragoso/thdwb v0.0.0-20191106005607-18cfeb88e782/go.mod h1:IXu355OpbfEz78+tgu81vte3YA/MEWQKBu/dXod4NM0=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dsnet/compress v0.0.1/go.mod h1:Aw8dCMJ7RioblQeTqt88akK31OvO8Dhf5JflhBbQEHo=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/eyedeekay/checki2cp v0.0.17/go.mod h1:kdHq1LqZxi2qarfyospSHrh4Aju5SydX+2AzlJKhSJM=
github.com/eyedeekay/checki2cp v0.0.21 h1:DVer7H6RffCWS8Bo3+J6EyppUc1y8lvApKdQnAiVj5g=
github.com/eyedeekay/checki2cp v0.0.21/go.mod h1:75sGwBgnacHmxxx8RQ7BIeS0gu5Pw916gFb2c80OUTc=
github.com/eyedeekay/eephttpd v0.0.0-20190903000420-52f5a8485a4e/go.mod h1:wFPQsNBnY95LkuujFEZARo7slafRwoF0D97FFHBoZro=
github.com/eyedeekay/go-fpw v0.0.0-20200512022837-c8b4dcdc74d4/go.mod h1:RyCx7KuH+5ryvIpUF7SpxiChLtjeuPbVFCIzf8shIFc=
github.com/eyedeekay/go-i2cp v0.0.0-20190716135428-6d41bed718b0 h1:rnn9OlD/3+tATEZNuiMR1C84O5CX8bZL2qqgttprKrw=
github.com/eyedeekay/go-i2cp v0.0.0-20190716135428-6d41bed718b0/go.mod h1:+P0fIhkqIYjo7exMJRTlSteRMbRyHbiBiKw+YlPWk+c=
github.com/eyedeekay/go-i2pcontrol v0.0.0-20200110011336-510cca77e350/go.mod h1:bhIQsVpbNNXMtcoZ9UF4hLQleOjaCgKGXiRRhNc8TOA=
github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc h1:ozp8Cxn9nsFF+p4tMcE63G0Kx+2lEywlCW0EvtISEZg=
github.com/eyedeekay/go-i2pd v0.0.0-20220213070306-9807541b2dfc/go.mod h1:Yg8xCWRLyq0mezPV+xJygBhJCf7wYsIdXbYGQk5tnW8=
github.com/eyedeekay/goSam v0.1.1-0.20190814204230-d4c9b8c57dd6/go.mod h1:kGTfZrncJ4CwMX3d1qA6bcMJTOcuTbOqgWg7WrFNAQ0=
github.com/eyedeekay/goSam v0.32.31-0.20210415231611-c6d9c0e340b8 h1:w8gZ6aGy4H3pwRI7seUvUrVPhzrrEid2X8G2DcH7Yvk=
github.com/eyedeekay/goSam v0.32.31-0.20210415231611-c6d9c0e340b8/go.mod h1:UgJnih/LpotwKriwVPOEa6yPDM2NDdVrKfLtS5DOLPE=
github.com/eyedeekay/httptunnel v0.0.0-20190831065052-9eab288b8a82/go.mod h1:VeXBZz04xj4eUGAcD8ygn2WFxY/dAvRbSNYMWoDzMxc=
github.com/eyedeekay/httptunnel v0.0.0-20190831071439-0ff3d5f798fb/go.mod h1:SnCAM9CskhwSFkzDfh+H5yNTbvhcTeKekkuX0ejCcSk=
github.com/eyedeekay/httptunnel v0.0.0-20210508193128-6e9606d6eb24 h1:Xkifu/edD0lcNzS7vMf6sS05Hk6Umv21aosiKwULpCk=
github.com/eyedeekay/httptunnel v0.0.0-20210508193128-6e9606d6eb24/go.mod h1:EASp//e3tfDMsChn4Xkwq9BdZBMHOR4QeMV6eEW64vY=
github.com/eyedeekay/i2pd v0.3.0-1stbinrelease.0.20210702172028-5d01ee95810a/go.mod h1:4qJhWn+yNrWRbqFHhU8kl7JgbcW1hm3PMgvlPlxO3gg=
github.com/eyedeekay/outproxy v0.0.0-20190908174238-22bd71d43733/go.mod h1:jUBr6XRbiuUBe/sSbVdO5upU4mp8842bdpXDsQY54Rc=
github.com/eyedeekay/portcheck v0.0.0-20190218044454-bb8718669680/go.mod h1:8VVIH19/CU2VFJB8P6e58Mo9nvDqqKgllS0oQY3F83U=
github.com/eyedeekay/ramp v0.0.0-20190429201811-305b382042ab/go.mod h1:h7mvUAMgZ/rtRDUOkvKTK+8LnDMeUhJSoa5EPdB51fc=
github.com/eyedeekay/sam-forwarder v0.0.0-20190814201550-7c0d7cb0d56c/go.mod h1:Ptrm1d4a3KC5/cN264Gn6OntYOmcuJ8Pkyd7+hA01gw=
github.com/eyedeekay/sam-forwarder v0.0.0-20190831071254-d67c0c0e311f/go.mod h1:u4K8aGwSIuMSQ/OzsH7zkshnEvCQgUupfexLXZIjsDI=
github.com/eyedeekay/sam-forwarder v0.0.0-20190905212604-029317222e15/go.mod h1:kFP6jkqHUTGGW/nMUZLnRonkPWE9fyEc8/eSU1CqTFg=
github.com/eyedeekay/sam-forwarder v0.0.0-20190908210105-71ca8cd65fda h1:Mpi42j17o2vXGZNmTAkv5pwXzVFKWkkAviSAjSF4xPs=
github.com/eyedeekay/sam-forwarder v0.0.0-20190908210105-71ca8cd65fda/go.mod h1:crhQdi30uVnJ5Xn3JAPoMxvyWg6yo5LOfH4JZ+VIaxA=
github.com/eyedeekay/sam3 v0.0.0-20190613034117-99ad6522ebe3/go.mod h1:Vrxh+71E3HVYqyRlT5Jg+E26sSuu8UNTLB4p8qyT408=
github.com/eyedeekay/sam3 v0.0.0-20190730185140-f8d54526ea25/go.mod h1:Y3igFVzN4ybqkkpfUWULGhw7WRp8lieq0ORXbLBbcZM=
github.com/eyedeekay/sam3 v0.32.2/go.mod h1:Y3igFVzN4ybqkkpfUWULGhw7WRp8lieq0ORXbLBbcZM=
github.com/eyedeekay/sam3 v0.32.32 h1:9Ea1Ere5O8Clx8zYxKnvhrWy7R96Q4FvxlPskYf8VW0=
github.com/eyedeekay/sam3 v0.32.32/go.mod h1:qRA9KIIVxbrHlkj+ZB+OoxFGFgdKeGp1vSgPw26eOVU=
github.com/eyedeekay/zerobundle v0.0.0-20210508181003-86893b4491fd/go.mod h1:wkwqUXsii7d0hSXusO/wbGmOQyYP7ltVrfanWnBNJj8=
github.com/eyedeekay/zerobundle/parts/0 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:r0sUb3XQ87Ae7PIdPjjLqNph/7nCWj5dkEWrUeDCaVI=
github.com/eyedeekay/zerobundle/parts/1 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:DQDEE5G1HE4682/HCjTFgoXkT4uni5aKPdPe1GmnVGU=
github.com/eyedeekay/zerobundle/parts/10 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Sw6+vGYrpTF6t+zkRqGOoDHwDcyodYskXAw7srFGZrE=
github.com/eyedeekay/zerobundle/parts/100 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:bNZ6JJe/MVVkkM+64mr7gdgQ1qFzRzQtUFpz3oCfMi0=
github.com/eyedeekay/zerobundle/parts/101 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:vgPII0Xmav3nfekQpFssUWpb6kREDK+l6Vri83fpSoE=
github.com/eyedeekay/zerobundle/parts/102 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:fZg6wtvONKTUdF1wcBa2gXSDkmwu2qhqAu/jLxo+X0k=
github.com/eyedeekay/zerobundle/parts/103 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:0wKW9QT91weSMmfNRlVhUuE64p7puotwDTHOdD2GRSw=
github.com/eyedeekay/zerobundle/parts/104 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:WIjhAmWWLHkJ0OVKlzRUNXtNwyigQ70oIoKaUgYnU5U=
github.com/eyedeekay/zerobundle/parts/105 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:X9tQlmz00TYyvHoZ/u5IDY0/fLZqc8oU9ZWi54CoUws=
github.com/eyedeekay/zerobundle/parts/106 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:KvO0TvBWLc2mcBWK6TsgBAd1dYAQkqEjMg96gJSxFVg=
github.com/eyedeekay/zerobundle/parts/107 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:uY1vIVZRq5liuaS1gLpU3I4j3Gj7qE8meScCHiH40Rc=
github.com/eyedeekay/zerobundle/parts/108 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:xidv/J6DUkbWa9kOgNFz4jtRdbcpA449TO9x6MkUAY8=
github.com/eyedeekay/zerobundle/parts/109 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:o56N6tVIxxDcV4Z+2ar+L8AzAdt8J2mbQ2aUrZAmeGY=
github.com/eyedeekay/zerobundle/parts/11 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:xSZAaT73v/UeBOchoyS1GcRYt7K/8Wtx5l8qdQrM/BA=
github.com/eyedeekay/zerobundle/parts/110 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:i6MvubcvtEVSpp3K8y/Yvok/fdDwpDGS6i2yfHxpYJc=
github.com/eyedeekay/zerobundle/parts/111 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:G4yXbYJRH18Slf2bHDIZgNXuVTZAEYkMFRu9gZW9uvw=
github.com/eyedeekay/zerobundle/parts/112 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:xuYUFBud30cylBgglW5NTbDXfIBkdIH/BrshqPVOCLE=
github.com/eyedeekay/zerobundle/parts/113 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:KNGpXq4wlwLcBIfALYxLpPGfGoC2pHxF4DZLuDLAFak=
github.com/eyedeekay/zerobundle/parts/114 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:vXjWbCkq5S5FWbj6wtEoB+JAJHZonPr54gYfFYdTVOE=
github.com/eyedeekay/zerobundle/parts/115 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:xUDSRuoNaNvIjJ/QcROei4yxbgr5iyDhdRrrgNbT0GU=
github.com/eyedeekay/zerobundle/parts/116 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:57gFtS8s3w8jwPq5HZ1sF6ki3yy8CqtaE8PRFE3ZYZ4=
github.com/eyedeekay/zerobundle/parts/117 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:8RXSO6J+gDPDLq29wV16TjQnllI2wgHVDorooCyyDxI=
github.com/eyedeekay/zerobundle/parts/118 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:nAfQ9hKFr4j/drwFOuTQ1J2Oa7iMMKaa9MsGjCZ4fEo=
github.com/eyedeekay/zerobundle/parts/119 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:x0huEOb1FID3/j6Gl+YIxpjQKvCsi64VYUStn/Z36vg=
github.com/eyedeekay/zerobundle/parts/12 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Suz5ZeHQoyqyejN6ib4xVv41GbeX7QaVx2aJloPtKwo=
github.com/eyedeekay/zerobundle/parts/120 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:EdX3Z9BX6FKCHzY5iLZLc8mg0sepJOLvMqpyTWlKN2s=
github.com/eyedeekay/zerobundle/parts/121 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:gJwUUhtZ3yQZOOh+9G/zX+o3/dddKD88h/kznKd/aq0=
github.com/eyedeekay/zerobundle/parts/122 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:dEVQlgXeRub+5KNF9dgY1V7xmpWQhf7R2ctGyfLaaWo=
github.com/eyedeekay/zerobundle/parts/123 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:5C5/PSxgNBUaqtZVGs90HfY4WGKnqAAzwpZ4zb/DrOY=
github.com/eyedeekay/zerobundle/parts/124 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:5QtS7UbUaYoVvy9tZ7tzGSXGfyWu2db/eyKw7dIsZBc=
github.com/eyedeekay/zerobundle/parts/125 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:2cuxBFEPEbnX/+DJvxrhqL2wqd16eqg4vqGwIfpY6zs=
github.com/eyedeekay/zerobundle/parts/126 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:wI5UXODaLhqiihdeuWQvSlfe/o80ODy9wPreM+YMMlA=
github.com/eyedeekay/zerobundle/parts/127 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Z/H5EP4z9K8QjYFD+Hus77LeKbyGHfHSlYuv0YfndDE=
github.com/eyedeekay/zerobundle/parts/13 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:ADzO1kazbQjE++4MI9E0cj+8iQaQ2Z9CDY92jmOwN5I=
github.com/eyedeekay/zerobundle/parts/14 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:p86GJgeD/DWgvGSZtjbOZ3MV5K2QM5ogPw8J6G2KnGY=
github.com/eyedeekay/zerobundle/parts/15 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:99yEf364z83eL+Lc99D2mM1opf0V0ZOhFsSk1NRfKi0=
github.com/eyedeekay/zerobundle/parts/16 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:HtODGKPRSOJuquzPxzlx8ZnSbRqLlfd0LaoHck8eBbE=
github.com/eyedeekay/zerobundle/parts/17 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:V4JvbHQpGbzVF+TSwiYKemlDZiZDiTagOi4CdD3ko+M=
github.com/eyedeekay/zerobundle/parts/18 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:YG5WucB1/4OT3rF2fjaFn+d794/SuOB6ygM5svHt6DA=
github.com/eyedeekay/zerobundle/parts/19 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:MQjDvYvkb97we1IgvDC08h8DEEoaSzYFEylzF6k6TRc=
github.com/eyedeekay/zerobundle/parts/2 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:9p2BrMPqcI+xpNXgEYrpLqP1OTVpCaf8+XagonwQ/7Q=
github.com/eyedeekay/zerobundle/parts/20 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:zpNWosRYVEq56TuF3kEm4MO7H6j5hzBSSs6BxAt7/HY=
github.com/eyedeekay/zerobundle/parts/21 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Z2y6IoTyoXc8E48zmbPSb+CQVRKLVhxE54ELA4vIUcc=
github.com/eyedeekay/zerobundle/parts/22 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:qQjn+oNwZqDo8qBme6evirUSOnJ8tRkUTnT4jfdFFe4=
github.com/eyedeekay/zerobundle/parts/23 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:zykZ0treCCwjaRQRycpvfmUiy4Fx/n+hfqA+nxqu7WU=
github.com/eyedeekay/zerobundle/parts/24 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:/Zj7pPESVRd3UZCS9HmzDuHV+CEauy3MKJwLQ+WDpwA=
github.com/eyedeekay/zerobundle/parts/25 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:dYDLMaWPKsFQGmtcwzxkYkgv8BDWx/X6BzcGZpkSOfg=
github.com/eyedeekay/zerobundle/parts/26 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:MA4hfjAJcfMlyFuCYunIHEf+cY9zmeE4ryFo3Po5JF4=
github.com/eyedeekay/zerobundle/parts/27 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:XYCTrc+EI0IJp1WqSmke8QwWZq8r30GMc7IldiLhQRU=
github.com/eyedeekay/zerobundle/parts/28 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:ULa1RnSblW49aQzh5OkYpzgucJytUCGIJCa6J3Wmi/s=
github.com/eyedeekay/zerobundle/parts/29 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:qc1FVwAnqcq38HUSyiaOhELMnElb3egWLMc9CZrXJ0U=
github.com/eyedeekay/zerobundle/parts/3 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:rbXS7rHqr/bjfZLE7unSRQ+yZRqQwpH9X8vLNreCHWA=
github.com/eyedeekay/zerobundle/parts/30 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:/0ZFt/Jne8VmPxq+yAJ92eZJGcVQ1xAIKriH7JiLsfE=
github.com/eyedeekay/zerobundle/parts/31 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:liOqHTgNuFYgn+g08BsixbNpoDBCJPuCMYk07567ydU=
github.com/eyedeekay/zerobundle/parts/32 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:0gybifj40shZlLwjimE9aKZ64+kBuhF6Y3CZ5qmdHN4=
github.com/eyedeekay/zerobundle/parts/33 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:tCpnAjdJDIwkmtcNF40/lN/ntwPLCeY/pStt+zraaDk=
github.com/eyedeekay/zerobundle/parts/34 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:N5TDdolp8T6xI/QUFGmRWw7I8JPEVg0AS1q1TmNPiOw=
github.com/eyedeekay/zerobundle/parts/35 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:bO8V2nliRTGKfo1wGvB1rO4o0dWg4yGi1SuqQ6OrY50=
github.com/eyedeekay/zerobundle/parts/36 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:eN/BVlryupcloAhyX1EkKchlrSbfiZZ5qKX9qxo4ROg=
github.com/eyedeekay/zerobundle/parts/37 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:2yT5zv8/qw8CqYiVyZrDQikSl/1w2HvA19rmmoZmKQM=
github.com/eyedeekay/zerobundle/parts/38 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:67DlDRKDEpL3Pv2NLZfJtdzbhr3TeObSZ/fMlkb83Bc=
github.com/eyedeekay/zerobundle/parts/39 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Wq04xNeuRoQ+PBwvQ5XbWDfCuhcATXPHQaDK4+mYEbY=
github.com/eyedeekay/zerobundle/parts/4 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:/AYmZRWuXvG3F/Pkg6EUBcoZryn+0rmOUhqYLwTIi2M=
github.com/eyedeekay/zerobundle/parts/40 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:R6uYmJWkoooy88K9g7XGTGx/NevPGdmZWijzdTCnGMM=
github.com/eyedeekay/zerobundle/parts/41 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:TIyNGUkXgCNvIzuCKelztZxja9M3oqXnv3MSV2oZI4o=
github.com/eyedeekay/zerobundle/parts/42 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:jPmMaibtGYWqTtQEj8T1FEJL0L/N5JNibZAF5olISPA=
github.com/eyedeekay/zerobundle/parts/43 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:NF4K1Rj5wRwdl4Gf9DZwzfCF7eN9BCR8KZskRKnbXjc=
github.com/eyedeekay/zerobundle/parts/44 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:wSdN3R6qC8kW8bBQGjXtzDiC7Wp6FP7IQHxG2VVNihY=
github.com/eyedeekay/zerobundle/parts/45 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:IHZ68spQacZYqj4L+d3WM/h8tgCQ2XmXgGjnhWD41NA=
github.com/eyedeekay/zerobundle/parts/46 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Y3f8FIDoDVt4AFynsKBEJJ7uHmpxncszvjJuQ/xU9oM=
github.com/eyedeekay/zerobundle/parts/47 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:bcsIhW6ImDpl0opjMo2a0R0vUvy9sdCay53aMixrdyQ=
github.com/eyedeekay/zerobundle/parts/48 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:UHfsb/IsV/v55xEbX6OJ2h10x2JV2QkD3gtsZfdEVAs=
github.com/eyedeekay/zerobundle/parts/49 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:KmpX6paQd8V0lQyb5Vf32LHqvxttRU0Kuf0EkaVefpU=
github.com/eyedeekay/zerobundle/parts/5 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:xnQ0thbNG8RVtUPy4hfGG1j4ofrnkVHAiEtKWHsy0Cg=
github.com/eyedeekay/zerobundle/parts/50 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:0hB/Gsdk/XXeH8TUPU4fb6dqGLGko3EqQwZTbQGFWWU=
github.com/eyedeekay/zerobundle/parts/51 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:mc3nEgk86vPADSNzQnfrTKCcWlk+RIEBByJJRGjWSFE=
github.com/eyedeekay/zerobundle/parts/52 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:wcrZPIPE3oDU6ZOtDPsq3LDdndV8rz/J5Ap6gWP6uwM=
github.com/eyedeekay/zerobundle/parts/53 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:4FyKA1J2NIQWopScrJrvffgng+N0WcmLr+OLbFduWEQ=
github.com/eyedeekay/zerobundle/parts/54 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:CYfIBsM8jV4xqX7S2j5xci3jaSj9TzTBSVtTaaY2KJU=
github.com/eyedeekay/zerobundle/parts/55 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:9jQnUFPxLovDWWq0O6tinFcsyRiwcIecCaf9JpKR83A=
github.com/eyedeekay/zerobundle/parts/56 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:9S04iK4gcGOaO9aTSOUJYwOY+aKXsxjtiHHFKFbSK7Q=
github.com/eyedeekay/zerobundle/parts/57 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:yxDg8hXgS8IhF8+OjPD9D/AWvocZti5ITSvKVNdkqEM=
github.com/eyedeekay/zerobundle/parts/58 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:MxN5/gcFww1UC+PMavjYd64geWJWDp/Bf/A9J9Ycul0=
github.com/eyedeekay/zerobundle/parts/59 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:ZURCoFl+UWFDDurQbFRarlqFYcB1rXmCCWhP3MLaHnk=
github.com/eyedeekay/zerobundle/parts/6 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:f7asFqs0K0X72hrjct81WkA02iaaelBQSYTV3QOjanw=
github.com/eyedeekay/zerobundle/parts/60 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:dqm2k3/MLCYf4nkLiGrN4TdfSb2iDm4ONZhtMTDe4Tk=
github.com/eyedeekay/zerobundle/parts/61 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:RLPVvYPWFS1zHmfggc2qL5EtIHTzp3NcuJNMP6HZxVo=
github.com/eyedeekay/zerobundle/parts/62 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:wGun39H/6ii6EXwyZFXfyHokLojZaRVg8KZ3mFRIQb0=
github.com/eyedeekay/zerobundle/parts/63 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:GIe5rQ+Ga6yPR+6tqflJlP9+WZ2xykt5cvORQsbF2v0=
github.com/eyedeekay/zerobundle/parts/64 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:yK7M5d0YSfbpygpBEbrdsr7QFxjEadzxuqPduw8dh3w=
github.com/eyedeekay/zerobundle/parts/65 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:r21iSU/BOfHCpa7v6r13zHwhRfl52wsc9NBmKMmkCJE=
github.com/eyedeekay/zerobundle/parts/66 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:LPH/QWYD+9KrGzfgNdkWPiddht7z60XW17K7hSsf78g=
github.com/eyedeekay/zerobundle/parts/67 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:UwH3xpzQwcc1lYQK87ZQhdABbL1HHFGeY6KfF7D7mAM=
github.com/eyedeekay/zerobundle/parts/68 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:E5Tzzsjpi/4eLj2ww8a2CmzIkLtfUZml4gCu3SfesIY=
github.com/eyedeekay/zerobundle/parts/69 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:jcJHibjcVrHvt2EZ6/IgCu1vknsNEThXNyWNNoJbpuY=
github.com/eyedeekay/zerobundle/parts/7 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:pFZHeNY82p6cZ8RiFiBjMJm6MRgwLoA64V09sY2V/ao=
github.com/eyedeekay/zerobundle/parts/70 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:QCHYlr7C0wtYRrRQH7/nAxhSFxfshXp9/4WZ9ryX5a0=
github.com/eyedeekay/zerobundle/parts/71 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Kua9+7c4TQoDSO3DQI0dkeGlSs+NSJPRfyvRr6s1KjI=
github.com/eyedeekay/zerobundle/parts/72 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:ODujh0Win47Sfl3Y3OPaPSPdpJP6h+9u0mK1rqcrl1Y=
github.com/eyedeekay/zerobundle/parts/73 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:2Vw7r64bJMvBWXReqp5ufLyqoVPrMDjRxYkOQktaPhU=
github.com/eyedeekay/zerobundle/parts/74 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:VVZWxY9pNy1gZMUnSGrqob+PQh6vFQMlmg2RnV7YvK4=
github.com/eyedeekay/zerobundle/parts/75 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:7ZcDiDfJpk/k5+v2LOcdEVmt5SCut0OO4vMavSGiu6A=
github.com/eyedeekay/zerobundle/parts/76 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:kuXL0iRkrW+/AEE9ZKW7S0rra6IT9aCau9kjVTZ9Zhk=
github.com/eyedeekay/zerobundle/parts/77 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:n1JEltHRskd2W47RSSYyPnJAsHFZJmotWuWwq1rf1Vw=
github.com/eyedeekay/zerobundle/parts/78 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:COntgzjlY/Ygqu2qwqmxo/s3RfOK6ocHxjkQ+J01pYY=
github.com/eyedeekay/zerobundle/parts/79 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Uu6loWDpFZ3fbDButI2ekunLTlmwQsz8o+zZxUu1Llw=
github.com/eyedeekay/zerobundle/parts/8 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:GyaxBZYPig/zP+v47dhR8vK2Cd8HGYAOIXb+vyYT9YE=
github.com/eyedeekay/zerobundle/parts/80 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:U3IAAukl+NQ2GiveijUgtmsbwDteKsRHlxqEkrsa/cY=
github.com/eyedeekay/zerobundle/parts/81 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:KAwdWBPLM4PFEwwCNJ5dy71nAQwliDpZ2/YRKhp9NHY=
github.com/eyedeekay/zerobundle/parts/82 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:HoWnyVLgQLJJgTVvLHzw3Y26lhwi9TY6mGDKwvPEEFA=
github.com/eyedeekay/zerobundle/parts/83 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:tSUT9kKZV5Bx6hn5cGBexQfY3XMzjwXWxHdfUoUhvhE=
github.com/eyedeekay/zerobundle/parts/84 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:pTtGn/7bkfcniwSuCK9AOf3IozBNJMmGBnU6zOo2Lm0=
github.com/eyedeekay/zerobundle/parts/85 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:BLcRLvNxRrVw/DZpEu3g8q6mkGnlKNNLSzsIAaidzkc=
github.com/eyedeekay/zerobundle/parts/86 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Ln9T4kXUzKR+bixtf47/kzawp/vTUXMofNIbMnVkGwo=
github.com/eyedeekay/zerobundle/parts/87 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:jcJFNz3OCmR/5EKevu7xd8fckAIr4QdHMkGRVxJailg=
github.com/eyedeekay/zerobundle/parts/88 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:LpdkVL7HI0EktFzGfK5+t28d1Fthm8E0jAYxhr42RYg=
github.com/eyedeekay/zerobundle/parts/89 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:/w5MzVlp6evonwnbVaAPKFdm3YXRs7VScx/zbac18/U=
github.com/eyedeekay/zerobundle/parts/9 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:FjcwaAw89/E0QfhAV8jF/xRSMepqQlIcwUSh6NYJTF4=
github.com/eyedeekay/zerobundle/parts/90 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:3KpaPHv7XayYKQuoAFZhRj9VkKIrTQP+YiR9qKxMcnw=
github.com/eyedeekay/zerobundle/parts/91 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:B9vPN+lAhj2xYyCYNx78Lu7E3PGlaEb7LPQW8PoRpo4=
github.com/eyedeekay/zerobundle/parts/92 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:jm2Y+gtVuc8ejwwIteWHI8a/8mS/yYgQ/QzixYQ/n/o=
github.com/eyedeekay/zerobundle/parts/93 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:ZCivN89N9MCwqJNHZ5sPjsRnlCQsGwMxyZF0ESncVZ0=
github.com/eyedeekay/zerobundle/parts/94 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:o1hHaMsel6ftPsu5sjAed9+L1yRo+GnTQOHpa5/C6QY=
github.com/eyedeekay/zerobundle/parts/95 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:Xw4WZ+ayb5rZCz1VlYIawFxtdnbVcGxexWuMGv42YBY=
github.com/eyedeekay/zerobundle/parts/96 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:gHasIrMmC/wOwlBG3z95hxCR80lPddJi8vVOBZ+G7zA=
github.com/eyedeekay/zerobundle/parts/97 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:MlDE/PhI13//dQQQ08OvmAHd6LDUCvnZvFhjj/0IJik=
github.com/eyedeekay/zerobundle/parts/98 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:wxzRUfbVl2JGPQxKbOvmkrt2yFCbCnL/kd5WSu465bQ=
github.com/eyedeekay/zerobundle/parts/99 v0.0.0-20210508034048-7cd2a4edba67/go.mod h1:23Y6kDua9WNX+si4vhbQiour2DNnTudWz2On+K9hQRY=
github.com/frankban/quicktest v1.13.0/go.mod h1:qLE0fzW0VuyUAJgPU19zByoIr0HtCHN/r/VLSOOIySU=
github.com/fsnotify/fsnotify v1.4.3-0.20170329110642-4da3e2cfbabc/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/garyburd/redigo v1.1.1-0.20170914051019-70e1b1943d4f/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/getlantern/context v0.0.0-20190109183933-c447772a6520/go.mod h1:L+mq6/vvYHKjCX2oez0CgEAJmbq1fbb/oNJIWQkBybY=
github.com/getlantern/errors v1.0.1/go.mod h1:l+xpFBrCtDLpK9qNjxs+cHU6+BAdlBaxHqikB6Lku3A=
github.com/getlantern/go-socks5 v0.0.0-20171114193258-79d4dd3e2db5/go.mod h1:kGHRXch95rnGLHjER/GhhFiHvfnqNz7KqWD9kGfATHY=
github.com/getlantern/golog v0.0.0-20201105130739-9586b8bde3a9/go.mod h1:ZyIjgH/1wTCl+B+7yH1DqrWp6MPJqESmwmEQ89ZfhvA=
github.com/getlantern/hex v0.0.0-20190417191902-c6586a6fe0b7/go.mod h1:dD3CgOrwlzca8ed61CsZouQS5h5jIzkK9ZWrTcf0s+o=
github.com/getlantern/hidden v0.0.0-20190325191715-f02dbb02be55/go.mod h1:6mmzY2kW1TOOrVy+r41Za2MxXM+hhqTtY3oBKd2AgFA=
github.com/getlantern/netx v0.0.0-20190110220209-9912de6f94fd/go.mod h1:wKdY0ikOgzrWSeB9UyBVKPRhjXQ+vTb+BPeJuypUuNE=
github.com/getlantern/ops v0.0.0-20190325191751-d70cb0d6f85f/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/getlantern/ops v0.0.0-20200403153110-8476b16edcd6/go.mod h1:D5ao98qkA6pxftxoqzibIBBrLSUli+kYnJqrgBf9cIA=
github.com/go-gl/gl v0.0.0-20181026044259-55b76b7df9d2/go.mod h1:482civXOzJJCPzJ4ZOX/pwvXBWSnzD4OKMdH4ClKGbk=
github.com/go-gl/gl v0.0.0-20210501111010-69f74958bac0/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM=
github.com/go-gl/glfw v0.0.0-20210410170116-ea3d685f79fb/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-stack/stack v1.6.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/gddo v0.0.0-20190419222130-af0f2af80721/go.mod h1:xEhNfoBDX1hzLm2Nf80qUvZ2sVwoMZ8d6IE2SrsQfh4=
github.com/golang/gddo v0.0.0-20200324184333-3c2cc9a6329d/go.mod h1:sam69Hju0uq+5uvLJUMDlsKlQ21Vrs1Kd/1YFPNYdOU=
github.com/golang/lint v0.0.0-20170918230701-e5d664eb928e/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
@@ -17,17 +218,62 @@ github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvq
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/go-cmp v0.1.1-0.20171103154506-982329095285/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
github.com/gregjones/httpcache v0.0.0-20170920190843-316c5e0ff04e/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69 h1:7xsUJsB2NrdcttQPa7JLEaGzvdbk7KvfrjgHZXOQRo0=
github.com/gtank/cryptopasta v0.0.0-20170601214702-1f550f6f2f69/go.mod h1:YLEMZOtU+AZ7dhN9T/IpGhXVGly2bvkJQ+zxj3WeVQo=
github.com/hashicorp/hcl v0.0.0-20170914154624-68e816d1c783/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/log15 v0.0.0-20170622235902-74a0988b5f80/go.mod h1:cOaXtrgN4ScfRrD9Bre7U1thNq5RtJ8ZoP4iXVGRj6o=
github.com/itchio/damage v0.0.0-20190703135837-76df725fc766 h1:4nBDNxFnzgCg46RTEKSQPK6g9TP87GvwLojqEoVIO5w=
github.com/itchio/damage v0.0.0-20190703135837-76df725fc766/go.mod h1:WA/BAVc27XYi+O39kOxQfFtexJP2DBYdZy4mgaLCiQE=
github.com/itchio/headway v0.0.0-20190702175331-a4c65c5306de/go.mod h1:Iif+7HeesRB0PvTYf0gOIFX8lj0za0SUsWryENQYt1E=
github.com/itchio/headway v0.0.0-20200301160421-e15721f23905 h1:gXP9pux2xvSQ03umJX8wuek4VE6gHNgZtqDdCmJmRQc=
github.com/itchio/headway v0.0.0-20200301160421-e15721f23905/go.mod h1:JpKeIqKW8xveb2juFrZ2kFR8GiMplC2H6bZ+UZHC/c0=
github.com/jchavannes/go-pgp v0.0.0-20200131171414-e5978e6d02b4 h1:AfTUqDjVFyY40SghT85bXRhpj34DOuIUQLB4DwExzkQ=
github.com/jchavannes/go-pgp v0.0.0-20200131171414-e5978e6d02b4/go.mod h1:dtFptCZ3M/9AWU38htm1xFvWqaJr5ZvkiOiozne99Ps=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/jpillora/go-tcp-proxy v1.0.0/go.mod h1:dDLgFeNeCec5CsLCmJlat+bb/oNDHc3d90G+anWRcBQ=
github.com/justinas/nosurf v0.0.0-20190416172904-05988550ea18/go.mod h1:Aucr5I5chr4OCuuVB4LTuHVrKHBuyRSo7vM2hqrcb7E=
github.com/justinas/nosurf v1.1.1 h1:92Aw44hjSK4MxJeMSyDa7jwuI9GR2J/JCQiaKvXXSlk=
github.com/justinas/nosurf v1.1.1/go.mod h1:ALpWdSbuNGy2lZWtyXdjkYv4edL23oSEgfBT1gPJ5BQ=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.9.2/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.5/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.1/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/klauspost/pgzip v1.2.3/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/majestrate/i2p-tools v0.0.0-20170507194519-afc8e46afa95/go.mod h1:e/TZ1O6X9t0qitnKc3xvHq8VXDpm/FmYuFf21epEkUc=
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
github.com/mholt/archiver v3.1.1+incompatible/go.mod h1:Dh2dOXnSdiLxRiPoVfIr/fI1TwETms9B8CTWfeh7ROU=
github.com/mholt/archiver/v3 v3.3.0/go.mod h1:YnQtqsp+94Rwd0D/rk5cnLrxusUBUXg+08Ebtr1Mqao=
github.com/mitchellh/go-ps v1.0.0 h1:i6ampVEEF4wQFF+bkYfwYgY+F/uYJDktmvLPf7qIgjc=
github.com/mitchellh/go-ps v1.0.0/go.mod h1:J4lOc8z8yJs6vUwklHw2XEIiT4z4C40KtWVN3nvg8Pg=
github.com/mitchellh/mapstructure v0.0.0-20170523030023-d0303fe80992/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8 h1:BhQQWYKJwXPtAhm12d4gQU4LKS9Yov22yOrDc2QA7ho=
github.com/mwitkow/go-http-dialer v0.0.0-20161116154839-378f744fb2b8/go.mod h1:ntWhh7pzdiiRKBMxUB5iG+Q2gmZBxGxpX1KyK6N8kX8=
github.com/nwaples/rardecode v1.0.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -40,65 +286,126 @@ github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7J
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/otiai10/copy v1.7.0 h1:hVoPiN+t+7d2nzzwMiDHPSOogsWAStewq3TwU05+clE=
github.com/otiai10/copy v1.7.0/go.mod h1:rmRl6QPdJj6EiUqXQ/4Nn2lLXoNQjFCQbbNrxgc/t3U=
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
github.com/otiai10/curr v1.0.0/go.mod h1:LskTG5wDwr8Rs+nNQ+1LlxRjAtTZZjtJW4rMXl6j4vs=
github.com/otiai10/mint v1.3.0/go.mod h1:F5AjcsTsWUqX+Na9fpHb52P8pcRX2CI6A3ctIT91xUo=
github.com/otiai10/mint v1.3.3 h1:7JgpsBaN0uMkyju4tbYHu0mnM55hNKVYLsXmwr15NQI=
github.com/otiai10/mint v1.3.3/go.mod h1:/yxELlJQ0ufhjUwhshSj+wFjZ78CnZ48/1wtmBH1OTc=
github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0=
github.com/pelletier/go-toml v1.0.1-0.20170904195809-1d6b12b7cb29/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2 h1:JhzVVoYvbOACxoUmOs6V/G4D5nPVUW73rKvXxP4XUJc=
github.com/phayes/freeport v0.0.0-20180830031419-95f893ade6f2/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pierrec/lz4 v2.5.2+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/russross/blackfriday v1.6.0 h1:KqfZb0pUVN2lYqZUYRddxF4OR8ZMURnJIG5Y3VRLtww=
github.com/russross/blackfriday v1.6.0/go.mod h1:ti0ldHuxg49ri4ksnFxlkCfN+hvslNlmVHqNRXXJNAY=
github.com/shurcooL/httpfs v0.0.0-20190707220628-8d4bc4ba7749/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
github.com/spf13/afero v0.0.0-20170901052352-ee1bd8ee15a1/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.1.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/jwalterweatherman v0.0.0-20170901151539-12bd96e66386/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.1-0.20170901120850-7aff26db30c1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.0.0/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.3.1-0.20190311161405-34c6fa2dc709/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/tfriedel6/canvas v0.12.1/go.mod h1:WIe1YgsQiKA1awmU6tSs8e5DkceDHC5MHgV5vQQZr/0=
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/ulikunitz/xz v0.5.7/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.10 h1:t92gobL9l3HE202wg3rlk19F6X+JOxl9BBrCCMYEYd8=
github.com/ulikunitz/xz v0.5.10/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/veandco/go-sdl2 v0.4.0/go.mod h1:FB+kTpX9YTE+urhYiClnRzpOXbiWgaU3+5F2AB78DPg=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/ybbus/jsonrpc v2.1.2+incompatible/go.mod h1:XJrh1eMSzdIYFbM08flv0wp5G35eRniyeGut1z+LSiE=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26 h1:E0lEWrifmR0ACbGf5PLji1XbW6rtIXLHCXO/YOqi0AE=
github.com/zieckey/goini v0.0.0-20180118150432-0da17d361d26/go.mod h1:TQpdgg7I9+PFIkatlx/dnZyZb4iZyCUx1HJj4rXi3+E=
github.com/zserge/lorca v0.1.8/go.mod h1:gTrVdXKyWxNhc8aUb1Uu3s0mY343arR1T6jUtxmBxR8=
github.com/zserge/lorca v0.1.9/go.mod h1:bVmnIbIRlOcoV285KIRSe4bUABKi7R7384Ycuum6e4A=
github.com/zserge/webview v0.0.0-20190123072648-16c93bcaeaeb/go.mod h1:a1CV8KR4Dd1eP2g+mEijGOp+HKczwdKHWyx0aPHKvo4=
gitlab.com/golang-commonmark/html v0.0.0-20180917080848-cfaf75183c4a/go.mod h1:JT4uoTz0tfPoyVH88GZoWDNm5NHJI2VbUW+eyPClueI=
gitlab.com/golang-commonmark/linkify v0.0.0-20180917065525-c22b7bdb1179/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
gitlab.com/golang-commonmark/markdown v0.0.0-20181102083822-772775880e1f/go.mod h1:SIHlEr9462fpIfTrVWf3GqQDxnA65Vm3BMMsUtuA6W0=
gitlab.com/golang-commonmark/mdurl v0.0.0-20180912090424-e5bce34c34f2/go.mod h1:wQk4rLkWrdOPjUAtqJRJ10hIlseLSVYWP95PLrjDF9s=
gitlab.com/golang-commonmark/puny v0.0.0-20180912090636-2cd490539afe/go.mod h1:P9LSM1KVzrIstFgUaveuwiAm8PK5VTB3yJEU8kqlbrU=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83 h1:/ZScEX8SfEmUGRHs0gxpqteO5nfNW6axyZbBdw9A12g=
golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce h1:Roh6XWxHFKrPgC/EQhVubSAGQ6Ozk6IdxHSzt1mR0EI=
golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20181106170214-d68db9428509/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/image v0.0.0-20200119044424-58c23975cae1/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/mobile v0.0.0-20181026062114-a27dd33d354d/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181102091132-c10e9556a7bc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2 h1:CIJ76btIcR3eFI5EgSo6k1qKw9KJexJuRLI9G7Hp5wE=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/oauth2 v0.0.0-20170912212905-13449ad91cb2/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/sync v0.0.0-20170517211232-f52d1811a629/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181128092732-4ed8d59d0b35/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190830142957-1e83adbbebd0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210228012217-479acdf4ea46/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9 h1:XfKQ4OlFl8okEOr5UvAqFRVj8pY/4yfcXrddB8qAbU0=
golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/time v0.0.0-20170424234030-8be79e1e0910/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190830223141-573d9926052a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.0.0-20170921000349-586095a6e407/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20170918111702-1e559d0a00ee/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/grpc v1.2.1-0.20170921194603-d4b75ebd4f9f/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -107,12 +414,23 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v0.0.0-20181124034731-591f970eefbb/go.mod h1:vMygbs4qMhSZSc4lCUl2OEE+rDiIIJAIdR4m7MiMcm0=
howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM=
howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=

20
i2pd.go Normal file
View File

@@ -0,0 +1,20 @@
//go:build i2pd
// +build i2pd
package main
import (
i2pd "github.com/eyedeekay/go-i2pd/goi2pd"
)
func InitI2PSAM() func() {
return i2pd.InitI2PSAM()
}
func StartI2P() {
i2pd.StartI2P()
}
func StopI2P() {
defer i2pd.StopI2P()
}

9
i2ptorbrowser.desktop Normal file
View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=/bin/sh -c "i2pbrowser -directory=$HOME/.i2p/browser"
Name=I2P in Tor Browser
Categories=Network;WebBrowser;
Icon=/var/lib/i2pbrowser/icons/garliconion.png

BIN
icon/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

View File

@@ -6,52 +6,53 @@
</head>
<body>
<h1 id="i2p.plugins.tor-updater">i2p.plugins.tor-updater</h1>
<p>A Tor package updater and runner as an I2P Plugin. This plugin is still being changed rapidly but it should be usable on most Linux distributions as of 23 Jan, 2022.</p>
<p>A Tor package updater and runner as an I2P Plugin. This plugin is usable on Windows, Linux, and OSX, as is the freestanding binary. This also functions as a freestanding update for the Tor Browser Bundle and is capable of configuring Tor Browser from the terminal and updating it without running it, should the user choose to operate this way.</p>
<h2 id="usage">Usage:</h2>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ex">Usage</span> of ./i2p.plugins.tor-manager-linux-amd64:</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a> <span class="ex">-arch</span> string</span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a> <span class="ex">OS/arch</span> to download (default <span class="st">&quot;64&quot;</span>)</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a> <span class="ex">-i2pbrowser</span></span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a> <span class="ex">Open</span> I2P in Tor Browser</span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a> <span class="ex">-lang</span> string</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a> <span class="ex">Language</span> to download</span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a> <span class="ex">-os</span> string</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a> <span class="ex">OS/arch</span> to download (default <span class="st">&quot;linux&quot;</span>)</span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a> <span class="ex">-torbrowser</span></span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a> <span class="ex">Open</span> Tor Browser</span></code></pre></div>
<p>See <a href="USAGE.md">Usage</a> for command-line usage. When used from the Terminal, it acts as a cross-platform Tor Browser installer and wrapper, which adds non-Tor specific options.</p>
<p><a href="usage.html">HTML version</a></p>
<h2 id="plugin">Plugin:</h2>
<p>Clearnet visitor? Youll need to use the <a href="https://github.com/eyedeekay/i2p.plugins.tor-manager/releases/">Github Releases Mirror</a>.</p>
<ul>
<li><a href="/i2p.plugins.tor-manager-linux-386.su3">i2p.plugins.tor-manager-linux-386</a></li>
<li><a href="/i2p.plugins.tor-manager-windows-amd64.su3">i2p.plugins.tor-manager-windows-amd64</a></li>
<li><a href="/i2p.plugins.tor-manager-darwin-arm64.su3">i2p.plugins.tor-manager-darwin-arm64</a></li>
<li><a href="/i2p.plugins.tor-manager-linux-amd64.su3">i2p.plugins.tor-manager-linux-amd64</a></li>
<li><a href="/i2p.plugins.tor-manager-windows-386.su3">i2p.plugins.tor-manager-windows-386</a></li>
<li><a href="/i2p.plugins.tor-manager-darwin-amd64.su3">i2p.plugins.tor-manager-darwin-amd64</a></li>
</ul>
<h2 id="status">Status:</h2>
<figure>
<img src="screenshot-console.png" alt="" /><figcaption>Screenshot 2</figcaption>
</figure>
<p>Linux: Usable, most things work. Windows: Unstable, mostly usable, does not work in some important cirumstances, cannot run from a flash drive OSX: Unstable, untested, not usable, WIP.</p>
<p>Linux: Usable, everything implemented works. Windows: Usable, everything implemented works. OSX: Usable, everything implemented works.</p>
<p>Other systems are not targeted and should use a Tor binary built from source, provided by TPO or, their prefered package management system and not this plugin. The plugin will not start a Tor instance if a SOCKS proxy is open on port 9050.</p>
<figure>
<img src="screenshot.png" alt="" /><figcaption>Screenshot</figcaption>
<img src="screenshot-i2pbrowser.png" alt="" /><figcaption>Screenshot</figcaption>
</figure>
<h3 id="primary-goals">Primary Goals</h3>
<ol type="1">
<li>Ship known-good public keys, download a current Tor for the platform in the background, authenticate it, and launch it only if necessary.</li>
</ol>
<ul>
<li>Works on Windows, Linux, probably also OSX</li>
<li>Works on Windows, Linux, OSX</li>
</ul>
<ol start="2" type="1">
<li>Supervise Tor as a ShellService plugin to I2P</li>
</ol>
<ul>
<li>Works on Linux</li>
<li>Works on Linux, Windows, OSX</li>
</ul>
<ol start="3" type="1">
<li>Keep Tor up-to-date</li>
</ol>
<ul>
<li>Works on Windows, Linux, probably also OSX</li>
<li>Works on Windows, Linux, OSX</li>
</ul>
<ol start="4" type="1">
<li>Work as an I2P Plugin OR as a freestanding app to be compatible with all I2P distributions</li>
</ol>
<ul>
<li>Works on Linux, probably works on Windows</li>
<li>Works on Linux, Windows, OSX</li>
</ul>
<ol start="5" type="1">
<li>Download Tor Browser from an in-I2P mirror(or one of a network of in-I2P mirrors)</li>
@@ -64,25 +65,96 @@
<li>Launch Tor Browser</li>
</ol>
<ul>
<li>Works on Linux</li>
<li>Works on Linux, Windows, OSX</li>
</ul>
<ol start="2" type="1">
<li>Configure and launch Tor browser for use with I2P</li>
</ol>
<ul>
<li>Works on Linux, probably also Windows, probably not OSX yet.</li>
<li>Works on Linux, Windows, OSX</li>
</ul>
<h4 id="optional-features-i-might-add-if-there-is-interest">Optional Features I might add if there is interest</h4>
<ol type="1">
<li>Mirror the files which it downloads to an I2P Site</li>
</ol>
<ul>
<li>Works on Windows, Linux, OSX</li>
</ul>
<ol start="2" type="1">
<li>Mirror the files which it downloads to I2P torrents</li>
</ol>
<ul>
<li>Not done</li>
</ul>
<ol start="3" type="1">
<li>Set up an onion site which announces an I2P mirror exists</li>
</ol>
<ul>
<li>Not done</li>
</ul>
<ol start="4" type="1">
<li>Use Bittorrent-over-I2P to download the Tor Browser software</li>
</ol>
<ul>
<li>Not Done</li>
</ul>
<ol start="5" type="1">
<li>Import libi2pd and offer the use of an embedded i2pd router.</li>
</ol>
<ul>
<li>Not done.</li>
</ul>
<ol start="6" type="1">
<li>Option to use BRB in a thread as an in-I2P replacement for <code>mibbit</code> IRC client.</li>
</ol>
<ul>
<li>Not done.</li>
</ul>
<h3 id="usage-as-a-library">Usage as a Library</h3>
<p><a href="https://pkg.go.dev/i2pgit.org/idk/i2p.plugins.tor-manager">More information at the GoDoc</a></p>
<p>This is also useful as a library for downloading a Tor Browser Bundle. This API isnt really stable, more “stabilizing.” Feel free to use it, but it may still change a little.</p>
<p>To create a new instance, use:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a>client, err = tbserve.NewClient(*verbose, *lang, *system, *arch, &amp;content)</span></code></pre></div>
<p>Customize the client using the exposed variables and methods:</p>
<div class="sourceCode" id="cb2"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true"></a>client.Host = *host</span>
<span id="cb2-2"><a href="#cb2-2" aria-hidden="true"></a>client.Port = *port</span>
<span id="cb2-3"><a href="#cb2-3" aria-hidden="true"></a>client.TBS.Profile = &amp;content</span>
<span id="cb2-4"><a href="#cb2-4" aria-hidden="true"></a>client.TBS.PassThroughArgs = flag.Args()</span></code></pre></div>
<p>And serve the controller:</p>
<div class="sourceCode" id="cb3"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true"></a><span class="kw">if</span> err := client.Serve(); err != <span class="ot">nil</span> {</span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true"></a> log.Fatal(err)</span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true"></a>}</span></code></pre></div>
<h3 id="similar-projects">Similar Projects:</h3>
<ul>
<li>https://github.com/micahflee/torbrowser-launcher</li>
<li>https://github.com/whonix/tb-updater</li>
<li><a href="https://github.com/micahflee/torbrowser-launcher">https://github.com/micahflee/torbrowser-launcher</a></li>
<li><a href="https://github.com/whonix/tb-updater">https://github.com/whonix/tb-updater</a></li>
<li>Probably about 200 or so bespoke scripts written and abandoned by hackers over the years, search github</li>
</ul>
<h4 id="why-this-is-better-than-those-projectsa.k.a-why-didnt-you-just-use">Why this is Better than those projects(A.K.A Why didnt you just use…)</h4>
<h5 id="torbrowser-launcher"><a href="https://github.com/micahfleee/torbrowser-launcher">TorBrowser Launcher</a></h5>
<p>i2p.plugins.tor-manager is in many ways a clone of Tor Browser Launcher by Micah Lee, it reproduces all of TBLs functionality for downloading, verifying, and running Tor Browser. In particular Micahs project deserves credit for the AppArmor profiles, which were used in the apparmor profile generator functionality and will probably continue to be the upstream example which I use in my code. Micahs also already got a PPA, a FlatPak, a Snap, an <code>.rpm</code> and a bunch of other stuff that provides, through packaging, a better way to deal with updates to his software and a better way to deal with the supply chain for many users. There is no reason that <code>i2p.plugins.tor-manager</code> cannot do this, in fact its easier for us than it is for Micah, but this project is about a month and a half old and his is several years old. I havent done a bunch of packages yet.</p>
<p>Improvements on Tor Browser Launcher include:</p>
<ul>
<li>Does not require GPG to be in the <code>$PATH</code> or on the system at all</li>
<li>Capable of managing a long-running Tor service without also running the Tor Browser</li>
<li>Works everywhere Tor Browser does, not just Linux. Including: Linux, Mac, Windows, AMD64, X86, and M1</li>
<li>Embeds all required resources into a single binary which unpacks itself to a directory of the users choice. Never touches any other directory.</li>
<li>Easy to package by placing a single static binary into a boilerplate package.</li>
<li>Automatically generate an AppArmor profile which works for custom installation directory</li>
<li>Accepts a custom profile argument without interfering with normal Tor Browser functionality.</li>
<li>Bundles a “Extra” profiles for I2P browsing, non-Anonymous browsing, and offline/localhost-only browsing.</li>
<li>Automatically organize multiple Tor Browser profiles for different networks(I2P, Clearnet) and discourage accidental mixing.</li>
<li>Optional TAILS mode, adds uBlock Origin to Tor Browser</li>
<li>Embeds an i2pd router in case the host system doesnt have an I2P router</li>
<li>No python. Language wars are stupid, but so is python.</li>
</ul>
<h4 id="tb-updaterwhonix"><a href="https://github.com/whonix/tb-updater">TB-Updater(Whonix)</a></h4>
<p>tb-updater is generally only useful on Linux systems and especially Debian-based systems, and only recieves serious testing within the Whonix system itself. Its a highly specialized tool in some ways, depending on packages which must be installed and repositories which must be configured. For their purposes, this is probably a good thing, Whonixs raison detre is to carefully configure every aspect of their system to be as anonymous and secure as possible, and their approach deals with supply-chain issues which <code>i2p.plugins.tor-manager</code> can only deal with in <strong>packaging</strong> and not by adding features to the launcher itself. Therefore, while most of the improvements on Tor Browser Launcher also apply to TB-Updater, the <code>i2p.plugins.tor-manager</code> and <code>tb-launcher</code> are actually less directly comparable.</p>
<p><a href="https://www.flaticon.com/free-icons/garlic" title="garlic icons">Garlic icons created by Icongeek26 - Flaticon</a> <a href="https://www.flaticon.com/free-icons/onion" title="onion icons">Onion icons created by Freepik - Flaticon</a></p>
<h3 id="more-screenshots">More Screenshots:</h3>
<ul>
<li><img src="screenshot.png" title="fig:" alt="Screenshot" /></li>
<li><img src="screenshot-dark.png" title="fig:" alt="Screenshot" /></li>
</ul>
</body>
</html>

55
link_darwin.go Normal file
View File

@@ -0,0 +1,55 @@
package main
import (
"i2pgit.org/idk/i2p.plugins.tor-manager/get"
"os"
"path/filepath"
)
func GenerateAppArmor() error {
return nil
}
func CreateShortcuts() error {
if err := CreateShortcut("torbrowser"); err != nil {
return err
}
if err := CreateShortcut("i2pbrowser"); err != nil {
return err
}
if err := CreateShortcut("i2pconfig"); err != nil {
return err
}
return nil
}
func CreateShortcut(linkname string) error {
// check if there is a symlink in the $HOME/Desktop Directory
// if not, create one
// if there is, check if it points to the correct location
// if not, delete it and create a new one
// if there is, do nothing
exe, err := os.Executable()
if err != nil {
return err
}
absolutepath, err := filepath.Abs(filepath.Join(filepath.Dir(exe), exe))
if err != nil {
return err
}
home, err := os.UserHomeDir()
if err != nil {
return err
}
path := filepath.Join(home, "Desktop", linkname)
if tbget.FileExists(linkname) {
if originfile, err := os.Readlink(path); err != nil || originfile != absolutepath {
if err := os.Remove(path); err != nil {
return err
}
return os.Symlink(absolutepath, path)
}
}
return os.Symlink(absolutepath, path)
return nil
}

58
link_linux.go Normal file
View File

@@ -0,0 +1,58 @@
package main
import (
"io/ioutil"
"log"
"os/user"
"path/filepath"
)
func DesktopDirectory() (string, error) {
myself, err := user.Current()
if err != nil {
return "", err
}
homedir := myself.HomeDir
desktop := filepath.Join(homedir, ".local", "share", "applications")
return desktop, nil
}
func CreateShortcuts() error {
desktopDir, err := DesktopDirectory()
if err != nil {
return err
}
torBrowserPath, err := pathToMe()
if err != nil {
return err
}
tordesktop := filepath.Join(desktopDir, "torbrowser.desktop")
torbrowserShortcut := torBrowserPath + " -torbrowser"
if err := makeLink(torbrowserShortcut, tordesktop); err != nil {
return err
}
i2pbrowserPath := torBrowserPath + " -i2pbrowser"
i2pdesktop := filepath.Join(desktopDir, "i2ptorbrowser.desktop")
if err := makeLink(i2pbrowserPath, i2pdesktop); err != nil {
return err
}
return nil
}
func desktopTemplate(command string) string {
return `[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=/bin/sh -c "` + command + `"
Name=Tor Browser
Categories=Network;WebBrowser;
Icon=/var/lib/i2pbrowser/icons/onion.png
`
}
func makeLink(src, dst string) error {
log.Println("Creating desktop shortcut:", dst)
return ioutil.WriteFile(dst, []byte(desktopTemplate(src)), 0644)
}

68
link_windows.go Normal file
View File

@@ -0,0 +1,68 @@
package main
import (
"log"
"github.com/go-ole/go-ole"
"github.com/go-ole/go-ole/oleutil"
"os/user"
"path/filepath"
)
func GenerateAppArmor() error {
return nil
}
func DesktopDirectory() (string, error) {
myself, error := user.Current()
if error != nil {
return "", error
}
homedir := myself.HomeDir
desktop := filepath.Join(homedir, "Desktop")
return desktop, nil
}
func CreateShortcuts() error {
desktopDir, err := DesktopDirectory()
if err != nil {
return err
}
desktop := filepath.Join(desktopDir, "torbrowser.lnk")
torBrowserPath, err := pathToMe()
if err != nil {
return err
}
torbrowserShortcut := torBrowserPath + " -torbrowser"
if err := makeLink(torbrowserShortcut, desktop); err != nil {
return err
}
i2pBrowserPath := torBrowserPath + " -i2pbrowser"
if err := makeLink(i2pBrowserPath, desktop); err != nil {
return err
}
return nil
}
func makeLink(src, dst string) error {
log.Println("Creating desktop shortcut:", dst)
ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_SPEED_OVER_MEMORY)
oleShellObject, err := oleutil.CreateObject("WScript.Shell")
if err != nil {
return err
}
defer oleShellObject.Release()
wshell, err := oleShellObject.QueryInterface(ole.IID_IDispatch)
if err != nil {
return err
}
defer wshell.Release()
cs, err := oleutil.CallMethod(wshell, "CreateShortcut", dst)
if err != nil {
return err
}
idispatch := cs.ToIDispatch()
oleutil.PutProperty(idispatch, "TargetPath", src)
oleutil.CallMethod(idispatch, "Save")
return nil
}

191
main.go
View File

@@ -3,23 +3,40 @@ package main
import (
"embed"
"flag"
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"github.com/cloudfoundry/jibber_jabber"
i2cpcheck "github.com/eyedeekay/checki2cp"
"github.com/itchio/damage"
"github.com/itchio/damage/hdiutil"
"github.com/itchio/headway/state"
tbget "i2pgit.org/idk/i2p.plugins.tor-manager/get"
tbserve "i2pgit.org/idk/i2p.plugins.tor-manager/serve"
)
/*
TODO: A "Default" config file which uses hardened Tor Browser for clearnet
(or default-route) browsing.
*/
//go:embed tor-browser/unpack/i2p.firefox/*
//go:embed tor-browser/unpack/i2p.firefox.config/*
//go:embed tor-browser/unpack/awo@eyedeekay.github.io.xpi
//go:embed tor-browser/TPO-signing-key.pub
//go:embed garliconion.png
//go:embed onion.png
//go:embed torbrowser.desktop
//go:embed i2ptorbrowser.desktop
var content embed.FS
func OS() string {
switch runtime.GOOS {
case "darwin":
return "mac"
return "osx"
case "linux":
return "linux"
case "windows":
@@ -35,6 +52,11 @@ func ARCH() string {
return "32"
case "amd64":
return "64"
case "arm64":
if OS() == "osx" {
return "64"
}
return ""
default:
return "unknown"
}
@@ -45,21 +67,66 @@ var (
system = flag.String("os", OS(), "OS/arch to download")
arch = flag.String("arch", ARCH(), "OS/arch to download")
i2pbrowser = flag.Bool("i2pbrowser", false, "Open I2P in Tor Browser")
i2pconfig = flag.Bool("i2pconfig", false, "Open I2P routerconsole in Tor Browser with javscript enabled and non-routerconsole sites disabled")
torbrowser = flag.Bool("torbrowser", false, "Open Tor Browser")
verbose = flag.Bool("verbose", false, "Verbose output")
directory = flag.String("directory", "", "Directory operate in")
host = flag.String("host", "127.0.0.1", "Host to serve on")
port = flag.Int("port", 7695, "Port to serve on")
bemirror = flag.Bool("bemirror", false, "Act as an in-I2P mirror when you're done downloading")
shortcuts = flag.Bool("shortcuts", false, "Create desktop shortcuts")
apparmor = flag.Bool("apparmor", false, "Generate apparmor rules")
offline = flag.Bool("offline", false, "Work offline. Differs from Firefox's offline mode in that cannot be disabled until the browser is closed.")
clearnet = flag.Bool("clearnet", false, "Use clearnet (no Tor or I2P)")
profile = flag.String("profile", "", "use a custom profile path, normally blank")
help = flag.Bool("help", false, "Print help")
/*onion = flag.Bool("onion", false, "Serve an onion site which shows some I2P propaganda, magnet links, your I2P mirror URL if configured")*/
/*torrent = flag.Bool("torrent", false, "Create a torrent of the downloaded files and seed it over I2P using an Open Tracker")*/
/*ptop = flag.Bool("p2p", false, "Use bittorrent over I2P to download the initial copy of Tor Browser")*/
/*mirror = flag.String("mirror", "", "Mirror to use")*/
/*bemirror = flag.Bool("bemirror", false, "Act as an in-I2P mirror when you're done downloading")*/
)
var client *tbserve.Client
func main() {
filename := filepath.Base(os.Args[0])
usage := flag.Usage
flag.Usage = func() {
fmt.Printf("Usage: %s %s\n", filename, "[options]")
fmt.Printf("\n")
fmt.Printf("Downloads, verifies and unpacks Tor Browser. Manages the Tor Browser\n")
fmt.Printf("system in environments where Tor is not in use.\n")
fmt.Printf("\n")
fmt.Printf("Options:\n")
fmt.Printf("\n")
usage()
}
flag.Parse()
tbget.WORKING_DIR = *directory
if filename == "i2pbrowser" {
log.Println("Starting I2P in Tor Browser")
*i2pbrowser = true
} else if filename == "torbrowser" {
log.Println("Starting Tor Browser")
*torbrowser = true
} else if filename == "i2pconfig" {
log.Println("Starting I2P routerconsole in Tor Browser")
*i2pconfig = true
} else if filename == "firefox" || *clearnet || *offline {
log.Println("Starting Firefox from Tor Browser package")
*clearnet = true
if *profile == "" {
if *offline {
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox.offline")
} else if *clearnet {
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox")
} else {
*profile = filepath.Join(tbget.WORKING_DIR, "profile.firefox.tor")
}
} else {
*profile = filepath.Join(tbget.WORKING_DIR, *profile)
}
log.Println("Using profile", *profile)
}
if *i2pbrowser && *torbrowser {
log.Fatal("Please don't open I2P and Tor Browser at the same time when running from the terminal.")
@@ -72,22 +139,128 @@ func main() {
}
log.Println("Using auto-detected language", *lang)
}
client, err := tbserve.NewClient("", *lang, *system, *arch, &content)
var err error
client, err = tbserve.NewClient(*verbose, *lang, *system, *arch, &content)
if err != nil {
log.Fatal("Couldn't create client", err)
}
//client.TBD.Profile = &content
if *verbose {
client.TBD.Verbose = true
if *i2pbrowser || *i2pconfig {
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK")
} else {
log.Println("I2P HTTP proxy not OK")
run, err := i2cpcheck.ConditionallyLaunchI2P()
if err != nil {
log.Println("Couldn't launch I2P", err)
}
if run {
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK after launching I2P")
} else {
go proxy()
if !tbget.TestHTTPBackupProxy() {
log.Fatal("Please set the I2P HTTP proxy on localhost:4444", err)
}
}
} else {
closer := InitI2PSAM()
defer closer()
go StartI2P()
defer StopI2P()
if tbget.TestHTTPDefaultProxy() {
log.Println("I2P HTTP proxy OK")
} else {
log.Fatal("Embedded i2pd unable to start")
}
}
}
}
if *apparmor {
err := GenerateAppArmor()
if err != nil {
log.Fatal("Couldn't generate apparmor rules", err)
}
log.Println("################################################################")
log.Println("# AppArmor rules generated successfully #")
log.Println("################################################################")
log.Println("!IMPORTANT! You must now run the following commands:")
log.Println("sudo mkdir -p /etc/apparmor.d/tunables/")
log.Println("sudo cp tunables.torbrowser.apparmor /etc/apparmor.d/tunables/torbrowser")
log.Println("sudo cp torbrowser.Tor.tor.apparmor /etc/apparmor.d/torbrowser.Tor.tor")
log.Println("sudo cp torbrowser.Browser.firefox.apparmor /etc/apparmor.d/torbrowser.Browser.firefox")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/tunables/torbrowser")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/torbrowser.Tor.tor")
log.Println("sudo apparmor_parser -r /etc/apparmor.d/torbrowser.Browser.firefox")
log.Println("To copy them to apparmor profiles directory and reload AppArmor")
return
}
if *shortcuts {
err := CreateShortcuts()
if err != nil {
log.Fatal("Couldn't create desktop shortcuts", err)
}
}
client.Host = *host
client.Port = *port
client.TBS.Profile = &content
if *i2pbrowser {
client.TBS.RunI2PBWithLang()
client.TBS.PassThroughArgs = flag.Args()
consumer := &state.Consumer{
OnMessage: func(lvl string, msg string) {
log.Printf("[%s] %s", lvl, msg)
},
}
host := hdiutil.NewHost(consumer)
defer damage.Unmount(host, client.TBD.BrowserDir())
// log.Fatalf("%s", client.TBS.PassThroughArgs)
if *help {
flag.Usage()
if err := client.TBS.RunTBHelpWithLang(); err != nil {
log.Fatal(err)
}
return
}
client.TBS.UnpackI2PAppData()
client.TBS.UnpackI2PData()
if *profile != "" {
log.Println("Using a custom profile")
if err := client.TBS.RunTBBWithOfflineClearnetProfile(*profile, *offline, *clearnet); err != nil {
log.Fatal(err)
}
} else if *offline {
log.Println("Working offline")
if err := client.TBS.RunTBBWithOfflineClearnetProfile(*profile, *offline, *clearnet); err != nil {
log.Fatal(err)
}
} else if *i2pbrowser {
if err := client.TBS.RunI2PBWithLang(); err != nil {
log.Fatal(err)
}
} else if *i2pconfig {
if err := client.TBS.RunI2PBAppWithLang(); err != nil {
log.Fatal(err)
}
} else if *torbrowser {
client.TBS.RunTBWithLang()
if err := client.TBS.RunTBWithLang(); err != nil {
log.Fatal(err)
}
} else {
if *bemirror {
go client.TBD.Serve()
}
if err := client.Serve(); err != nil {
log.Fatal(err)
}
}
}
func pathToMe() (string, error) {
ex, err := os.Executable()
if err != nil {
return "", err
}
exPath, err := filepath.Abs(ex)
if err != nil {
return "", err
}
return exPath, nil
}

20
no-i2pd.go Normal file
View File

@@ -0,0 +1,20 @@
//go:build !i2pd
// +build !i2pd
package main
func InitI2PSAM() func() {
return nullFunc
}
func nullFunc() {
}
func StartI2P() {
}
func StopI2P() {
}

16
offline.html Normal file
View File

@@ -0,0 +1,16 @@
<!DOCTYPE html>
<html>
<head>
<title>i2p.plugins.tor-manager - Tor Binary Manager</title>
<link rel="stylesheet" type="text/css" href ="/style.css" />
</head>
<body>
<h1 id="running-in-offline-mode">Running in Offline Mode</h1>
<p>Tor Browser is configured to run without <em>any</em> access to the clearnet, and will now only use local services running on this device. This uses a different mechanism than Firefoxs normal work offline mode and cannot be canceled.</p>
<ul>
<li>Visit the <a href="http://127.0.0.1:7657">I2P Router Console</a></li>
<li>Visit the <a href="http://127.0.0.1:8888">Freenet FProxy</a></li>
</ul>
<p>This wrapper has been developed for use with the I2P project. To learn more about I2P, visit <a href="https://geti2p.net">Get I2P</a></p>
</body>
</html>

BIN
onion.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

156
proxy.go Normal file
View File

@@ -0,0 +1,156 @@
package main
import (
"context"
"flag"
"log"
"net"
"net/http"
"os"
"os/signal"
"strings"
"time"
i2phttpproxy "github.com/eyedeekay/httptunnel"
i2pbrowserproxy "github.com/eyedeekay/httptunnel/multiproxy"
)
var (
watchProfiles = flag.String("watch-profiles", "", "Monitor and control these Firefox profiles. Temporarily Unused.")
aggressiveIsolation = false
samHostString = "127.0.0.1" //flag.String("bridge-host", "127.0.0.1", "host: of the SAM bridge")
samPortString = "7656" //flag.String("bridge-port", "7656", ":port of the SAM bridge")
destfile = "invalid.tunkey"
debugConnection = false
inboundTunnelLength = 3
outboundTunnelLength = 3
inboundTunnels = 4
outboundTunnels = 4
inboundBackups = 2
outboundBackups = 2
inboundVariance = 0
outboundVariance = 0
dontPublishLease = true
reduceIdle = false
useCompression = true
reduceIdleTime = 2000000
reduceIdleQuantity = 1
runQuiet = false
)
func proxy() {
ln, err := net.Listen("tcp", "127.0.0.1:4444")
if err != nil {
log.Fatal(err)
}
cln, err := net.Listen("tcp", "127.0.0.1:7696")
if err != nil {
log.Fatal(err)
}
ctx, cancel := context.WithCancel(context.Background())
go proxyMain(ctx, ln, cln)
<-ctx.Done()
cancel()
}
func proxyMain(ctx context.Context, ln net.Listener, cln net.Listener) {
flag.Parse()
for {
_, err := net.Listen("tcp", samHostString+":"+samPortString)
if err != nil {
break
}
}
profiles := strings.Split(*watchProfiles, ",")
srv := &http.Server{
ReadTimeout: 600 * time.Second,
WriteTimeout: 10 * time.Second,
Addr: ln.Addr().String(),
}
var err error
srv.Handler, err = i2pbrowserproxy.NewHttpProxy(
i2pbrowserproxy.SetHost(samHostString),
i2pbrowserproxy.SetPort(samPortString),
i2pbrowserproxy.SetProxyAddr(ln.Addr().String()),
i2pbrowserproxy.SetControlAddr(cln.Addr().String()),
i2pbrowserproxy.SetDebug(debugConnection),
i2pbrowserproxy.SetInLength(uint(inboundTunnelLength)),
i2pbrowserproxy.SetOutLength(uint(outboundTunnelLength)),
i2pbrowserproxy.SetInQuantity(uint(inboundTunnels)),
i2pbrowserproxy.SetOutQuantity(uint(outboundTunnels)),
i2pbrowserproxy.SetInBackups(uint(inboundBackups)),
i2pbrowserproxy.SetOutBackups(uint(outboundBackups)),
i2pbrowserproxy.SetInVariance(inboundVariance),
i2pbrowserproxy.SetOutVariance(outboundVariance),
i2pbrowserproxy.SetUnpublished(dontPublishLease),
i2pbrowserproxy.SetReduceIdle(reduceIdle),
i2pbrowserproxy.SetCompression(useCompression),
i2pbrowserproxy.SetReduceIdleTime(uint(reduceIdleTime)),
i2pbrowserproxy.SetReduceIdleQuantity(uint(reduceIdleQuantity)),
i2pbrowserproxy.SetKeysPath(destfile),
i2pbrowserproxy.SetProxyMode(aggressiveIsolation),
)
i2pbrowserproxy.Quiet = runQuiet
if err != nil {
log.Fatal(err)
}
ctrlsrv := &http.Server{
ReadHeaderTimeout: 600 * time.Second,
WriteTimeout: 600 * time.Second,
Addr: cln.Addr().String(),
}
ctrlsrv.Handler, err = i2phttpproxy.NewSAMHTTPController(profiles, srv)
if err != nil {
log.Fatal(err)
}
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for sig := range c {
if sig == os.Interrupt {
srv.Handler.(*i2pbrowserproxy.SAMMultiProxy).Close()
srv.Shutdown(ctx)
ctrlsrv.Shutdown(ctx)
}
}
}()
go func() {
log.Println("Starting control server on", cln.Addr())
if err := ctrlsrv.Serve(cln); err != nil {
if err == http.ErrServerClosed {
return
}
log.Fatal("Serve:", err)
}
log.Println("Stopping control server on", cln.Addr())
}()
go func() {
log.Println("Starting proxy server on", ln.Addr())
if err := srv.Serve(ln); err != nil {
if err == http.ErrServerClosed {
return
}
log.Fatal("Serve:", err)
}
log.Println("Stopping proxy server on", ln.Addr())
}()
counter()
<-ctx.Done()
}
func counter() {
var x int
for {
log.Println("Identity is", x, "minute(s) old")
time.Sleep(1 * time.Minute)
x++
}
}

BIN
screenshot-dark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

BIN
screenshot-i2pbrowser.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 300 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

@@ -11,12 +11,12 @@ import (
)
func (m *Client) generateMirrorJSON() (map[string]interface{}, error) {
path := filepath.Join(tbget.DOWNLOAD_PATH, "downloads.json")
path := filepath.Join(tbget.DOWNLOAD_PATH(), "downloads.json")
preBytes, err := ioutil.ReadFile(path)
if err != nil {
return nil, fmt.Errorf("GenerateMirrorJSON: %s", err)
}
binpath, _, err := m.TBD.GetUpdaterForLangFromJsonBytes(preBytes, "en-US")
binpath, _, err := m.TBD.GetUpdaterForLangFromJSONBytes(preBytes, "en-US")
if err != nil {
return nil, fmt.Errorf("GenerateMirrorJSON: %s", err)
}
@@ -31,6 +31,7 @@ func (m *Client) generateMirrorJSON() (map[string]interface{}, error) {
return JSON, nil
}
// Hostname Returns the hostname of the client, if it has one.
func (m *Client) Hostname() string {
if !strings.HasSuffix(m.hostname, "/") {
return m.hostname + "/"
@@ -38,17 +39,18 @@ func (m *Client) Hostname() string {
return m.hostname
}
// GenerateMirrorJSON generates the JSON file for the mirror.
func (m *Client) GenerateMirrorJSON() (string, error) {
JSON, err := m.generateMirrorJSON()
if err != nil {
return "", err
}
path := filepath.Join(tbget.DOWNLOAD_PATH, "downloads.json")
path := filepath.Join(tbget.DOWNLOAD_PATH(), "downloads.json")
preBytes, err := ioutil.ReadFile(path)
if err != nil {
return "", fmt.Errorf("GenerateMirrorJSONBytes: %s", err)
}
binpath, _, err := m.TBD.GetUpdaterForLangFromJsonBytes(preBytes, "en-US")
binpath, _, err := m.TBD.GetUpdaterForLangFromJSONBytes(preBytes, "en-US")
if err != nil {
return "", fmt.Errorf("GenerateMirrorJSONBytes: %s", err)
}
@@ -77,6 +79,7 @@ func (m *Client) GenerateMirrorJSON() (string, error) {
return "", fmt.Errorf("GenerateMirrorJSONBytes: %s", "No downloads found")
}
// GenerateReplaceString generates the string to replace in the JSON file.
func GenerateReplaceString(urlparts []string) string {
replaceString := ""
for _, val := range urlparts {

View File

@@ -4,12 +4,33 @@ import (
"io/ioutil"
"net/http"
"path/filepath"
"strings"
)
// Page generates the HTML for the panel.
func (m *Client) Page() (string, error) {
htmlbytes := htmlhead
htmlbytes = append(htmlbytes, []byte("<body>")...)
htmlbytes = append(htmlbytes, []byte(`<body>
<label class="switch">
<input type="checkbox" onclick='handleClick(this);'>
<span class="slider round"></span>
</label>`)...)
htmlbytes = append(htmlbytes, []byte(`<script>
function handleClick(cb) {
var xmlHttp = new XMLHttpRequest();
xmlHttp.open( "GET", "http://`)...)
htmlbytes = append(htmlbytes, []byte([]byte(m.GetAddress()))...)
htmlbytes = append(htmlbytes, []byte(`/switch-theme", false ); // false for synchronous request
xmlHttp.send( null );
location.reload();
return xmlHttp.responseText;
}
</script>
`)...)
mdbytes := m.PageHTML()
htmlbytes = append(htmlbytes, mdbytes...)
@@ -20,7 +41,7 @@ func (m *Client) Page() (string, error) {
htmlbytes = append(htmlbytes, m.TorOffStatusHTML(ours)...)
}
htmlbytes = append(htmlbytes, []byte(`</body>
<html>`)...)
</html>`)...)
return string(htmlbytes), nil
}
@@ -47,8 +68,14 @@ func (m *Client) serveJSON(rw http.ResponseWriter, rq *http.Request) {
func (m *Client) serveCSS(rw http.ResponseWriter, rq *http.Request) {
cssbytes, err := ioutil.ReadFile(filepath.Join(m.TBD.DownloadPath, rq.URL.Path))
if err != nil {
if m.DarkMode {
rw.Header().Set("Content-Type", "text/css")
rw.Write(darkDefaultCSS)
return
}
rw.Header().Set("Content-Type", "text/css")
rw.Write(defaultCSS)
return
}
rw.Header().Set("Content-Type", "text/css")
rw.Write(cssbytes)
@@ -66,6 +93,19 @@ func (m *Client) serveJS(rw http.ResponseWriter, rq *http.Request) {
func (m *Client) servePNG(rw http.ResponseWriter, rq *http.Request) {
pngbytes, err := ioutil.ReadFile(filepath.Join(m.TBD.DownloadPath, rq.URL.Path))
if err != nil {
rw.Header().Set("Content-Type", "image/png")
if strings.HasSuffix(rq.URL.Path, "garliconion.png") {
if bytes, err := m.TBD.Profile.ReadFile("garliconion.png"); err == nil {
rw.Write(bytes)
return
}
}
if strings.HasSuffix(rq.URL.Path, "onion.png") {
if bytes, err := m.TBD.Profile.ReadFile("onion.png"); err == nil {
rw.Write(bytes)
return
}
}
return
}
rw.Header().Set("Content-Type", "image/png")

View File

@@ -2,26 +2,35 @@ package tbserve
import (
"embed"
"io/ioutil"
"log"
"net/http"
"path/filepath"
"strconv"
"strings"
"github.com/justinas/nosurf"
cp "github.com/otiai10/copy"
tbget "i2pgit.org/idk/i2p.plugins.tor-manager/get"
TBSupervise "i2pgit.org/idk/i2p.plugins.tor-manager/supervise"
)
// Client manages and supervises a Tor Browser instance.
type Client struct {
hostname string
TBD *tbget.TBDownloader
TBS *TBSupervise.Supervisor
DarkMode bool
Host string
Port int
}
func NewClient(hostname string, lang string, os string, arch string, content *embed.FS) (*Client, error) {
// NewClient creates a new Client.
func NewClient(verbose bool, lang string, os string, arch string, content *embed.FS) (*Client, error) {
m := &Client{
hostname: hostname,
TBD: tbget.NewTBDownloader(lang, os, arch, content),
TBD: tbget.NewTBDownloader(lang, os, arch, content),
}
m.TBD.Verbose = verbose
m.TBD.MakeTBDirectory()
tgz, sig, err := m.TBD.DownloadUpdaterForLang(lang)
if err != nil {
@@ -37,8 +46,31 @@ func NewClient(hostname string, lang string, os string, arch string, content *em
return m, nil
}
// GetHost returns the hostname of the client.
func (m *Client) GetHost() string {
if m.Host == "" {
m.Host = "127.0.0.1"
}
return m.Host
}
// GetPort returns the port of the client.
func (m *Client) GetPort() string {
if m.Port == 0 {
m.Port = 7695
}
return strconv.Itoa(m.Port)
}
// GetAddress returns the address of the client.
func (m *Client) GetAddress() string {
return m.GetHost() + ":" + m.GetPort()
}
// ServeHTTP handles HTTP requests.
func (m *Client) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
path := rq.URL.Path
path := strings.Replace(rq.URL.Path, "..", "", -1)
rq.URL.Path = path
log.Printf("ServeHTTP: '%s'", path)
fileextension := filepath.Ext(path)
switch fileextension {
@@ -78,6 +110,10 @@ func (m *Client) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
log.Println("Stopping Tor")
go m.TBS.StopTor()
http.Redirect(rw, rq, "/", http.StatusFound)
case "/switch-theme":
log.Println("Switching theme")
m.DarkMode = !m.DarkMode
http.Redirect(rw, rq, "/", http.StatusFound)
default:
b, _ := m.Page()
rw.Header().Set("Content-Type", "text/html")
@@ -87,8 +123,15 @@ func (m *Client) ServeHTTP(rw http.ResponseWriter, rq *http.Request) {
}
// Serve serve the control panel locally
func (m *Client) Serve() error {
//http.Handle("/", m)
mirrorjson, err := m.GenerateMirrorJSON()
if err != nil {
return err
}
ioutil.WriteFile(filepath.Join(m.TBD.DownloadPath, "mirror.json"), []byte(mirrorjson), 0644)
cp.Copy(m.TBS.I2PProfilePath(), filepath.Join(m.TBD.DownloadPath, "i2p.firefox"))
go m.TBS.RunTorWithLang()
return http.ListenAndServe("127.0.0.1:7695", nosurf.New(m))
return http.ListenAndServe(m.GetAddress(), nosurf.New(m))
}

View File

@@ -353,4 +353,560 @@ var defaultCSS []byte = []byte(`
width: 100%
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
`)
var darkDefaultCSS []byte = []byte(`
* {
padding: 0;
margin: 0;
}
html {
margin: 0 4%;
padding: 0 20px;
min-height: 100%;
background: #9ab;
background: repeating-linear-gradient(to bottom, #9ab, #89a 2px);
scrollbar-color: #bcd #789;
}
body {
margin: 0;
padding: 20px 40px;
font-family: Open Sans, Noto Sans, Segoe UI, sans-serif;
font-size: 12pt;
color: #495057;
text-decoration: none;
word-wrap: break-word;
border-left: 1px solid #495057;
border-right: 1px solid #495057;
box-shadow: 0 0 2px 2px rgba(0, 0, 0, .1);
background: #f2f2f2;
}
h1, h2, h3, h4 {
display: block;
font-weight: 700;
}
h1 {
text-transform: uppercase;
font-weight: 900;
font-size: 200%;
}
h2 {
font-size: 140%;
}
h3 {
font-size: 120%;
}
h4 {
margin-bottom: 5px;
text-align: right;
text-transform: none;
font-size: 90%;
font-weight: 600;
font-style: italic;
}
p {
margin-bottom: 15px;
width: 100%;
line-height: 1.4;
word-wrap: break-word;
/* text-align: justify;*/
text-decoration: none;
}
ul {
margin: 10px 20px;
list-style: none;
}
li {
margin-left: 0;
padding: 12px 15px 15px 20px;
width: calc(100% - 40px);
text-align: justify;
border: 1px solid #9ab;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff;
background: #dee2e6;
}
li li {
padding-bottom: 0;
width: calc(100% - 40px);
text-align: left;
border: none;
border-top: 1px solid #9ab;
box-shadow: none;
}
li li:first-of-type {
margin-top: 15px;
border-top: none;
}
li a:first-of-type {
display: block;
width: 100%;
}
#applicationExplain {
float: unset;
}
li+li {
margin-top: 15px;
}
h3+ul, ul+h3, ul+h2 {
margin-top: 20px;
}
a, button {
color: #3b6bbf;
text-decoration: none;
font-weight: 700;
word-wrap: break-word;
outline: 0;
}
.applicationDesc {
color: #81888f;
text-decoration: none;
font-weight: 700;
word-wrap: break-word;
outline: 0;
}
.applicationDesc:hover, a:hover, button:hover {
text-decoration: none;
font-weight: 700;
word-wrap: break-word;
outline: 0;
}
button {
border: none;
cursor: pointer;
color: #3b6bbf;
text-decoration: none;
font-weight: 700;
word-wrap: break-word;
outline: 0;
}
.background {
background-color: #f8f8ff;
height: 100%;
}
.content {
margin: 1.5rem;
padding: 1rem;
min-height: 3rem;
min-width: 95%;
display: inline-block;
border: 1px solid #d9d9d6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
background: #f8f8ff;
}
#header, .application-info, .browser-info, .extended-info, .search-info {
margin-top: 1.5rem;
padding: 1rem;
min-height: 3rem;
min-width: 95%;
display: inline-block;
border: 1px solid #d9d9d6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
background: #f8f8ff;
}
.showhider {
margin-right: auto;
padding: 0!important;
text-transform: uppercase;
background: none !important;
border: none;
width: 90%;
color: #3b6bbf;
text-decoration: none;
font-weight: 700;
word-wrap: break-word;
outline: 0;
text-align: left;
}
#links .showhider {
font-size: 25px;
}
.section-header {
display: flex;
flex-direction: row;
margin-bottom: 80px;
}
#readyness {
padding-top: 1rem;
padding-bottom: 1rem;
margin: 1rem;
width: 42%;
min-width: 42%;
background: #dee2e6;
text-align: center!important;
border: 1px solid #dee2e6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
display: inline-block;
}
#onboarding {
min-height: 5rem;
padding: .5rem;
margin: .5rem;
margin-top: 4rem;
width: 42%;
min-width: 42%;
font-size: 2rem;
background: #a48fe1;
text-align: center!important;
border: 1px solid #a48fe1;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
#i2pbrowser-description {
padding-top: 1rem;
padding-bottom: 1rem;
width: 50%;
min-width: 50%;
display: inline-block;
background: #dee2e6;
border: 1px solid #dee2e6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
#linksExplain {
min-height: 5rem;
padding: .5rem;
margin: .5rem;
width: 30%;
min-width: 30%;
background: #dee2e6;
text-align: center!important;
border: 1px solid #dee2e6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
#applicationExplain, #controlExplain {
min-height: 5rem;
padding: .5rem;
margin: .5rem;
width: 30%;
min-width: 30%;
background: #dee2e6;
text-align: center!important;
border: 1px solid #dee2e6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
float: left;
}
#proxyReady {
min-height: 3rem;
padding: .5rem;
margin: .2rem;
width: 38%;
min-width: 38%;
display: inline-block;
background: #d9d9d6;
float: right;
text-align: center!important;
border: 1px solid #d9d9d6;
border-radius: 2px;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
#proxyUnready {
min-height: 3rem;
padding: .5rem;
margin: .2rem;
width: 38%;
min-width: 38%;
display: inline-block;
float: right;
text-align: center!important;
border: 1px solid #ffc56d;
border-radius: 2px;
background: #ffc56d;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
#consoleOn {
min-height: 3rem;
padding: .5rem;
margin: .2rem;
width: 38%;
min-width: 38%;
display: inline-block;
float: left;
text-align: center!important;
border: 1px solid #f7e59a;
border-radius: 2px;
background: #f7e59a;
box-shadow: inset 0 0 0 1px #fff, 0 0 1px #ccc;
}
.onboardingContent {
font-size: .8rem!important;
text-align: left;
display: none;
}
#info-content {
display: none;
}
.consoleOn:hover #proxy-check, .proxyReady:hover #proxy-check {
visibility: visible;
opacity: 1;
}
img {
max-width: 100%;
}
img.readyness {
height: 100%;
width: auto;
}
@media only screen and (max-width: 399px) {
.application-info {
display: none;
}
}
@media screen and (max-width: 1200px) {
body {
font-size: 10.5pt;
}
}
video {
width: 100%
}
a {
color: rgb(140, 140, 250);
}
::-webkit-scrollbar-track-piece {
background-color: rgba(255, 255, 255, 0.2) !important;
}
::-webkit-scrollbar-track {
background-color: rgba(255, 255, 255, 0.3) !important;
}
::-webkit-scrollbar-thumb {
background-color: rgba(255, 255, 255, 0.5) !important;
}
embed[type="application/pdf"] {
filter: invert(90%);
}
html {
color: rgb(191, 191, 191);
background: rgb(31, 31, 31) !important;
}
body {
background-color: rgb(31, 31, 31);
background-image: none !important;
}
input,
select,
textarea,
button {
color: rgb(191, 191, 191);
background-color: rgb(31, 31, 31);
}
font {
color: rgb(191, 191, 191);
}
html {
filter: contrast(100%) brightness(100%) saturate(100%);
}
.NIGHTEYE_Filter {
width: 100%;
height: 100%;
position: fixed;
left: 0px;
top: 0px;
pointer-events: none;
z-index: 2147483647;
}
.NIGHTEYE_YellowFilter {
background: rgba(255, 255, 0, 0.15);
opacity: 0;
}
.NIGHTEYE_BlueFilter {
background: rgba(0, 0, 255, 0.15);
opacity: 0;
}
.NIGHTEYE_DimFilter {
background: rgba(0, 0, 0, 0.5);
opacity: 0;
}
.NIGHTEYE_TransformZ {
transform: translateZ(0px);
}
/* The switch - the box around the slider */
.switch {
position: relative;
display: inline-block;
width: 60px;
height: 34px;
}
/* Hide default HTML checkbox */
.switch input {
opacity: 0;
width: 0;
height: 0;
}
/* The slider */
.slider {
position: absolute;
cursor: pointer;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: #ccc;
-webkit-transition: .4s;
transition: .4s;
}
.slider:before {
position: absolute;
content: "";
height: 26px;
width: 26px;
left: 4px;
bottom: 4px;
background-color: white;
-webkit-transition: .4s;
transition: .4s;
}
input:checked + .slider {
background-color: #2196F3;
}
input:focus + .slider {
box-shadow: 0 0 1px #2196F3;
}
input:checked + .slider:before {
-webkit-transform: translateX(26px);
-ms-transform: translateX(26px);
transform: translateX(26px);
}
/* Rounded sliders */
.slider.round {
border-radius: 34px;
}
.slider.round:before {
border-radius: 50%;
}
`)

View File

@@ -7,7 +7,7 @@ import (
"github.com/russross/blackfriday"
)
var defaultmd []byte = []byte(`
var dmd string = `
# Tor Binary Manager
This plugin manages the Tor Browser Bundle and a Tor binary
@@ -16,14 +16,15 @@ an alternative to a fixed outproxy by using Tor, and also
provides a way to run I2P in the Tor Browser without any other
configuration.
- [Launch I2P in Tor Browser](/launch-i2p-browser)
- [Launch Tor Browser](/launch-tor-browser)
- [![Launch I2P in Tor Browser](garliconion.png) - Launch I2P in Tor Browser](/launch-i2p-browser)
- [![Launch Tor Browser](onion.png) - Launch Tor Browser](/launch-tor-browser)
## Tor Controls
`)
`
var defaultmd []byte = []byte(dmd)
var htmlhead []byte = []byte(`
var hhd string = `
<!DOCTYPE html>
<html>
<head>
@@ -32,24 +33,35 @@ var htmlhead []byte = []byte(`
<title>Tor Binary Manager</title>
<link rel="stylesheet" href="/style.css">
</head>
`)
`
var torstart []byte = []byte(`
var htmlhead []byte = []byte(hhd)
var tstart string = `
- [![Stop Tor](/stop-tor.png)](/stop-tor)
`)
`
var torstop []byte = []byte(`
var torstart []byte = []byte(tstart)
var tstop string = `
- [![Start Tor](/start-tor.png)](/start-tor)
`)
`
var torrunning []byte = []byte(`
var torstop []byte = []byte(tstop)
var trun string = `
- Tor is Running as a System Service
`)
`
var torstopped []byte = []byte(`
var torrunning []byte = []byte(trun)
var tstopped string = `
- Tor is Stopped and there is no System Service
`)
`
var torstopped []byte = []byte(tstopped)
// PageHTML returns the HTML for the page heading
func (m *Client) PageHTML() []byte {
dir := filepath.Dir(m.TBD.DownloadPath)
mdpath := filepath.Join(dir, m.TBD.Lang, "index.md")
@@ -62,6 +74,7 @@ func (m *Client) PageHTML() []byte {
return htmlbytes
}
// TorOnStatusHTML returns the HTML for "Tor Status" section the page
func (m *Client) TorOnStatusHTML(ours bool) []byte {
dir := filepath.Dir(m.TBD.DownloadPath)
if ours {
@@ -70,44 +83,39 @@ func (m *Client) TorOnStatusHTML(ours bool) []byte {
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torstop)
return htmlbytes
} else {
htmlbytes := blackfriday.MarkdownCommon(torbytes)
return htmlbytes
}
} else {
mdpath := filepath.Join(dir, m.TBD.Lang, "toron.md")
toron, err := ioutil.ReadFile(mdpath)
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torrunning)
return htmlbytes
} else {
htmlbytes := blackfriday.MarkdownCommon(toron)
return htmlbytes
}
htmlbytes := blackfriday.MarkdownCommon(torbytes)
return htmlbytes
}
mdpath := filepath.Join(dir, m.TBD.Lang, "torstarted.md")
toron, err := ioutil.ReadFile(mdpath)
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torrunning)
return htmlbytes
}
htmlbytes := blackfriday.MarkdownCommon(toron)
return htmlbytes
}
// TorOffStatusHTML returns the HTML for "Tor Status" section the page
func (m *Client) TorOffStatusHTML(ours bool) []byte {
dir := filepath.Dir(m.TBD.DownloadPath)
if ours {
mdpath := filepath.Join(dir, m.TBD.Lang, "stoptor.md")
mdpath := filepath.Join(dir, m.TBD.Lang, "startor.md")
torbytes, err := ioutil.ReadFile(mdpath)
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torstart)
return htmlbytes
} else {
htmlbytes := blackfriday.MarkdownCommon(torbytes)
return htmlbytes
}
} else {
mdpath := filepath.Join(dir, m.TBD.Lang, "toron.md")
toroff, err := ioutil.ReadFile(mdpath)
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torstopped)
return htmlbytes
} else {
htmlbytes := blackfriday.MarkdownCommon(toroff)
return htmlbytes
}
htmlbytes := blackfriday.MarkdownCommon(torbytes)
return htmlbytes
}
mdpath := filepath.Join(dir, m.TBD.Lang, "torstopped.md")
toroff, err := ioutil.ReadFile(mdpath)
if err != nil {
htmlbytes := blackfriday.MarkdownCommon(torstopped)
return htmlbytes
}
htmlbytes := blackfriday.MarkdownCommon(toroff)
return htmlbytes
}

104
supervise/nontor.go Normal file
View File

@@ -0,0 +1,104 @@
package tbsupervise
var secbrowserjs = []byte(`
// Copyright (C) 2019 - 2021 ENCRYPTED SUPPORT LP <adrelanos@whonix.org>
// See the file COPYING for copying conditions.
// Warning! These settings disable Tor. You will not be anonymous!
// Configure Tor Browser without Tor settings for an everyday use
// security hardened browser. Take advantage of its excellent
// enhancements for reducing linkability, that is, "the ability
// for a user's activity on one site to be linked with their
// activity on another site without their knowledge or explicit
// consent."
// - See https://www.whonix.org/wiki/Tor_Browser_without_Tor
// - See https://www.whonix.org/wiki/SecBrowser
// This file gets copied at first start to:
// ~/.secbrowser/secbrowser/Browser/TorBrowser/Data/Browser/profile.default/user.js
// Disable Torbutton and Torlauncher extensions
user_pref("extensions.torbutton.startup", false);
user_pref("extensions.torlauncher.start_tor", false);
user_pref("network.proxy.socks_remote_dns", false);
// https://forums.whonix.org/t/tor-browser-10-without-tor/10313
user_pref("network.dns.disabled", false);
// Disable function torbutton source file:
// src/chrome/content/torbutton.js
// function: torbutton_do_tor_check
// and thereby also function: torbutton_initiate_remote_tor_check
// disables Control Port verification and remote Tor connection check.
user_pref("extensions.torbutton.test_enabled", false);
// Set security slider "Safest".
// Broken, therefore disabled by default.
// https://forums.whonix.org/t/broken-security-slider/8675
// user_pref("extensions.torbutton.inserted_security_level", true);
// user_pref("extensions.torbutton.security_slider", 1);
// Normalize Tor Browser behavior
user_pref("extensions.torbutton.noscript_persist", true);
user_pref("browser.privatebrowsing.autostart", false);
// Save passwords.
user_pref("signon.rememberSignons", true);
// Required for saving passwords.
// https://trac.torproject.org/projects/tor/ticket/30565#comment:7
user_pref("security.nocertdb", false);
// Disable Letterboxing.
// https://forums.whonix.org/t/is-anyone-having-white-bars-in-the-tbb-tor-browser-letterboxing/8345
// https://forums.whonix.org/t/secbrowser-a-security-hardened-non-anonymous-browser/3822/156
user_pref("privacy.resistFingerprinting.letterboxing", false);
// Enable punycode to fix
// very hard to notice Phishing Scam - Firefox / Tor Browser URL not showing real Domain Name - Homograph attack (Punycode).
// https://forums.whonix.org/t/very-hard-to-notice-phishing-scam-firefox-tor-browser-url-not-showing-real-domain-name-homograph-attack-punycode/8373
// https://forums.whonix.org/t/secbrowser-a-security-hardened-non-anonymous-browser/3822/162
user_pref("network.IDN_show_punycode", true);
// Disable popup asking to prefer onions since onions will not work in clearnet browser.
user_pref("privacy.prioritizeonions.showNotification", false);
`)
var secbrowserhtml = []byte(`
<!DOCTYPE html>
<html>
<head>
<title>i2p.plugins.tor-manager - Tor Binary Manager</title>
<link rel="stylesheet" type="text/css" href ="/style.css" />
</head>
<body>
<h1 id="running-in-clearnet-mode">Running in Clearnet Mode</h1>
<p>Tor Browser is configured to run without Tor, and will now use the non-anonymous web. It is also configured to use uBlock Origin. This allows you to use a hardened web browser for your non-anonymous tasks.</p>
<ul>
<li>To get started, perhaps try <a href="https://duckduckgo.com">DuckDuckGo</a></li>
<li>or <a href="https://privacyguides.org/">PrivacyGuides</a></li>
</ul>
<p>This wrapper has been developed for use with the I2P project. To learn more about I2P, visit [Get I2P](https://geti2p.net)</p>
</body>
</html>
`)
var offlinehtml = []byte(`
<!DOCTYPE html>
<html>
<head>
<title>i2p.plugins.tor-manager - Tor Binary Manager</title>
<link rel="stylesheet" type="text/css" href ="/style.css" />
</head>
<body>
<h1 id="running-in-offline-mode">Running in Offline Mode</h1>
<p>Tor Browser is configured to run without <em>any</em> access to the clearnet, and will now only use local services running on this device. This uses a different mechanism than Firefoxs normal work offline mode and cannot be canceled.</p>
<ul>
<li>Visit the <a href="http://127.0.0.1:7657">I2P Router Console</a></li>
<li>Visit the <a href="http://127.0.0.1:8888">Freenet FProxy</a></li>
</ul>
<p>This wrapper has been developed for use with the I2P project. To learn more about I2P, visit [Get I2P](https://geti2p.net)</p>
</body>
</html>
`)

View File

@@ -9,36 +9,79 @@ import (
"net"
"os"
"os/exec"
"path"
"path/filepath"
"strings"
"github.com/mitchellh/go-ps"
"github.com/otiai10/copy"
cp "github.com/otiai10/copy"
tbget "i2pgit.org/idk/i2p.plugins.tor-manager/get"
)
// UNPACK_URL is the URL to place to unpack the Browser Bundle
var UNPACK_URL = tbget.UNPACK_PATH
// DEFAULT_TB_LANG is the default language to use for the Tor Browser Bundle
var DEFAULT_TB_LANG = tbget.DefaultIETFLang
var (
OS = tbget.OS
ARCH = tbget.ARCH
)
// OS returns the current OS
func OS() string {
return tbget.OS
}
// ARCH returns the current architecture
func ARCH() string {
return tbget.ARCH
}
// Supervisor is the main struct for the Tor Browser Bundle Supervisor
type Supervisor struct {
UnpackPath string
Lang string
torcmd *exec.Cmd
tbcmd *exec.Cmd
ibcmd *exec.Cmd
Profile *embed.FS
//tbcmd *exec.Cmd
//ibcmd *exec.Cmd
Profile *embed.FS
PassThroughArgs []string
}
// PTAS is the validator for the pass-through arguments
func (s *Supervisor) PTAS() []string {
// loop over the arguments and make sure that we remove any --profile, -P args
// and blank them out.
var args []string
for index, arg := range s.PassThroughArgs {
if arg == "--profile" || arg == "-P" || arg == "-profile" {
continue
}
if index > 0 {
if s.PassThroughArgs[index-1] == "--profile" || s.PassThroughArgs[index-1] == "-P" || s.PassThroughArgs[index-1] == "-profile" {
continue
}
}
args = append(args, arg)
}
return args
}
// TBPath returns the path to the Tor Browser Bundle launcher
func (s *Supervisor) TBPath() string {
return filepath.Join(s.UnpackPath, "Browser", "start-tor-browser")
switch OS() {
case "linux":
return filepath.Join(s.UnpackPath, "Browser", "start-tor-browser")
case "osx":
return filepath.Join(s.UnpackPath, "Browser", "Tor Browser.app", "Contents", "MacOS", "start-tor-browser")
case "windows":
return filepath.Join(s.TBDirectory(), "firefox.exe")
default:
return filepath.Join(s.TBDirectory(), "firefox")
}
}
// FirefoxPath returns the path to the Firefox executable inside Tor Browser
func (s *Supervisor) FirefoxPath() string {
switch OS {
switch OS() {
case "linux":
return filepath.Join(s.UnpackPath, "Browser", "firefox.real")
case "windows":
@@ -48,49 +91,126 @@ func (s *Supervisor) FirefoxPath() string {
}
}
// TBDirectory returns the path to the Tor Browser Bundle directory
func (s *Supervisor) TBDirectory() string {
return filepath.Join(s.UnpackPath, "Browser")
}
// TorPath returns the path to the Tor executable
func (s *Supervisor) TorPath() string {
if OS() == "osx" {
return filepath.Join(s.UnpackPath, "Tor Browser.app", "Contents", "Resources", "TorBrowser", "Tor", "tor")
}
return filepath.Join(s.UnpackPath, "Browser", "TorBrowser", "Tor", "tor")
}
// TorDataPath returns the path to the Tor Browser Bundle Data directory
func (s *Supervisor) TorDataPath() string {
return filepath.Join(s.UnpackPath, "Browser", "TorBrowser", "Data")
}
func (s *Supervisor) I2PDataPath() string {
fp := filepath.Join(filepath.Dir(s.UnpackPath), "i2p.firefox")
if tbget.FileExists(fp) {
return fp
} else {
//unpack the embedded profile
// I2PProfilePath returns the path to the I2P profile
func (s *Supervisor) I2PProfilePath() string {
fp := filepath.Join(filepath.Dir(s.UnpackPath), ".i2p.firefox")
if !tbget.FileExists(fp) {
log.Printf("i2p data not found at %s, unpacking", fp)
if s.Profile != nil {
if err := s.UnpackI2PData(); err != nil {
log.Fatal(err)
}
}
return fp
}
return fp
}
// I2PProfilePath returns the path to the I2P profile
func (s *Supervisor) I2PAppProfilePath() string {
fp := filepath.Join(filepath.Dir(s.UnpackPath), ".i2p.firefox.config")
if !tbget.FileExists(fp) {
log.Printf("i2p app data not found at %s, unpacking", fp)
if s.Profile != nil {
if err := s.UnpackI2PAppData(); err != nil {
log.Fatal(err)
}
}
}
return fp
}
// I2PDataPath returns the path to the I2P data directory
func (s *Supervisor) I2PDataPath() string {
fp := s.I2PProfilePath()
up := filepath.Join(filepath.Dir(s.UnpackPath), "i2p.firefox")
if tbget.FileExists(up) {
return up
}
log.Printf("i2p workdir not found at %s, copying", up)
if s.Profile != nil {
if err := cp.Copy(fp, up); err != nil {
log.Fatal(err)
}
}
return up
}
// UnpackI2PData unpacks the I2P data into the s.UnpackPath
func (s *Supervisor) UnpackI2PData() error {
return fs.WalkDir(s.Profile, ".", func(path string, d fs.DirEntry, err error) error {
fp := filepath.Join(filepath.Dir(s.UnpackPath), "i2p.firefox")
return fs.WalkDir(s.Profile, ".", func(embedpath string, d fs.DirEntry, err error) error {
fp := filepath.Join(filepath.Dir(s.UnpackPath), ".i2p.firefox")
if err != nil {
log.Fatal(err)
}
fmt.Println(path, filepath.Join(fp, strings.Replace(path, "tor-browser/unpack/i2p.firefox", "", -1)))
fmt.Println(embedpath, filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox", "", -1)))
if d.IsDir() {
os.MkdirAll(filepath.Join(fp, strings.Replace(path, "tor-browser/unpack/i2p.firefox", "", -1)), 0755)
os.MkdirAll(filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox", "", -1)), 0755)
} else {
fullpath := filepath.Join(path)
fullpath := path.Join(embedpath)
bytes, err := s.Profile.ReadFile(fullpath)
if err != nil {
return err
}
unpack := filepath.Join(fp, strings.Replace(path, "tor-browser/unpack/i2p.firefox", "", -1))
unpack := filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox", "", -1))
if err := ioutil.WriteFile(unpack, bytes, 0644); err != nil {
return err
}
}
return nil
})
}
// I2PAppDataPath returns the path to the I2P application data directory
func (s *Supervisor) I2PAppDataPath() string {
fp := s.I2PAppProfilePath()
up := filepath.Join(filepath.Dir(s.UnpackPath), "i2p.firefox.config")
if tbget.FileExists(up) {
return up
}
log.Printf("i2p workdir not found at %s, copying", up)
if s.Profile != nil {
if err := cp.Copy(fp, up); err != nil {
log.Fatal(err)
}
}
return up
}
// UnpackI2PAppData unpacks the I2P application data into the s.UnpackPath
func (s *Supervisor) UnpackI2PAppData() error {
return fs.WalkDir(s.Profile, ".", func(embedpath string, d fs.DirEntry, err error) error {
fp := filepath.Join(filepath.Dir(s.UnpackPath), ".i2p.firefox.config")
if err != nil {
log.Fatal(err)
}
fmt.Println(embedpath, filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox.config", "", -1)))
if d.IsDir() {
os.MkdirAll(filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox.config", "", -1)), 0755)
} else {
fullpath := path.Join(embedpath)
bytes, err := s.Profile.ReadFile(fullpath)
if err != nil {
return err
}
unpack := filepath.Join(fp, strings.Replace(embedpath, "tor-browser/unpack/i2p.firefox.config", "", -1))
if err := ioutil.WriteFile(unpack, bytes, 0644); err != nil {
return err
}
@@ -100,49 +220,97 @@ func (s *Supervisor) UnpackI2PData() error {
}
func (s *Supervisor) tbbail() error {
if s.tbcmd != nil && s.tbcmd.Process != nil && s.tbcmd.ProcessState != nil {
if s.tbcmd.ProcessState.Exited() {
return nil
}
return fmt.Errorf("Already running")
}
return nil
return s.ibbail()
}
// RunTBWithLang runs the Tor Browser with the given language
func (s *Supervisor) RunTBWithLang() error {
tbget.ARCH = ARCH
tbget.ARCH = ARCH()
if s.Lang == "" {
s.Lang = DEFAULT_TB_LANG
}
if s.UnpackPath == "" {
s.UnpackPath = UNPACK_URL
s.UnpackPath = UNPACK_URL()
}
if s.tbbail() != nil {
return nil
}
log.Println("running tor browser with lang", s.Lang, s.UnpackPath)
switch OS {
log.Println("running tor browser with lang", s.Lang, s.UnpackPath, OS())
switch OS() {
case "linux":
if tbget.FileExists(s.UnpackPath) {
log.Println("running tor browser with lang", s.Lang, s.UnpackPath)
s.tbcmd = exec.Command(s.TBPath())
s.tbcmd.Stdout = os.Stdout
s.tbcmd.Stderr = os.Stderr
return s.tbcmd.Run()
} else {
log.Println("tor browser not found at", s.TBPath())
return fmt.Errorf("tor browser not found at %s", s.TBPath())
args := []string{}
args = append(args, s.PTAS()...)
bcmd := exec.Command(s.TBPath(), args...)
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
}
case "darwin":
s.tbcmd = exec.Command("/usr/bin/env", "open", "-a", "\"Tor Browser.app\"")
s.tbcmd.Dir = s.TBDirectory()
return s.tbcmd.Run()
case "windows":
s.tbcmd = exec.Command("cmd", "/c", "start", "\""+s.TBDirectory()+"\"", "\"firefox.exe\"")
s.tbcmd.Dir = s.TBDirectory()
return s.tbcmd.Run()
log.Println("tor browser not found at", s.TBPath())
return fmt.Errorf("tor browser not found at %s", s.TBPath())
case "osx":
firefoxPath := filepath.Join(s.UnpackPath, "Tor Browser.app", "Contents", "MacOS", "firefox")
bcmd := exec.Command(firefoxPath)
bcmd.Dir = s.UnpackPath
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
case "win":
log.Println("Running Windows EXE", s.TBDirectory(), "firefox.exe")
args := []string{}
args = append(args, s.PTAS()...)
bcmd := exec.Command(s.TBPath(), args...)
bcmd.Dir = s.TBDirectory()
return bcmd.Run()
default:
}
return nil
}
// RunTBWithLang runs the Tor Browser with the given language
func (s *Supervisor) RunTBHelpWithLang() error {
tbget.ARCH = ARCH()
if s.Lang == "" {
s.Lang = DEFAULT_TB_LANG
}
if s.UnpackPath == "" {
s.UnpackPath = UNPACK_URL()
}
if s.tbbail() != nil {
return nil
}
log.Println("running tor browser with lang", s.Lang, s.UnpackPath, OS())
switch OS() {
case "linux":
if tbget.FileExists(s.UnpackPath) {
log.Println("running tor browser with lang", s.Lang, s.UnpackPath)
bcmd := exec.Command(s.TBPath(), "--help")
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
}
log.Println("tor browser not found at", s.TBPath())
return fmt.Errorf("tor browser not found at %s", s.TBPath())
case "osx":
firefoxPath := filepath.Join(s.UnpackPath, "Tor Browser.app", "Contents", "MacOS", "firefox")
bcmd := exec.Command(firefoxPath, "--help")
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
bcmd.Dir = s.TBDirectory()
return bcmd.Run()
case "win":
log.Println("Running Windows EXE", s.TBDirectory(), "firefox.exe")
bcmd := exec.Command(s.TBPath(), "--help")
bcmd.Dir = s.TBDirectory()
return bcmd.Run()
default:
}
@@ -150,83 +318,243 @@ func (s *Supervisor) RunTBWithLang() error {
}
func (s *Supervisor) ibbail() error {
if s.ibcmd != nil && s.ibcmd.Process != nil && s.ibcmd.ProcessState != nil {
if s.ibcmd.ProcessState.Exited() {
return nil
processes, err := ps.Processes()
if err != nil {
return nil
}
for _, p := range processes {
if p.Executable() == s.TorPath() {
var err error
s.torcmd.Process, err = os.FindProcess(p.Pid())
if err == nil {
return fmt.Errorf("Already running")
}
}
return fmt.Errorf("Already running")
}
return nil
}
// RunI2PBWithLang runs the I2P Browser with the given language
func (s *Supervisor) RunI2PBWithLang() error {
tbget.ARCH = ARCH
if s.ibbail() != nil {
return nil
}
// export TOR_HIDE_BROWSER_LOGO=1
os.Setenv("TOR_HIDE_BROWSER_LOGO", "1")
return s.RunTBBWithProfile(s.I2PDataPath())
}
// RunI2PBAppWithLang runs the I2P Browser with the given language
func (s *Supervisor) RunI2PBAppWithLang() error {
if s.ibbail() != nil {
return nil
}
// export TOR_HIDE_BROWSER_LOGO=1
os.Setenv("TOR_HIDE_BROWSER_LOGO", "1")
return s.RunTBBWithOfflineClearnetProfile(s.I2PAppDataPath(), true, false)
}
func (s *Supervisor) GenerateClearnetProfile(profiledata string) error {
apath, err := filepath.Abs(profiledata)
if err != nil {
return err
}
// see: https://github.com/Whonix/tb-starter/blob/b5d2280ad445bc1fbdb613424664bf8503e6f395/usr/share/secbrowser/variables.bsh
// export TOR_NO_DISPLAY_NETWORK_SETTINGS=1
os.Setenv("TOR_NO_DISPLAY_NETWORK_SETTINGS", "1")
// export TOR_HIDE_BROWSER_LOGO=1
os.Setenv("TOR_HIDE_BROWSER_LOGO", "1")
// export TOR_SKIP_CONTROLPORTTEST=1
os.Setenv("TOR_SKIP_CONTROLPORTTEST", "1")
// export TOR_SKIP_LAUNCH=1
os.Setenv("TOR_SKIP_LAUNCH", "1")
// export TOR_TRANSPROXY=1
os.Setenv("TOR_TRANSPROXY", "1")
odir := filepath.Join(apath, "extensions")
if err := os.MkdirAll(odir, 0755); err != nil {
return err
}
if !tbget.FileExists(filepath.Join(apath, "user.js")) {
err := ioutil.WriteFile(filepath.Join(apath, "user.js"), secbrowserjs, 0644)
if err != nil {
return err
}
}
if !tbget.FileExists(filepath.Join(apath, "pref.js")) {
err := ioutil.WriteFile(filepath.Join(apath, "pref.js"), secbrowserjs, 0644)
if err != nil {
return err
}
}
htmlfile := filepath.Join(apath, "index.html")
if !tbget.FileExists(htmlfile) {
err := ioutil.WriteFile(htmlfile, []byte(secbrowserhtml), 0644)
if err != nil {
return err
}
}
opath := filepath.Join(odir, "uBlock0@raymondhill.net.xpi")
ipath := filepath.Join(filepath.Dir(s.UnpackPath), ".i2p.firefox", "extensions", "uBlock0@raymondhill.net.xpi")
if err := copy.Copy(ipath, opath); err != nil {
return err
}
return nil
}
func (s *Supervisor) CopyAWOXPI(profiledata string) error {
// export TOR_HIDE_BROWSER_LOGO=1
os.Setenv("TOR_HIDE_BROWSER_LOGO", "1")
apath, err := filepath.Abs(profiledata)
if err != nil {
return err
}
odir := filepath.Join(apath, "extensions")
if err := os.MkdirAll(odir, 0755); err != nil {
return err
}
if !tbget.FileExists(filepath.Join(apath, "user.js")) {
err := ioutil.WriteFile(filepath.Join(apath, "user.js"), []byte("#\n"), 0644)
if err != nil {
return err
}
}
if !tbget.FileExists(filepath.Join(apath, "pref.js")) {
err := ioutil.WriteFile(filepath.Join(apath, "pref.js"), []byte("#\n"), 0644)
if err != nil {
return err
}
}
opath := filepath.Join(odir, "awo@eyedeekay.github.io.xpi")
htmlfile := filepath.Join(apath, "index.html")
if !tbget.FileExists(htmlfile) {
err := ioutil.WriteFile(htmlfile, []byte(offlinehtml), 0644)
if err != nil {
return err
}
}
ipath := filepath.Join(filepath.Dir(s.UnpackPath), "awo@eyedeekay.github.io.xpi")
if err := copy.Copy(ipath, opath); err != nil {
return err
}
return nil
}
// RunTBBWithOfflineProfile runs the I2P Browser with the given language
func (s *Supervisor) RunTBBWithOfflineClearnetProfile(profiledata string, offline, clearnet bool) error {
defaultpage := "about:blank"
if clearnet {
log.Print("Generating Clearnet Profile")
if err := s.GenerateClearnetProfile(profiledata); err != nil {
log.Println("Error generating Clearnet Profile", err)
return err
}
defaultpage = profiledata + "/index.html"
}
if offline {
if err := s.CopyAWOXPI(profiledata); err != nil {
log.Println("Error copying AWO XPI", err)
return err
}
if !strings.Contains(filepath.Base(profiledata), "i2p") {
defaultpage = profiledata + "/index.html"
} else {
defaultpage = "http://127.0.0.1:7657/home"
}
}
if len(s.PTAS()) > 0 {
defaultpage = s.PTAS()[0]
}
tbget.ARCH = ARCH()
if s.Lang == "" {
s.Lang = DEFAULT_TB_LANG
}
if s.UnpackPath == "" {
s.UnpackPath = UNPACK_URL
s.UnpackPath = UNPACK_URL()
}
if s.ibbail() != nil {
return nil
}
log.Println("running tor browser with lang", s.Lang, s.UnpackPath)
switch OS {
log.Println("running i2p in tor browser with lang", s.Lang, s.UnpackPath, OS())
switch OS() {
case "linux":
if tbget.FileExists(s.UnpackPath) {
log.Println("running Tor browser with lang and I2P Profile", s.Lang, s.UnpackPath, s.FirefoxPath(), "--profile", s.I2PDataPath())
s.ibcmd = exec.Command(s.FirefoxPath(), "--profile", s.I2PDataPath())
s.ibcmd.Stdout = os.Stdout
s.ibcmd.Stderr = os.Stderr
return s.ibcmd.Run()
} else {
log.Println("tor browser not found at", s.FirefoxPath())
return fmt.Errorf("tor browser not found at %s", s.FirefoxPath())
args := []string{"--profile", profiledata, defaultpage}
args = append(args, s.PTAS()...)
log.Println("running Tor browser with lang and Custom Profile", s.Lang, s.UnpackPath, s.FirefoxPath(), args)
bcmd := exec.Command(s.FirefoxPath(), args...)
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
}
case "darwin":
s.ibcmd = exec.Command("/usr/bin/env", "open", "-a", "\"Tor Browser.app\"")
s.ibcmd.Dir = s.TBDirectory()
return s.ibcmd.Run()
case "windows":
s.ibcmd = exec.Command("cmd", "/c", "start", "\""+s.TBDirectory()+"\"", "\"firefox.exe "+"--profile "+s.I2PDataPath()+" \"")
s.ibcmd.Dir = s.TBDirectory()
return s.ibcmd.Run()
log.Println("tor browser not found at", s.FirefoxPath())
return fmt.Errorf("tor browser not found at %s", s.FirefoxPath())
case "osx":
firefoxPath := filepath.Join(s.UnpackPath, "Tor Browser.app", "Contents", "MacOS", "firefox")
args := []string{"--profile", profiledata, defaultpage}
args = append(args, s.PTAS()...)
log.Println("running Tor browser with lang and Custom Profile", s.Lang, s.UnpackPath, firefoxPath, args)
bcmd := exec.Command(firefoxPath, args...)
bcmd.Dir = profiledata
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
case "win":
args := []string{"--profile", profiledata, defaultpage}
args = append(args, s.PTAS()...)
log.Println("running Tor browser with lang and Custom Profile", s.Lang, s.UnpackPath, s.TBPath(), args)
bcmd := exec.Command(s.TBPath(), args...)
bcmd.Dir = profiledata
bcmd.Stdout = os.Stdout
bcmd.Stderr = os.Stderr
return bcmd.Run()
default:
}
return nil
}
// RunTBBWithProfile runs the I2P Browser with the given language
func (s *Supervisor) RunTBBWithProfile(profiledata string) error {
return s.RunTBBWithOfflineClearnetProfile(profiledata, false, false)
}
func (s *Supervisor) torbail() error {
_, err := net.Listen("TCP", "127.0.0.1:9050")
_, err := net.Listen("tcp", "127.0.0.1:9050")
if err != nil {
log.Println("Already Running on 9050", err)
return fmt.Errorf("Already running")
}
if s.torcmd != nil && s.torcmd.Process != nil && s.torcmd.ProcessState != nil {
if s.torcmd.ProcessState.Exited() {
log.Println("Tor exited, restarting")
return nil
}
log.Println("Already Running")
return fmt.Errorf("Already running")
}
log.Println("Starting Tor")
return nil
}
// RunTorWithLang runs the Tor Exe with the given language
func (s *Supervisor) RunTorWithLang() error {
tbget.ARCH = ARCH
tbget.ARCH = ARCH()
if s.Lang == "" {
s.Lang = DEFAULT_TB_LANG
}
if s.UnpackPath == "" {
s.UnpackPath = UNPACK_URL
s.UnpackPath = UNPACK_URL()
}
if err := s.torbail(); err != nil {
return nil
}
log.Println("running tor with lang", s.Lang, s.UnpackPath)
switch OS {
switch OS() {
case "linux":
if tbget.FileExists(s.UnpackPath) {
log.Println("running tor with lang", s.Lang, s.UnpackPath)
@@ -234,16 +562,20 @@ func (s *Supervisor) RunTorWithLang() error {
s.torcmd.Stdout = os.Stdout
s.torcmd.Stderr = os.Stderr
return s.torcmd.Run()
} else {
log.Println("tor not found at", s.TorPath())
return fmt.Errorf("tor not found at %s", s.TorPath())
}
case "darwin":
s.torcmd = exec.Command("/usr/bin/env", "open", "-a", "\"Tor Browser.app\"")
s.torcmd.Dir = s.TBDirectory()
log.Println("tor not found at", s.TorPath())
return fmt.Errorf("tor not found at %s", s.TorPath())
case "osx":
torPath := filepath.Join(s.UnpackPath, "Tor Browser.app", "Contents", "Resources", "TorBrowser", "Tor", "tor")
s.torcmd = exec.Command(torPath)
s.torcmd.Dir = filepath.Dir(torPath)
s.torcmd.Stdout = os.Stdout
s.torcmd.Stderr = os.Stderr
defer s.torcmd.Process.Kill()
return s.torcmd.Run()
case "windows":
s.torcmd = exec.Command("cmd", "/c", "start", "\""+s.TBDirectory()+"\\TorBrowser\\Tor\"", "\"tor.exe\"")
case "win":
log.Println("Running Windows EXE", filepath.Join(s.TBDirectory(), "TorBrowser", "Tor", "tor.exe"))
s.torcmd = exec.Command(filepath.Join(s.TBDirectory(), "TorBrowser", "Tor", "tor.exe"))
s.torcmd.Dir = s.TBDirectory()
return s.torcmd.Run()
default:
@@ -252,10 +584,13 @@ func (s *Supervisor) RunTorWithLang() error {
return nil
}
// StopTor stops tor
func (s *Supervisor) StopTor() error {
return s.torcmd.Process.Kill()
}
// TorIsAlive returns true,true if tor is alive and belongs to us, true,false
// if it's alive and doesn't belong to us, false,false if no Tor can be found
func (s *Supervisor) TorIsAlive() (bool, bool) {
_, err := net.Listen("TCP", "127.0.0.1:9050")
if err != nil {
@@ -280,6 +615,7 @@ func (s *Supervisor) TorIsAlive() (bool, bool) {
return false, true
}
// NewSupervisor creates a new supervisor
func NewSupervisor(tbPath, lang string) *Supervisor {
return &Supervisor{
UnpackPath: tbPath,

View File

@@ -0,0 +1,13 @@
# Tor Binary Manager
This plugin manages the Tor Browser Bundle and a Tor binary
for you. Combined with a SOCKS5 plugin for I2P, it acts as
an alternative to a fixed outproxy by using Tor, and also
provides a way to run I2P in the Tor Browser without any other
configuration.
- [![Launch I2P in Tor Browser](garliconion.png) - Launch I2P in Tor Browser](/launch-i2p-browser)
- [![Launch Tor Browser](onion.png) - Launch Tor Browser](/launch-tor-browser)
## Tor Controls

View File

@@ -0,0 +1,2 @@
- [![Stop Tor](/stop-tor.png)](/stop-tor)

View File

@@ -0,0 +1,2 @@
- [![Start Tor](/start-tor.png)](/start-tor)

View File

@@ -0,0 +1,2 @@
- Tor is Running as a Service

View File

@@ -0,0 +1,2 @@
- Tor is Stopped and there is no Service

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,19 @@
<!DOCTYPE NETSCAPE-Bookmark-file-1>
<!-- This is an automatically generated file.
It will be read and overwritten.
DO NOT EDIT! -->
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=UTF-8">
<TITLE>Bookmarks</TITLE>
<H1>Bookmarks Menu</H1>
<DL><p>
<DT><A HREF="place:type=6&sort=14&maxResults=10" ADD_DATE="1539649423" LAST_MODIFIED="1539649424">Recent Tags</A>
<HR> <DT><A HREF="http://legwork.i2p/yacysearch.html?query=%s&verify=cacheonly&contentdom=text&nav=location%2Chosts%2Cauthors%2Cnamespace%2Ctopics%2Cfiletype%2Cprotocol%2Clanguage&startRecord=0&indexof=off&meanCount=5&resource=global&prefermaskfilter=&maximumRecords=10&timezoneOffset=0" ADD_DATE="1539652098" LAST_MODIFIED="1539652098" SHORTCUTURL="legwork.i2p">Search YaCy &#39;legwork&#39;: Search Page</A>
<DD>Software HTTP Freeware Home Page
<DT><H3 ADD_DATE="1539649419" LAST_MODIFIED="1539649423" PERSONAL_TOOLBAR_FOLDER="true">Bookmarks Toolbar</H3>
<DL><p>
<DT><A HREF="place:sort=8&maxResults=10" ADD_DATE="1539649423" LAST_MODIFIED="1539649423">Most Visited</A>
<DT><A HREF="http://i2p-projekt.i2p/" ADD_DATE="1538511080" LAST_MODIFIED="1538511080">I2P Anonymous Network</A>
<DD>Anonymous peer-to-peer distributed communication layer built with open source tools and designed to run any traditional Internet service such as email, IRC or web hosting.
</DL><p>
</DL>

View File

@@ -0,0 +1,26 @@
@namespace url("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"); /* only needed once */
@namespace html url("http://www.w3.org/1999/xhtml");
#PersonalToolbar, #PanelUI-Button, #PanelUI-menu-button, #star-button, #forward-button, #home-button, #bookmarks-toolbar-button, #library-button, #sidebar-button, #pocket-button, #fxa-toolbar-menu-button, #reader-mode-button, #identity-icon {
visibility: collapse;
}
#urlbar-background {background-color: black !important;}
/* Remove back button circle */
#back-button:not(:hover),
#back-button:not(:hover) > .toolbarbutton-icon {
background: transparent !important;
border: none !important;
box-shadow: none !important;
}
#back-button:hover,
#back-button:hover > .toolbarbutton-icon {
border: none !important;
border-radius: 2px !important;
}
#urlbar-container, #nav-bar { visibility: collapse !important }
}

View File

@@ -0,0 +1,60 @@
#! /usr/bin/env sh
if [ -f "/etc/i2pbrowser/i2pbrowserrc" ]; then
. /etc/i2pbrowser/i2pbrowserrc
fi
if [ ! -z $I2PROUTER ]; then
"$I2PROUTER" start
fi
if [ -f "$HOME/.i2p/router.config" ]; then
if [ "$0" = "/usr/local/bin/i2pconfig" ]; then
if ! grep -R 'routerconsole.browser' "$HOME/.i2p/router.config" ; then
echo "routerconsole.browser=$0" | tee -a "$HOME/.i2p/router.config"
fi
fi
fi
if [ -z $CONFIGURING_PROFILE ]; then
CONFIGURING_PROFILE="."
fi
if [ -z $ROUTER_CONSOLE ]; then
ROUTER_CONSOLE="$1"
if [ -z $1 ]; then
ROUTER_CONSOLE="http://127.0.0.1:7657"
fi
fi
if [ ! -d "$CONFIGURING_PROFILE" ]; then
mkdir -p "$CONFIGURING_PROFILE"
cp -vr /var/lib/i2pbrowser/app-profile/* "$CONFIGURING_PROFILE"
fi
if [ ! -f "$CONFIGURING_PROFILE/user.js" ]; then
echo "user.js not present in $CONFIGURING_PROFILE, this is not a Firefox profile"
exit 1
fi
if [ -z $FIREFOX ]; then
if [ -f "firefox/firefox" ]; then
FIREFOX="./firefox/firefox"
fi
FIREFOX=$(which firefox-esr)
if [ -z $FIREFOX ]; then
FIREFOX=$(which firefox)
fi
fi
if [ -z $FIREFOX ]; then
echo "Firefox does not appear to be in your \$PATH."
echo "Please install Firefox via a package manager, or"
echo "or set the FIREFOX variable in your shell to the"
echo "location of a Firefox executable."
exit 1
fi
echo $FIREFOX --profile "$CONFIGURING_PROFILE" "$ROUTER_CONSOLE" $@
$FIREFOX --profile "$CONFIGURING_PROFILE" "$ROUTER_CONSOLE" $@

View File

@@ -0,0 +1,62 @@
user_pref("extensions.https_everywhere._observatory.enabled", false);
user_pref("extensions.https_everywhere.options.autoUpdateRulesets", false);
user_pref("extensions.https_everywhere.globalEnabled", false);
user_pref("extensions.https_everywhere._observatory.submit_during_tor", false);
user_pref("extensions.https_everywhere._observatory.submit_during_nontor", false);
user_pref("extensions.https_everywhere._observatory.use_custom_proxy", true);
user_pref("extensions.https_everywhere._observatory.proxy_host", "127.0.0.1");
user_pref("extensions.https_everywhere._observatory.proxy_port", 4444);
user_pref("extensions.torbutton.use_nontor_proxy", true);
//For socket conversion: in the future, I'll need to make TBB communicate with
//i2p over a unix socket. Fortunately, this is how you do that. It will be
//configurable in a similar way to the host:port configuration when that happens.
//user_pref("extensions.torlauncher.socks_port_use_ipc", );
//user_pref("extensions.torlauncher.socks_ipc_path", "");
user_pref("extensions.torlauncher.start_tor", false);
//user_pref("extensions.torlauncher.default_bridge_type", "");
user_pref("extensions.torlauncher.prompt_at_startup", false);
// Resist-fingerprinting and first-party isolation enable
user_pref("privacy.resistFingerprinting", true);
user_pref("privacy.firstparty.isolate", true);
// Use i2p http proxy for all connections and set homepage to safe local form.
// DON'T allow access to the admin panel from the profile we browse i2p with.
user_pref("network.proxy.no_proxies_on", "127.0.0.1:7657,localhost:7657,127.0.0.1:7662,localhost:7662,127.0.0.1:7669,localhost:7669");
user_pref("network.proxy.type", 1);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 4444);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 4444);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 4444);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 4444);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("browser.startup.homepage", "about:blank");
user_pref("dom.security.https_only_mode", false);
user_pref("keyword.enabled", false);
user_pref("extensions.allowPrivateBrowsingByDefault", true);
user_pref("extensions.PrivateBrowsing.notification", false);
user_pref("toolkit.legacyUserProfileCustomizations.stylesheets", true);
user_pref("extensions.pocket.enabled", false);
user_pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false);
user_pref("browser.newtabpage.activity-stream.showSponsored", false);
user_pref("services.sync.prefs.sync.browser.newtabpage.activity-stream.showSponsored", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.highlights", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.topstories", false);
user_pref("browser.newtabpage.activity-stream.default.sites", "http://127.0.0.1:7657/home,http://127.0.0.1:7657/i2psnark/,http://127.0.0.1:7657/susimail/");
user_pref("browser.newtabpage.activity-stream.feeds.topsites", true);
user_pref("ui.use_standins_for_native_colors", true);
user_pref("webgl.disable-extensions", true);
user_pref("webgl.min_capability_mode", true);
user_pref("webgl.disable-fail-if-major-performance-caveat", true);
user_pref("webgl.enable-webgl2", false);
user_pref("media.navigator.enabled", false);
user_pref("dom.w3c_touch_events.enabled", false);

View File

@@ -0,0 +1,223 @@
/*
Overrides#
for Extension Preferences# Tor Browser Bundle# Do not edit this file.##This file is modified from a file included in the Tor Browser Bundle.##Copyright 2017 The Tor Project.See LICENSE.tor#
for licensing information.
HTTPS Everywhere Preferences:
*/
user_pref("extensions.https_everywhere._observatory.popup_shown", true);
user_pref("extensions.https_everywhere.toolbar_hint_shown", true);
/*
NoScript Preferences: #In order to disable all scripts by
default, uncomment the following line...#user_pref("capability.policy.maonoscript.javascript.enabled", "noAccess");#
and comment out the following line
*/
user_pref("capability.policy.maonoscript.javascript.enabled", "allAccess");
user_pref("capability.policy.maonoscript.sites", "[System+Principal] about: about:tbupdate about:tor chrome: resource: blob: mediasource: moz-extension: moz-safe-about: about:neterror about:certerror about:feeds about:tabcrashed about:cache");
user_pref("noscript.default", "[System+Principal] about: about:tbupdate about:tor chrome: resource: blob: mediasource: moz-extension: moz-safe-about: about:neterror about:certerror about:feeds about:tabcrashed about:cache");
user_pref("noscript.mandatory", "[System+Principal] about: about:tbupdate about:tor chrome: resource: blob: mediasource: moz-extension: moz-safe-about: about:neterror about:certerror about:feeds about:tabcrashed about:cache");
user_pref("noscript.ABE.enabled", false);
user_pref("noscript.ABE.notify", false);
user_pref("noscript.ABE.wanIpAsLocal", false);
user_pref("noscript.confirmUnblock", false);
user_pref("noscript.contentBlocker", true);
user_pref("noscript.firstRunRedirection", false);
user_pref("noscript.global", true);
user_pref("noscript.gtemp", "");
user_pref("noscript.opacizeObject", 3);
user_pref("noscript.forbidWebGL", true);
user_pref("noscript.forbidFonts", true);
user_pref("noscript.options.tabSelectedIndexes", "5,0,0");
user_pref("noscript.policynames", "");
user_pref("noscript.secureCookies", true);
user_pref("noscript.showAllowPage", false);
user_pref("noscript.showBaseDomain", false);
user_pref("noscript.showDistrust", false);
user_pref("noscript.showRecentlyBlocked", false);
user_pref("noscript.showTemp", false);
user_pref("noscript.showTempToPerm", false);
user_pref("noscript.showUntrusted", false);
user_pref("noscript.STS.enabled", false);
user_pref("noscript.subscription.lastCheck", -142148139);
user_pref("noscript.temp", "");
user_pref("noscript.untrusted", "");
user_pref("noscript.forbidMedia", true);
user_pref("noscript.allowWhitelistUpdates", false);
user_pref("noscript.fixLinks", false);
// Now handled by plugins.click_to_play // Not in this one.
user_pref("noscript.forbidFlash", true);
user_pref("noscript.forbidSilverlight", true);
user_pref("noscript.forbidJava", true);
user_pref("noscript.forbidPlugins", true);
// Usability tweaks
user_pref("noscript.showPermanent", false);
user_pref("noscript.showTempAllowPage", true);
user_pref("noscript.showRevokeTemp", true);
user_pref("noscript.notify", false);
user_pref("noscript.autoReload", true);
user_pref("noscript.autoReload.allTabs", false);
user_pref("noscript.cascadePermissions", true);
user_pref("noscript.restrictSubdocScripting", true);
user_pref("noscript.showVolatilePrivatePermissionsToggle", false);
user_pref("noscript.volatilePrivatePermissions", true);
user_pref("noscript.clearClick", 0);
user_pref("intl.locale.matchOS", false);
user_pref("extensions.https_everywhere._observatory.enabled", false);
user_pref("extensions.https_everywhere.options.autoUpdateRulesets", false);
user_pref("extensions.https_everywhere.globalEnabled", false);
user_pref("extensions.https_everywhere._observatory.submit_during_tor", false);
user_pref("extensions.https_everywhere._observatory.submit_during_nontor", false);
user_pref("extensions.https_everywhere._observatory.use_custom_proxy", true);
user_pref("extensions.https_everywhere._observatory.proxy_host", "127.0.0.1");
user_pref("extensions.https_everywhere._observatory.proxy_port", 4444);
user_pref("extensions.torbutton.use_nontor_proxy", true);
//For socket conversion: in the future, I'll need to make TBB communicate with
//i2p over a unix socket. Fortunately, this is how you do that. It will be
//configurable in a similar way to the host:port configuration when that happens.
//user_pref("extensions.torlauncher.socks_port_use_ipc", );
//user_pref("extensions.torlauncher.socks_ipc_path", "");
user_pref("extensions.torlauncher.start_tor", false);
//user_pref("extensions.torlauncher.default_bridge_type", "");
user_pref("extensions.torlauncher.prompt_at_startup", false);
// Resist-fingerprinting and first-party isolation enable
user_pref("privacy.resistFingerprinting", true);
user_pref("privacy.firstparty.isolate", true);
// Use i2p http proxy for all connections and set homepage to safe local form.
// DON'T allow access to the admin panel from the profile we browse i2p with.
user_pref("network.proxy.no_proxies_on", "127.0.0.1:7657,localhost:7657,127.0.0.1:7662,localhost:7662,127.0.0.1:7669,localhost:7669");
user_pref("network.proxy.type", 1);
user_pref("network.proxy.http", "127.0.0.1");
user_pref("network.proxy.http_port", 4444);
user_pref("network.proxy.ssl", "127.0.0.1");
user_pref("network.proxy.ssl_port", 4444);
user_pref("network.proxy.ftp", "127.0.0.1");
user_pref("network.proxy.ftp_port", 4444);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 4444);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("browser.startup.homepage", "http://127.0.0.1:7657/home");
// Privacy-harden and disable irrelevant features.
user_pref("app.normandy.api_url", "");
user_pref("app.normandy.enabled", false);
user_pref("app.update.auto", false);
user_pref("app.update.enabled", false);
user_pref("beacon.enabled", false);
user_pref("browser.aboutHomeSnippets.updateUrl", "");
user_pref("browser.cache.disk_cache_ssl", false);
user_pref("browser.cache.disk.enable", false);
user_pref("browser.cache.offline.enable", false);
user_pref("browser.disableResetPrompt", true);
user_pref("browser.display.use_document_fonts", 0);
user_pref("browser.fixup.alternate.enabled", false);
user_pref("browser.formfill.enable", false);
user_pref("browser.library.activity-stream.enabled", false);
user_pref("browser.newtabpage.activity-stream.disableSnippets", true);
user_pref("browser.newtabpage.activity-stream.enabled", false);
user_pref("browser.newtabpage.activity-stream.feeds.section.highlights", false);
user_pref("browser.newtabpage.activity-stream.feeds.snippets", false);
user_pref("browser.newtabpage.activity-stream.feeds.telemetry", false);
user_pref("browser.newtabpage.activity-stream.feeds.topsites", false);
user_pref("browser.newtabpage.activity-stream.prerender", false);
user_pref("browser.newtabpage.activity-stream.showSearch", false);
user_pref("browser.newtabpage.enhanced", false);
user_pref("browser.newtabpage.introShown", true);
user_pref("browser.newtab.preload", false);
user_pref("browser.onboarding.enabled", false);
user_pref("browser.pagethumbnails.capturing_disabled", true);
user_pref("browser.safebrowsing.appRepURL", "");
user_pref("browser.safebrowsing.blockedURIs.enabled", false);
user_pref("browser.safebrowsing.downloads.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.enabled", false);
user_pref("browser.safebrowsing.downloads.remote.url", "");
user_pref("browser.safebrowsing.enabled", false);
user_pref("browser.safebrowsing.malware.enabled", false);
user_pref("browser.safebrowsing.phishing.enabled", false);
user_pref("browser.search.geoip.timeout", 1);
user_pref("browser.search.suggest.enabled", false);
user_pref("browser.selfsupport.url", "");
user_pref("browser.send_pings", false);
user_pref("browser.shell.checkDefaultBrowser", false);
user_pref("browser.startup.homepage_override.mstone", "ignore");
user_pref("browser.startup.page", 0);
user_pref("browser.toolbarbuttons.introduced.pocket-button", true);
user_pref("browser.urlbar.speculativeConnect.enabled", false);
user_pref("browser.urlbar.trimURLs", false);
user_pref("datareporting.healthreport.uploadEnabled", false);
user_pref("datareporting.policy.dataSubmissionEnabled", false);
user_pref("dom.battery.enabled", false);
user_pref("dom.enable_performance", false);
user_pref("dom.enable_performance_navigation_timing", false);
user_pref("dom.enable_resource_timing", false);
user_pref("dom.event.clipboardevents.enabled", false);
user_pref("dom.gamepad.enabled", false);
user_pref("dom.indexedDB.enabled", false);
user_pref("dom.min_timeout_value", 400);
user_pref("dom.push.connection.enabled", false);
user_pref("dom.push.enabled", false);
user_pref("dom.serviceWorkers.enabled", false);
user_pref("dom.serviceWorkers.interception.enabled", false);
user_pref("dom.storage.enabled", false);
user_pref("dom.webaudio.enabled", false);
user_pref("extensions.autoDisableScopes", 14);
user_pref("extensions.getAddons.cache.enabled", false);
user_pref("extensions.getAddons.showPane", false);
user_pref("extensions.pocket.enabled", false);
user_pref("extensions.screenshots.disabled", true);
user_pref("extensions.webservice.discoverURL", "");
user_pref("geo.enabled", false);
user_pref("geo.wifi.uri", "");
user_pref("gfx.downloadable_fonts.disable_cache", true);
user_pref("javascript.options.shared_memory", false);
user_pref("layout.css.visited_links_enabled", false);
user_pref("media.autoplay.enabled", false);
user_pref("media.cache_size", 0);
user_pref("media.navigator.enabled", false);
user_pref("media.peerconnection.enabled", false);
user_pref("media.video_stats.enabled", false);
user_pref("captivedetect.canonicalURL", "");
user_pref("network.captive-portal-service.enabled", false);
user_pref("network.cookie.cookieBehavior", 1);
user_pref("network.cookie.lifetimePolicy", 2);
user_pref("network.dns.disablePrefetch", true);
user_pref("network.http.referer.spoofSource", true);
user_pref("network.http.referer.trimmingPolicy", 2);
user_pref("network.http.referer.XOriginPolicy", 2);
user_pref("network.prefetch-next", false);
user_pref("privacy.donottrackheader.enabled", true);
user_pref("privacy.donottrackheader.value", 1);
user_pref("toolkit.telemetry.archive.enabled", false);
user_pref("toolkit.telemetry.coverage.opt-out", true);
user_pref("toolkit.telemetry.enabled", false);
user_pref("toolkit.telemetry.server", "");
user_pref("toolkit.telemetry.unified", false);
user_pref("webgl.disabled", true);
user_pref("browser.chrome.errorReporter.infoURL", "");
user_pref("breakpad.reportURL", "");
//user_pref("browser.newtabpage.activity-stream.default.sites", "");
user_pref("browser.newtabpage.activity-stream.showSponsoredTopSites", false);
user_pref("browser.newtabpage.activity-stream.showSponsored", false);
user_pref("services.sync.prefs.sync.browser.newtabpage.activity-stream.showSponsored", false);
user_pref("browser.newtabpage.enabled", true);
user_pref("browser.newtabpage.activity-stream.default.sites", "http://127.0.0.1:7657/home,http://127.0.0.1:7657/i2psnark/,http://127.0.0.1:7657/susimail/");
user_pref("dom.security.https_only_mode", false);
user_pref("keyword.enabled", false);
user_pref("extensions.allowPrivateBrowsingByDefault", true);
user_pref("extensions.PrivateBrowsing.notification", false);
user_pref("browser.newtabpage.activity-stream.feeds.topsites", true);
user_pref("ui.use_standins_for_native_colors", true);
user_pref("webgl.disable-extensions", true);
user_pref("webgl.min_capability_mode", true);
user_pref("webgl.disable-fail-if-major-performance-caveat", true);
user_pref("webgl.enable-webgl2", false);
user_pref("dom.w3c_touch_events.enabled", false);

View File

@@ -82,7 +82,7 @@ user_pref("extensions.torbutton.use_nontor_proxy", true);
//user_pref("extensions.torlauncher.socks_port_use_ipc", );
//user_pref("extensions.torlauncher.socks_ipc_path", "");
user_pref("extensions.torlauncher.start_tor", false);
user_pref("extensions.torlauncher.start_tor", true);
//user_pref("extensions.torlauncher.default_bridge_type", "");
user_pref("extensions.torlauncher.prompt_at_startup", false);
@@ -105,7 +105,7 @@ user_pref("network.proxy.ftp_port", 4444);
user_pref("network.proxy.socks", "127.0.0.1");
user_pref("network.proxy.socks_port", 4444);
user_pref("network.proxy.share_proxy_settings", true);
user_pref("browser.startup.homepage", "about:blank");
user_pref("browser.startup.homepage", "http://127.0.0.1:7657/home");
// Privacy-harden and disable irrelevant features.
user_pref("app.normandy.api_url", "");

9
torbrowser.desktop Normal file
View File

@@ -0,0 +1,9 @@
[Desktop Entry]
Encoding=UTF-8
Version=1.0
Type=Application
Terminal=false
Exec=/bin/sh -c "torbrowser -directory=$HOME/.i2p/browser"
Name=Tor Browser
Categories=Network;WebBrowser;
Icon=/var/lib/i2pbrowser/icons/onion.png

117
usage.html Normal file
View File

@@ -0,0 +1,117 @@
<!DOCTYPE html>
<html>
<head>
<title>i2p.plugins.tor-manager - Tor Binary Manager</title>
<link rel="stylesheet" type="text/css" href ="/style.css" />
</head>
<body>
<h1 id="torand-sometimes-firefox-manager-for-i2p">Tor(And sometimes Firefox) Manager for I2P</h1>
<h2 id="usage-i2p.plugins.tor-manager-options">Usage: i2p.plugins.tor-manager [options]</h2>
<h3 id="options">Options:</h3>
<div class="sourceCode" id="cb1"><pre class="sourceCode sh"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true"></a><span class="ex">Usage</span>: i2p.plugins.tor-manager [options]</span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true"></a></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true"></a><span class="ex">Downloads</span>, verifies and unpacks Tor Browser. Manages the Tor Browser</span>
<span id="cb1-4"><a href="#cb1-4" aria-hidden="true"></a><span class="ex">system</span> in environments where Tor is not in use.</span>
<span id="cb1-5"><a href="#cb1-5" aria-hidden="true"></a></span>
<span id="cb1-6"><a href="#cb1-6" aria-hidden="true"></a><span class="ex">Options</span>:</span>
<span id="cb1-7"><a href="#cb1-7" aria-hidden="true"></a></span>
<span id="cb1-8"><a href="#cb1-8" aria-hidden="true"></a><span class="ex">Usage</span> of ./i2p.plugins.tor-manager:</span>
<span id="cb1-9"><a href="#cb1-9" aria-hidden="true"></a> <span class="ex">-apparmor</span></span>
<span id="cb1-10"><a href="#cb1-10" aria-hidden="true"></a> <span class="ex">Generate</span> apparmor rules</span>
<span id="cb1-11"><a href="#cb1-11" aria-hidden="true"></a> <span class="ex">-arch</span> string</span>
<span id="cb1-12"><a href="#cb1-12" aria-hidden="true"></a> <span class="ex">OS/arch</span> to download (default <span class="st">&quot;64&quot;</span>)</span>
<span id="cb1-13"><a href="#cb1-13" aria-hidden="true"></a> <span class="ex">-bemirror</span></span>
<span id="cb1-14"><a href="#cb1-14" aria-hidden="true"></a> <span class="ex">Act</span> as an in-I2P mirror when you<span class="st">&#39;re done downloading</span></span>
<span id="cb1-15"><a href="#cb1-15" aria-hidden="true"></a><span class="st"> -clearnet</span></span>
<span id="cb1-16"><a href="#cb1-16" aria-hidden="true"></a><span class="st"> Use clearnet (no Tor or I2P)</span></span>
<span id="cb1-17"><a href="#cb1-17" aria-hidden="true"></a><span class="st"> -directory string</span></span>
<span id="cb1-18"><a href="#cb1-18" aria-hidden="true"></a><span class="st"> Directory operate in</span></span>
<span id="cb1-19"><a href="#cb1-19" aria-hidden="true"></a><span class="st"> -help</span></span>
<span id="cb1-20"><a href="#cb1-20" aria-hidden="true"></a><span class="st"> Print help</span></span>
<span id="cb1-21"><a href="#cb1-21" aria-hidden="true"></a><span class="st"> -host string</span></span>
<span id="cb1-22"><a href="#cb1-22" aria-hidden="true"></a><span class="st"> Host to serve on (default &quot;127.0.0.1&quot;)</span></span>
<span id="cb1-23"><a href="#cb1-23" aria-hidden="true"></a><span class="st"> -i2pbrowser</span></span>
<span id="cb1-24"><a href="#cb1-24" aria-hidden="true"></a><span class="st"> Open I2P in Tor Browser</span></span>
<span id="cb1-25"><a href="#cb1-25" aria-hidden="true"></a><span class="st"> -i2pconfig</span></span>
<span id="cb1-26"><a href="#cb1-26" aria-hidden="true"></a><span class="st"> Open I2P routerconsole in Tor Browser with javscript enabled and non-routerconsole sites disabled</span></span>
<span id="cb1-27"><a href="#cb1-27" aria-hidden="true"></a><span class="st"> -lang string</span></span>
<span id="cb1-28"><a href="#cb1-28" aria-hidden="true"></a><span class="st"> Language to download</span></span>
<span id="cb1-29"><a href="#cb1-29" aria-hidden="true"></a><span class="st"> -offline</span></span>
<span id="cb1-30"><a href="#cb1-30" aria-hidden="true"></a><span class="st"> Work offline. Differs from Firefox&#39;</span>s offline mode in that cannot be disabled until the browser is closed.</span>
<span id="cb1-31"><a href="#cb1-31" aria-hidden="true"></a> <span class="ex">-os</span> string</span>
<span id="cb1-32"><a href="#cb1-32" aria-hidden="true"></a> <span class="ex">OS/arch</span> to download (default <span class="st">&quot;linux&quot;</span>)</span>
<span id="cb1-33"><a href="#cb1-33" aria-hidden="true"></a> <span class="ex">-port</span> int</span>
<span id="cb1-34"><a href="#cb1-34" aria-hidden="true"></a> <span class="ex">Port</span> to serve on (default 7695)</span>
<span id="cb1-35"><a href="#cb1-35" aria-hidden="true"></a> <span class="ex">-profile</span> string</span>
<span id="cb1-36"><a href="#cb1-36" aria-hidden="true"></a> <span class="ex">use</span> a custom profile path, normally blank</span>
<span id="cb1-37"><a href="#cb1-37" aria-hidden="true"></a> <span class="ex">-shortcuts</span></span>
<span id="cb1-38"><a href="#cb1-38" aria-hidden="true"></a> <span class="ex">Create</span> desktop shortcuts</span>
<span id="cb1-39"><a href="#cb1-39" aria-hidden="true"></a> <span class="ex">-torbrowser</span></span>
<span id="cb1-40"><a href="#cb1-40" aria-hidden="true"></a> <span class="ex">Open</span> Tor Browser</span>
<span id="cb1-41"><a href="#cb1-41" aria-hidden="true"></a> <span class="ex">-verbose</span></span>
<span id="cb1-42"><a href="#cb1-42" aria-hidden="true"></a> <span class="ex">Verbose</span> output</span>
<span id="cb1-43"><a href="#cb1-43" aria-hidden="true"></a> <span class="ex">-watch-profiles</span> string</span>
<span id="cb1-44"><a href="#cb1-44" aria-hidden="true"></a> <span class="ex">Monitor</span> and control these Firefox profiles. Temporarily Unused.</span>
<span id="cb1-45"><a href="#cb1-45" aria-hidden="true"></a><span class="ex">Usage</span>: ./firefox.real [ options ... ] [URL]</span>
<span id="cb1-46"><a href="#cb1-46" aria-hidden="true"></a> <span class="ex">where</span> options include:</span>
<span id="cb1-47"><a href="#cb1-47" aria-hidden="true"></a></span>
<span id="cb1-48"><a href="#cb1-48" aria-hidden="true"></a><span class="ex">X11</span> options</span>
<span id="cb1-49"><a href="#cb1-49" aria-hidden="true"></a> <span class="ex">--display</span>=DISPLAY X display to use</span>
<span id="cb1-50"><a href="#cb1-50" aria-hidden="true"></a> <span class="ex">--sync</span> Make X calls synchronous</span>
<span id="cb1-51"><a href="#cb1-51" aria-hidden="true"></a> <span class="ex">--g-fatal-warnings</span> Make all warnings fatal</span>
<span id="cb1-52"><a href="#cb1-52" aria-hidden="true"></a></span>
<span id="cb1-53"><a href="#cb1-53" aria-hidden="true"></a><span class="ex">Firefox</span> options</span>
<span id="cb1-54"><a href="#cb1-54" aria-hidden="true"></a> <span class="ex">-h</span> or --help Print this message.</span>
<span id="cb1-55"><a href="#cb1-55" aria-hidden="true"></a> <span class="ex">-v</span> or --version Print Firefox version.</span>
<span id="cb1-56"><a href="#cb1-56" aria-hidden="true"></a> <span class="ex">--full-version</span> Print Firefox version, build and platform build ids.</span>
<span id="cb1-57"><a href="#cb1-57" aria-hidden="true"></a> <span class="ex">-P</span> <span class="op">&lt;</span>profile<span class="op">&gt;</span> Start with <span class="op">&lt;</span>profile<span class="op">&gt;</span>.</span>
<span id="cb1-58"><a href="#cb1-58" aria-hidden="true"></a> <span class="ex">--profile</span> <span class="op">&lt;</span>path<span class="op">&gt;</span> Start with profile at <span class="op">&lt;</span>path<span class="op">&gt;</span>.</span>
<span id="cb1-59"><a href="#cb1-59" aria-hidden="true"></a> <span class="ex">--migration</span> Start with migration wizard.</span>
<span id="cb1-60"><a href="#cb1-60" aria-hidden="true"></a> <span class="ex">--ProfileManager</span> Start with ProfileManager.</span>
<span id="cb1-61"><a href="#cb1-61" aria-hidden="true"></a> <span class="ex">--no-remote</span> (default) <span class="ex">Do</span> not accept or send remote commands<span class="kw">;</span> <span class="ex">implies</span></span>
<span id="cb1-62"><a href="#cb1-62" aria-hidden="true"></a> <span class="ex">--new-instance.</span></span>
<span id="cb1-63"><a href="#cb1-63" aria-hidden="true"></a> <span class="ex">--allow-remote</span> Accept and send remote commands.</span>
<span id="cb1-64"><a href="#cb1-64" aria-hidden="true"></a> <span class="ex">--new-instance</span> Open new instance, not a new window in running instance.</span>
<span id="cb1-65"><a href="#cb1-65" aria-hidden="true"></a> <span class="ex">--safe-mode</span> Disables extensions and themes for this session.</span>
<span id="cb1-66"><a href="#cb1-66" aria-hidden="true"></a> <span class="ex">--MOZ_LOG</span>=<span class="op">&lt;</span>modules<span class="op">&gt;</span> Treated as MOZ_LOG=<span class="op">&lt;</span>modules<span class="op">&gt;</span> environment variable,</span>
<span id="cb1-67"><a href="#cb1-67" aria-hidden="true"></a> <span class="ex">overrides</span> it.</span>
<span id="cb1-68"><a href="#cb1-68" aria-hidden="true"></a> <span class="ex">--MOZ_LOG_FILE</span>=<span class="op">&lt;</span>file<span class="op">&gt;</span> Treated as MOZ_LOG_FILE=<span class="op">&lt;</span>file<span class="op">&gt;</span> environment variable,</span>
<span id="cb1-69"><a href="#cb1-69" aria-hidden="true"></a> <span class="ex">overrides</span> it. If MOZ_LOG_FILE is not specified as an</span>
<span id="cb1-70"><a href="#cb1-70" aria-hidden="true"></a> <span class="ex">argument</span> or as an environment variable, logging will be</span>
<span id="cb1-71"><a href="#cb1-71" aria-hidden="true"></a> <span class="ex">written</span> to stdout.</span>
<span id="cb1-72"><a href="#cb1-72" aria-hidden="true"></a> <span class="ex">--headless</span> Run without a GUI.</span>
<span id="cb1-73"><a href="#cb1-73" aria-hidden="true"></a> <span class="ex">--browser</span> Open a browser window.</span>
<span id="cb1-74"><a href="#cb1-74" aria-hidden="true"></a> <span class="ex">--new-window</span> <span class="op">&lt;</span>url<span class="op">&gt;</span> Open <span class="op">&lt;</span>url<span class="op">&gt;</span> in a new window.</span>
<span id="cb1-75"><a href="#cb1-75" aria-hidden="true"></a> <span class="ex">--new-tab</span> <span class="op">&lt;</span>url<span class="op">&gt;</span> Open <span class="op">&lt;</span>url<span class="op">&gt;</span> in a new tab.</span>
<span id="cb1-76"><a href="#cb1-76" aria-hidden="true"></a> <span class="ex">--private-window</span> <span class="op">&lt;</span>url<span class="op">&gt;</span> Open <span class="op">&lt;</span>url<span class="op">&gt;</span> in a new private window.</span>
<span id="cb1-77"><a href="#cb1-77" aria-hidden="true"></a> <span class="ex">--preferences</span> Open Preferences dialog.</span>
<span id="cb1-78"><a href="#cb1-78" aria-hidden="true"></a> <span class="ex">--screenshot</span> [<span class="op">&lt;</span>path<span class="op">&gt;</span>] Save screenshot to <span class="op">&lt;</span>path<span class="op">&gt;</span> or in working directory.</span>
<span id="cb1-79"><a href="#cb1-79" aria-hidden="true"></a> <span class="ex">--window-size</span> width[,height] Width and optionally height of screenshot.</span>
<span id="cb1-80"><a href="#cb1-80" aria-hidden="true"></a> <span class="ex">--search</span> <span class="op">&lt;</span>term<span class="op">&gt;</span> Search <span class="op">&lt;</span>term<span class="op">&gt;</span> with your default search engine.</span>
<span id="cb1-81"><a href="#cb1-81" aria-hidden="true"></a> <span class="ex">--setDefaultBrowser</span> Set this app as the default browser.</span>
<span id="cb1-82"><a href="#cb1-82" aria-hidden="true"></a> <span class="ex">--first-startup</span> Run post-install actions before opening a new window.</span>
<span id="cb1-83"><a href="#cb1-83" aria-hidden="true"></a> <span class="ex">--kiosk</span> Start the browser in kiosk mode.</span>
<span id="cb1-84"><a href="#cb1-84" aria-hidden="true"></a> <span class="ex">--jsconsole</span> Open the Browser Console.</span>
<span id="cb1-85"><a href="#cb1-85" aria-hidden="true"></a> <span class="ex">--jsdebugger</span> [<span class="op">&lt;</span>path<span class="op">&gt;</span>] Open the Browser Toolbox. Defaults to the local build</span>
<span id="cb1-86"><a href="#cb1-86" aria-hidden="true"></a> <span class="ex">but</span> can be overridden by a firefox path.</span>
<span id="cb1-87"><a href="#cb1-87" aria-hidden="true"></a> <span class="ex">--wait-for-jsdebugger</span> Spin event loop until JS debugger connects.</span>
<span id="cb1-88"><a href="#cb1-88" aria-hidden="true"></a> <span class="ex">Enables</span> debugging (some) <span class="ex">application</span> startup code paths.</span>
<span id="cb1-89"><a href="#cb1-89" aria-hidden="true"></a> <span class="ex">Only</span> has an effect when <span class="kw">`</span><span class="ex">--jsdebugger</span><span class="kw">`</span> is also supplied.</span>
<span id="cb1-90"><a href="#cb1-90" aria-hidden="true"></a> <span class="ex">--devtools</span> Open DevTools on initial load.</span>
<span id="cb1-91"><a href="#cb1-91" aria-hidden="true"></a> <span class="ex">--start-debugger-server</span> [ws:][ <span class="op">&lt;</span>port<span class="op">&gt;</span> <span class="kw">|</span> <span class="op">&lt;</span><span class="ex">path</span><span class="op">&gt;</span> ] Start the devtools server on</span>
<span id="cb1-92"><a href="#cb1-92" aria-hidden="true"></a> <span class="ex">a</span> TCP port or Unix domain socket path. Defaults to TCP port</span>
<span id="cb1-93"><a href="#cb1-93" aria-hidden="true"></a> <span class="ex">6000.</span> Use WebSocket protocol if ws: prefix is specified.</span>
<span id="cb1-94"><a href="#cb1-94" aria-hidden="true"></a> <span class="ex">--recording</span> <span class="op">&lt;</span>file<span class="op">&gt;</span> Record drawing for a given URL.</span>
<span id="cb1-95"><a href="#cb1-95" aria-hidden="true"></a> <span class="ex">--recording-output</span> <span class="op">&lt;</span>file<span class="op">&gt;</span> Specify destination file for a drawing recording.</span>
<span id="cb1-96"><a href="#cb1-96" aria-hidden="true"></a> <span class="ex">--remote-debugging-port</span> [<span class="op">&lt;</span>port<span class="op">&gt;</span>] Start the Firefox remote agent,</span>
<span id="cb1-97"><a href="#cb1-97" aria-hidden="true"></a> <span class="fu">which</span> is a low-level debugging interface based on the CDP protocol.</span>
<span id="cb1-98"><a href="#cb1-98" aria-hidden="true"></a> <span class="ex">Defaults</span> to listen on localhost:9222.</span>
<span id="cb1-99"><a href="#cb1-99" aria-hidden="true"></a></span>
<span id="cb1-100"><a href="#cb1-100" aria-hidden="true"></a><span class="ex">Tor</span> Browser Script Options</span>
<span id="cb1-101"><a href="#cb1-101" aria-hidden="true"></a> <span class="ex">--verbose</span> Display Tor and Firefox output in the terminal</span>
<span id="cb1-102"><a href="#cb1-102" aria-hidden="true"></a> <span class="ex">--log</span> [file] Record Tor and Firefox output in file (default: tor-browser.log)</span>
<span id="cb1-103"><a href="#cb1-103" aria-hidden="true"></a> <span class="ex">--detach</span> Detach from terminal and run Tor Browser in the background.</span>
<span id="cb1-104"><a href="#cb1-104" aria-hidden="true"></a> <span class="ex">--register-app</span> Register Tor Browser as a desktop app for this user</span>
<span id="cb1-105"><a href="#cb1-105" aria-hidden="true"></a> <span class="ex">--unregister-app</span> Unregister Tor Browser as a desktop app for this user</span></code></pre></div>
</body>
</html>