1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25: 26:
27: $plugin_is_filter = 400 | CLASS_PLUGIN;
28: $plugin_description = gettext("Adds static HTML cache functionality to Zenphoto.");
29: $plugin_author = "Malte Müller (acrylian), Stephen Billard (sbillard)";
30:
31: $option_interface = 'static_html_cache';
32:
33: $cache_path = SERVERPATH . '/' . STATIC_CACHE_FOLDER . "/";
34: if (!file_exists($cache_path)) {
35: if (!mkdir($cache_path, FOLDER_MOD)) {
36: die(gettext("Static HTML Cache folder could not be created. Please try to create it manually via FTP with chmod 0777."));
37: }
38: }
39: $cachesubfolders = array("albums", "images", "pages");
40: foreach ($cachesubfolders as $cachesubfolder) {
41: $cache_folder = $cache_path . $cachesubfolder . '/';
42: if (!file_exists($cache_folder)) {
43: if (!mkdir($cache_folder, FOLDER_MOD)) {
44: die(gettext("Static HTML Cache folder could not be created. Please try to create it manually via FTP with chmod 0777."));
45: }
46: }
47: }
48:
49: if (OFFSET_PATH == 2) {
50: static_html_cache::clearHTMLCache();
51: }
52:
53: $_zp_HTML_cache = new static_html_cache();
54: zp_register_filter('image_processor_uri', 'static_html_cache::_disable');
55:
56: class static_html_cache {
57:
58: var $enabled = true;
59: private $pageCachePath = NULL;
60: private $dirty;
61:
62: 63: 64: 65: 66: 67: 68: 69: 70:
71: function checkIfAllowedPage() {
72: global $_zp_gallery_page, $_zp_current_image, $_zp_current_album, $_zp_current_zenpage_page,
73: $_zp_current_zenpage_news, $_zp_current_admin_obj, $_zp_current_category, $_zp_authority;
74: if (zp_loggedin(ADMIN_RIGHTS)) {
75: return false;
76: }
77: switch ($_zp_gallery_page) {
78: case "image.php":
79: $obj = $_zp_current_album;
80: $title = $_zp_current_image->filename;
81: break;
82: case "album.php":
83: $obj = $_zp_current_album;
84: $title = $_zp_current_album->name;
85: break;
86: case 'pages.php':
87: $obj = $_zp_current_zenpage_page;
88: $title = $_zp_current_zenpage_page->getTitlelink();
89: break;
90: case 'news.php':
91: if (in_context(ZP_ZENPAGE_NEWS_ARTICLE)) {
92: $obj = $_zp_current_zenpage_news;
93: $title = $obj->getTitlelink();
94: } else {
95: if (in_context(ZP_ZENPAGE_NEWS_CATEGORY)) {
96: $obj = $_zp_current_category;
97: $title = $obj->getTitlelink();
98: } else {
99: $obj = NULL;
100: $title = NULL;
101: }
102: }
103: break;
104: default:
105: $obj = NULL;
106: if (isset($_GET['title'])) {
107: $title = sanitize($_GET['title']);
108: } else {
109: $title = "";
110: }
111: break;
112: }
113: if ($obj && $obj->isMyItem($obj->manage_some_rights)) {
114: return false;
115: }
116: $accessType = checkAccess();
117: if ($accessType) {
118: if (is_numeric($accessType)) {
119: $accessType = 'zp_user_auth';
120: } else if ($accessType == 'zp_public_access' && count($_zp_authority->getAuthCookies()) > 0) {
121: $accessType .= '1';
122: }
123: } else {
124: return false;
125: }
126:
127: $excludeList = array_merge(explode(",", getOption('static_cache_excludedpages')), array('404.php/', 'password.php/'));
128: foreach ($excludeList as $item) {
129: $page_to_exclude = explode("/", $item);
130: if ($_zp_gallery_page == trim($page_to_exclude[0])) {
131: $exclude = trim($page_to_exclude[1]);
132: if (empty($exclude) || $title == $exclude) {
133: return false;
134: }
135: }
136: }
137: return $accessType;
138: }
139:
140: 141: 142: 143:
144: function startHTMLCache() {
145: global $_zp_gallery_page, $_zp_script_timer;
146: if ($this->enabled && $accessType = $this->checkIfAllowedPage()) {
147: $_zp_script_timer['static cache start'] = microtime();
148: $cachefilepath = $this->createCacheFilepath($accessType);
149: if (!empty($cachefilepath)) {
150: $cachefilepath = SERVERPATH . '/' . STATIC_CACHE_FOLDER . "/" . $cachefilepath;
151: if (file_exists($cachefilepath)) {
152: $lastmodified = filemtime($cachefilepath);
153:
154: if (time() - $lastmodified < getOption("static_cache_expire")) {
155:
156:
157: header('Content-Type: text/html; charset=' . LOCAL_CHARSET);
158: header("HTTP/1.0 200 OK");
159: header("Status: 200 OK");
160: header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $lastmodified) . ' GMT');
161:
162: echo file_get_contents($cachefilepath);
163:
164:
165: list($usec, $sec) = explode(' ', $_zp_script_timer['start']);
166: $start = (float) $usec + (float) $sec;
167: list($usec, $sec) = explode(' ', $_zp_script_timer['static cache start']);
168: $start_cache = (float) $usec + (float) $sec;
169: list($usec, $sec) = explode(' ', microtime());
170: $end = (float) $usec + (float) $sec;
171: echo "<!-- " . sprintf(gettext('Cached content of %3$s served by static_html_cache in %1$.4f seconds plus %2$.4f seconds unavoidable Zenphoto overhead.'), $end - $start_cache, $start_cache - $start, date('D, d M Y H:i:s', filemtime($cachefilepath))) . " -->\n";
172: exitZP();
173: }
174: }
175: $this->deletestatic_html_cacheFile($cachefilepath);
176: if (ob_start()) {
177: $this->pageCachePath = $cachefilepath;
178: }
179: }
180: unset($_zp_script_timer['static cache start']);
181: }
182: }
183:
184: 185: 186: 187: 188: 189:
190: function endHTMLCache() {
191: global $_zp_script_timer;
192: $cachefilepath = $this->pageCachePath;
193: if (!empty($cachefilepath)) {
194: $pagecontent = ob_get_contents();
195: ob_end_clean();
196: if ($this->enabled && $fh = fopen($cachefilepath, "w")) {
197: fputs($fh, $pagecontent);
198: fclose($fh);
199: clearstatcache();
200: }
201: $this->pageCachePath = NULL;
202: echo $pagecontent;
203: }
204: }
205:
206: 207: 208: 209: 210: 211:
212: function abortHTMLCache() {
213: if (!empty($this->pageCachePath)) {
214: $this->pageCachePath = NULL;
215: ob_end_flush();
216: }
217: }
218:
219: 220: 221: 222: 223:
224: function createCacheFilepath($accessType) {
225: global $_zp_current_image, $_zp_current_album, $_zp_gallery_page, $_zp_authority,
226: $_zp_current_zenpage_news, $_zp_current_category, $_zp_current_zenpage_page, $_zp_gallery, $_zp_page, $_zp_current_search;
227:
228: $cachefilepath = $_zp_gallery->getCurrentTheme() . '_' . str_replace('zp_', '', $accessType) . '_';
229: $album = "";
230: $image = "";
231: $searchfields = "";
232: $words = "";
233: $date = "";
234: $title = "";
235: $category = "";
236: if (isset($_REQUEST['locale'])) {
237: $locale = "_" . sanitize($_REQUEST['locale']);
238: } else {
239: $locale = "_" . getOption("locale");
240: }
241: switch ($_zp_gallery_page) {
242: case 'index.php':
243: $cachesubfolder = "pages";
244: $cachefilepath .= "index";
245: break;
246: case 'album.php':
247: case 'image.php':
248: $cachesubfolder = "albums";
249: $album = $_zp_current_album->name;
250: if (isset($_zp_current_image)) {
251: $cachesubfolder = "images";
252: $image = "-" . $_zp_current_image->filename;
253: }
254: $cachefilepath .= $album . $image;
255: if (in_context(ZP_SEARCH_LINKED)) {
256: $cachefilepath .= '_search_' . stripcslashes($_zp_current_search->codifySearchString());
257: }
258: break;
259: case 'pages.php':
260: $cachesubfolder = "pages";
261: $cachefilepath .= 'page-' . $_zp_current_zenpage_page->getTitlelink();
262: break;
263: case 'news.php':
264: $cachesubfolder = "pages";
265: if (is_object($_zp_current_zenpage_news)) {
266: $title = "-" . $_zp_current_zenpage_news->getTitlelink();
267: }
268: if (is_object($_zp_current_category)) {
269: $category = "_cat-" . $_zp_current_category->getTitlelink();
270: }
271: $cachefilepath .= 'news' . $category . $title;
272: break;
273: default:
274:
275: $cachesubfolder = "pages";
276: $cachefilepath .= 'custom-' . stripSuffix($_zp_gallery_page);
277: break;
278: }
279: $cachefilepath .= "_" . (int) $_zp_page;
280:
281: if (getOption('obfuscate_cache')) {
282: $cachefilepath = sha1($locale . HASH_SEED . $cachefilepath);
283: } else {
284:
285: $cachefilepath = str_replace(array('<', '>', ':', '"', '/', '\\', '|', '?', '*'), '_', $cachefilepath) . $locale;
286: }
287: return $cachesubfolder . "/" . $cachefilepath . '.html';
288: }
289:
290: 291: 292: 293: 294:
295: function deletestatic_html_cacheFile($cachefilepath) {
296: if (file_exists($cachefilepath)) {
297: @chmod($cachefilepath, 0777);
298: @unlink($cachefilepath);
299: }
300: }
301:
302: 303: 304: 305: 306:
307: static function clearHTMLCache($folder = NULL) {
308: if (is_null($folder)) {
309: $cachesubfolders = array("index", "albums", "images", "pages");
310: foreach ($cachesubfolders as $cachesubfolder) {
311: zpFunctions::removeDir(SERVERPATH . '/' . STATIC_CACHE_FOLDER . "/" . $cachesubfolder, true);
312: }
313: } else {
314: zpFunctions::removeDir(SERVERPATH . '/' . STATIC_CACHE_FOLDER . "/" . $folder);
315: }
316: }
317:
318: 319: 320:
321: static function disable() {
322: global $_zp_HTML_cache;
323: $_zp_HTML_cache->enabled = false;
324: }
325:
326: function static_html_cache_options() {
327: setOptionDefault('static_cache_expire', 86400);
328: setOptionDefault('static_cache_excludedpages', 'search.php/,contact.php/,register.php/,favorites.php/');
329: }
330:
331: function getOptionsSupported() {
332: return array(gettext('Static HTML cache expire') => array('key' => 'static_cache_expire', 'type' => OPTION_TYPE_TEXTBOX,
333: 'desc' => gettext("When the cache should expire in seconds. Default is 86400 seconds (1 day = 24 hrs * 60 min * 60 sec).")),
334: gettext('Excluded pages') => array('key' => 'static_cache_excludedpages', 'type' => OPTION_TYPE_TEXTBOX,
335: 'desc' => gettext("The list of pages to be excluded from cache generation. Pages that can be excluded are custom theme pages including Zenpage pages (these optionally more specific by titlelink) and the standard theme files image.php (optionally by image file name), album.php (optionally by album folder name) or index.php.<br /> If you want to exclude a page completely enter <em>page-filename.php/</em>. <br />If you want to exclude a page by a specific title, image filename, or album folder name enter <em>pagefilename.php/titlelink or image filename or album folder</em>. Separate several entries by comma.")),
336: );
337: }
338:
339: function handleOption($option, $currentValue) {
340:
341: }
342:
343: 344: 345: 346: 347:
348: static function _disable($uri) {
349: global $_zp_HTML_cache;
350: $_zp_HTML_cache->disable();
351: return $uri;
352: }
353:
354: }
355:
356: ?>