Merge remote-tracking branch 'micahlee/master'

This commit is contained in:
Ulrike Uhlig 2016-09-06 13:44:22 +02:00
commit 7a8c5d9353
36 changed files with 1202 additions and 1156 deletions

View File

@ -11,10 +11,23 @@ cd onionshare
*For .deb-based distros (like Debian, Ubuntu, Linux Mint):*
Note that python3-stem appears in Debian wheezy and newer, and it appears in Ubuntu 13.10 and newer. Older versions of Debian and Ubuntu aren't supported.
Then install the needed dependencies:
```sh
sudo apt-get install -y build-essential fakeroot python3-all python3-stdeb python3-flask python3-stem python3-pyqt5 dh-python
sudo apt-get install -y python3-flask python3-stem python3-pyqt5 python-nautilus
```
After that you can try both the CLI and the GUI version of OnionShare:
```sh
./install/scripts/onionshare
./install/scripts/onionshare-gui
```
A script to build a .deb package and install OnionShare easily is also provided for your convenience:
```sh
sudo apt-get install -y build-essential fakeroot python3-all python3-stdeb dh-python python-nautilus
./install/build_deb.sh
sudo dpkg -i deb_dist/onionshare_*.deb
```
@ -23,7 +36,7 @@ Note that OnionShare uses stdeb to generate Debian packages, and `python3-stdeb`
*For .rpm-based distros (Red Hat, Fedora, CentOS):*
```sh
sudo sudo dnf install -y rpm-build python3-flask python3-stem python3-qt5
sudo sudo dnf install -y rpm-build python3-flask python3-stem python3-qt5 nautilus-python
./install/build_rpm.sh
sudo yum install -y dist/onionshare-*.rpm
```
@ -49,9 +62,15 @@ brew install python3 pyqt5 qt5
Install some dependencies using pip3:
```sh
sudo pip3 install pyinstaller flask stem
sudo pip3 install flask stem
```
Install the latest development version of cx_Freeze:
* Download a [snapshot](https://bitbucket.org/anthony_tuininga/cx_freeze/downloads) of the latest development version of cx_Freeze, extract it, and cd into the folder you extracted it to
* Build the package: `python3 setup.py bdist_wheel`
* Install it with pip: `sudo pip3 install dist/cx_Freeze-5.0-cp35-cp35m-macosx_10_11_x86_64.whl`
Get the source code:
```sh
@ -70,7 +89,7 @@ Now you should have `dist/OnionShare.app`.
To codesign and build a .pkg for distribution:
```sh
install/build_osx.sh --sign
install/build_osx.sh --release
```
Now you should have `dist/OnionShare.pkg`.
@ -81,19 +100,25 @@ Now you should have `dist/OnionShare.pkg`.
These instructions include adding folders to the path in Windows. To do this, go to Start and type "advanced system settings", and open "View advanced system settings" in the Control Panel. Click Environment Variables. Under "System variables" double-click on Path. From there you can add and remove folders that are available in the PATH.
First, download and install the 32-bit (x86) version of Python 3.4.x from https://www.python.org/downloads/windows/. You need 3.4 instead of 3.5 because PyQt5 was built with 3.4. Add `C:\Python34` and `C:\Python34\Scripts` to the path.
Download the latest Python 3.5.x, 32-bit (x86) from https://www.python.org/downloads/. I downloaded `python-3.5.2.exe`. When installing it, make sure to check the "Add Python 3.5 to PATH" checkbox on the first page of the installer.
Open a command prompt and install some dependencies with pip: `pip3 install pyinstaller pypiwin32 flask stem`
Download and install Qt5 from https://www.qt.io/download-open-source/. I downloaded `qt-unified-windows-x86-2.0.3-1-online.exe`. There's no need to login to a Qt account during installation. Make sure you install the latest Qt 5.x.
Download and install Qt5 from https://www.qt.io/download-open-source/. I downloaded `qt-unified-windows-x86-2.0.2-2-online.exe`. There's no need to login to a Qt account during installation. Make sure you install the latest Qt 5.x.
Download and install the latest PyQt5 for 32-bit Windows from https://www.riverbankcomputing.com/software/pyqt/download5. I downloaded `PyQt5-5.5.1-gpl-Py3.4-Qt5.5.1-x32.exe`.
Open a command prompt and install dependencies with pip: `pip install pypiwin32 flask stem PyQt5`
Download and install the [Microsoft Visual C++ 2008 Redistributable Package (x86)](http://www.microsoft.com/en-us/download/details.aspx?id=29).
Installing cx_Freeze with support for Python 3.5 is annoying. Here are the steps (thanks https://github.com/sekrause/cx_Freeze-Wheels):
* Download and install the Visual C++ Build Tools 2005 from http://go.microsoft.com/fwlink/?LinkId=691126. I downloaded `visualcppbuildtools_full.exe`.
* Install the python wheel package: `pip install wheel`
* Download a [snapshot](https://bitbucket.org/anthony_tuininga/cx_freeze/downloads) of the latest development version of cx_Freeze, extract it, and cd into the folder you extracted it to
* Build the package: `python setup.py bdist_wheel`
* Install it with pip: `pip install dist\cx_Freeze-5.0-cp35-cp35m-win32.whl`
If you want to build the installer:
* Go to http://nsis.sourceforge.net/Download and download the latest NSIS. I downloaded `nsis-3.0b0-setup.exe`.
* Go to http://nsis.sourceforge.net/Download and download the latest NSIS. I downloaded `nsis-3.0-setup.exe`.
* Add `C:\Program Files (x86)\NSIS` to the path.
If you want to sign binaries with Authenticode:
@ -110,7 +135,7 @@ If you want to sign binaries with Authenticode:
### To make a .exe:
* Open a command prompt, cd into the onionshare directory, and type: `pyinstaller install\pyinstaller.spec -y`. `onionshare.exe` and all of its supporting files will get created inside the `dist\onionshare` folder.
* Open a command prompt, cd into the onionshare directory, and type: `python setup.py build`. `onionshare.exe`, `onionshare-gui.exe`, and all of their supporting files will get created inside the `build\exe.win32-3.5` folder.
### To build the installer:

View File

@ -8,3 +8,4 @@ include resources/html/*
include install/onionshare.desktop
include install/onionshare.appdata.xml
include install/onionshare80.xpm
include install/scripts/onionshare-nautilus.py

View File

@ -2,7 +2,7 @@
[![Build Status](https://travis-ci.org/micahflee/onionshare.png)](https://travis-ci.org/micahflee/onionshare)
OnionShare lets you securely and anonymously share files of any size. It works by starting a web server, making it accessible as a Tor hidden service, and generating an unguessable URL to access and download the files. It doesn't require setting up a server on the internet somewhere or using a third party filesharing service. You host the file on your own computer and use a Tor hidden service to make it temporarily accessible over the internet. The other user just needs to use Tor Browser to download the file from you.
OnionShare lets you securely and anonymously share files of any size. It works by starting a web server, making it accessible as a Tor onion service, and generating an unguessable URL to access and download the files. It doesn't require setting up a server on the internet somewhere or using a third party filesharing service. You host the file on your own computer and use a Tor onion service to make it temporarily accessible over the internet. The other user just needs to use Tor Browser to download the file from you.
Features include:
@ -27,9 +27,9 @@ You can set up your development environment to build OnionShare yourself by foll
## How to Use
Before you can share files, you need to open [Tor Browser](https://www.torproject.org/) in the background. This will provide the Tor service that OnionShare uses to start the hidden service.
Before you can share files, you need to open [Tor Browser](https://www.torproject.org/) in the background. This will provide the Tor service that OnionShare uses to start the onion service.
Open OnionShare and drag and drop files and folders you wish to share, and click Start Sharing. It will show you .onion URL such as `http://asxmi4q6i7pajg2b.onion/egg-cain` and copy it to your clipboard. This is the secret URL that can be used to download the file you're sharing. If you'd like multiple people to be able to download this file, uncheck the "close automatically" checkbox.
Open OnionShare and drag and drop files and folders you wish to share, and click Start Sharing. It will show you a .onion URL such as `http://asxmi4q6i7pajg2b.onion/egg-cain` and copy it to your clipboard. This is the secret URL that can be used to download the file you're sharing. If you'd like multiple people to be able to download this file, uncheck the "close automatically" checkbox.
Send this URL to the person you're trying to send the files to. If the files you're sending aren't secret, you can use normal means of sending the URL: emailing it, posting it to Facebook or Twitter, etc. If you're trying to send secret files then it's important to send this URL securely.

View File

@ -4,20 +4,20 @@
OnionShare is a tool that helps users securely and anonymously share files over the internet.
First, the sender chooses files and folders they wish to share with the recipient. OnionShare then starts a web server at `127.0.0.1` on a random port. It chooses two words from a 6800-long wordlist called a slug, and makes the files available for download at `http://127.0.0.1:[port]/[slug]/`. It then makes the web server accessible as Tor hidden service, and displays the URL `http://[hiddenservice].onion/[slug]` to the sender to share. A final OnionShare URL looks something like `http://f5ratndpx7rgvh7i.onion/fold-foxy`.
First, the sender chooses files and folders they wish to share with the recipient. OnionShare then starts a web server at `127.0.0.1` on a random port. It chooses two words from a 6800-long wordlist called a slug, and makes the files available for download at `http://127.0.0.1:[port]/[slug]/`. It then makes the web server accessible as Tor onion service, and displays the URL `http://[onionservice].onion/[slug]` to the sender to share. A final OnionShare URL looks something like `http://f5ratndpx7rgvh7i.onion/fold-foxy`.
The sender is responsible for securely sharing that URL with the recipient using a communication channel of their choice, such as in an encrypted email, chat, or voice call, or something less secure like a Twitter or Facebook message, depending on their threat model.
The recipient must use Tor Browser to load the URL and download the files.
As soon as the shared files get downloaded, or when the sender closes OnionShare, the Tor hidden service and web servers shut down, completely removing the files from the internet (there is an option to not shut down after the first download, to allow the files to be downloaded multiple times). Because of this, OnionShare is most useful if it's used in real-time. For example, if a user runs OnionShare on their laptop, and then suspends their laptop before the files have been downloaded, the service will not be available until the laptop is unsuspended and connected to the internet again.
As soon as the shared files get downloaded, or when the sender closes OnionShare, the Tor onion service and web servers shut down, completely removing the files from the internet (there is an option to not shut down after the first download, to allow the files to be downloaded multiple times). Because of this, OnionShare is most useful if it's used in real-time. For example, if a user runs OnionShare on their laptop, and then suspends their laptop before the files have been downloaded, the service will not be available until the laptop is unsuspended and connected to the internet again.
## What it protects against
* **Third parties don't have access to files being shared.** The files are hosted directly on the sender's computer and don't get uploaded to any server. Instead, the sender's computer becomes the server. Traditional ways of sending files, like in an email or using a cloud hosting service, require trusting the service with access to the files being shared.
* **Network eavesdroppers can't spy on files in transit.** Because connections between Tor hidden services and Tor Browser are end-to-end encrypted, no network attackers can eavesdrop on the shared files while the recipient is downloading them. If the eavesdropper is positioned on the sender's end, the recipient's end, or is a malicious Tor node, they will only see Tor traffic. If the eavesdropper is a malicious rendezvous node used to connect the recipient's Tor client with the sender's hidden service, the traffic will be encrypted using the hidden service key.
* **Network eavesdroppers can't spy on files in transit.** Because connections between Tor onion services and Tor Browser are end-to-end encrypted, no network attackers can eavesdrop on the shared files while the recipient is downloading them. If the eavesdropper is positioned on the sender's end, the recipient's end, or is a malicious Tor node, they will only see Tor traffic. If the eavesdropper is a malicious rendezvous node used to connect the recipient's Tor client with the sender's onion service, the traffic will be encrypted using the onion service key.
* **Anonymity of sender and recipient are protected by Tor.** OnionShare and Tor Browser protect the anonymity of the users. As long as the sender anonymously communicates the OnionShare URL with the recipient, the recipient and eavesdroppers can't learn the identity of the sender.
* **If an attacker enumerates the hidden service, the shared files remain safe.** There have been attacks against the Tor network that can enumerate hidden services. If someone discovers the .onion address of an OnionShare hidden service, they still cannot download the shared files without knowing the slug. The slug is generated by choosing two random words from a list of 6800 words, meaning there are 6800^2, or about 46 million possible slugs. But they can only make 20 wrong guesses before OnionShare stops the server, preventing brute force attacks against the slug. The OnionShare server also checks request URIs using a constant time string comparison function, so timing attacks can't be used to help guess the slug.
* **If an attacker enumerates the onion service, the shared files remain safe.** There have been attacks against the Tor network that can enumerate onion services. If someone discovers the .onion address of an OnionShare onion service, they still cannot download the shared files without knowing the slug. The slug is generated by choosing two random words from a list of 6800 words, meaning there are 6800^2, or about 46 million possible slugs. But they can only make 20 wrong guesses before OnionShare stops the server, preventing brute force attacks against the slug. The OnionShare server also checks request URIs using a constant time string comparison function, so timing attacks can't be used to help guess the slug.
## What it doesn't protect against

18
install/Info.plist Normal file
View File

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleExecutable</key>
<string>onionshare-gui</string>
<key>CFBundleIdentifier</key>
<string>com.micahflee.onionshare</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>CFBundleShortVersionString</key>
<string>{VERSION}</string>
<key>CFBundleIconFile</key>
<string>icon.icns</string>
</dict>
</plist>

View File

@ -1,10 +1,12 @@
REM use PyInstaller to builder a folder with onionshare.exe
pyinstaller install\pyinstaller.spec -y
REM build onionshare.exe, onionshare-gui.exe
python setup.py build
REM sign onionshare.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 dist\onionshare\onionshare.exe
REM sign onionshare.exe, onionshare-gui.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 build\exe.win32-3.5\onionshare.exe
signtool.exe sign /v /d "OnionShare" /a /tr http://timestamp.globalsign.com/scripts/timstamp.dll /fd sha256 build\exe.win32-3.5\onionshare-gui.exe
REM build an installer, dist\OnionShare_Setup.exe
mkdir dist
makensis.exe install\onionshare.nsi
REM sign OnionShare_Setup.exe

View File

@ -5,19 +5,27 @@ cd $ROOT
# deleting dist
echo Deleting dist folder
rm -rf $ROOT/dist &>/dev/null 2>&1
rm -rf $ROOT/build $ROOT/dist &>/dev/null 2>&1
# build the .app
echo Building OnionShare.app
pyinstaller install/pyinstaller.spec
python3 setup.py bdist_mac
if [ "$1" = "--sign" ]; then
SIGNING_IDENTITY_APP="3rd Party Mac Developer Application: Micah Lee"
SIGNING_IDENTITY_INSTALLER="3rd Party Mac Developer Installer: Micah Lee"
if [ "$1" = "--release" ]; then
mkdir -p dist
APP_PATH="build/OnionShare.app"
PKG_PATH="dist/OnionShare.pkg"
IDENTITY_NAME_APPLICATION="Developer ID Application: Micah Lee"
IDENTITY_NAME_INSTALLER="Developer ID Installer: Micah Lee"
# codesign the .app
codesign -vvvv --deep -s "$SIGNING_IDENTITY_APP" dist/OnionShare.app
echo "Codesigning the app bundle"
codesign --deep -s "$IDENTITY_NAME_APPLICATION" "$APP_PATH"
# build .pkg
productbuild --component dist/OnionShare.app /Applications dist/OnionShare.pkg --sign "$SIGNING_IDENTITY_INSTALLER"
echo "Creating an installer"
productbuild --sign "$IDENTITY_NAME_INSTALLER" --component "$APP_PATH" /Applications "$PKG_PATH"
echo "Cleaning up"
rm -rf "$APP_PATH"
echo "All done, your installer is in: $PKG_PATH"
fi

View File

@ -9,7 +9,7 @@ VERSION=`cat resources/version.txt`
rm -r build dist >/dev/null 2>&1
# build binary package
python3 setup.py bdist_rpm --requires="python3-flask, python3-stem, python3-qt5"
python3 setup.py bdist_rpm --requires="python3-flask, python3-stem, python3-qt5, nautilus-python"
# install it
echo ""

View File

@ -1,18 +1,18 @@
!define APPNAME "OnionShare"
!define BINPATH "..\dist\onionshare"
!define BINPATH "..\build\exe.win32-3.5"
!define ABOUTURL "https:\\onionshare.org\"
# change these with each release
!define INSTALLSIZE 60866
!define INSTALLSIZE 35630
!define VERSIONMAJOR 0
!define VERSIONMINOR 9
!define VERSIONSTRING "0.9"
!define VERSIONSTRING "0.9.1"
RequestExecutionLevel admin
Name "OnionShare"
InstallDir "$PROGRAMFILES\${APPNAME}"
LicenseData "license.txt"
LicenseData "..\resources\license.txt"
Icon "onionshare.ico"
!include LogicLib.nsh
@ -61,51 +61,68 @@ FunctionEnd
Section "install"
SetOutPath "$INSTDIR"
File "onionshare.ico"
SetOutPath "$INSTDIR\html"
File "${BINPATH}\html\404.html"
File "${BINPATH}\html\denied.html"
File "${BINPATH}\html\index.html"
SetOutPath "$INSTDIR\images"
File "${BINPATH}\images\logo.png"
File "${BINPATH}\images\drop_files.png"
File "${BINPATH}\images\server_stopped.png"
File "${BINPATH}\images\server_started.png"
File "${BINPATH}\images\server_working.png"
SetOutPath "$INSTDIR\Include"
File "${BINPATH}\include\pyconfig.h"
SetOutPath "$INSTDIR\locale"
File "${BINPATH}\locale\de.json"
File "${BINPATH}\locale\en.json"
File "${BINPATH}\locale\eo.json"
File "${BINPATH}\locale\es.json"
File "${BINPATH}\locale\fi.json"
File "${BINPATH}\locale\fr.json"
File "${BINPATH}\locale\it.json"
File "${BINPATH}\locale\nl.json"
File "${BINPATH}\locale\no.json"
File "${BINPATH}\locale\pt.json"
File "${BINPATH}\locale\ru.json"
File "${BINPATH}\locale\tr.json"
SetOutPath "$INSTDIR\qt5_plugins\iconengines"
File "${BINPATH}\qt5_plugins\iconengines\qsvgicon.dll"
SetOutPath "$INSTDIR\qt5_plugins\imageformats"
File "${BINPATH}\qt5_plugins\imageformats\qdds.dll"
File "${BINPATH}\qt5_plugins\imageformats\qgif.dll"
File "${BINPATH}\qt5_plugins\imageformats\qicns.dll"
File "${BINPATH}\qt5_plugins\imageformats\qico.dll"
File "${BINPATH}\qt5_plugins\imageformats\qjp2.dll"
File "${BINPATH}\qt5_plugins\imageformats\qjpeg.dll"
File "${BINPATH}\qt5_plugins\imageformats\qmng.dll"
File "${BINPATH}\qt5_plugins\imageformats\qsvg.dll"
File "${BINPATH}\qt5_plugins\imageformats\qtga.dll"
File "${BINPATH}\qt5_plugins\imageformats\qtiff.dll"
File "${BINPATH}\qt5_plugins\imageformats\qwbmp.dll"
File "${BINPATH}\qt5_plugins\imageformats\qwebp.dll"
SetOutPath "$INSTDIR\qt5_plugins\platforms"
File "${BINPATH}\qt5_plugins\platforms\qminimal.dll"
File "${BINPATH}\qt5_plugins\platforms\qoffscreen.dll"
File "${BINPATH}\qt5_plugins\platforms\qwindows.dll"
SetOutPath "$INSTDIR\imageformats"
File "${BINPATH}\imageformats\qdds.dll"
File "${BINPATH}\imageformats\qgif.dll"
File "${BINPATH}\imageformats\qicns.dll"
File "${BINPATH}\imageformats\qico.dll"
File "${BINPATH}\imageformats\qjpeg.dll"
File "${BINPATH}\imageformats\qsvg.dll"
File "${BINPATH}\imageformats\qtga.dll"
File "${BINPATH}\imageformats\qtiff.dll"
File "${BINPATH}\imageformats\qwbmp.dll"
File "${BINPATH}\imageformats\qwebp.dll"
SetOutPath "$INSTDIR\platforms"
File "${BINPATH}\platforms\qminimal.dll"
File "${BINPATH}\platforms\qoffscreen.dll"
File "${BINPATH}\platforms\qwindows.dll"
SetOutPath "$INSTDIR\resources"
File "${BINPATH}\resources\license.txt"
File "${BINPATH}\resources\version.txt"
File "${BINPATH}\resources\wordlist.txt"
SetOutPath "$INSTDIR\resources\html"
File "${BINPATH}\resources\html\404.html"
File "${BINPATH}\resources\html\denied.html"
File "${BINPATH}\resources\html\index.html"
SetOutPath "$INSTDIR\resources\images"
File "${BINPATH}\resources\images\logo.png"
File "${BINPATH}\resources\images\drop_files.png"
File "${BINPATH}\resources\images\server_stopped.png"
File "${BINPATH}\resources\images\server_started.png"
File "${BINPATH}\resources\images\server_working.png"
SetOutPath "$INSTDIR\resources\locale"
File "${BINPATH}\resources\locale\de.json"
File "${BINPATH}\resources\locale\en.json"
File "${BINPATH}\resources\locale\eo.json"
File "${BINPATH}\resources\locale\es.json"
File "${BINPATH}\resources\locale\fi.json"
File "${BINPATH}\resources\locale\fr.json"
File "${BINPATH}\resources\locale\it.json"
File "${BINPATH}\resources\locale\nl.json"
File "${BINPATH}\resources\locale\no.json"
File "${BINPATH}\resources\locale\pt.json"
File "${BINPATH}\resources\locale\ru.json"
File "${BINPATH}\resources\locale\tr.json"
SetOutPath "$INSTDIR"
File "${BINPATH}\MSVCP140.dll"
File "${BINPATH}\onionshare-gui.exe"
File "${BINPATH}\onionshare.exe"
File "${BINPATH}\pyexpat.pyd"
File "${BINPATH}\PyQt5.QtCore.pyd"
File "${BINPATH}\PyQt5.QtGui.pyd"
File "${BINPATH}\PyQt5.QtWidgets.pyd"
File "${BINPATH}\python35.dll"
File "${BINPATH}\python35.zip"
File "${BINPATH}\pywintypes35.dll"
File "${BINPATH}\Qt5Core.dll"
File "${BINPATH}\Qt5Gui.dll"
File "${BINPATH}\Qt5Svg.dll"
File "${BINPATH}\Qt5Widgets.dll"
File "${BINPATH}\select.pyd"
File "${BINPATH}\sip.pyd"
File "${BINPATH}\unicodedata.pyd"
File "${BINPATH}\VCRUNTIME140.dll"
File "${BINPATH}\win32wnet.pyd"
File "${BINPATH}\_bz2.pyd"
File "${BINPATH}\_ctypes.pyd"
File "${BINPATH}\_decimal.pyd"
@ -114,33 +131,6 @@ Section "install"
File "${BINPATH}\_multiprocessing.pyd"
File "${BINPATH}\_socket.pyd"
File "${BINPATH}\_ssl.pyd"
File "${BINPATH}\base_library.zip"
File "${BINPATH}\icudt53.dll"
File "${BINPATH}\icuin53.dll"
File "${BINPATH}\icuuc53.dll"
File "${BINPATH}\MSVCP100.dll"
File "${BINPATH}\MSVCR100.dll"
File "${BINPATH}\onionshare.exe"
File "${BINPATH}\onionshare.exe.manifest"
File "${BINPATH}\pyexpat.pyd"
File "${BINPATH}\PyQt5.Qt.pyd"
File "${BINPATH}\PyQt5.QtCore.pyd"
File "${BINPATH}\PyQt5.QtGui.pyd"
File "${BINPATH}\PyQt5.QtPrintSupport.pyd"
File "${BINPATH}\PyQt5.QtWidgets.pyd"
File "${BINPATH}\python34.dll"
File "${BINPATH}\pywintypes34.dll"
File "${BINPATH}\Qt5Core.dll"
File "${BINPATH}\Qt5Gui.dll"
File "${BINPATH}\Qt5PrintSupport.dll"
File "${BINPATH}\Qt5Svg.dll"
File "${BINPATH}\Qt5Widgets.dll"
File "${BINPATH}\select.pyd"
File "${BINPATH}\sip.pyd"
File "${BINPATH}\unicodedata.pyd"
File "${BINPATH}\version.txt"
File "${BINPATH}\win32wnet.pyd"
File "${BINPATH}\wordlist.txt"
# uninstaller
!ifndef INNER
@ -149,7 +139,7 @@ Section "install"
!endif
# start menu
CreateShortCut "$SMPROGRAMS\${APPNAME}.lnk" "$INSTDIR\onionshare.exe" "" "$INSTDIR\onionshare.ico"
CreateShortCut "$SMPROGRAMS\${APPNAME}.lnk" "$INSTDIR\onionshare-gui.exe" "" "$INSTDIR\onionshare.ico"
# registry information for add\remove programs
WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
@ -184,43 +174,61 @@ FunctionEnd
Delete "$SMPROGRAMS\${APPNAME}.lnk"
# remove files
Delete "$INSTDIR\html\404.html"
Delete "$INSTDIR\html\denied.html"
Delete "$INSTDIR\html\index.html"
Delete "$INSTDIR\images\logo.png"
Delete "$INSTDIR\images\drop_files.png"
Delete "$INSTDIR\images\server_stopped.png"
Delete "$INSTDIR\images\server_started.png"
Delete "$INSTDIR\images\server_working.png"
Delete "$INSTDIR\include\pyconfig.h"
Delete "$INSTDIR\locale\de.json"
Delete "$INSTDIR\locale\en.json"
Delete "$INSTDIR\locale\eo.json"
Delete "$INSTDIR\locale\es.json"
Delete "$INSTDIR\locale\fi.json"
Delete "$INSTDIR\locale\fr.json"
Delete "$INSTDIR\locale\it.json"
Delete "$INSTDIR\locale\nl.json"
Delete "$INSTDIR\locale\no.json"
Delete "$INSTDIR\locale\pt.json"
Delete "$INSTDIR\locale\ru.json"
Delete "$INSTDIR\locale\tr.json"
Delete "$INSTDIR\qt5_plugins\iconengines\qsvgicon.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qdds.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qgif.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qicns.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qico.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qjp2.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qjpeg.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qmng.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qsvg.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qtga.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qtiff.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qwbmp.dll"
Delete "$INSTDIR\qt5_plugins\imageformats\qwebp.dll"
Delete "$INSTDIR\qt5_plugins\platforms\qminimal.dll"
Delete "$INSTDIR\qt5_plugins\platforms\qoffscreen.dll"
Delete "$INSTDIR\qt5_plugins\platforms\qwindows.dll"
Delete "$INSTDIR\imageformats\qdds.dll"
Delete "$INSTDIR\imageformats\qgif.dll"
Delete "$INSTDIR\imageformats\qicns.dll"
Delete "$INSTDIR\imageformats\qico.dll"
Delete "$INSTDIR\imageformats\qjpeg.dll"
Delete "$INSTDIR\imageformats\qsvg.dll"
Delete "$INSTDIR\imageformats\qtga.dll"
Delete "$INSTDIR\imageformats\qtiff.dll"
Delete "$INSTDIR\imageformats\qwbmp.dll"
Delete "$INSTDIR\imageformats\qwebp.dll"
Delete "$INSTDIR\platforms\qminimal.dll"
Delete "$INSTDIR\platforms\qoffscreen.dll"
Delete "$INSTDIR\platforms\qwindows.dll"
Delete "$INSTDIR\resources\license.txt"
Delete "$INSTDIR\resources\version.txt"
Delete "$INSTDIR\resources\wordlist.txt"
Delete "$INSTDIR\resources\html\404.html"
Delete "$INSTDIR\resources\html\denied.html"
Delete "$INSTDIR\resources\html\index.html"
Delete "$INSTDIR\resources\images\logo.png"
Delete "$INSTDIR\resources\images\drop_files.png"
Delete "$INSTDIR\resources\images\server_stopped.png"
Delete "$INSTDIR\resources\images\server_started.png"
Delete "$INSTDIR\resources\images\server_working.png"
Delete "$INSTDIR\resources\locale\de.json"
Delete "$INSTDIR\resources\locale\en.json"
Delete "$INSTDIR\resources\locale\eo.json"
Delete "$INSTDIR\resources\locale\es.json"
Delete "$INSTDIR\resources\locale\fi.json"
Delete "$INSTDIR\resources\locale\fr.json"
Delete "$INSTDIR\resources\locale\it.json"
Delete "$INSTDIR\resources\locale\nl.json"
Delete "$INSTDIR\resources\locale\no.json"
Delete "$INSTDIR\resources\locale\pt.json"
Delete "$INSTDIR\resources\locale\ru.json"
Delete "$INSTDIR\resources\locale\tr.json"
Delete "$INSTDIR\MSVCP140.dll"
Delete "$INSTDIR\onionshare-gui.exe"
Delete "$INSTDIR\onionshare.exe"
Delete "$INSTDIR\pyexpat.pyd"
Delete "$INSTDIR\PyQt5.QtCore.pyd"
Delete "$INSTDIR\PyQt5.QtGui.pyd"
Delete "$INSTDIR\PyQt5.QtWidgets.pyd"
Delete "$INSTDIR\python35.dll"
Delete "$INSTDIR\python35.zip"
Delete "$INSTDIR\pywintypes35.dll"
Delete "$INSTDIR\Qt5Core.dll"
Delete "$INSTDIR\Qt5Gui.dll"
Delete "$INSTDIR\Qt5Svg.dll"
Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\select.pyd"
Delete "$INSTDIR\sip.pyd"
Delete "$INSTDIR\unicodedata.pyd"
Delete "$INSTDIR\VCRUNTIME140.dll"
Delete "$INSTDIR\win32wnet.pyd"
Delete "$INSTDIR\_bz2.pyd"
Delete "$INSTDIR\_ctypes.pyd"
Delete "$INSTDIR\_decimal.pyd"
@ -229,44 +237,16 @@ FunctionEnd
Delete "$INSTDIR\_multiprocessing.pyd"
Delete "$INSTDIR\_socket.pyd"
Delete "$INSTDIR\_ssl.pyd"
Delete "$INSTDIR\base_library.zip"
Delete "$INSTDIR\icudt53.dll"
Delete "$INSTDIR\icuin53.dll"
Delete "$INSTDIR\icuuc53.dll"
Delete "$INSTDIR\MSVCP100.dll"
Delete "$INSTDIR\MSVCR100.dll"
Delete "$INSTDIR\onionshare.exe"
Delete "$INSTDIR\onionshare.exe.manifest"
Delete "$INSTDIR\pyexpat.pyd"
Delete "$INSTDIR\PyQt5.Qt.pyd"
Delete "$INSTDIR\PyQt5.QtCore.pyd"
Delete "$INSTDIR\PyQt5.QtGui.pyd"
Delete "$INSTDIR\PyQt5.QtPrintSupport.pyd"
Delete "$INSTDIR\PyQt5.QtWidgets.pyd"
Delete "$INSTDIR\python34.dll"
Delete "$INSTDIR\pywintypes34.dll"
Delete "$INSTDIR\Qt5Core.dll"
Delete "$INSTDIR\Qt5Gui.dll"
Delete "$INSTDIR\Qt5PrintSupport.dll"
Delete "$INSTDIR\Qt5Svg.dll"
Delete "$INSTDIR\Qt5Widgets.dll"
Delete "$INSTDIR\select.pyd"
Delete "$INSTDIR\sip.pyd"
Delete "$INSTDIR\unicodedata.pyd"
Delete "$INSTDIR\version.txt"
Delete "$INSTDIR\win32wnet.pyd"
Delete "$INSTDIR\wordlist.txt"
Delete "$INSTDIR\onionshare.ico"
Delete "$INSTDIR\uninstall.exe"
rmDir "$INSTDIR\html"
rmDir "$INSTDIR\images"
rmDir "$INSTDIR\Include"
rmDir "$INSTDIR\locale"
rmDir "$INSTDIR\qt5_plugins\iconengines"
rmDir "$INSTDIR\qt5_plugins\imageformats"
rmDir "$INSTDIR\qt5_plugins\platforms"
rmDir "$INSTDIR\qt5_plugins"
rmDir "$INSTDIR\imageformats"
rmDir "$INSTDIR\platforms"
rmDir "$INSTDIR\resources\html"
rmDir "$INSTDIR\resources\images"
rmDir "$INSTDIR\resources\locale"
rmDir "$INSTDIR\resources"
rmDir "$INSTDIR"
# remove uninstaller information from the registry

View File

@ -7,10 +7,10 @@
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
cd $DIR
VERSION=`cat version`
VERSION=`cat resources/version.txt`
rm -rf deb_dist >/dev/null 2>&1
python setup.py --command-packages=stdeb.command sdist_dsc
python3 setup.py --command-packages=stdeb.command sdist_dsc
cd deb_dist/onionshare-$VERSION
dpkg-buildpackage -S
cd ..

View File

@ -1,59 +0,0 @@
# -*- mode: python -*-
import platform
system = platform.system()
block_cipher = None
a = Analysis(
['scripts/onionshare-gui'],
pathex=['.'],
binaries=None,
datas=[
('../resources/images/*', 'images'),
('../resources/locale/*', 'locale'),
('../resources/html/*', 'html'),
('../resources/version.txt', '.'),
('../resources/wordlist.txt', '.')
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher)
pyz = PYZ(
a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
exclude_binaries=True,
name='onionshare',
debug=False,
strip=False,
upx=True,
console=False)
coll = COLLECT(
exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
name='onionshare')
if system == 'Darwin':
app = BUNDLE(
coll,
name='OnionShare.app',
icon='install/onionshare.icns',
bundle_identifier='com.micahflee.onionshare',
info_plist={
'NSHighResolutionCapable': 'True'
}
)

View File

@ -18,12 +18,5 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os
try:
import onionshare
except ImportError:
sys.path.append(os.path.abspath(os.path.dirname(__file__)+'/..'))
import onionshare
import onionshare
onionshare.main()

View File

@ -18,12 +18,5 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os
try:
import onionshare_gui
except ImportError:
sys.path.append(os.path.abspath(os.path.dirname(__file__)+'/..'))
import onionshare_gui
import onionshare_gui
onionshare_gui.main()

View File

@ -0,0 +1,46 @@
#!/usr/bin/env python
import os
import subprocess
import urllib
import gi
gi.require_version('Nautilus', '3.0')
from gi.repository import Nautilus
from gi.repository import GObject
# Put me in /usr/share/nautilus-python/extensions/
class OnionShareExtension(GObject.GObject, Nautilus.MenuProvider):
def __init__(self):
pass
def url2path(self,url):
file_uri = url.get_activation_uri()
arg_uri = file_uri[7:]
path = urllib.url2pathname(arg_uri)
return path
def exec_onionshare(self, filenames):
# Would prefer this method but there is a conflict between GTK 2.0 vs GTK 3.0 components being loaded at once
# (nautilus:3090): Gtk-ERROR **: GTK+ 2.x symbols detected. Using GTK+ 2.x and GTK+ 3 in the same process is not supported
# sys.argv = ["", "--filenames"] + filenames
# sys.exit(onionshare_gui.main())
path = os.path.join(os.sep, 'usr', 'bin', 'onionshare-gui')
cmd = [path, "--filenames"] + filenames
subprocess.Popen(cmd)
def get_file_items(self, window, files):
menuitem = Nautilus.MenuItem(name='OnionShare::Nautilus',
label='Share via OnionShare',
tip='',
icon='')
menu = Nautilus.Menu()
menu.append_item(menuitem)
menuitem.connect("activate", self.menu_activate_cb, files)
return menuitem,
def menu_activate_cb(self, menu, files):
file_list = []
for file in files:
file_list.append(self.url2path(file))
self.exec_onionshare(file_list)

View File

@ -17,7 +17,7 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import sys, os, inspect, hashlib, base64, hmac, platform, zipfile, tempfile, math, time
import sys, os, inspect, hashlib, base64, platform, zipfile, tempfile, math, time
from random import SystemRandom
@ -34,20 +34,14 @@ def get_resource_path(filename):
systemwide, and whether regardless of platform
"""
p = get_platform()
if p == 'Linux':
if p == 'Linux' and sys.argv and sys.argv[0].startswith('/usr/bin/onionshare'):
# OnionShare is installed systemwide in Linux
if len(sys.argv) > 0 and sys.argv[0].startswith('/usr/bin/onionshare'):
resources_dir = os.path.join(sys.prefix, 'share/onionshare')
# Look for resources directory relative to python file
else:
resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'resources')
else:
# Check if app is "frozen" with pyinstaller
# https://pythonhosted.org/PyInstaller/#run-time-information
if getattr(sys, 'frozen', False):
resources_dir = sys._MEIPASS
else:
resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'resources')
resources_dir = os.path.join(sys.prefix, 'share/onionshare')
elif getattr(sys, 'frozen', False): # Check if app is "frozen" with cx_Freeze
# http://cx-freeze.readthedocs.io/en/latest/faq.html#using-data-files
resources_dir = os.path.join(os.path.dirname(sys.executable), 'resources')
else: # Look for resources directory relative to python file
resources_dir = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))), 'resources')
return os.path.join(resources_dir, filename)

View File

@ -32,27 +32,19 @@ class NoTor(Exception):
"""
pass
class HSDirError(Exception):
class Onion(object):
"""
This exception is raised when onionshare tries create a non-ephemeral
hidden service and does not have permission to create or write to
the hidden service directory.
"""
pass
class HS(object):
"""
HS is an abstraction layer for connecting to the Tor control port and
creating hidden services. Onionshare supports creating hidden services
Onion is an abstraction layer for connecting to the Tor control port and
creating onion services. OnionShare supports creating onion services
using two methods:
- Modifying the Tor configuration through the control port is the old
method, and will be deprecated in favor of ephemeral hidden services.
- Using the control port to create ephemeral hidden servers is the
method, and will be deprecated in favor of ephemeral onion services.
- Using the control port to create ephemeral onion servers is the
preferred method.
This class detects the versions of Tor and stem to determine if ephemeral
hidden services are supported. If not, it falls back to modifying the
onion services are supported. If not, it falls back to modifying the
Tor configuration.
"""
def __init__(self, transparent_torification=False):
@ -77,45 +69,36 @@ class HS(object):
if not found_tor:
raise NoTor(strings._("cant_connect_ctrlport").format(str(ports)))
# do the versions of stem and tor that I'm using support ephemeral hidden services?
# do the versions of stem and tor that I'm using support ephemeral onion services?
tor_version = self.c.get_version().version_str
list_ephemeral_hidden_services = getattr(self.c, "list_ephemeral_hidden_services", None)
self.supports_ephemeral = callable(list_ephemeral_hidden_services) and tor_version >= '0.2.7.1'
def start(self, port):
"""
Start a hidden service on port 80, pointing to the given port, and
Start a onion service on port 80, pointing to the given port, and
return the onion hostname.
"""
print(strings._("connecting_ctrlport").format(int(port)))
if self.supports_ephemeral:
print(strings._('using_ephemeral'))
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication = False)
res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication = True)
self.service_id = res.content()[0][2].split('=')[1]
onion_host = res.content()[0][2].split('=')[1] + '.onion'
onion_host = self.service_id + '.onion'
return onion_host
else:
# come up with a hidden service directory name
# come up with a onion service directory name
if helpers.get_platform() == 'Windows':
self.hidserv_dir = tempfile.mkdtemp()
self.hidserv_dir = self.hidserv_dir.replace('\\', '/')
else:
path = '/tmp/onionshare'
try:
if not os.path.exists(path):
os.makedirs(path, 0o700)
except:
raise HSDirError(strings._("error_hs_dir_cannot_create").format(path))
if not os.access(path, os.W_OK):
raise HSDirError(strings._("error_hs_dir_not_writable").format(path))
self.hidserv_dir = tempfile.mkdtemp(dir=path)
self.hidserv_dir = tempfile.mkdtemp(suffix='onionshare',dir='/tmp')
self.cleanup_filenames.append(self.hidserv_dir)
# set up hidden service
# set up onion service
hsdic = self.c.get_conf_map('HiddenServiceOptions') or {
'HiddenServiceDir': [], 'HiddenServicePort': []
}
@ -137,11 +120,11 @@ class HS(object):
def wait_for_hs(self, onion_host):
"""
This function is only required when using non-ephemeral hidden services. After
creating a hidden service, continually attempt to connect to it until it
successfully connects..
This function is only required when using non-ephemeral onion services. After
creating a onion service, continually attempt to connect to it until it
successfully connects.
"""
# legacy only, this function is no longer required with ephemeral hidden services
# legacy only, this function is no longer required with ephemeral onion services
print(strings._('wait_for_hs'))
ready = False
@ -186,20 +169,20 @@ class HS(object):
def cleanup(self):
"""
Stop hidden services that were created earlier, and delete any temporary
Stop onion services that were created earlier, and delete any temporary
files that were created.
"""
if self.supports_ephemeral:
# cleanup the ephemeral hidden service
# cleanup the ephemeral onion service
if self.service_id:
self.c.remove_ephemeral_hidden_service(self.service_id)
self.service_id = None
else:
# cleanup hidden service
# cleanup onion service
try:
if self.controller:
# Get fresh hidden services (maybe changed since last time)
# Get fresh onion services (maybe changed since last time)
# and remove ourselves
hsdic = self.controller.get_conf_map('HiddenServiceOptions') or {
'HiddenServiceDir': [], 'HiddenServicePort': []
@ -233,17 +216,17 @@ class HS(object):
'80 127.0.0.1:33302'
],
'HiddenServiceDir': [
'/tmp/onionshare/tmplTfZZu',
'/tmp/onionshare/tmpchDai3'
'/tmp/onionsharelTfZZu',
'/tmp/onionsharechDai3'
]
}
Output will look like this:
[
('HiddenServiceDir', '/tmp/onionshare/tmplTfZZu'),
('HiddenServiceDir', '/tmp/onionsharelTfZZu'),
('HiddenServicePort', '80 127.0.0.1:47906'),
('HiddenServiceDir', '/tmp/onionshare/tmpchDai3'),
('HiddenServiceDir', '/tmp/onionsharechDai3'),
('HiddenServicePort', '80 127.0.0.1:33302')
]
"""

View File

@ -18,18 +18,18 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os, sys, subprocess, time, argparse, inspect, shutil, socket, threading
import os, sys, time, argparse, shutil, socket, threading
from . import strings, helpers, web, hs
from . import strings, helpers, web, onion
class OnionShare(object):
"""
OnionShare is the main application class. Pass in options and run
start_hidden_service and it will do the magic.
start_onion_service and it will do the magic.
"""
def __init__(self, debug=False, local_only=False, stay_open=False, transparent_torification=False):
self.port = None
self.hs = None
self.onion = None
self.hidserv_dir = None
self.onion_host = None
@ -64,9 +64,9 @@ class OnionShare(object):
self.port = tmpsock.getsockname()[1]
tmpsock.close()
def start_hidden_service(self, gui=False):
def start_onion_service(self):
"""
Start the onionshare hidden service.
Start the onionshare onion service.
"""
if not self.port:
self.choose_port()
@ -75,10 +75,10 @@ class OnionShare(object):
self.onion_host = '127.0.0.1:{0:d}'.format(self.port)
return
if not self.hs:
self.hs = hs.HS(self.transparent_torification)
if not self.onion:
self.onion = onion.Onion(self.transparent_torification)
self.onion_host = self.hs.start(self.port)
self.onion_host = self.onion.start(self.port)
def cleanup(self):
"""
@ -92,9 +92,9 @@ class OnionShare(object):
shutil.rmtree(filename)
self.cleanup_filenames = []
# call hs's cleanup
if self.hs:
self.hs.cleanup()
# cleanup the onion
if self.onion:
self.onion.cleanup()
def main(cwd=None):
@ -102,7 +102,7 @@ def main(cwd=None):
The main() function implements all of the logic that the command-line version of
onionshare uses.
"""
strings.load_strings()
strings.load_strings(helpers)
print(strings._('version_string').format(helpers.get_version()))
# onionshare CLI in OSX needs to change current working directory (#132)
@ -141,10 +141,8 @@ def main(cwd=None):
try:
app = OnionShare(debug, local_only, stay_open, transparent_torification)
app.choose_port()
app.start_hidden_service()
except hs.NoTor as e:
sys.exit(e.args[0])
except hs.HSDirError as e:
app.start_onion_service()
except onion.NoTor as e:
sys.exit(e.args[0])
# prepare files to share
@ -158,15 +156,15 @@ def main(cwd=None):
print(strings._("large_filesize"))
print('')
# start onionshare service in new thread
# start onionshare http service in new thread
t = threading.Thread(target=web.start, args=(app.port, app.stay_open, app.transparent_torification))
t.daemon = True
t.start()
try: # Trap Ctrl-C
# wait for hs, only if using old version of tor
if not app.local_only:
ready = app.hs.wait_for_hs(app.onion_host)
if not app.local_only and not app.onion.supports_ephemeral:
ready = app.onion.wait_for_hs(app.onion_host)
if not ready:
sys.exit()
else:

View File

@ -17,14 +17,11 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import json, locale, sys, os
from . import helpers
import json, locale, os
strings = {}
def load_strings(default="en"):
def load_strings(helpers, default="en"):
"""
Loads translated strings and fallback to English
if the translation does not exist.

