https://fedorahosted.org/freeipa/ticket/5700

--
Martin^3 Babinsky
From 24dfd3148d2a9a8118b9d87d61c179578668666d Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Tue, 8 Mar 2016 15:56:52 +0100
Subject: [PATCH] otptoken-add: improve the robustness of QR code printing to
 tty

The python-qrcode print_ascii() method does not work in terminals with
non-UTF-8 encoding. Use print_tty() method in this case. Also check whether we
actually support correct QR code rendering in the client terminal before
forwarding the request to server.

https://fedorahosted.org/freeipa/ticket/5700
---
 ipalib/plugins/otptoken.py | 50 +++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 43 insertions(+), 7 deletions(-)

diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
index 846155dfb3af53ad65f3a4f488629837d10a2bce..f11bcc7957e638145fd4456c4ebe59b1e2411a7f 100644
--- a/ipalib/plugins/otptoken.py
+++ b/ipalib/plugins/otptoken.py
@@ -18,12 +18,18 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import print_function
+import sys
 
 from ipalib.plugins.baseldap import DN, LDAPObject, LDAPAddMember, LDAPRemoveMember
 from ipalib.plugins.baseldap import LDAPCreate, LDAPDelete, LDAPUpdate, LDAPSearch, LDAPRetrieve
 from ipalib import api, Int, Str, Bool, DateTime, Flag, Bytes, IntEnum, StrEnum, Password, _, ngettext
 from ipalib.plugable import Registry
-from ipalib.errors import PasswordMismatch, ConversionError, LastMemberError, NotFound, ValidationError
+from ipalib.errors import (
+    PasswordMismatch,
+    ConversionError,
+    ExecutionError,
+    NotFound,
+    ValidationError)
 from ipalib.request import context
 from ipalib.frontend import Local
 from ipaplatform.paths import paths
@@ -282,6 +288,41 @@ class otptoken_add(LDAPCreate):
         Str('uri?', label=_('URI')),
     )
 
+    def _check_qrcode_capability(self, **options):
+        if self.api.env.context != u'cli' or options.get('no_qrcode', False):
+            return
+
+        min_tty_width = 80
+        is_term_wide_enough = (
+            self.api.Backend.textui.get_tty_width() >= min_tty_width
+        )
+        term_encoding = getattr(sys.stdout, 'encoding', 'UTF-8')
+
+        if term_encoding != 'UTF-8' and not is_term_wide_enough:
+            raise ExecutionError(
+                message=u"Cannot print QR code: needs UTF-8 encoding or at "
+                        "least {} character terminal width".format(
+                            min_tty_width)
+            )
+
+    def _print_qrcode(self, textui, uri):
+        print("\n")
+        qr = qrcode.QRCode()
+        qr.add_data(uri)
+        qr.make()
+
+        term_encoding = getattr(sys.stdout, 'encoding', 'UTF-8')
+
+        if term_encoding != 'UTF-8':
+            qr.print_tty()
+        else:
+            qr.print_ascii(tty=True)
+        print("\n")
+
+    def forward(self, *args, **options):
+        self._check_qrcode_capability(**options)
+        return super(otptoken_add, self).forward(*args, **options)
+
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         # Fill in a default UUID when not specified.
         if entry_attrs.get('ipatokenuniqueid', None) is None:
@@ -356,12 +397,7 @@ class otptoken_add(LDAPCreate):
 
         # Print QR code to terminal if specified
         if uri and not options.get('no_qrcode', False):
-            print("\n")
-            qr = qrcode.QRCode()
-            qr.add_data(uri)
-            qr.make()
-            qr.print_ascii(tty=True)
-            print("\n")
+            self._print_qrcode(textui, uri)
 
         return rv
 
-- 
2.5.0

From 41a0dfba60f9268c169062fe606027077475cd3c Mon Sep 17 00:00:00 2001
From: Martin Babinsky <mbabi...@redhat.com>
Date: Tue, 8 Mar 2016 15:56:52 +0100
Subject: [PATCH] otptoken-add: improve the robustness of QR code printing to
 tty

The python-qrcode print_ascii() method does not work in terminals with
non-UTF-8 encoding. Use print_tty() method in this case. Also check whether we
actually support correct QR code rendering in the client terminal before
forwarding the request to server.

https://fedorahosted.org/freeipa/ticket/5700
---
 ipalib/plugins/otptoken.py | 44 ++++++++++++++++++++++++++++++++++++++------
 1 file changed, 38 insertions(+), 6 deletions(-)

diff --git a/ipalib/plugins/otptoken.py b/ipalib/plugins/otptoken.py
index 2d7e99d06f4f64319bbd2f8f13a60e5391a57d77..f11bcc7957e638145fd4456c4ebe59b1e2411a7f 100644
--- a/ipalib/plugins/otptoken.py
+++ b/ipalib/plugins/otptoken.py
@@ -18,6 +18,7 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
 from __future__ import print_function
+import sys
 
 from ipalib.plugins.baseldap import DN, LDAPObject, LDAPAddMember, LDAPRemoveMember
 from ipalib.plugins.baseldap import LDAPCreate, LDAPDelete, LDAPUpdate, LDAPSearch, LDAPRetrieve
@@ -26,6 +27,7 @@ from ipalib.plugable import Registry
 from ipalib.errors import (
     PasswordMismatch,
     ConversionError,
+    ExecutionError,
     NotFound,
     ValidationError)
 from ipalib.request import context
@@ -286,6 +288,41 @@ class otptoken_add(LDAPCreate):
         Str('uri?', label=_('URI')),
     )
 
+    def _check_qrcode_capability(self, **options):
+        if self.api.env.context != u'cli' or options.get('no_qrcode', False):
+            return
+
+        min_tty_width = 80
+        is_term_wide_enough = (
+            self.api.Backend.textui.get_tty_width() >= min_tty_width
+        )
+        term_encoding = getattr(sys.stdout, 'encoding', 'UTF-8')
+
+        if term_encoding != 'UTF-8' and not is_term_wide_enough:
+            raise ExecutionError(
+                message=u"Cannot print QR code: needs UTF-8 encoding or at "
+                        "least {} character terminal width".format(
+                            min_tty_width)
+            )
+
+    def _print_qrcode(self, textui, uri):
+        print("\n")
+        qr = qrcode.QRCode()
+        qr.add_data(uri)
+        qr.make()
+
+        term_encoding = getattr(sys.stdout, 'encoding', 'UTF-8')
+
+        if term_encoding != 'UTF-8':
+            qr.print_tty()
+        else:
+            qr.print_ascii(tty=True)
+        print("\n")
+
+    def forward(self, *args, **options):
+        self._check_qrcode_capability(**options)
+        return super(otptoken_add, self).forward(*args, **options)
+
     def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
         # Fill in a default UUID when not specified.
         if entry_attrs.get('ipatokenuniqueid', None) is None:
@@ -360,12 +397,7 @@ class otptoken_add(LDAPCreate):
 
         # Print QR code to terminal if specified
         if uri and not options.get('no_qrcode', False):
-            print("\n")
-            qr = qrcode.QRCode()
-            qr.add_data(uri)
-            qr.make()
-            qr.print_ascii(tty=True)
-            print("\n")
+            self._print_qrcode(textui, uri)
 
         return rv
 
-- 
2.5.0

-- 
Manage your subscription for the Freeipa-devel mailing list:
https://www.redhat.com/mailman/listinfo/freeipa-devel
Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code

Reply via email to