]> www.vanbest.org Git - motioneye-debian/commitdiff
major URL refactoring; running behind a reverse-proxy works now
authorCalin Crisan <ccrisan@gmail.com>
Tue, 15 Sep 2015 19:54:45 +0000 (22:54 +0300)
committerCalin Crisan <ccrisan@gmail.com>
Tue, 15 Sep 2015 20:00:54 +0000 (23:00 +0300)
14 files changed:
extra/motioneye.conf.sample
motioneye/__init__.py
motioneye/config.py
motioneye/handlers.py
motioneye/relayevent.py
motioneye/remote.py
motioneye/server.py
motioneye/settings.py
motioneye/static/js/frame.js
motioneye/static/js/main.js
motioneye/templates/base.html
motioneye/templates/main.html
motioneye/templates/version.html
motioneye/utils.py

index aff425bf178e7ae7ce5a85cf2f3cc3b0960d8029..79503c5984bfe119d9fd96164161e72d311e4491 100644 (file)
@@ -1,8 +1,8 @@
 
-# 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
index b185f8e5842cbadf80462485c9a82c54f5728a4a..511cacd66fb8eb523a7cc98c08e669033bce1aea 100644 (file)
@@ -1,2 +1,2 @@
 
-VERSION = "0.27.2"
+VERSION = "0.27.2-git"
index bc953a37b557d483f35f747f6449a785fe35533e..1160554d96f792e5e48c6b23f1b3932dcf28f7d6 100644 (file)
@@ -462,7 +462,7 @@ def add_camera(device_details):
             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()
@@ -477,20 +477,20 @@ def add_camera(device_details):
     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']
index 9772f2b61bbf24502efe4bac5da5ecad9fc2183a..0215b40da4932fae0064b1e3a1928fd15c2c779a 100644 (file)
@@ -226,7 +226,7 @@ class ConfigHandler(BaseHandler):
                     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)
                 
index 166287b55f1b3333f10dd8ff17ac976db9efdbc2..f22dd930cb635084b62fa88f9bfbf9fe04c003d6 100644 (file)
@@ -107,14 +107,14 @@ def main(parser, args):
     
     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:
index 374e410f52652ecf26e02b92b5f94a37b4eed165..9533cbc015823f4d1e34a81c8b671e92fd096b8e 100644 (file)
@@ -28,13 +28,13 @@ import utils
 _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 ''
@@ -78,14 +78,14 @@ def pretty_camera_url(local_config, camera=True):
     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]
@@ -107,17 +107,17 @@ def _remote_params(local_config):
             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):
@@ -156,13 +156,13 @@ def list(local_config, callback):
     
 
 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:
@@ -198,7 +198,7 @@ def set_config(local_config, ui_config, callback):
     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' % {
@@ -207,7 +207,7 @@ def set_config(local_config, ui_config, callback):
     
     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:
@@ -225,7 +225,7 @@ def set_config(local_config, ui_config, callback):
 
 
 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,
@@ -233,7 +233,7 @@ def set_preview(local_config, controls, callback):
     
     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:
@@ -251,7 +251,7 @@ def set_preview(local_config, controls, callback):
 
 
 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,
@@ -265,7 +265,7 @@ def get_current_picture(local_config, width, height, callback):
     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
@@ -292,7 +292,7 @@ def get_current_picture(local_config, width, height, callback):
 
 
 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,
@@ -303,7 +303,7 @@ def list_media(local_config, media_type, prefix, callback):
         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):
@@ -332,20 +332,20 @@ def list_media(local_config, media_type, prefix, callback):
 
 
 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:
@@ -364,20 +364,20 @@ def get_media_content(local_config, filename, media_type, callback):
 
 
 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:
@@ -406,13 +406,13 @@ def make_zipped_content(local_config, media_type, group, callback):
 
 
 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,
@@ -439,7 +439,7 @@ def get_zipped_content(local_config, media_type, key, group, callback):
 
 
 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,
@@ -448,13 +448,13 @@ def make_timelapse_movie(local_config, framerate, interval, group, callback):
             '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:
@@ -485,13 +485,13 @@ def make_timelapse_movie(local_config, framerate, interval, group, callback):
 
 
 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})
     
