[weboob] [PATCH 3/4] BNPorc: switch to the new virtual keyboard tool

Pierre Mazière pierre.maziere at gmail.com
Sun Oct 30 01:30:49 CEST 2011


Signed-off-by: Pierre Mazière <pierre.maziere at gmail.com>
---
 weboob/backends/bnporc/captcha.py     |  121 ---------------------------------
 weboob/backends/bnporc/pages/login.py |  104 +++++++++++++++++++++++-----
 2 files changed, 87 insertions(+), 138 deletions(-)
 delete mode 100644 weboob/backends/bnporc/captcha.py

diff --git a/weboob/backends/bnporc/captcha.py b/weboob/backends/bnporc/captcha.py
deleted file mode 100644
index eaa4543..0000000
--- a/weboob/backends/bnporc/captcha.py
+++ /dev/null
@@ -1,121 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# Copyright(C) 2009-2011  Romain Bignon
-#
-# This file is part of weboob.
-#
-# weboob is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# weboob is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public License
-# along with weboob. If not, see <http://www.gnu.org/licenses/>.
-
-
-import hashlib
-import sys
-import Image
-
-class TileError(Exception):
-    def __init__(self, msg, tile = None):
-        Exception.__init__(self, msg)
-        self.tile = tile
-
-
-class Captcha(object):
-    def __init__(self, file):
-        self.inim = Image.open(file)
-        self.nx,self.ny = self.inim.size
-        self.inmat = self.inim.load()
-        self.map = {}
-
-        self.tiles = [[Tile(x+5*y+1) for y in xrange(5)] for x in xrange(5)]
-
-    def __getitem__(self, (x, y)):
-        return self.inmat[x % self.nx, y % self.ny]
-
-    def all_coords(self):
-        for y in xrange(self.ny):
-            for x in xrange(self.nx):
-                yield x, y
-
-    def get_codes(self, code):
-        s = ''
-        for c in code:
-            s += '%02d' % self.map[int(c)].id
-        return s
-
-    def build_tiles(self):
-        y = 1
-        ty = 0
-        while y < self.ny:
-            x = 1
-            tx = 0
-            while x < self.nx:
-                tile = self.tiles[tx][ty]
-                for j in xrange(26):
-                    l = []
-                    tile.map.append(l)
-                    for i in xrange(26):
-                        if self[x+i,y+j] > 20:
-                            l.append('.')
-                            tile.valid = True
-                        else:
-                            l.append(' ')
-
-                if tile.valid:
-                    self.map[tile.get_num()] = tile
-
-                x += 27
-                tx += 1
-
-            y += 27
-            ty += 1
-
-class Tile(object):
-    hash = {'4a6eff78f6c6f172b75bf9fd7fd36d5d': 0,
-            '70019df58ec6e96d983507de86529058': 1,
-            '683a3700dbd1b9019b5ad3ca39c545d3': 2,
-            '998935d6f4111bd586001468a9c705a7': 3,
-            'a5cca8bf800fa505cf7ae5039b0cc73c': 4,
-            '2317a585e19c4f245cdc8acda51e4542': 5,
-            '956958628d014f6e6bf59d88cd254dc6': 6,
-            '13c35a4e7bf18e95186311876e66dd95': 7,
-            '736894876d76899a5cfecc745b095121': 8,
-            'ff41cd68224bece411c7fc876ab05a1d': 9
-           }
-
-    def __init__(self, _id):
-        self.id = _id
-        self.valid = False
-        self.map = []
-
-    def __repr__(self):
-        return "<Tile(%02d) valid=%s>" % (self.id, self.valid)
-
-    def checksum(self):
-        s = ''
-        for pxls in self.map:
-            for pxl in pxls:
-                s += pxl
-        return hashlib.md5(s).hexdigest()
-
-    def get_num(self):
-        sum = self.checksum()
-        try:
-            return self.hash[sum]
-        except KeyError:
-            raise TileError('Tile not found', self)
-
-    def display(self):
-        for pxls in self.map:
-            for pxl in pxls:
-                sys.stdout.write(pxl)
-            sys.stdout.write('\n')
-        print self.checksum()
diff --git a/weboob/backends/bnporc/pages/login.py b/weboob/backends/bnporc/pages/login.py
index 66332b5..adbdf8a 100644
--- a/weboob/backends/bnporc/pages/login.py
+++ b/weboob/backends/bnporc/pages/login.py
@@ -1,6 +1,6 @@
 # -*- coding: utf-8 -*-
 
-# Copyright(C) 2009-2011  Romain Bignon
+# Copyright(C) 2009-2011  Romain Bignon, Pierre Mazière
 #
 # This file is part of weboob.
 #
@@ -23,8 +23,8 @@ import urllib
 from logging import error
 
 from weboob.tools.browser import BasePage, BrowserUnavailable
-from weboob.backends.bnporc.captcha import Captcha, TileError
-
+from weboob.tools.virtkeyboard import VirtKeyboard,VirtKeyboardError
+import tempfile
 
 __all__ = ['LoginPage', 'ConfirmPage', 'ChangePasswordPage']
 
@@ -39,14 +39,45 @@ class LoginPage(BasePage):
                 raise BrowserUnavailable(msg)
 
     def login(self, login, password):
