Issues (41)

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/Property/Event/RecurrenceRule.php (11 issues)

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
 * This file is part of the eluceo/iCal package.
5
 *
6
 * (c) Markus Poerschke <[email protected]>
7
 *
8
 * This source file is subject to the MIT license that is bundled
9
 * with this source code in the file LICENSE.
10
 */
11
12
namespace Eluceo\iCal\Property\Event;
13
14
use Eluceo\iCal\ParameterBag;
15
use Eluceo\iCal\Property\ValueInterface;
16
use InvalidArgumentException;
17
18
/**
19
 * Implementation of Recurrence Rule.
20
 *
21
 * @see https://tools.ietf.org/html/rfc5545#section-3.8.5.3
22
 */
23
class RecurrenceRule implements ValueInterface
24
{
25
    const FREQ_YEARLY = 'YEARLY';
26
    const FREQ_MONTHLY = 'MONTHLY';
27
    const FREQ_WEEKLY = 'WEEKLY';
28
    const FREQ_DAILY = 'DAILY';
29
    const FREQ_HOURLY = 'HOURLY';
30
    const FREQ_MINUTELY = 'MINUTELY';
31
    const FREQ_SECONDLY = 'SECONDLY';
32
33
    const WEEKDAY_SUNDAY = 'SU';
34
    const WEEKDAY_MONDAY = 'MO';
35
    const WEEKDAY_TUESDAY = 'TU';
36
    const WEEKDAY_WEDNESDAY = 'WE';
37
    const WEEKDAY_THURSDAY = 'TH';
38
    const WEEKDAY_FRIDAY = 'FR';
39
    const WEEKDAY_SATURDAY = 'SA';
40
41
    /**
42
     * The frequency of an Event.
43
     *
44
     * @var string
45
     */
46
    protected $freq = self::FREQ_YEARLY;
47
48
    /**
49
     * BYSETPOS must require use of other BY*.
50
     *
51
     * @var bool
52
     */
53
    protected $canUseBySetPos = false;
54
55
    /**
56
     * @var int|null
57
     */
58
    protected $interval = 1;
59
60
    /**
61
     * @var int|null
62
     */
63
    protected $count = null;
64
65
    /**
66
     * @var \DateTimeInterface|null
67
     */
68
    protected $until = null;
69
70
    /**
71
     * @var string|null
72
     */
73
    protected $wkst;
74
75
    /**
76
     * @var array|null
77
     */
78
    protected $bySetPos = null;
79
80
    /**
81
     * @var string|null
82
     */
83
    protected $byMonth;
84
85
    /**
86
     * @var string|null
87
     */
88
    protected $byWeekNo;
89
90
    /**
91
     * @var string|null
92
     */
93
    protected $byYearDay;
94
95
    /**
96
     * @var string|null
97
     */
98
    protected $byMonthDay;
99
100
    /**
101
     * @var string|null
102
     */
103
    protected $byDay;
104
105
    /**
106
     * @var string|null
107
     */
108
    protected $byHour;
109
110
    /**
111
     * @var string|null
112
     */
113
    protected $byMinute;
114
115
    /**
116
     * @var string|null
117
     */
118
    protected $bySecond;
119
120 11
    public function getEscapedValue(): string
121
    {
122 11
        return $this->buildParameterBag()->toString();
123
    }
124
125
    /**
126
     * @return ParameterBag
127
     */
128 11
    protected function buildParameterBag()
129
    {
130 11
        $parameterBag = new ParameterBag();
131
132 11
        $parameterBag->setParam('FREQ', $this->freq);
133
134 11
        if (null !== $this->interval) {
135 10
            $parameterBag->setParam('INTERVAL', $this->interval);
136
        }
137
138 11
        if (null !== $this->count) {
139 1
            $parameterBag->setParam('COUNT', $this->count);
140
        }
141
142 11
        if (null != $this->until) {
143 1
            $parameterBag->setParam('UNTIL', $this->until->format('Ymd\THis\Z'));
144
        }
145
146 11
        if (null !== $this->wkst) {
147 1
            $parameterBag->setParam('WKST', $this->wkst);
148
        }
149
150 11
        if (null !== $this->bySetPos && $this->canUseBySetPos) {
151
            $parameterBag->setParam('BYSETPOS', $this->bySetPos);
152
        }
153
154 11
        if (null !== $this->byMonth) {
155 1
            $parameterBag->setParam('BYMONTH', explode(',', $this->byMonth));
156
        }
157
158 11
        if (null !== $this->byWeekNo) {
159 1
            $parameterBag->setParam('BYWEEKNO', explode(',', $this->byWeekNo));
160
        }
161
162 11
        if (null !== $this->byYearDay) {
163 1
            $parameterBag->setParam('BYYEARDAY', explode(',', $this->byYearDay));
164
        }
165
166 11
        if (null !== $this->byMonthDay) {
167 1
            $parameterBag->setParam('BYMONTHDAY', explode(',', $this->byMonthDay));
168
        }
169
170 11
        if (null !== $this->byDay) {
171 1
            $parameterBag->setParam('BYDAY', explode(',', $this->byDay));
172
        }
173
174 11
        if (null !== $this->byHour) {
175 1
            $parameterBag->setParam('BYHOUR', explode(',', $this->byHour));
176
        }
177
178 11
        if (null !== $this->byMinute) {
179 1
            $parameterBag->setParam('BYMINUTE', explode(',', $this->byMinute));
180
        }
181
182 11
        if (null !== $this->bySecond) {
183 1
            $parameterBag->setParam('BYSECOND', explode(',', $this->bySecond));
184
        }
185
186 11
        return $parameterBag;
187
    }
188
189
    /**
190
     * @param int|null $count
191
     *
192
     * @return $this
193
     */
194 1
    public function setCount($count)
195
    {
196 1
        $this->count = $count;
197
198 1
        return $this;
199
    }
200
201
    /**
202
     * @return int|null
203
     */
204 2
    public function getCount()
205
    {
206 2
        return $this->count;
207
    }
208
209
    /**
210
     * @return $this
211
     */
212 2
    public function setUntil(\DateTimeInterface $until = null)
213
    {
214 2
        $this->until = $until;
215
216 2
        return $this;
217
    }
218
219
    /**
220
     * @return \DateTimeInterface|null
221
     */
222 1
    public function getUntil()
223
    {
224 1
        return $this->until;
225
    }
226
227
    /**
228
     * The FREQ rule part identifies the type of recurrence rule.  This
229
     * rule part MUST be specified in the recurrence rule.  Valid values
230
     * include.
231
     *
232
     * SECONDLY, to specify repeating events based on an interval of a second or more;
233
     * MINUTELY, to specify repeating events based on an interval of a minute or more;
234
     * HOURLY, to specify repeating events based on an interval of an hour or more;
235
     * DAILY, to specify repeating events based on an interval of a day or more;
236
     * WEEKLY, to specify repeating events based on an interval of a week or more;
237
     * MONTHLY, to specify repeating events based on an interval of a month or more;
238
     * YEARLY, to specify repeating events based on an interval of a year or more.
239
     *
240
     * @param string $freq
241
     *
242
     * @return $this
243
     *
244
     * @throws \InvalidArgumentException
245
     */
246 4
    public function setFreq($freq)
247
    {
248 4
        if (@constant('static::FREQ_' . $freq) !== null) {
249 3
            $this->freq = $freq;
250
        } else {
251 1
            throw new \InvalidArgumentException("The Frequency {$freq} is not supported.");
252
        }
253
254 3
        return $this;
255
    }
256
257
    /**
258
     * @return string
259
     */
260 1
    public function getFreq()
261
    {
262 1
        return $this->freq;
263
    }
264
265
    /**
266
     * The INTERVAL rule part contains a positive integer representing at
267
     * which intervals the recurrence rule repeats.
268
     *
269
     * @param int|null $interval
270
     *
271
     * @return $this
272
     */
273 3
    public function setInterval($interval)
274
    {
275 3
        $this->interval = $interval;
276
277 3
        return $this;
278
    }
279
280
    /**
281
     * @return int|null
282
     */
283 1
    public function getInterval()
284
    {
285 1
        return $this->interval;
286
    }
287
288
    /**
289
     * The WKST rule part specifies the day on which the workweek starts.
290
     * Valid values are MO, TU, WE, TH, FR, SA, and SU.
291
     *
292
     * @param string $value
293
     *
294
     * @return $this
295
     */
296 1
    public function setWkst($value)
297
    {
298 1
        $this->wkst = $value;
299
300 1
        return $this;
301
    }
302
303
    /**
304
     * The BYSETPOS filters one interval of events by the specified position.
305
     * A positive position will start from the beginning and go forward while
306
     * a negative position will start at the end and move backward.
307
     *
308
     * Valid values are a comma separated string or an array of integers
309
     * from 1 to 366 or negative integers from -1 to -366.
310
     *
311
     * @param int|string|array|null $value
312
     *
313
     * @throws InvalidArgumentException
314
     *
315
     * @return $this
316
     */
317
    public function setBySetPos($value)
318
    {
319
        if (null === $value) {
320
            $this->bySetPos = $value;
321
322
            return $this;
323
        }
324
325
        if (!(is_string($value) || is_array($value) || is_int($value))) {
326
            throw new InvalidArgumentException('Invalid value for BYSETPOS');
327
        }
328
329
        $list = $value;
330
331
        if (is_int($value)) {
332
            if ($value === 0 || $value < -366 || $value > 366) {
333
                throw new InvalidArgumentException('Invalid value for BYSETPOS');
334
            }
335
            $this->bySetPos = [$value];
336
337
            return $this;
338
        }
339
340
        if (is_string($value)) {
341
            $list = explode(',', $value);
342
        }
343
344
        $output = [];
345
346
        foreach ($list as $item) {
0 ignored issues
show
The expression $list of type string|array|integer is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
347
            if (is_string($item)) {
348
                if (!preg_match('/^ *-?[0-9]* *$/', $item)) {
349
                    throw new InvalidArgumentException('Invalid value for BYSETPOS');
350
                }
351
                $item = intval($item);
352
            }
353
354
            if (!is_int($item) || $item === 0 || $item < -366 || $item > 366) {
355
                throw new InvalidArgumentException('Invalid value for BYSETPOS');
356
            }
357
358
            $output[] = $item;
359
        }
360
361
        $this->bySetPos = $output;
362
363
        return $this;
364
    }
365
366
    /**
367
     * The BYMONTH rule part specifies a COMMA-separated list of months of the year.
368
     * Valid values are 1 to 12.
369
     *
370
     * @param int $month
371
     *
372
     * @throws \InvalidArgumentException
373
     *
374
     * @return $this
375
     */
376 6
    public function setByMonth($month)
377
    {
378 6
        if (!is_integer($month) || $month <= 0 || $month > 12) {
379 5
            throw new InvalidArgumentException('Invalid value for BYMONTH');
380
        }
381
382 1
        $this->byMonth = $month;
0 ignored issues
show
Documentation Bug introduced by
It seems like $month of type integer is incompatible with the declared type string|null of property $byMonth.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
383
384 1
        $this->canUseBySetPos = true;
385
386 1
        return $this;
387
    }
388
389
    /**
390
     * The BYWEEKNO rule part specifies a COMMA-separated list of ordinals specifying weeks of the year.
391
     * Valid values are 1 to 53 or -53 to -1.
392
     *
393
     * @param int $value
394
     *
395
     * @throws \InvalidArgumentException
396
     *
397
     * @return $this
398
     */
399 5 View Code Duplication
    public function setByWeekNo($value)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
400
    {
401 5
        if (!is_integer($value) || $value > 53 || $value < -53 || $value === 0) {
402 4
            throw new InvalidArgumentException('Invalid value for BYWEEKNO');
403
        }
404
405 1
        $this->byWeekNo = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type integer is incompatible with the declared type string|null of property $byWeekNo.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
406
407 1
        $this->canUseBySetPos = true;
408
409 1
        return $this;
410
    }
411
412
    /**
413
     * The BYYEARDAY rule part specifies a COMMA-separated list of days of the year.
414
     * Valid values are 1 to 366 or -366 to -1.
415
     *
416
     * @param int $day
417
     *
418
     * @throws \InvalidArgumentException
419
     *
420
     * @return $this
421
     */
422 5 View Code Duplication
    public function setByYearDay($day)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
423
    {
424 5
        if (!is_integer($day) || $day > 366 || $day < -366 || $day === 0) {
425 4
            throw new InvalidArgumentException('Invalid value for BYYEARDAY');
426
        }
427
428 1
        $this->byYearDay = $day;
0 ignored issues
show
Documentation Bug introduced by
It seems like $day of type integer is incompatible with the declared type string|null of property $byYearDay.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
429
430 1
        $this->canUseBySetPos = true;
431
432 1
        return $this;
433
    }
434
435
    /**
436
     * The BYMONTHDAY rule part specifies a COMMA-separated list of days of the month.
437
     * Valid values are 1 to 31 or -31 to -1.
438
     *
439
     * @param int $day
440
     *
441
     * @return $this
442
     *
443
     * @throws \InvalidArgumentException
444
     */
445 5 View Code Duplication
    public function setByMonthDay($day)
0 ignored issues
show
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
446
    {
447 5
        if (!is_integer($day) || $day > 31 || $day < -31 || $day === 0) {
448 4
            throw new InvalidArgumentException('Invalid value for BYMONTHDAY');
449
        }
450
451 1
        $this->byMonthDay = $day;
0 ignored issues
show
Documentation Bug introduced by
It seems like $day of type integer is incompatible with the declared type string|null of property $byMonthDay.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
452
453 1
        $this->canUseBySetPos = true;
454
455 1
        return $this;
456
    }
457
458
    /**
459
     * The BYDAY rule part specifies a COMMA-separated list of days of the week;.
460
     *
461
     * SU indicates Sunday; MO indicates Monday; TU indicates Tuesday;
462
     * WE indicates Wednesday; TH indicates Thursday; FR indicates Friday; and SA indicates Saturday.
463
     *
464
     * Each BYDAY value can also be preceded by a positive (+n) or negative (-n) integer.
465
     * If present, this indicates the nth occurrence of a specific day within the MONTHLY or YEARLY "RRULE".
466
     *
467
     * @return $this
468
     */
469 1
    public function setByDay(string $day)
470
    {
471 1
        $this->byDay = $day;
472
473 1
        $this->canUseBySetPos = true;
474
475 1
        return $this;
476
    }
477
478
    /**
479
     * The BYHOUR rule part specifies a COMMA-separated list of hours of the day.
480
     * Valid values are 0 to 23.
481
     *
482
     * @param int $value
483
     *
484
     * @return $this
485
     *
486
     * @throws \InvalidArgumentException
487
     */
488 4
    public function setByHour($value)
489
    {
490 4
        if (!is_integer($value) || $value < 0 || $value > 23) {
491 3
            throw new \InvalidArgumentException('Invalid value for BYHOUR');
492
        }
493
494 1
        $this->byHour = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type integer is incompatible with the declared type string|null of property $byHour.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
495
496 1
        $this->canUseBySetPos = true;
497
498 1
        return $this;
499
    }
500
501
    /**
502
     * The BYMINUTE rule part specifies a COMMA-separated list of minutes within an hour.
503
     * Valid values are 0 to 59.
504
     *
505
     * @param int $value
506
     *
507
     * @return $this
508
     *
509
     * @throws \InvalidArgumentException
510
     */
511 4
    public function setByMinute($value)
512
    {
513 4
        if (!is_integer($value) || $value < 0 || $value > 59) {
514 3
            throw new \InvalidArgumentException('Invalid value for BYMINUTE');
515
        }
516
517 1
        $this->byMinute = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type integer is incompatible with the declared type string|null of property $byMinute.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
518
519 1
        $this->canUseBySetPos = true;
520
521 1
        return $this;
522
    }
523
524
    /**
525
     * The BYSECOND rule part specifies a COMMA-separated list of seconds within a minute.
526
     * Valid values are 0 to 60.
527
     *
528
     * @param int $value
529
     *
530
     * @return $this
531
     *
532
     * @throws \InvalidArgumentException
533
     */
534 4
    public function setBySecond($value)
535
    {
536 4
        if (!is_integer($value) || $value < 0 || $value > 60) {
537 3
            throw new \InvalidArgumentException('Invalid value for BYSECOND');
538
        }
539
540 1
        $this->bySecond = $value;
0 ignored issues
show
Documentation Bug introduced by
It seems like $value of type integer is incompatible with the declared type string|null of property $bySecond.

Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.

Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..

Loading history...
541
542 1
        $this->canUseBySetPos = true;
543
544 1
        return $this;
545
    }
546
}
547