Completed
Push — sidebaracl ( 7a112d...7c3e4a )
by Andreas
04:38
created

lib/exe/ajax.php (1 issue)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

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
if(!defined('DOKU_INC')) define('DOKU_INC',dirname(__FILE__).'/../../');
10
require_once(DOKU_INC.'inc/init.php');
11
//close session
12
session_write_close();
13
14
header('Content-Type: text/html; charset=utf-8');
15
16
//call the requested function
17
if($INPUT->post->has('call')){
18
    $call = $INPUT->post->str('call');
19
}else if($INPUT->get->has('call')){
20
    $call = $INPUT->get->str('call');
21
}else{
22
    exit;
23
}
24
$callfn = 'ajax_'.$call;
25
26
if(function_exists($callfn)){
27
    $callfn();
28
}else{
29
    $evt = new Doku_Event('AJAX_CALL_UNKNOWN', $call);
30
    if ($evt->advise_before()) {
31
        print "AJAX call '".htmlspecialchars($call)."' unknown!\n";
32
        exit;
33
    }
34
    $evt->advise_after();
35
    unset($evt);
36
}
37
38
/**
39
 * Searches for matching pagenames
40
 *
41
 * @author Andreas Gohr <[email protected]>
42
 */
43
function ajax_qsearch(){
44
    global $lang;
45
    global $INPUT;
46
47
    $maxnumbersuggestions = 50;
48
49
    $query = $INPUT->post->str('q');
50
    if(empty($query)) $query = $INPUT->get->str('q');
51
    if(empty($query)) return;
52
53
    $query = urldecode($query);
54
55
    $data = ft_pageLookup($query, true, useHeading('navigation'));
56
57
    if(!count($data)) return;
58
59
    print '<strong>'.$lang['quickhits'].'</strong>';
60
    print '<ul>';
61
    $counter = 0;
62
    foreach($data as $id => $title){
63
        if (useHeading('navigation')) {
64
            $name = $title;
65
        } else {
66
            $ns = getNS($id);
67
            if($ns){
68
                $name = noNS($id).' ('.$ns.')';
69
            }else{
70
                $name = $id;
71
            }
72
        }
73
        echo '<li>' . html_wikilink(':'.$id,$name) . '</li>';
74
75
        $counter ++;
76
        if($counter > $maxnumbersuggestions) {
77
            echo '<li>...</li>';
78
            break;
79
        }
80
    }
81
    print '</ul>';
82
}
83
84
/**
85
 * Support OpenSearch suggestions
86
 *
87
 * @link   http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0
88
 * @author Mike Frysinger <[email protected]>
89
 */
90
function ajax_suggestions() {
91
    global $INPUT;
92
93
    $query = cleanID($INPUT->post->str('q'));
94
    if(empty($query)) $query = cleanID($INPUT->get->str('q'));
95
    if(empty($query)) return;
96
97
    $data = ft_pageLookup($query);
98
    if(!count($data)) return;
99
    $data = array_keys($data);
100
101
    // limit results to 15 hits
102
    $data = array_slice($data, 0, 15);
103
    $data = array_map('trim',$data);
104
    $data = array_map('noNS',$data);
105
    $data = array_unique($data);
106
    sort($data);
107
108
    /* now construct a json */
109
    $suggestions = array(
110
                        $query,  // the original query
111
                        $data,   // some suggestions
112
                        array(), // no description
113
                        array()  // no urls
114
                   );
115
    $json = new JSON();
116
117
    header('Content-Type: application/x-suggestions+json');
118
    print $json->encode($suggestions);
119
}
120
121
/**
122
 * Refresh a page lock and save draft
123
 *
124
 * Andreas Gohr <[email protected]>
125
 */
