[Pkg-privacy-commits] [onionshare] 22/66: Porting onionshare from python2 to python3 (#261). This commit only ports the CLI version, not the GUI. Has not been tested in Fedora, Windows, or OSX. Removed hack to make unicode filenames work because hack does not work in python3. Replaced constant_time_compare function with a new one that works in python3. Tweaked hidden service checking code because urllib is different in python3.

Ulrike Uhlig u-guest at moszumanska.debian.org
Wed Apr 13 22:17:48 UTC 2016


This is an automated email from the git hooks/post-receive script.

u-guest pushed a commit to branch master
in repository onionshare.

commit 170811f450b801c03111b1a6ae59ed9808d1bead
Author: Micah Lee <micah at micahflee.com>
Date:   Fri Feb 12 14:34:19 2016 -0800

    Porting onionshare from python2 to python3 (#261). This commit only ports the CLI version, not the GUI. Has not been tested in Fedora, Windows, or OSX. Removed hack to make unicode filenames work because hack does not work in python3. Replaced constant_time_compare function with a new one that works in python3. Tweaked hidden service checking code because urllib is different in python3.
---
 BUILD.md                             |  4 ++--
 install/build_deb.sh                 |  2 +-
 install/linux_scripts/onionshare     |  2 +-
 install/linux_scripts/onionshare-gui |  2 +-
 onionshare/__init__.py               |  2 +-
 onionshare/helpers.py                | 38 ++++++++++++++----------------------
 onionshare/hs.py                     | 33 +++++++++++++++++--------------
 onionshare/onionshare.py             | 21 ++++++++++----------
 onionshare/strings.py                |  8 +++-----
 onionshare/web.py                    | 16 ++++++++-------
 setup.py                             |  8 +++++---
 stdeb.cfg                            |  6 +++---
 12 files changed, 70 insertions(+), 72 deletions(-)

diff --git a/BUILD.md b/BUILD.md
index 1c02c87..4604a6e 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -11,10 +11,10 @@ cd onionshare
 
 *For .deb-based distros (like Debian, Ubuntu, Linux Mint):*
 
-Note that python-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.
+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.
 
 ```sh
-sudo apt-get install -y build-essential fakeroot python-all python-stdeb python-flask python-stem python-qt4 dh-python
+sudo apt-get install -y build-essential fakeroot python3-all python3-stdeb python3-flask python3-stem python3-pyqt5 dh-python
 ./install/build_deb.sh
 sudo dpkg -i deb_dist/onionshare_*.deb
 ```
diff --git a/install/build_deb.sh b/install/build_deb.sh
index dc2fbaa..cd4ec42 100755
--- a/install/build_deb.sh
+++ b/install/build_deb.sh
@@ -9,7 +9,7 @@ VERSION=`cat version`
 rm -r deb_dist >/dev/null 2>&1
 
 # build binary package
-python setup.py --command-packages=stdeb.command bdist_deb
+python3 setup.py --command-packages=stdeb.command bdist_deb
 
 # return install instructions if onionshare builds properly
 echo ""
diff --git a/install/linux_scripts/onionshare b/install/linux_scripts/onionshare
index c563b1c..a8a7445 100755
--- a/install/linux_scripts/onionshare
+++ b/install/linux_scripts/onionshare
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
 OnionShare | https://onionshare.org/
diff --git a/install/linux_scripts/onionshare-gui b/install/linux_scripts/onionshare-gui
index b8d7819..8a72bf4 100755
--- a/install/linux_scripts/onionshare-gui
+++ b/install/linux_scripts/onionshare-gui
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
 OnionShare | https://onionshare.org/
diff --git a/onionshare/__init__.py b/onionshare/__init__.py
index 6535d58..f9c1daa 100644
--- a/onionshare/__init__.py
+++ b/onionshare/__init__.py
@@ -17,4 +17,4 @@ 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/>.
 """
-from onionshare import *
+from .onionshare import *
diff --git a/onionshare/helpers.py b/onionshare/helpers.py
index 43dd781..58c9a8d 100644
--- a/onionshare/helpers.py
+++ b/onionshare/helpers.py
@@ -17,15 +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 os, inspect, hashlib, base64, hmac, platform, zipfile, tempfile
-from itertools import izip
-import math
-import time
-
-# hack to make unicode filenames work (#141)
-import sys
-reload(sys)
-sys.setdefaultencoding("utf-8")
+import sys, os, inspect, hashlib, base64, hmac, platform, zipfile, tempfile, math, time
 
 
 def get_platform():
@@ -82,20 +74,20 @@ def get_version():
 
 def constant_time_compare(val1, val2):
     """
-    Compares two values in constant time.
-    """
-    _builtin_constant_time_compare = getattr(hmac, 'compare_digest', None)
-    if _builtin_constant_time_compare is not None:
-        return _builtin_constant_time_compare(val1, val2)
+    Returns True if the two strings are equal, False otherwise.
 
-    len_eq = len(val1) == len(val2)
-    if len_eq:
-        result = 0
-        left = val1
-    else:
-        result = 1
-        left = val2
-    for x, y in izip(bytearray(left), bytearray(val2)):
+    The time taken is independent of the number of characters that match.
+
+    For the sake of simplicity, this function executes in constant time only
+    when the two strings have the same length. It short-circuits when they
+    have different lengths.
+
+    From: http://www.levigross.com/2014/02/07/constant-time-comparison-functions-in...-python-haskell-clojure-and-java/
+    """
+    if len(val1) != len(val2):
+        return False
+    result = 0
+    for x, y in zip(val1, val2):
         result |= x ^ y
     return result == 0
 
@@ -106,7 +98,7 @@ def random_string(num_bytes, output_len=None):
     """
     b = os.urandom(num_bytes)
     h = hashlib.sha256(b).digest()[:16]
-    s = base64.b32encode(h).lower().replace('=', '')
+    s = base64.b32encode(h).lower().replace(b'=', b'').decode('utf-8')
     if not output_len:
         return s
     return s[:output_len]
diff --git a/onionshare/hs.py b/onionshare/hs.py
index c770ddf..dc9355f 100644
--- a/onionshare/hs.py
+++ b/onionshare/hs.py
@@ -19,10 +19,11 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
 from stem.control import Controller
-import os, sys, tempfile, shutil, urllib2, httplib
-import socks
+from stem import SocketError
+import os, sys, tempfile, shutil, urllib
 
-import helpers, strings
+from . import socks
+from . import helpers, strings
 
 class NoTor(Exception):
     """
@@ -62,17 +63,19 @@ class HS(object):
         self.service_id = None
 
         # connect to the tor controlport
+        found_tor = False
         self.c = None
         ports = [9151, 9153, 9051]
         for port in ports:
             try:
                 self.c = Controller.from_port(port=port)
                 self.c.authenticate()
+                found_tor = True
                 break
-            except:
+            except SocketError:
                 pass
-        if not self.c:
-            raise NoTor(strings._("cant_connect_ctrlport").format(ports))
+        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?
         tor_version = self.c.get_version().version_str
@@ -84,9 +87,9 @@ class HS(object):
         Start a hidden service on port 80, pointing to the given port, and
         return the onion hostname.
         """
-        print strings._("connecting_ctrlport").format(int(port))
+        print(strings._("connecting_ctrlport").format(int(port)))
         if self.supports_ephemeral:
-            print strings._('using_ephemeral')
+            print(strings._('using_ephemeral'))
             res = self.c.create_ephemeral_hidden_service({ 80: port }, await_publication = False)
             self.service_id = res.content()[0][2].split('=')[1]
             onion_host = res.content()[0][2].split('=')[1] + '.onion'
@@ -102,7 +105,7 @@ class HS(object):
                 path = '/tmp/onionshare'
                 try:
                     if not os.path.exists(path):
-                        os.makedirs(path, 0700)
+                        os.makedirs(path, 0o700)
                 except:
                     raise HSDirError(strings._("error_hs_dir_cannot_create").format(path))
                 if not os.access(path, os.W_OK):
@@ -139,7 +142,7 @@ class HS(object):
         successfully connects..
         """
         # legacy only, this function is no longer required with ephemeral hidden services
-        print strings._('wait_for_hs')
+        print(strings._('wait_for_hs'))
 
         ready = False
         while not ready:
@@ -149,7 +152,7 @@ class HS(object):
 
                 if self.transparent_torification:
                     # no need to set the socks5 proxy
-                    urllib2.urlopen('http://{0:s}'.format(onion_host))
+                    urllib.request.urlopen('http://{0:s}'.format(onion_host))
                 else:
                     tor_exists = False
                     ports = [9150, 9152, 9050]
@@ -164,17 +167,17 @@ class HS(object):
                         except socks.ProxyConnectionError:
                             pass
                     if not tor_exists:
-                        raise NoTor(strings._("cant_connect_socksport").format(tor_socks_ports))
+                        raise NoTor(strings._("cant_connect_socksport").format(str(ports)))
                 ready = True
 
                 sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_yup')))
-            except socks.SOCKS5Error:
+            except socks.GeneralProxyError:
                 sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
                 sys.stdout.flush()
-            except urllib2.HTTPError:  # torification error
+            except socks.SOCKS5Error:
                 sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
                 sys.stdout.flush()
-            except httplib.BadStatusLine: # torification (with bridge) error
+            except urllib.error.HTTPError:  # torification error
                 sys.stdout.write('{0:s}\n'.format(strings._('wait_for_hs_nope')))
                 sys.stdout.flush()
             except KeyboardInterrupt:
diff --git a/onionshare/onionshare.py b/onionshare/onionshare.py
index e10fe65..bfd3686 100644
--- a/onionshare/onionshare.py
+++ b/onionshare/onionshare.py
@@ -19,7 +19,8 @@ along with this program.  If not, see <http://www.gnu.org/licenses/>.
 """
 
 import os, sys, subprocess, time, argparse, inspect, shutil, socket, threading
-import strings, helpers, web, hs
+
+from . import strings, helpers, web, hs
 
 class OnionShare(object):
     """
@@ -97,7 +98,7 @@ def main(cwd=None):
     onionshare uses.
     """
     strings.load_strings()
-    print strings._('version_string').format(helpers.get_version())
+    print(strings._('version_string').format(helpers.get_version()))
 
     # onionshare CLI in OSX needs to change current working directory (#132)
     if helpers.get_platform() == 'Darwin':
@@ -142,15 +143,15 @@ def main(cwd=None):
         sys.exit(e.args[0])
 
     # prepare files to share
-    print strings._("preparing_files")
+    print(strings._("preparing_files"))
     web.set_file_info(filenames)
     app.cleanup_filenames.append(web.zip_filename)
 
     # warn about sending large files over Tor
     if web.zip_filesize >= 157286400:  # 150mb
-        print ''
-        print strings._("large_filesize")
-        print ''
+        print('')
+        print(strings._("large_filesize"))
+        print('')
 
     # start onionshare service in new thread
     t = threading.Thread(target=web.start, args=(app.port, app.stay_open, app.transparent_torification))
@@ -164,10 +165,10 @@ def main(cwd=None):
             if not ready:
                 sys.exit()
 
-        print strings._("give_this_url")
-        print 'http://{0:s}/{1:s}'.format(app.onion_host, web.slug)
-        print ''
-        print strings._("ctrlc_to_stop")
+        print(strings._("give_this_url"))
+        print('http://{0:s}/{1:s}'.format(app.onion_host, web.slug))
+        print('')
+        print(strings._("ctrlc_to_stop"))
 
         # wait for app to close
         while t.is_alive():
diff --git a/onionshare/strings.py b/onionshare/strings.py
index 29eab58..c211668 100644
--- a/onionshare/strings.py
+++ b/onionshare/strings.py
@@ -18,7 +18,8 @@ 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
-import helpers
+
+from . import helpers
 
 strings = {}
 
@@ -62,9 +63,6 @@ def translated(k, gui=False):
     """
     Returns a translated string.
     """
-    if gui:
-        return strings[k].encode("utf-8").decode('utf-8', 'replace')
-    else:
-        return strings[k].encode("utf-8")
+    return strings[k]
 
 _ = translated
diff --git a/onionshare/web.py b/onionshare/web.py
index 800e2be..ed9bb78 100644
--- a/onionshare/web.py
+++ b/onionshare/web.py
@@ -17,10 +17,12 @@ 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 Queue, mimetypes, platform, os, sys, urllib2
+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
-import strings, helpers
+
+from . import strings, helpers
 
 app = Flask(__name__)
 
@@ -72,7 +74,7 @@ REQUEST_DOWNLOAD = 1
 REQUEST_PROGRESS = 2
 REQUEST_OTHER = 3
 REQUEST_CANCELED = 4
-q = Queue.Queue()
+q = queue.Queue()
 
 
 def add_request(request_type, path, data=None):
@@ -154,7 +156,7 @@ def index(slug_candidate):
         open(helpers.get_html_path('index.html')).read(),
         slug=slug,
         file_info=file_info,
-        filename=os.path.basename(zip_filename).decode("utf-8"),
+        filename=os.path.basename(zip_filename),
         filesize=zip_filesize,
         filesize_human=helpers.human_readable_filesize(zip_filesize)
     )
@@ -192,7 +194,7 @@ def download(slug_candidate):
         canceled = False
         while not done:
             chunk = fp.read(chunk_size)
-            if chunk == '':
+            if chunk == b'':
                 done = True
             else:
                 try:
@@ -224,7 +226,7 @@ def download(slug_candidate):
 
         # download is finished, close the server
         if not stay_open and not canceled:
-            print strings._("closing_automatically")
+            print(strings._("closing_automatically"))
             if shutdown_func is None:
                 raise RuntimeError('Not running with the Werkzeug Server')
             shutdown_func()
@@ -292,6 +294,6 @@ def stop(port):
             s.connect(('127.0.0.1', port))
             s.sendall('GET /{0:s}/shutdown HTTP/1.1\r\n\r\n'.format(shutdown_slug))
         else:
-            urllib2.urlopen('http://127.0.0.1:{0:d}/{1:s}/shutdown'.format(port, shutdown_slug)).read()
+            urlopen('http://127.0.0.1:{0:d}/{1:s}/shutdown'.format(port, shutdown_slug)).read()
     except:
         pass
diff --git a/setup.py b/setup.py
index 21ef090..ecc1f1a 100644
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # -*- coding: utf-8 -*-
 """
 OnionShare | https://onionshare.org/
@@ -83,9 +83,11 @@ if system == 'Linux':
         url='https://github.com/micahflee/onionshare',
         license="GPL v3",
         keywords='onion, share, onionshare, tor, anonymous, web server',
-        packages=['onionshare', 'onionshare_gui'],
+        #packages=['onionshare', 'onionshare_gui'],
+        packages=['onionshare'],
         include_package_data=True,
-        scripts=['install/linux_scripts/onionshare', 'install/linux_scripts/onionshare-gui'],
+        #scripts=['install/linux_scripts/onionshare', 'install/linux_scripts/onionshare-gui'],
+        scripts=['install/linux_scripts/onionshare'],
         data_files=[
             (os.path.join(sys.prefix, 'share/applications'), ['install/onionshare.desktop']),
             (os.path.join(sys.prefix, 'share/appdata'), ['install/onionshare.appdata.xml']),
diff --git a/stdeb.cfg b/stdeb.cfg
index 7028f47..5645322 100644
--- a/stdeb.cfg
+++ b/stdeb.cfg
@@ -1,5 +1,5 @@
 [DEFAULT]
-Package: onionshare
-Depends: python-flask, python-stem, python-qt4
-Build-Depends: dh-python
+Package3: onionshare
+Depends3: python3-flask, python3-stem, python3-pyqt5
+Build-Depends3: python3-stdeb, python3-nose
 Suite: trusty

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-privacy/packages/onionshare.git



More information about the Pkg-privacy-commits mailing list