diff options
-rw-r--r-- | _test/conf/acl.auth.php | 1 | ||||
-rw-r--r-- | _test/tests/inc/media_ispublic.test.php | 18 | ||||
-rw-r--r-- | inc/media.php | 14 | ||||
-rw-r--r-- | lib/exe/fetch.php | 67 | ||||
-rw-r--r-- | lib/plugins/auth.php | 43 |
5 files changed, 102 insertions, 41 deletions
diff --git a/_test/conf/acl.auth.php b/_test/conf/acl.auth.php index 8a1b01f23..495740720 100644 --- a/_test/conf/acl.auth.php +++ b/_test/conf/acl.auth.php @@ -19,6 +19,7 @@ # delete 16 * @ALL 8 +private:* @ALL 0 # for testing wildcards: users:* @ALL 1 diff --git a/_test/tests/inc/media_ispublic.test.php b/_test/tests/inc/media_ispublic.test.php new file mode 100644 index 000000000..307c64654 --- /dev/null +++ b/_test/tests/inc/media_ispublic.test.php @@ -0,0 +1,18 @@ +<?php + +class media_ispublic_test extends DokuWikiTest { + + + public function test_external(){ + $this->assertTrue(media_ispublic('http://www.example.com/foo.png')); + $this->assertTrue(media_ispublic('https://www.example.com/foo.png')); + $this->assertTrue(media_ispublic('hTTp://www.example.com/foo.png')); + $this->assertTrue(media_ispublic('hTTps://www.example.com/foo.png')); + } + + public function test_internal(){ + $this->assertTrue(media_ispublic('wiki:logo.png')); + $this->assertFalse(media_ispublic('private:logo.png')); + } + +}
\ No newline at end of file diff --git a/inc/media.php b/inc/media.php index db1ca0d57..501d170f3 100644 --- a/inc/media.php +++ b/inc/media.php @@ -83,6 +83,20 @@ function media_metasave($id,$auth,$data){ } /** + * Check if a media item is public (eg, external URL or readable by @ALL) + * + * @author Andreas Gohr <andi@splitbrain.org> + * @param string $id the media ID or URL + * @return bool + */ +function media_ispublic($id){ + if(preg_match('/^https?:\/\//i',$id)) return true; + $id = cleanID($id); + if(auth_aclcheck(getNS($id).':*', '', array()) >= AUTH_READ) return true; + return false; +} + +/** * Display the form to edit image meta data * * @author Andreas Gohr <andi@splitbrain.org> diff --git a/lib/exe/fetch.php b/lib/exe/fetch.php index 9bac4d272..a558a3db8 100644 --- a/lib/exe/fetch.php +++ b/lib/exe/fetch.php @@ -47,6 +47,7 @@ if(!defined('SIMPLE_TEST')) { 'height' => $HEIGHT, 'status' => $STATUS, 'statusmessage' => $STATUSMESSAGE, + 'ispublic' => media_ispublic($MEDIA), ); // handle the file status @@ -81,10 +82,10 @@ if(!defined('SIMPLE_TEST')) { // finally send the file to the client $evt = new Doku_Event('MEDIA_SENDFILE', $data); if($evt->advise_before()) { - sendFile($data['file'], $data['mime'], $data['download'], $data['cache']); + sendFile($data['file'], $data['mime'], $data['download'], $data['cache'], $data['ispublic']); } // Do something after the download finished. - $evt->advise_after(); + $evt->advise_after(); // will not be emitted on 304 or x-sendfile }// END DO main @@ -93,33 +94,59 @@ if(!defined('SIMPLE_TEST')) { /** * Set headers and send the file to the client * + * The $cache parameter influences how long files may be kept in caches, the $public parameter + * influences if this caching may happen in public proxis or in the browser cache only FS#2734 + * + * This function will abort the current script when a 304 is sent or file sending is handled + * through x-sendfile + * * @author Andreas Gohr <andi@splitbrain.org> * @author Ben Coburn <btcoburn@silicodon.net> + * @param string $file local file to send + * @param string $mime mime type of the file + * @param bool $dl set to true to force a browser download + * @param int $cache remaining cache time in seconds (-1 for $conf['cache'], 0 for no-cache) + * @param bool $public is this a public ressource or a private one? */ -function sendFile($file, $mime, $dl, $cache) { +function sendFile($file, $mime, $dl, $cache, $public = false) { global $conf; - $fmtime = @filemtime($file); - // send headers + // send mime headers header("Content-Type: $mime"); - // smart http caching headers + + // calculate cache times if($cache == -1) { - // cache - // cachetime or one hour - header('Expires: '.gmdate("D, d M Y H:i:s", time() + max($conf['cachetime'], 3600)).' GMT'); - header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($conf['cachetime'], 3600)); - header('Pragma: public'); + $maxage = max($conf['cachetime'], 3600); // cachetime or one hour + $expires = time() + $maxage; } else if($cache > 0) { - // recache - // remaining cachetime + 10 seconds so the newly recached media is used - header('Expires: '.gmdate("D, d M Y H:i:s", $fmtime + $conf['cachetime'] + 10).' GMT'); - header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.max($fmtime - time() + $conf['cachetime'] + 10, 0)); - header('Pragma: public'); - } else if($cache == 0) { - // nocache - header('Cache-Control: must-revalidate, no-transform, post-check=0, pre-check=0'); - header('Pragma: public'); + $maxage = $cache; // given time + $expires = time() + $maxage; + } else { // $cache == 0 + $maxage = 0; + $expires = 0; // 1970-01-01 + } + + // smart http caching headers + if($maxage) { + if($public) { + // cache publically + header('Expires: '.gmdate("D, d M Y H:i:s", $expires).' GMT'); + header('Cache-Control: public, proxy-revalidate, no-transform, max-age='.$maxage); + header('Pragma: public'); + } else { + // cache in browser + header('Expires: '.gmdate("D, d M Y H:i:s", $expires).' GMT'); + header('Cache-Control: private, no-transform, max-age='.$maxage); + header('Pragma: no-cache'); + } + } else { + // no cache at all + header('Expires: Thu, 01 Jan 1970 00:00:00 GMT'); + header('Cache-Control: no-cache, no-transform'); + header('Pragma: no-cache'); } + //send important headers first, script stops here if '304 Not Modified' response + $fmtime = @filemtime($file); http_conditionalRequest($fmtime); //download or display? diff --git a/lib/plugins/auth.php b/lib/plugins/auth.php index c14a04dfb..ec8ed7e58 100644 --- a/lib/plugins/auth.php +++ b/lib/plugins/auth.php @@ -9,8 +9,8 @@ if(!defined('DOKU_INC')) die(); * all auth classes should inherit from this class * * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) - * @author Chris Smith <chris@jalakai.co.uk> - * @author Jan Schumann <js@jschumann-it.com> + * @author Chris Smith <chris@jalakai.co.uk> + * @author Jan Schumann <js@jschumann-it.com> */ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { public $success = true; @@ -21,18 +21,18 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { * in the constructor. */ protected $cando = array( - 'addUser' => false, // can Users be created? - 'delUser' => false, // can Users be deleted? - 'modLogin' => false, // can login names be changed? - 'modPass' => false, // can passwords be changed? - 'modName' => false, // can real names be changed? - 'modMail' => false, // can emails be changed? - 'modGroups' => false, // can groups be changed? - 'getUsers' => false, // can a (filtered) list of users be retrieved? - 'getUserCount'=> false, // can the number of users be retrieved? - 'getGroups' => false, // can a list of available groups be retrieved? - 'external' => false, // does the module do external auth checking? - 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) + 'addUser' => false, // can Users be created? + 'delUser' => false, // can Users be deleted? + 'modLogin' => false, // can login names be changed? + 'modPass' => false, // can passwords be changed? + 'modName' => false, // can real names be changed? + 'modMail' => false, // can emails be changed? + 'modGroups' => false, // can groups be changed? + 'getUsers' => false, // can a (filtered) list of users be retrieved? + 'getUserCount' => false, // can the number of users be retrieved? + 'getGroups' => false, // can a list of available groups be retrieved? + 'external' => false, // does the module do external auth checking? + 'logout' => true, // can the user logout again? (eg. not possible with HTTP auth) ); /** @@ -102,7 +102,7 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { * example for enforcing a user name schema. * * @author Gabriel Birke <birke@d-scribe.de> - * @param string $type Modification type ('create', 'modify', 'delete') + * @param string $type Modification type ('create', 'modify', 'delete') * @param array $params Parameters for the createUser, modifyUser or deleteUsers method. The content of this array depends on the modification type * @return mixed Result from the modification function or false if an event handler has canceled the action */ @@ -162,7 +162,7 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { * The function needs to set some globals needed by * DokuWiki like auth_login() does. * - * @see auth_login() + * @see auth_login() * @author Andreas Gohr <andi@splitbrain.org> * * @param string $user Username @@ -425,16 +425,17 @@ class DokuWiki_Auth_Plugin extends DokuWiki_Plugin { * * @deprecated 2012-11-09 */ - public function loadConfig(){ + public function loadConfig() { global $conf; - $plugin = $this->getPluginName(); + $plugin = $this->getPluginName(); + $oldname = preg_replace('/^auth/', '', $plugin); $default = $this->readDefaultSettings(); $oldconf = array(); - if(isset($conf['auth'][$plugin])) $oldconf = (array) $conf['auth'][$plugin]; + if(isset($conf['auth'][$oldname])) $oldconf = (array) $conf['auth'][$oldname]; + $conf['plugin'][$plugin] = array_merge($default, $oldconf, (array) $conf['plugin'][$plugin]); - $conf['plugin'][$plugin] = array_merge($default, $oldconf, $conf['plugin'][$plugin]); - $this->conf =& $conf['plugin'][$plugin]; + $this->conf =& $conf['plugin'][$plugin]; $this->configloaded = true; } } |