Issues (847)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

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
 * XML feed export
4
 *
5
 * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
6
 * @author     Andreas Gohr <[email protected]>
7
 *
8
 * @global array $conf
9
 * @global Input $INPUT
10
 */
11
12
use dokuwiki\Cache\Cache;
0 ignored issues
show
This use statement conflicts with another class in this namespace, Cache.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
13
use dokuwiki\ChangeLog\MediaChangeLog;
0 ignored issues
show
This use statement conflicts with another class in this namespace, MediaChangeLog.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
14
use dokuwiki\ChangeLog\PageChangeLog;
0 ignored issues
show
This use statement conflicts with another class in this namespace, PageChangeLog.

Let’s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let’s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
15
use dokuwiki\Extension\AuthPlugin;
16
use dokuwiki\Extension\Event;
17
18
if(!defined('DOKU_INC')) define('DOKU_INC', dirname(__FILE__).'/');
19
require_once(DOKU_INC.'inc/init.php');
20
21
//close session
22
session_write_close();
23
24
//feed disabled?
25
if(!actionOK('rss')) {
26
    http_status(404);
27
    echo '<error>RSS feed is disabled.</error>';
28
    exit;
29
}
30
31
// get params
32
$opt = rss_parseOptions();
33
34
// the feed is dynamic - we need a cache for each combo
35
// (but most people just use the default feed so it's still effective)
36
$key   = join('', array_values($opt)).'$'.$_SERVER['REMOTE_USER'].'$'.$_SERVER['HTTP_HOST'].$_SERVER['SERVER_PORT'];
37
$cache = new Cache($key, '.feed');
38
39
// prepare cache depends
40
$depends['files'] = getConfigFiles('main');
41
$depends['age']   = $conf['rss_update'];
42
$depends['purge'] = $INPUT->bool('purge');
43
44
// check cacheage and deliver if nothing has changed since last
45
// time or the update interval has not passed, also handles conditional requests
46
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
47
header('Pragma: public');
48
header('Content-Type: application/xml; charset=utf-8');
49
header('X-Robots-Tag: noindex');
50
if($cache->useCache($depends)) {
51
    http_conditionalRequest($cache->getTime());
52
    if($conf['allowdebug']) header("X-CacheUsed: $cache->cache");
53
    print $cache->retrieveCache();
54
    exit;
55
} else {
56
    http_conditionalRequest(time());
57
}
58
59
// create new feed
60
$rss                 = new UniversalFeedCreator();
61
$rss->title          = $conf['title'].(($opt['namespace']) ? ' '.$opt['namespace'] : '');
62
$rss->link           = DOKU_URL;
63
$rss->syndicationURL = DOKU_URL.'feed.php';
64
$rss->cssStyleSheet  = DOKU_URL.'lib/exe/css.php?s=feed';
0 ignored issues
show
The property cssStyleSheet does not seem to exist in UniversalFeedCreator.

An attempt at access to an undefined property has been detected. This may either be a typographical error or the property has been renamed but there are still references to its old name.

If you really want to allow access to undefined properties, you can define magic methods to allow access. See the php core documentation on Overloading.

Loading history...
65
66
$image        = new FeedImage();
67
$image->title = $conf['title'];
68
$image->url   = tpl_getMediaFile(array(':wiki:favicon.ico', ':favicon.ico', 'images/favicon.ico'), true);
69
$image->link  = DOKU_URL;
70
$rss->image   = $image;
71
72
$data  = null;
73
$modes = array(
74
    'list'   => 'rssListNamespace',
75
    'search' => 'rssSearch',
76
    'recent' => 'rssRecentChanges'
77
);
78
if(isset($modes[$opt['feed_mode']])) {
79
    $data = $modes[$opt['feed_mode']]($opt);
80
} else {
81
    $eventData = array(
82
        'opt'  => &$opt,
83
        'data' => &$data,
84
    );
85
    $event     = new Event('FEED_MODE_UNKNOWN', $eventData);
86
    if($event->advise_before(true)) {
87
        echo sprintf('<error>Unknown feed mode %s</error>', hsc($opt['feed_mode']));
88
        exit;
89
    }
90
    $event->advise_after();
91
}
92
93
rss_buildItems($rss, $data, $opt);
94
$feed = $rss->createFeed($opt['feed_type']);
0 ignored issues
show
The call to FeedCreator::createFeed() has too many arguments starting with $opt['feed_type'].

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
95
96
// save cachefile
97
$cache->storeCache($feed);
98
99
// finally deliver
100
print $feed;
101
102
// ---------------------------------------------------------------- //
103
104
/**
105
 * Get URL parameters and config options and return an initialized option array
106
 *
107
 * @author Andreas Gohr <[email protected]>
108
 */
