Unverified Commit 0ade64bf authored by Isis Lovecruft's avatar Isis Lovecruft
Browse files

Merge branch 'fix/11345-qrcodes_r2' into develop

parents f1bdddb8 66ef631c
......@@ -49,6 +49,7 @@ from bridgedb.Filters import filterBridgesByIP6
from bridgedb.Filters import filterBridgesByTransport
from bridgedb.Filters import filterBridgesByNotBlockedIn
from bridgedb.parse import headers
from bridgedb.qrcodes import generateQR
from bridgedb.safelog import logSafely
......@@ -785,6 +786,11 @@ class WebResourceBridges(resource.Resource):
rendered = bridgeLines
else:
request.setHeader("Content-Type", "text/html; charset=utf-8")
qrcode = None
qrjpeg = generateQR(bridgeLines)
if qrjpeg:
qrcode = 'data:image/jpeg;base64,%s' % base64.b64encode(qrjpeg)
try:
langs = translations.getLocaleFromHTTPRequest(request)
rtl = translations.usingRTLLang(langs)
......@@ -792,7 +798,8 @@ class WebResourceBridges(resource.Resource):
rendered = template.render(strings,
rtl=rtl,
lang=langs[0],
answer=bridgeLines)
answer=bridgeLines,
qrcode=qrcode)
except Exception as err:
rendered = replaceErrorPage(err)
......
# -*- coding: utf-8 ; test-case-name: bridgedb.test.test_qrcodes ; -*-
#_____________________________________________________________________________
#
# This file is part of BridgeDB, a Tor bridge distribution system.
#
# :authors: Isis Lovecruft 0xA3ADB67A2CDB8B35 <isis@torproject.org>
# please also see AUTHORS file
# :copyright: (c) 2007-2015, The Tor Project, Inc.
# (c) 2014-2015, Isis Lovecruft
# :license: see LICENSE for licensing information
#_____________________________________________________________________________
"""Utilities for working with QRCodes."""
import cStringIO
import logging
try:
import qrcode
except ImportError:
qrcode = False
logging.warn("Could not import Python qrcode module.")
logging.debug(("You'll need the qrcode Python module for this to "
"work. On Debian-based systems, this should be in the "
"python-qrcode package."))
def generateQR(bridgelines, imageFormat=u'JPEG', bridgeSchema=False):
"""Generate a QRCode for the client's bridge lines.
:param str bridgelines: The Bridge Lines which we are distributing to the
client.
:param bool bridgeSchema: If ``True``, prepend ``'bridge://'`` to the
beginning of each bridge line before QR encoding.
:rtype: str or ``None``
:returns: The generated QRCode, as a string.
"""
logging.debug("Attempting to encode bridge lines into a QRCode...")
if not bridgelines:
return
if not qrcode:
logging.info("Not creating QRCode for bridgelines; no qrcode module.")
try:
if bridgeSchema:
# See https://bugs.torproject.org/12639 for why bridge:// is used.
# (Hopefully, Orbot will pick up the ACTION_VIEW intent.)
schema = 'bridge://'
prefixed = []
for line in bridgelines.strip().split('\n'):
prefixed.append(schema + line)
bridgelines = '\n'.join(prefixed)
logging.debug("QR encoding bridge lines: %s" % bridgelines)
qr = qrcode.QRCode()
qr.add_data(bridgelines)
buf = cStringIO.StringIO()
img = qr.make_image().resize([350, 350])
img.save(buf, imageFormat)
buf.seek(0)
imgstr = buf.read()
return imgstr
except KeyError as error:
logging.error(str(error))
logging.debug(("It seems python-imaging doesn't understand how to "
"save in the %s format.") % imgFormat)
except Exception as error:
logging.error(("There was an error while attempting to generate the "
"QRCode: %s") % str(error))
## -*- coding: utf-8 -*-
<%inherit file="base.html"/>
<%page args="strings, rtl=False, lang='en', answer=0, **kwargs"/>
<%page args="strings, rtl=False, lang='en', answer=0, qrcode=0, **kwargs"/>
</div>
</div>
......@@ -31,6 +31,20 @@
window.alert(e);
}
}
function displayOrHide(element) {
try {
e = document.getElementById(element);
if (e.style.display === 'none') {
document.getElementById(element).style.display = 'block';
} else if (e.style.display === 'block') {
document.getElementById(element).style.display = 'none';
}
} catch (e) {
window.alert(e);
}
}
</script>
<div class="container-narrow">
......@@ -66,6 +80,50 @@ ${answer.replace("\n", "<br />")}
title="Select all bridge lines">
<i class="icon icon-2x icon-paste"></i> &nbsp; ${_("""Select All""")}
</button>
% if qrcode:
<a class="btn btn-primary" type="button" id="qrcodebtn"
href="${qrcode}" title="Show QRCode for bridge lines"
onclick="displayOrHide('qrcode')">
<i class="icon icon-2x icon-qrcode"></i> &nbsp; ${_("""Show QRCode""")}
</a>
% endif
</div>
<div class="modal" id="qrcode" style="display: none;">
<div class="modal-dialog modal-sm" style="width: 400px;">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" aria-hidden="true"
onclick="displayOrHide('qrcode')">
&times;
</button>
<h4 class="modal-title">${_("""QRCode for your bridge lines""")}</h4>
</div>
<div class="modal-body">
% if qrcode:
<p style="text-align: center;">
<img width="350" height="350"
title="QRCode for your bridge lines from BridgeDB"
src="${qrcode}" />
</p>
% else:
<p class="text-danger">
## TRANSLATORS: Please translate this into some silly way to say
## "There was a problem!" in your language. For example,
## for Italian, you might translate this into "Mama mia!",
## or for French: "Sacrebleu!". :)
${_("""Uh oh, spaghettios!""")}
${_("""It seems there was an error getting your QRCode.""")}
<i class="icon icon-frown"></i>
</p>
% endif
<p>
${_("""This QRCode contains your bridge lines. Scan it with a QRCode """ \
"""reader to copy your bridge lines onto mobile and other devices.""")}
</p>
</div>
</div>
</div>
</div>
</div>
......@@ -133,6 +191,10 @@ ${_("""Uh oh, spaghettios!""")}
<script type="text/javascript">
// Make the 'Select All' button clickable:
document.getElementById('selectbtn').className = "btn btn-primary";
// Remove the href attribute which opens the QRCode image as a data URL if
// JS is disabled:
document.getElementById('qrcodebtn').removeAttribute('href');
</script>
<hr />
......@@ -7,5 +7,7 @@ pycrypto==2.6.1
pyOpenSSL==0.14
pygeoip==0.2.7
pygpgme==0.3
pillow>=2.6.1
qrcode==5.0.1
recaptcha-client==1.0.6
zope.interface==3.6.1
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment