Issues (2)

Security Analysis    no request data  

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.

src/CronExpression.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
/**
4
 * NOTICE OF LICENSE
5
 *
6
 * This source file is subject to the Open Software License (OSL 3.0)
7
 * that is available through the world-wide-web at this URL:
8
 * http://opensource.org/licenses/osl-3.0.php
9
 *
10
 * Some of this work is derived from mtdowling/cron-expression which is copyrighted as:
11
 * Copyright (c) 2011 Michael Dowling <[email protected]> and contributors
12
 * The licence of this work can be found here: https://github.com/mtdowling/cron-expression/blob/master/LICENSE
13
 *
14
 * Some limitations might apply.
15
 *
16
 * PHP version 5
17
 *
18
 * @category  Library
19
 * @package   Microcron
20
 * @author    Bernhard Wick <[email protected]>
21
 * @copyright 2015 TechDivision GmbH - <[email protected]>
22
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
23
 * @link      http://www.appserver.io/
24
 */
25
26
namespace AppserverIo\Microcron;
27
28
use Cron\CronExpression as SimpleCron;
29
use Cron\FieldFactory as SimpleFieldFactory;
30
31
/**
32
 * AppserverIo\Microcron
33
 *
34
 * CRON expression parser that can determine whether or not a CRON expression is
35
 * due to run, the next run date and previous run date of a CRON expression.
36
 * This class is designed to be used every second
37
 *
38
 * Schedule parts must map to:
39
 * minute [0-59], hour [0-23], day of month, month [1-12|JAN-DEC], day of week
40
 * [1-7|MON-SUN], and an optional year.
41
 *
42
 * @category  Library
43
 * @package   Microcron
44
 * @author    Bernhard Wick <[email protected]>
45
 * @copyright 2015 TechDivision GmbH - <[email protected]>
46
 * @license   http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
47
 * @link      http://www.appserver.io/
48
 */
