Merge branch 'photocache' into 'dev'
Add Photo Cache addon support See merge request hubzilla/core!1412
This commit is contained in:
		| @@ -95,6 +95,29 @@ class Cron { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
| 		 | 		 | ||||||
|  | 		// Clean expired photos from cache | ||||||
|  | 		 | ||||||
|  | 		$age = get_config('system','active_expire_days', '30'); | ||||||
|  | 		$r = q("SELECT DISTINCT xchan, content FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s", | ||||||
|  | 			intval(PHOTO_CACHE), | ||||||
|  | 			db_utcnow(),  | ||||||
|  | 			db_quoteinterval($age . ' DAY') | ||||||
|  | 		); | ||||||
|  | 		if($r) { | ||||||
|  | 			foreach($r as $rr) { | ||||||
|  | 				$file = dbunescbin($rr['content']); | ||||||
|  | 				if(is_file($file)) { | ||||||
|  | 					@unlink($file); | ||||||
|  | 					logger('info: deleted cached photo file ' . $file, LOGGER_DEBUG); | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		q("DELETE FROM photo WHERE photo_usage = %d AND expires < %s - INTERVAL %s", | ||||||
|  | 			intval(PHOTO_CACHE), | ||||||
|  | 			db_utcnow(),  | ||||||
|  | 			db_quoteinterval($age . ' DAY') | ||||||
|  | 		);		 | ||||||
|  |  | ||||||
| 		// publish any applicable items that were set to be published in the future | 		// publish any applicable items that were set to be published in the future | ||||||
| 		// (time travel posts). Restrict to items that have come of age in the last | 		// (time travel posts). Restrict to items that have come of age in the last | ||||||
| 		// couple of days to limit the query to something reasonable.  | 		// couple of days to limit the query to something reasonable.  | ||||||
|   | |||||||
| @@ -1,19 +1,20 @@ | |||||||
| <?php | <?php | ||||||
|  |  | ||||||
|  |  | ||||||
| namespace Zotlabs\Module; | namespace Zotlabs\Module; | ||||||
|  |  | ||||||
| require_once('include/security.php'); | require_once('include/security.php'); | ||||||
| require_once('include/attach.php'); | require_once('include/attach.php'); | ||||||
| require_once('include/photo/photo_driver.php'); | require_once('include/photo/photo_driver.php'); | ||||||
|  |  | ||||||
|  |  | ||||||
| class Photo extends \Zotlabs\Web\Controller { | class Photo extends \Zotlabs\Web\Controller { | ||||||
|  |  | ||||||
| 	function init() { | 	function init() { | ||||||
|  |  | ||||||
| 		$prvcachecontrol = false; |  | ||||||
| 		$streaming = null; | 		$streaming = null; | ||||||
| 		$channel = null; | 		$channel = null; | ||||||
| 		$person = 0; | 		$person = 0; | ||||||
|  | 		$renew = false; | ||||||
|  |  | ||||||
| 		switch(argc()) { | 		switch(argc()) { | ||||||
| 			case 4: | 			case 4: | ||||||
| @@ -30,6 +31,14 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 				// NOTREACHED | 				// NOTREACHED | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		$cache_mode = array( | ||||||
|  | 			'on' => get_config('system','photo_cache_enable', 0), | ||||||
|  | 			'age' => 86400, | ||||||
|  | 			'exp' => true, | ||||||
|  | 			'leak' => false | ||||||
|  | 		); | ||||||
|  | 		call_hooks('cache_mode_hook', $cache_mode); | ||||||
|  | 		 | ||||||
| 		$observer_xchan = get_observer_hash(); | 		$observer_xchan = get_observer_hash(); | ||||||
| 		$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE']; | 		$ismodified = $_SERVER['HTTP_IF_MODIFIED_SINCE']; | ||||||
|  |  | ||||||
| @@ -106,13 +115,14 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 			   License link: http://creativecommons.org/licenses/by/3.0/ | 			   License link: http://creativecommons.org/licenses/by/3.0/ | ||||||
| 			*/ | 			*/ | ||||||
|  |  | ||||||
|  | 			// @FIXME It seems this part doesn't work because we are not setting such cookie | ||||||
| 			$cookie_value = false; | 			$cookie_value = false; | ||||||
| 			if (isset($_COOKIE['devicePixelRatio'])) { | 			if (isset($_COOKIE['devicePixelRatio'])) { | ||||||
| 			  $cookie_value = intval($_COOKIE['devicePixelRatio']); | 			  $cookie_value = intval($_COOKIE['devicePixelRatio']); | ||||||
| 			} | 			} | ||||||
| 			else { | 			else { | ||||||
| 			  // Force revalidation of cache on next request | 			  // Force revalidation of cache on next request | ||||||
| 			  $cache_directive = 'no-cache'; | 			  // $prvcachecontrol = 'no-cache'; | ||||||
| 			  $status = 'no cookie'; | 			  $status = 'no cookie'; | ||||||
| 			} | 			} | ||||||
| 	 | 	 | ||||||
| @@ -129,27 +139,43 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 				    $resolution = 1; | 				    $resolution = 1; | ||||||
| 			} | 			} | ||||||
| 			 | 			 | ||||||
| 			$r = q("SELECT uid, photo_usage FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", | 			$r = q("SELECT uid, photo_usage, expires, display_path FROM photo WHERE resource_id = '%s' AND imgscale = %d LIMIT 1", | ||||||
| 				dbesc($photo), | 				dbesc($photo), | ||||||
| 				intval($resolution) | 				intval($resolution) | ||||||
| 			); | 			); | ||||||
| 			if($r) { | 			if($r) { | ||||||
|  |  | ||||||
| 				$allowed = (-1); | 				$allowed = (-1); | ||||||
|  |  | ||||||
| 				if(intval($r[0]['photo_usage'])) { | 				$u = intval($r[0]['photo_usage']); | ||||||
|  | 				if($u) { | ||||||
| 					$allowed = 1; | 					$allowed = 1; | ||||||
| 					if(intval($r[0]['photo_usage']) === PHOTO_COVER)  | 					if($u === PHOTO_COVER)  | ||||||
| 						if($resolution < PHOTO_RES_COVER_1200) | 						if($resolution < PHOTO_RES_COVER_1200) | ||||||
| 							$allowed = (-1); | 							$allowed = (-1); | ||||||
| 					if(intval($r[0]['photo_usage']) === PHOTO_PROFILE) | 					if($u === PHOTO_PROFILE) | ||||||
| 						if(! in_array($resolution,[4,5,6])) | 						if(! in_array($resolution,[4,5,6])) | ||||||
| 							$allowed = (-1); | 							$allowed = (-1); | ||||||
|  | 					if($u === PHOTO_CACHE) { | ||||||
|  | 						// Cached image leak protection | ||||||
|  | 						if(! (local_channel() || $cache_mode['leak'])) { | ||||||
|  | 							header("Location: " . $r[0]['display_path']); | ||||||
|  | 							killme(); | ||||||
|  | 						} | ||||||
|  | 						// Revalidate cache | ||||||
|  | 						if($cache_mode['on'] && strtotime($r[0]['expires']) - 60 < time()) { | ||||||
|  | 							$cache = array( | ||||||
|  | 								'url' => $r[0]['display_path'], | ||||||
|  | 								'uid' => $r[0]['uid'] | ||||||
|  | 							); | ||||||
|  | 							call_hooks('cache_url_hook', $cache); | ||||||
|  | 							if(! $cache['status']) | ||||||
|  | 								http_status_exit(404,'not found'); | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
|  |  | ||||||
| 				if($allowed === (-1)) { | 				if($allowed === (-1)) | ||||||
| 					$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); | 					$allowed = attach_can_view($r[0]['uid'],$observer_xchan,$photo); | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				$channel = channelx_by_n($r[0]['uid']); | 				$channel = channelx_by_n($r[0]['uid']); | ||||||
|  |  | ||||||
| @@ -162,14 +188,17 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 				$exists = (($e) ? true : false); | 				$exists = (($e) ? true : false); | ||||||
| 			 | 			 | ||||||
| 				if($exists && $allowed) { | 				if($exists && $allowed) { | ||||||
|  | 					$expires = strtotime($e[0]['expires'] . 'Z'); | ||||||
| 					$data = dbunescbin($e[0]['content']); | 					$data = dbunescbin($e[0]['content']); | ||||||
| 					$filesize = $e[0]['filesize']; | 					$filesize = $e[0]['filesize']; | ||||||
| 					$mimetype = $e[0]['mimetype']; | 					$mimetype = $e[0]['mimetype']; | ||||||
| 					$modified = strtotime($e[0]['edited'] . 'Z'); | 					$modified = strtotime($e[0]['edited'] . 'Z'); | ||||||
| 					if(intval($e[0]['os_storage'])) |  | ||||||
|  | 					if(intval($e[0]['os_storage'])) { | ||||||
| 						$streaming = $data; | 						$streaming = $data; | ||||||
|  | 					} | ||||||
| 					if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '') | 					if($e[0]['allow_cid'] != '' || $e[0]['allow_gid'] != '' || $e[0]['deny_gid'] != '' || $e[0]['deny_gid'] != '') | ||||||
| 						$prvcachecontrol = true; | 						$prvcachecontrol = 'no-store, no-cache, must-revalidate'; | ||||||
| 				} | 				} | ||||||
| 				else { | 				else { | ||||||
| 					if(! $allowed) { | 					if(! $allowed) { | ||||||
| @@ -180,9 +209,9 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 					} | 					} | ||||||
|  |  | ||||||
| 				} | 				} | ||||||
| 			} else { |  | ||||||
| 				http_status_exit(404,'not found'); |  | ||||||
| 			}  | 			}  | ||||||
|  | 			else | ||||||
|  | 				http_status_exit(404,'not found'); | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		header_remove('Pragma'); | 		header_remove('Pragma'); | ||||||
| @@ -226,23 +255,13 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
| 		// @FIXME Seems never invoked | 		if(isset($prvcachecontrol)) { | ||||||
| 		// Writing in cachefile |  | ||||||
| 		if (isset($cachefile) && $cachefile != '') { |  | ||||||
| 			file_put_contents($cachefile, $data); |  | ||||||
| 			$modified = filemtime($cachefile); |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
|  |  | ||||||
| 		header("Content-type: " . $mimetype); |  | ||||||
| 	 |  | ||||||
| 		if($prvcachecontrol) { |  | ||||||
| 	 | 	 | ||||||
| 			// it is a private photo that they have no permission to view. | 			// it is a private photo that they have no permission to view. | ||||||
| 			// tell the browser not to cache it, in case they authenticate | 			// tell the browser not to cache it, in case they authenticate | ||||||
| 			// and subsequently have permission to see it | 			// and subsequently have permission to see it | ||||||
| 	 | 	 | ||||||
| 			header("Cache-Control: no-store, no-cache, must-revalidate"); | 			header("Cache-Control: " . $prvcachecontrol); | ||||||
| 	 | 	 | ||||||
| 		} | 		} | ||||||
| 		else { | 		else { | ||||||
| @@ -255,18 +274,23 @@ class Photo extends \Zotlabs\Web\Controller { | |||||||
| 			// This has performance considerations but we highly recommend you  | 			// This has performance considerations but we highly recommend you  | ||||||
| 			// leave it alone.  | 			// leave it alone.  | ||||||
| 	 | 	 | ||||||
| 			$cache = get_config('system','photo_cache_time', 86400);    // 1 day by default | 			$maxage = $cache_mode['age']; | ||||||
|  |  | ||||||
| 		 	header("Expires: " . gmdate("D, d M Y H:i:s", time() + $cache) . " GMT"); | 			if($cache_mode['exp'] || (! isset($expires)) || (isset($expires) && $expires - 60 < time())) | ||||||
| 			header("Cache-Control: max-age=" . $cache); | 				$expires = time() + $maxage; | ||||||
|  | 			else | ||||||
|  | 				$maxage = $expires - time(); | ||||||
|  | 			 | ||||||
|  | 		 	header("Expires: " . gmdate("D, d M Y H:i:s", $expires) . " GMT"); | ||||||
|  | 			header("Cache-Control: max-age=" . $maxage); | ||||||
| 	 | 	 | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | 		header("Content-type: " . $mimetype); | ||||||
| 		header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT"); | 		header("Last-Modified: " . gmdate("D, d M Y H:i:s", $modified) . " GMT"); | ||||||
| 		header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data))); | 		header("Content-Length: " . (isset($filesize) ? $filesize : strlen($data))); | ||||||
|  |  | ||||||
| 		// If it's a file resource, stream it.  | 		// If it's a file resource, stream it.  | ||||||
|  |  | ||||||
| 		if($streaming && $channel) { | 		if($streaming && $channel) { | ||||||
| 			if(strpos($streaming,'store') !== false) | 			if(strpos($streaming,'store') !== false) | ||||||
| 				$istream = fopen($streaming,'rb'); | 				$istream = fopen($streaming,'rb'); | ||||||
|   | |||||||
							
								
								
									
										32
									
								
								Zotlabs/Update/_1229.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								Zotlabs/Update/_1229.php
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | |||||||
|  | <?php | ||||||
|  |  | ||||||
|  | namespace Zotlabs\Update; | ||||||
|  |  | ||||||
|  | class _1229 { | ||||||
|  |  | ||||||
|  | 	function run() { | ||||||
|  | 	 | ||||||
|  | 	    q("START TRANSACTION"); | ||||||
|  |  | ||||||
|  | 		if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { | ||||||
|  | 			$r1 = q("ALTER TABLE photo ADD expires timestamp NOT NULL DEFAULT '0001-01-01 00:00:00' "); | ||||||
|  |  			$r2 = q("create index \"photo_expires_idx\" on photo (\"expires\")"); | ||||||
|  |  | ||||||
|  | 			$r = ($r1 && $r2); | ||||||
|  | 		} | ||||||
|  | 		else { | ||||||
|  | 			$r = q("ALTER TABLE `photo` ADD `expires` datetime NOT NULL DEFAULT '0001-01-01 00:00:00' ,  | ||||||
|  | 				ADD INDEX `expires` (`expires`)"); | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		if($r) { | ||||||
|  | 			q("COMMIT"); | ||||||
|  | 			return UPDATE_SUCCESS; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		q("ROLLBACK"); | ||||||
|  | 		return UPDATE_FAILED; | ||||||
|  |  | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | } | ||||||
							
								
								
									
										3
									
								
								boot.php
									
									
									
									
									
								
							
							
						
						
									
										3
									
								
								boot.php
									
									
									
									
									
								
							| @@ -53,7 +53,7 @@ define ( 'PLATFORM_NAME',           'hubzilla' ); | |||||||
| define ( 'STD_VERSION',             '3.9.5' ); | define ( 'STD_VERSION',             '3.9.5' ); | ||||||
| define ( 'ZOT_REVISION',            '6.0a' ); | define ( 'ZOT_REVISION',            '6.0a' ); | ||||||
|  |  | ||||||
| define ( 'DB_UPDATE_VERSION',       1228 ); | define ( 'DB_UPDATE_VERSION',       1229 ); | ||||||
|  |  | ||||||
| define ( 'PROJECT_BASE',   __DIR__ ); | define ( 'PROJECT_BASE',   __DIR__ ); | ||||||
|  |  | ||||||
| @@ -217,6 +217,7 @@ define ( 'PHOTO_PROFILE',          0x0001 ); | |||||||
| define ( 'PHOTO_XCHAN',            0x0002 ); | define ( 'PHOTO_XCHAN',            0x0002 ); | ||||||
| define ( 'PHOTO_THING',            0x0004 ); | define ( 'PHOTO_THING',            0x0004 ); | ||||||
| define ( 'PHOTO_COVER',            0x0010 ); | define ( 'PHOTO_COVER',            0x0010 ); | ||||||
|  | define ( 'PHOTO_CACHE',            0x0020 ); | ||||||
|  |  | ||||||
| define ( 'PHOTO_ADULT',            0x0008 ); | define ( 'PHOTO_ADULT',            0x0008 ); | ||||||
| define ( 'PHOTO_FLAG_OS',          0x4000 ); | define ( 'PHOTO_FLAG_OS',          0x4000 ); | ||||||
|   | |||||||
| @@ -1105,9 +1105,20 @@ function linkify($s, $me = false) { | |||||||
|  * to a local redirector which uses https and which redirects to the selected content |  * to a local redirector which uses https and which redirects to the selected content | ||||||
|  * |  * | ||||||
|  * @param string $s |  * @param string $s | ||||||
|  |  * @param int $uid | ||||||
|  * @returns string |  * @returns string | ||||||
|  */ |  */ | ||||||
| function sslify($s) { | function sslify($s) { | ||||||
|  | 	 | ||||||
|  | 	// Local photo cache | ||||||
|  | 	$str = array( | ||||||
|  | 		'body' => $s, | ||||||
|  | 		'uid' => local_channel() | ||||||
|  | 	); | ||||||
|  | 	call_hooks('cache_body_hook', $str); | ||||||
|  | 	 | ||||||
|  | 	$s = $str['body']; | ||||||
|  |  | ||||||
| 	if (strpos(z_root(),'https:') === false) | 	if (strpos(z_root(),'https:') === false) | ||||||
| 		return $s; | 		return $s; | ||||||
| 	 | 	 | ||||||
| @@ -1117,8 +1128,7 @@ function sslify($s) { | |||||||
| 	// Complain to your browser maker | 	// Complain to your browser maker | ||||||
|  |  | ||||||
| 	$allow = get_config('system','sslify_everything'); | 	$allow = get_config('system','sslify_everything'); | ||||||
|  | 	$pattern = (($allow) ? "/\<(.*?)src=[\"|'](http\:.*?)[\"|'](.*?)\>/" : "/\<img(.*?)src=[\"|'](http\:.*?)[\"|'](.*?)\>/" ); | ||||||
| 	$pattern = (($allow) ? "/\<(.*?)src=\"(http\:.*?)\"(.*?)\>/" : "/\<img(.*?)src=\"(http\:.*?)\"(.*?)\>/" ); |  | ||||||
|  |  | ||||||
| 	$matches = null; | 	$matches = null; | ||||||
| 	$cnt = preg_match_all($pattern, $s, $matches, PREG_SET_ORDER); | 	$cnt = preg_match_all($pattern, $s, $matches, PREG_SET_ORDER); | ||||||
|   | |||||||
| @@ -947,6 +947,7 @@ CREATE TABLE IF NOT EXISTS `photo` ( | |||||||
|   `resource_id` char(191) NOT NULL DEFAULT '', |   `resource_id` char(191) NOT NULL DEFAULT '', | ||||||
|   `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00', |   `created` datetime NOT NULL DEFAULT '0001-01-01 00:00:00', | ||||||
|   `edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00', |   `edited` datetime NOT NULL DEFAULT '0001-01-01 00:00:00', | ||||||
|  |   `expires` datetime NOT NULL DEFAULT '0001-01-01 00:00:00', | ||||||
|   `title` char(191) NOT NULL DEFAULT '', |   `title` char(191) NOT NULL DEFAULT '', | ||||||
|   `description` text NOT NULL, |   `description` text NOT NULL, | ||||||
|   `album` char(191) NOT NULL DEFAULT '', |   `album` char(191) NOT NULL DEFAULT '', | ||||||
| @@ -979,6 +980,7 @@ CREATE TABLE IF NOT EXISTS `photo` ( | |||||||
|   KEY `xchan` (`xchan`), |   KEY `xchan` (`xchan`), | ||||||
|   KEY `filesize` (`filesize`), |   KEY `filesize` (`filesize`), | ||||||
|   KEY `resource_id` (`resource_id`), |   KEY `resource_id` (`resource_id`), | ||||||
|  |   KEY `expires` (`expires`), | ||||||
|   KEY `is_nsfw` (`is_nsfw`), |   KEY `is_nsfw` (`is_nsfw`), | ||||||
|   KEY `os_storage` (`os_storage`), |   KEY `os_storage` (`os_storage`), | ||||||
|   KEY `photo_usage` (`photo_usage`) |   KEY `photo_usage` (`photo_usage`) | ||||||
|   | |||||||
| @@ -928,6 +928,7 @@ CREATE TABLE "photo" ( | |||||||
|   "resource_id" text NOT NULL, |   "resource_id" text NOT NULL, | ||||||
|   "created" timestamp NOT NULL, |   "created" timestamp NOT NULL, | ||||||
|   "edited" timestamp NOT NULL, |   "edited" timestamp NOT NULL, | ||||||
|  |   "expires" timestamp NOT NULL, | ||||||
|   "title" text NOT NULL, |   "title" text NOT NULL, | ||||||
|   "description" text NOT NULL, |   "description" text NOT NULL, | ||||||
|   "album" text NOT NULL, |   "album" text NOT NULL, | ||||||
| @@ -961,6 +962,7 @@ create index "photo_aid" on photo ("aid"); | |||||||
| create index "photo_xchan" on photo ("xchan"); | create index "photo_xchan" on photo ("xchan"); | ||||||
| create index "photo_filesize" on photo ("filesize"); | create index "photo_filesize" on photo ("filesize"); | ||||||
| create index "photo_resource_id" on photo ("resource_id"); | create index "photo_resource_id" on photo ("resource_id"); | ||||||
|  | create index "photo_expires_idx" on photo ("expires"); | ||||||
| create index "photo_usage" on photo ("photo_usage"); | create index "photo_usage" on photo ("photo_usage"); | ||||||
| create index "photo_is_nsfw" on photo ("is_nsfw"); | create index "photo_is_nsfw" on photo ("is_nsfw"); | ||||||
| create index "photo_os_storage" on photo ("os_storage"); | create index "photo_os_storage" on photo ("os_storage"); | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user