View File

@ -20,7 +20,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
import queue, mimetypes, platform, os, sys
from urllib.request import urlopen
from flask import Flask, Response, request, render_template_string, abort
from functools import wraps
from . import strings, helpers
@ -231,7 +230,7 @@ def download(slug_candidate):
# The user has canceled the download, so stop serving the file
if client_cancel:
add_request(REQUEST_CANCELED, path, {'id': download_id})
break;
break
chunk = fp.read(chunk_size)
if chunk == b'':

View File

@ -58,6 +58,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
start_server_finished = QtCore.pyqtSignal()
stop_server_finished = QtCore.pyqtSignal()
starting_server_step2 = QtCore.pyqtSignal()
starting_server_step3 = QtCore.pyqtSignal()
starting_server_error = QtCore.pyqtSignal(str)
def __init__(self, qtapp, app):
super(OnionShareGui, self).__init__()
@ -90,6 +92,8 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.file_selection.file_list.files_updated.connect(self.server_status.update)
self.server_status.url_copied.connect(self.copy_url)
self.starting_server_step2.connect(self.start_server_step2)
self.starting_server_step3.connect(self.start_server_step3)
self.starting_server_error.connect(self.start_server_error)
# filesize warning
self.filesize_warning = QtWidgets.QLabel()
@ -127,52 +131,53 @@ class OnionShareGui(QtWidgets.QMainWindow):
self.timer.timeout.connect(self.check_for_requests)
self.timer.start(500)
def start_server_step2(self):
"""
Step 2 in starting the onionshare server. This displays the large filesize
warning, if applicable.
"""
# warn about sending large files over Tor
if web.zip_filesize >= 157286400: # 150mb
self.filesize_warning.setText(strings._("large_filesize", True))
self.filesize_warning.show()
def start_server(self):
"""
Start the onionshare server. This uses multiple threads to start the Tor hidden
Start the onionshare server. This uses multiple threads to start the Tor onion
server and the web app.
"""
# Reset web counters
web.download_count = 0
web.error404_count = 0
# start the hidden service
self.status_bar.showMessage(strings._('gui_starting_server1', True))
# pick an available local port for the http service to listen on
self.app.choose_port()
try:
self.app.start_hidden_service(gui=True)
except onionshare.hs.NoTor as e:
alert(e.args[0], QtWidgets.QMessageBox.Warning)
self.server_status.stop_server()
self.status_bar.clearMessage()
return
# start onionshare service in new thread
t = threading.Thread(target=web.start, args=(self.app.port, self.app.stay_open, self.app.transparent_torification))
t.daemon = True
t.start()
# start the onion service in a new thread
def start_onion_service(self):
self.status_bar.showMessage(strings._('gui_starting_server1', True))
try:
self.app.start_onion_service()
self.starting_server_step2.emit()
except onionshare.onion.NoTor as e:
self.starting_server_error.emit(e.args[0])
return
t1 = threading.Thread(target=start_onion_service, kwargs={'self': self})
t1.daemon = True
t1.start()
# start onionshare http service in new thread
t2 = threading.Thread(target=web.start, args=(self.app.port, self.app.stay_open, self.app.transparent_torification))
t2.daemon = True
t2.start()
def start_server_step2(self):
"""
Step 2 in starting the onionshare server. Prepare files for serving.
"""
# prepare the files for sending in a new thread
def finish_starting_server(self):
# prepare files to share
web.set_file_info(self.file_selection.file_list.filenames)
self.app.cleanup_filenames.append(web.zip_filename)
self.starting_server_step2.emit()
self.starting_server_step3.emit()
# wait for hs
if not self.app.local_only:
if not self.app.local_only and not self.app.onion.supports_ephemeral:
self.status_bar.showMessage(strings._('gui_starting_server3', True))
self.app.hs.wait_for_hs(self.app.onion_host)
self.app.onion.wait_for_hs(self.app.onion_host)
# done
self.start_server_finished.emit()
@ -182,6 +187,24 @@ class OnionShareGui(QtWidgets.QMainWindow):
t.daemon = True
t.start()
def start_server_step3(self):
"""
Step 3 in starting the onionshare server. This displays the large filesize
warning, if applicable.
"""
# warn about sending large files over Tor
if web.zip_filesize >= 157286400: # 150mb
self.filesize_warning.setText(strings._("large_filesize", True))
self.filesize_warning.show()
def start_server_error(self, error):
"""
If there's an error when trying to start the onion service
"""
alert(error, QtWidgets.QMessageBox.Warning)
self.server_status.stop_server()
self.status_bar.clearMessage()
def stop_server(self):
"""
Stop the onionshare server.
@ -284,7 +307,7 @@ def main():
"""
The main() function implements all of the logic that the GUI version of onionshare uses.
"""
strings.load_strings()
strings.load_strings(helpers)
print(strings._('version_string').format(helpers.get_version()))
# start the Qt app

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,9 @@
{
"connecting_ctrlport": "Připojuju se na kontrolní port Toru pro nastavení hidden service na portu {0:d}.",
"connecting_ctrlport": "Připojuju se na kontrolní port Toru pro nastavení onion service na portu {0:d}.",
"cant_connect_ctrlport": "Nejde se připojit na kontrolní port Toru na portu {0:s}. OnionShare vyžaduje, aby Tor Browser běžel na pozadí. Pokud ho nemáte, můžete ho stáhnout z https://www.torproject.org/.",
"cant_connect_socksport": "Nejde se připojit na Tor SOCKS5 server na portu {0:s}. OnionShare vyžaduje, aby Tor Browser běžel na pozadí. Pokud ho nemáte, můžete ho stáhnout z https://www.torproject.org/.",
"preparing_files": "Připravuji soubory na sdílení.",
"wait_for_hs": "Čekám až bude hidden service připravena:",
"wait_for_hs": "Čekám až bude onion service připravena:",
"wait_for_hs_trying": "Zkouším...",
"wait_for_hs_nope": "Ještě nepřipraven.",
"wait_for_hs_yup": "Připraven!",
@ -17,9 +17,9 @@
"large_filesize": "Varování: Posílání velkých souborů může trvat hodiny",
"error_tails_invalid_port": "Nesprávná hodnota, port musí být celé číslo",
"error_tails_unknown_root": "Unknown error with Tails root process",
"help_tails_port": "Tails only: port for opening firewall, starting hidden service",
"help_tails_port": "Tails only: port for opening firewall, starting onion service",
"help_local_only": "Nepoužívat Tor: jen pro vývoj",
"help_stay_open": "Nechat běžet hidden service po skončení stahování",
"help_stay_open": "Nechat běžet onion service po skončení stahování",
"help_transparent_torification": "My system is transparently torified",
"help_debug": "Zaznamenat chyby na disk",
"help_filename": "Seznam souborů a složek ke sdílení",
@ -35,11 +35,11 @@
"gui_downloads": "Stahování:",
"gui_canceled": "Zrušeno",
"gui_copied_url": "URL zkopírováno do schránky",
"gui_starting_server1": "Spouštím Tor hidden service...",
"gui_starting_server1": "Spouštím Tor onion service...",
"gui_starting_server2": "Crunching files...",
"gui_starting_server3": "Čekám na Tor hidden service...",
"gui_starting_server3": "Čekám na Tor onion service...",
"gui_please_wait": "Prosím čekejte...",
"error_hs_dir_cannot_create": "Nejde vytvořit složka {0:s} pro hidden service",
"error_hs_dir_not_writable": "Nejde zapisovat do složky {0:s} pro hidden service",
"using_ephemeral": "Staring ephemeral Tor hidden service and awaiting publication"
"error_hs_dir_cannot_create": "Nejde vytvořit složka {0:s} pro onion service",
"error_hs_dir_not_writable": "Nejde zapisovat do složky {0:s} pro onion service",
"using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication"
}

View File

@ -17,9 +17,9 @@
"large_filesize": "Warnung: Das Senden von großen Dateien kann Stunden dauern",
"error_tails_invalid_port": "Ungültiger Wert, Port muss eine ganze Zahl sein",
"error_tails_unknown_root": "Unbekannter Fehler mit Tails root Prozess",
"help_tails_port": "Nur für Tails: Port um den Firewall zu öffnen, starte Hidden Service",
"help_tails_port": "Nur für Tails: Port um den Firewall zu öffnen, starte onion service",
"help_local_only": "Nicht mit Tor benutzen, nur für Entwicklung",
"help_stay_open": "Den Hidden Service nicht anhalten nachdem ein Download beendet wurde",
"help_stay_open": "Den onion service nicht anhalten nachdem ein Download beendet wurde",
"help_debug": "Fehler auf Festplatte schreiben",
"help_filename": "Liste der zu teilenden Dateien oder Verzeichnisse",
"gui_drag_and_drop": "Drag & drop\nDateien hier",

View File

@ -1,5 +1,5 @@
{
"connecting_ctrlport": "Connecting to Tor control port to set up hidden service on port {0:d}.",
"connecting_ctrlport": "Connecting to Tor control port to set up onion service on port {0:d}.",
"cant_connect_ctrlport": "Can't connect to Tor control port on port {0:s}. OnionShare requires Tor Browser to be running in the background to work. If you don't have it you can get it from https://www.torproject.org/.",
"cant_connect_socksport": "Can't connect to Tor SOCKS5 server on port {0:s}. OnionShare requires Tor Browser to be running in the background to work. If you don't have it you can get it from https://www.torproject.org/.",
"preparing_files": "Preparing files to share.",
@ -17,9 +17,9 @@
"large_filesize": "Warning: Sending large files could take hours",
"error_tails_invalid_port": "Invalid value, port must be an integer",
"error_tails_unknown_root": "Unknown error with Tails root process",
"help_tails_port": "Tails only: port for opening firewall, starting hidden service",
"help_tails_port": "Tails only: port for opening firewall, starting onion service",
"help_local_only": "Do not attempt to use tor: for development only",
"help_stay_open": "Keep hidden service running after download has finished",
"help_stay_open": "Keep onion service running after download has finished",
"help_transparent_torification": "My system is transparently torified",
"help_debug": "Log errors to disk",
"help_filename": "List of files or folders to share",
@ -35,13 +35,13 @@
"gui_downloads": "Downloads:",
"gui_canceled": "Canceled",
"gui_copied_url": "Copied URL to clipboard",
"gui_starting_server1": "Starting Tor hidden service...",
"gui_starting_server1": "Starting Tor onion service...",
"gui_starting_server2": "Crunching files...",
"gui_starting_server3": "Waiting for Tor hidden service...",
"gui_starting_server3": "Waiting for Tor onion service...",
"gui_please_wait": "Please wait...",
"error_hs_dir_cannot_create": "Cannot create hidden service dir {0:s}",
"error_hs_dir_not_writable": "Hidden service dir {0:s} is not writable",
"using_ephemeral": "Staring ephemeral Tor hidden service and awaiting publication",
"error_hs_dir_cannot_create": "Cannot create onion service dir {0:s}",
"error_hs_dir_not_writable": "onion service dir {0:s} is not writable",
"using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication",
"gui_download_progress_complete": "%p%, Time Elapsed: {0:s}",
"gui_download_progress_starting": "{0:s}, %p% (Computing ETA)",
"gui_download_progress_eta": "{0:s}, ETA: {1:s}, %p%",

View File

@ -1,5 +1,5 @@
{
"connecting_ctrlport": "Konektas al Tor-kontrolpordo por starigi hidden service je pordo {0:d}.",
"connecting_ctrlport": "Konektas al Tor-kontrolpordo por starigi onion service je pordo {0:d}.",
"cant_connect_ctrlport": "Ne eblas konekti al Tor-kontrolpordo je pordo {0:s}. OnionShare bezonas Tor Browser por esti ŝaltita en la fono. Se vi ne havas ĝin, vi povas ricevi ĝin je https://www.torproject.org/.",
"cant_connect_socksport": "Ne eblas konekti al Tor-SOCKS5-servilo je pordo {0:s}. OnionShare bezonas Tor Browser por esti ŝaltita en la fono. Se vi ne havas ĝin, vi povas ricevi ĝin je https://www.torproject.org/.",
"preparing_files": "Preparas dosierojn por kundivido.",
@ -17,9 +17,9 @@
"large_filesize": "Atentigo: Sendado de grandaj dosieroj povas daŭri horojn",
"error_tails_invalid_port": "Malĝusta valoro, pordo devas esti plena nombro",
"error_tails_unknown_root": "Nekonata eraro kun Tails-root-procezo",
"help_tails_port": "Tails only: port for opening firewall, starting hidden service",
"help_tails_port": "Tails only: port for opening firewall, starting onion service",
"help_local_only": "Ne strebu uzi tor: nur por evoluado",
"help_stay_open": "Lasu hidden service funkcii post fino de elŝuto",
"help_stay_open": "Lasu onion service funkcii post fino de elŝuto",
"help_transparent_torification": "My system is transparently torified",
"help_debug": "Protokoli erarojn sur diskon",
"help_filename": "Listo de dosieroj aŭ dosierujoj por kundividi",
@ -35,11 +35,11 @@
"gui_downloads": "Elŝutoj:",
"gui_canceled": "Nuligita",
"gui_copied_url": "URL kopiita en tondujon",
"gui_starting_server1": "Startigas Tor hidden service...",
"gui_starting_server1": "Startigas Tor onion service...",
"gui_starting_server2": "Crunching files...",
"gui_starting_server3": "Atendas por Tor hidden service...",
"gui_starting_server3": "Atendas por Tor onion service...",
"gui_please_wait": "Bonvolu atendi...",
"error_hs_dir_cannot_create": "Ne eblas krei hidden-service-dosierujon {0:s}",
"error_hs_dir_not_writable": "Ne eblas konservi dosierojn en hidden-service-dosierujo {0:s}",
"using_ephemeral": "Staring ephemeral Tor hidden service and awaiting publication"
"using_ephemeral": "Staring ephemeral Tor onion service and awaiting publication"
}

View File

@ -15,10 +15,10 @@
"close_on_finish": "Apagar el servidor automáticamente.",
"closing_automatically": "Apagando automáticamente porque la descarga finalizó",
"error_tails_invalid_port": "Valor inválido, el puerto debe ser un entero",
"error_tails_unknown_root": "Error desconocido en el proceso de Tails corriendo como root",
"error_tails_unknown_root": "Error desconocido en el proceso de Tails ejecutando como roo",
"help_tails_port": "Sólo Tails: puerto para abrir en el firewall, al levantar el servicio oculto",
"help_local_only": "No intentar usar tor: para desarrollo solamente",
"help_stay_open": "Mantener el servicio oculto corriendo después de que la descarga haya finalizado",
"help_local_only": "No intentar usar Tor: sólo para desarrollo",
"help_stay_open": "Mantener el servicio oculto ejecutando después de que la descarga haya finalizado",
"help_debug": "Guardar registro de errores en el disco",
"help_filename": "Lista de archivos o carpetas para compartir",
"gui_drag_and_drop": "Arrastre\narchivos aquí",

View File

@ -1,5 +1,5 @@
{
"connecting_ctrlport": "Connexion au réseau Tor pour mettre en place un Hidden Service sur le port {0:d}.",
"connecting_ctrlport": "Connexion au réseau Tor pour mettre en place un onion service sur le port {0:d}.",
"cant_connect_ctrlport": "Impossible de se connecter au port de contrôle Tor sur le port {0:s}. Est-ce que Tor tourne ?",
"preparing_files": "Préparation des fichiers à partager.",
"wait_for_hs": "En attente du HS:",
@ -15,9 +15,9 @@
"closing_automatically": "Fermeture automatique car le téléchargement est fini",
"error_tails_invalid_port": "Valeur invalide, le port doit être un nombre entier",
"error_tails_unknown_root": "Erreur inconnue avec un processus root sur Tails",
"help_tails_port": "Seulement sur Tails: port pour ouvrir le firewall, démarrage du Hidden Service",
"help_tails_port": "Seulement sur Tails: port pour ouvrir le firewall, démarrage du onion service",
"help_local_only": "Ne tentez pas d'utiliser Tor, uniquement pour développement",
"help_stay_open": "Laisser tourner le Hidden Service après que le téléchargment soit fini",
"help_stay_open": "Laisser tourner le onion service après que le téléchargment soit fini",
"help_debug": "Enregistrer les erreurs sur le disque",
"help_filename": "Liste des fichiers ou dossiers à partager",
"gui_drag_and_drop": "Glissez déposez\nles fichiers ici",

View File

@ -35,11 +35,11 @@
"gui_downloads": "Downloads:",
"gui_canceled": "Afgebroken",
"gui_copied_url": "URL gekopieerd naar klembord",
"gui_starting_server1": "Tor hidden service wordt gestart...",
"gui_starting_server1": "Tor onion service wordt gestart...",
"gui_starting_server2": "Bestanden verwerken...",
"gui_starting_server3": "Wachten op Tor hidden service...",
"gui_starting_server3": "Wachten op Tor onion service...",
"gui_please_wait": "Moment geduld...",
"error_hs_dir_cannot_create": "Kan verborgen service map {0:s} niet aanmaken",
"error_hs_dir_not_writable": "Verborgen service map {0:s} is niet schrijfbaar",
"using_ephemeral": "Kortstondige Tor hidden service gestart en in afwachting van publicatie"
"using_ephemeral": "Kortstondige Tor onion service gestart en in afwachting van publicatie"
}

View File

@ -17,7 +17,7 @@
"large_filesize": "Uyarı: Büyük dosyaların gönderimi saatler sürebilir",
"error_tails_invalid_port": "Geçersiz değer, port sayı olmalıdır",
"error_tails_unknown_root": "Tails ana işlemi ile ilgili bilinmeyen hata",
"help_tails_port": "Sadece Tails: port for opening firewall, starting hidden service",
"help_tails_port": "Sadece Tails: port for opening firewall, starting onion service",
"help_local_only": "Tor kullanmaya kalkışmayın: sadece geliştirme için",
"help_stay_open": "İndirme tamamlandıktan sonra gizli hizmeti çalıştırmaya devam et",
"help_transparent_torification": "Sistemim apaçık torlu",

View File

@ -1 +1 @@
0.9
0.9.1-dev

165
setup.py
View File

@ -19,12 +19,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import os, sys
try:
from setuptools import setup
except ImportError:
from distutils.core import setup
import os, sys, platform, tempfile
def file_list(path):
files = []
@ -34,72 +29,120 @@ def file_list(path):
return files
version = open('resources/version.txt').read().strip()
description = (
"""OnionShare lets you securely and anonymously share a file of any size with someone. """
"""It works by starting a web server, making it accessible as a Tor hidden service, """
"""and generating an unguessable URL to access and download the file.""")
long_description = description + " " + (
"""It doesn't require setting up a server on the internet somewhere or using a third """
"""party filesharing service. You host the file on your own computer and use a Tor """
"""hidden service to make it temporarily accessible over the internet. The other user """
"""just needs to use Tor Browser to download the file from you."""
)
author = 'Micah Lee'
author_email = 'micah@micahflee.com'
url = 'https://github.com/micahflee/onionshare'
license = 'GPL v3'
keywords = 'onion, share, onionshare, tor, anonymous, web server'
images = [
'resources/images/logo.png',
'resources/images/drop_files.png',
'resources/images/server_stopped.png',
'resources/images/server_started.png',
'resources/images/server_working.png'
]
p = platform.system()
locale = [
'resources/locale/cs.json',
'resources/locale/de.json',
'resources/locale/en.json',
'resources/locale/eo.json',
'resources/locale/es.json',
'resources/locale/fi.json',
'resources/locale/fr.json',
'resources/locale/it.json',
'resources/locale/nl.json',
'resources/locale/no.json',
'resources/locale/pt.json',
'resources/locale/ru.json',
'resources/locale/tr.json'
]
# Windows and Mac
if p == 'Windows' or p == 'Darwin':
from cx_Freeze import setup, Executable
html = [
'resources/html/index.html',
'resources/html/denied.html',
'resources/html/404.html'
]
if p == 'Windows':
executables = [
Executable('install/scripts/onionshare',
icon='install/onionshare.ico',
base=None),
Executable('install/scripts/onionshare-gui',
icon='install/onionshare.ico',
shortcutName='OnionShare',
shortcutDir='ProgramMenuFolder',
base='Win32GUI')
]
custom_info_plist = ''
setup(
name='onionshare',
version=version,
description=description,
long_description=long_description,
author='Micah Lee',
author_email='micah@micahflee.com',
url='https://github.com/micahflee/onionshare',
license="GPL v3",
keywords='onion, share, onionshare, tor, anonymous, web server',
packages=['onionshare', 'onionshare_gui'],
include_package_data=True,
scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'],
data_files=[
(os.path.join(sys.prefix, 'share/applications'), ['install/onionshare.desktop']),
(os.path.join(sys.prefix, 'share/appdata'), ['install/onionshare.appdata.xml']),
(os.path.join(sys.prefix, 'share/pixmaps'), ['install/onionshare80.xpm']),
(os.path.join(sys.prefix, 'share/onionshare'), [
'resources/version.txt',
'resources/wordlist.txt'
]),
(os.path.join(sys.prefix, 'share/onionshare/images'), images),
(os.path.join(sys.prefix, 'share/onionshare/locale'), locale),
(os.path.join(sys.prefix, 'share/onionshare/html'), html)
]
)
elif p == 'Darwin':
executables = [
Executable('install/scripts/onionshare-gui'),
Executable('install/scripts/onionshare')
]
# Write the correct version into Info.plist
f = tempfile.NamedTemporaryFile(mode='w')
custom_info_plist = f.name
f.write(open('install/Info.plist').read().replace('{VERSION}', str(version)))
f.flush()
setup(
name='OnionShare', version=version,
description=description, long_description=long_description,
author=author, author_email=author_email,
url=url, license=license, keywords=keywords,
options={
'build_exe': {
'packages': ['jinja2.ext'],
'excludes': [],
'include_files': ['resources']
},
'bdist_mac': {
'iconfile': 'install/onionshare.icns',
'bundle_name': 'OnionShare',
'qt_menu_nib': '/usr/local/Cellar/qt5/5.6.1-1/plugins/platforms',
'custom_info_plist': custom_info_plist
}
},
executables=executables
)
# Linux
else:
from setuptools import setup
setup(
name='onionshare', version=version,
description=description, long_description=long_description,
author=author, author_email=author_email,
url=url, license=license, keywords=keywords,
packages=['onionshare', 'onionshare_gui'],
include_package_data=True,
scripts=['install/scripts/onionshare', 'install/scripts/onionshare-gui'],
data_files=[
(os.path.join(sys.prefix, 'share/applications'), ['install/onionshare.desktop']),
(os.path.join(sys.prefix, 'share/appdata'), ['install/onionshare.appdata.xml']),
(os.path.join(sys.prefix, 'share/pixmaps'), ['install/onionshare80.xpm']),
(os.path.join(sys.prefix, 'share/onionshare'), [
'resources/version.txt',
'resources/wordlist.txt'
]),
(os.path.join(sys.prefix, 'share/onionshare/images'), [
'resources/images/logo.png',
'resources/images/drop_files.png',
'resources/images/server_stopped.png',
'resources/images/server_started.png',
'resources/images/server_working.png'
]),
(os.path.join(sys.prefix, 'share/onionshare/locale'), [
'resources/locale/cs.json',
'resources/locale/de.json',
'resources/locale/en.json',
'resources/locale/eo.json',
'resources/locale/es.json',
'resources/locale/fi.json',
'resources/locale/fr.json',
'resources/locale/it.json',
'resources/locale/nl.json',
'resources/locale/no.json',
'resources/locale/pt.json',
'resources/locale/ru.json',
'resources/locale/tr.json'
]),
(os.path.join(sys.prefix, 'share/onionshare/html'), [
'resources/html/index.html',
'resources/html/denied.html',
'resources/html/404.html'
]),
('/usr/share/nautilus-python/extensions/', ['install/scripts/onionshare-nautilus.py']),
]
)

