summaryrefslogtreecommitdiff
path: root/lib/exe
diff options
context:
space:
mode:
Diffstat (limited to 'lib/exe')
-rw-r--r--lib/exe/ajax.php456
-rw-r--r--lib/exe/css.php185
-rw-r--r--lib/exe/indexer.php38
-rw-r--r--lib/exe/js.php90
-rw-r--r--lib/exe/mediamanager.php22
-rw-r--r--lib/exe/xmlrpc.php191
6 files changed, 409 insertions, 573 deletions
diff --git a/lib/exe/ajax.php b/lib/exe/ajax.php
index e514762fd..2bfa3680c 100644
--- a/lib/exe/ajax.php
+++ b/lib/exe/ajax.php
@@ -8,7 +8,7 @@
//fix for Opera XMLHttpRequests
if(!count($_POST) && !empty($HTTP_RAW_POST_DATA)){
- parse_str($HTTP_RAW_POST_DATA, $_POST);
+ parse_str($HTTP_RAW_POST_DATA, $_POST);
}
if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
@@ -20,25 +20,25 @@ header('Content-Type: text/html; charset=utf-8');
//call the requested function
-if(isset($_POST['call']))
- $call = $_POST['call'];
-else if(isset($_GET['call']))
- $call = $_GET['call'];
-else
- exit;
-
+if(isset($_POST['call'])){
+ $call = $_POST['call'];
+}else if(isset($_GET['call'])){
+ $call = $_GET['call'];
+}else{
+ exit;
+}
$callfn = 'ajax_'.$call;
if(function_exists($callfn)){
- $callfn();
+ $callfn();
}else{
- $evt = new Doku_Event('AJAX_CALL_UNKNOWN', $call);
- if ($evt->advise_before()) {
- print "AJAX call '".htmlspecialchars($call)."' unknown!\n";
- exit;
- }
- $evt->advise_after();
- unset($evt);
+ $evt = new Doku_Event('AJAX_CALL_UNKNOWN', $call);
+ if ($evt->advise_before()) {
+ print "AJAX call '".htmlspecialchars($call)."' unknown!\n";
+ exit;
+ }
+ $evt->advise_after();
+ unset($evt);
}
/**
@@ -47,33 +47,33 @@ if(function_exists($callfn)){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function ajax_qsearch(){
- global $conf;
- global $lang;
-
- $query = $_POST['q'];
- if(empty($query)) $query = $_GET['q'];
- if(empty($query)) return;
-
- $data = ft_pageLookup($query, true, useHeading('navigation'));
-
- if(!count($data)) return;
-
- print '<strong>'.$lang['quickhits'].'</strong>';
- print '<ul>';
- foreach($data as $id => $title){
- if (useHeading('navigation')) {
- $name = $title;
- } else {
- $ns = getNS($id);
- if($ns){
- $name = shorten(noNS($id), ' ('.$ns.')',30);
- }else{
- $name = $id;
+ global $conf;
+ global $lang;
+
+ $query = $_POST['q'];
+ if(empty($query)) $query = $_GET['q'];
+ if(empty($query)) return;
+
+ $data = ft_pageLookup($query, true, useHeading('navigation'));
+
+ if(!count($data)) return;
+
+ print '<strong>'.$lang['quickhits'].'</strong>';
+ print '<ul>';
+ foreach($data as $id => $title){
+ if (useHeading('navigation')) {
+ $name = $title;
+ } else {
+ $ns = getNS($id);
+ if($ns){
+ $name = noNS($id).' ('.$ns.')';
+ }else{
+ $name = $id;
+ }
}
+ echo '<li>' . html_wikilink(':'.$id,$name) . '</li>';
}
- echo '<li>' . html_wikilink(':'.$id,$name) . '</li>';
- }
- print '</ul>';
+ print '</ul>';
}
/**
@@ -83,36 +83,36 @@ function ajax_qsearch(){
* @author Mike Frysinger <vapier@gentoo.org>
*/
function ajax_suggestions() {
- global $conf;
- global $lang;
-
- $query = cleanID($_POST['q']);
- if(empty($query)) $query = cleanID($_GET['q']);
- if(empty($query)) return;
-
- $data = array();
- $data = ft_pageLookup($query);
- if(!count($data)) return;
- $data = array_keys($data);
-
- // limit results to 15 hits
- $data = array_slice($data, 0, 15);
- $data = array_map('trim',$data);
- $data = array_map('noNS',$data);
- $data = array_unique($data);
- sort($data);
-
- /* now construct a json */
- $suggestions = array(
- $query, // the original query
- $data, // some suggestions
- array(), // no description
- array() // no urls
- );
- $json = new JSON();
-
- header('Content-Type: application/x-suggestions+json');
- print $json->encode($suggestions);
+ global $conf;
+ global $lang;
+
+ $query = cleanID($_POST['q']);
+ if(empty($query)) $query = cleanID($_GET['q']);
+ if(empty($query)) return;
+
+ $data = array();
+ $data = ft_pageLookup($query);
+ if(!count($data)) return;
+ $data = array_keys($data);
+
+ // limit results to 15 hits
+ $data = array_slice($data, 0, 15);
+ $data = array_map('trim',$data);
+ $data = array_map('noNS',$data);
+ $data = array_unique($data);
+ sort($data);
+
+ /* now construct a json */
+ $suggestions = array(
+ $query, // the original query
+ $data, // some suggestions
+ array(), // no description
+ array() // no urls
+ );
+ $json = new JSON();
+
+ header('Content-Type: application/x-suggestions+json');
+ print $json->encode($suggestions);
}
/**
@@ -121,32 +121,42 @@ function ajax_suggestions() {
* Andreas Gohr <andi@splitbrain.org>
*/
function ajax_lock(){
- global $conf;
- global $lang;
- $id = cleanID($_POST['id']);
- if(empty($id)) return;
+ global $conf;
+ global $lang;
+ global $ID;
+ global $INFO;
- if(!checklock($id)){
- lock($id);
- echo 1;
- }
+ $ID = cleanID($_POST['id']);
+ if(empty($ID)) return;
- if($conf['usedraft'] && $_POST['wikitext']){
- $client = $_SERVER['REMOTE_USER'];
- if(!$client) $client = clientIP(true);
+ $INFO = pageinfo();
+
+ if (!$INFO['writable']) {
+ echo 'Permission denied';
+ return;
+ }
- $draft = array('id' => $id,
- 'prefix' => substr($_POST['prefix'], 0, -1),
- 'text' => $_POST['wikitext'],
- 'suffix' => $_POST['suffix'],
- 'date' => (int) $_POST['date'],
- 'client' => $client,
- );
- $cname = getCacheName($draft['client'].$id,'.draft');
- if(io_saveFile($cname,serialize($draft))){
- echo $lang['draftdate'].' '.dformat();
+ if(!checklock($ID)){
+ lock($ID);
+ echo 1;
+ }
+
+ if($conf['usedraft'] && $_POST['wikitext']){
+ $client = $_SERVER['REMOTE_USER'];
+ if(!$client) $client = clientIP(true);
+
+ $draft = array('id' => $ID,
+ 'prefix' => substr($_POST['prefix'], 0, -1),
+ 'text' => $_POST['wikitext'],
+ 'suffix' => $_POST['suffix'],
+ 'date' => (int) $_POST['date'],
+ 'client' => $client,
+ );
+ $cname = getCacheName($draft['client'].$ID,'.draft');
+ if(io_saveFile($cname,serialize($draft))){
+ echo $lang['draftdate'].' '.dformat();
+ }
}
- }
}
@@ -156,14 +166,14 @@ function ajax_lock(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function ajax_draftdel(){
- $id = cleanID($_REQUEST['id']);
- if(empty($id)) return;
+ $id = cleanID($_REQUEST['id']);
+ if(empty($id)) return;
- $client = $_SERVER['REMOTE_USER'];
- if(!$client) $client = clientIP(true);
+ $client = $_SERVER['REMOTE_USER'];
+ if(!$client) $client = clientIP(true);
- $cname = getCacheName($client.$id,'.draft');
- @unlink($cname);
+ $cname = getCacheName($client.$id,'.draft');
+ @unlink($cname);
}
/**
@@ -172,22 +182,20 @@ function ajax_draftdel(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function ajax_medians(){
- global $conf;
-
- // wanted namespace
- $ns = cleanID($_POST['ns']);
- $dir = utf8_encodeFN(str_replace(':','/',$ns));
-
- $lvl = count(explode(':',$ns));
-
- $data = array();
- search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir);
- foreach($data as $item){
- $item['level'] = $lvl+1;
- echo media_nstree_li($item);
- echo media_nstree_item($item);
- echo '</li>';
- }
+ global $conf;
+
+ // wanted namespace
+ $ns = cleanID($_POST['ns']);
+ $dir = utf8_encodeFN(str_replace(':','/',$ns));
+
+ $lvl = count(explode(':',$ns));
+
+ $data = array();
+ search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir);
+ foreach(array_keys($data) as $item){
+ $data[$item]['level'] = $lvl+1;
+ }
+ echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li');
}
/**
@@ -196,11 +204,11 @@ function ajax_medians(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function ajax_medialist(){
- global $conf;
- global $NS;
+ global $conf;
+ global $NS;
- $NS = $_POST['ns'];
- tpl_mediaContent(true);
+ $NS = $_POST['ns'];
+ tpl_mediaContent(true);
}
/**
@@ -209,24 +217,20 @@ function ajax_medialist(){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function ajax_index(){
- global $conf;
-
- // wanted namespace
- $ns = cleanID($_POST['idx']);
- $dir = utf8_encodeFN(str_replace(':','/',$ns));
-
- $lvl = count(explode(':',$ns));
-
- $data = array();
- search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir);
- foreach($data as $item){
- $item['level'] = $lvl+1;
- echo html_li_index($item);
- echo '<div class="li">';
- echo html_list_index($item);
- echo '</div>';
- echo '</li>';
- }
+ global $conf;
+
+ // wanted namespace
+ $ns = cleanID($_POST['idx']);
+ $dir = utf8_encodeFN(str_replace(':','/',$ns));
+
+ $lvl = count(explode(':',$ns));
+
+ $data = array();
+ search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir);
+ foreach(array_keys($data) as $item){
+ $data[$item]['level'] = $lvl+1;
+ }
+ echo html_buildlist($data, 'idx', 'html_list_index', 'html_li_index');
}
/**
@@ -235,107 +239,105 @@ function ajax_index(){
* @author Andreas Gohr <gohr@cosmocode.de>
*/
function ajax_linkwiz(){
- global $conf;
- global $lang;
-
- $q = ltrim($_POST['q'],':');
- $id = noNS($q);
- $ns = getNS($q);
-
- $ns = cleanID($ns);
- $id = cleanID($id);
-
- $nsd = utf8_encodeFN(str_replace(':','/',$ns));
- $idd = utf8_encodeFN(str_replace(':','/',$id));
-
- $data = array();
- if($q && !$ns){
-
- // use index to lookup matching pages
- $pages = array();
- $pages = ft_pageLookup($id,true);
-
- // result contains matches in pages and namespaces
- // we now extract the matching namespaces to show
- // them seperately
- $dirs = array();
-
-
- foreach($pages as $pid => $title){
- if(strpos(noNS($pid),$id) === false){
- // match was in the namespace
- $dirs[getNS($pid)] = 1; // assoc array avoids dupes
- }else{
- // it is a matching page, add it to the result
- $data[] = array(
- 'id' => $pid,
- 'title' => $title,
- 'type' => 'f',
- );
- }
- unset($pages[$pid]);
- }
- foreach($dirs as $dir => $junk){
- $data[] = array(
- 'id' => $dir,
- 'type' => 'd',
- );
- }
+ global $conf;
+ global $lang;
+
+ $q = ltrim(trim($_POST['q']),':');
+ $id = noNS($q);
+ $ns = getNS($q);
+
+ $ns = cleanID($ns);
+ $id = cleanID($id);
+
+ $nsd = utf8_encodeFN(str_replace(':','/',$ns));
+ $idd = utf8_encodeFN(str_replace(':','/',$id));
+
+ $data = array();
+ if($q && !$ns){
+
+ // use index to lookup matching pages
+ $pages = array();
+ $pages = ft_pageLookup($id,true);
+
+ // result contains matches in pages and namespaces
+ // we now extract the matching namespaces to show
+ // them seperately
+ $dirs = array();
+
+ foreach($pages as $pid => $title){
+ if(strpos(noNS($pid),$id) === false){
+ // match was in the namespace
+ $dirs[getNS($pid)] = 1; // assoc array avoids dupes
+ }else{
+ // it is a matching page, add it to the result
+ $data[] = array(
+ 'id' => $pid,
+ 'title' => $title,
+ 'type' => 'f',
+ );
+ }
+ unset($pages[$pid]);
+ }
+ foreach($dirs as $dir => $junk){
+ $data[] = array(
+ 'id' => $dir,
+ 'type' => 'd',
+ );
+ }
- }else{
-
- $opts = array(
- 'depth' => 1,
- 'listfiles' => true,
- 'listdirs' => true,
- 'pagesonly' => true,
- 'firsthead' => true,
- 'sneakyacl' => $conf['sneaky_index'],
- );
- if($id) $opts['filematch'] = '^.*\/'.$id;
- if($id) $opts['dirmatch'] = '^.*\/'.$id;
- search($data,$conf['datadir'],'search_universal',$opts,$nsd);
-
- // add back to upper
- if($ns){
- array_unshift($data,array(
- 'id' => getNS($ns),
- 'type' => 'u',
- ));
- }
- }
+ }else{
- // fixme sort results in a useful way ?
+ $opts = array(
+ 'depth' => 1,
+ 'listfiles' => true,
+ 'listdirs' => true,
+ 'pagesonly' => true,
+ 'firsthead' => true,
+ 'sneakyacl' => $conf['sneaky_index'],
+ );
+ if($id) $opts['filematch'] = '^.*\/'.$id;
+ if($id) $opts['dirmatch'] = '^.*\/'.$id;
+ search($data,$conf['datadir'],'search_universal',$opts,$nsd);
+
+ // add back to upper
+ if($ns){
+ array_unshift($data,array(
+ 'id' => getNS($ns),
+ 'type' => 'u',
+ ));
+ }
+ }
- if(!count($data)){
- echo $lang['nothingfound'];
- exit;
- }
+ // fixme sort results in a useful way ?
- // output the found data
- $even = 1;
- foreach($data as $item){
- $even *= -1; //zebra
+ if(!count($data)){
+ echo $lang['nothingfound'];
+ exit;
+ }
- if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':';
- $link = wl($item['id']);
+ // output the found data
+ $even = 1;
+ foreach($data as $item){
+ $even *= -1; //zebra
- echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">';
+ if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':';
+ $link = wl($item['id']);
+ echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">';
- if($item['type'] == 'u'){
- $name = $lang['upperns'];
- }else{
- $name = htmlspecialchars($item['id']);
- }
+ if($item['type'] == 'u'){
+ $name = $lang['upperns'];
+ }else{
+ $name = htmlspecialchars($item['id']);
+ }
- echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>';
+ echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>';
- if($item['title']){
- echo '<span>'.htmlspecialchars($item['title']).'</span>';
+ if($item['title']){
+ echo '<span>'.htmlspecialchars($item['title']).'</span>';
+ }
+ echo '</div>';
}
- echo '</div>';
- }
}
diff --git a/lib/exe/css.php b/lib/exe/css.php
index e64ebc22a..8f86f2433 100644
--- a/lib/exe/css.php
+++ b/lib/exe/css.php
@@ -30,10 +30,10 @@ function css_out(){
global $lang;
global $config_cascade;
- $style = '';
+ $mediatype = 'screen';
if (isset($_REQUEST['s']) &&
in_array($_REQUEST['s'], array('all', 'print', 'feed'))) {
- $style = $_REQUEST['s'];
+ $mediatype = $_REQUEST['s'];
}
$tpl = trim(preg_replace('/[^\w-]+/','',$_REQUEST['t']));
@@ -46,7 +46,7 @@ function css_out(){
}
// The generated script depends on some dynamic options
- $cache = getCacheName('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].DOKU_BASE.$tplinc.$style,'.css');
+ $cache = new cache('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].DOKU_BASE.$tplinc.$mediatype,'.css');
// load template styles
$tplstyles = array();
@@ -60,49 +60,41 @@ function css_out(){
// Array of needed files and their web locations, the latter ones
// are needed to fix relative paths in the stylesheets
$files = array();
- //if (isset($tplstyles['all'])) $files = array_merge($files, $tplstyles['all']);
- if(!empty($style)){
- $files[DOKU_INC.'lib/styles/'.$style.'.css'] = DOKU_BASE.'lib/styles/';
- // load plugin, template, user styles
- $files = array_merge($files, css_pluginstyles($style));
- if (isset($tplstyles[$style])) $files = array_merge($files, $tplstyles[$style]);
-
- if(isset($config_cascade['userstyle'][$style])){
- $files[$config_cascade['userstyle'][$style]] = DOKU_BASE;
- }
- }else{
- $files[DOKU_INC.'lib/styles/style.css'] = DOKU_BASE.'lib/styles/';
- // load plugin, template, user styles
- $files = array_merge($files, css_pluginstyles('screen'));
- if (isset($tplstyles['screen'])) $files = array_merge($files, $tplstyles['screen']);
+ // load core styles
+ $files[DOKU_INC.'lib/styles/'.$mediatype.'.css'] = DOKU_BASE.'lib/styles/';
+ // load jQuery-UI theme
+ $files[DOKU_INC.'lib/scripts/jquery/jquery-ui-theme/smoothness.css'] = DOKU_BASE.'lib/scripts/jquery/jquery-ui-theme/';
+ // load plugin styles
+ $files = array_merge($files, css_pluginstyles($mediatype));
+ // load template styles
+ if (isset($tplstyles[$mediatype])) {
+ $files = array_merge($files, $tplstyles[$mediatype]);
+ }
+ // if old 'default' userstyle setting exists, make it 'screen' userstyle for backwards compatibility
+ if (isset($config_cascade['userstyle']['default'])) {
+ $config_cascade['userstyle']['screen'] = $config_cascade['userstyle']['default'];
+ }
+ // load user styles
+ if(isset($config_cascade['userstyle'][$mediatype])){
+ $files[$config_cascade['userstyle'][$mediatype]] = DOKU_BASE;
+ }
+ // load rtl styles
+ // @todo: this currently adds the rtl styles only to the 'screen' media type
+ // but 'print' and 'all' should also be supported
+ if ($mediatype=='screen') {
if($lang['direction'] == 'rtl'){
if (isset($tplstyles['rtl'])) $files = array_merge($files, $tplstyles['rtl']);
}
- if(isset($config_cascade['userstyle']['default'])){
- $files[$config_cascade['userstyle']['default']] = DOKU_BASE;
- }
}
- // check cache age & handle conditional request
- header('Cache-Control: public, max-age=3600');
- header('Pragma: public');
- if(css_cacheok($cache,array_keys($files),$tplinc)){
- http_conditionalRequest(filemtime($cache));
- if($conf['allowdebug']) header("X-CacheUsed: $cache");
-
- // finally send output
- if ($conf['gzip_output'] && http_gzip_valid($cache)) {
- header('Vary: Accept-Encoding');
- header('Content-Encoding: gzip');
- readfile($cache.".gz");
- } else {
- if (!http_sendfile($cache)) readfile($cache);
- }
+ $cache_files = array_merge(array_keys($files), getConfigFiles('main'));
+ $cache_files[] = $tplinc.'style.ini';
+ $cache_files[] = __FILE__;
- return;
- } else {
- http_conditionalRequest(time());
- }
+ // check cache age & handle conditional request
+ // This may exit if a cache can be used
+ http_cached($cache->cache,
+ $cache->useCache(array('files' => $cache_files)));
// start output buffering and build the stylesheet
ob_start();
@@ -123,50 +115,21 @@ function css_out(){
// apply style replacements
$css = css_applystyle($css,$tplinc);
+ // place all @import statements at the top of the file
+ $css = css_moveimports($css);
+
// compress whitespace and comments
if($conf['compress']){
$css = css_compress($css);
}
- // save cache file
- io_saveFile($cache,$css);
- if(function_exists('gzopen')) io_saveFile("$cache.gz",$css);
-
- // finally send output
- if ($conf['gzip_output']) {
- header('Vary: Accept-Encoding');
- header('Content-Encoding: gzip');
- print gzencode($css,9,FORCE_GZIP);
- } else {
- print $css;
+ // embed small images right into the stylesheet
+ if($conf['cssdatauri']){
+ $base = preg_quote(DOKU_BASE,'#');
+ $css = preg_replace_callback('#(url\([ \'"]*)('.$base.')(.*?(?:\.(png|gif)))#i','css_datauri',$css);
}
-}
-
-/**
- * Checks if a CSS Cache file still is valid
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function css_cacheok($cache,$files,$tplinc){
- global $config_cascade;
-
- if(isset($_REQUEST['purge'])) return false; //support purge request
-
- $ctime = @filemtime($cache);
- if(!$ctime) return false; //There is no cache
-
- // some additional files to check
- $files = array_merge($files, getConfigFiles('main'));
- $files[] = $tplinc.'style.ini';
- $files[] = __FILE__;
- // now walk the files
- foreach($files as $file){
- if(@filemtime($file) > $ctime){
- return false;
- }
- }
- return true;
+ http_cached_finish($cache->cache, $css);
}
/**
@@ -199,7 +162,7 @@ function css_interwiki(){
// default style
echo 'a.interwiki {';
echo ' background: transparent url('.DOKU_BASE.'lib/images/interwiki.png) 0px 1px no-repeat;';
- echo ' padding-left: 16px;';
+ echo ' padding: 1px 0px 1px 16px;';
echo '}';
// additional styles when icon available
@@ -264,30 +227,53 @@ function css_loadfile($file,$location=''){
$css = io_readFile($file);
if(!$location) return $css;
- $css = preg_replace('#(url\([ \'"]*)((?!/|http://|https://| |\'|"))#','\\1'.$location.'\\3',$css);
+ $css = preg_replace('#(url\([ \'"]*)(?!/|data:|http://|https://| |\'|")#','\\1'.$location,$css);
+ $css = preg_replace('#(@import\s+[\'"])(?!/|data:|http://|https://)#', '\\1'.$location, $css);
+
return $css;
}
+/**
+ * Converte local image URLs to data URLs if the filesize is small
+ *
+ * Callback for preg_replace_callback
+ */
+function css_datauri($match){
+ global $conf;
+
+ $pre = unslash($match[1]);
+ $base = unslash($match[2]);
+ $url = unslash($match[3]);
+ $ext = unslash($match[4]);
+
+ $local = DOKU_INC.$url;
+ $size = @filesize($local);
+ if($size && $size < $conf['cssdatauri']){
+ $data = base64_encode(file_get_contents($local));
+ }
+ if($data){
+ $url = 'data:image/'.$ext.';base64,'.$data;
+ }else{
+ $url = $base.$url;
+ }
+ return $pre.$url;
+}
+
/**
* Returns a list of possible Plugin Styles (no existance check here)
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function css_pluginstyles($mode='screen'){
+function css_pluginstyles($mediatype='screen'){
global $lang;
$list = array();
$plugins = plugin_list();
foreach ($plugins as $p){
- if($mode == 'all'){
- $list[DOKU_PLUGIN."$p/all.css"] = DOKU_BASE."lib/plugins/$p/";
- }elseif($mode == 'print'){
- $list[DOKU_PLUGIN."$p/print.css"] = DOKU_BASE."lib/plugins/$p/";
- }elseif($mode == 'feed'){
- $list[DOKU_PLUGIN."$p/feed.css"] = DOKU_BASE."lib/plugins/$p/";
- }else{
+ $list[DOKU_PLUGIN."$p/$mediatype.css"] = DOKU_BASE."lib/plugins/$p/";
+ // alternative for screen.css
+ if ($mediatype=='screen') {
$list[DOKU_PLUGIN."$p/style.css"] = DOKU_BASE."lib/plugins/$p/";
- $list[DOKU_PLUGIN."$p/screen.css"] = DOKU_BASE."lib/plugins/$p/";
}
if($lang['direction'] == 'rtl'){
$list[DOKU_PLUGIN."$p/rtl.css"] = DOKU_BASE."lib/plugins/$p/";
@@ -297,6 +283,29 @@ function css_pluginstyles($mode='screen'){
}
/**
+ * Move all @import statements in a combined stylesheet to the top so they
+ * aren't ignored by the browser.
+ *
+ * @author Gabriel Birke <birke@d-scribe.de>
+ */
+function css_moveimports($css)
+{
+ if(!preg_match_all('/@import\s+(?:url\([^)]+\)|"[^"]+")\s*[^;]*;\s*/', $css, $matches, PREG_OFFSET_CAPTURE)) {
+ return $css;
+ }
+ $newCss = "";
+ $imports = "";
+ $offset = 0;
+ foreach($matches[0] as $match) {
+ $newCss .= substr($css, $offset, $match[1] - $offset);
+ $imports .= $match[0];
+ $offset = $match[1] + strlen($match[0]);
+ }
+ $newCss .= substr($css, $offset);
+ return $imports.$newCss;
+}
+
+/**
* Very simple CSS optimizer
*
* @author Andreas Gohr <andi@splitbrain.org>
diff --git a/lib/exe/indexer.php b/lib/exe/indexer.php
index 58b0d0787..95e2af05b 100644
--- a/lib/exe/indexer.php
+++ b/lib/exe/indexer.php
@@ -11,9 +11,6 @@ require_once(DOKU_INC.'inc/init.php');
session_write_close(); //close session
if(!defined('NL')) define('NL',"\n");
-// Version tag used to force rebuild on upgrade
-define('INDEXER_VERSION', 2);
-
// keep running after browser closes connection
@ignore_user_abort(true);
@@ -136,41 +133,8 @@ function runIndexer(){
if(!$ID) return false;
- // check if indexing needed
- $idxtag = metaFN($ID,'.indexed');
- if(@file_exists($idxtag)){
- if(io_readFile($idxtag) >= INDEXER_VERSION){
- $last = @filemtime($idxtag);
- if($last > @filemtime(wikiFN($ID))){
- print "runIndexer(): index for $ID up to date".NL;
- return false;
- }
- }
- }
-
- // try to aquire a lock
- $lock = $conf['lockdir'].'/_indexer.lock';
- while(!@mkdir($lock,$conf['dmode'])){
- usleep(50);
- if(time()-@filemtime($lock) > 60*5){
- // looks like a stale lock - remove it
- @rmdir($lock);
- print "runIndexer(): stale lock removed".NL;
- }else{
- print "runIndexer(): indexer locked".NL;
- return false;
- }
- }
- if($conf['dperm']) chmod($lock, $conf['dperm']);
-
// do the work
- idx_addPage($ID);
-
- // we're finished - save and free lock
- io_saveFile(metaFN($ID,'.indexed'),INDEXER_VERSION);
- @rmdir($lock);
- print "runIndexer(): finished".NL;
- return true;
+ return idx_addPage($ID, true);
}
/**
diff --git a/lib/exe/js.php b/lib/exe/js.php
index 117021308..93d5439e0 100644
--- a/lib/exe/js.php
+++ b/lib/exe/js.php
@@ -32,27 +32,37 @@ function js_out(){
global $config_cascade;
// The generated script depends on some dynamic options
- $cache = getCacheName('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.js');
+ $cache = new cache('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],
+ '.js');
+
+ // load minified version for some files
+ $min = $conf['compress'] ? '.min' : '';
// array of core files
$files = array(
+ DOKU_INC."lib/scripts/jquery/jquery$min.js",
+ DOKU_INC.'lib/scripts/jquery/jquery.cookie.js',
+ DOKU_INC."lib/scripts/jquery/jquery-ui$min.js",
DOKU_INC.'lib/scripts/helpers.js',
- DOKU_INC.'lib/scripts/events.js',
DOKU_INC.'lib/scripts/delay.js',
DOKU_INC.'lib/scripts/cookie.js',
DOKU_INC.'lib/scripts/script.js',
DOKU_INC.'lib/scripts/tw-sack.js',
- DOKU_INC.'lib/scripts/ajax.js',
+ DOKU_INC.'lib/scripts/qsearch.js',
+ DOKU_INC.'lib/scripts/tree.js',
DOKU_INC.'lib/scripts/index.js',
DOKU_INC.'lib/scripts/drag.js',
DOKU_INC.'lib/scripts/textselection.js',
DOKU_INC.'lib/scripts/toolbar.js',
DOKU_INC.'lib/scripts/edit.js',
+ DOKU_INC.'lib/scripts/editor.js',
+ DOKU_INC.'lib/scripts/locktimer.js',
DOKU_INC.'lib/scripts/linkwiz.js',
DOKU_INC.'lib/scripts/media.js',
- DOKU_INC.'lib/scripts/subscriptions.js',
+ DOKU_INC.'lib/scripts/compatibility.js',
# disabled for FS#1958 DOKU_INC.'lib/scripts/hotkeys.js',
DOKU_TPLINC.'script.js',
+ DOKU_INC.'lib/scripts/behaviour.js',
);
// add possible plugin scripts and userscript
@@ -61,25 +71,13 @@ function js_out(){
$files[] = $config_cascade['userscript']['default'];
}
+ $cache_files = array_merge($files, getConfigFiles('main'));
+ $cache_files[] = __FILE__;
+
// check cache age & handle conditional request
- header('Cache-Control: public, max-age=3600');
- header('Pragma: public');
- if(js_cacheok($cache,$files)){
- http_conditionalRequest(filemtime($cache));
- if($conf['allowdebug']) header("X-CacheUsed: $cache");
-
- // finally send output
- if ($conf['gzip_output'] && http_gzip_valid($cache)) {
- header('Vary: Accept-Encoding');
- header('Content-Encoding: gzip');
- readfile($cache.".gz");
- } else {
- if (!http_sendfile($cache)) readfile($cache);
- }
- return;
- } else {
- http_conditionalRequest(time());
- }
+ // This may exit if a cache can be used
+ http_cached($cache->cache,
+ $cache->useCache(array('files' => $cache_files)));
// start output buffering and build the script
ob_start();
@@ -108,14 +106,10 @@ function js_out(){
// init stuff
js_runonstart("addEvent(document,'click',closePopups)");
- js_runonstart('addTocToggle()');
- js_runonstart("initSizeCtl('size__ctl','wiki__text')");
js_runonstart("initToolbar('tool__bar','wiki__text',toolbar)");
if($conf['locktime'] != 0){
- js_runonstart("locktimer.init(".($conf['locktime'] - 60).",'".js_escape($lang['willexpire'])."',".$conf['usedraft'].")");
+ js_runonstart("locktimer.init(".($conf['locktime'] - 60).",'".js_escape($lang['willexpire'])."',".$conf['usedraft'].", 'wiki__text')");
}
- js_runonstart('scrollToMarker()');
- js_runonstart('focusMarker()');
// init hotkeys - must have been done after init of toolbar
# disabled for FS#1958 js_runonstart('initializeHotkeys()');
@@ -130,18 +124,7 @@ function js_out(){
$js .= "\n"; // https://bugzilla.mozilla.org/show_bug.cgi?id=316033
- // save cache file
- io_saveFile($cache,$js);
- if(function_exists('gzopen')) io_saveFile("$cache.gz",$js);
-
- // finally send output
- if ($conf['gzip_output']) {
- header('Vary: Accept-Encoding');
- header('Content-Encoding: gzip');
- print gzencode($js,9,FORCE_GZIP);
- } else {
- print $js;
- }
+ http_cached_finish($cache->cache, $js);
}
/**
@@ -173,32 +156,7 @@ function js_load($file){
}
$data = str_replace($match[0],$idata,$data);
}
- echo $data;
-}
-
-/**
- * Checks if a JavaScript Cache file still is valid
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- */
-function js_cacheok($cache,$files){
- if(isset($_REQUEST['purge'])) return false; //support purge request
-
- $ctime = @filemtime($cache);
- if(!$ctime) return false; //There is no cache
-
- // some additional files to check
- $files = array_merge($files, getConfigFiles('main'));
- $files[] = DOKU_CONF.'userscript.js';
- $files[] = __FILE__;
-
- // now walk the files
- foreach($files as $file){
- if(@filemtime($file) > $ctime){
- return false;
- }
- }
- return true;
+ echo "$data\n";
}
/**
@@ -285,7 +243,7 @@ function js_compress($s){
// items that don't need spaces next to them
$chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"[]";
- $regex_starters = array("(", "=", "[", "," , ":");
+ $regex_starters = array("(", "=", "[", "," , ":", "!");
$whitespaces_chars = array(" ", "\t", "\n", "\r", "\0", "\x0B");
diff --git a/lib/exe/mediamanager.php b/lib/exe/mediamanager.php
index c79a25c08..02fde5a8d 100644
--- a/lib/exe/mediamanager.php
+++ b/lib/exe/mediamanager.php
@@ -82,18 +82,24 @@
// handle deletion
if($DEL) {
- $INUSE = media_inuse($DEL);
- if(!$INUSE) {
- if(media_delete($DEL,$AUTH)) {
- msg(sprintf($lang['deletesucc'],noNS($DEL)),1);
- } else {
- msg(sprintf($lang['deletefail'],noNS($DEL)),-1);
+ $res = 0;
+ if(checkSecurityToken()) {
+ $res = media_delete($DEL,$AUTH);
+ }
+ if ($res & DOKU_MEDIA_DELETED) {
+ $msg = sprintf($lang['deletesucc'], noNS($DEL));
+ if ($res & DOKU_MEDIA_EMPTY_NS) {
+ // current namespace was removed. redirecting to root ns passing msg along
+ send_redirect(DOKU_URL.'lib/exe/mediamanager.php?msg1='.
+ rawurlencode($msg).'&edid='.$_REQUEST['edid']);
}
- } else {
+ msg($msg,1);
+ } elseif ($res & DOKU_MEDIA_INUSE) {
if(!$conf['refshow']) {
- unset($INUSE);
msg(sprintf($lang['mediainuse'],noNS($DEL)),0);
}
+ } else {
+ msg(sprintf($lang['deletefail'],noNS($DEL)),-1);
}
}
diff --git a/lib/exe/xmlrpc.php b/lib/exe/xmlrpc.php
index d232930a3..8b572d213 100644
--- a/lib/exe/xmlrpc.php
+++ b/lib/exe/xmlrpc.php
@@ -1,7 +1,7 @@
<?php
if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
-// fix when '<?xml' isn't on the very first line
+// fix when '< ?xml' isn't on the very first line
if(isset($HTTP_RAW_POST_DATA)) $HTTP_RAW_POST_DATA = trim($HTTP_RAW_POST_DATA);
/**
@@ -30,26 +30,9 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
global $USERINFO;
if(!$conf['useacl']) return true; //no ACL - then no checks
+ if(trim($conf['xmlrpcuser']) == '') return true; //no restrictions
- $allowed = explode(',',$conf['xmlrpcuser']);
- $allowed = array_map('trim', $allowed);
- $allowed = array_unique($allowed);
- $allowed = array_filter($allowed);
-
- if(!count($allowed)) return true; //no restrictions
-
- $user = $_SERVER['REMOTE_USER'];
- $groups = (array) $USERINFO['grps'];
-
- if(in_array($user,$allowed)) return true; //user explicitly mentioned
-
- //check group memberships
- foreach($groups as $group){
- if(in_array('@'.$group,$allowed)) return true;
- }
-
- //still here? no access!
- return false;
+ return auth_isMember($conf['xmlrpcuser'],$_SERVER['REMOTE_USER'],(array) $USERINFO['grps']);
}
/**
@@ -296,6 +279,7 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* Return a raw wiki page
*/
function rawPage($id,$rev=''){
+ $id = cleanID($id);
if(auth_quickaclcheck($id) < AUTH_READ){
return new IXR_Error(1, 'You are not allowed to read this page');
}
@@ -351,6 +335,7 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* Return a wiki page rendered to html
*/
function htmlPage($id,$rev=''){
+ $id = cleanID($id);
if(auth_quickaclcheck($id) < AUTH_READ){
return new IXR_Error(1, 'You are not allowed to read this page');
}
@@ -362,9 +347,8 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
*/
function listPages(){
$list = array();
- $pages = array_filter(array_filter(idx_getIndex('page', ''),
- 'isVisiblePage'),
- 'page_exists');
+ $pages = idx_get_indexer()->getPages();
+ $pages = array_filter(array_filter($pages,'isVisiblePage'),'page_exists');
foreach(array_keys($pages) as $idx) {
$perm = auth_quickaclcheck($pages[$idx]);
@@ -488,6 +472,7 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* Return some basic data about a page
*/
function pageInfo($id,$rev=''){
+ $id = cleanID($id);
if(auth_quickaclcheck($id) < AUTH_READ){
return new IXR_Error(1, 'You are not allowed to read this page');
}
@@ -559,27 +544,7 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
unlock($id);
// run the indexer if page wasn't indexed yet
- if(!@file_exists(metaFN($id, '.indexed'))) {
- // try to aquire a lock
- $lock = $conf['lockdir'].'/_indexer.lock';
- while(!@mkdir($lock,$conf['dmode'])){
- usleep(50);
- if(time()-@filemtime($lock) > 60*5){
- // looks like a stale lock - remove it
- @rmdir($lock);
- }else{
- return false;
- }
- }
- if($conf['dperm']) chmod($lock, $conf['dperm']);
-
- // do the work
- idx_addPage($id);
-
- // we're finished - save and free lock
- io_saveFile(metaFN($id,'.indexed'),INDEXER_VERSION);
- @rmdir($lock);
- }
+ idx_addPage($id);
return 0;
}
@@ -601,64 +566,27 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* Michael Klier <chi@chimeric.de>
*/
function putAttachment($id, $file, $params) {
- global $conf;
- global $lang;
-
+ $id = cleanID($id);
$auth = auth_quickaclcheck(getNS($id).':*');
- if($auth >= AUTH_UPLOAD) {
- if(!isset($id)) {
- return new IXR_ERROR(1, 'Filename not given.');
- }
- $ftmp = $conf['tmpdir'] . '/' . md5($id.clientIP());
-
- // save temporary file
- @unlink($ftmp);
- $buff = base64_decode($file);
- io_saveFile($ftmp, $buff);
+ if(!isset($id)) {
+ return new IXR_ERROR(1, 'Filename not given.');
+ }
- // get filename
- list($iext, $imime,$dl) = mimetype($id);
- $id = cleanID($id);
- $fn = mediaFN($id);
-
- // get filetype regexp
- $types = array_keys(getMimeTypes());
- $types = array_map(create_function('$q','return preg_quote($q,"/");'),$types);
- $regex = join('|',$types);
-
- // because a temp file was created already
- if(preg_match('/\.('.$regex.')$/i',$fn)) {
- //check for overwrite
- $overwrite = @file_exists($fn);
- if($overwrite && (!$params['ow'] || $auth < AUTH_DELETE)) {
- return new IXR_ERROR(1, $lang['uploadexist'].'1');
- }
- // check for valid content
- $ok = media_contentcheck($ftmp, $imime);
- if($ok == -1) {
- return new IXR_ERROR(1, sprintf($lang['uploadexist'].'2', ".$iext"));
- } elseif($ok == -2) {
- return new IXR_ERROR(1, $lang['uploadspam']);
- } elseif($ok == -3) {
- return new IXR_ERROR(1, $lang['uploadxss']);
- }
+ global $conf;
- // prepare event data
- $data[0] = $ftmp;
- $data[1] = $fn;
- $data[2] = $id;
- $data[3] = $imime;
- $data[4] = $overwrite;
+ $ftmp = $conf['tmpdir'] . '/' . md5($id.clientIP());
- // trigger event
- return trigger_event('MEDIA_UPLOAD_FINISH', $data, array($this, '_media_upload_action'), true);
+ // save temporary file
+ @unlink($ftmp);
+ $buff = base64_decode($file);
+ io_saveFile($ftmp, $buff);
- } else {
- return new IXR_ERROR(1, $lang['uploadwrong']);
- }
+ $res = media_save(array('name' => $ftmp), $id, $params['ow'], $auth, 'rename');
+ if (is_array($res)) {
+ return new IXR_ERROR(-$res[1], $res[0]);
} else {
- return new IXR_ERROR(1, "You don't have permissions to upload files.");
+ return $res;
}
}
@@ -668,56 +596,17 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* @author Gina Haeussge <osd@foosel.net>
*/
function deleteAttachment($id){
+ $id = cleanID($id);
$auth = auth_quickaclcheck(getNS($id).':*');
- if($auth < AUTH_DELETE) return new IXR_ERROR(1, "You don't have permissions to delete files.");
- global $conf;
- global $lang;
-
- // check for references if needed
- $mediareferences = array();
- if($conf['refcheck']){
- $mediareferences = ft_mediause($id,$conf['refshow']);
- }
-
- if(!count($mediareferences)){
- $file = mediaFN($id);
- if(@unlink($file)){
- addMediaLogEntry(time(), $id, DOKU_CHANGE_TYPE_DELETE);
- io_sweepNS($id,'mediadir');
- return 0;
- }
- //something went wrong
- return new IXR_ERROR(1, 'Could not delete file');
- } else {
+ $res = media_delete($id, $auth);
+ if ($res & DOKU_MEDIA_DELETED) {
+ return 0;
+ } elseif ($res & DOKU_MEDIA_NOT_AUTH) {
+ return new IXR_ERROR(1, "You don't have permissions to delete files.");
+ } elseif ($res & DOKU_MEDIA_INUSE) {
return new IXR_ERROR(1, 'File is still referenced');
- }
- }
-
- /**
- * Moves the temporary file to its final destination.
- *
- * Michael Klier <chi@chimeric.de>
- */
- function _media_upload_action($data) {
- global $conf;
-
- if(is_array($data) && count($data)===5) {
- io_createNamespace($data[2], 'media');
- if(rename($data[0], $data[1])) {
- chmod($data[1], $conf['fmode']);
- media_notify($data[2], $data[1], $data[3]);
- // add a log entry to the media changelog
- if ($data[4]) {
- addMediaLogEntry(time(), $data[2], DOKU_CHANGE_TYPE_EDIT);
- } else {
- addMediaLogEntry(time(), $data[2], DOKU_CHANGE_TYPE_CREATE);
- }
- return $data[2];
- } else {
- return new IXR_ERROR(1, 'Upload failed.');
- }
} else {
- return new IXR_ERROR(1, 'Upload failed.');
+ return new IXR_ERROR(1, 'Could not delete file');
}
}
@@ -725,6 +614,7 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* Returns the permissions of a given wiki page
*/
function aclCheck($id) {
+ $id = cleanID($id);
return auth_quickaclcheck($id);
}
@@ -734,13 +624,14 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* @author Michael Klier <chi@chimeric.de>
*/
function listLinks($id) {
+ $id = cleanID($id);
if(auth_quickaclcheck($id) < AUTH_READ){
return new IXR_Error(1, 'You are not allowed to read this page');
}
$links = array();
// resolve page instructions
- $ins = p_cached_instructions(wikiFN(cleanID($id)));
+ $ins = p_cached_instructions(wikiFN($id));
// instantiate new Renderer - needed for interwiki links
include(DOKU_INC.'inc/parser/xhtml.php');
@@ -848,6 +739,10 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
* @author Michael Klier <chi@chimeric.de>
*/
function pageVersions($id, $first) {
+ $id = cleanID($id);
+ if(auth_quickaclcheck($id) < AUTH_READ){
+ return new IXR_Error(1, 'You are not allowed to read this page');
+ }
global $conf;
$versions = array();
@@ -923,7 +818,8 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
$unlockfail = array();
foreach((array) $set['lock'] as $id){
- if(checklock($id)){
+ $id = cleanID($id);
+ if(auth_quickaclcheck($id) < AUTH_EDIT || checklock($id)){
$lockfail[] = $id;
}else{
lock($id);
@@ -932,10 +828,11 @@ class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer {
}
foreach((array) $set['unlock'] as $id){
- if(unlock($id)){
- $unlocked[] = $id;
- }else{
+ $id = cleanID($id);
+ if(auth_quickaclcheck($id) < AUTH_EDIT || !unlock($id)){
$unlockfail[] = $id;
+ }else{
+ $unlocked[] = $id;
}
}