-        img = Captcha(self.browser.openurl('/NSImgGrille'))
+        symbols={'0':'9cc4789a2cb223e8f2d5e676e90264b5',
+                 '1':'e10b58fc085f9683052d5a63c96fc912',
+                 '2':'04ec647e7b3414bcc069f0c54eb55a4c',
+                 '3':'fde84fd9bac725db8463554448f1e469',
+                 '4':'2359eea8671bf112b58264bec0294f71',
+                 '5':'82b55b63480114f04fad8c5c4fa5673a',
+                 '6':'e074864faeaeabb3be3d118192cd8879',
+                 '7':'753468d88d4810206a6f0ab9c6ef1b16',
+                 '8':'9cc4789a2cb223e8f2d5e676e90264b5',
+                 '9':'828cf0faf86ac78e7f43208907620527'
+                }
+
+        map=self.document.find("//map[@name='MapGril']")
+
+        coords={}
+        for area in map.getiterator("area"):
+            code=area.attrib.get("onclick")[-4:-2]
+            area_coords=[]
+            for coord in area.attrib.get("coords").split(","):
+                area_coords.append(int(coord))
+            coords[code]=tuple(area_coords)
 
         try:
-            img.build_tiles()
-        except TileError, err:
+            vk=VirtKeyboard(self.browser.openurl("/NSImgGrille"),coords,27)
+        except VirtKeyboardError,err:
             error("Error: %s" % err)
-            if err.tile:
-                err.tile.display()
+            return False
+
+        for s in symbols.keys():
+            try:
+                vk.get_symbol_code(symbols[s])
+            except VirtKeyboardError:
+                if self.browser.responses_dirname is None:
+                    self.browser.responses_dirname = \
+                            tempfile.mkdtemp(prefix='weboob_session_')
+                vk.generate_MD5(self.browser.responses_dirname)
+                error("Error: Symbol '%s' not found; all symbol hashes are available in %s" \
+                      % (s,self.browser.responses_dirname))
+                return False
 
         self.browser.select_form('logincanalnet')
         # HACK because of fucking malformed HTML, the field isn't recognized by mechanize.
@@ -54,7 +85,10 @@ class LoginPage(BasePage):
         self.browser.set_all_readonly(False)
 
         self.browser['ch1'] = login
-        self.browser['ch5'] = img.get_codes(password)
+        passwd=''
+        for c in password:
+            passwd+=vk.get_symbol_code(symbols[c])
+        self.browser['ch5'] = passwd
         self.browser.submit()
 
 
@@ -64,17 +98,53 @@ class ConfirmPage(BasePage):
 
 class ChangePasswordPage(BasePage):
     def change_password(self, current, new):
-        img = Captcha(self.browser.openurl('/NSImgGrille'))
+        symbols={'0':'9cc4789a2cb223e8f2d5e676e90264b5',
+                 '1':'e10b58fc085f9683052d5a63c96fc912',
+                 '2':'04ec647e7b3414bcc069f0c54eb55a4c',
+                 '3':'fde84fd9bac725db8463554448f1e469',
+                 '4':'2359eea8671bf112b58264bec0294f71',
+                 '5':'82b55b63480114f04fad8c5c4fa5673a',
+                 '6':'e074864faeaeabb3be3d118192cd8879',
+                 '7':'753468d88d4810206a6f0ab9c6ef1b16',
+                 '8':'9cc4789a2cb223e8f2d5e676e90264b5',
+                 '9':'828cf0faf86ac78e7f43208907620527'
+                }
+
+        map=self.document.find("//map[@name='MapGril']")
+
+        coords={}
+        for area in map.getiterator("area"):
+            code=area.attrib.get("onclick")[-4:-2]
+            area_coords=[]
+            for coord in area.attrib.get("coords").split(","):
+                area_coords.append(int(coord))
+            coords[code]=tuple(area_coords)
 
         try:
-            img.build_tiles()
-        except TileError, err:
-            error('Error: %s' % err)
-            if err.tile:
-                err.tile.display()
+            vk=VirtKeyboard(self.browser.openurl("/NSImgGrille"),coords,27)
+        except VirtKeyboardError,err:
+            error("Error: %s" % err)
+            return False
+
+        for s in symbols.keys():
+            try:
+                vk.get_symbol_code(symbols[s])
+            except VirtKeyboardError:
+                if self.browser.responses_dirname is None:
+                    self.browser.responses_dirname = \
+                            tempfile.mkdtemp(prefix='weboob_session_')
+                vk.generate_MD5(self.browser.responses_dirname)
+                error("Error: Symbol '%s' not found; all symbol hashes are available in %s" \
+                      % (s,self.browser.responses_dirname))
+                return False
+
+        code_current=''
+        for c in current:
+            code_current+=vk.get_symbol_code(symbols[c])
 
-        code_current = img.get_codes(current)
-        code_new = img.get_codes(new)
+        code_new=''
+        for c in new:
+            code_new+=vk.get_symbol_code(symbols[c])
 
         data = {'ch1': code_current,
                 'ch2': code_new,
-- 
1.7.7




More information about the weboob mailing list