def http(self): if self._http is None: self._http = Http(workdir=self.workdir, base_url=self.yabi_url) return self._http
class Yabi(object): def __init__(self, url, backend=None, bg=False, debug=False): self._http = None self.yabi_url = url self.workdir = os.path.expanduser('~/.yabish') self.cachedir = os.path.join(self.workdir, 'cache') self.csrftokenfile = os.path.join(self.workdir, 'csrf_token') self.cookiesfile = os.path.join(self.workdir, 'cookies.txt') self.username = None self.backend = backend self.run_in_background = bg self.debug = debug if self.debug: import httplib2 httplib2.debuglevel = 1 @property def http(self): if self._http is None: self._http = Http(workdir=self.workdir, base_url=self.yabi_url) return self._http @property def csrf_token(self): token = None if os.path.exists(self.csrftokenfile): with open(self.csrftokenfile) as f: token = f.read().strip() if not token: token = self.retrieve_csrf_token() if token is not None: with open(self.csrftokenfile, "w") as f: f.write(token) return token def retrieve_csrf_token(self): url = self.yabi_url.rstrip('/') + '/login' resp, contents = self.http.make_request(self._create_request('GET', url)) cookies = Cookie.SimpleCookie() cookies.load(resp.get('set-cookie', '')) csrf_cookie = None for name, value in cookies.items(): # We do not know the exact name of the CSRF cookie on the # client-side but we know it starts with 'csrf_yabi_' if name.startswith('csrf_yabi'): csrf_cookie = value break csrf_token = None if csrf_cookie is not None: csrf_token = csrf_cookie.value return csrf_token def reset_csrf_token(self): os.unlink(self.csrftokenfile) def delete_dir(self, stageindir): rmdir = actions.Rm(self) rmdir.process([stageindir]) def login(self): import getpass system_user = getpass.getuser() username = raw_input('Username (%s): ' % system_user) if '' == username.strip(): username = system_user password = getpass.getpass() login_action = actions.Login(self) return login_action.process([username, password]) def _create_request(self, method, url, params=None, files=None): if method not in ('GET', 'POST'): raise ValueError("Method should be GET or POST") if params is None: params = {} # Pretend we're making AJAX calls headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} if method == 'POST': if self.csrf_token is not None: headers['Referer'] = self.yabi_url headers['X-CSRFToken'] = self.csrf_token if method == 'GET': request = GetRequest(url, params, headers=headers) elif method == 'POST': request = PostRequest(url, params, files=files, headers=headers) return request def request(self, method, url, params=None, files=None): try: request = self._create_request(method, url, params, files) if self.debug: print('=' * 5 + 'Making HTTP request') resp, contents = self.http.make_request(request) if self.debug: print(resp, contents) print('=' * 5 + 'End of HTTP request') except UnauthorizedError: if not self.login(): raise Exception("Invalid username/password") resp, contents = self.http.make_request(request) if int(resp.status) == 403: # CSRF token error. Reset the token and try again. self.reset_csrf_token() request = self._create_request(method, url, params, files) resp, contents = self.http.make_request(request) if int(resp.status) >= 400: raise errors.CommunicationError(int(resp.status), url, contents) return resp, contents def get(self, url, params=None): return self.request('GET', url, params) def post(self, url, params=None, files=None): return self.request('POST', url, params=params, files=files) def choose_action(self, action_name): class_name = action_name.capitalize() try: cls = getattr(sys.modules['yabishell.actions'], class_name) except AttributeError: if self.run_in_background: cls = actions.BackgroundRemoteAction else: cls = actions.ForegroundRemoteAction return cls(self, name=action_name) def session_finished(self): if self._http: self._http.finish_session()
class Yabi(object): def __init__(self, url, backend=None, bg=False, debug=False): self._http = None self.yabi_url = url self.workdir = os.path.expanduser('~/.yabish') self.cachedir = os.path.join(self.workdir, 'cache') self.csrftokenfile = os.path.join(self.workdir, 'csrf_token') self.cookiesfile = os.path.join(self.workdir, 'cookies.txt') self.username = None self.backend = backend self.run_in_background = bg self.debug = debug if self.debug: import httplib2 httplib2.debuglevel = 1 @property def http(self): if self._http is None: self._http = Http(workdir=self.workdir, base_url=self.yabi_url) return self._http @property def csrf_token(self): token = None if os.path.exists(self.csrftokenfile): with open(self.csrftokenfile) as f: token = f.read().strip() if not token: token = self.retrieve_csrf_token() if token is not None: with open(self.csrftokenfile, "w") as f: f.write(token) return token def retrieve_csrf_token(self): url = self.yabi_url.rstrip('/') + '/login' resp, contents = self.http.make_request( self._create_request('GET', url)) cookies = Cookie.SimpleCookie() cookies.load(resp.get('set-cookie', '')) csrf_cookie = None for name, value in cookies.items(): # We do not know the exact name of the CSRF cookie on the # client-side but we know it starts with 'csrf_yabi_' if name.startswith('csrf_yabi'): csrf_cookie = value break csrf_token = None if csrf_cookie is not None: csrf_token = csrf_cookie.value return csrf_token def reset_csrf_token(self): os.unlink(self.csrftokenfile) def delete_dir(self, stageindir): rmdir = actions.Rm(self) rmdir.process([stageindir]) def login(self): import getpass system_user = getpass.getuser() username = raw_input('Username (%s): ' % system_user) if '' == username.strip(): username = system_user password = getpass.getpass() login_action = actions.Login(self) return login_action.process([username, password]) def _create_request(self, method, url, params=None, files=None): if method not in ('GET', 'POST'): raise ValueError("Method should be GET or POST") if params is None: params = {} # Pretend we're making AJAX calls headers = {'HTTP_X_REQUESTED_WITH': 'XMLHttpRequest'} if method == 'POST': if self.csrf_token is not None: headers['Referer'] = self.yabi_url headers['X-CSRFToken'] = self.csrf_token if method == 'GET': request = GetRequest(url, params, headers=headers) elif method == 'POST': request = PostRequest(url, params, files=files, headers=headers) return request def request(self, method, url, params=None, files=None): try: request = self._create_request(method, url, params, files) if self.debug: print('=' * 5 + 'Making HTTP request') resp, contents = self.http.make_request(request) if self.debug: print(resp, contents) print('=' * 5 + 'End of HTTP request') except UnauthorizedError: if not self.login(): raise Exception("Invalid username/password") resp, contents = self.http.make_request(request) if int(resp.status) == 403: # CSRF token error. Reset the token and try again. self.reset_csrf_token() request = self._create_request(method, url, params, files) resp, contents = self.http.make_request(request) if int(resp.status) >= 400: raise errors.CommunicationError(int(resp.status), url, contents) return resp, contents def get(self, url, params=None): return self.request('GET', url, params) def post(self, url, params=None, files=None): return self.request('POST', url, params=params, files=files) def choose_action(self, action_name): class_name = action_name.capitalize() try: cls = getattr(sys.modules['yabishell.actions'], class_name) except AttributeError: if self.run_in_background: cls = actions.BackgroundRemoteAction else: cls = actions.ForegroundRemoteAction return cls(self, name=action_name) def session_finished(self): if self._http: self._http.finish_session()