def do_login(self): ''' There's a bunch of dynamically generated obfuscated JavaScript, which uses DOM. For now the easiest option seems to be to run it in PhantomJs. ''' for i in xrange(self.MAX_RETRIES): scrf, scrn = mkstemp('.js') cookf, cookn = mkstemp('.json') os.write(scrf, LOGIN_JS % { 'timeout': self.TIMEOUT, 'username': self.username, 'password': self.password, 'output': cookn, 'question1': self.question1, 'answer1': self.answer1, 'question2': self.question2, 'answer2': self.answer2, 'question3': self.question3, 'answer3': self.answer3}) os.close(scrf) os.close(cookf) check_output(["phantomjs", scrn], stderr=STDOUT) with open(cookn) as cookf: cookies = json.loads(cookf.read()) os.remove(scrn) os.remove(cookn) self.session.cookies.clear() for c in cookies: for k in ['expiry', 'expires', 'httponly']: c.pop(k, None) c['value'] = unquote(c['value']) self.session.cookies.set(**c) self.summary.go() if self.page.logged: break else: raise BrowserIncorrectPassword
def extra(self): APPEND = r'jQuery\( "form" \).each\(function\(\) {' \ r'if\(isValidUrl\(jQuery\(this\).attr\("action"\)\)\){' \ r'jQuery\(this\).append\(([^)]+)\);}}\);' script = self.doc.xpath( '//script[contains(text(),"XXX_Extra")]/text()')[0] script = re.sub(APPEND, lambda m: 'return %s;' % m.group(1), script) script = re.sub(r'jQuery\(document\)[^\n]+\n', '', script) for x in re.findall('function ([^(]+)\(', script): script += '\nvar x = %s(); if (x) print(x);' % x scriptFd, scriptName = mkstemp('.js') os.write(scriptFd, script) os.close(scriptFd) html = check_output(["d8", scriptName], stderr=STDOUT) os.remove(scriptName) return re.findall(r'name=([^ ]+) value=([^>]+)>', html)
def ask(self, question, default=None, masked=None, regexp=None, choices=None, tiny=None): """ Ask a question to user. @param question text displayed (str) @param default optional default value (str) @param masked if True, do not show typed text (bool) @param regexp text must match this regexp (str) @param choices choices to do (list) @param tiny ask for the (small) value of the choice (bool) @return entered text by user (str) """ if isinstance(question, Value): v = copy(question) if default is not None: v.default = to_unicode(default) if isinstance(default, str) else default if masked is not None: v.masked = masked if regexp is not None: v.regexp = regexp if choices is not None: v.choices = choices if tiny is not None: v.tiny = tiny else: if isinstance(default, bool): klass = ValueBool elif isinstance(default, float): klass = ValueFloat elif isinstance(default, (int, long)): klass = ValueInt else: klass = Value v = klass(label=question, default=default, masked=masked, regexp=regexp, choices=choices, tiny=tiny) question = v.label if v.id: question = u'[%s] %s' % (v.id, question) if isinstance(v, ValueBackendPassword): print(question.encode(self.encoding) + ':') question = v.label choices = OrderedDict() choices['c'] = 'Run an external tool during backend load' if not v.noprompt: choices['p'] = 'Prompt value when needed (do not store it)' choices['s'] = 'Store value in config' if v.is_command(v.default): d = 'c' elif v.default == '' and not v.noprompt: d = 'p' else: d = 's' r = self.ask('*** How do you want to store it?', choices=choices, tiny=True, default=d) if r == 'p': return '' if r == 'c': print( 'Enter the shell command that will print the required value on the standard output' ) if v.is_command(v.default): print(': %s' % v.default[1:-1]) else: d = None while True: cmd = self.ask('') try: check_output(cmd, shell=True) except subprocess.CalledProcessError as e: print('%s' % e) else: return '`%s`' % cmd aliases = {} if isinstance(v, ValueBool): question = u'%s (%s/%s)' % (question, 'Y' if v.default else 'y', 'n' if v.default else 'N') elif v.choices: if v.tiny is None: v.tiny = True for key in v.choices.iterkeys(): if len(key) > 5 or ' ' in key: v.tiny = False break if v.tiny: question = u'%s (%s)' % (question, '/'.join( (s.upper() if s == v.default else s) for s in v.choices.iterkeys())) for s in v.choices.iterkeys(): if s == v.default: aliases[s.upper()] = s for key, value in v.choices.iteritems(): print(' %s%s%s: %s' % (self.BOLD, key, self.NC, value)) else: for n, (key, value) in enumerate(v.choices.iteritems()): print(' %s%2d)%s %s' % (self.BOLD, n + 1, self.NC, value.encode(self.encoding))) aliases[str(n + 1)] = key question = u'%s (choose in list)' % question if v.masked: question = u'%s (hidden input)' % question if not isinstance( v, ValueBool) and not v.tiny and v.default not in (None, ''): question = u'%s [%s]' % (question, '*******' if v.masked else v.default) question += ': ' while True: if v.masked: if sys.platform == 'win32': line = getpass.getpass(str(question)) else: line = getpass.getpass(question.encode(self.encoding)) else: self.stdout.write(question.encode(self.encoding)) self.stdout.flush() line = self.stdin.readline() if len(line) == 0: raise EOFError() else: line = line.rstrip('\r\n') if not line and v.default is not None: line = v.default if isinstance(line, str): line = line.decode('utf-8') if line in aliases: line = aliases[line] try: v.set(line) except ValueError as e: print(u'Error: %s' % e, file=self.stderr) else: break v.noprompt = True return v.get()
def ask(self, question, default=None, masked=None, regexp=None, choices=None, tiny=None): """ Ask a question to user. @param question text displayed (str) @param default optional default value (str) @param masked if True, do not show typed text (bool) @param regexp text must match this regexp (str) @param choices choices to do (list) @param tiny ask for the (small) value of the choice (bool) @return entered text by user (str) """ if isinstance(question, Value): v = copy(question) if default is not None: v.default = to_unicode(default) if isinstance(default, str) else default if masked is not None: v.masked = masked if regexp is not None: v.regexp = regexp if choices is not None: v.choices = choices if tiny is not None: v.tiny = tiny else: if isinstance(default, bool): klass = ValueBool elif isinstance(default, float): klass = ValueFloat elif isinstance(default, (int,long)): klass = ValueInt else: klass = Value v = klass(label=question, default=default, masked=masked, regexp=regexp, choices=choices, tiny=tiny) question = v.label if v.id: question = u'[%s] %s' % (v.id, question) if isinstance(v, ValueBackendPassword): print(question.encode(self.encoding) + ':') question = v.label choices = OrderedDict() choices['c'] = 'Run an external tool during backend load' if not v.noprompt: choices['p'] = 'Prompt value when needed (do not store it)' choices['s'] = 'Store value in config' if v.is_command(v.default): d = 'c' elif v.default == '' and not v.noprompt: d = 'p' else: d = 's' r = self.ask('*** How do you want to store it?', choices=choices, tiny=True, default=d) if r == 'p': return '' if r == 'c': print('Enter the shell command that will print the required value on the standard output') if v.is_command(v.default): print(': %s' % v.default[1:-1]) else: d = None while True: cmd = self.ask('') try: check_output(cmd, shell=True) except subprocess.CalledProcessError as e: print('%s' % e) else: return '`%s`' % cmd aliases = {} if isinstance(v, ValueBool): question = u'%s (%s/%s)' % (question, 'Y' if v.default else 'y', 'n' if v.default else 'N') elif v.choices: if v.tiny is None: v.tiny = True for key in v.choices.iterkeys(): if len(key) > 5 or ' ' in key: v.tiny = False break if v.tiny: question = u'%s (%s)' % (question, '/'.join((s.upper() if s == v.default else s) for s in v.choices.iterkeys())) for s in v.choices.iterkeys(): if s == v.default: aliases[s.upper()] = s for key, value in v.choices.iteritems(): print(' %s%s%s: %s' % (self.BOLD, key, self.NC, value)) else: for n, (key, value) in enumerate(v.choices.iteritems()): print(' %s%2d)%s %s' % (self.BOLD, n + 1, self.NC, value.encode(self.encoding))) aliases[str(n + 1)] = key question = u'%s (choose in list)' % question if v.masked: question = u'%s (hidden input)' % question if not isinstance(v, ValueBool) and not v.tiny and v.default not in (None, ''): question = u'%s [%s]' % (question, '*******' if v.masked else v.default) question += ': ' while True: if v.masked: if sys.platform == 'win32': line = getpass.getpass(str(question)) else: line = getpass.getpass(question.encode(self.encoding)) else: self.stdout.write(question.encode(self.encoding)) self.stdout.flush() line = self.stdin.readline() if len(line) == 0: raise EOFError() else: line = line.rstrip('\r\n') if not line and v.default is not None: line = v.default if isinstance(line, str): line = line.decode('utf-8') if line in aliases: line = aliases[line] try: v.set(line) except ValueError as e: print(u'Error: %s' % e, file=self.stderr) else: break v.noprompt = True return v.get()