Example #1
0
    def post(self, contents, max_age):
        form = self.get_form(xpath='//form[@class="well"]')

        password, d = encrypt(b64encode(contents.encode('utf-8')))
        form['content'] = json.dumps(d)
        form['expiration'] = self.AGES[max_age]
        j = form.submit().json()

        assert j['status'] == 'ok'
        return urljoin(urljoin(self.url, form.url), '%s#%s' % (j['paste'], password))
Example #2
0
    def post(self, contents, max_age):
        form = self.get_form(xpath='//form[@class="well"]')

        password, d = encrypt(b64encode(contents.encode('utf-8')))
        form['content'] = json.dumps(d)
        form['expiration'] = self.AGES[max_age]
        j = form.submit().json()

        assert j['status'] == 'ok'
        return urljoin(urljoin(self.url, form.url), '%s#%s' % (j['paste'], password))
Example #3
0
 def obj_url(self):
     url = urljoin(self.page.browser.BASEURL,
                   CleanText('./@data-url')(self))
     self.page.browser.location(url)
     if self.page.doc.xpath('//form[contains(., "Afficher")]'):
         return url
     raise SkipItem()
Example #4
0
    def get_cards(self):
        cards = []
        for tr in self.doc.xpath('//table[@class="dataNum"]/tbody/tr'):
            cards.append(urljoin(self.url, Link('.//a')(tr)))

        assert cards
        return cards
Example #5
0
 def absurl(self, uri, base=None):
     # FIXME this is copy-pasta from DomainBrowser
     if not base:
         base = self.url
     if base is None or base is True:
         base = self.BASEURL
     return urljoin(base, uri)
Example #6
0
 def obj_photos(self):
     photos = []
     for img in XPath('//div[has-class("carousel-content")]//img/@src')(self):
         url = u'%s' % img.replace('75x75', '800x600')
         url = urljoin(self.page.url, url)  # Ensure URL is absolute
         photos.append(HousingPhoto(url))
     return photos
Example #7
0
 def url2page(self, page):
     baseurl = self.PROTOCOL + '://' + self.DOMAIN + self.BASEPATH
     m = re.match('^' + urljoin(baseurl, 'wiki/(.+)$'), page)
     if m:
         return m.group(1)
     else:
         return page
Example #8
0
    def get_accounts_list(self):
        for table in self.doc.xpath('//div[@class="comptestabl"]/table'):
            try:
                account_type = self.ACCOUNT_TYPES[table.get('summary').lower()]
                if not account_type:
                    account_type = self.ACCOUNT_TYPES[table.xpath('./caption/text()')[0].strip().lower()]
            except (IndexError,KeyError):
                account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tbody/tr'):
                cols = tr.findall('td')

                link = cols[0].find('a')
                if link is None:
                    continue

                a = Account()
                a.type = account_type
                a.id = unicode(re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})', link.attrib['title']).group(1))
                a.label = unicode(link.attrib['title'].replace('%s ' % a.id, ''))
                tmp_balance = CleanText(None).filter(cols[1])
                a.currency = a.get_currency(tmp_balance)
                if not a.currency:
                    a.currency = u'EUR'
                a.balance = Decimal(Transaction.clean_amount(tmp_balance))
                a._has_cards = False
                a.url = urljoin(self.url, link.attrib['href'])
                yield a
Example #9
0
 def obj_photos(self):
     photos = []
     for img in XPath('//div[has-class("carousel-content")]//img/@src')(self):
         url = u'%s' % img.replace('75x75', '800x600')
         url = urljoin(self.page.url, url)  # Ensure URL is absolute
         photos.append(HousingPhoto(url))
     return photos
