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.

bin/dwpage.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
#!/usr/bin/env php
2
<?php
3
4
use splitbrain\phpcli\CLI;
5
use splitbrain\phpcli\Options;
6
7
if(!defined('DOKU_INC')) define('DOKU_INC', realpath(dirname(__FILE__) . '/../') . '/');
8
define('NOSESSION', 1);
9
require_once(DOKU_INC . 'inc/init.php');
10
11
/**
12
 * Checkout and commit pages from the command line while maintaining the history
13
 */
14
class PageCLI extends CLI {
15
16
    protected $force = false;
17
    protected $username = '';
18
19
    /**
20
     * Register options and arguments on the given $options object
21
     *
22
     * @param Options $options
23
     * @return void
24
     */
25
    protected function setup(Options $options) {
26
        /* global */
27
        $options->registerOption(
28
            'force',
29
            'force obtaining a lock for the page (generally bad idea)',
30
            'f'
31
        );
32
        $options->registerOption(
33
            'user',
34
            'work as this user. defaults to current CLI user',
35
            'u',
36
            'username'
37
        );
38
        $options->setHelp(
39
            'Utility to help command line Dokuwiki page editing, allow ' .
40
            'pages to be checked out for editing then committed after changes'
41
        );
42
43
        /* checkout command */
44
        $options->registerCommand(
45
            'checkout',
46
            'Checks out a file from the repository, using the wiki id and obtaining ' .
47
            'a lock for the page. ' . "\n" .
48
            'If a working_file is specified, this is where the page is copied to. ' .
49
            'Otherwise defaults to the same as the wiki page in the current ' .
50
            'working directory.'
51
        );
52
        $options->registerArgument(
53
            'wikipage',
54
            'The wiki page to checkout',
55
            true,
56
            'checkout'
57
        );
58
        $options->registerArgument(
59
            'workingfile',
60
            'How to name the local checkout',
61
            false,
62
            'checkout'
63
        );
64
65
        /* commit command */
66
        $options->registerCommand(
67
            'commit',
68
            'Checks in the working_file into the repository using the specified ' .
69
            'wiki id, archiving the previous version.'
70
        );
71
        $options->registerArgument(
72
            'workingfile',
73
            'The local file to commit',
74
            true,
75
            'commit'
76
        );
77
        $options->registerArgument(
78
            'wikipage',
79
            'The wiki page to create or update',
80
            true,
81
            'commit'
82
        );
83
        $options->registerOption(
84
            'message',
85
            'Summary describing the change (required)',
86
            'm',
87
            'summary',
88
            'commit'
89
        );
90
        $options->registerOption(
91
            'trivial',
92
            'minor change',
93
            't',
94
            false,
95
            'commit'
96
        );
97
98
        /* lock command */
99
        $options->registerCommand(
100
            'lock',
101
            'Obtains or updates a lock for a wiki page'
102
        );
103
        $options->registerArgument(
104
            'wikipage',
105
            'The wiki page to lock',
106
            true,
107
            'lock'
108
        );
109
110
        /* unlock command */
111
        $options->registerCommand(
112
            'unlock',
113
            'Removes a lock for a wiki page.'
114
        );
115
        $options->registerArgument(
116
            'wikipage',
117
            'The wiki page to unlock',
118
            true,
119
            'unlock'
120
        );
121
122
        /* gmeta command */
123
        $options->registerCommand(
124
            'getmeta',
125
            'Prints metadata value for a page to stdout.'
126
        );
127
        $options->registerArgument(
128
            'wikipage',
129
            'The wiki page to get the metadata for',
130
            true,
131
            'getmeta'
132
        );
133
        $options->registerArgument(
134
            'key',
135
            'The name of the metadata item to be retrieved.' . "\n" .
136
            'If empty, an array of all the metadata items is returned.' ."\n" .
137
            'For retrieving items that are stored in sub-arrays, separate the ' .
138
            'keys of the different levels by spaces, in quotes, eg "date modified".',
139
            false,
140
            'getmeta'
141
        );
142
    }
143
144
    /**
145
     * Your main program
146
     *
147
     * Arguments and options have been parsed when this is run
148
     *
149
     * @param Options $options
150
     * @return void
151
     */
152
    protected function main(Options $options) {
153
        $this->force = $options->getOpt('force', false);
154
        $this->username = $options->getOpt('user', $this->getUser());
155
156
        $command = $options->getCmd();
157
        $args = $options->getArgs();
158
        switch($command) {
159
            case 'checkout':
160
                $wiki_id = array_shift($args);
161
                $localfile = array_shift($args);
162
                $this->commandCheckout($wiki_id, $localfile);
163
                break;
164
            case 'commit':
165
                $localfile = array_shift($args);
166
                $wiki_id = array_shift($args);
167
                $this->commandCommit(
168
                    $localfile,
169
                    $wiki_id,
170
                    $options->getOpt('message', ''),
171
                    $options->getOpt('trivial', false)
172
                );
173
                break;
174
            case 'lock':
175
                $wiki_id = array_shift($args);
176
                $this->obtainLock($wiki_id);
177
                $this->success("$wiki_id locked");
178
                break;
179
            case 'unlock':
180
                $wiki_id = array_shift($args);
181
                $this->clearLock($wiki_id);
182
                $this->success("$wiki_id unlocked");
183
                break;
184
            case 'getmeta':
185
                $wiki_id = array_shift($args);
186
                $key = trim(array_shift($args));
187
                $meta = p_get_metadata($wiki_id, $key, METADATA_RENDER_UNLIMITED);
188
                echo trim(json_encode($meta, JSON_PRETTY_PRINT));
189
                echo "\n";
190
                break;
191
            default:
192
                echo $options->help();
193
        }
194
    }
195
196
    /**
197
     * Check out a file
198
     *
199
     * @param string $wiki_id
200
     * @param string $localfile
201
     */
202
    protected function commandCheckout($wiki_id, $localfile) {
203
        global $conf;
204
205
        $wiki_id = cleanID($wiki_id);
206
        $wiki_fn = wikiFN($wiki_id);
207
208
        if(!file_exists($wiki_fn)) {
209
            $this->fatal("$wiki_id does not yet exist");
210
        }
211
212
        if(empty($localfile)) {
213
            $localfile = getcwd() . '/' . \dokuwiki\Utf8\PhpString::basename($wiki_fn);
214
        }
215
216
        if(!file_exists(dirname($localfile))) {
217
            $this->fatal("Directory " . dirname($localfile) . " does not exist");
218
        }
219
220
        if(stristr(realpath(dirname($localfile)), realpath($conf['datadir'])) !== false) {
221
            $this->fatal("Attempt to check out file into data directory - not allowed");
222
        }
223
224
        $this->obtainLock($wiki_id);
225
226
        if(!copy($wiki_fn, $localfile)) {
227
            $this->clearLock($wiki_id);
228
            $this->fatal("Unable to copy $wiki_fn to $localfile");
229
        }
230
231
        $this->success("$wiki_id > $localfile");
232
    }
233
234
    /**
235
     * Save a file as a new page revision
236
     *
237
     * @param string $localfile
238
     * @param string $wiki_id
239
     * @param string $message
240
     * @param bool $minor
241
     */
242
    protected function commandCommit($localfile, $wiki_id, $message, $minor) {
243
        $wiki_id = cleanID($wiki_id);
244
        $message = trim($message);
245
246
        if(!file_exists($localfile)) {
247
            $this->fatal("$localfile does not exist");
248
        }
249
250
        if(!is_readable($localfile)) {
251
            $this->fatal("Cannot read from $localfile");
252
        }
253
254
        if(!$message) {
255
            $this->fatal("Summary message required");
256
        }
257
258
        $this->obtainLock($wiki_id);
259
260
        saveWikiText($wiki_id, file_get_contents($localfile), $message, $minor);
261
262
        $this->clearLock($wiki_id);
263
264
        $this->success("$localfile > $wiki_id");
265
    }
266
267
    /**
268
     * Lock the given page or exit
269
     *
270
     * @param string $wiki_id
271
     */
272
    protected function obtainLock($wiki_id) {
273
        if($this->force) $this->deleteLock($wiki_id);
274
275
        $_SERVER['REMOTE_USER'] = $this->username;
276
277
        if(checklock($wiki_id)) {
278
            $this->error("Page $wiki_id is already locked by another user");
279
            exit(1);
280
        }
281
282
        lock($wiki_id);
283
284
        if(checklock($wiki_id)) {
285
            $this->error("Unable to obtain lock for $wiki_id ");
286
            var_dump(checklock($wiki_id));
0 ignored issues
show
Security Debugging Code introduced by
var_dump(checklock($wiki_id)); looks like debug code. Are you sure you do not want to remove it? This might expose sensitive data.
Loading history...
287
            exit(1);
288
        }
289
    }
290
291
    /**
292
     * Clear the lock on the given page
293
     *
294
     * @param string $wiki_id
295
     */
296
    protected function clearLock($wiki_id) {
297
        if($this->force) $this->deleteLock($wiki_id);
298
299
        $_SERVER['REMOTE_USER'] = $this->username;
300
        if(checklock($wiki_id)) {
301
            $this->error("Page $wiki_id is locked by another user");
302
            exit(1);
303
        }
304
305
        unlock($wiki_id);
306
307
        if(file_exists(wikiLockFN($wiki_id))) {
308
            $this->error("Unable to clear lock for $wiki_id");
309
            exit(1);
310
        }
311
    }
312
313
    /**
314
     * Forcefully remove a lock on the page given
315
     *
316
     * @param string $wiki_id
317
     */
318
    protected function deleteLock($wiki_id) {
319
        $wikiLockFN = wikiLockFN($wiki_id);
320
321
        if(file_exists($wikiLockFN)) {
322
            if(!unlink($wikiLockFN)) {
323
                $this->error("Unable to delete $wikiLockFN");
324
                exit(1);
325
            }
326
        }
327
    }
328
329
    /**
330
     * Get the current user's username from the environment
331
     *
332
     * @return string
333
     */
334
    protected function getUser() {
335
        $user = getenv('USER');
336
        if(empty ($user)) {
337
            $user = getenv('USERNAME');
338
        } else {
339
            return $user;
340
        }
341
        if(empty ($user)) {
342
            $user = 'admin';
343
        }
344
        return $user;
345
    }
346
}
347
348
// Main
349
$cli = new PageCLI();
350
$cli->run();
351