126
function ajax_lock(){
127
    global $conf;
128
    global $lang;
129
    global $ID;
130
    global $INFO;
131
    global $INPUT;
132
133
    $ID = cleanID($INPUT->post->str('id'));
134
    if(empty($ID)) return;
135
136
    $INFO = pageinfo();
137
138
    if (!$INFO['writable']) {
139
        echo 'Permission denied';
140
        return;
141
    }
142
143
    if(!checklock($ID)){
144
        lock($ID);
145
        echo 1;
146
    }
147
148
    if($conf['usedraft'] && $INPUT->post->str('wikitext')){
149
        $client = $_SERVER['REMOTE_USER'];
150
        if(!$client) $client = clientIP(true);
151
152
        $draft = array('id'     => $ID,
153
                'prefix' => substr($INPUT->post->str('prefix'), 0, -1),
154
                'text'   => $INPUT->post->str('wikitext'),
155
                'suffix' => $INPUT->post->str('suffix'),
156
                'date'   => $INPUT->post->int('date'),
157
                'client' => $client,
158
                );
159
        $cname = getCacheName($draft['client'].$ID,'.draft');
160
        if(io_saveFile($cname,serialize($draft))){
161
            echo $lang['draftdate'].' '.dformat();
162
        }
163
    }
164
165
}
166
167
/**
168
 * Delete a draft
169
 *
170
 * @author Andreas Gohr <[email protected]>
171
 */
172
function ajax_draftdel(){
173
    global $INPUT;
174
    $id = cleanID($INPUT->str('id'));
175
    if(empty($id)) return;
176
177
    $client = $_SERVER['REMOTE_USER'];
178
    if(!$client) $client = clientIP(true);
179
180
    $cname = getCacheName($client.$id,'.draft');
181
    @unlink($cname);
182
}
183
184
/**
185
 * Return subnamespaces for the Mediamanager
186
 *
187
 * @author Andreas Gohr <[email protected]>
188
 */
189
function ajax_medians(){
190
    global $conf;
191
    global $INPUT;
192
193
    // wanted namespace
194
    $ns  = cleanID($INPUT->post->str('ns'));
195
    $dir  = utf8_encodeFN(str_replace(':','/',$ns));
196
197
    $lvl = count(explode(':',$ns));
198
199
    $data = array();
200
    search($data,$conf['mediadir'],'search_index',array('nofiles' => true),$dir);
201
    foreach(array_keys($data) as $item){
202
        $data[$item]['level'] = $lvl+1;
203
    }
204
    echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li');
205
}
206
207
/**
208
 * Return list of files for the Mediamanager
209
 *
210
 * @author Andreas Gohr <[email protected]>
211
 */
212
function ajax_medialist(){
213
    global $NS;
214
    global $INPUT;
215
216
    $NS = cleanID($INPUT->post->str('ns'));
217
    $sort = $INPUT->post->bool('recent') ? 'date' : 'natural';
218
    if ($INPUT->post->str('do') == 'media') {
219
        tpl_mediaFileList();
220
    } else {
221
        tpl_mediaContent(true, $sort);
222
    }
223
}
224
225
/**
226
 * Return the content of the right column
227
 * (image details) for the Mediamanager
228
 *
229
 * @author Kate Arzamastseva <[email protected]>
230
 */
231
function ajax_mediadetails(){
232
    global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT;
233
    $fullscreen = true;
234
    require_once(DOKU_INC.'lib/exe/mediamanager.php');
235
236
    $image = '';
237
    if ($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
238
    if (isset($IMG)) $image = $IMG;
239
    if (isset($JUMPTO)) $image = $JUMPTO;
240
    $rev = false;
241
    if (isset($REV) && !$JUMPTO) $rev = $REV;
242
243
    html_msgarea();
244
    tpl_mediaFileDetails($image, $rev);
245
}
246
247
/**
248
 * Returns image diff representation for mediamanager
249
 * @author Kate Arzamastseva <[email protected]>
250
 */
251
function ajax_mediadiff(){
252
    global $NS;
253
    global $INPUT;
254
255
    $image = '';
256
    if ($INPUT->has('image')) $image = cleanID($INPUT->str('image'));
257
    $NS = getNS($image);
258
    $auth = auth_quickaclcheck("$NS:*");
259
    media_diff($image, $NS, $auth, true);
0 ignored issues
show
It seems like $NS defined by getNS($image) on line 257 can also be of type false; however, media_diff() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
260
}
261
262
function ajax_mediaupload(){
263
    global $NS, $MSG, $INPUT;
264
265
    $id = '';
266
    if ($_FILES['qqfile']['tmp_name']) {
267
        $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']);
268
    } elseif ($INPUT->get->has('qqfile')) {
269
        $id = $INPUT->get->str('qqfile');
270
    }
271
272
    $id = cleanID($id);
273
274
    $NS = $INPUT->str('ns');
275
    $ns = $NS.':'.getNS($id);
276
277
    $AUTH = auth_quickaclcheck("$ns:*");
278
    if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$ns:xxx", 'media'); }
279
280
    if ($_FILES['qqfile']['error']) unset($_FILES['qqfile']);
281
282
    $res = false;
283
    if ($_FILES['qqfile']['tmp_name']) $res = media_upload($NS, $AUTH, $_FILES['qqfile']);
284
    if ($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH);
285
286
    if($res) {
287
        $result = array(
288
            'success' => true,
289
            'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'),
290
            'id' => $NS . ':' . $id,
291
            'ns' => $NS
292
        );
293
    } else {
294
        $error = '';
295
        if(isset($MSG)) {
296
            foreach($MSG as $msg) {
297
                $error .= $msg['msg'];
298
            }
299
        }
300
        $result = array(
301
            'error' => $error,
302
            'ns' => $NS
303
        );
304
    }
305
    $json = new JSON;
306
    echo htmlspecialchars($json->encode($result), ENT_NOQUOTES);
307
}
308
309
/**
310
 * Return sub index for index view
311
 *
312
 * @author Andreas Gohr <[email protected]>
313
 */
