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 9if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../'); 10require_once(DOKU_INC.'inc/init.php'); 11//close session 12session_write_close(); 13 14header('Content-Type: text/html; charset=utf-8'); 15 16//call the requested function 17if($INPUT->has('call')) { 18 $call = $INPUT->filter('utf8_stripspecials')->str('call'); 19} else { 20 exit; 21} 22$callfn = 'ajax_'.$call; 23 24if(function_exists($callfn)){ 25 $callfn(); 26}else{ 27 $evt = new Doku_Event('AJAX_CALL_UNKNOWN', $call); 28 if ($evt->advise_before()) { 29 print "AJAX call '".htmlspecialchars($call)."' unknown!\n"; 30 exit; 31 } 32 $evt->advise_after(); 33 unset($evt); 34} 35 36/** 37 * Searches for matching pagenames 38 * 39 * @author Andreas Gohr <andi@splitbrain.org> 40 */ 41function ajax_qsearch(){ 42 global $lang; 43 global $INPUT; 44 45 $maxnumbersuggestions = 50; 46 47 $query = $INPUT->post->str('q'); 48 if(empty($query)) $query = $INPUT->get->str('q'); 49 if(empty($query)) return; 50 51 $query = urldecode($query); 52 53 $data = ft_pageLookup($query, true, useHeading('navigation')); 54 55 if(!count($data)) return; 56 57 print '<strong>'.$lang['quickhits'].'</strong>'; 58 print '<ul>'; 59 $counter = 0; 60 foreach($data as $id => $title){ 61 if (useHeading('navigation')) { 62 $name = $title; 63 } else { 64 $ns = getNS($id); 65 if($ns){ 66 $name = noNS($id).' ('.$ns.')'; 67 }else{ 68 $name = $id; 69 } 70 } 71 echo '<li>' . html_wikilink(':'.$id,$name) . '</li>'; 72 73 $counter ++; 74 if($counter > $maxnumbersuggestions) { 75 echo '<li>...</li>'; 76 break; 77 } 78 } 79 print '</ul>'; 80} 81 82/** 83 * Support OpenSearch suggestions 84 * 85 * @link http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0 86 * @author Mike Frysinger <vapier@gentoo.org> 87 */ 88function ajax_suggestions() { 89 global $INPUT; 90 91 $query = cleanID($INPUT->post->str('q')); 92 if(empty($query)) $query = cleanID($INPUT->get->str('q')); 93 if(empty($query)) return; 94 95 $data = ft_pageLookup($query); 96 if(!count($data)) return; 97 $data = array_keys($data); 98 99 // limit results to 15 hits 100 $data = array_slice($data, 0, 15); 101 $data = array_map('trim',$data); 102 $data = array_map('noNS',$data); 103 $data = array_unique($data); 104 sort($data); 105 106 /* now construct a json */ 107 $suggestions = array( 108 $query, // the original query 109 $data, // some suggestions 110 array(), // no description 111 array() // no urls 112 ); 113 $json = new JSON(); 114 115 header('Content-Type: application/x-suggestions+json'); 116 print $json->encode($suggestions); 117} 118 119/** 120 * Refresh a page lock and save draft 121 * 122 * Andreas Gohr <andi@splitbrain.org> 123 */ 124function ajax_lock(){ 125 global $conf; 126 global $lang; 127 global $ID; 128 global $INFO; 129 global $INPUT; 130 131 $ID = cleanID($INPUT->post->str('id')); 132 if(empty($ID)) return; 133 134 $INFO = pageinfo(); 135 136 if (!$INFO['writable']) { 137 echo 'Permission denied'; 138 return; 139 } 140 141 if(!checklock($ID)){ 142 lock($ID); 143 echo 1; 144 } 145 146 if($conf['usedraft'] && $INPUT->post->str('wikitext')){ 147 $client = $_SERVER['REMOTE_USER']; 148 if(!$client) $client = clientIP(true); 149 150 $draft = array('id' => $ID, 151 'prefix' => substr($INPUT->post->str('prefix'), 0, -1), 152 'text' => $INPUT->post->str('wikitext'), 153 'suffix' => $INPUT->post->str('suffix'), 154 'date' => $INPUT->post->int('date'), 155 'client' => $client, 156 ); 157 $cname = getCacheName($draft['client'].$ID,'.draft'); 158 if(io_saveFile($cname,serialize($draft))){ 159 echo $lang['draftdate'].' '.dformat(); 160 } 161 } 162 163} 164 165/** 166 * Delete a draft 167 * 168 * @author Andreas Gohr <andi@splitbrain.org> 169 */ 170function ajax_draftdel(){ 171 global $INPUT; 172 $id = cleanID($INPUT->str('id')); 173 if(empty($id)) return; 174 175 $client = $_SERVER['REMOTE_USER']; 176 if(!$client) $client = clientIP(true); 177 178 $cname = getCacheName($client.$id,'.draft'); 179 @unlink($cname); 180} 181 182/** 183 * Return subnamespaces for the Mediamanager 184 * 185 * @author Andreas Gohr <andi@splitbrain.org> 186 */ 187function ajax_medians(){ 188 global $conf; 189 global $INPUT; 190 191 // wanted namespace 192 $ns = cleanID($INPUT->post->str('ns')); 193 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 194 195 $lvl = count(explode(':',$ns)); 196 197 $data = array(); 198 search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir); 199 foreach(array_keys($data) as $item){ 200 $data[$item]['level'] = $lvl+1; 201 } 202 echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 203} 204 205/** 206 * Return list of files for the Mediamanager 207 * 208 * @author Andreas Gohr <andi@splitbrain.org> 209 */ 210function ajax_medialist(){ 211 global $NS; 212 global $INPUT; 213 214 $NS = cleanID($INPUT->post->str('ns')); 215 $sort = $INPUT->post->bool('recent') ? 'date' : 'natural'; 216 if ($INPUT->post->str('do') == 'media') { 217 tpl_mediaFileList(); 218 } else { 219 tpl_mediaContent(true, $sort); 220 } 221} 222 223/** 224 * Return the content of the right column 225 * (image details) for the Mediamanager 226 * 227 * @author Kate Arzamastseva <pshns@ukr.net> 228 */ 229function ajax_mediadetails(){ 230 global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT; 231 $fullscreen = true; 232 require_once(DOKU_INC.'lib/exe/mediamanager.php'); 233 234 $image = ''; 235 if ($INPUT->has('image')) $image = cleanID($INPUT->str('image')); 236 if (isset($IMG)) $image = $IMG; 237 if (isset($JUMPTO)) $image = $JUMPTO; 238 $rev = false; 239 if (isset($REV) && !$JUMPTO) $rev = $REV; 240 241 html_msgarea(); 242 tpl_mediaFileDetails($image, $rev); 243} 244 245/** 246 * Returns image diff representation for mediamanager 247 * @author Kate Arzamastseva <pshns@ukr.net> 248 */ 249function ajax_mediadiff(){ 250 global $NS; 251 global $INPUT; 252 253 $image = ''; 254 if ($INPUT->has('image')) $image = cleanID($INPUT->str('image')); 255 $NS = getNS($image); 256 $auth = auth_quickaclcheck("$NS:*"); 257 media_diff($image, $NS, $auth, true); 258} 259 260function ajax_mediaupload(){ 261 global $NS, $MSG, $INPUT; 262 263 $id = ''; 264 if ($_FILES['qqfile']['tmp_name']) { 265 $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']); 266 } elseif ($INPUT->get->has('qqfile')) { 267 $id = $INPUT->get->str('qqfile'); 268 } 269 270 $id = cleanID($id); 271 272 $NS = $INPUT->str('ns'); 273 $ns = $NS.':'.getNS($id); 274 275 $AUTH = auth_quickaclcheck("$ns:*"); 276 if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$ns:xxx", 'media'); } 277 278 if ($_FILES['qqfile']['error']) unset($_FILES['qqfile']); 279 280 $res = false; 281 if ($_FILES['qqfile']['tmp_name']) $res = media_upload($NS, $AUTH, $_FILES['qqfile']); 282 if ($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH); 283 284 if($res) { 285 $result = array( 286 'success' => true, 287 'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'), 288 'id' => $NS . ':' . $id, 289 'ns' => $NS 290 ); 291 } else { 292 $error = ''; 293 if(isset($MSG)) { 294 foreach($MSG as $msg) { 295 $error .= $msg['msg']; 296 } 297 } 298 $result = array( 299 'error' => $error, 300 'ns' => $NS 301 ); 302 } 303 $json = new JSON; 304 header('Content-Type: application/json'); 305 echo $json->encode($result); 306} 307 308/** 309 * Return sub index for index view 310 * 311 * @author Andreas Gohr <andi@splitbrain.org> 312 */ 313function ajax_index(){ 314 global $conf; 315 global $INPUT; 316 317 // wanted namespace 318 $ns = cleanID($INPUT->post->str('idx')); 319 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 320 321 $lvl = count(explode(':',$ns)); 322 323 $data = array(); 324 search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir); 325 foreach(array_keys($data) as $item){ 326 $data[$item]['level'] = $lvl+1; 327 } 328 echo html_buildlist($data, 'idx', 'html_list_index', 'html_li_index'); 329} 330 331/** 332 * List matching namespaces and pages for the link wizard 333 * 334 * @author Andreas Gohr <gohr@cosmocode.de> 335 */ 336function ajax_linkwiz(){ 337 global $conf; 338 global $lang; 339 global $INPUT; 340 341 $q = ltrim(trim($INPUT->post->str('q')),':'); 342 $id = noNS($q); 343 $ns = getNS($q); 344 345 $ns = cleanID($ns); 346 $id = cleanID($id); 347 348 $nsd = utf8_encodeFN(str_replace(':','/',$ns)); 349 350 $data = array(); 351 if($q && !$ns){ 352 353 // use index to lookup matching pages 354 $pages = ft_pageLookup($id,true); 355 356 // result contains matches in pages and namespaces 357 // we now extract the matching namespaces to show 358 // them seperately 359 $dirs = array(); 360 361 foreach($pages as $pid => $title){ 362 if(strpos(noNS($pid),$id) === false){ 363 // match was in the namespace 364 $dirs[getNS($pid)] = 1; // assoc array avoids dupes 365 }else{ 366 // it is a matching page, add it to the result 367 $data[] = array( 368 'id' => $pid, 369 'title' => $title, 370 'type' => 'f', 371 ); 372 } 373 unset($pages[$pid]); 374 } 375 foreach($dirs as $dir => $junk){ 376 $data[] = array( 377 'id' => $dir, 378 'type' => 'd', 379 ); 380 } 381 382 }else{ 383 384 $opts = array( 385 'depth' => 1, 386 'listfiles' => true, 387 'listdirs' => true, 388 'pagesonly' => true, 389 'firsthead' => true, 390 'sneakyacl' => $conf['sneaky_index'], 391 ); 392 if($id) $opts['filematch'] = '^.*\/'.$id; 393 if($id) $opts['dirmatch'] = '^.*\/'.$id; 394 search($data,$conf['datadir'],'search_universal',$opts,$nsd); 395 396 // add back to upper 397 if($ns){ 398 array_unshift($data,array( 399 'id' => getNS($ns), 400 'type' => 'u', 401 )); 402 } 403 } 404 405 // fixme sort results in a useful way ? 406 407 if(!count($data)){ 408 echo $lang['nothingfound']; 409 exit; 410 } 411 412 // output the found data 413 $even = 1; 414 foreach($data as $item){ 415 $even *= -1; //zebra 416 417 if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':'; 418 $link = wl($item['id']); 419 420 echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">'; 421 422 if($item['type'] == 'u'){ 423 $name = $lang['upperns']; 424 }else{ 425 $name = htmlspecialchars($item['id']); 426 } 427 428 echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>'; 429 430 if(!blank($item['title'])){ 431 echo '<span>'.htmlspecialchars($item['title']).'</span>'; 432 } 433 echo '</div>'; 434 } 435 436} 437 438//Setup VIM: ex: et ts=2 : 439