Example #10
0
File: pro.py Project: linura/weboob
    def get_accounts_list(self):
        for table in self.doc.xpath('//div[@class="comptestabl"]/table'):
            try:
                account_type = self.ACCOUNT_TYPES[table.get('summary').lower()]
                if not account_type:
                    account_type = self.ACCOUNT_TYPES[table.xpath(
                        './caption/text()')[0].strip().lower()]
            except (IndexError, KeyError):
                account_type = Account.TYPE_UNKNOWN
            for tr in table.xpath('./tbody/tr'):
                cols = tr.findall('td')

                link = cols[0].find('a')
                if link is None:
                    continue

                a = Account()
                a.type = account_type
                a.id = unicode(
                    re.search('([A-Z\d]{4}[A-Z\d\*]{3}[A-Z\d]{4})',
                              link.attrib['title']).group(1))
                a.label = unicode(link.attrib['title'].replace(
                    '%s ' % a.id, ''))
                tmp_balance = CleanText(None).filter(cols[1])
                a.currency = a.get_currency(tmp_balance)
                if not a.currency:
                    a.currency = u'EUR'
                a.balance = Decimal(Transaction.clean_amount(tmp_balance))
                a._has_cards = False
                a.url = urljoin(self.url, link.attrib['href'])
                yield a
Example #11
0
    def iter_advisor(self):
        if not self.advisor.is_here():
            self.location(self.advisor_url.format(self.sag))

        # it looks like we have an advisor only on cmds
        if "ca-cmds" in self.first_domain:
            perimetre, agence = self.page.get_codeperimetre().split('-')
            publickey = self.location(urljoin('https://' + self.first_domain, '/Vitrine/jsp/CMDS/b.js')).page.get_publickey()
            self.location(urljoin('https://' + self.first_domain.replace("www.ca", "www.credit-agricole"),
                                  "vitrine/tracking/t/%s-%s.html" % (hashlib.sha1(perimetre + publickey).hexdigest(),
                                                                     agence)))
            yield self.page.get_advisor()
        # for other we take numbers
        else:
            for adv in self.page.iter_numbers():
                yield adv
Example #12
0
 def absurl(self, uri, base=None):
     # FIXME this is copy-pasta from DomainBrowser
     if not base:
         base = self.url
     if base is None or base is True:
         base = self.BASEURL
     return urljoin(base, uri)