314
function ajax_index(){
315
    global $conf;
316
    global $INPUT;
317
318
    // wanted namespace
319
    $ns  = cleanID($INPUT->post->str('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 <[email protected]>
336
 */
337
function ajax_linkwiz(){
338
    global $conf;
339
    global $lang;
340
    global $INPUT;
341
342
    $q  = ltrim(trim($INPUT->post->str('q')),':');
343
    $id = noNS($q);
344
    $ns = getNS($q);
345
346
    $ns = cleanID($ns);
347
    $id = cleanID($id);
348
349
    $nsd  = utf8_encodeFN(str_replace(':','/',$ns));
350
351
    $data = array();
352
    if($q && !$ns){
353
354
        // use index to lookup matching pages
355
        $pages = ft_pageLookup($id,true);
356
357
        // result contains matches in pages and namespaces
358
        // we now extract the matching namespaces to show
359
        // them seperately
360
        $dirs  = array();
361
362
        foreach($pages as $pid => $title){
363
            if(strpos(noNS($pid),$id) === false){
364
                // match was in the namespace
365
                $dirs[getNS($pid)] = 1; // assoc array avoids dupes
366
            }else{
367
                // it is a matching page, add it to the result
368
                $data[] = array(
369
                        'id'    => $pid,
370
                        'title' => $title,
371
                        'type'  => 'f',
372
                        );
373
            }
374
            unset($pages[$pid]);
375
        }
376
        foreach($dirs as $dir => $junk){
377
            $data[] = array(
378
                    'id'   => $dir,
379
                    'type' => 'd',
380
                    );
381
        }
382
383
    }else{
384
385
        $opts = array(
386
                'depth' => 1,
387
                'listfiles' => true,
388
                'listdirs'  => true,
389
                'pagesonly' => true,
390
                'firsthead' => true,
391
                'sneakyacl' => $conf['sneaky_index'],
392
                );
393
        if($id) $opts['filematch'] = '^.*\/'.$id;
394
        if($id) $opts['dirmatch']  = '^.*\/'.$id;
395
        search($data,$conf['datadir'],'search_universal',$opts,$nsd);
396
397
        // add back to upper
398
        if($ns){
399
            array_unshift($data,array(
400
                        'id'   => getNS($ns),
401
                        'type' => 'u',
402
                        ));
403
        }
404
    }
405
406
    // fixme sort results in a useful way ?
407
408
    if(!count($data)){
409
        echo $lang['nothingfound'];
410
        exit;
411
    }
412
413
    // output the found data
414
    $even = 1;
415
    foreach($data as $item){
416
        $even *= -1; //zebra
417
418
        if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id']) $item['id'] .= ':';
419
        $link = wl($item['id']);
420
421
        echo '<div class="'.(($even > 0)?'even':'odd').' type_'.$item['type'].'">';
422
423
        if($item['type'] == 'u'){
424
            $name = $lang['upperns'];
425
        }else{
426
            $name = htmlspecialchars($item['id']);
427
        }
428
429
        echo '<a href="'.$link.'" title="'.htmlspecialchars($item['id']).'" class="wikilink1">'.$name.'</a>';
430
431
        if($item['title']){
432
            echo '<span>'.htmlspecialchars($item['title']).'</span>';
433
        }
434
        echo '</div>';
435
    }
436
437
}
438
439
//Setup VIM: ex: et ts=2 :
440