2014-02-07 15:00:50 -06:00
|
|
|
import simplejson
|
2014-04-19 04:48:54 -05:00
|
|
|
import mimetypes
|
|
|
|
import urllib2
|
2014-04-19 10:54:51 -05:00
|
|
|
import socket
|
|
|
|
|
|
|
|
from urlparse import urlparse
|
2014-02-07 15:00:50 -06:00
|
|
|
|
2012-11-20 03:47:19 -06:00
|
|
|
from django.views.generic import TemplateView
|
2014-06-19 07:39:45 -05:00
|
|
|
from django.contrib.auth import get_user_model
|
2014-02-07 15:00:50 -06:00
|
|
|
from django.views.generic import DetailView, View
|
2012-12-16 08:10:00 -06:00
|
|
|
from django.db.models import Q
|
2013-02-02 09:12:40 -06:00
|
|
|
from django.contrib.gis.measure import D
|
2013-02-12 10:34:33 -06:00
|
|
|
from django.conf import settings
|
|
|
|
from django.core.paginator import Paginator, EmptyPage, PageNotAnInteger
|
2014-04-19 05:28:24 -05:00
|
|
|
from django.http import HttpResponse, HttpResponseBadRequest
|
2014-02-10 14:37:12 -06:00
|
|
|
from django.utils.translation import ugettext as _
|
|
|
|
from django.core.urlresolvers import reverse
|
2014-05-01 16:51:38 -05:00
|
|
|
from django.db.models.sql.where import ExtraWhere, OR
|
|
|
|
from pgindex import search as pg_search
|
2012-11-20 03:47:19 -06:00
|
|
|
|
2012-12-22 13:32:11 -06:00
|
|
|
from leaflet_storage.models import Map
|
2013-02-02 09:12:40 -06:00
|
|
|
from leaflet_storage.forms import DEFAULT_CENTER
|
2012-11-20 03:47:19 -06:00
|
|
|
|
2014-06-19 07:39:45 -05:00
|
|
|
User = get_user_model()
|
|
|
|
|
2012-11-20 03:47:19 -06:00
|
|
|
|
2013-02-12 10:34:33 -06:00
|
|
|
class PaginatorMixin(object):
|
|
|
|
per_page = 5
|
|
|
|
|
|
|
|
def paginate(self, qs):
|
|
|
|
paginator = Paginator(qs, self.per_page)
|
|
|
|
page = self.request.GET.get('p')
|
|
|
|
try:
|
|
|
|
qs = paginator.page(page)
|
|
|
|
except PageNotAnInteger:
|
|
|
|
# If page is not an integer, deliver first page.
|
|
|
|
qs = paginator.page(1)
|
|
|
|
except EmptyPage:
|
|
|
|
# If page is out of range (e.g. 9999), deliver last page of results.
|
|
|
|
qs = paginator.page(paginator.num_pages)
|
|
|
|
return qs
|
|
|
|
|
|
|
|
|
|
|
|
class Home(TemplateView, PaginatorMixin):
|
2013-01-02 08:49:20 -06:00
|
|
|
template_name = "umap/home.html"
|
2012-12-22 13:32:11 -06:00
|
|
|
list_template_name = "leaflet_storage/map_list.html"
|
2012-11-20 03:47:19 -06:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2014-09-09 10:43:28 -05:00
|
|
|
qs = Map.public
|
2014-09-09 12:13:11 -05:00
|
|
|
if not 'spatialite' in settings.DATABASES['default']['ENGINE']:
|
2014-09-09 10:43:28 -05:00
|
|
|
# Unsupported query type for sqlite.
|
|
|
|
qs = qs.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1)))
|
2013-02-12 10:34:33 -06:00
|
|
|
demo_map = None
|
|
|
|
if hasattr(settings, "UMAP_DEMO_PK"):
|
|
|
|
try:
|
2014-01-09 16:49:53 -06:00
|
|
|
demo_map = Map.public.get(pk=settings.UMAP_DEMO_PK)
|
2013-02-12 10:34:33 -06:00
|
|
|
except Map.DoesNotExist:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
qs = qs.exclude(id=demo_map.pk)
|
2014-02-07 15:00:50 -06:00
|
|
|
showcase_map = None
|
|
|
|
if hasattr(settings, "UMAP_SHOWCASE_PK"):
|
|
|
|
try:
|
|
|
|
showcase_map = Map.public.get(pk=settings.UMAP_SHOWCASE_PK)
|
|
|
|
except Map.DoesNotExist:
|
|
|
|
pass
|
|
|
|
else:
|
|
|
|
qs = qs.exclude(id=showcase_map.pk)
|
2013-02-12 10:34:33 -06:00
|
|
|
maps = qs.order_by('-modified_at')[:50]
|
|
|
|
maps = self.paginate(maps)
|
|
|
|
|
2012-11-20 03:47:19 -06:00
|
|
|
return {
|
2012-12-12 06:13:14 -06:00
|
|
|
"maps": maps,
|
2013-05-01 17:54:40 -05:00
|
|
|
"demo_map": demo_map,
|
2014-02-07 15:00:50 -06:00
|
|
|
"showcase_map": showcase_map,
|
2013-05-01 17:54:40 -05:00
|
|
|
"DEMO_SITE": settings.UMAP_DEMO_SITE
|
2012-11-20 03:47:19 -06:00
|
|
|
}
|
|
|
|
|
2012-12-07 06:40:57 -06:00
|
|
|
def get_template_names(self):
|
|
|
|
"""
|
|
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
|
|
"""
|
|
|
|
if self.request.is_ajax():
|
|
|
|
return [self.list_template_name]
|
|
|
|
else:
|
|
|
|
return [self.template_name]
|
|
|
|
|
2012-11-20 03:47:19 -06:00
|
|
|
home = Home.as_view()
|
2012-12-11 13:04:03 -06:00
|
|
|
|
|
|
|
|
2013-02-12 10:34:33 -06:00
|
|
|
class About(Home):
|
|
|
|
|
|
|
|
template_name = "umap/about.html"
|
|
|
|
|
|
|
|
about = About.as_view()
|
|
|
|
|
|
|
|
|
|
|
|
class UserMaps(DetailView, PaginatorMixin):
|
2012-12-11 13:04:03 -06:00
|
|
|
model = User
|
|
|
|
slug_url_kwarg = 'username'
|
|
|
|
slug_field = 'username'
|
2012-12-22 13:32:11 -06:00
|
|
|
list_template_name = "leaflet_storage/map_list.html"
|
2012-12-11 13:04:03 -06:00
|
|
|
context_object_name = "current_user"
|
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2014-01-09 16:49:53 -06:00
|
|
|
manager = Map.objects if self.request.user == self.object else Map.public
|
2014-04-28 09:13:28 -05:00
|
|
|
maps = manager.filter(Q(owner=self.object) | Q(editors=self.object)).distinct().order_by('-modified_at')[:50]
|
2013-02-12 10:34:33 -06:00
|
|
|
maps = self.paginate(maps)
|
2012-12-11 13:04:03 -06:00
|
|
|
kwargs.update({
|
|
|
|
"maps": maps
|
|
|
|
})
|
|
|
|
return super(UserMaps, self).get_context_data(**kwargs)
|
|
|
|
|
|
|
|
def get_template_names(self):
|
|
|
|
"""
|
|
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
|
|
"""
|
|
|
|
if self.request.is_ajax():
|
|
|
|
return [self.list_template_name]
|
|
|
|
else:
|
|
|
|
return super(UserMaps, self).get_template_names()
|
|
|
|
|
|
|
|
user_maps = UserMaps.as_view()
|
2012-12-16 08:10:00 -06:00
|
|
|
|
|
|
|
|
2013-02-12 10:34:33 -06:00
|
|
|
class Search(TemplateView, PaginatorMixin):
|
2013-01-02 08:49:20 -06:00
|
|
|
template_name = "umap/search.html"
|
2012-12-22 13:32:11 -06:00
|
|
|
list_template_name = "leaflet_storage/map_list.html"
|
2012-12-16 08:10:00 -06:00
|
|
|
|
|
|
|
def get_context_data(self, **kwargs):
|
2013-02-12 10:34:33 -06:00
|
|
|
q = self.request.GET.get('q')
|
2014-05-01 16:51:38 -05:00
|
|
|
results = []
|
2013-02-12 10:34:33 -06:00
|
|
|
if q:
|
2014-05-01 16:51:38 -05:00
|
|
|
results = pg_search(q)
|
|
|
|
if getattr(settings, 'UMAP_USE_UNACCENT', False):
|
|
|
|
# Add unaccent support
|
|
|
|
results.query.where.add(ExtraWhere(("ts @@ plainto_tsquery('simple', unaccent(%s))", ), [q, ]), OR)
|
|
|
|
results = results.order_by('-rank', '-start_publish')
|
|
|
|
results = self.paginate(results)
|
|
|
|
results.object_list = [Map.objects.get(pk=i.obj_pk) for i in results]
|
2012-12-16 08:10:00 -06:00
|
|
|
kwargs.update({
|
2014-05-01 16:51:38 -05:00
|
|
|
'maps': results,
|
2012-12-16 08:10:00 -06:00
|
|
|
'q': q
|
2013-05-01 06:49:24 -05:00
|
|
|
})
|
2012-12-16 08:10:00 -06:00
|
|
|
return kwargs
|
|
|
|
|
|
|
|
def get_template_names(self):
|
|
|
|
"""
|
|
|
|
Dispatch template according to the kind of request: ajax or normal.
|
|
|
|
"""
|
|
|
|
if self.request.is_ajax():
|
|
|
|
return [self.list_template_name]
|
|
|
|
else:
|
|
|
|
return super(Search, self).get_template_names()
|
|
|
|
|
|
|
|
search = Search.as_view()
|
2014-02-07 15:00:50 -06:00
|
|
|
|
|
|
|
|
|
|
|
class MapsShowCase(View):
|
|
|
|
|
2014-04-19 04:48:54 -05:00
|
|
|
def get(self, *args, **kwargs):
|
2014-04-20 17:02:10 -05:00
|
|
|
maps = Map.public.filter(center__distance_gt=(DEFAULT_CENTER, D(km=1))).order_by('-modified_at')[:2500]
|
2014-02-07 15:00:50 -06:00
|
|
|
|
|
|
|
def make(m):
|
2014-02-10 14:37:12 -06:00
|
|
|
description = m.description or ""
|
|
|
|
if m.owner:
|
|
|
|
description = u"{description}\n{by} [[{url}|{name}]]".format(
|
|
|
|
description=description,
|
|
|
|
by=_("by"),
|
|
|
|
url=reverse('user_maps', kwargs={"username": m.owner.username}),
|
|
|
|
name=m.owner,
|
|
|
|
)
|
|
|
|
description = u"{}\n[[{}|{}]]".format(description, m.get_absolute_url(), _("View the map"))
|
2014-02-07 15:00:50 -06:00
|
|
|
geometry = m.settings['geometry'] if "geometry" in m.settings else simplejson.loads(m.center.geojson)
|
|
|
|
return {
|
|
|
|
"type": "Feature",
|
|
|
|
"geometry": geometry,
|
|
|
|
"properties": {
|
|
|
|
"name": m.name,
|
|
|
|
"description": description
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
geojson = {
|
|
|
|
"type": "FeatureCollection",
|
|
|
|
"features": [make(m) for m in maps]
|
|
|
|
}
|
|
|
|
return HttpResponse(simplejson.dumps(geojson))
|
|
|
|
|
|
|
|
showcase = MapsShowCase.as_view()
|
2014-04-19 04:48:54 -05:00
|
|
|
|
|
|
|
|
2014-04-19 10:54:51 -05:00
|
|
|
from django.core.validators import URLValidator, ValidationError
|
|
|
|
|
|
|
|
|
|
|
|
def validate_url(request):
|
|
|
|
assert request.method == "GET"
|
|
|
|
assert request.is_ajax()
|
|
|
|
url = request.GET.get('url')
|
|
|
|
assert url
|
|
|
|
try:
|
|
|
|
URLValidator(url)
|
|
|
|
except ValidationError:
|
|
|
|
raise AssertionError()
|
|
|
|
assert 'HTTP_REFERER' in request.META
|
|
|
|
referer = urlparse(request.META.get('HTTP_REFERER'))
|
|
|
|
toproxy = urlparse(url)
|
|
|
|
local = urlparse(settings.SITE_URL)
|
|
|
|
assert toproxy.hostname
|
|
|
|
assert referer.hostname == local.hostname
|
|
|
|
assert toproxy.hostname != "localhost"
|
|
|
|
assert toproxy.netloc != local.netloc
|
2014-07-18 16:26:16 -05:00
|
|
|
try:
|
|
|
|
# clean this when in python 3.4
|
|
|
|
ipaddress = socket.gethostbyname(toproxy.hostname)
|
|
|
|
except:
|
|
|
|
raise AssertionError()
|
2014-04-19 12:44:56 -05:00
|
|
|
assert not ipaddress.startswith('127.')
|
|
|
|
assert not ipaddress.startswith('192.168.')
|
2014-04-19 10:54:51 -05:00
|
|
|
return url
|
|
|
|
|
|
|
|
|
2014-04-19 04:48:54 -05:00
|
|
|
class AjaxProxy(View):
|
|
|
|
|
|
|
|
def get(self, *args, **kwargs):
|
|
|
|
# You should not use this in production (use Nginx or so)
|
2014-04-19 10:54:51 -05:00
|
|
|
try:
|
|
|
|
url = validate_url(self.request)
|
|
|
|
except AssertionError:
|
|
|
|
return HttpResponseBadRequest()
|
2014-04-19 12:44:56 -05:00
|
|
|
headers = {
|
|
|
|
'User-Agent': 'uMapProxy +http://wiki.openstreetmap.org/wiki/UMap'
|
|
|
|
}
|
|
|
|
request = urllib2.Request(url, headers=headers)
|
|
|
|
opener = urllib2.build_opener()
|
2014-04-19 04:48:54 -05:00
|
|
|
try:
|
2014-04-19 12:44:56 -05:00
|
|
|
proxied_request = opener.open(request)
|
2014-04-19 04:48:54 -05:00
|
|
|
except urllib2.HTTPError as e:
|
|
|
|
return HttpResponse(e.msg, status=e.code, mimetype='text/plain')
|
|
|
|
else:
|
2014-04-19 12:44:56 -05:00
|
|
|
status_code = proxied_request.code
|
|
|
|
mimetype = proxied_request.headers.typeheader or mimetypes.guess_type(url)
|
|
|
|
content = proxied_request.read()
|
2014-04-20 05:24:13 -05:00
|
|
|
# Quick hack to prevent Django from adding a Vary: Cookie header
|
|
|
|
self.request.session.accessed = False
|
2014-04-19 04:48:54 -05:00
|
|
|
return HttpResponse(content, status=status_code, mimetype=mimetype)
|
|
|
|
ajax_proxy = AjaxProxy.as_view()
|