[25027] | 1 | <?php
|
---|
| 2 | /**
|
---|
| 3 | * DokuWiki AJAX call handler
|
---|
| 4 | *
|
---|
| 5 | * @license GPL 2 (http://www.gnu.org/licenses/gpl.html)
|
---|
| 6 | * @author Andreas Gohr <[email protected]>
|
---|
| 7 | */
|
---|
| 8 |
|
---|
| 9 | //fix for Opera XMLHttpRequests
|
---|
| 10 | if(!count($_POST) && !empty($HTTP_RAW_POST_DATA)){
|
---|
| 11 | parse_str($HTTP_RAW_POST_DATA, $_POST);
|
---|
| 12 | }
|
---|
| 13 |
|
---|
| 14 | if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
|
---|
| 15 | require_once(DOKU_INC.'inc/init.php');
|
---|
| 16 | //close session
|
---|
| 17 | session_write_close();
|
---|
| 18 |
|
---|
| 19 | header('Content-Type: text/html; charset=utf-8');
|
---|
| 20 |
|
---|
| 21 |
|
---|
| 22 | //call the requested function
|
---|
| 23 | if(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 |
|
---|
| 32 | if(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 <[email protected]>
|
---|
| 48 | */
|
---|
| 49 | function 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 <[email protected]>
|
---|
| 84 | */
|
---|
| 85 | function 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 <[email protected]>
|
---|
| 122 | */
|
---|
| 123 | function 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 <[email protected]>
|
---|
| 167 | */
|
---|
| 168 | function 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 <[email protected]>
|
---|
| 183 | */
|
---|
| 184 | function 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($data as $item){
|
---|
| 196 | $item['level'] = $lvl+1;
|
---|
| 197 | echo media_nstree_li($item);
|
---|
| 198 | echo media_nstree_item($item);
|
---|
| 199 | echo '</li>';
|
---|
| 200 | }
|
---|
| 201 | }
|
---|
| 202 |
|
---|
| 203 | /**
|
---|
| 204 | * Return list of files for the Mediamanager
|
---|
| 205 | *
|
---|
| 206 | * @author Andreas Gohr <[email protected]>
|
---|
| 207 | */
|
---|
| 208 | function ajax_medialist(){
|
---|
| 209 | global $conf;
|
---|
| 210 | global $NS;
|
---|
| 211 |
|
---|
| 212 | $NS = $_POST['ns'];
|
---|
| 213 | tpl_mediaContent(true);
|
---|
| 214 | }
|
---|
| 215 |
|
---|
| 216 | /**
|
---|
| 217 | * Return sub index for index view
|
---|
| 218 | *
|
---|
| 219 | * @author Andreas Gohr <[email protected]>
|
---|
| 220 | */
|
---|
| 221 | function ajax_index(){
|
---|
| 222 | global $conf;
|
---|
| 223 |
|
---|
| 224 | // wanted namespace
|
---|
| 225 | $ns = cleanID($_POST['idx']);
|
---|
| 226 | $dir = utf8_encodeFN(str_replace(':','/',$ns));
|
---|
| 227 |
|
---|
| 228 | $lvl = count(explode(':',$ns));
|
---|
| 229 |
|
---|
| 230 | $data = array();
|
---|
| 231 | search($data,$conf['datadir'],'search_index',array('ns' => $ns),$dir);
|
---|
| 232 | foreach($data as $item){
|
---|
| 233 | $item['level'] = $lvl+1;
|
---|
| 234 | echo html_li_index($item);
|
---|
| 235 | echo '<div class="li">';
|
---|
| 236 | echo html_list_index($item);
|
---|
| 237 | echo '</div>';
|
---|
| 238 | echo '</li>';
|
---|
| 239 | }
|
---|
| 240 | }
|
---|
| 241 |
|
---|
| 242 | /**
|
---|
| 243 | * List matching namespaces and pages for the link wizard
|
---|
| 244 | *
|
---|
| 245 | * @author Andreas Gohr <[email protected]>
|
---|
| 246 | */
|
---|
| 247 | function ajax_linkwiz(){
|
---|
| 248 | global $conf;
|
---|
| 249 | global $lang;
|
---|
| 250 |
|
---|
| 251 | $q = ltrim(trim($_POST['q']),':');
|
---|
| 252 | $id = noNS($q);
|
---|
| 253 | $ns = getNS($q);
|
---|
| 254 |
|
---|
| 255 | $ns = cleanID($ns);
|
---|
| 256 | $id = cleanID($id);
|
---|
| 257 |
|
---|
| 258 | $nsd = utf8_encodeFN(str_replace(':','/',$ns));
|
---|
| 259 | $idd = utf8_encodeFN(str_replace(':','/',$id));
|
---|
| 260 |
|
---|
| 261 | $data = array();
|
---|
| 262 | if($q && !$ns){
|
---|
| 263 |
|
---|
| 264 | // use index to lookup matching pages
|
---|
| 265 | $pages = array();
|
---|
| 266 | $pages = ft_pageLookup($id,true);
|
---|
| 267 |
|
---|
| 268 | // result contains matches in pages and namespaces
|
---|
| 269 | // we now extract the matching namespaces to show
|
---|
| 270 | // them seperately
|
---|
| 271 | $dirs = array();
|
---|
| 272 |
|
---|
| 273 | foreach($pages as $pid => $title){
|
---|
| 274 | if(strpos(noNS($pid),$id) === false){
|
---|
| 275 | // match was in the namespace
|
---|
| 276 | $dirs[getNS($pid)] = 1; // assoc array avoids dupes
|
---|
| 277 | }else{
|
---|
| 278 | // it is a matching page, add it to the result
|
---|
| 279 | $data[] = array(
|
---|
| 280 | 'id' => $pid,
|
---|
| 281 | 'title' => $title,
|
---|
| 282 | 'type' => 'f',
|
---|
| 283 | );
|
---|
| 284 | }
|
---|
| 285 | unset($pages[$pid]);
|
---|
| 286 | }
|
---|
| 287 | foreach($dirs as $dir => $junk){
|
---|
| 288 | $data[] = array(
|
---|
| 289 | 'id' => $dir,
|
---|
| 290 | 'type' => 'd',
|
---|
| 291 | );
|
---|
| 292 | }
|
---|
| 293 |
|
---|
| 294 | }else{
|
---|
| 295 |
|
---|
| 296 | $opts = array(
|
---|
| 297 | 'depth' => 1,
|
---|
| 298 | 'listfiles' => true,
|
---|
| 299 | 'listdirs' => true,
|
---|
| 300 | 'pagesonly' => true,
|
---|
| 301 | 'firsthead' => true,
|
---|
| 302 | 'sneakyacl' => $conf['sneaky_index'],
|
---|
| 303 | );
|
---|
| 304 | if($id) $opts['filematch'] = '^.*\/'.$id;
|
---|
| 305 | if($id) $opts['dirmatch'] = '^.*\/'.$id;
|
---|
| 306 | search($data,$conf['datadir'],'search_universal',$opts,$nsd);
|
---|
| 307 |
|
---|
| 308 | // add back to upper
|
---|
| 309 | if($ns){
|
---|
| 310 | array_unshift($data,array(
|
---|
| 311 | 'id' => getNS($ns),
|
---|
| 312 | 'type' => 'u',
|
---|
| 313 | ));
|
---|
| 314 | }
|
---|
| 315 | }
|
---|
| 316 |
|
---|
| 317 | // fixme sort results in a useful way ?
|
---|
| 318 |
|
---|
| 319 | if(!count($data)){
|
---|
| 320 | echo $lang['nothingfound'];
|
---|
| 321 | exit;
|
---|
| 322 | }
|
---|
| 323 |
|
---|
| 324 | // output the found data
|
---|
| 325 | $even = 1;
|
---|
| 326 | foreach($data as $item){
|
---|
| 327 | $even *= -1; //zebra
|
---|
| 328 |
|
---|
| 329 | if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':';
|
---|
| 330 | $link = wl($item['id']);
|
---|
| 331 |
|
---|
| 332 | echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">';
|
---|
| 333 |
|
---|
| 334 | if($item['type'] == 'u'){
|
---|
| 335 | $name = $lang['upperns'];
|
---|
| 336 | }else{
|
---|
| 337 | $name = htmlspecialchars($item['id']);
|
---|
| 338 | }
|
---|
| 339 |
|
---|
| 340 | echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>';
|
---|
| 341 |
|
---|
| 342 | if($item['title']){
|
---|
| 343 | echo '<span>'.htmlspecialchars($item['title']).'</span>';
|
---|
| 344 | }
|
---|
| 345 | echo '</div>';
|
---|
| 346 | }
|
---|
| 347 |
|
---|
| 348 | }
|
---|
| 349 |
|
---|
| 350 | //Setup VIM: ex: et ts=2 :
|
---|