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