1<?php 2/** 3 * DokuWiki AJAX call handler 4 * 5 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 6 * @author Andreas Gohr <andi@splitbrain.org> 7 */ 8 9//fix for Opera XMLHttpRequests 10if(!count($_POST) && $HTTP_RAW_POST_DATA){ 11 parse_str($HTTP_RAW_POST_DATA, $_POST); 12} 13 14if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); 15require_once(DOKU_INC.'inc/init.php'); 16require_once(DOKU_INC.'inc/common.php'); 17require_once(DOKU_INC.'inc/pageutils.php'); 18require_once(DOKU_INC.'inc/auth.php'); 19//close sesseion 20session_write_close(); 21 22header('Content-Type: text/html; charset=utf-8'); 23 24 25//call the requested function 26if(isset($_POST['call'])) 27 $call = $_POST['call']; 28else if(isset($_GET['call'])) 29 $call = $_GET['call']; 30else 31 exit; 32 33$callfn = 'ajax_'.$call; 34 35if(function_exists($callfn)){ 36 $callfn(); 37}else{ 38 $evt = new Doku_Event('AJAX_CALL_UNKNOWN', $call); 39 if ($evt->advise_before()) { 40 print "AJAX call '".htmlspecialchars($call)."' unknown!\n"; 41 exit; 42 } 43 $evt->advise_after(); 44 unset($evt); 45} 46 47/** 48 * Searches for matching pagenames 49 * 50 * @author Andreas Gohr <andi@splitbrain.org> 51 */ 52function ajax_qsearch(){ 53 global $conf; 54 global $lang; 55 56 $query = cleanID($_POST['q']); 57 if(empty($query)) $query = cleanID($_GET['q']); 58 if(empty($query)) return; 59 60 require_once(DOKU_INC.'inc/html.php'); 61 require_once(DOKU_INC.'inc/fulltext.php'); 62 63 $data = array(); 64 $data = ft_pageLookup($query); 65 66 if(!count($data)) return; 67 68 print '<strong>'.$lang['quickhits'].'</strong>'; 69 print '<ul>'; 70 foreach($data as $id){ 71 print '<li>'; 72 $ns = getNS($id); 73 if($ns){ 74 $name = shorten(noNS($id), ' ('.$ns.')',30); 75 }else{ 76 $name = $id; 77 } 78 print html_wikilink(':'.$id,$name); 79 print '</li>'; 80 } 81 print '</ul>'; 82} 83 84/** 85 * Support OpenSearch suggestions 86 * 87 * @link http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0 88 * @author Mike Frysinger <vapier@gentoo.org> 89 */ 90function ajax_suggestions() { 91 global $conf; 92 global $lang; 93 94 $query = cleanID($_POST['q']); 95 if(empty($query)) $query = cleanID($_GET['q']); 96 if(empty($query)) return; 97 98 require_once(DOKU_INC.'inc/html.php'); 99 require_once(DOKU_INC.'inc/fulltext.php'); 100 require_once(DOKU_INC.'inc/JSON.php'); 101 102 $data = array(); 103 $data = ft_pageLookup($query); 104 if(!count($data)) return; 105 106 // limit results to 15 hits 107 $data = array_slice($data, 0, 15); 108 $data = array_map('trim',$data); 109 $data = array_map('noNS',$data); 110 $data = array_unique($data); 111 sort($data); 112 113 /* now construct a json */ 114 $suggestions = array( 115 $query, // the original query 116 $data, // some suggestions 117 array(), // no description 118 array() // no urls 119 ); 120 $json = new JSON(); 121 122 header('Content-Type: application/x-suggestions+json'); 123 print $json->encode($suggestions); 124} 125 126/** 127 * Refresh a page lock and save draft 128 * 129 * Andreas Gohr <andi@splitbrain.org> 130 */ 131function ajax_lock(){ 132 global $conf; 133 global $lang; 134 $id = cleanID($_POST['id']); 135 if(empty($id)) return; 136 137 if(!checklock($id)){ 138 lock($id); 139 echo 1; 140 } 141 142 if($conf['usedraft'] && $_POST['wikitext']){ 143 $client = $_SERVER['REMOTE_USER']; 144 if(!$client) $client = clientIP(true); 145 146 $draft = array('id' => $id, 147 'prefix' => $_POST['prefix'], 148 'text' => $_POST['wikitext'], 149 'suffix' => $_POST['suffix'], 150 'date' => $_POST['date'], 151 'client' => $client, 152 ); 153 $cname = getCacheName($draft['client'].$id,'.draft'); 154 if(io_saveFile($cname,serialize($draft))){ 155 echo $lang['draftdate'].' '.strftime($conf['dformat']); 156 } 157 } 158 159} 160 161/** 162 * Delete a draft 163 * 164 * @author Andreas Gohr <andi@splitbrain.org> 165 */ 166function ajax_draftdel(){ 167 $id = cleanID($_POST['id']); 168 if(empty($id)) return; 169 170 $client = $_SERVER['REMOTE_USER']; 171 if(!$client) $client = clientIP(true); 172 173 $cname = getCacheName($client.$id,'.draft'); 174 @unlink($cname); 175} 176 177/** 178 * Return subnamespaces for the Mediamanager 179 * 180 * @author Andreas Gohr <andi@splitbrain.org> 181 */ 182function ajax_medians(){ 183 global $conf; 184 require_once(DOKU_INC.'inc/search.php'); 185 require_once(DOKU_INC.'inc/media.php'); 186 187 // wanted namespace 188 $ns = cleanID($_POST['ns']); 189 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 190 191 $lvl = count(explode(':',$ns)); 192 193 $data = array(); 194 search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir); 195 foreach($data as $item){ 196 $item['level'] = $lvl+1; 197 echo media_nstree_li($item); 198 echo media_nstree_item($item); 199 echo '</li>'; 200 } 201} 202 203/** 204 * Return list of files for the Mediamanager 205 * 206 * @author Andreas Gohr <andi@splitbrain.org> 207 */ 208function ajax_medialist(){ 209 global $conf; 210 require_once(DOKU_INC.'inc/media.php'); 211 212 media_filelist($_POST['ns']); 213} 214 215/** 216 * Return sub index for index view 217 * 218 * @author Andreas Gohr <andi@splitbrain.org> 219 */ 220function ajax_index(){ 221 global $conf; 222 require_once(DOKU_INC.'inc/search.php'); 223 require_once(DOKU_INC.'inc/html.php'); 224 225 // wanted namespace 226 $ns = cleanID($_POST['idx']); 227 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 228 229 $lvl = count(explode(':',$ns)); 230 231 $data = array(); 232 search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir); 233 foreach($data as $item){ 234 $item['level'] = $lvl+1; 235 echo html_li_index($item); 236 echo '<div class="li">'; 237 echo html_list_index($item); 238 echo '</div>'; 239 echo '</li>'; 240 } 241} 242 243/** 244 * List matching namespaces and pages for the link wizard 245 * 246 * @author Andreas Gohr <gohr@cosmocode.de> 247 */ 248function ajax_linkwiz(){ 249 global $conf; 250 global $lang; 251 require_once(DOKU_INC.'inc/html.php'); 252 253 $q = ltrim($_POST['q'],':'); 254 $id = noNS($q); 255 $ns = getNS($q); 256 257 $ns = cleanID($ns); 258 $id = cleanID($id); 259 260 $nsd = utf8_encodeFN(str_replace(':','/',$ns)); 261 $idd = utf8_encodeFN(str_replace(':','/',$id)); 262 263 $data = array(); 264 if($q && !$ns){ 265 266 // use index to lookup matching pages 267 require_once(DOKU_INC.'inc/fulltext.php'); 268 require_once(DOKU_INC.'inc/parserutils.php'); 269 $pages = array(); 270 $pages = ft_pageLookup($id,false); 271 272 // result contains matches in pages and namespaces 273 // we now extract the matching namespaces to show 274 // them seperately 275 $dirs = array(); 276 $count = count($pages); 277 for($i=0; $i<$count; $i++){ 278 if(strpos(noNS($pages[$i]),$id) === false){ 279 // match was in the namespace 280 $dirs[getNS($pages[$i])] = 1; // assoc array avoids dupes 281 }else{ 282 // it is a matching page, add it to the result 283 $data[] = array( 284 'id' => $pages[$i], 285 'title' => p_get_first_heading($pages[$i],false), 286 'type' => 'f', 287 ); 288 } 289 unset($pages[$i]); 290 } 291 foreach($dirs as $dir => $junk){ 292 $data[] = array( 293 'id' => $dir, 294 'type' => 'd', 295 ); 296 } 297 298 }else{ 299 300 require_once(DOKU_INC.'inc/search.php'); 301 $opts = array( 302 'depth' => 1, 303 'listfiles' => true, 304 'listdirs' => true, 305 'pagesonly' => true, 306 'firsthead' => true, 307 ); 308 if($id) $opts['filematch'] = '^.*\/'.$id; 309 if($id) $opts['dirmatch'] = '^.*\/'.$id; 310 search($data,$conf['datadir'],'search_universal',$opts,$nsd); 311 312 // add back to upper 313 if($ns){ 314 array_unshift($data,array( 315 'id' => getNS($ns), 316 'type' => 'u', 317 )); 318 } 319 } 320 321 // fixme sort results in a useful way ? 322 323 if(!count($data)){ 324 echo $lang['nothingfound']; 325 exit; 326 } 327 328 // output the found data 329 $even = 1; 330 foreach($data as $item){ 331 $even *= -1; //zebra 332 333 if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':'; 334 $link = wl($item['id']); 335 336 echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">'; 337 338 339 if($item['type'] == 'u'){ 340 $name = $lang['upperns']; 341 }else{ 342 $name = htmlspecialchars($item['id']); 343 } 344 345 echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>'; 346 347 if($item['title']){ 348 echo '<span>'.htmlspecialchars($item['title']).'</span>'; 349 } 350 echo '</div>'; 351 } 352 353} 354 355//Setup VIM: ex: et ts=2 enc=utf-8 : 356