@@ -521,13 +521,13 @@ def check_timelapse_movie(local_config, group, callback):
 
 
 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},
@@ -553,14 +553,14 @@ def get_timelapse_movie(local_config, key, group, callback):
 
 
 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}
@@ -573,7 +573,7 @@ def get_media_preview(local_config, filename, media_type, width, height, callbac
     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:
@@ -592,19 +592,19 @@ def get_media_preview(local_config, filename, media_type, width, height, callbac
 
 
 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:
@@ -623,19 +623,19 @@ def del_media_content(local_config, filename, media_type, callback):
 
 
 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:
index 3de3ce6e1dee95c0c1d4193488ecc52804a56c18..cfa29145228172defb82c10a36588208eaf88eb4 100644 (file)
@@ -158,33 +158,25 @@ def _log_request(handler):
     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():
@@ -376,6 +368,11 @@ def run():
     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')
     
index 82e059e1ed672ba29e15965b88b1d33f50447cd2..64a1911c626f7029cd475bcf916090a86f6912f7 100644 (file)
@@ -17,7 +17,7 @@ STATIC_PATH = os.path.join(PROJECT_PATH, 'static')
 # 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'
index 276e100d72da89d56cb4899007b401fd44028468..c61475cdb10522cd826fbfb8b633a3021730add5 100644 (file)
@@ -18,7 +18,7 @@ function setupCameraFrame() {
     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');
@@ -124,13 +124,13 @@ function refreshCameraFrame() {
             }
             
             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;
index ebaca5b4eb944b645312f131e03d79e620912546..32ba3b16a22f8ae4c116eb1181596f3c6472fdba 100644 (file)
@@ -7,7 +7,7 @@ var inProgress = false;
 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 */
 
@@ -124,8 +124,8 @@ function qualifyUrl(url) {
     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;
@@ -140,24 +140,25 @@ function qualifyUri(uri) {
     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) {
@@ -1459,7 +1460,7 @@ function dict2CameraUi(dict) {
     
     $('#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');
@@ -1550,7 +1551,7 @@ function dict2CameraUi(dict) {
     $('#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;
@@ -1720,10 +1721,10 @@ function beginProgress(cameraIds) {
     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) {
@@ -1765,12 +1766,12 @@ function endProgress() {
     }, 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 */
@@ -1779,7 +1780,7 @@ function downloadFile(uri) {
     $('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();
@@ -1789,7 +1790,7 @@ function uploadFile(uri, input, callback) {
     var files = input[0].files;
     formData.append('files', files[0], files[0].name);
 
-    ajax('POST', uri, formData, callback);
+    ajax('POST', path, formData, callback);
 }
 
 
@@ -1867,7 +1868,7 @@ function doApply() {
             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]--;
             });
@@ -1881,7 +1882,7 @@ function doApply() {
             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);
                         },
@@ -1937,13 +1938,13 @@ function doApply() {
 
 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);
                     },
@@ -1964,14 +1965,14 @@ function doShutDown() {
 
 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);
@@ -2016,7 +2017,7 @@ function doRemCamera() {
         }
 
         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);
@@ -2034,7 +2035,7 @@ function doUpdate() {
     }
     
     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 + ')');
         }
@@ -2042,10 +2043,10 @@ function doUpdate() {
             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);
@@ -2131,11 +2132,11 @@ function doRestore() {
 
             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);
@@ -2176,7 +2177,7 @@ function doRestore() {
 
 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);
@@ -2188,10 +2189,10 @@ function doDownloadZipped(cameraId, groupKey) {
     });
 }
 
-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);
@@ -2216,7 +2217,7 @@ function doDeleteFile(uri, callback) {
 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 */
             
@@ -2240,7 +2241,7 @@ function doDeleteAllFiles(mediaType, cameraId, groupKey, callback) {
 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: []};
@@ -2306,11 +2307,11 @@ function fetchCurrentConfig(onFetch) {
     }
  
     /* 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;
@@ -2328,7 +2329,7 @@ function fetchCurrentConfig(onFetch) {
 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);
@@ -2421,7 +2422,7 @@ function pushPreview(control) {
     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) {
@@ -2494,7 +2495,7 @@ function runLoginDialog(retry) {
     $('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>' +
@@ -2559,7 +2560,7 @@ function runPictureDialog(entries, pos, mediaType) {
     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];
@@ -2579,7 +2580,7 @@ function runPictureDialog(entries, pos, mediaType) {
         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;
@@ -2737,8 +2738,8 @@ function runAddCameraDialog() {
         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('/')) {
@@ -2753,8 +2754,8 @@ function runAddCameraDialog() {
         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('/')) {
@@ -2819,10 +2820,10 @@ function runAddCameraDialog() {
         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];
@@ -2835,20 +2836,20 @@ function runAddCameraDialog() {
             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();
@@ -2865,7 +2866,7 @@ function runAddCameraDialog() {
         
         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) {
@@ -2945,7 +2946,7 @@ function runAddCameraDialog() {
             }
             else { /* assuming v4l2 */
                 data.proto = 'v4l2';
-                data.uri = addCameraSelect.val();
+                data.path = addCameraSelect.val();
             }
             
             /* add all extra attributes */
@@ -2956,7 +2957,7 @@ function runAddCameraDialog() {
             });
 
             beginProgress();
