offline.pl 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. # Copyright (C) 2011 Alex Schroeder <alex@gnu.org>
  2. # This program is free software: you can redistribute it and/or modify it under
  3. # the terms of the GNU General Public License as published by the Free Software
  4. # Foundation, either version 3 of the License, or (at your option) any later
  5. # version.
  6. #
  7. # This program is distributed in the hope that it will be useful, but WITHOUT
  8. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  9. # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  10. #
  11. # You should have received a copy of the GNU General Public License along with
  12. # this program. If not, see <http://www.gnu.org/licenses/>.
  13. use strict;
  14. use v5.10;
  15. AddModuleDescription('offline.pl', 'Offline Extension');
  16. our ($q, %Action, $StyleSheet, $ScriptName, $HtmlHeaders, @MyAdminCode, @MyInitVariables, $DocumentHeader, $SurgeProtection);
  17. # Based on http://diveintohtml5.org/offline.html
  18. push(@MyAdminCode, \&OfflineMenu);
  19. sub OfflineMenu {
  20. my ($id, $menuref, $restref) = @_;
  21. push(@$menuref,
  22. ScriptLink('action=browse;id=' . UrlEncode($id) . ';offline=1',
  23. T('Make available offline'),
  24. 'offline'));
  25. }
  26. push(@MyInitVariables, \&InitOffline);
  27. sub InitOffline {
  28. # Make sure we parse path_info and parameters
  29. GetId();
  30. # Switch to HTML5 if the offline parameter is set
  31. if (GetParam('offline', 0)) {
  32. # add link to the manifest listing all the pages
  33. my $manifest = ScriptUrl('action=manifest');
  34. $DocumentHeader = qq{<!DOCTYPE HTML>
  35. <html manifest="$manifest">
  36. };
  37. # HACK ALERT: In order to allow the browser to cache all the pages
  38. # listed in the manifest, we need to disable surge protection for
  39. # the offline pages.
  40. $SurgeProtection = 0;
  41. # every offline page will link to other offline pages
  42. $ScriptName .= '/offline' unless $ScriptName =~ m!/offline$!;
  43. # add some links for Apple devices (boo!)
  44. if ($HtmlHeaders !~ /apple-mobile-web-app-capable/) {
  45. $HtmlHeaders .= qq{
  46. <meta name="apple-mobile-web-app-capable" content="yes" />
  47. <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  48. };
  49. }
  50. }
  51. }
  52. $Action{manifest} = \&DoManifest;
  53. # List all the pages necessary for the offline application.
  54. sub DoManifest {
  55. print GetHttpHeader('text/cache-manifest');
  56. print "CACHE MANIFEST\n";
  57. # make sure to list the URLs for the offline version
  58. local $ScriptName = $ScriptName . '/offline';
  59. # don't forget to URL encode
  60. foreach my $id (AllPagesList()) {
  61. print ScriptUrl(UrlEncode($id)) . "\n";
  62. }
  63. # Missing pages that should show the default text such as
  64. # RecentChanges cannot be added because fetching them results in a
  65. # 404 error.
  66. # foreach my $id (@UserGotoBarPages) {
  67. # print ScriptUrl($id) . "\n" unless $IndexHash{$id};
  68. # }
  69. # External CSS
  70. print ref $StyleSheet ? join("\n", @$StyleSheet) . "\n" : "$StyleSheet\n" if $StyleSheet;
  71. # FIXME: $StyleSheetPage
  72. # FIXME: external images, stuff in $HtmlHeaders
  73. # Error message all the stuff that's not available offline.
  74. my $offline = ScriptUrl('action=offline');
  75. print qq{
  76. FALLBACK:
  77. / $offline
  78. NETWORK:
  79. *
  80. };
  81. }
  82. $Action{offline} = \&DoOffline;
  83. # Show an excuse for the pages that have not been cached.
  84. sub DoOffline {
  85. ReportError(T('Offline'),
  86. '200 OK',
  87. 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.')));
  88. }
  89. # Fix redirection.
  90. *OldOfflineReBrowsePage = \&ReBrowsePage;
  91. *ReBrowsePage = \&NewOfflineReBrowsePage;
  92. sub NewOfflineReBrowsePage {
  93. my ($id) = @_;
  94. if (GetParam('offline', 0)) {
  95. BrowsePage($id);
  96. } else {
  97. OldOfflineReBrowsePage(@_);
  98. }
  99. }