109
function rss_parseOptions() {
110
    global $conf;
111
    global $INPUT;
112
113
    $opt = array();
114
115
    foreach(array(
116
                // Basic feed properties
117
                // Plugins may probably want to add new values to these
118
                // properties for implementing own feeds
119
120
                // One of: list, search, recent
121
                'feed_mode'    => array('str', 'mode', 'recent'),
122
                // One of: diff, page, rev, current
123
                'link_to'      => array('str', 'linkto', $conf['rss_linkto']),
124
                // One of: abstract, diff, htmldiff, html
125
                'item_content' => array('str', 'content', $conf['rss_content']),
126
127
                // Special feed properties
128
                // These are only used by certain feed_modes
129
130
                // String, used for feed title, in list and rc mode
131
                'namespace'    => array('str', 'ns', null),
132
                // Positive integer, only used in rc mode
133
                'items'        => array('int', 'num', $conf['recent']),
134
                // Boolean, only used in rc mode
135
                'show_minor'   => array('bool', 'minor', false),
136
                // Boolean, only used in rc mode
137
                'only_new'     => array('bool', 'onlynewpages', false),
138
                // String, only used in list mode
139
                'sort'         => array('str', 'sort', 'natural'),
140
                // String, only used in search mode
141
                'search_query' => array('str', 'q', null),
142
                // One of: pages, media, both
143
                'content_type' => array('str', 'view', $conf['rss_media'])
144
145
            ) as $name => $val) {
146
        $opt[$name] = $INPUT->{$val[0]}($val[1], $val[2], true);
147
    }
148
149
    $opt['items']      = max(0, (int) $opt['items']);
150
    $opt['show_minor'] = (bool) $opt['show_minor'];
151
    $opt['only_new']   = (bool) $opt['only_new'];
152
    $opt['sort'] = valid_input_set('sort', array('default' => 'natural', 'date'), $opt);
153
154
    $opt['guardmail'] = ($conf['mailguard'] != '' && $conf['mailguard'] != 'none');
155
156
    $type = $INPUT->valid(
157
        'type',
158
        array( 'rss', 'rss2', 'atom', 'atom1', 'rss1'),
159
        $conf['rss_type']
160
    );
161
    switch($type) {
162
        case 'rss':
163
            $opt['feed_type'] = 'RSS0.91';
164
            $opt['mime_type'] = 'text/xml';
165
            break;
166
        case 'rss2':
167
            $opt['feed_type'] = 'RSS2.0';
168
            $opt['mime_type'] = 'text/xml';
169
            break;
170
        case 'atom':
171
            $opt['feed_type'] = 'ATOM0.3';
172
            $opt['mime_type'] = 'application/xml';
173
            break;
174
        case 'atom1':
175
            $opt['feed_type'] = 'ATOM1.0';
176
            $opt['mime_type'] = 'application/atom+xml';
177
            break;
178
        default:
179
            $opt['feed_type'] = 'RSS1.0';
180
            $opt['mime_type'] = 'application/xml';
181
    }
182
183
    $eventData = array(
184
        'opt' => &$opt,
185
    );
186
    Event::createAndTrigger('FEED_OPTS_POSTPROCESS', $eventData);
187
    return $opt;
188
}
189
190
/**
191
 * Add recent changed pages to a feed object
192
 *
193
 * @author Andreas Gohr <[email protected]>
194
 * @param  FeedCreator $rss the FeedCreator Object
195
 * @param  array       $data the items to add
196
 * @param  array       $opt  the feed options
197
 */
