-# static files (.css, .js etc) are served at this root url;
+# the base URL path at which motionEye lives
# change this if you run motionEye behind a reverse proxy (e.g. nginx),
-# and you want static files to be served directly by it
-static_url /static/
+# and you want to make motionEye accessible at a specific base path (e.g. /cams)
+#base_path /cams
# path to the configuration directory (must be writable by motionEye)
conf_path /etc/motioneye
-VERSION = "0.27.2"
+VERSION = "0.27.2-git"
else:
host = device_details['username'] + '@' + host
- device_details['url'] = urlparse.urlunparse((device_details['scheme'], host, device_details['uri'], '', '', ''))
+ device_details['url'] = urlparse.urlunparse((device_details['scheme'], host, device_details['path'], '', '', ''))
# determine the last camera id
camera_ids = get_camera_ids()
camera_config = {'@enabled': True}
if proto == 'v4l2':
# find a suitable resolution
- for (w, h) in v4l2ctl.list_resolutions(device_details['uri']):
+ for (w, h) in v4l2ctl.list_resolutions(device_details['path']):
if w > 300:
camera_config['width'] = w
camera_config['height'] = h
break
- camera_config['videodevice'] = device_details['uri']
+ camera_config['videodevice'] = device_details['path']
elif proto == 'motioneye':
camera_config['@proto'] = 'motioneye'
camera_config['@scheme'] = device_details['scheme']
camera_config['@host'] = device_details['host']
camera_config['@port'] = device_details['port']
- camera_config['@uri'] = device_details['uri']
+ camera_config['@path'] = device_details['path']
camera_config['@username'] = device_details['username']
camera_config['@password'] = device_details['password']
camera_config['@remote_camera_id'] = device_details['remote_camera_id']
for key, value in local_config.items():
remote_ui_config[key.replace('@', '')] = value
- # replace the real device URI with the remote camera URL
+ # replace the real device url with the remote camera path
remote_ui_config['device_url'] = remote.pretty_camera_url(local_config)
self.finish_json(remote_ui_config)
admin_username, admin_password = get_admin_credentials()
- uri = '/_relay_event/?event=%(event)s&thread_id=%(thread_id)s&_username=%(username)s' % {
+ path = '/_relay_event/?event=%(event)s&thread_id=%(thread_id)s&_username=%(username)s' % {
'username': admin_username,
'thread_id': options.thread_id,
'event': options.event}
- signature = utils.compute_signature('POST', uri, '', admin_password)
+ signature = utils.compute_signature('POST', path, '', admin_password)
- url = 'http://127.0.0.1:%(port)s' + uri + '&_signature=' + signature
+ url = 'http://127.0.0.1:%(port)s' + path + '&_signature=' + signature
url = url % {'port': settings.PORT}
try:
_DOUBLE_SLASH_REGEX = re.compile('//+')
-def _make_request(scheme, host, port, username, password, uri, method='GET', data=None, query=None, timeout=None):
- uri = _DOUBLE_SLASH_REGEX.sub('/', uri)
- url = '%(scheme)s://%(host)s%(port)s%(uri)s' % {
+def _make_request(scheme, host, port, username, password, path, method='GET', data=None, query=None, timeout=None):
+ path = _DOUBLE_SLASH_REGEX.sub('/', path)
+ url = '%(scheme)s://%(host)s%(port)s%(path)s' % {
'scheme': scheme,
'host': host,
'port': ':' + str(port) if port else '',
- 'uri': uri or ''}
+ 'path': path or ''}
query = dict(query or {})
query['_username'] = username or ''
scheme = local_config.get('@scheme', local_config.get('scheme')) or 'http'
host = local_config.get('@host', local_config.get('host'))
port = local_config.get('@port', local_config.get('port'))
- uri = local_config.get('@uri', local_config.get('uri')) or ''
+ path = local_config.get('@path', local_config.get('path')) or ''
url = scheme + '://' + host
if port and str(port) not in ['80', '443']:
url += ':' + str(port)
- if uri:
- url += uri
+ if path:
+ url += path
if url.endswith('/'):
url = url[:-1]
local_config.get('@port', local_config.get('port')),
local_config.get('@username', local_config.get('username')),
local_config.get('@password', local_config.get('password')),
- local_config.get('@uri', local_config.get('uri')) or '',
+ local_config.get('@path', local_config.get('path')) or '',
local_config.get('@remote_camera_id', local_config.get('remote_camera_id')))
def list(local_config, callback):
- scheme, host, port, username, password, uri, _ = _remote_params(local_config)
+ scheme, host, port, username, password, path, _ = _remote_params(local_config)
logging.debug('listing remote cameras on %(url)s' % {
'url': pretty_camera_url(local_config, camera=False)})
- request = _make_request(scheme, host, port, username, password, uri + '/config/list/')
+ request = _make_request(scheme, host, port, username, password, path + '/config/list/')
def on_response(response):
def make_camera_response(c):
def get_config(local_config, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('getting config for remote camera %(id)s on %(url)s' % {
'id': camera_id,
'url': pretty_camera_url(local_config)})
- request = _make_request(scheme, host, port, username, password, uri + '/config/%(id)s/get/' % {'id': camera_id})
+ request = _make_request(scheme, host, port, username, password, path + '/config/%(id)s/get/' % {'id': camera_id})
def on_response(response):
if response.error:
port = local_config.get('@port', local_config.get('port'))
username = local_config.get('@username', local_config.get('username'))
password = local_config.get('@password', local_config.get('password'))
- uri = local_config.get('@uri', local_config.get('uri')) or ''
+ path = local_config.get('@path', local_config.get('path')) or ''
camera_id = local_config.get('@remote_camera_id', local_config.get('remote_camera_id'))
logging.debug('setting config for remote camera %(id)s on %(url)s' % {
ui_config = json.dumps(ui_config)
- request = _make_request(scheme, host, port, username, password, uri + '/config/%(id)s/set/' % {'id': camera_id}, method='POST', data=ui_config)
+ request = _make_request(scheme, host, port, username, password, path + '/config/%(id)s/set/' % {'id': camera_id}, method='POST', data=ui_config)
def on_response(response):
if response.error:
def set_preview(local_config, controls, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('setting preview for remote camera %(id)s on %(url)s' % {
'id': camera_id,
data = json.dumps(controls)
- request = _make_request(scheme, host, port, username, password, uri + '/config/%(id)s/set_preview/' % {'id': camera_id}, method='POST', data=data)
+ request = _make_request(scheme, host, port, username, password, path + '/config/%(id)s/set_preview/' % {'id': camera_id}, method='POST', data=data)
def on_response(response):
if response.error:
def get_current_picture(local_config, width, height, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('getting current picture for remote camera %(id)s on %(url)s' % {
'id': camera_id,
if height:
query['height'] = str(height)
- request = _make_request(scheme, host, port, username, password, uri + '/picture/%(id)s/current/' % {'id': camera_id}, query=query)
+ request = _make_request(scheme, host, port, username, password, path + '/picture/%(id)s/current/' % {'id': camera_id}, query=query)
def on_response(response):
motion_detected = False
def list_media(local_config, media_type, prefix, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('getting media list for remote camera %(id)s on %(url)s' % {
'id': camera_id,
query['prefix'] = prefix
# timeout here is 10 times larger than usual - we expect a big delay when fetching the media list
- request = _make_request(scheme, host, port, username, password, uri + '/%(media_type)s/%(id)s/list/' % {
+ request = _make_request(scheme, host, port, username, password, path + '/%(media_type)s/%(id)s/list/' % {
'id': camera_id, 'media_type': media_type}, query=query, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
def get_media_content(local_config, filename, media_type, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('downloading file %(filename)s of remote camera %(id)s on %(url)s' % {
'filename': filename,
'id': camera_id,
'url': pretty_camera_url(local_config)})
- uri += '/%(media_type)s/%(id)s/download/%(filename)s' % {
+ path += '/%(media_type)s/%(id)s/download/%(filename)s' % {
'media_type': media_type,
'id': camera_id,
'filename': filename}
# timeout here is 10 times larger than usual - we expect a big delay when fetching the media list
- request = _make_request(scheme, host, port, username, password, uri, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT)
+ request = _make_request(scheme, host, port, username, password, path, timeout=10 * settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
if response.error:
def make_zipped_content(local_config, media_type, group, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('preparing zip file for group %(group)s of remote camera %(id)s on %(url)s' % {
'group': group,
'id': camera_id,
'url': pretty_camera_url(local_config)})
- prepare_uri = uri + '/%(media_type)s/%(id)s/zipped/%(group)s/' % {
+ prepare_path = path + '/%(media_type)s/%(id)s/zipped/%(group)s/' % {
'media_type': media_type,
'id': camera_id,
'group': group}
# timeout here is 100 times larger than usual - we expect a big delay
- request = _make_request(scheme, host, port, username, password, prepare_uri, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT)
+ request = _make_request(scheme, host, port, username, password, prepare_path, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
if response.error:
def get_zipped_content(local_config, media_type, key, group, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('downloading zip file for remote camera %(id)s on %(url)s' % {
'id': camera_id,
'url': pretty_camera_url(local_config)})
- request = _make_request(scheme, host, port, username, password, uri + '/%(media_type)s/%(id)s/zipped/%(group)s/?key=%(key)s' % {
+ request = _make_request(scheme, host, port, username, password, path + '/%(media_type)s/%(id)s/zipped/%(group)s/?key=%(key)s' % {
'media_type': media_type,
'group': group,
'id': camera_id,
def make_timelapse_movie(local_config, framerate, interval, group, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('making timelapse movie for group %(group)s of remote camera %(id)s with rate %(framerate)s/%(int)s on %(url)s' % {
'group': group,
'int': interval,
'url': pretty_camera_url(local_config)})
- uri += '/picture/%(id)s/timelapse/%(group)s/?interval=%(int)s&framerate=%(framerate)s' % {
+ path += '/picture/%(id)s/timelapse/%(group)s/?interval=%(int)s&framerate=%(framerate)s' % {
'id': camera_id,
'int': interval,
'framerate': framerate,
'group': group}
- request = _make_request(scheme, host, port, username, password, uri, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT)
+ request = _make_request(scheme, host, port, username, password, path, timeout=100 * settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
if response.error:
def check_timelapse_movie(local_config, group, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('checking timelapse movie status for remote camera %(id)s on %(url)s' % {
'id': camera_id,
'url': pretty_camera_url(local_config)})
- request = _make_request(scheme, host, port, username, password, uri + '/picture/%(id)s/timelapse/%(group)s/?check=true' % {
+ request = _make_request(scheme, host, port, username, password, path + '/picture/%(id)s/timelapse/%(group)s/?check=true' % {
'id': camera_id,
'group': group})
def get_timelapse_movie(local_config, key, group, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('downloading timelapse movie for remote camera %(id)s on %(url)s' % {
'id': camera_id,
'url': pretty_camera_url(local_config)})
- request = _make_request(scheme, host, port, username, password, uri + '/picture/%(id)s/timelapse/%(group)s/?key=%(key)s' % {
+ request = _make_request(scheme, host, port, username, password, path + '/picture/%(id)s/timelapse/%(group)s/?key=%(key)s' % {
'id': camera_id,
'group': group,
'key': key},
def get_media_preview(local_config, filename, media_type, width, height, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('getting file preview for %(filename)s of remote camera %(id)s on %(url)s' % {
'filename': filename,
'id': camera_id,
'url': pretty_camera_url(local_config)})
- uri += '/%(media_type)s/%(id)s/preview/%(filename)s' % {
+ path += '/%(media_type)s/%(id)s/preview/%(filename)s' % {
'media_type': media_type,
'id': camera_id,
'filename': filename}
if height:
query['height'] = str(height)
- request = _make_request(scheme, host, port, username, password, uri, query=query)
+ request = _make_request(scheme, host, port, username, password, path, query=query)
def on_response(response):
if response.error:
def del_media_content(local_config, filename, media_type, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('deleting file %(filename)s of remote camera %(id)s on %(url)s' % {
'filename': filename,
'id': camera_id,
'url': pretty_camera_url(local_config)})
- uri += '/%(media_type)s/%(id)s/delete/%(filename)s' % {
+ path += '/%(media_type)s/%(id)s/delete/%(filename)s' % {
'media_type': media_type,
'id': camera_id,
'filename': filename}
- request = _make_request(scheme, host, port, username, password, uri, method='POST', data='{}', timeout=settings.REMOTE_REQUEST_TIMEOUT)
+ request = _make_request(scheme, host, port, username, password, path, method='POST', data='{}', timeout=settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
if response.error:
def del_media_group(local_config, group, media_type, callback):
- scheme, host, port, username, password, uri, camera_id = _remote_params(local_config)
+ scheme, host, port, username, password, path, camera_id = _remote_params(local_config)
logging.debug('deleting group %(group)s of remote camera %(id)s on %(url)s' % {
'group': group,
'id': camera_id,
'url': pretty_camera_url(local_config)})
- uri += '/%(media_type)s/%(id)s/delete_all/%(group)s/' % {
+ path += '/%(media_type)s/%(id)s/delete_all/%(group)s/' % {
'media_type': media_type,
'id': camera_id,
'group': group}
- request = _make_request(scheme, host, port, username, password, uri, method='POST', data='{}', timeout=settings.REMOTE_REQUEST_TIMEOUT)
+ request = _make_request(scheme, host, port, username, password, path, method='POST', data='{}', timeout=settings.REMOTE_REQUEST_TIMEOUT)
def on_response(response):
if response.error:
log_method("%d %s %.2fms", handler.get_status(),
handler._request_summary(), request_time)
-application = Application(
- [
- (r'^/$', handlers.MainHandler),
- (r'^/config/main/(?P<op>set|get)/?$', handlers.ConfigHandler),
- (r'^/config/(?P<camera_id>\d+)/(?P<op>get|set|rem|set_preview)/?$', handlers.ConfigHandler),
- (r'^/config/(?P<op>add|list|backup|restore)/?$', handlers.ConfigHandler),
- (r'^/picture/(?P<camera_id>\d+)/(?P<op>current|list|frame)/?$', handlers.PictureHandler),
- (r'^/picture/(?P<camera_id>\d+)/(?P<op>download|preview|delete)/(?P<filename>.+?)/?$', handlers.PictureHandler),
- (r'^/picture/(?P<camera_id>\d+)/(?P<op>zipped|timelapse|delete_all)/(?P<group>.+?)/?$', handlers.PictureHandler),
- (r'^/movie/(?P<camera_id>\d+)/(?P<op>list)/?$', handlers.MovieHandler),
- (r'^/movie/(?P<camera_id>\d+)/(?P<op>download|preview|delete)/(?P<filename>.+?)/?$', handlers.MovieHandler),
- (r'^/movie/(?P<camera_id>\d+)/(?P<op>delete_all)/(?P<group>.+?)/?$', handlers.MovieHandler),
- (r'^/_relay_event/?$', handlers.RelayEventHandler),
- (r'^/log/(?P<name>\w+)/?$', handlers.LogHandler),
- (r'^/update/?$', handlers.UpdateHandler),
- (r'^/power/(?P<op>shutdown|reboot)/?$', handlers.PowerHandler),
- (r'^/version/?$', handlers.VersionHandler),
- (r'^/login/?$', handlers.LoginHandler),
- (r'^.*$', handlers.NotFoundHandler),
- ],
- debug=False,
- log_function=_log_request,
- static_path=settings.STATIC_PATH,
- static_url_prefix=settings.STATIC_URL
-)
-
-template.add_context('STATIC_URL', settings.STATIC_URL)
+handler_mapping = [
+ (r'^/$', handlers.MainHandler),
+ (r'^/config/main/(?P<op>set|get)/?$', handlers.ConfigHandler),
+ (r'^/config/(?P<camera_id>\d+)/(?P<op>get|set|rem|set_preview)/?$', handlers.ConfigHandler),
+ (r'^/config/(?P<op>add|list|backup|restore)/?$', handlers.ConfigHandler),
+ (r'^/picture/(?P<camera_id>\d+)/(?P<op>current|list|frame)/?$', handlers.PictureHandler),
+ (r'^/picture/(?P<camera_id>\d+)/(?P<op>download|preview|delete)/(?P<filename>.+?)/?$', handlers.PictureHandler),
+ (r'^/picture/(?P<camera_id>\d+)/(?P<op>zipped|timelapse|delete_all)/(?P<group>.+?)/?$', handlers.PictureHandler),
+ (r'^/movie/(?P<camera_id>\d+)/(?P<op>list)/?$', handlers.MovieHandler),
+ (r'^/movie/(?P<camera_id>\d+)/(?P<op>download|preview|delete)/(?P<filename>.+?)/?$', handlers.MovieHandler),
+ (r'^/movie/(?P<camera_id>\d+)/(?P<op>delete_all)/(?P<group>.+?)/?$', handlers.MovieHandler),
+ (r'^/_relay_event/?$', handlers.RelayEventHandler),
+ (r'^/log/(?P<name>\w+)/?$', handlers.LogHandler),
+ (r'^/update/?$', handlers.UpdateHandler),
+ (r'^/power/(?P<op>shutdown|reboot)/?$', handlers.PowerHandler),
+ (r'^/version/?$', handlers.VersionHandler),
+ (r'^/login/?$', handlers.LoginHandler),
+ (r'^.*$', handlers.NotFoundHandler),
+]
def configure_signals():
if settings.THUMBNAILER_INTERVAL:
start_thumbnailer()
+ template.add_context('static_path', settings.BASE_PATH + '/static/')
+
+ application = Application(handler_mapping, debug=False, log_function=_log_request,
+ static_path=settings.STATIC_PATH, static_url_prefix='/static/')
+
application.listen(settings.PORT, settings.LISTEN)
logging.info('server started')
# static files (.css, .js etc) are served at this root url;
# change this if you run motionEye behind a reverse proxy (e.g. nginx),
# and you want static files to be served directly by it
-STATIC_URL = '/static/'
+BASE_PATH = ''
# path to the configuration directory (must be writable by motionEye)
CONF_PATH = [sys.prefix, ''][sys.prefix == '/usr'] + '/etc/motioneye'
cameraFrameDiv[0].streamingServerResize = cameraFrameDiv.attr('streaming_server_resize') == 'True';
cameraFrameDiv[0].proto = cameraFrameDiv.attr('proto');
cameraFrameDiv[0].url = cameraFrameDiv.attr('url');
- progressImg.attr('src', staticUrl + 'img/camera-progress.gif');
+ progressImg.attr('src', staticPath + 'img/camera-progress.gif');
cameraProgress.addClass('visible');
cameraPlaceholder.css('opacity', '0');
}
var timestamp = new Date().getTime();
- var uri = baseUri + 'picture/' + cameraId + '/current/?_=' + timestamp;
+ var path = basePath + 'picture/' + cameraId + '/current/?_=' + timestamp;
if (cameraFrame.serverSideResize) {
- uri += '&width=' + img.width;
+ path += '&width=' + img.width;
}
- uri = addAuthParams('GET', uri);
- img.src = uri;
+ path = addAuthParams('GET', path);
+ img.src = path;
img.loading = 1;
cameraFrame.refreshDivider = 0;
var refreshInterval = 50; /* milliseconds */
var username = '';
var password = '';
-var baseUri = null;
+var basePath = null;
var signatureRegExp = new RegExp('[^a-zA-Z0-9/?_.=&{}\\[\\]":, _-]', 'g');
var initialConfigFetched = false; /* used to workaround browser extensions that trigger stupid change events */
return a.href;
}
-function qualifyUri(uri) {
- var url = qualifyUrl(uri);
+function qualifyPath(path) {
+ var url = qualifyUrl(path);
var pos = url.indexOf('//');
if (pos === -1) { /* not a full url */
return url;
return url.substring(pos);
}
-function computeSignature(method, uri, body) {
- uri = qualifyUri(uri);
+function computeSignature(method, path, body) {
+ path = qualifyPath(path);
- var parts = splitUrl(uri);
+ var parts = splitUrl(path);
var query = parts.params;
- var baseUrl = parts.baseUrl;
+ var path = parts.baseUrl;
+ path = '/' + path.substring(basePath.length);
/* sort query arguments alphabetically */
query = Object.keys(query).map(function (key) {return {key: key, value: decodeURIComponent(query[key])};});
query = query.filter(function (q) {return q.key !== '_signature';});
query.sortKey(function (q) {return q.key;});
query = query.map(function (q) {return q.key + '=' + encodeURIComponent(q.value);}).join('&');
- uri = baseUrl + '?' + query;
- uri = uri.replace(signatureRegExp, '-');
+ path = path + '?' + query;
+ path = path.replace(signatureRegExp, '-');
body = body && body.replace(signatureRegExp, '-');
var password = window.password.replace(signatureRegExp, '-');
- return sha1(method + ':' + uri + ':' + (body || '') + ':' + password).toLowerCase();
+ return sha1(method + ':' + path + ':' + (body || '') + ':' + password).toLowerCase();
}
function addAuthParams(method, url, body) {
$('#videoDeviceSwitch')[0].checked = dict['enabled']; markHideIfNull('enabled', 'videoDeviceSwitch');
$('#deviceNameEntry').val(dict['name']); markHideIfNull('name', 'deviceNameEntry');
- $('#deviceUriEntry').val(dict['device_url']); markHideIfNull('device_url', 'deviceUriEntry');
+ $('#deviceUrlEntry').val(dict['device_url']); markHideIfNull('device_url', 'deviceUrlEntry');
$('#deviceTypeEntry').val(prettyType); markHideIfNull(!prettyType, 'deviceTypeEntry');
$('#deviceTypeEntry')[0].proto = dict['proto'];
$('#lightSwitchDetectSwitch')[0].checked = dict['light_switch_detect']; markHideIfNull('light_switch_detect', 'lightSwitchDetectSwitch');
$('#streamingAuthModeSelect').val(dict['streaming_auth_mode']); markHideIfNull('streaming_auth_mode', 'streamingAuthModeSelect');
$('#streamingMotion')[0].checked = dict['streaming_motion']; markHideIfNull('streaming_motion', 'streamingMotion');
- var cameraUrl = location.protocol + '//' + location.host + '/picture/' + dict.id + '/';
+ var cameraUrl = location.protocol + '//' + location.host + basePath + 'picture/' + dict.id + '/';
var snapshotUrl = null;
var mjpgUrl = null;
inProgress = true;
/* replace the main page message with a progress indicator */
- $('div.add-camera-message').replaceWith('<img class="main-loading-progress" src="' + staticUrl + 'img/main-loading-progress.gif">');
+ $('div.add-camera-message').replaceWith('<img class="main-loading-progress" src="' + staticPath + 'img/main-loading-progress.gif">');
/* show the apply button progress indicator */
- $('#applyButton').html('<img class="apply-progress" src="' + staticUrl + 'img/apply-progress.gif">');
+ $('#applyButton').html('<img class="apply-progress" src="' + staticPath + 'img/apply-progress.gif">');
/* show the camera progress indicators */
if (cameraIds) {
}, 500);
}
-function downloadFile(uri) {
- uri = baseUri + uri;
+function downloadFile(path) {
+ path = basePath + path;
var url = window.location.href;
var parts = url.split('/');
- url = parts.slice(0, 3).join('/') + uri;
+ url = parts.slice(0, 3).join('/') + path;
url = addAuthParams('GET', url);
/* download the file by creating a temporary iframe */
$('body').append(frame);
}
-function uploadFile(uri, input, callback) {
+function uploadFile(path, input, callback) {
if (!window.FormData) {
showErrorMessage("Your browser doesn't implement this function!");s
callback();
var files = input[0].files;
formData.append('files', files[0], files[0].name);
- ajax('POST', uri, formData, callback);
+ ajax('POST', path, formData, callback);
}
refreshDisabled[cameraId]++;
});
- ajax('POST', baseUri + 'config/0/set/', pushConfigs, function (data) {
+ ajax('POST', basePath + 'config/0/set/', pushConfigs, function (data) {
affectedCameraIds.forEach(function (cameraId) {
refreshDisabled[cameraId]--;
});
if (data.reboot) {
var count = 0;
function checkServerReboot() {
- ajax('GET', baseUri + 'config/0/get/', null,
+ ajax('GET', basePath + 'config/0/get/', null,
function () {
window.location.reload(true);
},
function doShutDown() {
runConfirmDialog('Really shut down?', function () {
- ajax('POST', baseUri + 'power/shutdown/');
+ ajax('POST', basePath + 'power/shutdown/');
setTimeout(function () {
refreshInterval = 1000000;
showModalDialog('<div class="modal-progress"></div>');
function checkServer() {
- ajax('GET', baseUri, null,
+ ajax('GET', basePath, null,
function () {
setTimeout(checkServer, 1000);
},
function doReboot() {
runConfirmDialog('Really reboot?', function () {
- ajax('POST', baseUri + 'power/reboot/');
+ ajax('POST', basePath + 'power/reboot/');
setTimeout(function () {
refreshInterval = 1000000;
showModalDialog('<div class="modal-progress"></div>');
var shutDown = false;
function checkServer() {
- ajax('GET', baseUri, null,
+ ajax('GET', basePath, null,
function () {
if (!shutDown) {
setTimeout(checkServer, 1000);
}
beginProgress();
- ajax('POST', baseUri + 'config/' + cameraId + '/rem/', null, function (data) {
+ ajax('POST', basePath + 'config/' + cameraId + '/rem/', null, function (data) {
if (data == null || data.error) {
endProgress();
showErrorMessage(data && data.error);
}
showModalDialog('<div class="modal-progress"></div>');
- ajax('GET', baseUri + 'update/', null, function (data) {
+ ajax('GET', basePath + 'update/', null, function (data) {
if (data.update_version == null) {
runAlertDialog('motionEye is up to date (current version: ' + data.current_version + ')');
}
runConfirmDialog('New version available: ' + data.update_version + '. Update?', function () {
refreshInterval = 1000000;
showModalDialog('<div style="text-align: center;"><span>Updating. This may take a few minutes.</span><div class="modal-progress"></div></div>');
- ajax('POST', baseUri + 'update/?version=' + data.update_version, null, function () {
+ ajax('POST', basePath + 'update/?version=' + data.update_version, null, function () {
var count = 0;
function checkServer() {
- ajax('GET', baseUri + 'config/0/get/', null,
+ ajax('GET', basePath + 'config/0/get/', null,
function () {
runAlertDialog('motionEye was successfully updated!', function () {
window.location.reload(true);
setTimeout(function () {
showModalDialog('<div style="text-align: center;"><span>Restoring configuration...</span><div class="modal-progress"></div></div>');
- uploadFile(baseUri + 'config/restore/', fileInput, function (data) {
+ uploadFile(basePath + 'config/restore/', fileInput, function (data) {
if (data && data.ok) {
var count = 0;
function checkServer() {
- ajax('GET', baseUri + 'config/0/get/', null,
+ ajax('GET', basePath + 'config/0/get/', null,
function () {
runAlertDialog('The configuration has been restored!', function () {
window.location.reload(true);
function doDownloadZipped(cameraId, groupKey) {
showModalDialog('<div class="modal-progress"></div>', null, null, true);
- ajax('GET', baseUri + 'picture/' + cameraId + '/zipped/' + groupKey + '/', null, function (data) {
+ ajax('GET', basePath + 'picture/' + cameraId + '/zipped/' + groupKey + '/', null, function (data) {
if (data.error) {
hideModalDialog(); /* progress */
showErrorMessage(data.error);
});
}
-function doDeleteFile(uri, callback) {
+function doDeleteFile(path, callback) {
var url = window.location.href;
var parts = url.split('/');
- url = parts.slice(0, 3).join('/') + uri;
+ url = parts.slice(0, 3).join('/') + path;
runConfirmDialog('Really delete this file?', function () {
showModalDialog('<div class="modal-progress"></div>', null, null, true);
function doDeleteAllFiles(mediaType, cameraId, groupKey, callback) {
runConfirmDialog('Really delete all ' + mediaType + 's in ' + groupKey + '?', function () {
showModalDialog('<div class="modal-progress"></div>', null, null, true);
- ajax('POST', baseUri + mediaType + '/' + cameraId + '/delete_all/' + groupKey + '/', null, function (data) {
+ ajax('POST', basePath + mediaType + '/' + cameraId + '/delete_all/' + groupKey + '/', null, function (data) {
hideModalDialog(); /* progress */
hideModalDialog(); /* confirm */
function fetchCurrentConfig(onFetch) {
function fetchCameraList() {
/* fetch the camera list */
- ajax('GET', baseUri + 'config/list/', null, function (data) {
+ ajax('GET', basePath + 'config/list/', null, function (data) {
if (data == null || data.error) {
showErrorMessage(data && data.error);
data = {cameras: []};
}
/* add a progress indicator */
- $('div.page-container').append('<img class="main-loading-progress" src="' + staticUrl + 'img/main-loading-progress.gif">');
+ $('div.page-container').append('<img class="main-loading-progress" src="' + staticPath + 'img/main-loading-progress.gif">');
if (isAdmin()) {
/* fetch the main configuration */
- ajax('GET', baseUri + 'config/main/get/', null, function (data) {
+ ajax('GET', basePath + 'config/main/get/', null, function (data) {
if (data == null || data.error) {
showErrorMessage(data && data.error);
return;
function fetchCurrentCameraConfig(onFetch) {
var cameraId = $('#cameraSelect').val();
if (cameraId != null) {
- ajax('GET', baseUri + 'config/' + cameraId + '/get/?force=true', null, function (data) {
+ ajax('GET', basePath + 'config/' + cameraId + '/get/?force=true', null, function (data) {
if (data == null || data.error) {
showErrorMessage(data && data.error);
dict2CameraUi(null);
refreshDisabled[cameraId] |= 0;
refreshDisabled[cameraId]++;
- ajax('POST', baseUri + 'config/' + cameraId + '/set_preview/', data, function (data) {
+ ajax('POST', basePath + 'config/' + cameraId + '/set_preview/', data, function (data) {
refreshDisabled[cameraId]--;
if (data == null || data.error) {
$('body').append(tempFrame);
var form =
- $('<form action="' + baseUri + 'login/" target="temp" method="POST"><table class="login-dialog">' +
+ $('<form action="' + basePath + 'login/" target="temp" method="POST"><table class="login-dialog">' +
'<tr>' +
'<td class="login-dialog-error" colspan="100"></td>' +
'</tr>' +
var nextArrow = $('<div class="picture-dialog-next-arrow button mouse-effect" title="next picture"></div>');
content.append(nextArrow);
- var progressImg = $('<img class="picture-dialog-progress" src="' + staticUrl + 'img/modal-progress.gif">');
+ var progressImg = $('<img class="picture-dialog-progress" src="' + staticPath + 'img/modal-progress.gif">');
function updatePicture() {
var entry = entries[pos];
progressImg.css('left', (img.parent().width() - progressImg.width()) / 2);
progressImg.css('top', (img.parent().height() - progressImg.height()) / 2);
- img.attr('src', addAuthParams('GET', baseUri + mediaType + '/' + entry.cameraId + '/preview' + entry.path));
+ img.attr('src', addAuthParams('GET', basePath + mediaType + '/' + entry.cameraId + '/preview' + entry.path));
img.load(function () {
var aspectRatio = this.naturalWidth / this.naturalHeight;
var sizeWidth = width * width / aspectRatio;
else if (typeSelect.val() == 'netcam') {
usernameEntry.removeAttr('readonly');
- /* make sure there is one trailing slash so that
- * an URI can be detected */
+ /* make sure there is one trailing slash
+ * so that a path can be detected */
var url = urlEntry.val().trim();
var m = url.match(new RegExp('/', 'g'));
if (m && m.length < 3 && !url.endsWith('/')) {
else if (typeSelect.val() == 'mjpeg') {
usernameEntry.removeAttr('readonly');
- /* make sure there is one trailing slash so that
- * an URI can be detected */
+ /* make sure there is one trailing slash
+ * so that a path can be detected */
var url = urlEntry.val().trim();
var m = url.match(new RegExp('/', 'g'));
if (m && m.length < 3 && !url.endsWith('/')) {
var scheme = parts[0];
var index = parts[1].indexOf('/');
var host = null;
- var uri = '';
+ var path = '';
if (index >= 0) {
host = parts[1].substring(0, index);
- uri = parts[1].substring(index);
+ path = parts[1].substring(index);
}
else {
host = parts[1];
port = parts[1];
}
- if (uri == '') {
- uri = '/';
+ if (path == '') {
+ path = '/';
}
return {
scheme: scheme,
host: host,
port: port,
- uri: uri
+ path: path
};
}
function listCameras() {
- var progress = $('<div style="text-align: center; margin: 2px;"><img src="' + staticUrl + 'img/small-progress.gif"></div>');
+ var progress = $('<div style="text-align: center; margin: 2px;"><img src="' + staticPath + 'img/small-progress.gif"></div>');
addCameraSelect.html('');
addCameraSelect.hide();
cameraMsgLabel.html('');
- ajax('GET', baseUri + 'config/list/', data, function (data) {
+ ajax('GET', basePath + 'config/list/', data, function (data) {
progress.remove();
if (data == null || data.error) {
}
else { /* assuming v4l2 */
data.proto = 'v4l2';
- data.uri = addCameraSelect.val();
+ data.path = addCameraSelect.val();
}
/* add all extra attributes */
});
beginProgress();
- ajax('POST', baseUri + 'config/add/', data, function (data) {
+ ajax('POST', basePath + 'config/add/', data, function (data) {
endProgress();
if (data == null || data.error) {
noKeys: true
});
- var url = baseUri + 'picture/' + cameraId + '/timelapse/' + groupKey + '/';
+ var url = basePath + 'picture/' + cameraId + '/timelapse/' + groupKey + '/';
var data = {interval: intervalSelect.val(), framerate: framerateSlider.val()};
var first = true;
if (!entryDiv) {
entryDiv = $('<div class="media-list-entry"></div>');
- var previewImg = $('<img class="media-list-preview" src="' + staticUrl + 'img/modal-progress.gif"/>');
+ var previewImg = $('<img class="media-list-preview" src="' + staticPath + 'img/modal-progress.gif"/>');
entryDiv.append(previewImg);
- previewImg[0]._src = addAuthParams('GET', baseUri + mediaType + '/' + cameraId + '/preview' + entry.path + '?height=' + height);
+ previewImg[0]._src = addAuthParams('GET', basePath + mediaType + '/' + cameraId + '/preview' + entry.path + '?height=' + height);
var downloadButton = $('<div class="media-list-download-button button">Download</div>');
entryDiv.append(downloadButton);
});
deleteButton.click(function () {
- doDeleteFile(baseUri + mediaType + '/' + cameraId + '/delete' + entry.path, function () {
+ doDeleteFile(basePath + mediaType + '/' + cameraId + '/delete' + entry.path, function () {
entryDiv.remove();
entries.splice(i, 1); /* remove entry from group */
return addEntries();
}
- var previewImg = $('<img class="media-list-progress" src="' + staticUrl + 'img/modal-progress.gif"/>');
+ var previewImg = $('<img class="media-list-progress" src="' + staticPath + 'img/modal-progress.gif"/>');
mediaListDiv.append(previewImg);
- var url = baseUri + mediaType + '/' + cameraId + '/list/?prefix=' + (key || 'ungrouped');
+ var url = basePath + mediaType + '/' + cameraId + '/list/?prefix=' + (key || 'ungrouped');
ajax('GET', url, null, function (data) {
previewImg.remove();
showModalDialog('<div class="modal-progress"></div>');
/* fetch the media list */
- ajax('GET', baseUri + mediaType + '/' + cameraId + '/list/', null, function (data) {
+ ajax('GET', basePath + mediaType + '/' + cameraId + '/list/', null, function (data) {
if (data == null || data.error) {
hideModalDialog();
showErrorMessage(data && data.error);
'</div>' +
'</div>' +
'<div class="camera-container">' +
- '<div class="camera-placeholder"><img class="no-camera" src="' + staticUrl + 'img/no-camera.svg"></div>' +
+ '<div class="camera-placeholder"><img class="no-camera" src="' + staticPath + 'img/no-camera.svg"></div>' +
'<img class="camera">' +
'<div class="camera-progress"><img class="camera-progress"></div>' +
'</div>' +
cameraFrameDiv[0].refreshDivider = 0;
cameraFrameDiv[0].config = cameraConfig;
nameSpan.html(cameraConfig.name);
- progressImg.attr('src', staticUrl + 'img/camera-progress.gif');
+ progressImg.attr('src', staticPath + 'img/camera-progress.gif');
cameraProgress.click(function () {
doFullScreenCamera(cameraId);
fullScreenButton.click(function (cameraId) {
return function () {
- var url = baseUri + 'picture/' + cameraId + '/frame/';
- window.open(url, '_blank');
+ var path = basePath + 'picture/' + cameraId + '/frame/';
+ window.open(path, '_blank');
};
}(cameraId));
updateCameras(cameras);
}
else {
- ajax('GET', baseUri + 'config/list/', null, function (data) {
+ ajax('GET', basePath + 'config/list/', null, function (data) {
if (data == null || data.error) {
showErrorMessage(data && data.error);
return;
}
var timestamp = new Date().getTime();
- var uri = baseUri + 'picture/' + cameraId + '/current/?_=' + timestamp;
+ var path = basePath + 'picture/' + cameraId + '/current/?_=' + timestamp;
if (serverSideResize) {
- uri += '&width=' + img.width;
+ path += '&width=' + img.width;
}
- uri = addAuthParams('GET', uri);
+ path = addAuthParams('GET', path);
- img.src = uri;
+ img.src = path;
img.loading = 1;
}
/* startup function */
$(document).ready(function () {
- /* detect base uri */
+ /* detect base path */
if (frame) {
- baseUri = qualifyUri('../../../');
+ window.basePath = qualifyPath('../../../');
}
else {
- baseUri = splitUrl(qualifyUri('')).baseUrl;
+ window.basePath = splitUrl(qualifyPath('')).baseUrl;
/* restore the username from cookie */
window.username = getCookie('username');
initUI();
beginProgress();
- ajax('GET', baseUri + 'login/', null, function () {
+ ajax('GET', basePath + 'login/', null, function () {
if (!frame) {
fetchCurrentConfig(endProgress);
}
{% endblock %}
<title>{% block title %}{% endblock %}</title>
{% block style %}
- <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/jquery.timepicker.css" />
+ <link rel="stylesheet" type="text/css" href="{{static_path}}css/jquery.timepicker.css" />
<link rel="shortcut icon" href="/static/favicon.ico" />
<link rel="apple-touch-icon" href="/static/favicon.ico" />
{% endblock %}
{% block script %}
- <script type="text/javascript" src="{{STATIC_URL}}js/css-browser-selector.js"></script>
- <script type="text/javascript" src="{{STATIC_URL}}js/jquery.min.js"></script>
- <script type="text/javascript" src="{{STATIC_URL}}js/jquery.timepicker.min.js"></script>
- <script type="text/javascript" src="{{STATIC_URL}}js/jquery.mousewheel.js"></script>
-
+ <script type="text/javascript" src="{{static_path}}js/css-browser-selector.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/jquery.min.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/jquery.timepicker.min.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/jquery.mousewheel.js"></script>
+
<script type="text/javascript">
- var staticUrl = '{{STATIC_URL}}';
+ var staticPath = '{{static_path}}';
</script>
{% endblock %}
</head>
{% block style %}
{{super()}}
- <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/ui.css" />
- <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/main.css" />
+ <link rel="stylesheet" type="text/css" href="{{static_path}}css/ui.css" />
+ <link rel="stylesheet" type="text/css" href="{{static_path}}css/main.css" />
{% if frame %}
- <link rel="stylesheet" type="text/css" href="{{STATIC_URL}}css/frame.css" />
+ <link rel="stylesheet" type="text/css" href="{{static_path}}css/frame.css" />
{% endif %}
{% endblock %}
{% block script %}
{{super()}}
- <script type="text/javascript" src="{{STATIC_URL}}js/ui.js"></script>
- <script type="text/javascript" src="{{STATIC_URL}}js/main.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/ui.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/main.js"></script>
{% if frame %}
- <script type="text/javascript" src="{{STATIC_URL}}js/frame.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/frame.js"></script>
{% endif %}
<script type="text/javascript">
var adminUsername = '{{admin_username}}';
var frame = {% if frame %}true{% else %}false{% endif %};
- var baseUri = null;
var hasLocalCamSupport = {% if has_motion %}true{% else %}false{% endif %};
var hasNetCamSupport = {% if has_motion %}true{% else %}false{% endif %};
</script>
<div class="logo">
<a href="/">
<span class="logo">motionEye</span>
- <img class="logo" src="{{STATIC_URL}}img/motioneye-logo.svg">
+ <img class="logo" src="{{static_path}}img/motioneye-logo.svg">
</a>
</div>
</div>
</tr>
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">Camera Device</span></td>
- <td class="settings-item-value"><input type="text" class="styled device camera-config" id="deviceUriEntry" readonly="readonly"></td>
+ <td class="settings-item-value"><input type="text" class="styled device camera-config" id="deviceUrlEntry" readonly="readonly"></td>
</tr>
<tr class="settings-item advanced-setting">
<td class="settings-item-label"><span class="settings-item-label">Camera Type</span></td>
<div class="settings-progress"></div>
</div>
</div>
- <img class="background-logo" src="{{STATIC_URL}}img/motioneye-logo.svg" onmousedown="return false;">
+ <img class="background-logo" src="{{static_path}}img/motioneye-logo.svg" onmousedown="return false;">
<div class="page-container"></div>
<div class="footer">
<div class="copyright-note">copyright © Calin Crisan</div>
proto="{{camera_config['@proto']}}" url="{{camera_config['@url']}}">
<div class="camera-container">
- <div class="camera-placeholder"><img class="no-camera" src="{{STATIC_URL}}img/no-camera.svg"></div><img
+ <div class="camera-placeholder"><img class="no-camera" src="{{static_path}}img/no-camera.svg"></div><img
class="camera"><div class="camera-progress"><img class="camera-progress"></div>
</div>
</div>
var hostname = '{{hostname}}';
var version = '{{version}}';
</script>
- <script type="text/javascript" src="{{STATIC_URL}}js/version.js"></script>
+ <script type="text/javascript" src="{{static_path}}js/version.js"></script>
{% endblock %}
{% block body %}
data.setdefault('scheme', 'http')
data.setdefault('host', '127.0.0.1')
data.setdefault('port', '80')
- data.setdefault('uri', '')
+ data.setdefault('path', '')
data.setdefault('username', None)
data.setdefault('password', None)
- url = '%(scheme)s://%(host)s%(port)s%(uri)s' % {
+ url = '%(scheme)s://%(host)s%(port)s%(path)s' % {
'scheme': data['scheme'],
'host': data['host'],
'port': ':' + str(data['port']) if data['port'] else '',
- 'uri': data['uri'] or ''}
+ 'path': data['path'] or ''}
called = [False]
status_2xx = [False]
data.setdefault('scheme', 'rtsp')
data.setdefault('host', '127.0.0.1')
data['port'] = data.get('port') or '554'
- data.setdefault('uri', '')
+ data.setdefault('path', '')
data.setdefault('username', None)
data.setdefault('password', None)
- url = '%(scheme)s://%(host)s%(port)s%(uri)s' % {
+ url = '%(scheme)s://%(host)s%(port)s%(path)s' % {
'scheme': data['scheme'],
'host': data['host'],
'port': ':' + str(data['port']) if data['port'] else '',
- 'uri': data['uri'] or ''}
+ 'path': data['path'] or ''}
called = [False]
timeout = [None]
stream = connect()
-def compute_signature(method, uri, body, key):
- parts = list(urlparse.urlsplit(uri))
+def compute_signature(method, path, body, key):
+ parts = list(urlparse.urlsplit(path))
query = [q for q in urlparse.parse_qsl(parts[3], keep_blank_values=True) if (q[0] != '_signature')]
query.sort(key=lambda q: q[0])
# "safe" characters here are set to match the encodeURIComponent JavaScript counterpart
query = '&'.join([(q[0] + '=' + q[1]) for q in query])
parts[0] = parts[1] = ''
parts[3] = query
- uri = urlparse.urlunsplit(parts)
- uri = _SIGNATURE_REGEX.sub('-', uri)
+ path = urlparse.urlunsplit(parts)
+ path = _SIGNATURE_REGEX.sub('-', path)
key = _SIGNATURE_REGEX.sub('-', key)
if body and body.startswith('---'):
body = body and _SIGNATURE_REGEX.sub('-', body.decode('utf8'))
- return hashlib.sha1('%s:%s:%s:%s' % (method, uri, body or '', key)).hexdigest().lower()
+ return hashlib.sha1('%s:%s:%s:%s' % (method, path, body or '', key)).hexdigest().lower()
def build_basic_header(username, password):
last_nonce = nonce
- base = 'username="%s", realm="%s", nonce="%s", uri="%s", ' \
+ base = 'username="%s", realm="%s", nonce="%s", path="%s", ' \
'response="%s"' % (username, realm, nonce, path, respdig)
if opaque:
base += ', opaque="%s"' % opaque