49
class CronExpression extends SimpleCron
50
{
51
    /**
52
     * Constants which define the position of semantic pieces of a DateTime object
53
     *
54
     * @var string
55
     */
56
    const SECOND = 0;
57
    const MINUTE = 1;
58
    const HOUR = 2;
59
    const DAY = 3;
60
    const MONTH = 4;
61
    const WEEKDAY = 5;
62
    const YEAR = 6;
63
64
    /**
65
     * CRON expression parts
66
     *
67
     * @var array $cronParts
68
     */
69
    protected $cronParts;
70
71
    /**
72
     *  CRON field factory
73
     *
74
     * @var FieldFactory $fieldFactory
75
     */
76
    protected $fieldFactory;
77
78
    /**
79
     * Order in which to test of cron parts
80
     *
81
     * @var array $order
82
     */
83
    protected static $order = array(self::YEAR, self::MONTH, self::DAY, self::WEEKDAY, self::HOUR, self::MINUTE, self::SECOND);
84
85
    /**
86
     * Parse a CRON expression
87
     *
88
     * @param string             $expression   CRON expression (e.g. '8 * * * *')
89
     * @param SimpleFieldFactory $fieldFactory Factory to create cron fields
90
     */
91 8
    public function __construct($expression, SimpleFieldFactory $fieldFactory)
92
    {
93 8
        $this->fieldFactory = $fieldFactory;
0 ignored issues
show
Documentation Bug introduced by
$fieldFactory is of type object<Cron\FieldFactory>, but the property $fieldFactory was declared to be of type object<AppserverIo\Microcron\FieldFactory>. Are you sure that you always receive this specific sub-class here, or does it make sense to add an instanceof check?

Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a given class or a super-class is assigned to a property that is type hinted more strictly.

Either this assignment is in error or an instanceof check should be added for that assignment.

class Alien {}

class Dalek extends Alien {}

class Plot
{
    /** @var  Dalek */
    public $villain;
}

$alien = new Alien();
$plot = new Plot();
if ($alien instanceof Dalek) {
    $plot->villain = $alien;
}
Loading history...
94 8
        $this->setExpression($expression);
95 7
    }
96
97
    /**
98
     * Factory method to create a new CronExpression.
99
     * There are  several special predefined values which can be used to substitute the
100
     * CRON expression. You might see them below
101
     *
102
     * @param string             $expression   The CRON expression to create
103
     * @param SimpleFieldFactory $fieldFactory (optional) Field factory to use
104
     *
105
     *      @yearly, @annually) - Run once a year, midnight, Jan. 1 - 0 0 0 1 1 *
106
     *      @monthly - Run once a month, midnight, first of month - 0 0 0 1 * *
107
     *      @weekly - Run once a week, midnight on Sun - 0 0 0 * * 0
108
     *      @daily - Run once a day, midnight - 0 0 0 * * *
109
     *      @hourly - Run once an hour, first minute - 0 0 * * * *
110
     *      @byMinute - Run once a minute, first second - 0 * * * * *
111
     *      @bySecond - Run once a second - * * * * * *
112
     *
113
     * @return CronExpression
114
     */
115 3
    public static function factory($expression, SimpleFieldFactory $fieldFactory = null)
116
    {
117
        $mappings = array(
118 3
            '@yearly' => '0 0 0 1 1 *',
119
            '@annually' => '0 0 0 1 1 *',
120
            '@monthly' => '0 0 0 1 * *',
121
            '@weekly' => '0 0 0 * * 0',
122
            '@daily' => '0 0 0 * * *',
123
            '@hourly' => '0 0 * * * *',
124
            '@byMinute' => '0 * * * * *',
125
            '@bySecond' => '* * * * * *'
126
        );
127
128 3
        if (isset($mappings[$expression])) {
129 3
            $expression = $mappings[$expression];
130
        }
131
132 3
        return new static($expression, $fieldFactory ?: new FieldFactory());
133
    }
134
135
    /**
136
     * Get all or part of the CRON expression
137
     *
138
     * @param string $part (optional) Specify the part to retrieve or NULL to
139
     *                     get the full cron schedule string.
140
     *
141
     * @return string|null Returns the CRON expression, a part of the
142
     *      CRON expression, or NULL if the part was specified but not found
143
     */
144 7
    public function getExpression($part = null)
145
    {
146 7
        if (null === $part) {
147 1
            return implode(' ', $this->cronParts);
148 7
        } elseif (array_key_exists($part, $this->cronParts)) {
149 7
            return $this->cronParts[$part];
150
        }
151
152 3
        return null;
153
    }
154
155
    /**
156
     * Get the next or previous run date of the expression relative to a date
157
     *
158
     * @param string|\DateTime $currentTime      (optional) Relative calculation date
159
     * @param int              $nth              (optional) Number of matches to skip before returning
160
     * @param bool             $invert           (optional) Set to TRUE to go backwards in time
161
     * @param bool             $allowCurrentDate (optional) Set to TRUE to return the
162
     *                                           current date if it matches the cron expression
163
     *
164
     * @return \DateTime
165
     * @throws \RuntimeException on too many iterations
166
     */
167 59
    protected function getRunDate($currentTime = null, $nth = 0, $invert = false, $allowCurrentDate = false)
168
    {
169 59
        if ($currentTime instanceof \DateTime) {
170 11
            $currentDate = $currentTime;
171
        } else {
172 57
            $currentDate = new \DateTime($currentTime ?: 'now');
173 57
            $currentDate->setTimezone(new \DateTimeZone(date_default_timezone_get()));
174
        }
175
176 59
        $currentDate->setTime($currentDate->format('H'), $currentDate->format('i'), $currentDate->format('s'));
177 59
        $nextRun = clone $currentDate;
178 59
        $nth = (int) $nth;
179
180
        // Set a hard limit to bail on an impossible date
181 59
        for ($i = 0; $i < 1000; $i++) {
182 59
            foreach (self::$order as $position) {
183 59
                $part = $this->getExpression($position);
184 59
                if (null === $part) {
185 58
                    continue;
186
                }
187
188 59
                $satisfied = false;
189
                // Get the field object used to validate this part
190 59
                $field = $this->fieldFactory->getField($position);
191
                // Check if this is singular or a list
192 59
                if (strpos($part, ',') === false) {
193 59
                    $satisfied = $field->isSatisfiedBy($nextRun, $part);
194
                } else {
195 6
                    foreach (array_map('trim', explode(',', $part)) as $listPart) {
196 6
                        if ($field->isSatisfiedBy($nextRun, $listPart)) {
197 6
                            $satisfied = true;
198 6
                            break;
199
                        }
200
                    }
201
                }
202
203
                // If the field is not satisfied, then start over
204 59
                if (!$satisfied) {
205 45
                    $field->increment($nextRun, $invert);
206 59
                    continue 2;
207
                }
208
            }
209
210
            // Skip this match if needed
211 59
            if ((!$allowCurrentDate && $nextRun == $currentDate) || --$nth > -1) {
212 4
                $this->fieldFactory->getField(0)->increment($nextRun, $invert);
213 4
                continue;
214
            }
215
216 59
            return $nextRun;
217
        }
218
219
        // @codeCoverageIgnoreStart
220
        throw new \RuntimeException('Impossible CRON expression');
221
        // @codeCoverageIgnoreEnd
222
    }
223
224
    /**
225
     * Determine if the CRON is due to run based, on the current date or a
226
     * specific date
227
     *
228
     * @param string|\DateTime $currentTime (optional) Relative calculation date
229
     *
230
     * @return bool Returns TRUE if the cron is due to run or FALSE if not
231
     */
232 55
    public function isDue($currentTime = null)
233
    {
234 55
        if (null === $currentTime || 'now' === $currentTime) {
235 1
            $currentDate = date('Y-m-d H:i:s');
236 1
            $currentTime = strtotime($currentDate);
237 55
        } elseif ($currentTime instanceof \DateTime) {
238 9
            $currentDate = $currentTime->format('Y-m-d H:i:s');
239 9
            $currentTime = strtotime($currentDate);
240
        } else {
241 47
            $currentTime = new \DateTime($currentTime);
242 47
            $currentTime->setTime($currentTime->format('H'), $currentTime->format('i'), $currentTime->format('s'));
243 47
            $currentDate = $currentTime->format('Y-m-d H:i:s');
244 47
            $currentTime = $currentTime->getTimeStamp();
245
        }
246
247 55
        return $this->getNextRunDate($currentDate, 0, true)->getTimestamp() == $currentTime;
248
    }
249
250
    /**
251
     * Set or change the CRON expression
252
     *
253
     * @param string $expression CRON expression (e.g. 8 * * * *)
254
     *
255
     * @return CronExpression
256
     * @throws \InvalidArgumentException if not a valid CRON expression
257
     */
258 3
    public function setExpression($expression)
259
    {
260 3
        $this->cronParts = preg_split('/\s/', $expression, -1, PREG_SPLIT_NO_EMPTY);
261 3
        if (count($this->cronParts) < 6) {
262 1
            throw new \InvalidArgumentException(
263 1
                $expression . ' is not a valid CRON expression'
264
            );
265
        }
266
267 2
        foreach ($this->cronParts as $position => $part) {
268 2
            $this->setPart($position, $part);
269
        }
270
271 2
        return $this;
272
    }
273
274
    /**
275
     * Set part of the CRON expression
276
     *
277
     * @param int    $position The position of the CRON expression to set
278
     * @param string $value    The value to set
279
     *
280
     * @return \Cron\CronExpression
281
     * @throws \InvalidArgumentException if the value is not valid for the part
282
     */
283 3
    public function setPart($position, $value)
284
    {
285 3
        if (!$this->fieldFactory->getField($position)->validate($value)) {
286 1
            throw new \InvalidArgumentException(
287 1
                'Invalid CRON field value ' . $value . ' as position ' . $position
288
            );
289
        }
290
291 3
        $this->cronParts[$position] = $value;
292
293 3
        return $this;
294
    }
295
}
296