View File

@ -1,6 +1,7 @@
[DEFAULT]
Package3: onionshare
Depends3: python3-flask, python3-stem, python3-pyqt5
Build-Depends3: python3-nose
Suite: trusty utopic vivid wily xenial jessie
Depends3: python3-flask, python3-stem, python3-pyqt5, python-nautilus
Build-Depends3: python3-nose, python3-flask, python3-stem, python3-pyqt5
Build-Depends: python3-nose, python3-flask, python3-stem, python3-pyqt5
Suite: wily
X-Python3-Version: >= 3.2

View File

@ -17,9 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
from onionshare import helpers
from nose import with_setup
import test_helpers
def test_get_platform_returns_platform_system():
"""get_platform() returns platform.system() when ONIONSHARE_PLATFORM is not defined"""

View File

@ -17,10 +17,15 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import locale
from onionshare import strings
from nose import with_setup
import locale, os
from onionshare import helpers, strings
# Stub get_resource_path so it finds the correct path while running tests
def get_resource_path(filename):
resources_dir = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources')
path = os.path.join(resources_dir, filename)
return path
helpers.get_resource_path = get_resource_path
def test_starts_with_empty_strings():
"""creates an empty strings dict by default"""
@ -30,12 +35,12 @@ def test_starts_with_empty_strings():
def test_load_strings_defaults_to_english():
"""load_strings() loads English by default"""
locale.getdefaultlocale = lambda: ('en_US', 'UTF-8')
strings.load_strings()
strings.load_strings(helpers)
assert strings._('wait_for_hs') == "Waiting for HS to be ready:"
def test_load_strings_loads_other_languages():
"""load_strings() loads other languages in different locales"""
locale.getdefaultlocale = lambda: ('fr_FR', 'UTF-8')
strings.load_strings("fr")
strings.load_strings(helpers, "fr")
assert strings._('wait_for_hs') == "En attente du HS:"

View File

@ -18,7 +18,6 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import socket
from onionshare import OnionShare
from nose import with_setup
def test_choose_port_returns_a_port_number():

View File

@ -17,6 +17,7 @@ You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""
import tempfile
import os
class MockSubprocess():
@ -31,9 +32,7 @@ class MockSubprocess():
def write_tempfile(text):
tempdir = tempfile.mkdtemp()
path = tempdir + "/test-file.txt"
path = os.path.join(tempfile.mkdtemp(), "/test-file.txt")
with open(path, "w") as f:
f.write(text)
f.close()
return path