diff options
Diffstat (limited to 'vendors/dokuwiki/lib/exe')
-rw-r--r-- | vendors/dokuwiki/lib/exe/ajax.php | 370 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/css.php | 330 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/detail.php | 58 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/fetch.php | 173 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/index.html | 12 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/indexer.php | 375 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/js.php | 397 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/mediamanager.php | 105 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/multipleUpload.swf | bin | 0 -> 64561 bytes | |||
-rw-r--r-- | vendors/dokuwiki/lib/exe/opensearch.php | 38 | ||||
-rw-r--r-- | vendors/dokuwiki/lib/exe/xmlrpc.php | 921 |
11 files changed, 2779 insertions, 0 deletions
diff --git a/vendors/dokuwiki/lib/exe/ajax.php b/vendors/dokuwiki/lib/exe/ajax.php new file mode 100644 index 000000000..4618abd71 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/ajax.php @@ -0,0 +1,370 @@ +<?php +/** + * DokuWiki AJAX call handler + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ + +//fix for Opera XMLHttpRequests +if(!count($_POST) && $HTTP_RAW_POST_DATA){ + parse_str($HTTP_RAW_POST_DATA, $_POST); +} + +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/common.php'); +require_once(DOKU_INC.'inc/pageutils.php'); +require_once(DOKU_INC.'inc/auth.php'); +//close sesseion +session_write_close(); + +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; + +$callfn = 'ajax_'.$call; + +if(function_exists($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); +} + +/** + * Searches for matching pagenames + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function ajax_qsearch(){ + global $conf; + global $lang; + + $query = cleanID($_POST['q']); + if(empty($query)) $query = cleanID($_GET['q']); + if(empty($query)) return; + + require_once(DOKU_INC.'inc/html.php'); + require_once(DOKU_INC.'inc/fulltext.php'); + + $data = array(); + $data = ft_pageLookup($query); + + if(!count($data)) return; + + print '<strong>'.$lang['quickhits'].'</strong>'; + print '<ul>'; + foreach($data as $id){ + print '<li>'; + $ns = getNS($id); + if($ns){ + $name = shorten(noNS($id), ' ('.$ns.')',30); + }else{ + $name = $id; + } + print html_wikilink(':'.$id,$name); + print '</li>'; + } + print '</ul>'; +} + +/** + * Support OpenSearch suggestions + * + * @link http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0 + * @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; + + require_once(DOKU_INC.'inc/html.php'); + require_once(DOKU_INC.'inc/fulltext.php'); + require_once(DOKU_INC.'inc/JSON.php'); + + $data = array(); + $data = ft_pageLookup($query); + if(!count($data)) return; + + // 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); +} + +/** + * Refresh a page lock and save draft + * + * Andreas Gohr <andi@splitbrain.org> + */ +function ajax_lock(){ + global $conf; + global $lang; + $id = cleanID($_POST['id']); + if(empty($id)) return; + + 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' => $_POST['prefix'], + 'text' => $_POST['wikitext'], + 'suffix' => $_POST['suffix'], + 'date' => $_POST['date'], + 'client' => $client, + ); + $cname = getCacheName($draft['client'].$id,'.draft'); + if(io_saveFile($cname,serialize($draft))){ + echo $lang['draftdate'].' '.dformat(); + } + } + +} + +/** + * Delete a draft + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function ajax_draftdel(){ + $id = cleanID($_POST['id']); + if(empty($id)) return; + + $client = $_SERVER['REMOTE_USER']; + if(!$client) $client = clientIP(true); + + $cname = getCacheName($client.$id,'.draft'); + @unlink($cname); +} + +/** + * Return subnamespaces for the Mediamanager + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function ajax_medians(){ + global $conf; + require_once(DOKU_INC.'inc/search.php'); + require_once(DOKU_INC.'inc/media.php'); + + // 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>'; + } +} + +/** + * Return list of files for the Mediamanager + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function ajax_medialist(){ + global $conf; + global $NS; + require_once(DOKU_INC.'inc/media.php'); + require_once(DOKU_INC.'inc/template.php'); + + $NS = $_POST['ns']; + tpl_mediaContent(true); +} + +/** + * Return list of search result for the Mediamanager + * + * @author Tobias Sarnowski <sarnowski@cosmocode.de> + */ +function ajax_mediasearchlist(){ + global $conf; + require_once(DOKU_INC.'inc/media.php'); + + media_searchlist($_POST['ns']); +} + +/** + * Return sub index for index view + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function ajax_index(){ + global $conf; + require_once(DOKU_INC.'inc/search.php'); + require_once(DOKU_INC.'inc/html.php'); + + // 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>'; + } +} + +/** + * List matching namespaces and pages for the link wizard + * + * @author Andreas Gohr <gohr@cosmocode.de> + */ +function ajax_linkwiz(){ + global $conf; + global $lang; + require_once(DOKU_INC.'inc/html.php'); + + $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 + require_once(DOKU_INC.'inc/fulltext.php'); + require_once(DOKU_INC.'inc/parserutils.php'); + $pages = array(); + $pages = ft_pageLookup($id,false); + + // result contains matches in pages and namespaces + // we now extract the matching namespaces to show + // them seperately + $dirs = array(); + $count = count($pages); + for($i=0; $i<$count; $i++){ + if(strpos(noNS($pages[$i]),$id) === false){ + // match was in the namespace + $dirs[getNS($pages[$i])] = 1; // assoc array avoids dupes + }else{ + // it is a matching page, add it to the result + $data[] = array( + 'id' => $pages[$i], + 'title' => p_get_first_heading($pages[$i],false), + 'type' => 'f', + ); + } + unset($pages[$i]); + } + foreach($dirs as $dir => $junk){ + $data[] = array( + 'id' => $dir, + 'type' => 'd', + ); + } + + }else{ + + require_once(DOKU_INC.'inc/search.php'); + $opts = array( + 'depth' => 1, + 'listfiles' => true, + 'listdirs' => true, + 'pagesonly' => true, + 'firsthead' => true, + ); + 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', + )); + } + } + + // fixme sort results in a useful way ? + + if(!count($data)){ + echo $lang['nothingfound']; + exit; + } + + // output the found data + $even = 1; + foreach($data as $item){ + $even *= -1; //zebra + + 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']); + } + + echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>'; + + if($item['title']){ + echo '<span>'.htmlspecialchars($item['title']).'</span>'; + } + echo '</div>'; + } + +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/vendors/dokuwiki/lib/exe/css.php b/vendors/dokuwiki/lib/exe/css.php new file mode 100644 index 000000000..2cb383de0 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/css.php @@ -0,0 +1,330 @@ +<?php +/** + * DokuWiki StyleSheet creator + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) +if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/pageutils.php'); +require_once(DOKU_INC.'inc/httputils.php'); +require_once(DOKU_INC.'inc/io.php'); +require_once(DOKU_INC.'inc/confutils.php'); + +// Main (don't run when UNIT test) +if(!defined('SIMPLE_TEST')){ + header('Content-Type: text/css; charset=utf-8'); + css_out(); +} + + +// ---------------------- functions ------------------------------ + +/** + * Output all needed Styles + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_out(){ + global $conf; + global $lang; + $style = ''; + if (isset($_REQUEST['s']) && + in_array($_REQUEST['s'], array('all', 'print', 'feed'))) { + $style = $_REQUEST['s']; + } + + $tpl = trim(preg_replace('/[^\w-]+/','',$_REQUEST['t'])); + if($tpl){ + $tplinc = DOKU_INC.'lib/tpl/'.$tpl.'/'; + $tpldir = DOKU_BASE.'lib/tpl/'.$tpl.'/'; + }else{ + $tplinc = DOKU_TPLINC; + $tpldir = DOKU_TPL; + } + + // The generated script depends on some dynamic options + $cache = getCacheName('styles'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'].DOKU_BASE.$tplinc.$style,'.css'); + + // load template styles + $tplstyles = array(); + if(@file_exists($tplinc.'style.ini')){ + $ini = parse_ini_file($tplinc.'style.ini',true); + foreach($ini['stylesheets'] as $file => $mode){ + $tplstyles[$mode][$tplinc.$file] = $tpldir; + } + } + + // 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_MEDIA.'lib/styles/'; + // load plugin, template, user styles + $files = array_merge($files, css_pluginstyles($style)); + if (isset($tplstyles[$style])) $files = array_merge($files, $tplstyles[$style]); + $files[DOKU_CONF.'user'.$style.'.css'] = DOKU_MEDIA; + }else{ + $files[DOKU_INC.'lib/styles/style.css'] = DOKU_MEDIA.'lib/styles/'; + // load plugin, template, user styles + $files = array_merge($files, css_pluginstyles('screen')); + if (isset($tplstyles['screen'])) $files = array_merge($files, $tplstyles['screen']); + if($lang['direction'] == 'rtl'){ + if (isset($tplstyles['rtl'])) $files = array_merge($files, $tplstyles['rtl']); + } + $files[DOKU_CONF.'userstyle.css'] = 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); + } + + return; + } else { + http_conditionalRequest(time()); + } + + // start output buffering and build the stylesheet + ob_start(); + + // print the default classes for interwiki links and file downloads + css_interwiki(); + css_filetypes(); + + // load files + foreach($files as $file => $location){ + print css_loadfile($file, $location); + } + + // end output buffering and get contents + $css = ob_get_contents(); + ob_end_clean(); + + // apply style replacements + $css = css_applystyle($css,$tplinc); + + // 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; + } +} + +/** + * 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; +} + +/** + * Does placeholder replacements in the style according to + * the ones defined in a templates style.ini file + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_applystyle($css,$tplinc){ + if(@file_exists($tplinc.'style.ini')){ + $ini = parse_ini_file($tplinc.'style.ini',true); + $css = strtr($css,$ini['replacements']); + } + return $css; +} + +/** + * Prints classes for interwikilinks + * + * Interwiki links have two classes: 'interwiki' and 'iw_$name>' where + * $name is the identifier given in the config. All Interwiki links get + * an default style with a default icon. If a special icon is available + * for an interwiki URL it is set in it's own class. Both classes can be + * overwritten in the template or userstyles. + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_interwiki(){ + + // default style + echo 'a.interwiki {'; + echo ' background: transparent url('.DOKU_MEDIA.'lib/images/interwiki.png) 0px 1px no-repeat;'; + echo ' padding-left: 16px;'; + echo '}'; + + // additional styles when icon available + $iwlinks = getInterwiki(); + foreach(array_keys($iwlinks) as $iw){ + $class = preg_replace('/[^_\-a-z0-9]+/i','_',$iw); + if(@file_exists(DOKU_INC.'lib/images/interwiki/'.$iw.'.png')){ + echo "a.iw_$class {"; + echo ' background-image: url('.DOKU_MEDIA.'lib/images/interwiki/'.$iw.'.png)'; + echo '}'; + }elseif(@file_exists(DOKU_INC.'lib/images/interwiki/'.$iw.'.gif')){ + echo "a.iw_$class {"; + echo ' background-image: url('.DOKU_MEDIA.'lib/images/interwiki/'.$iw.'.gif)'; + echo '}'; + } + } +} + +/** + * Prints classes for file download links + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_filetypes(){ + + // default style + echo 'a.mediafile {'; + echo ' background: transparent url('.DOKU_MEDIA.'lib/images/fileicons/file.png) 0px 1px no-repeat;'; + echo ' padding-left: 18px;'; + echo ' padding-bottom: 1px;'; + echo '}'; + + // additional styles when icon available + // scan directory for all icons + $exts = array(); + if($dh = opendir(DOKU_INC.'lib/images/fileicons')){ + while(false !== ($file = readdir($dh))){ + if(preg_match('/([_\-a-z0-9]+(?:\.[_\-a-z0-9]+)*?)\.(png|gif)/i',$file,$match)){ + $ext = strtolower($match[1]); + $type = '.'.strtolower($match[2]); + if($ext!='file' && (!isset($exts[$ext]) || $type=='.png')){ + $exts[$ext] = $type; + } + } + } + closedir($dh); + } + foreach($exts as $ext=>$type){ + $class = preg_replace('/[^_\-a-z0-9]+/','_',$ext); + echo "a.mf_$class {"; + echo ' background-image: url('.DOKU_MEDIA.'lib/images/fileicons/'.$ext.$type.')'; + echo '}'; + } +} + +/** + * Loads a given file and fixes relative URLs with the + * given location prefix + */ +function css_loadfile($file,$location=''){ + if(!@file_exists($file)) return ''; + $css = io_readFile($file); + if(!$location) return $css; + + $css = preg_replace('#(url\([ \'"]*)((?!/|http://|https://| |\'|"))#','\\1'.$location.'\\3',$css); + return $css; +} + + +/** + * Returns a list of possible Plugin Styles (no existance check here) + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_pluginstyles($mode='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/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/"; + } + } + return $list; +} + +/** + * Very simple CSS optimizer + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_compress($css){ + //strip comments through a callback + $css = preg_replace_callback('#(/\*)(.*?)(\*/)#s','css_comment_cb',$css); + + //strip (incorrect but common) one line comments + $css = preg_replace('/(?<!:)\/\/.*$/m','',$css); + + // strip whitespaces + $css = preg_replace('![\r\n\t ]+!',' ',$css); + $css = preg_replace('/ ?([:;,{}\/]) ?/','\\1',$css); + + // shorten colors + $css = preg_replace("/#([0-9a-fA-F]{1})\\1([0-9a-fA-F]{1})\\2([0-9a-fA-F]{1})\\3/", "#\\1\\2\\3",$css); + + return $css; +} + +/** + * Callback for css_compress() + * + * Keeps short comments (< 5 chars) to maintain typical browser hacks + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function css_comment_cb($matches){ + if(strlen($matches[2]) > 4) return ''; + return $matches[0]; +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/vendors/dokuwiki/lib/exe/detail.php b/vendors/dokuwiki/lib/exe/detail.php new file mode 100644 index 000000000..f30e039d4 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/detail.php @@ -0,0 +1,58 @@ +<?php + if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); + define('DOKU_MEDIADETAIL',1); + require_once(DOKU_INC.'inc/init.php'); + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/lang/en/lang.php'); + require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php'); + require_once(DOKU_INC.'inc/JpegMeta.php'); + require_once(DOKU_INC.'inc/html.php'); + require_once(DOKU_INC.'inc/template.php'); + require_once(DOKU_INC.'inc/auth.php'); + //close session + session_write_close(); + + $IMG = getID('media'); + $ID = cleanID($_REQUEST['id']); + + if($conf['allowdebug'] && $_REQUEST['debug']){ + print '<pre>'; + foreach(explode(' ','basedir userewrite baseurl useslash') as $x){ + print '$'."conf['$x'] = '".$conf[$x]."';\n"; + } + foreach(explode(' ','DOCUMENT_ROOT HTTP_HOST SCRIPT_FILENAME PHP_SELF '. + 'REQUEST_URI SCRIPT_NAME PATH_INFO PATH_TRANSLATED') as $x){ + print '$'."_SERVER['$x'] = '".$_SERVER[$x]."';\n"; + } + print "getID('media'): ".getID('media')."\n"; + print "getID('media',false): ".getID('media',false)."\n"; + print '</pre>'; + } + + $ERROR = false; + // check image permissions + $AUTH = auth_quickaclcheck($IMG); + if($AUTH >= AUTH_READ){ + // check if image exists + $SRC = mediaFN($IMG); + if(!@file_exists($SRC)){ + //doesn't exist! + + } + }else{ + // no auth + $ERROR = p_locale_xhtml('denied'); + } + + /*if(!$ERROR){ + // load EXIF/IPTC/image details + $INFO = array(); + $INFO['std'][''] + imagesize + }*/ + + + //start output and load template + header('Content-Type: text/html; charset=utf-8'); + include(template('detail.php')); + diff --git a/vendors/dokuwiki/lib/exe/fetch.php b/vendors/dokuwiki/lib/exe/fetch.php new file mode 100644 index 000000000..11877ef36 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/fetch.php @@ -0,0 +1,173 @@ +<?php +/** + * DokuWiki media passthrough file + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ + + if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); + define('DOKU_DISABLE_GZIP_OUTPUT', 1); + require_once(DOKU_INC.'inc/init.php'); + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/media.php'); + require_once(DOKU_INC.'inc/pageutils.php'); + require_once(DOKU_INC.'inc/httputils.php'); + require_once(DOKU_INC.'inc/confutils.php'); + require_once(DOKU_INC.'inc/auth.php'); + + //close sesseion + session_write_close(); + + $mimetypes = getMimeTypes(); + + //get input + $MEDIA = stripctl(getID('media',false)); // no cleaning except control chars - maybe external + $CACHE = calc_cache($_REQUEST['cache']); + $WIDTH = (int) $_REQUEST['w']; + $HEIGHT = (int) $_REQUEST['h']; + list($EXT,$MIME,$DL) = mimetype($MEDIA,false); + if($EXT === false){ + $EXT = 'unknown'; + $MIME = 'application/octet-stream'; + $DL = true; + } + + //media to local file + if(preg_match('#^(https?)://#i',$MEDIA)){ + //check hash + if(substr(md5(auth_cookiesalt().$MEDIA),0,6) != $_REQUEST['hash']){ + header("HTTP/1.0 412 Precondition Failed"); + print 'Precondition Failed'; + exit; + } + //handle external images + if(strncmp($MIME,'image/',6) == 0) $FILE = media_get_from_URL($MEDIA,$EXT,$CACHE); + if(!$FILE){ + //download failed - redirect to original URL + header('Location: '.$MEDIA); + exit; + } + }else{ + $MEDIA = cleanID($MEDIA); + if(empty($MEDIA)){ + header("HTTP/1.0 400 Bad Request"); + print 'Bad request'; + exit; + } + + //check permissions (namespace only) + if(auth_quickaclcheck(getNS($MEDIA).':X') < AUTH_READ){ + header("HTTP/1.0 401 Unauthorized"); + //fixme add some image for imagefiles + print 'Unauthorized'; + exit; + } + $FILE = mediaFN($MEDIA); + } + + //check file existance + if(!@file_exists($FILE)){ + header("HTTP/1.0 404 Not Found"); + //FIXME add some default broken image + print 'Not Found'; + exit; + } + + $ORIG = $FILE; + + //handle image resizing/cropping + if((substr($MIME,0,5) == 'image') && $WIDTH){ + if($HEIGHT){ + $FILE = media_crop_image($FILE,$EXT,$WIDTH,$HEIGHT); + }else{ + $FILE = media_resize_image($FILE,$EXT,$WIDTH,$HEIGHT); + } + } + + // finally send the file to the client + $data = array('file' => $FILE, + 'mime' => $MIME, + 'download' => $DL, + 'cache' => $CACHE, + 'orig' => $ORIG, + 'ext' => $EXT, + 'width' => $WIDTH, + 'height' => $HEIGHT); + + $evt = new Doku_Event('MEDIA_SENDFILE', $data); + if ($evt->advise_before()) { + sendFile($data['file'],$data['mime'],$data['download'],$data['cache']); + } + +/* ------------------------------------------------------------------------ */ + +/** + * Set headers and send the file to the client + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Ben Coburn <btcoburn@silicodon.net> + */ +function sendFile($file,$mime,$dl,$cache){ + global $conf; + $fmtime = @filemtime($file); + // send headers + header("Content-Type: $mime"); + // smart http caching headers + 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'); + } 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'); + } + //send important headers first, script stops here if '304 Not Modified' response + http_conditionalRequest($fmtime); + + + //download or display? + if($dl){ + header('Content-Disposition: attachment; filename="'.basename($file).'";'); + }else{ + header('Content-Disposition: inline; filename="'.basename($file).'";'); + } + + //use x-sendfile header to pass the delivery to compatible webservers + if (http_sendfile($file)) exit; + + // send file contents + $fp = @fopen($file,"rb"); + if($fp){ + http_rangeRequest($fp,filesize($file),$mime); + }else{ + header("HTTP/1.0 500 Internal Server Error"); + print "Could not read $file - bad permissions?"; + } +} + +/** + * Returns the wanted cachetime in seconds + * + * Resolves named constants + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function calc_cache($cache){ + global $conf; + + if(strtolower($cache) == 'nocache') return 0; //never cache + if(strtolower($cache) == 'recache') return $conf['cachetime']; //use standard cache + return -1; //cache endless +} + +//Setup VIM: ex: et ts=2 enc=utf-8 : diff --git a/vendors/dokuwiki/lib/exe/index.html b/vendors/dokuwiki/lib/exe/index.html new file mode 100644 index 000000000..d614603ac --- /dev/null +++ b/vendors/dokuwiki/lib/exe/index.html @@ -0,0 +1,12 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head> +<meta http-equiv="refresh" content="0; URL=../../" /> +<meta name="robots" content="noindex" /> +<title>nothing here...</title> +</head> +<body> +<!-- this is just here to prevent directory browsing --> +</body> +</html> diff --git a/vendors/dokuwiki/lib/exe/indexer.php b/vendors/dokuwiki/lib/exe/indexer.php new file mode 100644 index 000000000..872f6b5be --- /dev/null +++ b/vendors/dokuwiki/lib/exe/indexer.php @@ -0,0 +1,375 @@ +<?php +/** + * DokuWiki indexer + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +define('DOKU_DISABLE_GZIP_OUTPUT',1); +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/auth.php'); +require_once(DOKU_INC.'inc/events.php'); +session_write_close(); //close session +if(!defined('NL')) define('NL',"\n"); +global $ID; +// Version tag used to force rebuild on upgrade +define('INDEXER_VERSION', 2); + +// keep running after browser closes connection +@ignore_user_abort(true); + +// check if user abort worked, if yes send output early +$defer = !@ignore_user_abort() || $conf['broken_iua']; +if(!$defer){ + sendGIF(); // send gif +} + +$ID = cleanID($_REQUEST['id']); + +// Catch any possible output (e.g. errors) +if(!isset($_REQUEST['debug'])) ob_start(); + +// run one of the jobs +$tmp = array(); // No event data +$evt = new Doku_Event('INDEXER_TASKS_RUN', $tmp); +if ($evt->advise_before()) { + runIndexer() or + metaUpdate() or + runSitemapper() or + runTrimRecentChanges() or + runTrimRecentChanges(true) or + $evt->advise_after(); +} +if($defer) sendGIF(); + +if(!isset($_REQUEST['debug'])) ob_end_clean(); +exit; + +// -------------------------------------------------------------------- + +/** + * Trims the recent changes cache (or imports the old changelog) as needed. + * + * @param media_changes If the media changelog shall be trimmed instead of + * the page changelog + * + * @author Ben Coburn <btcoburn@silicodon.net> + */ +function runTrimRecentChanges($media_changes = false) { + global $conf; + + $fn = ($media_changes ? $conf['media_changelog'] : $conf['changelog']); + + // Trim the Recent Changes + // Trims the recent changes cache to the last $conf['changes_days'] recent + // changes or $conf['recent'] items, which ever is larger. + // The trimming is only done once a day. + if (@file_exists($fn) && + (@filemtime($fn.'.trimmed')+86400)<time() && + !@file_exists($fn.'_tmp')) { + @touch($fn.'.trimmed'); + io_lock($fn); + $lines = file($fn); + if (count($lines)<=$conf['recent']) { + // nothing to trim + io_unlock($fn); + return false; + } + + io_saveFile($fn.'_tmp', ''); // presave tmp as 2nd lock + $trim_time = time() - $conf['recent_days']*86400; + $out_lines = array(); + + for ($i=0; $i<count($lines); $i++) { + $log = parseChangelogLine($lines[$i]); + if ($log === false) continue; // discard junk + if ($log['date'] < $trim_time) { + $old_lines[$log['date'].".$i"] = $lines[$i]; // keep old lines for now (append .$i to prevent key collisions) + } else { + $out_lines[$log['date'].".$i"] = $lines[$i]; // definitely keep these lines + } + } + + if (count($lines)==count($out_lines)) { + // nothing to trim + @unlink($fn.'_tmp'); + io_unlock($fn); + return false; + } + + // sort the final result, it shouldn't be necessary, + // however the extra robustness in making the changelog cache self-correcting is worth it + ksort($out_lines); + $extra = $conf['recent'] - count($out_lines); // do we need extra lines do bring us up to minimum + if ($extra > 0) { + ksort($old_lines); + $out_lines = array_merge(array_slice($old_lines,-$extra),$out_lines); + } + + // save trimmed changelog + io_saveFile($fn.'_tmp', implode('', $out_lines)); + @unlink($fn); + if (!rename($fn.'_tmp', $fn)) { + // rename failed so try another way... + io_unlock($fn); + io_saveFile($fn, implode('', $out_lines)); + @unlink($fn.'_tmp'); + } else { + io_unlock($fn); + } + return true; + } + + // nothing done + return false; +} + +/** + * Runs the indexer for the current page + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function runIndexer(){ + global $ID; + global $conf; + print "runIndexer(): started".NL; + + // Move index files (if needed) + // Uses the importoldindex plugin to upgrade the index automatically. + // FIXME: Remove this from runIndexer when it is no longer needed. + if (@file_exists($conf['cachedir'].'/page.idx') && + (!@file_exists($conf['indexdir'].'/page.idx') || + !filesize($conf['indexdir'].'/page.idx')) && + !@file_exists($conf['indexdir'].'/index_importing')) { + echo "trigger TEMPORARY_INDEX_UPGRADE_EVENT\n"; + $tmp = array(); // no event data + trigger_event('TEMPORARY_INDEX_UPGRADE_EVENT', $tmp); + } + + 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']); + + require_once(DOKU_INC.'inc/indexer.php'); + + // upgrade to version 2 + if (!@file_exists($conf['indexdir'].'/pageword.idx')) + idx_upgradePageWords(); + + // 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; +} + +/** + * Will render the metadata for the page if not exists yet + * + * This makes sure pages which are created from outside DokuWiki will + * gain their data when viewed for the first time. + */ +function metaUpdate(){ + global $ID; + print "metaUpdate(): started".NL; + + if(!$ID) return false; + $file = metaFN($ID, '.meta'); + echo "meta file: $file".NL; + + // rendering needed? + if (@file_exists($file)) return false; + if (!@file_exists(wikiFN($ID))) return false; + + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/parserutils.php'); + global $conf; + + + // gather some additional info from changelog + $info = io_grep($conf['changelog'], + '/^(\d+)\t(\d+\.\d+\.\d+\.\d+)\t'.preg_quote($ID,'/').'\t([^\t]+)\t([^\t\n]+)/', + 0,true); + + $meta = array(); + if(!empty($info)){ + $meta['date']['created'] = $info[0][1]; + foreach($info as $item){ + if($item[4] != '*'){ + $meta['date']['modified'] = $item[1]; + if($item[3]){ + $meta['contributor'][$item[3]] = $item[3]; + } + } + } + } + + $meta = p_render_metadata($ID, $meta); + io_saveFile($file, serialize($meta)); + + echo "metaUpdate(): finished".NL; + return true; +} + +/** + * Builds a Google Sitemap of all public pages known to the indexer + * + * The map is placed in the root directory named sitemap.xml.gz - This + * file needs to be writable! + * + * @author Andreas Gohr + * @link https://www.google.com/webmasters/sitemaps/docs/en/about.html + */ +function runSitemapper(){ + global $conf; + print "runSitemapper(): started".NL; + if(!$conf['sitemap']) return false; + + if($conf['compression'] == 'bz2' || $conf['compression'] == 'gz'){ + $sitemap = 'sitemap.xml.gz'; + }else{ + $sitemap = 'sitemap.xml'; + } + print "runSitemapper(): using $sitemap".NL; + + if(@file_exists(DOKU_INC.$sitemap)){ + if(!is_writable(DOKU_INC.$sitemap)) return false; + }else{ + if(!is_writable(DOKU_INC)) return false; + } + + if(@filesize(DOKU_INC.$sitemap) && + @filemtime(DOKU_INC.$sitemap) > (time()-($conf['sitemap']*60*60*24))){ + print 'runSitemapper(): Sitemap up to date'.NL; + return false; + } + + $pages = file($conf['indexdir'].'/page.idx'); + print 'runSitemapper(): creating sitemap using '.count($pages).' pages'.NL; + + // build the sitemap + ob_start(); + print '<?xml version="1.0" encoding="UTF-8"?>'.NL; + print '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">'.NL; + foreach($pages as $id){ + $id = trim($id); + $file = wikiFN($id); + + //skip hidden, non existing and restricted files + if(isHiddenPage($id)) continue; + $date = @filemtime($file); + if(!$date) continue; + if(auth_aclcheck($id,'','') < AUTH_READ) continue; + + print ' <url>'.NL; + print ' <loc>'.wl($id,'',true).'</loc>'.NL; + print ' <lastmod>'.date_iso8601($date).'</lastmod>'.NL; + print ' </url>'.NL; + } + print '</urlset>'.NL; + $data = ob_get_contents(); + ob_end_clean(); + + //save the new sitemap + io_saveFile(DOKU_INC.$sitemap,$data); + + //ping search engines... + $http = new DokuHTTPClient(); + $http->timeout = 8; + + //ping google + print 'runSitemapper(): pinging google'.NL; + $url = 'http://www.google.com/webmasters/sitemaps/ping?sitemap='; + $url .= urlencode(DOKU_URL.$sitemap); + $resp = $http->get($url); + if($http->error) print 'runSitemapper(): '.$http->error.NL; + print 'runSitemapper(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp)).NL; + + //ping yahoo + print 'runSitemapper(): pinging yahoo'.NL; + $url = 'http://search.yahooapis.com/SiteExplorerService/V1/updateNotification?appid=dokuwiki&url='; + $url .= urlencode(DOKU_URL.$sitemap); + $resp = $http->get($url); + if($http->error) print 'runSitemapper(): '.$http->error.NL; + print 'runSitemapper(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp)).NL; + + //ping microsoft + print 'runSitemapper(): pinging microsoft'.NL; + $url = 'http://www.bing.com/webmaster/ping.aspx?siteMap='; + $url .= urlencode(DOKU_URL.$sitemap); + $resp = $http->get($url); + if($http->error) print 'runSitemapper(): '.$http->error.NL; + print 'runSitemapper(): '.preg_replace('/[\n\r]/',' ',strip_tags($resp)).NL; + + print 'runSitemapper(): finished'.NL; + return true; +} + +/** + * Formats a timestamp as ISO 8601 date + * + * @author <ungu at terong dot com> + * @link http://www.php.net/manual/en/function.date.php#54072 + */ +function date_iso8601($int_date) { + //$int_date: current date in UNIX timestamp + $date_mod = date('Y-m-d\TH:i:s', $int_date); + $pre_timezone = date('O', $int_date); + $time_zone = substr($pre_timezone, 0, 3).":".substr($pre_timezone, 3, 2); + $date_mod .= $time_zone; + return $date_mod; +} + +/** + * Just send a 1x1 pixel blank gif to the browser + * + * @author Andreas Gohr <andi@splitbrain.org> + * @author Harry Fuecks <fuecks@gmail.com> + */ +function sendGIF(){ + if(isset($_REQUEST['debug'])){ + header('Content-Type: text/plain'); + return; + } + $img = base64_decode('R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAEALAAAAAABAAEAAAIBTAA7'); + header('Content-Type: image/gif'); + header('Content-Length: '.strlen($img)); + header('Connection: Close'); + print $img; + flush(); + // Browser should drop connection after this + // Thinks it's got the whole image +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : +// No trailing PHP closing tag - no output please! +// See Note at http://www.php.net/manual/en/language.basic-syntax.instruction-separation.php diff --git a/vendors/dokuwiki/lib/exe/js.php b/vendors/dokuwiki/lib/exe/js.php new file mode 100644 index 000000000..cb1016231 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/js.php @@ -0,0 +1,397 @@ +<?php +/** + * DokuWiki JavaScript creator + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @author Andreas Gohr <andi@splitbrain.org> + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) +if(!defined('NL')) define('NL',"\n"); +if(!defined('DOKU_DISABLE_GZIP_OUTPUT')) define('DOKU_DISABLE_GZIP_OUTPUT',1); // we gzip ourself here +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/pageutils.php'); +require_once(DOKU_INC.'inc/httputils.php'); +require_once(DOKU_INC.'inc/io.php'); +require_once(DOKU_INC.'inc/JSON.php'); + +// Main (don't run when UNIT test) +if(!defined('SIMPLE_TEST')){ + header('Content-Type: text/javascript; charset=utf-8'); + js_out(); +} + + +// ---------------------- functions ------------------------------ + +/** + * Output all needed JavaScript + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function js_out(){ + global $conf; + global $lang; + + // The generated script depends on some dynamic options + $cache = getCacheName('scripts'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'],'.js'); + + // array of core files + $files = array( + DOKU_INC.'lib/scripts/helpers.js', + DOKU_INC.'lib/scripts/events.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/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/linkwiz.js', + DOKU_INC.'lib/scripts/media.js', + DOKU_TPLINC.'script.js', + ); + + // add possible plugin scripts and userscript + $files = array_merge($files,js_pluginscripts()); + $files[] = DOKU_CONF.'userscript.js'; + + // 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()); + } + + // start output buffering and build the script + ob_start(); + + // add some global variables + print "var DOKU_BASE = '".DOKU_BASE."';"; + print "var DOKU_MEDIA = '".DOKU_MEDIA."';"; + print "var DOKU_TPL = '".DOKU_TPL."';"; + print "var DOKU_UHN = ".((int) useHeading('navigation')).";"; + print "var DOKU_UHC = ".((int) useHeading('content')).";"; + + // load JS specific translations + $json = new JSON(); + $lang['js']['plugins'] = js_pluginstrings(); + echo 'LANG = '.$json->encode($lang['js']).";\n"; + + // load toolbar + require_once(DOKU_INC.'inc/toolbar.php'); + toolbar_JSdefines('toolbar'); + + // load files + foreach($files as $file){ + echo "\n\n/* XXXXXXXXXX begin of ".str_replace(DOKU_INC, '', $file) ." XXXXXXXXXX */\n\n"; + js_load($file); + echo "\n\n/* XXXXXXXXXX end of " . str_replace(DOKU_INC, '', $file) . " XXXXXXXXXX */\n\n"; + } + + + // init stuff + js_runonstart("ajax_qsearch.init('qsearch__in','qsearch__out')"); + js_runonstart("addEvent(document,'click',closePopups)"); + js_runonstart('addTocToggle()'); + js_runonstart("initSizeCtl('size__ctl','wiki__text')"); + js_runonstart("initToolbar('tool__bar','wiki__text',toolbar)"); + js_runonstart("initChangeCheck('".js_escape($lang['notsavedyet'])."')"); + js_runonstart("locktimer.init(".($conf['locktime'] - 60).",'".js_escape($lang['willexpire'])."',".$conf['usedraft'].")"); + js_runonstart('scrollToMarker()'); + js_runonstart('focusMarker()'); + + // end output buffering and get contents + $js = ob_get_contents(); + ob_end_clean(); + + // compress whitespace and comments + if($conf['compress']){ + $js = js_compress($js); + } + + $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; + } +} + +/** + * Load the given file, handle include calls and print it + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function js_load($file){ + if(!@file_exists($file)) return; + static $loaded = array(); + + $data = io_readFile($file); + while(preg_match('#/\*\s*DOKUWIKI:include(_once)?\s+([\w\./]+)\s*\*/#',$data,$match)){ + $ifile = $match[2]; + + // is it a include_once? + if($match[1]){ + $base = basename($ifile); + if($loaded[$base]) continue; + $loaded[$base] = true; + } + + if($ifile{0} != '/') $ifile = dirname($file).'/'.$ifile; + + if(@file_exists($ifile)){ + $idata = io_readFile($ifile); + }else{ + $idata = ''; + } + $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; +} + +/** + * Returns a list of possible Plugin Scripts (no existance check here) + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function js_pluginscripts(){ + $list = array(); + $plugins = plugin_list(); + foreach ($plugins as $p){ + $list[] = DOKU_PLUGIN."$p/script.js"; + } + return $list; +} + +/** + * Return an two-dimensional array with strings from the language file of each plugin. + * + * - $lang['js'] must be an array. + * - Nothing is returned for plugins without an entry for $lang['js'] + * + * @author Gabriel Birke <birke@d-scribe.de> + */ +function js_pluginstrings() +{ + global $conf; + $pluginstrings = array(); + $plugins = plugin_list(); + foreach ($plugins as $p){ + if (isset($lang)) unset($lang); + if (@file_exists(DOKU_PLUGIN."$p/lang/en/lang.php")) { + include DOKU_PLUGIN."$p/lang/en/lang.php"; + } + if (isset($conf['lang']) && $conf['lang']!='en' && @file_exists(DOKU_PLUGIN."$p/lang/".$conf['lang']."/lang.php")) { + include DOKU_PLUGIN."$p/lang/".$conf['lang']."/lang.php"; + } + if (isset($lang['js'])) { + $pluginstrings[$p] = $lang['js']; + } + } + return $pluginstrings; +} + +/** + * Escapes a String to be embedded in a JavaScript call, keeps \n + * as newline + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function js_escape($string){ + return str_replace('\\\\n','\\n',addslashes($string)); +} + +/** + * Adds the given JavaScript code to the window.onload() event + * + * @author Andreas Gohr <andi@splitbrain.org> + */ +function js_runonstart($func){ + echo "addInitEvent(function(){ $func; });".NL; +} + +/** + * Strip comments and whitespaces from given JavaScript Code + * + * This is a port of Nick Galbreath's python tool jsstrip.py which is + * released under BSD license. See link for original code. + * + * @author Nick Galbreath <nickg@modp.com> + * @author Andreas Gohr <andi@splitbrain.org> + * @link http://code.google.com/p/jsstrip/ + */ +function js_compress($s){ + $s = ltrim($s); // strip all initial whitespace + $s .= "\n"; + $i = 0; // char index for input string + $j = 0; // char forward index for input string + $line = 0; // line number of file (close to it anyways) + $slen = strlen($s); // size of input string + $lch = ''; // last char added + $result = ''; // we store the final result here + + // items that don't need spaces next to them + $chars = "^&|!+\-*\/%=\?:;,{}()<>% \t\n\r'\"[]"; + + $regex_starters = array("(", "=", "[", "," , ":"); + + $whitespaces_chars = array(" ", "\t", "\n", "\r", "\0", "\x0B"); + + while($i < $slen){ + // skip all "boring" characters. This is either + // reserved word (e.g. "for", "else", "if") or a + // variable/object/method (e.g. "foo.color") + while ($i < $slen && (strpos($chars,$s[$i]) === false) ){ + $result .= $s{$i}; + $i = $i + 1; + } + + $ch = $s{$i}; + // multiline comments (keeping IE conditionals) + if($ch == '/' && $s{$i+1} == '*' && $s{$i+2} != '@'){ + $endC = strpos($s,'*/',$i+2); + if($endC === false) trigger_error('Found invalid /*..*/ comment', E_USER_ERROR); + $i = $endC + 2; + continue; + } + + // singleline + if($ch == '/' && $s{$i+1} == '/'){ + $endC = strpos($s,"\n",$i+2); + if($endC === false) trigger_error('Invalid comment', E_USER_ERROR); + $i = $endC; + continue; + } + + // tricky. might be an RE + if($ch == '/'){ + // rewind, skip white space + $j = 1; + while(in_array($s{$i-$j}, $whitespaces_chars)){ + $j = $j + 1; + } + if( in_array($s{$i-$j}, $regex_starters) ){ + // yes, this is an re + // now move forward and find the end of it + $j = 1; + while($s{$i+$j} != '/'){ + while( ($s{$i+$j} != '\\') && ($s{$i+$j} != '/')){ + $j = $j + 1; + } + if($s{$i+$j} == '\\') $j = $j + 2; + } + $result .= substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + } + + // double quote strings + if($ch == '"'){ + $j = 1; + while( $s{$i+$j} != '"' && ($i+$j < $slen)){ + if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == '"' || $s{$i+$j+1} == '\\') ){ + $j += 2; + }else{ + $j += 1; + } + } + $result .= substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + + // single quote strings + if($ch == "'"){ + $j = 1; + while( $s{$i+$j} != "'" && ($i+$j < $slen)){ + if( $s{$i+$j} == '\\' && ($s{$i+$j+1} == "'" || $s{$i+$j+1} == '\\') ){ + $j += 2; + }else{ + $j += 1; + } + } + $result .= substr($s,$i,$j+1); + $i = $i + $j + 1; + continue; + } + + // whitespaces + if( $ch == ' ' || $ch == "\r" || $ch == "\n" || $ch == "\t" ){ + // leading spaces + if($i+1 < $slen && (strpos($chars,$s[$i+1]) !== false)){ + $i = $i + 1; + continue; + } + // trailing spaces + // if this ch is space AND the last char processed + // is special, then skip the space + $lch = substr($result,-1); + if($lch && (strpos($chars,$lch) !== false)){ + $i = $i + 1; + continue; + } + // else after all of this convert the "whitespace" to + // a single space. It will get appended below + $ch = ' '; + } + + // other chars + $result .= $ch; + $i = $i + 1; + } + + return trim($result); +} + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/vendors/dokuwiki/lib/exe/mediamanager.php b/vendors/dokuwiki/lib/exe/mediamanager.php new file mode 100644 index 000000000..f6e91b858 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/mediamanager.php @@ -0,0 +1,105 @@ +<?php + if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); + define('DOKU_MEDIAMANAGER',1); + + // for multi uploader: + @ini_set('session.use_only_cookies',0); + + require_once(DOKU_INC.'inc/init.php'); + require_once(DOKU_INC.'inc/lang/en/lang.php'); + require_once(DOKU_INC.'inc/lang/'.$conf['lang'].'/lang.php'); + require_once(DOKU_INC.'inc/media.php'); + require_once(DOKU_INC.'inc/common.php'); + require_once(DOKU_INC.'inc/search.php'); + require_once(DOKU_INC.'inc/template.php'); + require_once(DOKU_INC.'inc/auth.php'); + + trigger_event('MEDIAMANAGER_STARTED',$tmp=array()); + session_write_close(); //close session + + // handle passed message + if($_REQUEST['msg1']) msg(hsc($_REQUEST['msg1']),1); + if($_REQUEST['err']) msg(hsc($_REQUEST['err']),-1); + + + // get namespace to display (either direct or from deletion order) + if($_REQUEST['delete']){ + $DEL = cleanID($_REQUEST['delete']); + $IMG = $DEL; + $NS = getNS($DEL); + }elseif($_REQUEST['edit']){ + $IMG = cleanID($_REQUEST['edit']); + $NS = getNS($IMG); + }elseif($_REQUEST['img']){ + $IMG = cleanID($_REQUEST['img']); + $NS = getNS($IMG); + }else{ + $NS = $_REQUEST['ns']; + $NS = cleanID($NS); + } + + // check auth + $AUTH = auth_quickaclcheck("$NS:*"); + + // create the given namespace (just for beautification) + if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$NS:xxx", 'media'); } + + // handle flash upload + if(isset($_FILES['Filedata'])){ + $_FILES['upload'] =& $_FILES['Filedata']; + $JUMPTO = media_upload($NS,$AUTH); + if($JUMPTO == false){ + header("HTTP/1.0 400 Bad Request"); + echo 'Upload failed'; + } + echo 'ok'; + exit; + } + + // give info on PHP catched upload errors + if($_FILES['upload']['error']){ + switch($_FILES['upload']['error']){ + case 1: + case 2: + msg(sprintf($lang['uploadsize'], + filesize_h(php_to_byte(ini_get('upload_max_filesize')))),-1); + break; + default: + msg($lang['uploadfail'].' ('.$_FILES['upload']['error'].')',-1); + } + unset($_FILES['upload']); + } + + // handle upload + if($_FILES['upload']['tmp_name']){ + $JUMPTO = media_upload($NS,$AUTH); + if($JUMPTO) $NS = getNS($JUMPTO); + } + + // handle meta saving + if($IMG && $_REQUEST['do']['save']){ + $JUMPTO = media_metasave($IMG,$AUTH,$_REQUEST['meta']); + } + + // 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); + } + } else { + if(!$conf['refshow']) { + unset($INUSE); + msg(sprintf($lang['mediainuse'],noNS($DEL)),0); + } + } + } + + // finished - start output + header('Content-Type: text/html; charset=utf-8'); + include(template('mediamanager.php')); + +/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */ diff --git a/vendors/dokuwiki/lib/exe/multipleUpload.swf b/vendors/dokuwiki/lib/exe/multipleUpload.swf Binary files differnew file mode 100644 index 000000000..888aab045 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/multipleUpload.swf diff --git a/vendors/dokuwiki/lib/exe/opensearch.php b/vendors/dokuwiki/lib/exe/opensearch.php new file mode 100644 index 000000000..f16b4f681 --- /dev/null +++ b/vendors/dokuwiki/lib/exe/opensearch.php @@ -0,0 +1,38 @@ +<?php +/** + * DokuWiki OpenSearch creator + * + * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) + * @link http://www.opensearch.org/ + * @author Mike Frysinger <vapier@gentoo.org> + * @author Andreas Gohr <andi@splitbrain.org> + */ + +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); +if(!defined('NOSESSION')) define('NOSESSION',true); // we do not use a session or authentication here (better caching) +if(!defined('NL')) define('NL',"\n"); +require_once(DOKU_INC.'inc/init.php'); + +// try to be clever about the favicon location +if(file_exists(DOKU_INC.'favicon.ico')){ + $ico = DOKU_URL.'favicon.ico'; +}elseif(file_exists(DOKU_TPLINC.'images/favicon.ico')){ + $ico = DOKU_URL.'lib/tpl/'.$conf['template'].'/images/favicon.ico'; +}elseif(file_exists(DOKU_TPLINC.'favicon.ico')){ + $ico = DOKU_URL.'lib/tpl/'.$conf['template'].'/favicon.ico'; +}else{ + $ico = DOKU_URL.'lib/tpl/default/images/favicon.ico'; +} + +// output +header('Content-Type: application/opensearchdescription+xml; charset=utf-8'); +echo '<?xml version="1.0"?>'.NL; +echo '<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">'.NL; +echo ' <ShortName>'.htmlspecialchars($conf['title']).'</ShortName>'.NL; +echo ' <Image width="16" height="16" type="image/x-icon">'.$ico.'</Image>'.NL; +echo ' <Url type="text/html" template="'.DOKU_URL.DOKU_SCRIPT.'?do=search&id={searchTerms}" />'.NL; +echo ' <Url type="application/x-suggestions+json" template="'. + DOKU_URL.'lib/exe/ajax.php?call=suggestions&q={searchTerms}" />'.NL; +echo '</OpenSearchDescription>'.NL; + +//Setup VIM: ex: et ts=4 enc=utf-8 : diff --git a/vendors/dokuwiki/lib/exe/xmlrpc.php b/vendors/dokuwiki/lib/exe/xmlrpc.php new file mode 100644 index 000000000..d3913482f --- /dev/null +++ b/vendors/dokuwiki/lib/exe/xmlrpc.php @@ -0,0 +1,921 @@ +<?php +if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); + +// 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); + +/** + * Increased whenever the API is changed + */ +define('DOKU_XMLRPC_API_VERSION',2); + +require_once(DOKU_INC.'inc/init.php'); +require_once(DOKU_INC.'inc/common.php'); +require_once(DOKU_INC.'inc/auth.php'); +session_write_close(); //close session + +if(!$conf['xmlrpc']) die('XML-RPC server not enabled.'); + +require_once(DOKU_INC.'inc/IXR_Library.php'); + + +/** + * Contains needed wrapper functions and registers all available + * XMLRPC functions. + */ +class dokuwiki_xmlrpc_server extends IXR_IntrospectionServer { + var $methods = array(); + var $public_methods = array(); + + /** + * Checks if the current user is allowed to execute non anonymous methods + */ + function checkAuth(){ + global $conf; + global $USERINFO; + + if(!$conf['useacl']) return true; //no ACL - then no checks + + $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; + } + + /** + * Adds a callback, extends parent method + * + * add another parameter to define if anonymous access to + * this method should be granted. + */ + function addCallback($method, $callback, $args, $help, $public=false){ + if($public) $this->public_methods[] = $method; + return parent::addCallback($method, $callback, $args, $help); + } + + /** + * Execute a call, extends parent method + * + * Checks for authentication first + */ + function call($methodname, $args){ + if(!in_array($methodname,$this->public_methods) && !$this->checkAuth()){ + return new IXR_Error(-32603, 'server error. not authorized to call method "'.$methodname.'".'); + } + return parent::call($methodname, $args); + } + + /** + * Constructor. Register methods and run Server + */ + function dokuwiki_xmlrpc_server(){ + $this->IXR_IntrospectionServer(); + + /* DokuWiki's own methods */ + $this->addCallback( + 'dokuwiki.getXMLRPCAPIVersion', + 'this:getAPIVersion', + array('integer'), + 'Returns the XMLRPC API version.', + true + ); + + $this->addCallback( + 'dokuwiki.getVersion', + 'getVersion', + array('string'), + 'Returns the running DokuWiki version.', + true + ); + + $this->addCallback( + 'dokuwiki.login', + 'this:login', + array('integer','string','string'), + 'Tries to login with the given credentials and sets auth cookies.', + true + ); + + $this->addCallback( + 'dokuwiki.getPagelist', + 'this:readNamespace', + array('struct','string','struct'), + 'List all pages within the given namespace.' + ); + + $this->addCallback( + 'dokuwiki.getTime', + 'time', + array('int'), + 'Return the current time at the wiki server.' + ); + + $this->addCallback( + 'dokuwiki.setLocks', + 'this:setLocks', + array('struct','struct'), + 'Lock or unlock pages.' + ); + + /* Wiki API v2 http://www.jspwiki.org/wiki/WikiRPCInterface2 */ + $this->addCallback( + 'wiki.getRPCVersionSupported', + 'this:wiki_RPCVersion', + array('int'), + 'Returns 2 with the supported RPC API version.', + true + ); + $this->addCallback( + 'wiki.getPage', + 'this:rawPage', + array('string','string'), + 'Get the raw Wiki text of page, latest version.' + ); + $this->addCallback( + 'wiki.getPageVersion', + 'this:rawPage', + array('string','string','int'), + 'Get the raw Wiki text of page.' + ); + $this->addCallback( + 'wiki.getPageHTML', + 'this:htmlPage', + array('string','string'), + 'Return page in rendered HTML, latest version.' + ); + $this->addCallback( + 'wiki.getPageHTMLVersion', + 'this:htmlPage', + array('string','string','int'), + 'Return page in rendered HTML.' + ); + $this->addCallback( + 'wiki.getAllPages', + 'this:listPages', + array('struct'), + 'Returns a list of all pages. The result is an array of utf8 pagenames.' + ); + $this->addCallback( + 'wiki.getAttachments', + 'this:listAttachments', + array('struct', 'string', 'struct'), + 'Returns a list of all media files.' + ); + $this->addCallback( + 'wiki.getBackLinks', + 'this:listBackLinks', + array('struct','string'), + 'Returns the pages that link to this page.' + ); + $this->addCallback( + 'wiki.getPageInfo', + 'this:pageInfo', + array('struct','string'), + 'Returns a struct with infos about the page.' + ); + $this->addCallback( + 'wiki.getPageInfoVersion', + 'this:pageInfo', + array('struct','string','int'), + 'Returns a struct with infos about the page.' + ); + $this->addCallback( + 'wiki.getPageVersions', + 'this:pageVersions', + array('struct','string','int'), + 'Returns the available revisions of the page.' + ); + $this->addCallback( + 'wiki.putPage', + 'this:putPage', + array('int', 'string', 'string', 'struct'), + 'Saves a wiki page.' + ); + $this->addCallback( + 'wiki.listLinks', + 'this:listLinks', + array('struct','string'), + 'Lists all links contained in a wiki page.' + ); + $this->addCallback( + 'wiki.getRecentChanges', + 'this:getRecentChanges', + array('struct','int'), + 'Returns a struct about all recent changes since given timestamp.' + ); + $this->addCallback( + 'wiki.getRecentMediaChanges', + 'this:getRecentMediaChanges', + array('struct','int'), + 'Returns a struct about all recent media changes since given timestamp.' + ); + $this->addCallback( + 'wiki.aclCheck', + 'this:aclCheck', + array('int', 'string'), + 'Returns the permissions of a given wiki page.' + ); + $this->addCallback( + 'wiki.putAttachment', + 'this:putAttachment', + array('struct', 'string', 'base64', 'struct'), + 'Upload a file to the wiki.' + ); + $this->addCallback( + 'wiki.deleteAttachment', + 'this:deleteAttachment', + array('int', 'string'), + 'Delete a file from the wiki.' + ); + $this->addCallback( + 'wiki.getAttachment', + 'this:getAttachment', + array('base64', 'string'), + 'Download a file from the wiki.' + ); + $this->addCallback( + 'wiki.getAttachmentInfo', + 'this:getAttachmentInfo', + array('struct', 'string'), + 'Returns a struct with infos about the attachment.' + ); + + /** + * Trigger XMLRPC_CALLBACK_REGISTER, action plugins can use this event + * to extend the XMLRPC interface and register their own callbacks. + * + * Event data: + * The XMLRPC server object: + * + * $event->data->addCallback() - register a callback, the second + * paramter has to be of the form "plugin:<pluginname>:<plugin + * method>" + * + * $event->data->callbacks - an array which holds all awaylable + * callbacks + */ + trigger_event('XMLRPC_CALLBACK_REGISTER', $this); + + $this->serve(); + } + + /** + * Return a raw wiki page + */ + function rawPage($id,$rev=''){ + if(auth_quickaclcheck($id) < AUTH_READ){ + return new IXR_Error(1, 'You are not allowed to read this page'); + } + $text = rawWiki($id,$rev); + if(!$text) { + $data = array($id); + return trigger_event('HTML_PAGE_FROMTEMPLATE',$data,'pageTemplate',true); + } else { + return $text; + } + } + + /** + * Return a media file encoded in base64 + * + * @author Gina Haeussge <osd@foosel.net> + */ + function getAttachment($id){ + $id = cleanID($id); + if (auth_quickaclcheck(getNS($id).':*') < AUTH_READ) + return new IXR_Error(1, 'You are not allowed to read this file'); + + $file = mediaFN($id); + if (!@ file_exists($file)) + return new IXR_Error(1, 'The requested file does not exist'); + + $data = io_readFile($file, false); + $base64 = base64_encode($data); + return $base64; + } + + /** + * Return info about a media file + * + * @author Gina Haeussge <osd@foosel.net> + */ + function getAttachmentInfo($id){ + $id = cleanID($id); + $info = array( + 'lastModified' => 0, + 'size' => 0, + ); + + $file = mediaFN($id); + if ((auth_quickaclcheck(getNS($id).':*') >= AUTH_READ) && file_exists($file)){ + $info['lastModified'] = new IXR_Date(filemtime($file)); + $info['size'] = filesize($file); + } + + return $info; + } + + /** + * Return a wiki page rendered to html + */ + function htmlPage($id,$rev=''){ + if(auth_quickaclcheck($id) < AUTH_READ){ + return new IXR_Error(1, 'You are not allowed to read this page'); + } + return p_wiki_xhtml($id,$rev,false); + } + + /** + * List all pages - we use the indexer list here + */ + function listPages(){ + global $conf; + + $list = array(); + $pages = file($conf['indexdir'] . '/page.idx'); + $pages = array_filter($pages, 'isVisiblePage'); + + foreach(array_keys($pages) as $idx) { + if(page_exists($pages[$idx])) { + $perm = auth_quickaclcheck($pages[$idx]); + if($perm >= AUTH_READ) { + $page = array(); + $page['id'] = trim($pages[$idx]); + $page['perms'] = $perm; + $page['size'] = @filesize(wikiFN($pages[$idx])); + $page['lastModified'] = new IXR_Date(@filemtime(wikiFN($pages[$idx]))); + $list[] = $page; + } + } + } + + return $list; + } + + /** + * List all pages in the given namespace (and below) + */ + function readNamespace($ns,$opts){ + global $conf; + + if(!is_array($opts)) $opts=array(); + + $ns = cleanID($ns); + $dir = utf8_encodeFN(str_replace(':', '/', $ns)); + $data = array(); + require_once(DOKU_INC.'inc/search.php'); + $opts['skipacl'] = 0; // no ACL skipping for XMLRPC + search($data, $conf['datadir'], 'search_allpages', $opts, $dir); + return $data; + } + + /** + * List all media files. + * + * Available options are 'recursive' for also including the subnamespaces + * in the listing, and 'pattern' for filtering the returned files against + * a regular expression matching their name. + * + * @author Gina Haeussge <osd@foosel.net> + */ + function listAttachments($ns, $options = array()) { + global $conf; + global $lang; + + $ns = cleanID($ns); + + if (!is_array($options)) $options = array(); + $options['skipacl'] = 0; // no ACL skipping for XMLRPC + + + if(auth_quickaclcheck($ns.':*') >= AUTH_READ) { + $dir = utf8_encodeFN(str_replace(':', '/', $ns)); + + $data = array(); + require_once(DOKU_INC.'inc/search.php'); + search($data, $conf['mediadir'], 'search_media', $options, $dir); + $len = count($data); + if(!$len) return array(); + + for($i=0; $i<$len; $i++) { + unset($data[$i]['meta']); + $data[$i]['lastModified'] = new IXR_Date($data[$i]['mtime']); + } + return $data; + } else { + return new IXR_Error(1, 'You are not allowed to list media files.'); + } + } + + /** + * Return a list of backlinks + */ + function listBackLinks($id){ + require_once(DOKU_INC.'inc/fulltext.php'); + return ft_backlinks($id); + } + + /** + * Return some basic data about a page + */ + function pageInfo($id,$rev=''){ + if(auth_quickaclcheck($id) < AUTH_READ){ + return new IXR_Error(1, 'You are not allowed to read this page'); + } + $file = wikiFN($id,$rev); + $time = @filemtime($file); + if(!$time){ + return new IXR_Error(10, 'The requested page does not exist'); + } + + $info = getRevisionInfo($id, $time, 1024); + + $data = array( + 'name' => $id, + 'lastModified' => new IXR_Date($time), + 'author' => (($info['user']) ? $info['user'] : $info['ip']), + 'version' => $time + ); + + return ($data); + } + + /** + * Save a wiki page + * + * @author Michael Klier <chi@chimeric.de> + */ + function putPage($id, $text, $params) { + global $TEXT; + global $lang; + global $conf; + + $id = cleanID($id); + $TEXT = cleanText($text); + $sum = $params['sum']; + $minor = $params['minor']; + + if(empty($id)) + return new IXR_Error(1, 'Empty page ID'); + + if(!page_exists($id) && trim($TEXT) == '' ) { + return new IXR_ERROR(1, 'Refusing to write an empty new wiki page'); + } + + if(auth_quickaclcheck($id) < AUTH_EDIT) + return new IXR_Error(1, 'You are not allowed to edit this page'); + + // Check, if page is locked + if(checklock($id)) + return new IXR_Error(1, 'The page is currently locked'); + + // SPAM check + if(checkwordblock()) + return new IXR_Error(1, 'Positive wordblock check'); + + // autoset summary on new pages + if(!page_exists($id) && empty($sum)) { + $sum = $lang['created']; + } + + // autoset summary on deleted pages + if(page_exists($id) && empty($TEXT) && empty($sum)) { + $sum = $lang['deleted']; + } + + lock($id); + + saveWikiText($id,$TEXT,$sum,$minor); + + 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']); + + require_once(DOKU_INC.'inc/indexer.php'); + + // do the work + idx_addPage($id); + + // we're finished - save and free lock + io_saveFile(metaFN($id,'.indexed'),INDEXER_VERSION); + @rmdir($lock); + } + + return 0; + } + + /** + * Uploads a file to the wiki. + * + * Michael Klier <chi@chimeric.de> + */ + function putAttachment($id, $file, $params) { + global $conf; + global $lang; + + $auth = auth_quickaclcheck(getNS($id).':*'); + if($auth >= AUTH_UPLOAD) { + if(!isset($id)) { + return new IXR_ERROR(1, 'Filename not given.'); + } + + $ftmp = $conf['tmpdir'] . '/' . $id; + + // save temporary file + @unlink($ftmp); + $buff = base64_decode($file); + io_saveFile($ftmp, $buff); + + // 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 + @require_once(DOKU_INC.'inc/media.php'); + $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']); + } + + // prepare event data + $data[0] = $ftmp; + $data[1] = $fn; + $data[2] = $id; + $data[3] = $imime; + $data[4] = $overwrite; + + // trigger event + require_once(DOKU_INC.'inc/events.php'); + return trigger_event('MEDIA_UPLOAD_FINISH', $data, array($this, '_media_upload_action'), true); + + } else { + return new IXR_ERROR(1, $lang['uploadwrong']); + } + } else { + return new IXR_ERROR(1, "You don't have permissions to upload files."); + } + } + + /** + * Deletes a file from the wiki. + * + * @author Gina Haeussge <osd@foosel.net> + */ + function deleteAttachment($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']){ + require_once(DOKU_INC.'inc/fulltext.php'); + $mediareferences = ft_mediause($id,$conf['refshow']); + } + + if(!count($mediareferences)){ + $file = mediaFN($id); + if(@unlink($file)){ + require_once(DOKU_INC.'inc/changelog.php'); + 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 { + 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 + require_once(DOKU_INC.'inc/changelog.php'); + 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.'); + } + } + + /** + * Returns the permissions of a given wiki page + */ + function aclCheck($id) { + return auth_quickaclcheck($id); + } + + /** + * Lists all links contained in a wiki page + * + * @author Michael Klier <chi@chimeric.de> + */ + function listLinks($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))); + + // instantiate new Renderer - needed for interwiki links + include(DOKU_INC.'inc/parser/xhtml.php'); + $Renderer = new Doku_Renderer_xhtml(); + $Renderer->interwiki = getInterwiki(); + + // parse parse instructions + foreach($ins as $in) { + $link = array(); + switch($in[0]) { + case 'internallink': + $link['type'] = 'local'; + $link['page'] = $in[1][0]; + $link['href'] = wl($in[1][0]); + array_push($links,$link); + break; + case 'externallink': + $link['type'] = 'extern'; + $link['page'] = $in[1][0]; + $link['href'] = $in[1][0]; + array_push($links,$link); + break; + case 'interwikilink': + $url = $Renderer->_resolveInterWiki($in[1][2],$in[1][3]); + $link['type'] = 'extern'; + $link['page'] = $url; + $link['href'] = $url; + array_push($links,$link); + break; + } + } + + return ($links); + } + + /** + * Returns a list of recent changes since give timestamp + * + * @author Michael Hamann <michael@content-space.de> + * @author Michael Klier <chi@chimeric.de> + */ + function getRecentChanges($timestamp) { + if(strlen($timestamp) != 10) + return new IXR_Error(20, 'The provided value is not a valid timestamp'); + + require_once(DOKU_INC.'inc/changelog.php'); + require_once(DOKU_INC.'inc/pageutils.php'); + + $recents = getRecentsSince($timestamp); + + $changes = array(); + + foreach ($recents as $recent) { + $change = array(); + $change['name'] = $recent['id']; + $change['lastModified'] = new IXR_Date($recent['date']); + $change['author'] = $recent['user']; + $change['version'] = $recent['date']; + $change['perms'] = $recent['perms']; + $change['size'] = @filesize(wikiFN($recent['id'])); + array_push($changes, $change); + } + + if (!empty($changes)) { + return $changes; + } else { + // in case we still have nothing at this point + return new IXR_Error(30, 'There are no changes in the specified timeframe'); + } + } + + /** + * Returns a list of recent media changes since give timestamp + * + * @author Michael Hamann <michael@content-space.de> + * @author Michael Klier <chi@chimeric.de> + */ + function getRecentMediaChanges($timestamp) { + if(strlen($timestamp) != 10) + return new IXR_Error(20, 'The provided value is not a valid timestamp'); + + require_once(DOKU_INC.'inc/changelog.php'); + require_once(DOKU_INC.'inc/pageutils.php'); + + $recents = getRecentsSince($timestamp, null, '', RECENTS_MEDIA_CHANGES); + + $changes = array(); + + foreach ($recents as $recent) { + $change = array(); + $change['name'] = $recent['id']; + $change['lastModified'] = new IXR_Date($recent['date']); + $change['author'] = $recent['user']; + $change['version'] = $recent['date']; + $change['perms'] = $recent['perms']; + $change['size'] = @filesize(mediaFN($recent['id'])); + array_push($changes, $change); + } + + if (!empty($changes)) { + return $changes; + } else { + // in case we still have nothing at this point + return new IXR_Error(30, 'There are no changes in the specified timeframe'); + } + } + + /** + * Returns a list of available revisions of a given wiki page + * + * @author Michael Klier <chi@chimeric.de> + */ + function pageVersions($id, $first) { + global $conf; + + $versions = array(); + + if(empty($id)) + return new IXR_Error(1, 'Empty page ID'); + + require_once(DOKU_INC.'inc/changelog.php'); + + $revisions = getRevisions($id, $first, $conf['recent']+1); + + if(count($revisions)==0 && $first!=0) { + $first=0; + $revisions = getRevisions($id, $first, $conf['recent']+1); + } + + if(count($revisions)>0 && $first==0) { + array_unshift($revisions, ''); // include current revision + array_pop($revisions); // remove extra log entry + } + + $hasNext = false; + if(count($revisions)>$conf['recent']) { + $hasNext = true; + array_pop($revisions); // remove extra log entry + } + + if(!empty($revisions)) { + foreach($revisions as $rev) { + $file = wikiFN($id,$rev); + $time = @filemtime($file); + // we check if the page actually exists, if this is not the + // case this can lead to less pages being returned than + // specified via $conf['recent'] + if($time){ + $info = getRevisionInfo($id, $time, 1024); + if(!empty($info)) { + $data['user'] = $info['user']; + $data['ip'] = $info['ip']; + $data['type'] = $info['type']; + $data['sum'] = $info['sum']; + $data['modified'] = new IXR_Date($info['date']); + $data['version'] = $info['date']; + array_push($versions, $data); + } + } + } + return $versions; + } else { + return array(); + } + } + + /** + * The version of Wiki RPC API supported + */ + function wiki_RPCVersion(){ + return 2; + } + + + /** + * Locks or unlocks a given batch of pages + * + * Give an associative array with two keys: lock and unlock. Both should contain a + * list of pages to lock or unlock + * + * Returns an associative array with the keys locked, lockfail, unlocked and + * unlockfail, each containing lists of pages. + */ + function setLocks($set){ + $locked = array(); + $lockfail = array(); + $unlocked = array(); + $unlockfail = array(); + + foreach((array) $set['lock'] as $id){ + if(checklock($id)){ + $lockfail[] = $id; + }else{ + lock($id); + $locked[] = $id; + } + } + + foreach((array) $set['unlock'] as $id){ + if(unlock($id)){ + $unlocked[] = $id; + }else{ + $unlockfail[] = $id; + } + } + + return array( + 'locked' => $locked, + 'lockfail' => $lockfail, + 'unlocked' => $unlocked, + 'unlockfail' => $unlockfail, + ); + } + + function getAPIVersion(){ + return DOKU_XMLRPC_API_VERSION; + } + + function login($user,$pass){ + global $conf; + global $auth; + if(!$conf['useacl']) return 0; + if(!$auth) return 0; + if($auth->canDo('external')){ + return $auth->trustExternal($user,$pass,false); + }else{ + return auth_login($user,$pass,false,true); + } + } + + +} + +$server = new dokuwiki_xmlrpc_server(); + +// vim:ts=4:sw=4:et:enc=utf-8: |