if camera_id not in config.get_camera_ids():
raise HTTPError(404, 'no such camera')
+ local_config = config.get_camera(camera_id)
+ if utils.remote_camera(local_config):
+ def on_response(error=None):
+ if error:
+ return self.finish_json({'error': 'Failed to execute action on remote camera at %(url)s: %(msg)s.' % {
+ 'url': remote.pretty_camera_url(local_config), 'msg': error}})
+
+ self.finish_json()
+
+ return remote.exec_action(local_config, action, on_response)
+
if action == 'snapshot':
logging.debug('executing snapshot action for camera with id %s' % camera_id)
return self.snapshot()
query=query)
def on_response(response):
- motion_detected = False
-
- cookies = response.headers.get('Set-Cookie')
- if cookies:
- cookies = cookies.split(';')
- cookies = [[i.strip() for i in c.split('=')] for c in cookies]
- cookies = dict([c for c in cookies if len(c) == 2])
- motion_detected = cookies.get('motion_detected_' + str(camera_id)) == 'true'
- fps = cookies.get('capture_fps_' + str(camera_id))
- fps = float(fps) if fps else 0
-
+ cookies = utils.parse_cookies(response.headers.get_list('Set-Cookie'))
+ motion_detected = cookies.get('motion_detected_' + str(camera_id)) == 'true'
+ fps = cookies.get('capture_fps_' + str(camera_id))
+ fps = float(fps) if fps else 0
+
if response.error:
logging.error('failed to get current picture for remote camera %(id)s on %(url)s: %(msg)s' % {
'id': camera_id,
http_client = AsyncHTTPClient()
http_client.fetch(request, _callback_wrapper(on_response))
+
+
+def exec_action(local_config, action, callback):
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
+
+ logging.debug('executing action "%(action)s" of remote camera %(id)s on %(url)s' % {
+ 'action': action,
+ 'id': camera_id,
+ 'url': pretty_camera_url(local_config)})
+
+ path += '/action/%(id)s/%(action)s/' % {
+ 'action': action,
+ 'id': camera_id}
+
+ request = _make_request(scheme, host, port, username, password, path,
+ method='POST', data='{}',
+ timeout=settings.REMOTE_REQUEST_TIMEOUT, content_type='application/json')
+
+ def on_response(response):
+ if response.error:
+ logging.error('failed to execute action "%(action)s" of remote camera %(id)s on %(url)s: %(msg)s' % {
+ 'action': action,
+ 'id': camera_id,
+ 'url': pretty_camera_url(local_config),
+ 'msg': utils.pretty_http_error(response)})
+
+ return callback(error=utils.pretty_http_error(response))
+
+ callback()
+
+ http_client = AsyncHTTPClient()
+ http_client.fetch(request, _callback_wrapper(on_response))
_SIGNATURE_REGEX = re.compile('[^a-zA-Z0-9/?_.=&{}\[\]":, _-]')
+_SPECIAL_COOKIE_NAMES = {'expires', 'domain', 'path', 'secure', 'httponly'}
COMMON_RESOLUTIONS = [
return hashlib.sha1('%s:%s:%s:%s' % (method, path, body or '', key)).hexdigest().lower()
+def parse_cookies(cookies_headers):
+ parsed = {}
+
+ for cookie in cookies_headers:
+ cookie = cookie.split(';')
+ for c in cookie:
+ (name, value) = c.split('=', 1)
+ name = name.strip()
+ value = value.strip()
+
+ if name.lower() in _SPECIAL_COOKIE_NAMES:
+ continue
+
+ parsed[name] = value
+
+ return parsed
+
def build_basic_header(username, password):
return 'Basic ' + base64.encodestring('%s:%s' % (username, password)).replace('\n', '')