aboutsummaryrefslogtreecommitdiffstats
path: root/include/photo
diff options
context:
space:
mode:
authorMax Kostikov <max@kostikov.co>2018-11-08 18:00:18 +0100
committerMax Kostikov <max@kostikov.co>2018-11-08 18:00:18 +0100
commit17cf824545a4e059183f0a43af9692a90100c55a (patch)
treee2af776d5e5436774afdc3f8ad6335d945348e1d /include/photo
parente35f5d3c9384dba1fd920c9c08dba5222dbd21c6 (diff)
downloadvolse-hubzilla-17cf824545a4e059183f0a43af9692a90100c55a.tar.gz
volse-hubzilla-17cf824545a4e059183f0a43af9692a90100c55a.tar.bz2
volse-hubzilla-17cf824545a4e059183f0a43af9692a90100c55a.zip
Return image modification date using HTTP 'Last-Modified' and '304 Not Modified' on remote fetch for caching
Diffstat (limited to 'include/photo')
-rw-r--r--include/photo/photo_driver.php274
1 files changed, 159 insertions, 115 deletions
diff --git a/include/photo/photo_driver.php b/include/photo/photo_driver.php
index 2e2f5a758..911b97ade 100644
--- a/include/photo/photo_driver.php
+++ b/include/photo/photo_driver.php
@@ -570,122 +570,166 @@ function delete_thing_photo($url,$ob_hash) {
-function import_xchan_photo($photo,$xchan,$thing = false) {
-
- $flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
- $album = (($thing) ? 'Things' : 'Contact Photos');
-
- logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
-
- if($thing)
- $hash = photo_new_resource();
- else {
- $r = q("select resource_id from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
- dbesc($xchan),
- intval(PHOTO_XCHAN)
- );
- if($r) {
- $hash = $r[0]['resource_id'];
- }
- else {
- $hash = photo_new_resource();
- }
- }
-
- $photo_failure = false;
- $img_str = '';
-
- if($photo) {
- $filename = basename($photo);
-
- $result = z_fetch_url($photo,true);
-
- if($result['success']) {
- $img_str = $result['body'];
- $type = guess_image_type($photo, $result['header']);
-
- $h = explode("\n",$result['header']);
- if($h) {
- foreach($h as $hl) {
- if(stristr($hl,'content-type:')) {
- if(! stristr($hl,'image/')) {
- $photo_failure = true;
- }
- }
- }
- }
- }
- }
- else {
- $photo_failure = true;
- }
-
- if(! $photo_failure) {
- $img = photo_factory($img_str, $type);
- if($img->is_valid()) {
- $width = $img->getWidth();
- $height = $img->getHeight();
-
- if($width && $height) {
- if(($width / $height) > 1.2) {
- // crop out the sides
- $margin = $width - $height;
- $img->cropImage(300,($margin / 2),0,$height,$height);
- }
- elseif(($height / $width) > 1.2) {
- // crop out the bottom
- $margin = $height - $width;
- $img->cropImage(300,0,0,$width,$width);
-
- }
- else {
- $img->scaleImageSquare(300);
- }
-
- }
- else
- $photo_failure = true;
-
- $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4);
-
- $r = $img->save($p);
-
- if($r === false)
- $photo_failure = true;
-
- $img->scaleImage(80);
- $p['imgscale'] = 5;
-
- $r = $img->save($p);
-
- if($r === false)
- $photo_failure = true;
-
- $img->scaleImage(48);
- $p['imgscale'] = 6;
-
- $r = $img->save($p);
-
- if($r === false)
- $photo_failure = true;
-
- $photo = z_root() . '/photo/' . $hash . '-4';
- $thumb = z_root() . '/photo/' . $hash . '-5';
- $micro = z_root() . '/photo/' . $hash . '-6';
- }
- else {
- logger('import_xchan_photo: invalid image from ' . $photo);
- $photo_failure = true;
- }
- }
- if($photo_failure) {
- $photo = z_root() . '/' . get_default_profile_photo();
- $thumb = z_root() . '/' . get_default_profile_photo(80);
- $micro = z_root() . '/' . get_default_profile_photo(48);
- $type = 'image/png';
- }
+/**
+ * @brief fetches an photo from external site and prepares its miniatures.
+ *
+ * @param string $photo
+ * external URL to fetch base image
+ * @param string $xchan
+ * channel unique hash
+ * @param boolean $thing
+ * TRUE if this is a thing URL
+ * @param boolean $force
+ * TRUE if ignore image modification date check (force fetch)
+ *
+ * @return array of results
+ * * \e string \b 0 => local URL to full image
+ * * \e string \b 1 => local URL to standard thumbnail
+ * * \e string \b 2 => local URL to micro thumbnail
+ * * \e string \b 3 => image type
+ * * \e boolean \b 4 => TRUE if fetch failure
+ * * \e string \b 5 => modification date
+ */
- return(array($photo,$thumb,$micro,$type,$photo_failure));
+function import_xchan_photo($photo,$xchan,$thing = false,$force = false) {
+
+ $modified = '';
+
+ $flags = (($thing) ? PHOTO_THING : PHOTO_XCHAN);
+ $album = (($thing) ? 'Things' : 'Contact Photos');
+
+ logger('import_xchan_photo: updating channel photo from ' . $photo . ' for ' . $xchan, LOGGER_DEBUG);
+
+ if($thing) {
+ $hash = photo_new_resource();
+ }
+ else {
+ $r = q("select resource_id, edited, mimetype from photo where xchan = '%s' and photo_usage = %d and imgscale = 4 limit 1",
+ dbesc($xchan),
+ intval(PHOTO_XCHAN)
+ );
+ if($r) {
+ $hash = $r[0]['resource_id'];
+ $modified = $r[0]['edited'];
+ $type = $r[0]['mimetype'];
+ }
+ else {
+ $hash = photo_new_resource();
+ }
+ }
+
+ $photo_failure = false;
+ $img_str = '';
+
+ if($photo) {
+ $filename = basename($photo);
+
+ if($force || $modified == '') {
+ $result = z_fetch_url($photo,true);
+ }
+ else {
+ $h = array('headers' => array("If-Modified-Since: " . gmdate("D, d M Y H:i:s", strtotime($modified . "Z")) . " GMT"));
+ $result = z_fetch_url($photo,true,0,$h);
+ }
+
+ if($result['success']) {
+ $img_str = $result['body'];
+ $type = guess_image_type($photo, $result['header']);
+ $modified = gmdate('Y-m-d H:i:s', (preg_match('/last-modified: (.+) \S+/i', $result['header'], $o) ? strtotime($o[1] . 'Z') : time()));
+
+ $h = explode("\n",$result['header']);
+ if($h) {
+ foreach($h as $hl) {
+ if(stristr($hl,'content-type:')) {
+ if(! stristr($hl,'image/')) {
+ $photo_failure = true;
+ }
+ }
+ }
+ }
+ }
+ elseif($result['return_code'] = 304) {
+ $photo = z_root() . '/photo/' . $hash . '-4';
+ $thumb = z_root() . '/photo/' . $hash . '-5';
+ $micro = z_root() . '/photo/' . $hash . '-6';
+ }
+ else {
+ $photo_failure = true;
+ }
+
+ }
+ else {
+ $photo_failure = true;
+ }
+
+ if(! $photo_failure && $result['return_code'] != 304) {
+ $img = photo_factory($img_str, $type);
+ if($img->is_valid()) {
+ $width = $img->getWidth();
+ $height = $img->getHeight();
+
+ if($width && $height) {
+ if(($width / $height) > 1.2) {
+ // crop out the sides
+ $margin = $width - $height;
+ $img->cropImage(300,($margin / 2),0,$height,$height);
+ }
+ elseif(($height / $width) > 1.2) {
+ // crop out the bottom
+ $margin = $height - $width;
+ $img->cropImage(300,0,0,$width,$width);
+
+ }
+ else {
+ $img->scaleImageSquare(300);
+ }
+
+ }
+ else
+ $photo_failure = true;
+
+ $p = array('xchan' => $xchan,'resource_id' => $hash, 'filename' => basename($photo), 'album' => $album, 'photo_usage' => $flags, 'imgscale' => 4);
+
+ $r = $img->save($p);
+
+ if($r === false)
+ $photo_failure = true;
+
+ $img->scaleImage(80);
+ $p['imgscale'] = 5;
+
+ $r = $img->save($p);
+
+ if($r === false)
+ $photo_failure = true;
+
+ $img->scaleImage(48);
+ $p['imgscale'] = 6;
+
+ $r = $img->save($p);
+
+ if($r === false)
+ $photo_failure = true;
+
+ $photo = z_root() . '/photo/' . $hash . '-4';
+ $thumb = z_root() . '/photo/' . $hash . '-5';
+ $micro = z_root() . '/photo/' . $hash . '-6';
+ }
+ else {
+ logger('import_xchan_photo: invalid image from ' . $photo);
+ $photo_failure = true;
+ }
+ }
+ if($photo_failure) {
+ $default = get_default_profile_photo();
+ $photo = z_root() . '/' . $default;
+ $thumb = z_root() . '/' . get_default_profile_photo(80);
+ $micro = z_root() . '/' . get_default_profile_photo(48);
+ $type = 'image/png';
+ $modified = gmdate('Y-m-d H:i:s', filemtime($default));
+ }
+
+ return(array($photo,$thumb,$micro,$type,$photo_failure,$modified));
}