# Copyright (C) 2011 Alex Schroeder # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . use strict; use v5.10; AddModuleDescription('offline.pl', 'Offline Extension'); our ($q, %Action, $StyleSheet, $ScriptName, $HtmlHeaders, @MyAdminCode, @MyInitVariables, $DocumentHeader, $SurgeProtection); # Based on http://diveintohtml5.org/offline.html push(@MyAdminCode, \&OfflineMenu); sub OfflineMenu { my ($id, $menuref, $restref) = @_; push(@$menuref, ScriptLink('action=browse;id=' . UrlEncode($id) . ';offline=1', T('Make available offline'), 'offline')); } push(@MyInitVariables, \&InitOffline); sub InitOffline { # Make sure we parse path_info and parameters GetId(); # Switch to HTML5 if the offline parameter is set if (GetParam('offline', 0)) { # add link to the manifest listing all the pages my $manifest = ScriptUrl('action=manifest'); $DocumentHeader = qq{ }; # HACK ALERT: In order to allow the browser to cache all the pages # listed in the manifest, we need to disable surge protection for # the offline pages. $SurgeProtection = 0; # every offline page will link to other offline pages $ScriptName .= '/offline' unless $ScriptName =~ m!/offline$!; # add some links for Apple devices (boo!) if ($HtmlHeaders !~ /apple-mobile-web-app-capable/) { $HtmlHeaders .= qq{ }; } } } $Action{manifest} = \&DoManifest; # List all the pages necessary for the offline application. sub DoManifest { print GetHttpHeader('text/cache-manifest'); print "CACHE MANIFEST\n"; # make sure to list the URLs for the offline version local $ScriptName = $ScriptName . '/offline'; # don't forget to URL encode foreach my $id (AllPagesList()) { print ScriptUrl(UrlEncode($id)) . "\n"; } # Missing pages that should show the default text such as # RecentChanges cannot be added because fetching them results in a # 404 error. # foreach my $id (@UserGotoBarPages) { # print ScriptUrl($id) . "\n" unless $IndexHash{$id}; # } # External CSS print ref $StyleSheet ? join("\n", @$StyleSheet) . "\n" : "$StyleSheet\n" if $StyleSheet; # FIXME: $StyleSheetPage # FIXME: external images, stuff in $HtmlHeaders # Error message all the stuff that's not available offline. my $offline = ScriptUrl('action=offline'); print qq{ FALLBACK: / $offline NETWORK: * }; } $Action{offline} = \&DoOffline; # Show an excuse for the pages that have not been cached. sub DoOffline { ReportError(T('Offline'), '200 OK', 0, $q->p(T('You are currently offline and what you requested is not part of the offline application. You need to be online to do this.'))); } # Fix redirection. *OldOfflineReBrowsePage = \&ReBrowsePage; *ReBrowsePage = \&NewOfflineReBrowsePage; sub NewOfflineReBrowsePage { my ($id) = @_; if (GetParam('offline', 0)) { BrowsePage($id); } else { OldOfflineReBrowsePage(@_); } }