Skip to content

Commit

Permalink
Merge pull request #2102 from anastasia/pdf-mobile
Browse files Browse the repository at this point in the history
Pdf mobile
  • Loading branch information
rebeccacremona authored Aug 21, 2017
2 parents cae4475 + b7fa0a6 commit d73ed80
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 8 deletions.
2 changes: 1 addition & 1 deletion perma_web/fabfile/dev.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ def sauce_tunnel():
Set up Sauce tunnel before running functional tests targeted at localhost.
"""
if subprocess.call(['which','sc']) == 1: # error return code -- program not found
sys.exit("Please check that the `sc` program is installed and in your path. To install: https://docs.saucelabs.com/reference/sauce-connect/")
sys.exit("Please check that the `sc` program is installed and in your path. To install: https://wiki.saucelabs.com/display/DOCS/Sauce+Connect+Proxy")
local("sc -u %s -k %s" % (settings.SAUCE_USERNAME, settings.SAUCE_ACCESS_KEY))


Expand Down
5 changes: 5 additions & 0 deletions perma_web/perma/templates/archive/download_to_view_pdf.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
<div class="record-message">
<p class="record-message-primary">Perma.cc can't display this file type on mobile, but you can view or download the archived file by clicking below.</p>
<p class="record-message-secondary">File type {{mime_type}}</p>
<a class="btn btn-primary" target="_blank" href="{{capture.url}}">View/Download File</a>
<div>
7 changes: 6 additions & 1 deletion perma_web/perma/templates/archive/single-link.html
Original file line number Diff line number Diff line change
Expand Up @@ -239,14 +239,19 @@
{% endif %}

</header>

{% endblock %}

{% block mainContent %}

{% if link.user_deleted %}
{% include "archive/deleted.html" %}
{% elif can_view %}
{% include "archive/iframe.html" %}
{% if redirect_to_download_view %}
{% include "archive/download_to_view_pdf.html" %}
{% else %}
{% include "archive/iframe.html" %}
{% endif %}
{% elif link.is_private %}
{% include "archive/dark-archive.html" %}
{% endif %}
Expand Down
13 changes: 12 additions & 1 deletion perma_web/perma/tests/test_views_common.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from django.conf import settings
from django.core import mail
from django.core.urlresolvers import reverse
from django.test import override_settings
from django.test import override_settings, Client

from perma.urls import urlpatterns
from perma.models import Registrar
Expand Down Expand Up @@ -54,6 +54,17 @@ def test_dark_archive(self):
response = self.get('single_linky', reverse_kwargs={'kwargs': {'guid': 'ABCD-0001'}})
self.assertIn("This record is private.", response.content)

def test_redirect_to_download(self):
# Give user option to download to view pdf if on mobile
client = Client(HTTP_USER_AGENT='Mozilla/5.0 (iPhone; CPU iPhone OS 6_1_4 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B350 Safari/8536.25')
response = client.get(reverse('single_linky', kwargs={'guid': '7CF8-SS4G'}))
self.assertIn("Perma.cc can\'t display this file type on mobile", response.content)

# If not on mobile, display link as normal
client = Client(HTTP_USER_AGENT='Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/601.7.7 (KHTML, like Gecko) Version/9.1.2 Safari/601.7.7')
response = client.get(reverse('single_linky', kwargs={'guid': '7CF8-SS4G'}))
self.assertNotIn("Perma.cc can\'t display this file type on mobile", response.content)

def test_deleted(self):
response = self.get('single_linky', reverse_kwargs={'kwargs': {'guid': 'ABCD-0003'}})
self.assertIn("This record has been deleted.", response.content)
Expand Down
13 changes: 13 additions & 0 deletions perma_web/perma/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from netaddr import IPAddress, IPNetwork
from functools import wraps
import requests
from ua_parser import user_agent_parser

from django.core.paginator import Paginator
from django.db.models import Q
Expand Down Expand Up @@ -252,3 +253,15 @@ def get_lat_long(address):
warn("Error connecting to geocoding API: %s" % r.status_code)


def parse_user_agent(user_agent_str):
return user_agent_parser.ParseUserAgent(user_agent_str)


### pdf handling on mobile ###

def redirect_to_download(capture_mime_type, user_agent_str):
# redirecting to a page with a download button (and not attempting to display)
# if mobile apple device, and the request is a pdf
parsed_agent = parse_user_agent(user_agent_str)

return "Mobile" in parsed_agent["family"] and "pdf" in capture_mime_type
22 changes: 17 additions & 5 deletions perma_web/perma/views/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
from ratelimit.decorators import ratelimit
from datetime import timedelta
from wsgiref.handlers import format_date_time
from ua_parser import user_agent_parser
from urllib import urlencode

from django.contrib.auth.views import redirect_to_login
Expand All @@ -24,7 +23,7 @@

from ..models import Link, Registrar, Organization, LinkUser
from ..forms import ContactForm
from ..utils import if_anonymous, ratelimit_ip_key
from ..utils import if_anonymous, ratelimit_ip_key, redirect_to_download, parse_user_agent
from ..email import send_admin_email, send_user_email_copy_admins

from warcio.warcwriter import BufferWARCWriter
Expand Down Expand Up @@ -109,6 +108,7 @@ def single_linky(request, guid):
"""
Given a Perma ID, serve it up.
"""
raw_user_agent = request.META.get('HTTP_USER_AGENT', '')

# Create a canonical version of guid (non-alphanumerics removed, hyphens every 4 characters, uppercase),
# and forward to that if it's different from current guid.
Expand Down Expand Up @@ -195,7 +195,7 @@ def make_warcinfo(filename, guid, coll_title, coll_desc, rec_title, pages):
# safari=1 in the query string indicates that the redirect has already happened.
# See http://labs.fundbox.com/third-party-cookies-with-ie-at-2am/
if link.is_private and not request.GET.get('safari'):
user_agent = user_agent_parser.ParseUserAgent(request.META.get('HTTP_USER_AGENT', ''))
user_agent = parse_user_agent(raw_user_agent)
if user_agent.get('family') == 'Safari':
return redirect_to_login(request.build_absolute_uri(),
"//%s%s" % (settings.WARC_HOST, reverse('user_management_set_safari_cookie')))
Expand All @@ -210,6 +210,16 @@ def make_warcinfo(filename, guid, coll_title, coll_desc, rec_title, pages):
if (not capture or capture.status != 'success') and link.screenshot_capture and link.screenshot_capture.status == 'success':
return HttpResponseRedirect(reverse('single_linky', args=[guid])+"?type=image")

try:
capture_mime_type = capture.mime_type()
except AttributeError:
# If capture is deleted, then mime type does not exist. Catch error.
capture_mime_type = None

# Special handling for mobile pdf viewing because it can be buggy
# Redirecting to a download page if on mobile
redirect_to_download_view = redirect_to_download(capture_mime_type, raw_user_agent)

# If this record was just created by the current user, show them a new record message
new_record = request.user.is_authenticated() and link.created_by_id == request.user.id and not link.user_deleted \
and link.creation_timestamp > timezone.now() - timedelta(seconds=300)
Expand All @@ -224,6 +234,8 @@ def make_warcinfo(filename, guid, coll_title, coll_desc, rec_title, pages):

context = {
'link': link,
'redirect_to_download_view': redirect_to_download_view,
'mime_type': capture_mime_type,
'can_view': request.user.can_view(link),
'can_edit': request.user.can_edit(link),
'can_delete': request.user.can_delete(link),
Expand All @@ -239,9 +251,9 @@ def make_warcinfo(filename, guid, coll_title, coll_desc, rec_title, pages):

response = render(request, 'archive/single-link.html', context)
date_header = format_date_time(mktime(link.creation_timestamp.timetuple()))
link_memento = protocol + settings.HOST + '/' + link.guid
link_memento = protocol + settings.HOST + '/' + link.guid
link_timegate = protocol + settings.WARC_HOST + settings.TIMEGATE_WARC_ROUTE + '/' + link.safe_url
link_timemap = protocol + settings.WARC_HOST + settings.WARC_ROUTE + '/timemap/*/' + link.safe_url
link_timemap = protocol + settings.WARC_HOST + settings.WARC_ROUTE + '/timemap/*/' + link.safe_url
response['Memento-Datetime'] = date_header

link_memento_headers = '<{0}>; rel="original"; datetime="{1}",<{2}>; rel="memento"; datetime="{1}",<{3}>; rel="timegate",<{4}>; rel="timemap"; type="application/link-format"'
Expand Down

0 comments on commit d73ed80

Please sign in to comment.