198
function rss_buildItems(&$rss, &$data, $opt) {
199
    global $conf;
200
    global $lang;
201
    /* @var AuthPlugin $auth */
202
    global $auth;
203
204
    $eventData = array(
205
        'rss'  => &$rss,
206
        'data' => &$data,
207
        'opt'  => &$opt,
208
    );
209
    $event     = new Event('FEED_DATA_PROCESS', $eventData);
210
    if($event->advise_before(false)) {
211
        foreach($data as $ditem) {
212
            if(!is_array($ditem)) {
213
                // not an array? then only a list of IDs was given
214
                $ditem = array('id' => $ditem);
215
            }
216
217
            $item = new FeedItem();
218
            $id   = $ditem['id'];
219
            if(!$ditem['media']) {
220
                $meta = p_get_metadata($id);
221
            } else {
222
                $meta = array();
223
            }
224
225
            // add date
226
            if($ditem['date']) {
227
                $date = $ditem['date'];
228
            } elseif ($ditem['media']) {
229
                $date = @filemtime(mediaFN($id));
230
            } elseif (file_exists(wikiFN($id))) {
231
                $date = @filemtime(wikiFN($id));
232
            } elseif($meta['date']['modified']) {
233
                $date = $meta['date']['modified'];
234
            } else {
235
                $date = 0;
236
            }
237
            if($date) $item->date = date('r', $date);
238
239
            // add title
240
            if($conf['useheading'] && $meta['title']) {
241
                $item->title = $meta['title'];
242
            } else {
243
                $item->title = $ditem['id'];
244
            }
245
            if($conf['rss_show_summary'] && !empty($ditem['sum'])) {
246
                $item->title .= ' - '.strip_tags($ditem['sum']);
247
            }
248
249
            // add item link
250
            switch($opt['link_to']) {
251
                case 'page':
252
                    if($ditem['media']) {
253
                        $item->link = media_managerURL(
254
                            array(
255
                                 'image' => $id,
256
                                 'ns'    => getNS($id),
257
                                 'rev'   => $date
258
                            ), '&', true
259
                        );
260
                    } else {
261
                        $item->link = wl($id, 'rev='.$date, true, '&');
262
                    }
263
                    break;
264
                case 'rev':
265
                    if($ditem['media']) {
266
                        $item->link = media_managerURL(
267
                            array(
268
                                 'image'       => $id,
269
                                 'ns'          => getNS($id),
270
                                 'rev'         => $date,
271
                                 'tab_details' => 'history'
272
                            ), '&', true
273
                        );
274
                    } else {
275
                        $item->link = wl($id, 'do=revisions&rev='.$date, true, '&');
276
                    }
277
                    break;
278
                case 'current':
279
                    if($ditem['media']) {
280
                        $item->link = media_managerURL(
281
                            array(
282
                                 'image' => $id,
283
                                 'ns'    => getNS($id)
284
                            ), '&', true
285
                        );
286
                    } else {
287
                        $item->link = wl($id, '', true, '&');
288
                    }
289
                    break;
290
                case 'diff':
291
                default:
292
                    if($ditem['media']) {
293
                        $item->link = media_managerURL(
294
                            array(
295
                                 'image'       => $id,
296
                                 'ns'          => getNS($id),
297
                                 'rev'         => $date,
298
                                 'tab_details' => 'history',
299
                                 'mediado'     => 'diff'
300
                            ), '&', true
301
                        );
302
                    } else {
303
                        $item->link = wl($id, 'rev='.$date.'&do=diff', true, '&');
304
                    }
305
            }
306
307
            // add item content
308
            switch($opt['item_content']) {
309
                case 'diff':
310
                case 'htmldiff':
311
                    if($ditem['media']) {
312
                        $medialog = new MediaChangeLog($id);
313
                        $revs  = $medialog->getRevisions(0, 1);
314
                        $rev   = $revs[0];
315
                        $src_r = '';
316
                        $src_l = '';
317
318
                        if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)), 300)) {
319
                            $more  = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
320
                            $src_r = ml($id, $more, true, '&amp;', true);
321
                        }
322
                        if($rev && $size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), 300)) {
323
                            $more  = 'rev='.$rev.'&w='.$size[0].'&h='.$size[1];
324
                            $src_l = ml($id, $more, true, '&amp;', true);
325
                        }
