#!/usr/bin/env python2 ''' pCTF 2012 CLI interface Email bug reports to plaid.parliament.of.pwning@gmail.com. ''' import sys import getpass import json import cookielib import urllib import urllib2 import urlparse import textwrap import getpass try: import readline def completer(text, state): commands = [ 'help', 'hints', 'problems', 'score', 'show', 'submit', 'vote_clear', 'vote_down', 'vote_show', 'vote_summary', 'vote_up', 'quit', ] options = [x for x in commands if x.startswith(text)] if state < len(options): return options[state] else: return None readline.set_completer(completer) readline.parse_and_bind("tab: complete") except ImportError: pass class PCTFClient(object): def __init__(self, username=None, password=None, base_url='http://ctf.plaidctf.com'): self._cookiejar = cookielib.CookieJar() self._username = username self._password = password self._base_url = base_url self._opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(self._cookiejar)) self._auth = None self._csrftoken = None def login(self): # Get CSRF token url = urlparse.urljoin(self._base_url, '/dropdowns/login') self._opener.open(url) for c in self._cookiejar: if c.name == 'csrftoken': self._csrftoken = c.value url = urlparse.urljoin(self._base_url, '/teams/login') form_data = { 'username': self._username, 'password': self._password, 'csrfmiddlewaretoken': self._csrftoken } try: response = self._opener.open(url, urllib.urlencode(form_data)) except urllib2.URLError, reason: return False if 'Please try again.' in response.read(): return False for c in self._cookiejar: if c.name == 'auth': self._auth = c.value return True def request(self, path, data): url = urlparse.urljoin(self._base_url, path) if data is None: req = urllib2.Request(url) else: form_data = { 'data': json.dumps(data), 'csrfmiddlewaretoken': self._csrftoken } req = urllib2.Request(url, urllib.urlencode(form_data)) req.add_header('X-Auth', self._auth) response = self._opener.open(req) return response.read() def getteam(self): data = self.request('/teams/my_team', None) my_team = json.loads(data) if my_team['score'] is None: my_team['score'] = 0 return my_team def clean(self, s): s = s.replace('
', '\n\n') s = s.replace('
', '\n\n') s = s.replace('
', '\n\n') s = s.replace('<', '<') s = s.replace('>', '>') return '\n'.join(textwrap.wrap(s)) def getproblems(self, unsolved_only=True): if unsolved_only: data = self.request('/problems/list?unsolved_only', None) else: data = self.request('/problems/list', None) problems = json.loads(data) for p in problems: p['description'] = self.clean(p['description']) return problems def clean_hints(self, s): # silly split and join to get rid of