new bnporc backend
This commit is contained in:
parent
655bc10e3e
commit
69bb9e4826
8 changed files with 498 additions and 0 deletions
21
weboob/backends/bnporc/__init__.py
Normal file
21
weboob/backends/bnporc/__init__.py
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .backend import BNPorcBackend
|
||||||
67
weboob/backends/bnporc/backend.py
Normal file
67
weboob/backends/bnporc/backend.py
Normal file
|
|
@ -0,0 +1,67 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from weboob.backend import Backend
|
||||||
|
from weboob.capabilities.bank import ICapBank, AccountNotFound
|
||||||
|
|
||||||
|
from .browser import BNPorc
|
||||||
|
|
||||||
|
class BNPorcBackend(Backend, ICapBank):
|
||||||
|
NAME = 'bnporc'
|
||||||
|
MAINTAINER = 'Romain Bignon'
|
||||||
|
EMAIL = 'romain@peerfuse.org'
|
||||||
|
VERSION = '1.0'
|
||||||
|
LICENSE = 'GPLv3'
|
||||||
|
|
||||||
|
CONFIG = {'login': Backend.ConfigField(description='Account ID'),
|
||||||
|
'password': Backend.ConfigField(description='Password of account', is_masked=True)
|
||||||
|
}
|
||||||
|
browser = None
|
||||||
|
|
||||||
|
def need_browser(func):
|
||||||
|
def inner(self, *args, **kwargs):
|
||||||
|
if not self.browser:
|
||||||
|
self.browser = BNPorc(self.config['login'], self.config['password'])
|
||||||
|
|
||||||
|
return func(self, *args, **kwargs)
|
||||||
|
return inner
|
||||||
|
|
||||||
|
@need_browser
|
||||||
|
def iter_accounts(self):
|
||||||
|
for account in self.browser.get_accounts_list():
|
||||||
|
yield account
|
||||||
|
|
||||||
|
@need_browser
|
||||||
|
def get_account(self, _id):
|
||||||
|
try:
|
||||||
|
_id = long(_id)
|
||||||
|
except ValueError:
|
||||||
|
raise AccountNotFound()
|
||||||
|
else:
|
||||||
|
account = self.browser.get_account(_id)
|
||||||
|
if account:
|
||||||
|
return account
|
||||||
|
else:
|
||||||
|
raise AccountNotFound()
|
||||||
|
|
||||||
|
@need_browser
|
||||||
|
def iter_operations(self, account):
|
||||||
|
for coming in self.browser.get_coming_operations(account):
|
||||||
|
yield coming
|
||||||
98
weboob/backends/bnporc/browser.py
Normal file
98
weboob/backends/bnporc/browser.py
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from cStringIO import StringIO
|
||||||
|
|
||||||
|
from weboob.tools.browser import Browser, BrowserIncorrectPassword
|
||||||
|
from weboob.tools.parser import StandardParser
|
||||||
|
from weboob.backends.bnporc import pages
|
||||||
|
|
||||||
|
# Parser
|
||||||
|
class BNParser(StandardParser):
|
||||||
|
def parse(self, data, encoding):
|
||||||
|
s = data.read()
|
||||||
|
s = s.replace('<?Pub Caret>', '')
|
||||||
|
data = StringIO(s)
|
||||||
|
return StandardParser.parse(self, data)
|
||||||
|
|
||||||
|
# Browser
|
||||||
|
class BNPorc(Browser):
|
||||||
|
DOMAIN = 'www.secure.bnpparibas.net'
|
||||||
|
PROTOCOL = 'https'
|
||||||
|
ENCODING = None # refer to the HTML encoding
|
||||||
|
PAGES = {'.*identifiant=DOSSIER_Releves_D_Operation.*': pages.AccountsList,
|
||||||
|
'.*identifiant=DSP_HISTOCPT.*': pages.AccountHistory,
|
||||||
|
'.*NS_AVEEC.*': pages.AccountComing,
|
||||||
|
'.*NS_AVEDP.*': pages.AccountPrelevement,
|
||||||
|
'.*Action=DSP_VGLOBALE.*': pages.LoginPage,
|
||||||
|
'.*type=homeconnex.*': pages.LoginPage,
|
||||||
|
'.*layout=HomeConnexion': pages.ConfirmPage,
|
||||||
|
}
|
||||||
|
|
||||||
|
is_logging = False
|
||||||
|
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
kwargs['parser'] = BNParser
|
||||||
|
Browser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
def home(self):
|
||||||
|
self.location('https://www.secure.bnpparibas.net/banque/portail/particulier/HomeConnexion?type=homeconnex')
|
||||||
|
|
||||||
|
def is_logged(self):
|
||||||
|
return not self.is_on_page(pages.LoginPage) or self.is_logging
|
||||||
|
|
||||||
|
def login(self):
|
||||||
|
assert isinstance(self.username, (str,unicode))
|
||||||
|
assert isinstance(self.password, (str,unicode))
|
||||||
|
assert self.password.isdigit()
|
||||||
|
|
||||||
|
if not self.is_on_page(pages.LoginPage):
|
||||||
|
self.location('https://www.secure.bnpparibas.net/banque/portail/particulier/HomeConnexion?type=homeconnex')
|
||||||
|
|
||||||
|
self.is_logging = True
|
||||||
|
self.page.login(self.username, self.password)
|
||||||
|
self.location('/NSFR?Action=DSP_VGLOBALE')
|
||||||
|
|
||||||
|
if self.is_on_page(pages.LoginPage):
|
||||||
|
raise BrowserIncorrectPassword()
|
||||||
|
self.is_logging = False
|
||||||
|
|
||||||
|
def get_accounts_list(self):
|
||||||
|
if not self.is_on_page(pages.AccountsList):
|
||||||
|
self.location('/NSFR?Action=DSP_VGLOBALE')
|
||||||
|
return self.page.get_list()
|
||||||
|
|
||||||
|
def get_account(self, id):
|
||||||
|
assert isinstance(id, (int, long))
|
||||||
|
|
||||||
|
if not self.is_on_page(pages.AccountsList):
|
||||||
|
self.location('/NSFR?Action=DSP_VGLOBALE')
|
||||||
|
|
||||||
|
l = self.page.get_list()
|
||||||
|
for a in l:
|
||||||
|
if a.id == id:
|
||||||
|
return a
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_coming_operations(self, account):
|
||||||
|
if not self.is_on_page(pages.AccountComing) or self.page.account.id != account.id:
|
||||||
|
self.location('/NS_AVEEC?ch4=%s' % account.link_id)
|
||||||
|
return self.page.get_operations()
|
||||||
122
weboob/backends/bnporc/captcha.py
Normal file
122
weboob/backends/bnporc/captcha.py
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import hashlib
|
||||||
|
import sys
|
||||||
|
import Image
|
||||||
|
|
||||||
|
class TileError(Exception):
|
||||||
|
def __init__(self, msg, tile = None):
|
||||||
|
Exception.__init__(self, msg)
|
||||||
|
self.tile = tile
|
||||||
|
|
||||||
|
class Captcha:
|
||||||
|
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 = 5
|
||||||
|
ty = 0
|
||||||
|
while y < self.ny:
|
||||||
|
x = 6
|
||||||
|
tx = 0
|
||||||
|
while x < self.nx:
|
||||||
|
if self[x,y] == 8:
|
||||||
|
tile = self.tiles[tx][ty]
|
||||||
|
tile.valid = True
|
||||||
|
yy = y
|
||||||
|
while not self[x,yy] in (3,7):
|
||||||
|
l = []
|
||||||
|
tile.map.append(l)
|
||||||
|
xx = x
|
||||||
|
while not self[xx,yy] in (3,7):
|
||||||
|
l.append(self[xx,yy])
|
||||||
|
xx += 1
|
||||||
|
|
||||||
|
yy += 1
|
||||||
|
|
||||||
|
self.map[tile.getNum()] = tile
|
||||||
|
|
||||||
|
x += 26
|
||||||
|
tx += 1
|
||||||
|
|
||||||
|
y += 25
|
||||||
|
ty += 1
|
||||||
|
|
||||||
|
class Tile:
|
||||||
|
hash = {'b2d25ae11efaaaec6dd6a4c00f0dfc29': 1,
|
||||||
|
'600873fa288e75ca6cca092ae95bf129': 2,
|
||||||
|
'da24ac28930feee169adcbc9bad4acaf': 3,
|
||||||
|
'76294dec2a3c6a7b8d9fcc7a116d1d4f': 4,
|
||||||
|
'd9531059e3834b6b8a97e29417a47dec': 5,
|
||||||
|
'8ba0c0cfe5e64d6b4afb1aa6f3612c1a': 6,
|
||||||
|
'19e0120231e7a9cf4544f96d8c388c8a': 7,
|
||||||
|
'83d8ad340156cb7f5c1e64454b66c773': 8,
|
||||||
|
'5ee8648d77eeb3e0979f6e59b2fbe66a': 9,
|
||||||
|
'3f3fb79bf61ebad096e05287119169df': 0
|
||||||
|
}
|
||||||
|
|
||||||
|
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 += '%02d' % pxl
|
||||||
|
return hashlib.md5(s).hexdigest()
|
||||||
|
|
||||||
|
def getNum(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('%02d' % pxl)
|
||||||
|
sys.stdout.write('\n')
|
||||||
|
|
||||||
26
weboob/backends/bnporc/pages/__init__.py
Normal file
26
weboob/backends/bnporc/pages/__init__.py
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from .accounts_list import AccountsList
|
||||||
|
from .account_coming import AccountComing
|
||||||
|
from .login import LoginPage, ConfirmPage
|
||||||
|
|
||||||
|
class AccountHistory(AccountsList): pass
|
||||||
|
class AccountPrelevement(AccountsList): pass
|
||||||
51
weboob/backends/bnporc/pages/account_coming.py
Normal file
51
weboob/backends/bnporc/pages/account_coming.py
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
from weboob.tools.browser import BasePage
|
||||||
|
from weboob.capabilities.bank import Operation
|
||||||
|
|
||||||
|
class AccountComing(BasePage):
|
||||||
|
|
||||||
|
def loaded(self):
|
||||||
|
self.operations = []
|
||||||
|
|
||||||
|
for tr in self.document.getiterator('tr'):
|
||||||
|
if tr.attrib.get('class', '') == 'hdoc1' or tr.attrib.get('class', '') == 'hdotc1':
|
||||||
|
operation = Operation()
|
||||||
|
tds = tr.findall('td')
|
||||||
|
if len(tds) != 3:
|
||||||
|
continue
|
||||||
|
date = tds[0].getchildren()[0].attrib.get('name', '')
|
||||||
|
label = u''
|
||||||
|
label += tds[1].text
|
||||||
|
for child in tds[1].getchildren():
|
||||||
|
if child.text: label += child.text
|
||||||
|
if child.tail: label += child.tail
|
||||||
|
label += tds[1].tail
|
||||||
|
label = label.strip()
|
||||||
|
amount = tds[2].text.replace('.','').replace(',','.')
|
||||||
|
|
||||||
|
operation.setDate(date)
|
||||||
|
operation.setLabel(label)
|
||||||
|
operation.setAmount(float(amount))
|
||||||
|
self.operations.append(operation)
|
||||||
|
|
||||||
|
def get_operations(self):
|
||||||
|
return self.operations
|
||||||
61
weboob/backends/bnporc/pages/accounts_list.py
Normal file
61
weboob/backends/bnporc/pages/accounts_list.py
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import re
|
||||||
|
|
||||||
|
from weboob.capabilities.bank import Account
|
||||||
|
from weboob.tools.browser import BasePage
|
||||||
|
from weboob.tools.parser import tostring
|
||||||
|
|
||||||
|
class AccountsList(BasePage):
|
||||||
|
LINKID_REGEXP = re.compile(".*ch4=(\w+).*")
|
||||||
|
|
||||||
|
def loaded(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_list(self):
|
||||||
|
l = []
|
||||||
|
for tr in self.document.getiterator('tr'):
|
||||||
|
if tr.attrib.get('class', '') == 'comptes':
|
||||||
|
account = Account()
|
||||||
|
for td in tr.getiterator('td'):
|
||||||
|
if td.attrib.get('headers', '').startswith('Numero_'):
|
||||||
|
id = td.text
|
||||||
|
account.setID(long(''.join(id.split(' '))))
|
||||||
|
elif td.attrib.get('headers', '').startswith('Libelle_'):
|
||||||
|
a = td.findall('a')
|
||||||
|
label = unicode(a[0].text)
|
||||||
|
account.setLabel(label)
|
||||||
|
m = self.LINKID_REGEXP.match(a[0].attrib.get('href', ''))
|
||||||
|
if m:
|
||||||
|
account.setLinkID(m.group(1))
|
||||||
|
elif td.attrib.get('headers', '').startswith('Solde'):
|
||||||
|
a = td.findall('a')
|
||||||
|
balance = a[0].text
|
||||||
|
balance = balance.replace('.','').replace(',','.')
|
||||||
|
account.setBalance(float(balance))
|
||||||
|
elif td.attrib.get('headers', '').startswith('Avenir'):
|
||||||
|
a = td.findall('a')
|
||||||
|
coming = a[0].text
|
||||||
|
coming = coming.replace('.','').replace(',','.')
|
||||||
|
account.setComing(float(coming))
|
||||||
|
|
||||||
|
l.append(account)
|
||||||
|
return l
|
||||||
52
weboob/backends/bnporc/pages/login.py
Normal file
52
weboob/backends/bnporc/pages/login.py
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
"""
|
||||||
|
Copyright(C) 2009-2010 Romain Bignon
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, version 3 of the License.
|
||||||
|
|
||||||
|
This program 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 General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program; if not, write to the Free Software
|
||||||
|
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import ClientForm
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from weboob.tools.browser import BasePage
|
||||||
|
from weboob.backends.bnporc.captcha import Captcha, TileError
|
||||||
|
|
||||||
|
class LoginPage(BasePage):
|
||||||
|
def loaded(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def login(self, login, password):
|
||||||
|
img = Captcha(self.browser.openurl('/NSImgGrille'))
|
||||||
|
self.browser.back()
|
||||||
|
|
||||||
|
try:
|
||||||
|
img.build_tiles()
|
||||||
|
except TileError, err:
|
||||||
|
print >>sys.stderr, "Error: %s" % err
|
||||||
|
if err.tile:
|
||||||
|
err.tile.display()
|
||||||
|
|
||||||
|
self.browser.select_form('logincanalnet')
|
||||||
|
# HACK because of fucking malformed HTML, the field isn't recognized by mechanize.
|
||||||
|
self.browser.controls.append(ClientForm.TextControl('text', 'ch1', {'value': ''}))
|
||||||
|
self.browser.set_all_readonly(False)
|
||||||
|
|
||||||
|
self.browser['ch1'] = login
|
||||||
|
self.browser['ch5'] = img.get_codes(password)
|
||||||
|
self.browser.submit()
|
||||||
|
|
||||||
|
class ConfirmPage(BasePage):
|
||||||
|
pass
|
||||||
Loading…
Add table
Add a link
Reference in a new issue