326
                        $content = '';
327
                        if($src_r) {
328
                            $content = '<table>';
329
                            $content .= '<tr><th width="50%">'.$rev.'</th>';
330
                            $content .= '<th width="50%">'.$lang['current'].'</th></tr>';
331
                            $content .= '<tr align="center"><td><img src="'.$src_l.'" alt="" /></td><td>';
332
                            $content .= '<img src="'.$src_r.'" alt="'.$id.'" /></td></tr>';
333
                            $content .= '</table>';
334
                        }
335
336
                    } else {
337
                        require_once(DOKU_INC.'inc/DifferenceEngine.php');
338
                        $pagelog = new PageChangeLog($id);
339
                        $revs = $pagelog->getRevisions(0, 1);
340
                        $rev  = $revs[0];
341
342
                        if($rev) {
343
                            $df = new Diff(explode("\n", rawWiki($id, $rev)),
344
                                           explode("\n", rawWiki($id, '')));
345
                        } else {
346
                            $df = new Diff(array(''),
347
                                           explode("\n", rawWiki($id, '')));
348
                        }
349
350
                        if($opt['item_content'] == 'htmldiff') {
351
                            // note: no need to escape diff output, TableDiffFormatter provides 'safe' html
352
                            $tdf     = new TableDiffFormatter();
353
                            $content = '<table>';
354
                            $content .= '<tr><th colspan="2" width="50%">'.$rev.'</th>';
355
                            $content .= '<th colspan="2" width="50%">'.$lang['current'].'</th></tr>';
356
                            $content .= $tdf->format($df);
357
                            $content .= '</table>';
358
                        } else {
359
                            // note: diff output must be escaped, UnifiedDiffFormatter provides plain text
360
                            $udf     = new UnifiedDiffFormatter();
361
                            $content = "<pre>\n".hsc($udf->format($df))."\n</pre>";
362
                        }
363
                    }
364
                    break;
365
                case 'html':
366
                    if($ditem['media']) {
367
                        if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) {
368
                            $more    = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
369
                            $src     = ml($id, $more, true, '&amp;', true);
370
                            $content = '<img src="'.$src.'" alt="'.$id.'" />';
371
                        } else {
372
                            $content = '';
373
                        }
374
                    } else {
375
                        if (@filemtime(wikiFN($id)) === $date) {
376
                            $content = p_wiki_xhtml($id, '', false);
377
                        } else {
378
                            $content = p_wiki_xhtml($id, $date, false);
379
                        }
380
                        // no TOC in feeds
381
                        $content = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $content);
382
383
                        // add alignment for images
384
                        $content = preg_replace('/(<img .*?class="medialeft")/s', '\\1 align="left"', $content);
385
                        $content = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $content);
386
387
                        // make URLs work when canonical is not set, regexp instead of rerendering!
388
                        if(!$conf['canonical']) {
389
                            $base    = preg_quote(DOKU_REL, '/');
390
                            $content = preg_replace('/(<a href|<img src)="('.$base.')/s', '$1="'.DOKU_URL, $content);
391
                        }
392
                    }
393
394
                    break;
395
                case 'abstract':
396
                default:
397
                    if($ditem['media']) {
398
                        if($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) {
399
                            $more    = 'w='.$size[0].'&h='.$size[1].'&t='.@filemtime(mediaFN($id));
400
                            $src     = ml($id, $more, true, '&amp;', true);
401
                            $content = '<img src="'.$src.'" alt="'.$id.'" />';
402
                        } else {
403
                            $content = '';
404
                        }
405
                    } else {
406
                        $content = $meta['description']['abstract'];
407
                    }
408
            }
