From c29dc6e4219a920b505ef667b82d4f601b34e52b Mon Sep 17 00:00:00 2001 From: Andreas Gohr <andi@splitbrain.org> Date: Sat, 16 Sep 2006 23:02:29 +0200 Subject: [PATCH] updatecheck feature This patch adds a feature to let DokuWiki automatically check if updates are available or any other important messages (like security warnings) and then display this info to the admin user. DokuWiki will contact the URL http://www.splitbrain.org/lib/exe/msg.php with a parameter telling it which messages it already know (read from conf/msg) - the server side script then will return all new messages. The messages will be displayed until DokuWiki was upgraded or conf/msg was updated manually. Messages are cached and only checked once a day. The messenger URL will probably change before the next release. darcs-hash:20060916210229-7ad00-7ac592650e171ae4144b0eb47a751a4ca480f031.gz --- conf/dokuwiki.php | 5 + doku.php | 3 + inc/common.php | 218 +-------------- inc/infoutils.php | 250 ++++++++++++++++++ lib/images/notify.png | Bin 0 -> 789 bytes lib/plugins/config/lang/en/lang.php | 1 + .../config/settings/config.metadata.php | 1 + lib/styles/style.css | 11 + 8 files changed, 279 insertions(+), 210 deletions(-) create mode 100644 inc/infoutils.php create mode 100644 lib/images/notify.png diff --git a/conf/dokuwiki.php b/conf/dokuwiki.php index 542431029..972c4f57e 100644 --- a/conf/dokuwiki.php +++ b/conf/dokuwiki.php @@ -1,6 +1,10 @@ <?php /** * This is DokuWiki's Main Configuration file + * + * All the default values are kept here, you should not modify it but use + * a local.conf.php file instaed to override the settings from here. + * * This is a piece of PHP code so PHP syntax applies! * * For help with the configuration see http://www.splitbrain.org/dokuwiki/wiki:config @@ -62,6 +66,7 @@ $conf['profileconfirm'] = '1'; //Require current password to confirm c $conf['disableactions'] = ''; //comma separated list of actions to disable /* Advanced Options */ +$conf['updatecheck'] = 1; //automatically check for new releases? $conf['userewrite'] = 0; //this makes nice URLs: 0: off 1: .htaccess 2: internal $conf['useslash'] = 0; //use slash instead of colon? only when rewrite is on $conf['usedraft'] = 1; //automatically save a draft while editing (0|1) diff --git a/doku.php b/doku.php index d2be871b2..48ac56682 100644 --- a/doku.php +++ b/doku.php @@ -63,6 +63,9 @@ //prepare breadcrumbs (initialize a static var) breadcrumbs(); + // check upstream + checkUpdateMessages(); + trigger_event('DOKUWIKI_STARTED',$tmp=array()); //close session diff --git a/inc/common.php b/inc/common.php index 016c7922d..271446f55 100644 --- a/inc/common.php +++ b/inc/common.php @@ -6,13 +6,14 @@ * @author Andreas Gohr <andi@splitbrain.org> */ - if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); - require_once(DOKU_CONF.'dokuwiki.php'); - require_once(DOKU_INC.'inc/io.php'); - require_once(DOKU_INC.'inc/changelog.php'); - require_once(DOKU_INC.'inc/utf8.php'); - require_once(DOKU_INC.'inc/mail.php'); - require_once(DOKU_INC.'inc/parserutils.php'); +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); +require_once(DOKU_CONF.'dokuwiki.php'); +require_once(DOKU_INC.'inc/io.php'); +require_once(DOKU_INC.'inc/changelog.php'); +require_once(DOKU_INC.'inc/utf8.php'); +require_once(DOKU_INC.'inc/mail.php'); +require_once(DOKU_INC.'inc/parserutils.php'); +require_once(DOKU_INC.'inc/infoutils.php'); /** * These constants are used with the recents function @@ -168,45 +169,6 @@ function buildAttributes($params){ } -/** - * print a message - * - * If HTTP headers were not sent yet the message is added - * to the global message array else it's printed directly - * using html_msgarea() - * - * - * Levels can be: - * - * -1 error - * 0 info - * 1 success - * - * @author Andreas Gohr <andi@splitbrain.org> - * @see html_msgarea - */ -function msg($message,$lvl=0,$line='',$file=''){ - global $MSG; - $errors[-1] = 'error'; - $errors[0] = 'info'; - $errors[1] = 'success'; - - if($line || $file) $message.=' ['.basename($file).':'.$line.']'; - - if(!headers_sent()){ - if(!isset($MSG)) $MSG = array(); - $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); - }else{ - $MSG = array(); - $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); - if(function_exists('html_msgarea')){ - html_msgarea(); - }else{ - print "ERROR($lvl) $message"; - } - } -} - /** * This builds the breadcrumb trail and returns it as array * @@ -695,34 +657,6 @@ function con($pre,$text,$suf,$pretty=false){ return $pre.$text.$suf; } -/** - * print debug messages - * - * little function to print the content of a var - * - * @author Andreas Gohr <andi@splitbrain.org> - */ -function dbg($msg,$hidden=false){ - (!$hidden) ? print '<pre class="dbg">' : print "<!--\n"; - print_r($msg); - (!$hidden) ? print '</pre>' : print "\n-->"; -} - -/** - * Print info to a log file - * - * @author Andreas Gohr <andi@splitbrain.org> - */ -function dbglog($msg){ - global $conf; - $file = $conf['cachedir'].'/debug.log'; - $fh = fopen($file,'a'); - if($fh){ - fwrite($fh,date('H:i:s ').$_SERVER['REMOTE_ADDR'].': '.$msg."\n"); - fclose($fh); - } -} - /** * Saves a wikitext by calling io_writeWikiPage * @@ -968,142 +902,6 @@ function obfuscate($email) { } } -/** - * Return DokuWikis version - * - * @author Andreas Gohr <andi@splitbrain.org> - */ -function getVersion(){ - //import version string - if(@file_exists('VERSION')){ - //official release - return 'Release '.trim(io_readfile(DOKU_INC.'/VERSION')); - }elseif(is_dir('_darcs')){ - //darcs checkout - read last 2000 bytes of inventory - $sz = filesize('_darcs/inventory'); - $seek = max(0,$sz-2000); - $fh = fopen('_darcs/inventory','rb'); - fseek($fh,$seek); - $chunk = fread($fh,2000); - fclose($fh); - $inv = preg_grep('#\*\*\d{14}[\]$]#',explode("\n",$chunk)); - $cur = array_pop($inv); - preg_match('#\*\*(\d{4})(\d{2})(\d{2})#',$cur,$matches); - return 'Darcs '.$matches[1].'-'.$matches[2].'-'.$matches[3]; - }else{ - return 'snapshot?'; - } -} - -/** - * Run a few sanity checks - * - * @author Andreas Gohr <andi@splitbrain.org> - */ -function check(){ - global $conf; - global $INFO; - - msg('DokuWiki version: '.getVersion(),1); - - if(version_compare(phpversion(),'4.3.0','<')){ - msg('Your PHP version is too old ('.phpversion().' vs. 4.3.+ recommended)',-1); - }elseif(version_compare(phpversion(),'4.3.10','<')){ - msg('Consider upgrading PHP to 4.3.10 or higher for security reasons (your version: '.phpversion().')',0); - }else{ - msg('PHP version '.phpversion(),1); - } - - if(is_writable($conf['changelog'])){ - msg('Changelog is writable',1); - }else{ - if (@file_exists($conf['changelog'])) { - msg('Changelog is not writable',-1); - } - } - - if (isset($conf['changelog_old']) && @file_exists($conf['changelog_old'])) { - msg('Old changelog exists.', 0); - } - - if (@file_exists($conf['changelog'].'_failed')) { - msg('Importing old changelog failed.', -1); - } else if (@file_exists($conf['changelog'].'_importing')) { - msg('Importing old changelog now.', 0); - } else if (@file_exists($conf['changelog'].'_import_ok')) { - msg('Old changelog imported.', 1); - if (!plugin_isdisabled('importoldchangelog')) { - msg('Importoldchangelog plugin not disabled after import.', -1); - } - } - - if(is_writable($conf['datadir'])){ - msg('Datadir is writable',1); - }else{ - msg('Datadir is not writable',-1); - } - - if(is_writable($conf['olddir'])){ - msg('Attic is writable',1); - }else{ - msg('Attic is not writable',-1); - } - - if(is_writable($conf['mediadir'])){ - msg('Mediadir is writable',1); - }else{ - msg('Mediadir is not writable',-1); - } - - if(is_writable($conf['cachedir'])){ - msg('Cachedir is writable',1); - }else{ - msg('Cachedir is not writable',-1); - } - - if(is_writable($conf['lockdir'])){ - msg('Lockdir is writable',1); - }else{ - msg('Lockdir is not writable',-1); - } - - if(is_writable(DOKU_CONF.'users.auth.php')){ - msg('conf/users.auth.php is writable',1); - }else{ - msg('conf/users.auth.php is not writable',0); - } - - if(function_exists('mb_strpos')){ - if(defined('UTF8_NOMBSTRING')){ - msg('mb_string extension is available but will not be used',0); - }else{ - msg('mb_string extension is available and will be used',1); - } - }else{ - msg('mb_string extension not available - PHP only replacements will be used',0); - } - - if($conf['allowdebug']){ - msg('Debugging support is enabled. If you don\'t need it you should set $conf[\'allowdebug\'] = 0',-1); - }else{ - msg('Debugging support is disabled',1); - } - - msg('Your current permission for this page is '.$INFO['perm'],0); - - if(is_writable($INFO['filepath'])){ - msg('The current page is writable by the webserver',0); - }else{ - msg('The current page is not writable by the webserver',0); - } - - if($INFO['writable']){ - msg('The current page is writable by you',0); - }else{ - msg('The current page is not writable you',0); - } -} - /** * Let us know if a user is tracking a page * diff --git a/inc/infoutils.php b/inc/infoutils.php new file mode 100644 index 000000000..fcaba23cf --- /dev/null +++ b/inc/infoutils.php @@ -0,0 +1,250 @@ +<?php +/** + * Information and debugging functions + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ +if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/'); +if(!defined('DOKU_MESSAGEURL')) define('DOKU_MESSAGEURL','http://www.splitbrain.org/lib/exe/msg.php?msg='); +require_once(DOKU_INC.'inc/HTTPClient.php'); + +/** + * Check for new messages from upstream + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function checkUpdateMessages(){ + global $conf; + global $INFO; + if(!$conf['updatecheck']) return; + if($INFO['perm'] < AUTH_ADMIN) return; + + $cf = $conf['cachedir'].'/messages.txt'; + $lm = @filemtime($cf); + + // check if new messages needs to be fetched + if($lm < time()-(60*60*24) || $lm < @filemtime(DOKU_CONF.'msg')){ + $num = file(DOKU_CONF.'msg'); + $num = (int) $num[0]; + $http = new DokuHTTPClient(); + $http->timeout = 8; + $data = $http->get(DOKU_MESSAGEURL.$num); + io_saveFile($cf,$data); + }else{ + $data = io_readFile($cf); + } + + // show messages through the usual message mechanism + $msgs = explode("\n%\n",$data); + foreach($msgs as $msg){ + if($msg) msg($msg,2); + } +} + + +/** + * Return DokuWikis version + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function getVersion(){ + //import version string + if(@file_exists('VERSION')){ + //official release + return 'Release '.trim(io_readfile(DOKU_INC.'/VERSION')); + }elseif(is_dir('_darcs')){ + //darcs checkout - read last 2000 bytes of inventory + $sz = filesize('_darcs/inventory'); + $seek = max(0,$sz-2000); + $fh = fopen('_darcs/inventory','rb'); + fseek($fh,$seek); + $chunk = fread($fh,2000); + fclose($fh); + $inv = preg_grep('#\*\*\d{14}[\]$]#',explode("\n",$chunk)); + $cur = array_pop($inv); + preg_match('#\*\*(\d{4})(\d{2})(\d{2})#',$cur,$matches); + return 'Darcs '.$matches[1].'-'.$matches[2].'-'.$matches[3]; + }else{ + return 'snapshot?'; + } +} + +/** + * Run a few sanity checks + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function check(){ + global $conf; + global $INFO; + + msg('DokuWiki version: '.getVersion(),1); + + if(version_compare(phpversion(),'4.3.0','<')){ + msg('Your PHP version is too old ('.phpversion().' vs. 4.3.+ recommended)',-1); + }elseif(version_compare(phpversion(),'4.3.10','<')){ + msg('Consider upgrading PHP to 4.3.10 or higher for security reasons (your version: '.phpversion().')',0); + }else{ + msg('PHP version '.phpversion(),1); + } + + if(is_writable($conf['changelog'])){ + msg('Changelog is writable',1); + }else{ + if (@file_exists($conf['changelog'])) { + msg('Changelog is not writable',-1); + } + } + + if (isset($conf['changelog_old']) && @file_exists($conf['changelog_old'])) { + msg('Old changelog exists.', 0); + } + + if (@file_exists($conf['changelog'].'_failed')) { + msg('Importing old changelog failed.', -1); + } else if (@file_exists($conf['changelog'].'_importing')) { + msg('Importing old changelog now.', 0); + } else if (@file_exists($conf['changelog'].'_import_ok')) { + msg('Old changelog imported.', 1); + if (!plugin_isdisabled('importoldchangelog')) { + msg('Importoldchangelog plugin not disabled after import.', -1); + } + } + + if(is_writable($conf['datadir'])){ + msg('Datadir is writable',1); + }else{ + msg('Datadir is not writable',-1); + } + + if(is_writable($conf['olddir'])){ + msg('Attic is writable',1); + }else{ + msg('Attic is not writable',-1); + } + + if(is_writable($conf['mediadir'])){ + msg('Mediadir is writable',1); + }else{ + msg('Mediadir is not writable',-1); + } + + if(is_writable($conf['cachedir'])){ + msg('Cachedir is writable',1); + }else{ + msg('Cachedir is not writable',-1); + } + + if(is_writable($conf['lockdir'])){ + msg('Lockdir is writable',1); + }else{ + msg('Lockdir is not writable',-1); + } + + if(is_writable(DOKU_CONF.'users.auth.php')){ + msg('conf/users.auth.php is writable',1); + }else{ + msg('conf/users.auth.php is not writable',0); + } + + if(function_exists('mb_strpos')){ + if(defined('UTF8_NOMBSTRING')){ + msg('mb_string extension is available but will not be used',0); + }else{ + msg('mb_string extension is available and will be used',1); + } + }else{ + msg('mb_string extension not available - PHP only replacements will be used',0); + } + + if($conf['allowdebug']){ + msg('Debugging support is enabled. If you don\'t need it you should set $conf[\'allowdebug\'] = 0',-1); + }else{ + msg('Debugging support is disabled',1); + } + + msg('Your current permission for this page is '.$INFO['perm'],0); + + if(is_writable($INFO['filepath'])){ + msg('The current page is writable by the webserver',0); + }else{ + msg('The current page is not writable by the webserver',0); + } + + if($INFO['writable']){ + msg('The current page is writable by you',0); + }else{ + msg('The current page is not writable you',0); + } +} + +/** + * print a message + * + * If HTTP headers were not sent yet the message is added + * to the global message array else it's printed directly + * using html_msgarea() + * + * + * Levels can be: + * + * -1 error + * 0 info + * 1 success + * + * @author Andreas Gohr <andi@splitbrain.org> + * @see html_msgarea + */ +function msg($message,$lvl=0,$line='',$file=''){ + global $MSG; + $errors[-1] = 'error'; + $errors[0] = 'info'; + $errors[1] = 'success'; + $errors[2] = 'notify'; + + if($line || $file) $message.=' ['.basename($file).':'.$line.']'; + + if(!headers_sent()){ + if(!isset($MSG)) $MSG = array(); + $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); + }else{ + $MSG = array(); + $MSG[]=array('lvl' => $errors[$lvl], 'msg' => $message); + if(function_exists('html_msgarea')){ + html_msgarea(); + }else{ + print "ERROR($lvl) $message"; + } + } +} + +/** + * print debug messages + * + * little function to print the content of a var + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function dbg($msg,$hidden=false){ + (!$hidden) ? print '<pre class="dbg">' : print "<!--\n"; + print_r($msg); + (!$hidden) ? print '</pre>' : print "\n-->"; +} + +/** + * Print info to a log file + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function dbglog($msg){ + global $conf; + $file = $conf['cachedir'].'/debug.log'; + $fh = fopen($file,'a'); + if($fh){ + fwrite($fh,date('H:i:s ').$_SERVER['REMOTE_ADDR'].': '.$msg."\n"); + fclose($fh); + } +} + + diff --git a/lib/images/notify.png b/lib/images/notify.png new file mode 100644 index 0000000000000000000000000000000000000000..6e0015df4f737ded7e7e14b546616e704f023226 GIT binary patch literal 789 zcmV+w1M2*VP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00004XF*Lt006JZ zHwB960000PbVXQnQ*UN;cVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU!r%6OXR5;6( zl3PgAVHn1Ru7ZMY3W6PN`&(`;PpO4Pnzgcvps0-SLV~CZBQZ$DvSvkiDo3UXOG$Ak zo0B=`)D7u0W)n4!n>w3Y+732PG_{dW-vWnGW?ek+eegcN?|t9z2?7xGKN@MGRD*J^ z&rlky@ZUE!D5>oxB^64H+e}Jso>dhAcXJ|I^4Pu&0hSi(IWgLX71SJg^}9{IANt4a z6@3vO@*Gyvx&UJ2j;g6eXHOcITv{wUTQS>}4p&n=2Fk;r%w^@S*8a(S*4l9Z?xB2q zbEz@ceIA}S32-WSa5Toip*ae*h-LZ>K#V(y+NX@kSg_V%$^H^^#w5(VjmNa^Al#Zr zxKskTv?tM3%<%;PqbiC^j8kOR6?gv~_-2jxYPk=$UI?e|FeaO0Fjl)4b{QYeM$$#= z33NONUJd|;<y@`1?;MsL5_l&v;WedVvHuKQui`OUAC93)9zK*&uu4OIjxnV^j>c@3 zEdc1N;!Mt4u3_FH!uuLNdh0_mSQm{kBBv%A#u5&?pX`FYmIHU&F-*wfP<N9l3jjKw z23L%z;@~moV4&eNRQF<`6CZ)LfQ^qb0X(f?=o7PHkuc$CNkq>x9%`;Lgug8DbunAt zBaI+kWJ7UF0I#(WUwSj4$>*c9h=G}AiU3$-A0$Ax*`Bq(7C5v$WSb3D;V`_ofN@<0 zyyGH_s4k);Wh-=dcVI!ug{|Qbq&Jv@e+2kN0@9!>-iNlrSST`i(3d5k^wJhQO4^KW zF%1@J6soS$C)Ne{CC_FF<ylPVN#g8=Q~3N&2!mt~KB;%3w@iSF%k<8_0#+r>V2Y&a z4Co4YFjq&xTp5X`tPqr@&_w?P@T)qFu}N};o>QJmcZySJ(<RBYc5yO|wYKI5>R-Md ToJi+(00000NkvXXu0mjf*@atu literal 0 HcmV?d00001 diff --git a/lib/plugins/config/lang/en/lang.php b/lib/plugins/config/lang/en/lang.php index d92e930f2..db8c270b9 100644 --- a/lib/plugins/config/lang/en/lang.php +++ b/lib/plugins/config/lang/en/lang.php @@ -96,6 +96,7 @@ $lang['disableactions_wikicode'] = 'View source/Export Raw'; $lang['disableactions_other'] = 'Other actions (comma separated)'; /* Advanced Options */ +$lang['updatecheck'] = 'Check for updates and security warnings? DokuWiki needs to contact splitbrain.org for this feature.'; $lang['userewrite'] = 'Use nice URLs'; $lang['useslash'] = 'Use slash as namespace separator in URLs'; $lang['usedraft'] = 'Automatically save a draft while editing'; diff --git a/lib/plugins/config/settings/config.metadata.php b/lib/plugins/config/settings/config.metadata.php index b55c0e930..09d3736f3 100644 --- a/lib/plugins/config/settings/config.metadata.php +++ b/lib/plugins/config/settings/config.metadata.php @@ -147,6 +147,7 @@ $meta['jpg_quality'] = array('numeric','_pattern' => '/^100$|^[1-9]?[0-9]$/'); $meta['fetchsize'] = array('numeric'); $meta['_advanced'] = array('fieldset'); +$meta['updatecheck'] = array('onoff'); $meta['userewrite'] = array('multichoice','_choices' => array(0,1,2)); $meta['useslash'] = array('onoff'); $meta['sepchar'] = array('sepchar'); diff --git a/lib/styles/style.css b/lib/styles/style.css index cb39516c4..209e5654c 100644 --- a/lib/styles/style.css +++ b/lib/styles/style.css @@ -46,6 +46,17 @@ div.success { overflow: hidden; } +div.notify { + background: #ffc url(../images/notify.png) 0.5em 0px no-repeat; + color: #000; + border-bottom: 1px solid #ffa; + font-size: 90%; + margin: 0; + padding-left: 3em; + overflow: hidden; +} + + /* image alignment */ .medialeft { float: left; -- GitLab