|
Orion Poplawski |
65d4a76 |
diff -ur ipython-2.4.1/IPython/html/base/handlers.py ipython/IPython/html/base/handlers.py
|
|
Orion Poplawski |
65d4a76 |
--- ipython-2.4.1/IPython/html/base/handlers.py 2015-02-09 15:59:57.000000000 -0700
|
|
Orion Poplawski |
65d4a76 |
+++ ipython/IPython/html/base/handlers.py 2015-07-16 09:08:21.874322394 -0600
|
|
Orion Poplawski |
65d4a76 |
@@ -29,6 +29,10 @@
|
|
Orion Poplawski |
65d4a76 |
from http.client import responses
|
|
Orion Poplawski |
65d4a76 |
except ImportError:
|
|
Orion Poplawski |
65d4a76 |
from httplib import responses
|
|
Orion Poplawski |
65d4a76 |
+try:
|
|
Orion Poplawski |
65d4a76 |
+ from urllib.parse import urlparse # Py 3
|
|
Orion Poplawski |
65d4a76 |
+except ImportError:
|
|
Orion Poplawski |
65d4a76 |
+ from urlparse import urlparse # Py 2
|
|
Orion Poplawski |
65d4a76 |
|
|
Orion Poplawski |
65d4a76 |
from jinja2 import TemplateNotFound
|
|
Orion Poplawski |
65d4a76 |
from tornado import web
|
|
Orion Poplawski |
65d4a76 |
@@ -208,6 +212,50 @@
|
|
Orion Poplawski |
65d4a76 |
origin = self.request.headers.get("Sec-Websocket-Origin", None)
|
|
Orion Poplawski |
65d4a76 |
return origin
|
|
Orion Poplawski |
65d4a76 |
|
|
Orion Poplawski |
65d4a76 |
+ def check_origin_api(self):
|
|
Orion Poplawski |
65d4a76 |
+ """Check Origin for cross-site API requests.
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ Copied from WebSocket with changes:
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ - allow unspecified host/origin (e.g. scripts)
|
|
Orion Poplawski |
65d4a76 |
+ """
|
|
Orion Poplawski |
65d4a76 |
+ if self.allow_origin == '*':
|
|
Orion Poplawski |
65d4a76 |
+ return True
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ host = self.request.headers.get("Host")
|
|
Orion Poplawski |
65d4a76 |
+ origin = self.request.headers.get("Origin")
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ # If no header is provided, assume it comes from a script/curl.
|
|
Orion Poplawski |
65d4a76 |
+ # We are only concerned with cross-site browser stuff here.
|
|
Orion Poplawski |
65d4a76 |
+ if origin is None or host is None:
|
|
Orion Poplawski |
65d4a76 |
+ return True
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ origin = origin.lower()
|
|
Orion Poplawski |
65d4a76 |
+ origin_host = urlparse(origin).netloc
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ # OK if origin matches host
|
|
Orion Poplawski |
65d4a76 |
+ if origin_host == host:
|
|
Orion Poplawski |
65d4a76 |
+ return True
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ # Check CORS headers
|
|
Orion Poplawski |
65d4a76 |
+ if self.allow_origin:
|
|
Orion Poplawski |
65d4a76 |
+ allow = self.allow_origin == origin
|
|
Orion Poplawski |
65d4a76 |
+ elif self.allow_origin_pat:
|
|
Orion Poplawski |
65d4a76 |
+ allow = bool(self.allow_origin_pat.match(origin))
|
|
Orion Poplawski |
65d4a76 |
+ else:
|
|
Orion Poplawski |
65d4a76 |
+ # No CORS headers deny the request
|
|
Orion Poplawski |
65d4a76 |
+ allow = False
|
|
Orion Poplawski |
65d4a76 |
+ if not allow:
|
|
Orion Poplawski |
65d4a76 |
+ self.log.warn("Blocking Cross Origin API request. Origin: %s, Host: %s",
|
|
Orion Poplawski |
65d4a76 |
+ origin, host,
|
|
Orion Poplawski |
65d4a76 |
+ )
|
|
Orion Poplawski |
65d4a76 |
+ return allow
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
+ def prepare(self):
|
|
Orion Poplawski |
65d4a76 |
+ if not self.check_origin_api():
|
|
Orion Poplawski |
65d4a76 |
+ raise web.HTTPError(404)
|
|
Orion Poplawski |
65d4a76 |
+ return super(IPythonHandler, self).prepare()
|
|
Orion Poplawski |
65d4a76 |
+
|
|
Orion Poplawski |
65d4a76 |
#---------------------------------------------------------------
|
|
Orion Poplawski |
65d4a76 |
# template rendering
|
|
Orion Poplawski |
65d4a76 |
#---------------------------------------------------------------
|
|
Orion Poplawski |
65d4a76 |
@@ -339,6 +387,7 @@
|
|
Orion Poplawski |
65d4a76 |
message = e.log_message
|
|
Orion Poplawski |
65d4a76 |
self.log.warn(message)
|
|
Orion Poplawski |
65d4a76 |
self.set_status(e.status_code)
|
|
Orion Poplawski |
65d4a76 |
+ self.set_header('Content-Type', 'application/json')
|
|
Orion Poplawski |
65d4a76 |
self.finish(json.dumps(dict(message=message)))
|
|
Orion Poplawski |
65d4a76 |
except Exception:
|
|
Orion Poplawski |
65d4a76 |
self.log.error("Unhandled error in API request", exc_info=True)
|
|
Orion Poplawski |
65d4a76 |
@@ -348,6 +397,7 @@
|
|
Orion Poplawski |
65d4a76 |
self.set_status(status)
|
|
Orion Poplawski |
65d4a76 |
tb_text = ''.join(traceback.format_exception(t, value, tb))
|
|
Orion Poplawski |
65d4a76 |
reply = dict(message=message, traceback=tb_text)
|
|
Orion Poplawski |
65d4a76 |
+ self.set_header('Content-Type', 'application/json')
|
|
Orion Poplawski |
65d4a76 |
self.finish(json.dumps(reply))
|
|
Orion Poplawski |
65d4a76 |
else:
|
|
Orion Poplawski |
65d4a76 |
return result
|