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 $data = ft_pageLookup($query, true, useHeading('navigation')); 58 59 if(!count($data)) return; 60 61 print '<strong>'.$lang['quickhits'].'</strong>'; 62 print '<ul>'; 63 foreach($data as $id => $title){ 64 if (useHeading('navigation')) { 65 $name = $title; 66 } else { 67 $ns = getNS($id); 68 if($ns){ 69 $name = noNS($id).' ('.$ns.')'; 70 }else{ 71 $name = $id; 72 } 73 } 74 echo '<li>' . html_wikilink(':'.$id,$name) . '</li>'; 75 } 76 print '</ul>'; 77} 78 79/** 80 * Support OpenSearch suggestions 81 * 82 * @link http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0 83 * @author Mike Frysinger <vapier@gentoo.org> 84 */ 85function ajax_suggestions() { 86 global $conf; 87 global $lang; 88 89 $query = cleanID($_POST['q']); 90 if(empty($query)) $query = cleanID($_GET['q']); 91 if(empty($query)) return; 92 93 $data = array(); 94 $data = ft_pageLookup($query); 95 if(!count($data)) return; 96 $data = array_keys($data); 97 98 // limit results to 15 hits 99 $data = array_slice($data, 0, 15); 100 $data = array_map('trim',$data); 101 $data = array_map('noNS',$data); 102 $data = array_unique($data); 103 sort($data); 104 105 /* now construct a json */ 106 $suggestions = array( 107 $query, // the original query 108 $data, // some suggestions 109 array(), // no description 110 array() // no urls 111 ); 112 $json = new JSON(); 113 114 header('Content-Type: application/x-suggestions+json'); 115 print $json->encode($suggestions); 116} 117 118/** 119 * Refresh a page lock and save draft 120 * 121 * Andreas Gohr <andi@splitbrain.org> 122 */ 123function ajax_lock(){ 124 global $conf; 125 global $lang; 126 global $ID; 127 global $INFO; 128 129 $ID = cleanID($_POST['id']); 130 if(empty($ID)) return; 131 132 $INFO = pageinfo(); 133 134 if (!$INFO['writable']) { 135 echo 'Permission denied'; 136 return; 137 } 138 139 if(!checklock($ID)){ 140 lock($ID); 141 echo 1; 142 } 143 144 if($conf['usedraft'] && $_POST['wikitext']){ 145 $client = $_SERVER['REMOTE_USER']; 146 if(!$client) $client = clientIP(true); 147 148 $draft = array('id' => $ID, 149 'prefix' => substr($_POST['prefix'], 0, -1), 150 'text' => $_POST['wikitext'], 151 'suffix' => $_POST['suffix'], 152 'date' => (int) $_POST['date'], 153 'client' => $client, 154 ); 155 $cname = getCacheName($draft['client'].$ID,'.draft'); 156 if(io_saveFile($cname,serialize($draft))){ 157 echo $lang['draftdate'].' '.dformat(); 158 } 159 } 160 161} 162 163/** 164 * Delete a draft 165 * 166 * @author Andreas Gohr <andi@splitbrain.org> 167 */ 168function ajax_draftdel(){ 169 $id = cleanID($_REQUEST['id']); 170 if(empty($id)) return; 171 172 $client = $_SERVER['REMOTE_USER']; 173 if(!$client) $client = clientIP(true); 174 175 $cname = getCacheName($client.$id,'.draft'); 176 @unlink($cname); 177} 178 179/** 180 * Return subnamespaces for the Mediamanager 181 * 182 * @author Andreas Gohr <andi@splitbrain.org> 183 */ 184function ajax_medians(){ 185 global $conf; 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(array_keys($data) as $item){ 196 $data[$item]['level'] = $lvl+1; 197 } 198 echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); 199} 200 201/** 202 * Return list of files for the Mediamanager 203 * 204 * @author Andreas Gohr <andi@splitbrain.org> 205 */ 206function ajax_medialist(){ 207 global $conf; 208 global $NS; 209 210 $NS = $_POST['ns']; 211 if ($_POST['do'] == 'media') { 212 tpl_fileList(); 213 } else { 214 tpl_mediaContent(true); 215 } 216} 217 218/** 219 * Return the content of the right column 220 * (image details) for the Mediamanager 221 * 222 * @author Kate Arzamastseva <pshns@ukr.net> 223 */ 224function ajax_mediadetails(){ 225 global $DEL, $NS, $IMG, $AUTH, $JUMPTO, $REV, $lang, $fullscreen, $conf; 226 $fullscreen = true; 227 require_once(DOKU_INC.'lib/exe/mediamanager.php'); 228 229 if ($_REQUEST['image']) $image = cleanID($_REQUEST['image']); 230 if (isset($IMG)) $image = $IMG; 231 if (isset($JUMPTO)) $image = $JUMPTO; 232 if (isset($REV) && !$JUMPTO) $rev = $REV; 233 234 html_msgarea(); 235 tpl_fileDetails($image, $rev); 236} 237 238/** 239 * Returns image diff representation for mediamanager 240 * @author Kate Arzamastseva <pshns@ukr.net> 241 */ 242function ajax_mediadiff(){ 243 global $NS; 244 245 if ($_REQUEST['image']) $image = cleanID($_REQUEST['image']); 246 $NS = $_POST['ns']; 247 $auth = auth_quickaclcheck("$ns:*"); 248 media_diff($image, $NS, $auth, true); 249} 250 251function ajax_mediaupload(){ 252 global $NS; 253 $NS = $_REQUEST['ns']; 254 $AUTH = auth_quickaclcheck("$NS:*"); 255 if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$NS:xxx", 'media'); } 256 257 if($_FILES['qqfile']['error']){ 258 unset($_FILES['qqfile']); 259 } 260 261 if($_FILES['qqfile']['tmp_name']){ 262 $id = $_REQUEST['file_name']; 263 if (!$id) $id = $_FILES['qqfile']['name']; 264 $file = $_FILES['qqfile']['tmp_name']; 265 list($ext,$mime,$dl) = mimetype($id); 266 267 $res = media_save( 268 array('name' => $file, 269 'mime' => $mime, 270 'ext' => $ext), 271 $NS.':'.$id, 272 $_REQUEST['ow'], 273 $AUTH, 274 'move_uploaded_file' 275 ); 276 if (!is_array($res)) { 277 $result = array('success'=>true); 278 } 279 } 280 281 if (isset($_GET['qqfile'])) { 282 $id = $_GET['qqfile']; 283 list($ext,$mime,$dl) = mimetype($id); 284 $input = fopen("php://input", "r"); 285 $temp = tmpfile(); 286 $realSize = stream_copy_to_stream($input, $temp); 287 fclose($input); 288 if ($realSize != (int)$_SERVER["CONTENT_LENGTH"]) return false; 289 if (!($tmp = io_mktmpdir())) return false; 290 $path = $tmp.'/'.$id; 291 $target = fopen($path, "w"); 292 fseek($temp, 0, SEEK_SET); 293 stream_copy_to_stream($temp, $target); 294 fclose($target); 295 $res = media_save( 296 array('name' => $path, 297 'mime' => $mime, 298 'ext' => $ext), 299 $NS.':'.$id, 300 (($_REQUEST['ow'] == 'true') ? true : false), 301 $AUTH, 302 'copy' 303 ); 304 unlink($path); 305 if ($tmp) dir_delete($tmp); 306 if (!is_array($res)) { 307 $result = array('success'=>true); 308 } 309 } 310 if (!$result) $result = array('error'=> 'Could not save uploaded file.'); 311 echo htmlspecialchars(json_encode($result), ENT_NOQUOTES); 312} 313 314function dir_delete($path) { 315 if (!is_string($path) || $path == "") return false; 316 317 if (is_dir($path) && !is_link($path)) { 318 if (!$dh = @opendir($path)) return false; 319 320 while ($f = readdir($dh)) { 321 if ($f == '..' || $f == '.') continue; 322 dir_delete("$path/$f"); 323 } 324 325 closedir($dh); 326 return @rmdir($path); 327 } else { 328 return @unlink($path); 329 } 330 331 return false; 332} 333 334/** 335 * Return sub index for index view 336 * 337 * @author Andreas Gohr <andi@splitbrain.org> 338 */ 339function ajax_index(){ 340 global $conf; 341 342 // wanted namespace 343 $ns = cleanID($_POST['idx']); 344 $dir = utf8_encodeFN(str_replace(':','/',$ns)); 345 346 $lvl = count(explode(':',$ns)); 347 348 $data = array(); 349 search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir); 350 foreach(array_keys($data) as $item){ 351 $data[$item]['level'] = $lvl+1; 352 } 353 echo html_buildlist($data, 'idx', 'html_list_index', 'html_li_index'); 354} 355 356/** 357 * List matching namespaces and pages for the link wizard 358 * 359 * @author Andreas Gohr <gohr@cosmocode.de> 360 */ 361function ajax_linkwiz(){ 362 global $conf; 363 global $lang; 364 365 $q = ltrim(trim($_POST['q']),':'); 366 $id = noNS($q); 367 $ns = getNS($q); 368 369 $ns = cleanID($ns); 370 $id = cleanID($id); 371 372 $nsd = utf8_encodeFN(str_replace(':','/',$ns)); 373 $idd = utf8_encodeFN(str_replace(':','/',$id)); 374 375 $data = array(); 376 if($q && !$ns){ 377 378 // use index to lookup matching pages 379 $pages = array(); 380 $pages = ft_pageLookup($id,true); 381 382 // result contains matches in pages and namespaces 383 // we now extract the matching namespaces to show 384 // them seperately 385 $dirs = array(); 386 387 foreach($pages as $pid => $title){ 388 if(strpos(noNS($pid),$id) === false){ 389 // match was in the namespace 390 $dirs[getNS($pid)] = 1; // assoc array avoids dupes 391 }else{ 392 // it is a matching page, add it to the result 393 $data[] = array( 394 'id' => $pid, 395 'title' => $title, 396 'type' => 'f', 397 ); 398 } 399 unset($pages[$pid]); 400 } 401 foreach($dirs as $dir => $junk){ 402 $data[] = array( 403 'id' => $dir, 404 'type' => 'd', 405 ); 406 } 407 408 }else{ 409 410 $opts = array( 411 'depth' => 1, 412 'listfiles' => true, 413 'listdirs' => true, 414 'pagesonly' => true, 415 'firsthead' => true, 416 'sneakyacl' => $conf['sneaky_index'], 417 ); 418 if($id) $opts['filematch'] = '^.*\/'.$id; 419 if($id) $opts['dirmatch'] = '^.*\/'.$id; 420 search($data,$conf['datadir'],'search_universal',$opts,$nsd); 421 422 // add back to upper 423 if($ns){ 424 array_unshift($data,array( 425 'id' => getNS($ns), 426 'type' => 'u', 427 )); 428 } 429 } 430 431 // fixme sort results in a useful way ? 432 433 if(!count($data)){ 434 echo $lang['nothingfound']; 435 exit; 436 } 437 438 // output the found data 439 $even = 1; 440 foreach($data as $item){ 441 $even *= -1; //zebra 442 443 if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':'; 444 $link = wl($item['id']); 445 446 echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">'; 447 448 if($item['type'] == 'u'){ 449 $name = $lang['upperns']; 450 }else{ 451 $name = htmlspecialchars($item['id']); 452 } 453 454 echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>'; 455 456 if($item['title']){ 457 echo '<span>'.htmlspecialchars($item['title']).'</span>'; 458 } 459 echo '</div>'; 460 } 461 462} 463 464//Setup VIM: ex: et ts=2 : 465