409
            $item->description = $content; //FIXME a plugin hook here could be senseful
410
411
            // add user
412
            # FIXME should the user be pulled from metadata as well?
413
            $user         = @$ditem['user']; // the @ spares time repeating lookup
414
            if(blank($user)) {
415
                $item->author = 'Anonymous';
416
                $item->authorEmail = '[email protected]';
417
            } else {
418
                $item->author = $user;
419
                $item->authorEmail = $user . '@undisclosed.example.com';
420
421
                // get real user name if configured
422
                if($conf['useacl'] && $auth) {
423
                    $userInfo = $auth->getUserData($user);
424
                    if($userInfo) {
425
                        switch($conf['showuseras']) {
426
                            case 'username':
427
                            case 'username_link':
428
                                $item->author = $userInfo['name'];
429
                                break;
430
                            default:
431
                                $item->author = $user;
432
                                break;
433
                        }
434
                    } else {
435
                        $item->author = $user;
436
                    }
437
                }
438
            }
439
440
            // add category
441
            if(isset($meta['subject'])) {
442
                $item->category = $meta['subject'];
443
            } else {
444
                $cat = getNS($id);
445
                if($cat) $item->category = $cat;
0 ignored issues
show
Bug Best Practice introduced by
The expression $cat of type string|false is loosely compared to true; this is ambiguous if the string can be empty. You might want to explicitly use !== false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
446
            }
447
448
            // finally add the item to the feed object, after handing it to registered plugins
449
            $evdata = array(
450
                'item'  => &$item,
451
                'opt'   => &$opt,
452
                'ditem' => &$ditem,
453
                'rss'   => &$rss
454
            );
455
            $evt    = new Event('FEED_ITEM_ADD', $evdata);
456
            if($evt->advise_before()) {
457
                $rss->addItem($item);
458
            }
459
            $evt->advise_after(); // for completeness
460
        }
461
    }
462
    $event->advise_after();
463
}
464
465
/**
466
 * Add recent changed pages to the feed object
467
 *
468
 * @author Andreas Gohr <[email protected]>
469
 */
470
function rssRecentChanges($opt) {
471
    global $conf;
472
    $flags = 0;
473
    if(!$conf['rss_show_deleted']) $flags += RECENTS_SKIP_DELETED;
474
    if(!$opt['show_minor']) $flags += RECENTS_SKIP_MINORS;
475
    if($opt['only_new']) $flags += RECENTS_ONLY_CREATION;
476
    if($opt['content_type'] == 'media' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_CHANGES;
477
    if($opt['content_type'] == 'both' && $conf['mediarevisions']) $flags += RECENTS_MEDIA_PAGES_MIXED;
478
479
    $recents = getRecents(0, $opt['items'], $opt['namespace'], $flags);
480
    return $recents;
481
}
482
483
/**
484
 * Add all pages of a namespace to the feed object
485
 *
486
 * @author Andreas Gohr <[email protected]>
487
 */
488
function rssListNamespace($opt) {
489
    require_once(DOKU_INC.'inc/search.php');
490
    global $conf;
491
492
    $ns = ':'.cleanID($opt['namespace']);
493
    $ns = utf8_encodeFN(str_replace(':', '/', $ns));
494
495
    $data = array();
496
    $search_opts = array(
497
        'depth' => 1,
498
        'pagesonly' => true,
499
        'listfiles' => true
500
    );
501
    search($data, $conf['datadir'], 'search_universal', $search_opts, $ns, $lvl = 1, $opt['sort']);
502
503
    return $data;
504
}
505
506
/**
507
 * Add the result of a full text search to the feed object
508
 *
509
 * @author Andreas Gohr <[email protected]>
510
 */
511
function rssSearch($opt) {
512
    if(!$opt['search_query']) return array();
513
514
    require_once(DOKU_INC.'inc/fulltext.php');
515
    $data = ft_pageSearch($opt['search_query'], $poswords);
516
    $data = array_keys($data);
517
518
    return $data;
519
}
520
521
//Setup VIM: ex: et ts=4 :
522