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