-            ajax('POST', baseUri + 'config/add/', data, function (data) {
+            ajax('POST', basePath + 'config/add/', data, function (data) {
                 endProgress();
 
                 if (data == null || data.error) {
@@ -3044,7 +3045,7 @@ function runTimelapseDialog(cameraId, groupKey, group) {
                 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;
             
@@ -3158,9 +3159,9 @@ function runMediaDialog(cameraId, mediaType) {
                 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);
@@ -3182,7 +3183,7 @@ function runMediaDialog(cameraId, mediaType) {
                     });
                     
                     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 */
 
@@ -3231,10 +3232,10 @@ function runMediaDialog(cameraId, mediaType) {
             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();
             
@@ -3367,7 +3368,7 @@ function runMediaDialog(cameraId, mediaType) {
     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);
@@ -3508,7 +3509,7 @@ function addCameraFrameUi(cameraConfig) {
                     '</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>' +
@@ -3539,7 +3540,7 @@ function addCameraFrameUi(cameraConfig) {
     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);
@@ -3589,8 +3590,8 @@ function addCameraFrameUi(cameraConfig) {
     
     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));
     
@@ -3677,7 +3678,7 @@ function recreateCameraFrames(cameras) {
         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;
@@ -3794,14 +3795,14 @@ function refreshCameraFrames() {
         }
         
         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;
     }
 
@@ -3874,13 +3875,13 @@ function checkCameraErrors() {
     /* 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');
@@ -3917,7 +3918,7 @@ $(document).ready(function () {
     initUI();
     beginProgress();
     
-    ajax('GET', baseUri + 'login/', null, function () {
+    ajax('GET', basePath + 'login/', null, function () {
         if (!frame) {
             fetchCurrentConfig(endProgress);
         }
index 6679b8dbb21ab4efb6e7ccaef6e58d5d11cc898e..5d3d47e52632b7c94dc1875a4d84fabe47255ce0 100644 (file)
         {% 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>
index 393ab5172ee9090b9258c3a8c9edb11b416b2866..1349c2d6528316ad777de570abaaa0b805d92752 100644 (file)
 
 {% 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>
@@ -89,7 +88,7 @@
             <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 &copy; 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>
index 3c7a8f8c6dd048e5ba8ed616325ca69ee181fe9c..d3a9249833a58a304f19c852af67a093a7636cd2 100644 (file)
@@ -6,7 +6,7 @@
         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 %}
index a3fe0b8bf9550653402af934e3ac754388efa26f..f88d2de3d4b5bf9e6f9b689708e97c1d05832185 100644 (file)
@@ -336,15 +336,15 @@ def test_mjpeg_url(data, auth_modes, allow_jpeg, callback):
     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]
@@ -414,15 +414,15 @@ def test_rtsp_url(data, callback):
     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]
@@ -563,8 +563,8 @@ def test_rtsp_url(data, callback):
     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
@@ -572,8 +572,8 @@ def compute_signature(method, uri, body, key):
     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('---'):
@@ -581,7 +581,7 @@ def compute_signature(method, uri, body, key):
 
     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):
@@ -664,7 +664,7 @@ def build_digest_header(method, url, username, password, state):
 
     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