Example #13
0
    def get_account(self):
        for div in self.doc.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = CleanText().filter(div.xpath('.//span[@class="acc-num"]'))
            a.label = CleanText().filter(
                div.xpath('.//span[@class="card-desc"]'))
            if "carte" in a.label.lower():
                a.type = Account.TYPE_CARD
            balance = CleanText().filter(
                div.xpath('.//span[@class="balance-data"]'))
            if balance in (u'Indisponible',
                           u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.currency = a.get_currency(balance)
                a.balance = -abs(parse_decimal(balance))

            # Cancel card don't have a link to watch history
            link = self.doc.xpath('.//div[@class="wide-bar"]/h3/a')
            if len(link) == 1:
                a.url = urljoin(self.url, link[0].attrib['href'])
            else:
                a.url = None

            return a
Example #14
0
 def url2page(self, page):
     baseurl = self.PROTOCOL + '://' + self.DOMAIN + self.BASEPATH
     m = re.match('^' + urljoin(baseurl, 'wiki/(.+)$'), page)
     if m:
         return m.group(1)
     else:
         return page
Example #15
0
 def obj_url(self):
     try:
         return urljoin(
             self.page.browser.BASEURL,
             Link('.//a[has-class("Download")]')(self)
         )
     except XPathNotFound:
         return NotAvailable
Example #16
0
 def obj_url(self):
     try:
         return urljoin(
             self.page.browser.BASEURL,
             Link('./td[8]/a[1]')(self)
         )
     except XPathNotFound:
         return NotAvailable
Example #17
0
 def obj_url(self):
     try:
         return urljoin(
             self.page.browser.BASEURL,
             Link('.//a[has-class("Download")]')(self)
         )
     except XPathNotFound:
         return NotAvailable
Example #18
0
            def obj_url(self):
                self.obj_thumbnail()

                url = urljoin(self.page.url, Link('..//a[has-class("thumbnail")]')(self))
                if url != Field('_page')(self):
                    return url
                # TODO lazy load with fillobj?
                return self.page.browser.open(url).page.get_image_url()
Example #19
0
 def obj_url(self):
     url = Link(u'./a', default=NotAvailable)(self)
     if not url:
         url = Regexp(Attr(u'.//span', 'onclick', default=''), r'\'(https.*)\'', default=NotAvailable)(self)
     if url:
         if 'CreditRenouvelable' in url:
             url = Link(u'.//a[contains(text(), "espace de gestion crédit renouvelable")]')(self.el)
         return urljoin(self.page.url, url)
     return url
Example #20
0
 def obj_url(self):
     url = Link(u'./a', default=NotAvailable)(self)
     if not url:
         url = Regexp(Attr(u'.//span', 'onclick', default=''), r'\'(https.*)\'', default=NotAvailable)(self)
     if url:
         if 'CreditRenouvelable' in url:
             url = Link(u'.//a[contains(text(), "espace de gestion crédit renouvelable")]')(self.el)
         return urljoin(self.page.url, url)
     return url
Example #21
0
 def obj_photos(self):
     photos = []
     url = Attr('.//div[has-class("offer-picture")]//img',
                'src')(self)
     if url:
         url = url.replace('400x267', '800x600')
         url = urljoin(self.page.url, url)  # Ensure URL is absolute
         photos.append(HousingPhoto(url))
     return photos
Example #22
0
 def iter_accounts(self):
     self.accounts.stay_or_go()
     # sometimes when the user has messages, accounts's page will redirect
     # to the message page and the user will have to click "ok" to access his accounts
     # this will happen as long as the messages aren't deleted.
     # In this case, accounts may be reached through a different link (in the "ok" button)
     acc_link = self.page.get_acc_link()
     if acc_link:
         self.location(urljoin(self.BASEURL, acc_link))
     return self.page.iter_accounts()
Example #23
0
        def next_page(self):
            pager = self.page.doc.xpath('//div[@class="pager"]')
            if pager:  # more than one page if only enough transactions
                assert len(pager) == 1

                next_links = pager[0].xpath('./span/following-sibling::a[@class="page"]')
                if next_links:
                    url_next_page = Link('.')(next_links[0])
                    url_next_page = urljoin(self.page.url, url_next_page)
                    return self.page.browser.build_request(url_next_page)
Example #24
0
    def download_document_pdf(self, document):
        if not isinstance(document, Document):
            document = self.get_document(document)
        if document.url is NotAvailable:
            return
        if document.format == 'pdf':
            return self.browser.open(document.url).content

        url = urljoin(self.browser.BASEURL, document.url)
        return html_to_pdf(self.browser, url=url)
Example #25
0
 def iter_accounts(self):
     self.accounts.stay_or_go()
     # sometimes when the user has messages, accounts's page will redirect
     # to the message page and the user will have to click "ok" to access his accounts
     # this will happen as long as the messages aren't deleted.
     # In this case, accounts may be reached through a different link (in the "ok" button)
     acc_link = self.page.get_acc_link()
     if acc_link:
         self.location(urljoin(self.BASEURL, acc_link))
     return self.page.iter_accounts()
Example #26
0
 def iter_documents(self, subid):
     for d in self.doc['data']['items']:
         doc = Document()
         doc.id = '%s_%s' % (subid, d['id'])
         doc._docid = d['id']
         doc.label = d['import']['name']
         doc.date = parse_date(d['import']['endDate'])
         doc.url = urljoin(self.url, '/pagga/download/%s' % doc._docid)
         doc.type = DocumentTypes.BILL
         doc.format = 'pdf'
         yield doc
Example #27
0
        def next_page(self):
            pager = self.page.doc.xpath('//div[@class="pager"]')
            if pager:  # more than one page if only enough transactions
                assert len(pager) == 1

                next_links = pager[0].xpath(
                    './span/following-sibling::a[@class="page"]')
                if next_links:
                    url_next_page = Link('.')(next_links[0])
                    url_next_page = urljoin(self.page.url, url_next_page)
                    return self.page.browser.build_request(url_next_page)
Example #28
0
 def post(self, paste, max_age=0):
     bin = b64decode(paste.contents)
     name = paste.title or 'file'  # filename is mandatory
     filefield = {'file': (name, BytesIO(bin))}
     params = {'format': 'json'}
     if max_age:
         params['delete-day'] = int(math.ceil(max_age / 86400.))
     self.location('/', data=params, files=filefield)
     assert self.upload_page.is_here()
     info = self.page.fetch_info()
     paste.id = urljoin(self.base_url, info['short'])
Example #29
0
 def iter_documents(self, subid):
     for d in self.doc['data']['items']:
         doc = Document()
         doc.id = '%s_%s' % (subid, d['id'])
         doc._docid = d['id']
         doc.label = d['import']['name']
         doc.date = parse_date(d['import']['endDate'])
         doc.url = urljoin(self.url, '/pagga/download/%s' % doc._docid)
         doc.type = DocumentTypes.BILL
         doc.format = 'pdf'
         yield doc
Example #30
0
 def obj_photos(self):
     photos = []
     url = Attr(
         './/div[has-class("offer-picture")]//img',
         'src'
     )(self)
     if url:
         url = url.replace('400x267', '800x600')
         url = urljoin(self.page.url, url)  # Ensure URL is absolute
         photos.append(HousingPhoto(url))
     return photos
Example #31
0
 def post(self, paste, max_age=0):
     bin = b64decode(paste.contents)
     name = paste.title or 'file' # filename is mandatory
     filefield = {'file': (name, BytesIO(bin))}
     params = {'format': 'json'}
     if max_age:
         params['delete-day'] = int(math.ceil(max_age / 86400.))
     self.location('/', data=params, files=filefield)
     assert self.upload_page.is_here()
     info = self.page.fetch_info()
     paste.id = urljoin(self.base_url, info['short'])
Example #32
0
    def iter_advisor(self):
        if not self.advisor.is_here():
            self.location(self.advisor_url.format(self.sag))

        # it looks like we have an advisor only on cmds
        if "ca-cmds" in self.first_domain:
            perimetre, agence = self.page.get_codeperimetre().split('-')
            publickey = self.location(
                urljoin('https://' + self.first_domain,
                        '/Vitrine/jsp/CMDS/b.js')).page.get_publickey()
            self.location(
                urljoin(
                    'https://' +
                    self.first_domain.replace("www.ca", "www.credit-agricole"),
                    "vitrine/tracking/t/%s-%s.html" %
                    (hashlib.sha1(perimetre + publickey).hexdigest(), agence)))
            yield self.page.get_advisor()
        # for other we take numbers
        else:
            for adv in self.page.iter_numbers():
                yield adv
Example #33
0
    def handle_refresh(self):
        if self.REFRESH_MAX is None:
            return

        for refresh in self.doc.xpath('//head/meta[lower-case(@http-equiv)="refresh"]'):
            m = self.browser.REFRESH_RE.match(refresh.get('content', ''))
            if not m:
                continue
            url = urljoin(self.url, m.groupdict().get('url', None))
            sleep = float(m.groupdict()['sleep'])

            if sleep <= self.REFRESH_MAX:
                self.logger.info('Redirecting to %s', url)
                self.browser.location(url)
                break
            else:
                self.logger.debug('Do not refresh to %s because %s > REFRESH_MAX(%s)' % (url, sleep, self.REFRESH_MAX))
Example #34
0
 def populate(self, accounts):
     cards = []
     for account in accounts:
         for li in self.doc.xpath('//li[@class="nav-category"]'):
             title = CleanText().filter(li.xpath('./h3'))
             for a in li.xpath('./ul/li//a'):
                 label = CleanText().filter(
                     a.xpath('.//span[@class="nav-category__name"]'))
                 balance_el = a.xpath(
                     './/span[@class="nav-category__value"]')
                 balance = CleanDecimal(
                     replace_dots=True,
                     default=NotAvailable).filter(balance_el)
                 if 'CARTE' in label and not empty(balance):
                     acc = Account()
                     acc.balance = balance
                     acc.label = label
                     acc.currency = FrenchTransaction.Currency().filter(
                         balance_el)
                     acc.url = urljoin(self.url,
                                       Link().filter(a.xpath('.')))
                     acc._history_page = acc.url
                     try:
                         acc.id = acc._webid = Regexp(
                             pattern='carte/(.*)$').filter(Link().filter(
                                 a.xpath('.')))
                     except RegexpError:
                         # Those are external cards, ie: amex cards
                         continue
                     acc.type = Account.TYPE_CARD
                     if not acc in cards:
                         cards.append(acc)
                 elif account.label == label and account.balance == balance:
                     if not account.type:
                         account.type = AccountsPage.ACCOUNT_TYPES.get(
                             title, Account.TYPE_UNKNOWN)
                     account._webid = Attr(
                         None, 'data-account-label').filter(
                             a.xpath(
                                 './/span[@class="nav-category__name"]'))
     if cards:
         self.browser.go_cards_number(cards[0].url)
         if self.browser.cards.is_here():
             self.browser.page.populate_cards_number(cards)
             accounts.extend(cards)
Example #35
0
 def iter_documents(self, sub):
     elts = self.doc.xpath('//li[@class="rowdate"]')
     for elt in elts:
         try:
             elt.xpath('.//a[contains(@id,"lienPDFReleve")]')[0]
         except IndexError:
            continue
         date_str = elt.xpath('.//span[contains(@id,"moisEnCours")]')[0].text
         month_str = date_str.split()[0]
         date = datetime.strptime(re.sub(month_str, str(FRENCH_MONTHS.index(month_str) + 1), date_str), "%m %Y").date()
         bil = Bill()
         bil.id = sub._id + "." + date.strftime("%Y%m")
         bil.date = date
         bil.format = u'pdf'
         bil.type = u'bill'
         bil.label = u'' + date.strftime("%Y%m%d")
         bil.url = urljoin(self.url, '/PortailAS/PDFServletReleveMensuel.dopdf?PDF.moisRecherche=%s' % date.strftime("%m%Y"))
         yield bil
Example #36
0
    def get_code(self):
        # Codes (AMF / ISIN) are available after a click on a tab
        characteristics_url = urljoin(self.url, Attr(u'//a[contains(text(), "Caractéristiques")]', 'data-href', default=None)(self.doc))
        if characteristics_url is not None:
            detail_page = self.browser.open(characteristics_url).page

            # We prefer to return an ISIN code by default
            code_isin = detail_page.get_code_isin()
            if code_isin is not None:
                self.CODE_TYPE = Investment.CODE_TYPE_ISIN
                return code_isin

            # But if it's unavailable we can fallback to an AMF code
            code_amf = detail_page.get_code_amf()
            if code_amf is not None:
                self.CODE_TYPE = Investment.CODE_TYPE_AMF
                return code_amf

        return NotAvailable
Example #37
0
    def fill_video_url(self, video):
        self._setup_session(self.PROFILE)
        try:
            video = self.video_url.open(_id=video.id).fill_url(obj=video)
            if self.method == u'hls':
                streams = []
                for item in self.read_url(video.url):
                    item = item.decode('ascii')
                    if not item.startswith('#') and item.strip():
                        streams.append(item)

                if streams:
                    streams.reverse()
                    url = streams[self.quality] if self.quality < len(streams) else streams[0]
                    video.url = urljoin(video.url, url)
                else:
                    video.url = NotAvailable
            return video
        except HTTPNotFound:
            return video
Example #38
0
    def get_account(self):
        for div in self.doc.xpath('.//div[@id="card-details"]'):
            a = Account()
            a.id = CleanText().filter(div.xpath('.//span[@class="acc-num"]'))
            a.label = CleanText().filter(div.xpath('.//span[@class="card-desc"]'))
            a.type = Account.TYPE_CARD
            balance = CleanText().filter(div.xpath('.//span[@class="balance-data"]'))
            if balance in (u'Indisponible', u'Indisponible Facturation en cours', ''):
                a.balance = NotAvailable
            else:
                a.currency = a.get_currency(balance)
                a.balance = - abs(parse_decimal(balance))

            # Cancel card don't have a link to watch history
            link = self.doc.xpath('.//div[@class="wide-bar"]/h3/a')
            if len(link) == 1:
                a.url = urljoin(self.url, link[0].attrib['href'])
            else:
                a.url = None

            return a
Example #39
0
    def absurl(self, uri, base=None):
        """
        Get the absolute URL, relative to a base URL.
        If base is None, it will try to use the current URL.
        If there is no current URL, it will try to use BASEURL.

        If base is False, it will always try to use the current URL.
        If base is True, it will always try to use BASEURL.

        :param uri: URI to make absolute. It can be already absolute.
        :type uri: str

        :param base: Base absolute URL.
        :type base: str or None or False or True

        :rtype: str
        """
        if not base:
            base = self.url
        if base is None or base is True:
            base = self.BASEURL
        return urljoin(base, uri)
Example #40
0
    def get_code(self):
        # Codes (AMF / ISIN) are available after a click on a tab
        characteristics_url = urljoin(self.url, Attr(u'//a[contains(text(), "Caractéristiques")]', 'data-href', default=None)(self.doc))
        if characteristics_url is not None:
            detail_page = self.browser.open(characteristics_url).page

            if not isinstance(detail_page, EtoileGestionCharacteristicsPage):
                return NotAvailable

            # We prefer to return an ISIN code by default
            code_isin = detail_page.get_isin_code()
            if code_isin is not None:
                self.CODE_TYPE = Investment.CODE_TYPE_ISIN
                return code_isin

            # But if it's unavailable we can fallback to an AMF code
            code_amf = detail_page.get_code_amf()
            if code_amf is not None:
                self.CODE_TYPE = Investment.CODE_TYPE_AMF
                return code_amf

        return NotAvailable
Example #41
0
    def absurl(self, uri, base=None):
        """
        Get the absolute URL, relative to a base URL.
        If base is None, it will try to use the current URL.
        If there is no current URL, it will try to use BASEURL.

        If base is False, it will always try to use the current URL.
        If base is True, it will always try to use BASEURL.

        :param uri: URI to make absolute. It can be already absolute.
        :type uri: str

        :param base: Base absolute URL.
        :type base: str or None or False or True

        :rtype: str
        """
        if not base:
            base = self.url
        if base is None or base is True:
            base = self.BASEURL
        return urljoin(base, uri)
Example #42
0
 def obj_url(self):
     url = Link(u'./a', default=NotAvailable)(self)
     if url:
         return urljoin(self.page.url, url)
     return url
Example #43
0
 def obj_url(self):
     url = Link(u'.//a', default=None)(self)
     if url:
         return urljoin(self.page.url, url)
     return self.page.url
Example #44
0
 def get_js_url(self):
     # look for frame url in the top page
     return urljoin(self.url, JSVar(CleanText('//script'), var='url')(self.doc))
Example #45
0
    def do_login(self):
        """
        Attempt to log in.
        Note: this method does nothing if we are already logged in.
        """
        if not self.username or not self.password:
            raise BrowserIncorrectPassword()

        # Reset domain to log on pro website if first login attempt failed on personal website.
        if self.multi_type:
            self.BASEURL = 'https://www.caisse-epargne.fr'
            self.typeAccount = 'WP'

        data = self.login.go(login=self.username).get_response()

        if data is None:
            raise BrowserIncorrectPassword()

        if "authMode" in data and data['authMode'] == 'redirect':
            raise ChangeBrowser()

        if len(data['account']) > 1:
            self.multi_type = True
            data = self.account_login.go(
                login=self.username,
                accountType=self.typeAccount).get_response()

        assert data is not None

        typeAccount = data['account'][0]

        idTokenClavier = data['keyboard']['Id']
        vk = CaissedepargneKeyboard(data['keyboard']['ImageClavier'],
                                    data['keyboard']['Num']['string'])
        newCodeConf = vk.get_string_code(self.password)

        playload = {
            'idTokenClavier': idTokenClavier,
            'newCodeConf': newCodeConf,
            'auth_mode': 'ajax',
            'nuusager': self.nuser.encode('utf-8'),
            'codconf': self.password,
            'typeAccount': typeAccount,
            'step': 'authentification',
            'ctx': 'typsrv=WE',
            'clavierSecurise': '1',
            'nuabbd': self.username
        }

        res = self.location(data['url'], params=playload)
        if not res.page:
            raise BrowserUnavailable()

        response = res.page.get_response()

        assert response is not None

        if not response['action']:
            if not self.typeAccount == 'WP' and self.multi_type:
                # If we haven't test PRO espace we check before raising wrong pass
                self.do_login()
                return
            raise BrowserIncorrectPassword(response['error'])

        self.BASEURL = urljoin(data['url'], '/')

        try:
            self.home.go()
        except BrowserHTTPNotFound:
            raise BrowserIncorrectPassword()
Example #46
0
    def do_login(self):
        """
        Attempt to log in.
        Note: this method does nothing if we are already logged in.
        """
        # Among the parameters used during the login step, there is
        # a connection type (called typeAccount) that can take the
        # following values:
        # WE: espace particulier
        # WP: espace pro
        # WM: personnes protégées
        # EU: Cenet
        #
        # A connection can have one connection type as well as many of
        # them. There is an issue when there is many connection types:
        # the connection type to use can't be guessed in advance, we
        # have to test all of them until the login step is successful
        # (sometimes all connection type can be used for the login, sometimes
        # only one will work).
        #
        # For simplicity's sake, we try each connection type from first to
        # last (they are returned in a list by the first request)
        #
        # Examples of connection types combination that have been seen so far:
        # [WE]
        # [WP]
        # [WE, WP]
        # [WE, WP, WM]
        # [WP, WM]
        # [EU]
        # [EU, WE]  (EU tends to come first when present)

        if not self.username or not self.password:
            raise BrowserIncorrectPassword()

        # Retrieve the list of types: can contain a single type or more
        # - when there is a single type: all the information are available
        # - when there are several types: an additional request is needed
        try:
            connection = self.login.go(login=self.username)
        # The website crash sometime when the module is not on caissedepargne (on linebourse, for exemple).
        # The module think is not connected anymore, so we go to the home logged page. If there are no error
        # that mean we are already logged and now, on the good website

        except ValueError:
            self.home.go()
            if self.home.is_here():
                return
            # If that not the case, that's an other error that we have to correct
            raise

        data = connection.get_response()

        if data is None:
            raise BrowserIncorrectPassword()

        accounts_types = data.get('account', [])
        if not self.nuser and 'WE' not in accounts_types:
            raise BrowserIncorrectPassword("Utilisez Caisse d'Épargne Professionnels et renseignez votre nuser pour connecter vos comptes sur l'epace Professionels ou Entreprises.")

        if len(accounts_types) > 1:
            # Additional request when there is more than one connection type
            # to "choose" from the list of connection types
            self.multi_type = True

            if self.inexttype < len(accounts_types):
                if accounts_types[self.inexttype] == 'EU' and not self.nuser:
                    # when EU is present and not alone, it tends to come first
                    # if nuser is unset though, user probably doesn't want 'EU'
                    self.inexttype += 1

                self.typeAccount = accounts_types[self.inexttype]
            else:
                assert False, 'should have logged in with at least one connection type'
            self.inexttype += 1

            data = self.account_login.go(login=self.username, accountType=self.typeAccount).get_response()

        assert data is not None

        if data.get('authMode', '') == 'redirect':  # the connection type EU could also be used as a criteria
            raise SiteSwitch('cenet')

        typeAccount = data['account'][0]

        if self.multi_type:
            assert typeAccount == self.typeAccount

        id_token_clavier = data['keyboard']['Id']
        vk = CaissedepargneKeyboard(data['keyboard']['ImageClavier'], data['keyboard']['Num']['string'])
        newCodeConf = vk.get_string_code(self.password)

        playload = {
            'idTokenClavier': id_token_clavier,
            'newCodeConf': newCodeConf,
            'auth_mode': 'ajax',
            'nuusager': self.nuser.encode('utf-8'),
            'codconf': '',  # must be present though empty
            'typeAccount': typeAccount,
            'step': 'authentification',
            'ctx': 'typsrv={}'.format(typeAccount),
            'clavierSecurise': '1',
            'nuabbd': self.username
        }

        try:
            res = self.location(data['url'], params=playload)
        except ValueError:
            raise BrowserUnavailable()
        if not res.page:
            raise BrowserUnavailable()

        response = res.page.get_response()

        assert response is not None

        if response['error'] == 'Veuillez changer votre mot de passe':
            raise BrowserPasswordExpired(response['error'])

        if not response['action']:
            # the only possible way to log in w/o nuser is on WE. if we're here no need to go further.
            if not self.nuser and self.typeAccount == 'WE':
                raise BrowserIncorrectPassword(response['error'])

            # we tested all, next iteration will throw the assertion
            if self.inexttype == len(accounts_types) and 'Temporairement votre abonnement est bloqué' in response['error']:
                raise ActionNeeded(response['error'])

            if self.multi_type:
                # try to log in with the next connection type's value
                self.do_login()
                return
            raise BrowserIncorrectPassword(response['error'])

        self.BASEURL = urljoin(data['url'], '/')

        try:
            self.home.go()
        except BrowserHTTPNotFound:
            raise BrowserIncorrectPassword()
Example #47
0
 def get_js_url(self):
     # look for frame url in the top page
     return urljoin(self.url,
                    JSVar(CleanText('//script'), var='url')(self.doc))
Example #48
0
 def obj_url(self):
     td = TableCell('label')(self)[0].xpath('.//a')[0]
     return urljoin(self.page.url, td.attrib['href'])
Example #49
0
 def obj_url(self):
     return urljoin(self.page.url, Regexp(Dict('sOperation'), r'&quot;(/.*\.pdf)')(self))
Example #50
0
 def obj_url(self):
     return urljoin(self.page.url, Link('.//a')(self))
Example #51
0
 def obj_thumbnail(self):
     path = Attr('./a[has-class("thumbnail")]/img', 'src', default=None)(self)
     if path is None:
         raise SkipItem('not an image thread')
     return Thumbnail(urljoin(self.page.url, path))
Example #52
0
 def get_image_url(self):
     if self.doc.xpath('//video[@class="preview"]'):
         raise SkipItem('Videos are not implemented')
     return urljoin(self.url, Link('//a[img[@class="preview"]]')(self.doc))
Example #53
0
 def __call__(self, item):
     ret = super(AbsoluteLink, self).__call__(item)
     if ret:
         ret = urljoin(item.page.url, ret)
     return ret
Example #54
0
 def absurl(self, url):
     """
     Get an absolute URL from an a partial URL, relative to the Page URL
     """
     return urljoin(self.url, url)