diff options
-rw-r--r-- | Zotlabs/Lib/ThreadItem.php | 2 | ||||
-rw-r--r-- | Zotlabs/Module/New_channel.php | 4 | ||||
-rw-r--r-- | Zotlabs/Module/Profile_photo.php | 2 | ||||
-rw-r--r-- | Zotlabs/Storage/Directory.php | 284 | ||||
-rw-r--r-- | include/feedutils.php | 4 | ||||
-rw-r--r-- | include/nav.php | 13 | ||||
-rw-r--r-- | include/reddav.php | 299 | ||||
-rw-r--r-- | include/spam.php | 35 | ||||
-rw-r--r-- | include/text.php | 16 | ||||
-rw-r--r-- | view/tpl/force_image_reload.tpl | 72 |
10 files changed, 386 insertions, 345 deletions
diff --git a/Zotlabs/Lib/ThreadItem.php b/Zotlabs/Lib/ThreadItem.php index 6625b7b52..638afeb6b 100644 --- a/Zotlabs/Lib/ThreadItem.php +++ b/Zotlabs/Lib/ThreadItem.php @@ -248,7 +248,7 @@ class ThreadItem { $has_bookmarks = false; if(is_array($item['term'])) { foreach($item['term'] as $t) { - if(!UNO && $t['type'] == TERM_BOOKMARK) + if(!UNO && $t['ttype'] == TERM_BOOKMARK) $has_bookmarks = true; } } diff --git a/Zotlabs/Module/New_channel.php b/Zotlabs/Module/New_channel.php index 1dcf84fb0..26883b6e2 100644 --- a/Zotlabs/Module/New_channel.php +++ b/Zotlabs/Module/New_channel.php @@ -125,9 +125,9 @@ class New_channel extends \Zotlabs\Web\Controller { } } - $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"')); + $name = array('name', t('Name or caption'), ((x($_REQUEST,'name')) ? $_REQUEST['name'] : ''), t('Examples: "Bob Jameson", "Lisa and her Horses", "Soccer", "Aviation Group"'), "*"); $nickhub = '@' . \App::get_hostname(); - $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub)); + $nickname = array('nickname', t('Choose a short nickname'), ((x($_REQUEST,'nickname')) ? $_REQUEST['nickname'] : ''), sprintf( t('Your nickname will be used to create an easy to remember channel address e.g. nickname%s'), $nickhub), "*"); $privacy_role = ((x($_REQUEST,'permissions_role')) ? $_REQUEST['permissions_role'] : "" ); $role = array('permissions_role' , t('Channel role and privacy'), ($privacy_role) ? $privacy_role : 'social', t('Select a channel role with your privacy requirements.') . ' <a href="help/roles" target="_blank">' . t('Read more about roles') . '</a>',get_roles()); diff --git a/Zotlabs/Module/Profile_photo.php b/Zotlabs/Module/Profile_photo.php index 9359b80f8..f459f7deb 100644 --- a/Zotlabs/Module/Profile_photo.php +++ b/Zotlabs/Module/Profile_photo.php @@ -180,6 +180,8 @@ class Profile_photo extends \Zotlabs\Web\Controller { dbesc(datetime_convert()), dbesc($channel['xchan_hash']) ); + // Similarly, tell the nav bar to bypass the cache and update the avater image. + $_SESSION['reload_avatar'] = true; info( t('Shift-reload the page or clear browser cache if the new photo does not display immediately.') . EOL); diff --git a/Zotlabs/Storage/Directory.php b/Zotlabs/Storage/Directory.php index 06ae90a5f..7a2d9e68b 100644 --- a/Zotlabs/Storage/Directory.php +++ b/Zotlabs/Storage/Directory.php @@ -91,7 +91,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { throw new DAV\Exception\Forbidden('Permission denied.'); } - $contents = RedCollectionData($this->red_path, $this->auth); + $contents = $this->CollectionData($this->red_path, $this->auth); return $contents; } @@ -119,7 +119,7 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { return new Directory('/' . $modulename, $this->auth); } - $x = RedFileData($this->ext_path . '/' . $name, $this->auth); + $x = $this->FileData($this->ext_path . '/' . $name, $this->auth); if ($x) { return $x; } @@ -431,8 +431,8 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { return true; } - $x = RedFileData($this->ext_path . '/' . $name, $this->auth, true); - //logger('RedFileData returns: ' . print_r($x, true), LOGGER_DATA); + $x = $this->FileData($this->ext_path . '/' . $name, $this->auth, true); + //logger('FileData returns: ' . print_r($x, true), LOGGER_DATA); if ($x) return true; @@ -565,4 +565,280 @@ class Directory extends DAV\Node implements DAV\ICollection, DAV\IQuota { $free ); } + + + /** + * @brief Array with all Directory and File DAV\Node items for the given path. + * + * + * @param string $file path to a directory + * @param \Zotlabs\Storage\BasicAuth &$auth + * @returns null|array \Sabre\DAV\INode[] + * @throw \Sabre\DAV\Exception\Forbidden + * @throw \Sabre\DAV\Exception\NotFound + */ + + function CollectionData($file, &$auth) { + $ret = array(); + + $x = strpos($file, '/cloud'); + if ($x === 0) { + $file = substr($file, 6); + } + + // return a list of channel if we are not inside a channel + if ((! $file) || ($file === '/')) { + return $this->ChannelList($auth); + } + + $file = trim($file, '/'); + $path_arr = explode('/', $file); + + if (! $path_arr) + return null; + + $channel_name = $path_arr[0]; + + $r = q("SELECT channel_id FROM channel WHERE channel_address = '%s' LIMIT 1", + dbesc($channel_name) + ); + + if (! $r) + return null; + + $channel_id = $r[0]['channel_id']; + $perms = permissions_sql($channel_id); + + $auth->owner_id = $channel_id; + + $path = '/' . $channel_name; + + $folder = ''; + $errors = false; + $permission_error = false; + + for ($x = 1; $x < count($path_arr); $x++) { + $r = q("SELECT id, hash, filename, flags, is_dir FROM attach WHERE folder = '%s' AND filename = '%s' AND uid = %d AND is_dir != 0 $perms LIMIT 1", + dbesc($folder), + dbesc($path_arr[$x]), + intval($channel_id) + ); + if (! $r) { + // path wasn't found. Try without permissions to see if it was the result of permissions. + $errors = true; + $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 limit 1", + dbesc($folder), + basename($path_arr[$x]), + intval($channel_id) + ); + if ($r) { + $permission_error = true; + } + break; + } + + if ($r && intval($r[0]['is_dir'])) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + } + + if ($errors) { + if ($permission_error) { + throw new DAV\Exception\Forbidden('Permission denied.'); + } + else { + throw new DAV\Exception\NotFound('A component of the request file path could not be found.'); + } + } + + // This should no longer be needed since we just returned errors for paths not found + if ($path !== '/' . $file) { + logger("Path mismatch: $path !== /$file"); + return NULL; + } + if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { + $prefix = 'DISTINCT ON (filename)'; + $suffix = 'ORDER BY filename'; + } + else { + $prefix = ''; + $suffix = 'GROUP BY filename'; + } + $r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix", + dbesc($folder), + intval($channel_id) + ); + + foreach ($r as $rr) { + //logger('filename: ' . $rr['filename'], LOGGER_DEBUG); + if (intval($rr['is_dir'])) { + $ret[] = new Directory($path . '/' . $rr['filename'], $auth); + } + else { + $ret[] = new File($path . '/' . $rr['filename'], $rr, $auth); + } + } + + return $ret; + } + + + /** + * @brief Returns an array with viewable channels. + * + * Get a list of Directory objects with all the channels where the visitor + * has <b>view_storage</b> perms. + * + * + * @param BasicAuth &$auth + * @return array Directory[] + */ + + function ChannelList(&$auth) { + $ret = array(); + + $r = q("SELECT channel_id, channel_address FROM channel WHERE channel_removed = 0 + AND channel_system = 0 AND NOT (channel_pageflags & %d)>0", + intval(PAGE_HIDDEN) + ); + + if ($r) { + foreach ($r as $rr) { + if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) { + logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA); + // @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory + $ret[] = new Directory('/cloud/' . $rr['channel_address'], $auth); + } + } + } + return $ret; + } + + + /** + * @brief + * + * + * @param string $file + * path to file or directory + * @param BasicAuth &$auth + * @param boolean $test (optional) enable test mode + * @return File|Directory|boolean|null + * @throw \Sabre\DAV\Exception\Forbidden + */ + + function FileData($file, &$auth, $test = false) { + logger($file . (($test) ? ' (test mode) ' : ''), LOGGER_DATA); + + $x = strpos($file, '/cloud'); + if ($x === 0) { + $file = substr($file, 6); + } + else { + $x = strpos($file,'/dav'); + if($x === 0) + $file = substr($file,4); + } + + + if ((! $file) || ($file === '/')) { + return new Directory('/', $auth); + } + + $file = trim($file, '/'); + + $path_arr = explode('/', $file); + + if (! $path_arr) + return null; + + $channel_name = $path_arr[0]; + + $r = q("select channel_id from channel where channel_address = '%s' limit 1", + dbesc($channel_name) + ); + + if (! $r) + return null; + + $channel_id = $r[0]['channel_id']; + + $path = '/' . $channel_name; + + $auth->owner_id = $channel_id; + + $permission_error = false; + + $folder = ''; + + require_once('include/security.php'); + $perms = permissions_sql($channel_id); + + $errors = false; + + for ($x = 1; $x < count($path_arr); $x++) { + $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 $perms", + dbesc($folder), + dbesc($path_arr[$x]), + intval($channel_id) + ); + + if ($r && intval($r[0]['is_dir'])) { + $folder = $r[0]['hash']; + $path = $path . '/' . $r[0]['filename']; + } + if (! $r) { + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach + where folder = '%s' and filename = '%s' and uid = %d $perms order by filename limit 1", + dbesc($folder), + dbesc(basename($file)), + intval($channel_id) + ); + } + if (! $r) { + $errors = true; + $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach + where folder = '%s' and filename = '%s' and uid = %d order by filename limit 1", + dbesc($folder), + dbesc(basename($file)), + intval($channel_id) + ); + if ($r) + $permission_error = true; + } + } + + if ($path === '/' . $file) { + if ($test) + return true; + // final component was a directory. + return new Directory($file, $auth); + } + + if ($errors) { + logger('not found ' . $file); + if ($test) + return false; + if ($permission_error) { + logger('permission error ' . $file); + throw new DAV\Exception\Forbidden('Permission denied.'); + } + return; + } + + if ($r) { + if ($test) + return true; + + if (intval($r[0]['is_dir'])) { + return new Directory($path . '/' . $r[0]['filename'], $auth); + } + else { + return new File($path . '/' . $r[0]['filename'], $r[0], $auth); + } + } + return false; + } + } diff --git a/include/feedutils.php b/include/feedutils.php index 685b2f982..01ec0687e 100644 --- a/include/feedutils.php +++ b/include/feedutils.php @@ -393,7 +393,7 @@ function get_atom_elements($feed, $item, &$author) { $terms = array(); $terms[] = array( 'otype' => TERM_OBJ_POST, - 'type' => TERM_BOOKMARK, + 'ttype' => TERM_BOOKMARK, 'url' => $res['plink'], 'term' => $res['title'], ); @@ -403,7 +403,7 @@ function get_atom_elements($feed, $item, &$author) { $terms = array(); $terms[] = array( 'otype' => TERM_OBJ_POST, - 'type' => TERM_BOOKMARK, + 'ttype' => TERM_BOOKMARK, 'url' => $res['plink'], 'term' => $res['plink'], ); diff --git a/include/nav.php b/include/nav.php index 6a79b6530..1fb0e98dc 100644 --- a/include/nav.php +++ b/include/nav.php @@ -255,6 +255,19 @@ $powered_by = ''; '$pleasewait' => t('Please wait...') )); + + if(x($_SESSION, 'reload_avatar') && $observer) { + // The avatar has been changed on the server but the browser doesn't know that, + // force the browser to reload the image from the server instead of its cache. + $tpl = get_markup_template('force_image_reload.tpl'); + + App::$page['nav'] .= replace_macros($tpl, array( + '$imgUrl' => $observer['xchan_photo_m'] + )); + unset($_SESSION['reload_avatar']); + } + + call_hooks('page_header', App::$page['nav']); } diff --git a/include/reddav.php b/include/reddav.php deleted file mode 100644 index abf21b86d..000000000 --- a/include/reddav.php +++ /dev/null @@ -1,299 +0,0 @@ -<?php -/** - * @file include/reddav.php - * @brief some DAV related functions for Hubzilla. - * - * This file contains some functions which did not fit into one of the RedDAV - * classes. - * - * The extended SabreDAV classes you will find in the RedDAV namespace under - * @ref includes/RedDAV/. - * The original SabreDAV classes you can find under @ref vendor/sabre/dav/. - * We need to use SabreDAV 1.8.x for PHP5.3 compatibility. SabreDAV >= 2.0 - * requires PHP >= 5.4. - * - * @todo split up the classes into own files. - * - * @link http://github.com/friendica/red - * @license http://opensource.org/licenses/mit-license.php The MIT License (MIT) - */ - -use Sabre\DAV; -use Zotlabs\Storage; - -require_once('vendor/autoload.php'); -require_once('include/attach.php'); - -/** - * @brief Returns an array with viewable channels. - * - * Get a list of RedDirectory objects with all the channels where the visitor - * has <b>view_storage</b> perms. - * - * @todo Is there any reason why this is not inside RedDirectory class? - * @fixme function name looks like a class name, should we rename it? - * - * @param RedBasicAuth &$auth - * @return array RedDirectory[] - */ -function RedChannelList(&$auth) { - $ret = array(); - - $r = q("SELECT channel_id, channel_address FROM channel WHERE channel_removed = 0 AND channel_system = 0 AND NOT (channel_pageflags & %d)>0", - intval(PAGE_HIDDEN) - ); - - if ($r) { - foreach ($r as $rr) { - if (perm_is_allowed($rr['channel_id'], $auth->observer, 'view_storage')) { - logger('found channel: /cloud/' . $rr['channel_address'], LOGGER_DATA); - // @todo can't we drop '/cloud'? It gets stripped off anyway in RedDirectory - $ret[] = new Zotlabs\Storage\Directory('/cloud/' . $rr['channel_address'], $auth); - } - } - } - return $ret; -} - - -/** - * @brief TODO what exactly does this function? - * - * Array with all RedDirectory and RedFile DAV\Node items for the given path. - * - * @todo Is there any reason why this is not inside RedDirectory class? Seems - * only to be used there and we could simplify it a bit there. - * @fixme function name looks like a class name, should we rename it? - * - * @param string $file path to a directory - * @param RedBasicAuth &$auth - * @returns null|array \Sabre\DAV\INode[] - * @throw \Sabre\DAV\Exception\Forbidden - * @throw \Sabre\DAV\Exception\NotFound - */ -function RedCollectionData($file, &$auth) { - $ret = array(); - - $x = strpos($file, '/cloud'); - if ($x === 0) { - $file = substr($file, 6); - } - - // return a list of channel if we are not inside a channel - if ((! $file) || ($file === '/')) { - return RedChannelList($auth); - } - - $file = trim($file, '/'); - $path_arr = explode('/', $file); - - if (! $path_arr) - return null; - - $channel_name = $path_arr[0]; - - $r = q("SELECT channel_id FROM channel WHERE channel_address = '%s' LIMIT 1", - dbesc($channel_name) - ); - - if (! $r) - return null; - - $channel_id = $r[0]['channel_id']; - $perms = permissions_sql($channel_id); - - $auth->owner_id = $channel_id; - - $path = '/' . $channel_name; - - $folder = ''; - $errors = false; - $permission_error = false; - - for ($x = 1; $x < count($path_arr); $x++) { - $r = q("SELECT id, hash, filename, flags, is_dir FROM attach WHERE folder = '%s' AND filename = '%s' AND uid = %d AND is_dir != 0 $perms LIMIT 1", - dbesc($folder), - dbesc($path_arr[$x]), - intval($channel_id) - ); - if (! $r) { - // path wasn't found. Try without permissions to see if it was the result of permissions. - $errors = true; - $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 limit 1", - dbesc($folder), - basename($path_arr[$x]), - intval($channel_id) - ); - if ($r) { - $permission_error = true; - } - break; - } - - if ($r && intval($r[0]['is_dir'])) { - $folder = $r[0]['hash']; - $path = $path . '/' . $r[0]['filename']; - } - } - - if ($errors) { - if ($permission_error) { - throw new DAV\Exception\Forbidden('Permission denied.'); - } else { - throw new DAV\Exception\NotFound('A component of the request file path could not be found.'); - } - } - - // This should no longer be needed since we just returned errors for paths not found - if ($path !== '/' . $file) { - logger("Path mismatch: $path !== /$file"); - return NULL; - } - if(ACTIVE_DBTYPE == DBTYPE_POSTGRES) { - $prefix = 'DISTINCT ON (filename)'; - $suffix = 'ORDER BY filename'; - } else { - $prefix = ''; - $suffix = 'GROUP BY filename'; - } - $r = q("select $prefix id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, created, edited from attach where folder = '%s' and uid = %d $perms $suffix", - dbesc($folder), - intval($channel_id) - ); - - foreach ($r as $rr) { - //logger('filename: ' . $rr['filename'], LOGGER_DEBUG); - if (intval($rr['is_dir'])) { - $ret[] = new Zotlabs\Storage\Directory($path . '/' . $rr['filename'], $auth); - } else { - $ret[] = new Zotlabs\Storage\File($path . '/' . $rr['filename'], $rr, $auth); - } - } - - return $ret; -} - - -/** - * @brief TODO What exactly is this function for? - * - * @fixme function name looks like a class name, should we rename it? - * - * @param string $file - * path to file or directory - * @param RedBasicAuth &$auth - * @param boolean $test (optional) enable test mode - * @return RedFile|RedDirectory|boolean|null - * @throw \Sabre\DAV\Exception\Forbidden - */ -function RedFileData($file, &$auth, $test = false) { - logger($file . (($test) ? ' (test mode) ' : ''), LOGGER_DATA); - - $x = strpos($file, '/cloud'); - if ($x === 0) { - $file = substr($file, 6); - } - else { - $x = strpos($file,'/dav'); - if($x === 0) - $file = substr($file,4); - } - - - if ((! $file) || ($file === '/')) { - return new Zotlabs\Storage\Directory('/', $auth); - } - - $file = trim($file, '/'); - - $path_arr = explode('/', $file); - - if (! $path_arr) - return null; - - $channel_name = $path_arr[0]; - - $r = q("select channel_id from channel where channel_address = '%s' limit 1", - dbesc($channel_name) - ); - - if (! $r) - return null; - - $channel_id = $r[0]['channel_id']; - - $path = '/' . $channel_name; - - $auth->owner_id = $channel_id; - - $permission_error = false; - - $folder = ''; - - require_once('include/security.php'); - $perms = permissions_sql($channel_id); - - $errors = false; - - for ($x = 1; $x < count($path_arr); $x++) { - $r = q("select id, hash, filename, flags, is_dir from attach where folder = '%s' and filename = '%s' and uid = %d and is_dir != 0 $perms", - dbesc($folder), - dbesc($path_arr[$x]), - intval($channel_id) - ); - - if ($r && intval($r[0]['is_dir'])) { - $folder = $r[0]['hash']; - $path = $path . '/' . $r[0]['filename']; - } - if (! $r) { - $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach - where folder = '%s' and filename = '%s' and uid = %d $perms order by filename limit 1", - dbesc($folder), - dbesc(basename($file)), - intval($channel_id) - ); - } - if (! $r) { - $errors = true; - $r = q("select id, uid, hash, filename, filetype, filesize, revision, folder, flags, is_dir, os_storage, created, edited from attach - where folder = '%s' and filename = '%s' and uid = %d order by filename limit 1", - dbesc($folder), - dbesc(basename($file)), - intval($channel_id) - ); - if ($r) - $permission_error = true; - } - } - - if ($path === '/' . $file) { - if ($test) - return true; - // final component was a directory. - return new Zotlabs\Storage\Directory($file, $auth); - } - - if ($errors) { - logger('not found ' . $file); - if ($test) - return false; - if ($permission_error) { - logger('permission error ' . $file); - throw new DAV\Exception\Forbidden('Permission denied.'); - } - return; - } - - if ($r) { - if ($test) - return true; - - if (intval($r[0]['is_dir'])) { - return new Zotlabs\Storage\Directory($path . '/' . $r[0]['filename'], $auth); - } else { - return new Zotlabs\Storage\File($path . '/' . $r[0]['filename'], $r[0], $auth); - } - } - return false; -}
\ No newline at end of file diff --git a/include/spam.php b/include/spam.php deleted file mode 100644 index 8b158b7ae..000000000 --- a/include/spam.php +++ /dev/null @@ -1,35 +0,0 @@ -<?php /** @file */ - - -function string_splitter($s) { - - if(! $s) - return array(); - - $s = preg_replace('/\pP+/','',$s); - - $x = mb_split("\[|\]|\s",$s); - - $ret = array(); - if($x) { - foreach($x as $y) { - if(mb_strlen($y) > 2) - $ret[] = substr($y,0,64); - } - } - return $ret; -} - - - -function get_words($uid,$list) { - - stringify($list,true); - - $r = q("select * from spam where term in ( " . $list . ") and uid = %d", - intval($uid) - ); - - return $r; -} - diff --git a/include/text.php b/include/text.php index 89c3a0539..986e3b56c 100644 --- a/include/text.php +++ b/include/text.php @@ -2354,7 +2354,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d $str_tags .= $newtag; } - return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $basetag, 'url' => $url, 'contact' => $r[0]); + return [ + 'replaced' => $replaced, + 'termtype' => $termtype, + 'term' => $basetag, + 'url' => $url, + 'contact' => $r[0] + ]; } //is it a person tag? @@ -2545,7 +2551,13 @@ function handle_tag($a, &$body, &$access_tag, &$str_tags, $profile_uid, $tag, $d } } - return array('replaced' => $replaced, 'termtype' => $termtype, 'term' => $newname, 'url' => $url, 'contact' => $r[0]); + return [ + 'replaced' => $replaced, + 'termtype' => $termtype, + 'term' => $newname, + 'url' => $url, + 'contact' => $r[0] + ]; } function linkify_tags($a, &$body, $uid, $diaspora = false) { diff --git a/view/tpl/force_image_reload.tpl b/view/tpl/force_image_reload.tpl new file mode 100644 index 000000000..839bd22b5 --- /dev/null +++ b/view/tpl/force_image_reload.tpl @@ -0,0 +1,72 @@ +{{* +Force the browser to reload an image from the server instead of the cache. +based on an answer from http://stackoverflow.com/a/22429796/3343347 + +Usage: Set $imgUrl to the src url you want to be re-fetched from the server + +*}} + +<script> + $(document).ready( + function() { + forceImgReload("{{$imgUrl}}"); + } + ); + + {{* + * find and return any existing img tags with a matching src url, and set them to an intermediate + * src url so they can later be reverted back once the cached version has been updated. + *}} + function prepareImagesForReload(srcUrl) { + + var result = $("img[src='" + srcUrl + "']").get(); + + for (i = 0; i < result.length; i++) { + {{* + * Set the image to a reloading image, in this case an animated "reloading" svg + * Ideally this wont be displayed long enough to matter. + *}} + result[i].src = "data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100' preserveAspectRatio='xMidYMid' class='uil-reload'%3E%3Cpath fill='none' class='bk' d='M0 0h100v100H0z'/%3E%3Cg%3E%3Cpath d='M50 15a35 35 0 1 0 24.787 10.213' fill='none' stroke='%23777' stroke-width='12'/%3E%3Cpath d='M50 0v30l16-15L50 0' fill='%23777'/%3E%3CanimateTransform attributeName='transform' type='rotate' from='0 50 50' to='360 50 50' dur='1s' repeatCount='indefinite'/%3E%3C/g%3E%3C/svg%3E"; + } + + return result; + } + + function restoreImages(srcUrl, imgList) { + + for (i = 0; i < imgList.length; i++) { + imgList[i].src = srcUrl; + } + } + + function forceImgReload(srcUrl) { + var imgList; + var step = 0; + var iframe = window.document.createElement("iframe"); // Hidden iframe, in which to perform the load+reload. + + {{* Callback function, called after iframe load+reload completes (or fails). + Will be called TWICE unless twostage-mode process is cancelled. (Once after load, once after reload). *}} + var iframeLoadCallback = function(e) { + + if (step === 0) { + // initial load just completed. Note that it doesn't actually matter if this load succeeded or not. + + step = 1; + imgList = prepareImagesForReload(srcUrl); + iframe.contentWindow.location.reload(true); // initiate forced-reload! + + } else if (step === 1) { + // forced re-load is done + + restoreImages(srcUrl, imgList); + if (iframe.parentNode) iframe.parentNode.removeChild(iframe); + } + } + + iframe.style.display = "none"; + window.parent.document.body.appendChild(iframe); {{* NOTE: if this is done AFTER setting src, Firefox MAY fail to fire the load event! *}} + iframe.addEventListener("load", iframeLoadCallback, false); + iframe.addEventListener("error", iframeLoadCallback, false); + iframe.src = srcUrl; + } +</script> |