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 '".hsc($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 $lang; 126 global $ID; 127 global $INFO; 128 global $INPUT; 129 130 $ID = cleanID($INPUT->post->str('id')); 131 if($ID === '') return; 132 $INFO = pageinfo(); 133 if(isset($INFO['draft'])) unset($INFO['draft']); 134 135 // the preview action does locking and draft saving for us 136 try { 137 $preview = new \dokuwiki\Action\Preview(); 138 $preview->checkPermissions(); 139 $preview->preProcess(); 140 } catch(\dokuwiki\Action\Exception\ActionException $e) { 141 echo $e->getMessage(); 142 return; 143 } 144 145 if(!checklock($ID)){ 146 lock($ID); 147 echo 1; 148 } 149 150 if(isset($INFO['draft'])) { 151 echo $lang['draftdate'].' '.dformat(); 152 } 153} 154 155/** 156 * Delete a draft 157 * 158 * @author Andreas Gohr <andi@splitbrain.org> 159 */ 160function ajax_draftdel(){ 161 global $INPUT; 162 $id = cleanID($INPUT->str('id')); 163 if(empty($id)) return; 164 165 $client = $_SERVER['REMOTE_USER']; 166 if(!$client) $client = clientIP(true); 167 168 $cname = getCacheName($client.$id,'.draft'); 169 @unlink($cname); 170} 171 172/** 173 * Return subnamespaces for the Mediamanager 174 * 175 * @author Andreas Gohr <andi@splitbrain.org> 176 */ 177function ajax_medians(){ 178 global $conf; 179 global $INPUT; 180 181 // wanted namespace 182 $ns = cleanID($INPUT->post->str('ns')); 183 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 184 185 $lvl = count(explode(':',$ns)); 186 187 $data = array(); 188 search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir); 189 foreach(array_keys($data) as $item){ 190 $data[$item]['level'] = $lvl+1; 191 } 192 echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 193} 194 195/** 196 * Return list of files for the Mediamanager 197 * 198 * @author Andreas Gohr <andi@splitbrain.org> 199 */ 200function ajax_medialist(){ 201 global $NS; 202 global $INPUT; 203 204 $NS = cleanID($INPUT->post->str('ns')); 205 $sort = $INPUT->post->bool('recent') ? 'date' : 'natural'; 206 if ($INPUT->post->str('do') == 'media') { 207 tpl_mediaFileList(); 208 } else { 209 tpl_mediaContent(true, $sort); 210 } 211} 212 213/** 214 * Return the content of the right column 215 * (image details) for the Mediamanager 216 * 217 * @author Kate Arzamastseva <pshns@ukr.net> 218 */ 219function ajax_mediadetails(){ 220 global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT; 221 $fullscreen = true; 222 require_once(DOKU_INC.'lib/exe/mediamanager.php'); 223 224 $image = ''; 225 if ($INPUT->has('image')) $image = cleanID($INPUT->str('image')); 226 if (isset($IMG)) $image = $IMG; 227 if (isset($JUMPTO)) $image = $JUMPTO; 228 $rev = false; 229 if (isset($REV) && !$JUMPTO) $rev = $REV; 230 231 html_msgarea(); 232 tpl_mediaFileDetails($image, $rev); 233} 234 235/** 236 * Returns image diff representation for mediamanager 237 * @author Kate Arzamastseva <pshns@ukr.net> 238 */ 239function ajax_mediadiff(){ 240 global $NS; 241 global $INPUT; 242 243 $image = ''; 244 if ($INPUT->has('image')) $image = cleanID($INPUT->str('image')); 245 $NS = getNS($image); 246 $auth = auth_quickaclcheck("$NS:*"); 247 media_diff($image, $NS, $auth, true); 248} 249 250function ajax_mediaupload(){ 251 global $NS, $MSG, $INPUT; 252 253 $id = ''; 254 if ($_FILES['qqfile']['tmp_name']) { 255 $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']); 256 } elseif ($INPUT->get->has('qqfile')) { 257 $id = $INPUT->get->str('qqfile'); 258 } 259 260 $id = cleanID($id); 261 262 $NS = $INPUT->str('ns'); 263 $ns = $NS.':'.getNS($id); 264 265 $AUTH = auth_quickaclcheck("$ns:*"); 266 if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$ns:xxx", 'media'); } 267 268 if ($_FILES['qqfile']['error']) unset($_FILES['qqfile']); 269 270 $res = false; 271 if ($_FILES['qqfile']['tmp_name']) $res = media_upload($NS, $AUTH, $_FILES['qqfile']); 272 if ($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH); 273 274 if($res) { 275 $result = array( 276 'success' => true, 277 'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'), 278 'id' => $NS . ':' . $id, 279 'ns' => $NS 280 ); 281 } else { 282 $error = ''; 283 if(isset($MSG)) { 284 foreach($MSG as $msg) { 285 $error .= $msg['msg']; 286 } 287 } 288 $result = array( 289 'error' => $error, 290 'ns' => $NS 291 ); 292 } 293 $json = new JSON; 294 header('Content-Type: application/json'); 295 echo $json->encode($result); 296} 297 298/** 299 * Return sub index for index view 300 * 301 * @author Andreas Gohr <andi@splitbrain.org> 302 */ 303function ajax_index(){ 304 global $conf; 305 global $INPUT; 306 307 // wanted namespace 308 $ns = cleanID($INPUT->post->str('idx')); 309 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 310 311 $lvl = count(explode(':',$ns)); 312 313 $data = array(); 314 search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir); 315 foreach(array_keys($data) as $item){ 316 $data[$item]['level'] = $lvl+1; 317 } 318 echo html_buildlist($data, 'idx', 'html_list_index', 'html_li_index'); 319} 320 321/** 322 * List matching namespaces and pages for the link wizard 323 * 324 * @author Andreas Gohr <gohr@cosmocode.de> 325 */ 326function ajax_linkwiz(){ 327 global $conf; 328 global $lang; 329 global $INPUT; 330 331 $q = ltrim(trim($INPUT->post->str('q')),':'); 332 $id = noNS($q); 333 $ns = getNS($q); 334 335 $ns = cleanID($ns); 336 $id = cleanID($id); 337 338 $nsd = utf8_encodeFN(str_replace(':','/',$ns)); 339 340 $data = array(); 341 if($q && !$ns){ 342 343 // use index to lookup matching pages 344 $pages = ft_pageLookup($id,true); 345 346 // result contains matches in pages and namespaces 347 // we now extract the matching namespaces to show 348 // them seperately 349 $dirs = array(); 350 351 foreach($pages as $pid => $title){ 352 if(strpos(noNS($pid),$id) === false){ 353 // match was in the namespace 354 $dirs[getNS($pid)] = 1; // assoc array avoids dupes 355 }else{ 356 // it is a matching page, add it to the result 357 $data[] = array( 358 'id' => $pid, 359 'title' => $title, 360 'type' => 'f', 361 ); 362 } 363 unset($pages[$pid]); 364 } 365 foreach($dirs as $dir => $junk){ 366 $data[] = array( 367 'id' => $dir, 368 'type' => 'd', 369 ); 370 } 371 372 }else{ 373 374 $opts = array( 375 'depth' => 1, 376 'listfiles' => true, 377 'listdirs' => true, 378 'pagesonly' => true, 379 'firsthead' => true, 380 'sneakyacl' => $conf['sneaky_index'], 381 ); 382 if($id) $opts['filematch'] = '^.*\/'.$id; 383 if($id) $opts['dirmatch'] = '^.*\/'.$id; 384 search($data,$conf['datadir'],'search_universal',$opts,$nsd); 385 386 // add back to upper 387 if($ns){ 388 array_unshift($data,array( 389 'id' => getNS($ns), 390 'type' => 'u', 391 )); 392 } 393 } 394 395 // fixme sort results in a useful way ? 396 397 if(!count($data)){ 398 echo $lang['nothingfound']; 399 exit; 400 } 401 402 // output the found data 403 $even = 1; 404 foreach($data as $item){ 405 $even *= -1; //zebra 406 407 if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':'; 408 $link = wl($item['id']); 409 410 echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">'; 411 412 if($item['type'] == 'u'){ 413 $name = $lang['upperns']; 414 }else{ 415 $name = hsc($item['id']); 416 } 417 418 echo '<a href="'.$link.'" title="'.hsc($item['id']).'" class="wikilink1">'.$name.'</a>'; 419 420 if(!blank($item['title'])){ 421 echo '<span>'.hsc($item['title']).'</span>'; 422 } 423 echo '</div>'; 424 } 425 426} 427 428//Setup VIM: ex: et ts=2 : 429