This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace dokuwiki; |
||
4 | |||
5 | use dokuwiki\Ui; |
||
6 | use dokuwiki\Utf8\Sort; |
||
7 | |||
8 | /** |
||
9 | * Manage all builtin AJAX calls |
||
10 | * |
||
11 | * @todo The calls should be refactored out to their own proper classes |
||
12 | * @package dokuwiki |
||
13 | */ |
||
14 | class Ajax { |
||
15 | |||
16 | /** |
||
17 | * Execute the given call |
||
18 | * |
||
19 | * @param string $call name of the ajax call |
||
20 | */ |
||
21 | public function __construct($call) { |
||
22 | $callfn = 'call' . ucfirst($call); |
||
23 | if(method_exists($this, $callfn)) { |
||
24 | $this->$callfn(); |
||
25 | } else { |
||
26 | $evt = new Extension\Event('AJAX_CALL_UNKNOWN', $call); |
||
27 | if($evt->advise_before()) { |
||
28 | print "AJAX call '" . hsc($call) . "' unknown!\n"; |
||
29 | } else { |
||
30 | $evt->advise_after(); |
||
31 | unset($evt); |
||
32 | } |
||
33 | } |
||
34 | } |
||
35 | |||
36 | /** |
||
37 | * Searches for matching pagenames |
||
38 | * |
||
39 | * @author Andreas Gohr <[email protected]> |
||
40 | */ |
||
41 | protected function callQsearch() { |
||
42 | global $lang; |
||
43 | global $INPUT; |
||
44 | |||
45 | $maxnumbersuggestions = 50; |
||
46 | |||
47 | $query = $INPUT->post->str('q'); |
||
48 | if(empty($query)) $query = $INPUT->get->str('q'); |
||
49 | if(empty($query)) return; |
||
50 | |||
51 | $query = urldecode($query); |
||
52 | |||
53 | $data = ft_pageLookup($query, true, useHeading('navigation')); |
||
54 | |||
55 | if(!count($data)) return; |
||
56 | |||
57 | print '<strong>' . $lang['quickhits'] . '</strong>'; |
||
58 | print '<ul>'; |
||
59 | $counter = 0; |
||
60 | foreach($data as $id => $title) { |
||
61 | if(useHeading('navigation')) { |
||
62 | $name = $title; |
||
63 | } else { |
||
64 | $ns = getNS($id); |
||
65 | if($ns) { |
||
66 | $name = noNS($id) . ' (' . $ns . ')'; |
||
67 | } else { |
||
68 | $name = $id; |
||
69 | } |
||
70 | } |
||
71 | echo '<li>' . html_wikilink(':' . $id, $name) . '</li>'; |
||
72 | |||
73 | $counter++; |
||
74 | if($counter > $maxnumbersuggestions) { |
||
75 | echo '<li>...</li>'; |
||
76 | break; |
||
77 | } |
||
78 | } |
||
79 | print '</ul>'; |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * Support OpenSearch suggestions |
||
84 | * |
||
85 | * @link http://www.opensearch.org/Specifications/OpenSearch/Extensions/Suggestions/1.0 |
||
86 | * @author Mike Frysinger <[email protected]> |
||
87 | */ |
||
88 | protected function callSuggestions() { |
||
89 | global $INPUT; |
||
90 | |||
91 | $query = cleanID($INPUT->post->str('q')); |
||
92 | if(empty($query)) $query = cleanID($INPUT->get->str('q')); |
||
93 | if(empty($query)) return; |
||
94 | |||
95 | $data = ft_pageLookup($query); |
||
96 | if(!count($data)) return; |
||
97 | $data = array_keys($data); |
||
98 | |||
99 | // limit results to 15 hits |
||
100 | $data = array_slice($data, 0, 15); |
||
101 | $data = array_map('trim', $data); |
||
102 | $data = array_map('noNS', $data); |
||
103 | $data = array_unique($data); |
||
104 | Sort::sort($data); |
||
105 | |||
106 | /* now construct a json */ |
||
107 | $suggestions = array( |
||
108 | $query, // the original query |
||
109 | $data, // some suggestions |
||
110 | array(), // no description |
||
111 | array() // no urls |
||
112 | ); |
||
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 | protected function callLock() { |
||
124 | global $ID; |
||
125 | global $INFO; |
||
126 | global $INPUT; |
||
127 | |||
128 | $ID = cleanID($INPUT->post->str('id')); |
||
129 | if(empty($ID)) return; |
||
130 | |||
131 | $INFO = pageinfo(); |
||
132 | |||
133 | $response = [ |
||
134 | 'errors' => [], |
||
135 | 'lock' => '0', |
||
136 | 'draft' => '', |
||
137 | ]; |
||
138 | if(!$INFO['writable']) { |
||
139 | $response['errors'][] = 'Permission to write this page has been denied.'; |
||
140 | echo json_encode($response); |
||
141 | return; |
||
142 | } |
||
143 | |||
144 | if(!checklock($ID)) { |
||
145 | lock($ID); |
||
146 | $response['lock'] = '1'; |
||
147 | } |
||
148 | |||
149 | $draft = new Draft($ID, $INFO['client']); |
||
150 | if ($draft->saveDraft()) { |
||
151 | $response['draft'] = $draft->getDraftMessage(); |
||
152 | } else { |
||
153 | $response['errors'] = array_merge($response['errors'], $draft->getErrors()); |
||
154 | } |
||
155 | echo json_encode($response); |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Delete a draft |
||
160 | * |
||
161 | * @author Andreas Gohr <[email protected]> |
||
162 | */ |
||
163 | protected function callDraftdel() { |
||
164 | global $INPUT; |
||
165 | $id = cleanID($INPUT->str('id')); |
||
166 | if(empty($id)) return; |
||
167 | |||
168 | $client = $_SERVER['REMOTE_USER']; |
||
169 | if(!$client) $client = clientIP(true); |
||
170 | |||
171 | $cname = getCacheName($client . $id, '.draft'); |
||
172 | @unlink($cname); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * Return subnamespaces for the Mediamanager |
||
177 | * |
||
178 | * @author Andreas Gohr <[email protected]> |
||
179 | */ |
||
180 | protected function callMedians() { |
||
181 | global $conf; |
||
182 | global $INPUT; |
||
183 | |||
184 | // wanted namespace |
||
185 | $ns = cleanID($INPUT->post->str('ns')); |
||
186 | $dir = utf8_encodeFN(str_replace(':', '/', $ns)); |
||
187 | |||
188 | $lvl = count(explode(':', $ns)); |
||
189 | |||
190 | $data = array(); |
||
191 | search($data, $conf['mediadir'], 'search_index', array('nofiles' => true), $dir); |
||
192 | foreach(array_keys($data) as $item) { |
||
193 | $data[$item]['level'] = $lvl + 1; |
||
194 | } |
||
195 | echo html_buildlist($data, 'idx', 'media_nstree_item', 'media_nstree_li'); |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Return list of files for the Mediamanager |
||
200 | * |
||
201 | * @author Andreas Gohr <[email protected]> |
||
202 | */ |
||
203 | protected function callMedialist() { |
||
204 | global $NS; |
||
205 | global $INPUT; |
||
206 | |||
207 | $NS = cleanID($INPUT->post->str('ns')); |
||
208 | $sort = $INPUT->post->bool('recent') ? 'date' : 'natural'; |
||
209 | if($INPUT->post->str('do') == 'media') { |
||
210 | tpl_mediaFileList(); |
||
211 | } else { |
||
212 | tpl_mediaContent(true, $sort); |
||
213 | } |
||
214 | } |
||
215 | |||
216 | /** |
||
217 | * Return the content of the right column |
||
218 | * (image details) for the Mediamanager |
||
219 | * |
||
220 | * @author Kate Arzamastseva <[email protected]> |
||
221 | */ |
||
222 | protected function callMediadetails() { |
||
223 | global $IMG, $JUMPTO, $REV, $fullscreen, $INPUT; |
||
224 | $fullscreen = true; |
||
225 | require_once(DOKU_INC . 'lib/exe/mediamanager.php'); |
||
226 | |||
227 | $image = ''; |
||
228 | if($INPUT->has('image')) $image = cleanID($INPUT->str('image')); |
||
229 | if(isset($IMG)) $image = $IMG; |
||
230 | if(isset($JUMPTO)) $image = $JUMPTO; |
||
231 | $rev = false; |
||
232 | if(isset($REV) && !$JUMPTO) $rev = $REV; |
||
233 | |||
234 | html_msgarea(); |
||
235 | tpl_mediaFileDetails($image, $rev); |
||
236 | } |
||
237 | |||
238 | /** |
||
239 | * Returns image diff representation for mediamanager |
||
240 | * |
||
241 | * @author Kate Arzamastseva <[email protected]> |
||
242 | */ |
||
243 | protected function callMediadiff() { |
||
244 | global $NS; |
||
245 | global $INPUT; |
||
246 | |||
247 | $image = ''; |
||
248 | if($INPUT->has('image')) $image = cleanID($INPUT->str('image')); |
||
249 | $NS = getNS($image); |
||
250 | $auth = auth_quickaclcheck("$NS:*"); |
||
251 | media_diff($image, $NS, $auth, true); |
||
0 ignored issues
–
show
|
|||
252 | } |
||
253 | |||
254 | /** |
||
255 | * Manages file uploads |
||
256 | * |
||
257 | * @author Kate Arzamastseva <[email protected]> |
||
258 | */ |
||
259 | protected function callMediaupload() { |
||
260 | global $NS, $MSG, $INPUT; |
||
261 | |||
262 | $id = ''; |
||
263 | if(isset($_FILES['qqfile']['tmp_name'])) { |
||
264 | $id = $INPUT->post->str('mediaid', $_FILES['qqfile']['name']); |
||
265 | } elseif($INPUT->get->has('qqfile')) { |
||
266 | $id = $INPUT->get->str('qqfile'); |
||
267 | } |
||
268 | |||
269 | $id = cleanID($id); |
||
270 | |||
271 | $NS = $INPUT->str('ns'); |
||
272 | $ns = $NS . ':' . getNS($id); |
||
273 | |||
274 | $AUTH = auth_quickaclcheck("$ns:*"); |
||
275 | if($AUTH >= AUTH_UPLOAD) { |
||
276 | io_createNamespace("$ns:xxx", 'media'); |
||
277 | } |
||
278 | |||
279 | if(isset($_FILES['qqfile']['error']) && $_FILES['qqfile']['error']) unset($_FILES['qqfile']); |
||
280 | |||
281 | $res = false; |
||
282 | if(isset($_FILES['qqfile']['tmp_name'])) $res = media_upload($NS, $AUTH, $_FILES['qqfile']); |
||
283 | if($INPUT->get->has('qqfile')) $res = media_upload_xhr($NS, $AUTH); |
||
284 | |||
285 | if($res) { |
||
286 | $result = array( |
||
287 | 'success' => true, |
||
288 | 'link' => media_managerURL(array('ns' => $ns, 'image' => $NS . ':' . $id), '&'), |
||
289 | 'id' => $NS . ':' . $id, |
||
290 | 'ns' => $NS |
||
291 | ); |
||
292 | } else { |
||
293 | $error = ''; |
||
294 | if(isset($MSG)) { |
||
295 | foreach($MSG as $msg) { |
||
296 | $error .= $msg['msg']; |
||
297 | } |
||
298 | } |
||
299 | $result = array( |
||
300 | 'error' => $error, |
||
301 | 'ns' => $NS |
||
302 | ); |
||
303 | } |
||
304 | |||
305 | header('Content-Type: application/json'); |
||
306 | echo json_encode($result); |
||
307 | } |
||
308 | |||
309 | /** |
||
310 | * Return sub index for index view |
||
311 | * |
||
312 | * @author Andreas Gohr <[email protected]> |
||
313 | */ |
||
314 | protected function callIndex() { |
||
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 | $idx = new Ui\Index; |
||
330 | echo html_buildlist($data, 'idx', [$idx,'formatListItem'], [$idx,'tagListItem']); |
||
331 | } |
||
332 | |||
333 | /** |
||
334 | * List matching namespaces and pages for the link wizard |
||
335 | * |
||
336 | * @author Andreas Gohr <[email protected]> |
||
337 | */ |
||
338 | protected function callLinkwiz() { |
||
339 | global $conf; |
||
340 | global $lang; |
||
341 | global $INPUT; |
||
342 | |||
343 | $q = ltrim(trim($INPUT->post->str('q')), ':'); |
||
344 | $id = noNS($q); |
||
345 | $ns = getNS($q); |
||
346 | |||
347 | $ns = cleanID($ns); |
||
0 ignored issues
–
show
|
|||
348 | $id = cleanID($id); |
||
349 | |||
350 | $nsd = utf8_encodeFN(str_replace(':', '/', $ns)); |
||
351 | |||
352 | $data = array(); |
||
353 | if($q !== '' && $ns === '') { |
||
354 | |||
355 | // use index to lookup matching pages |
||
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( |
||
401 | $data, array( |
||
402 | 'id' => getNS($ns), |
||
403 | 'type' => 'u', |
||
404 | ) |
||
405 | ); |
||
406 | } |
||
407 | } |
||
408 | |||
409 | // fixme sort results in a useful way ? |
||
410 | |||
411 | if(!count($data)) { |
||
412 | echo $lang['nothingfound']; |
||
413 | exit; |
||
414 | } |
||
415 | |||
416 | // output the found data |
||
417 | $even = 1; |
||
418 | foreach($data as $item) { |
||
419 | $even *= -1; //zebra |
||
420 | |||
421 | if(($item['type'] == 'd' || $item['type'] == 'u') && $item['id'] !== '') $item['id'] .= ':'; |
||
422 | $link = wl($item['id']); |
||
423 | |||
424 | echo '<div class="' . (($even > 0) ? 'even' : 'odd') . ' type_' . $item['type'] . '">'; |
||
425 | |||
426 | if($item['type'] == 'u') { |
||
427 | $name = $lang['upperns']; |
||
428 | } else { |
||
429 | $name = hsc($item['id']); |
||
430 | } |
||
431 | |||
432 | echo '<a href="' . $link . '" title="' . hsc($item['id']) . '" class="wikilink1">' . $name . '</a>'; |
||
433 | |||
434 | if(!blank($item['title'])) { |
||
435 | echo '<span>' . hsc($item['title']) . '</span>'; |
||
436 | } |
||
437 | echo '</div>'; |
||
438 | } |
||
439 | |||
440 | } |
||
441 | |||
442 | } |
||
443 |
This check looks for type mismatches where the missing type is
false
. This is usually indicative of an error condtion.Consider the follow example
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 returnedfalse
before passing on the value to another function or method that may not be able to handle afalse
.