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 | * This file is part of the TelegramBot package. |
||
4 | * |
||
5 | * (c) Avtandil Kikabidze aka LONGMAN <[email protected]> |
||
6 | * |
||
7 | * For the full copyright and license information, please view the LICENSE |
||
8 | * file that was distributed with this source code. |
||
9 | */ |
||
10 | |||
11 | namespace Longman\TelegramBot; |
||
12 | |||
13 | use Longman\TelegramBot\Exception\TelegramLogException; |
||
14 | use Monolog\Formatter\LineFormatter; |
||
15 | use Monolog\Handler\StreamHandler; |
||
16 | use Monolog\Logger; |
||
17 | |||
18 | class TelegramLog |
||
19 | { |
||
20 | /** |
||
21 | * Monolog instance |
||
22 | * |
||
23 | * @var \Monolog\Logger |
||
24 | */ |
||
25 | static protected $monolog; |
||
26 | |||
27 | /** |
||
28 | * Monolog instance for update |
||
29 | * |
||
30 | * @var \Monolog\Logger |
||
31 | */ |
||
32 | static protected $monolog_update; |
||
33 | |||
34 | /** |
||
35 | * Path for error log |
||
36 | * |
||
37 | * @var string |
||
38 | */ |
||
39 | static protected $error_log_path; |
||
40 | |||
41 | /** |
||
42 | * Path for debug log |
||
43 | * |
||
44 | * @var string |
||
45 | */ |
||
46 | static protected $debug_log_path; |
||
47 | |||
48 | /** |
||
49 | * Path for update log |
||
50 | * |
||
51 | * @var string |
||
52 | */ |
||
53 | static protected $update_log_path; |
||
54 | |||
55 | /** |
||
56 | * Temporary stream handle for debug log |
||
57 | * |
||
58 | * @var resource|null |
||
59 | */ |
||
60 | static protected $debug_log_temp_stream_handle; |
||
61 | |||
62 | /** |
||
63 | * Initialize |
||
64 | * |
||
65 | * Initilize monolog instance. Singleton |
||
66 | * Is possbile provide an external monolog instance |
||
67 | * |
||
68 | * @param \Monolog\Logger |
||
69 | * |
||
70 | * @return \Monolog\Logger |
||
71 | */ |
||
72 | 3 | public static function initialize(Logger $external_monolog = null) |
|
73 | { |
||
74 | 3 | if (self::$monolog === null) { |
|
75 | 3 | if ($external_monolog !== null) { |
|
76 | 1 | self::$monolog = $external_monolog; |
|
77 | |||
78 | 1 | foreach (self::$monolog->getHandlers() as $handler) { |
|
79 | 1 | if ($handler->getLevel() === 400) { |
|
0 ignored issues
–
show
|
|||
80 | 1 | self::$error_log_path = 'true'; |
|
81 | } |
||
82 | 1 | if ($handler->getLevel() === 100) { |
|
0 ignored issues
–
show
It seems like you code against a concrete implementation and not the interface
Monolog\Handler\HandlerInterface as the method getLevel() does only exist in the following implementations of said interface: Monolog\Handler\AbstractHandler , Monolog\Handler\AbstractProcessingHandler , Monolog\Handler\AbstractSyslogHandler , Monolog\Handler\AmqpHandler , Monolog\Handler\BrowserConsoleHandler , Monolog\Handler\BufferHandler , Monolog\Handler\ChromePHPHandler , Monolog\Handler\CouchDBHandler , Monolog\Handler\CubeHandler , Monolog\Handler\DeduplicationHandler , Monolog\Handler\DoctrineCouchDBHandler , Monolog\Handler\DynamoDbHandler , Monolog\Handler\ElasticSearchHandler , Monolog\Handler\ErrorLogHandler , Monolog\Handler\ExceptionTestHandler , Monolog\Handler\FilterHandler , Monolog\Handler\FingersCrossedHandler , Monolog\Handler\FirePHPHandler , Monolog\Handler\FleepHookHandler , Monolog\Handler\FlowdockHandler , Monolog\Handler\GelfHandler , Monolog\Handler\GroupHandler , Monolog\Handler\HipChatHandler , Monolog\Handler\IFTTTHandler , Monolog\Handler\LogEntriesHandler , Monolog\Handler\LogglyHandler , Monolog\Handler\MailHandler , Monolog\Handler\MandrillHandler , Monolog\Handler\MongoDBHandler , Monolog\Handler\NativeMailerHandler , Monolog\Handler\NewRelicHandler , Monolog\Handler\NullHandler , Monolog\Handler\PHPConsoleHandler , Monolog\Handler\PsrHandler , Monolog\Handler\PushoverHandler , Monolog\Handler\RavenHandler , Monolog\Handler\RedisHandler , Monolog\Handler\RollbarHandler , Monolog\Handler\RotatingFileHandler , Monolog\Handler\SamplingHandler , Monolog\Handler\SlackHandler , Monolog\Handler\SocketHandler , Monolog\Handler\StreamHandler , Monolog\Handler\StubNewRelicHandler , Monolog\Handler\StubNewR...HandlerWithoutExtension , Monolog\Handler\SwiftMailerHandler , Monolog\Handler\SyslogHandler , Monolog\Handler\SyslogUdpHandler , Monolog\Handler\TestChromePHPHandler , Monolog\Handler\TestFirePHPHandler , Monolog\Handler\TestHandler , Monolog\Handler\WhatFailureGroupHandler , Monolog\Handler\ZendMonitorHandler .
Let’s take a look at an example: interface User
{
/** @return string */
public function getPassword();
}
class MyUser implements User
{
public function getPassword()
{
// return something
}
public function getDisplayName()
{
// return some name.
}
}
class AuthSystem
{
public function authenticate(User $user)
{
$this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
// do something.
}
}
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break. Available Fixes
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types
inside the if block in such a case.
![]() |
|||
83 | 1 | self::$debug_log_path = 'true'; |
|
84 | } |
||
85 | } |
||
86 | } else { |
||
87 | 2 | self::$monolog = new Logger('bot_log'); |
|
88 | } |
||
89 | } |
||
90 | |||
91 | 3 | return self::$monolog; |
|
92 | } |
||
93 | |||
94 | /** |
||
95 | * Initialize error log |
||
96 | * |
||
97 | * @param string $path |
||
98 | * |
||
99 | * @return \Monolog\Logger |
||
100 | * @throws \Longman\TelegramBot\Exception\TelegramLogException |
||
101 | * @throws \InvalidArgumentException |
||
102 | * @throws \Exception |
||
103 | */ |
||
104 | 2 | View Code Duplication | public static function initErrorLog($path) |
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. ![]() |
|||
105 | { |
||
106 | 2 | if ($path === null || $path === '') { |
|
107 | 1 | throw new TelegramLogException('Empty path for error log'); |
|
108 | } |
||
109 | 1 | self::initialize(); |
|
110 | 1 | self::$error_log_path = $path; |
|
111 | |||
112 | 1 | return self::$monolog->pushHandler( |
|
113 | 1 | (new StreamHandler(self::$error_log_path, Logger::ERROR)) |
|
114 | 1 | ->setFormatter(new LineFormatter(null, null, true)) |
|
115 | ); |
||
116 | } |
||
117 | |||
118 | /** |
||
119 | * Initialize debug log |
||
120 | * |
||
121 | * @param string $path |
||
122 | * |
||
123 | * @return \Monolog\Logger |
||
124 | * @throws \Longman\TelegramBot\Exception\TelegramLogException |
||
125 | * @throws \InvalidArgumentException |
||
126 | * @throws \Exception |
||
127 | */ |
||
128 | 2 | View Code Duplication | public static function initDebugLog($path) |
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. ![]() |
|||
129 | { |
||
130 | 2 | if ($path === null || $path === '') { |
|
131 | 1 | throw new TelegramLogException('Empty path for debug log'); |
|
132 | } |
||
133 | 1 | self::initialize(); |
|
134 | 1 | self::$debug_log_path = $path; |
|
135 | |||
136 | 1 | return self::$monolog->pushHandler( |
|
137 | 1 | (new StreamHandler(self::$debug_log_path, Logger::DEBUG)) |
|
138 | 1 | ->setFormatter(new LineFormatter(null, null, true)) |
|
139 | ); |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get the stream handle of the temporary debug output |
||
144 | * |
||
145 | * @return mixed The stream if debug is active, else false |
||
146 | */ |
||
147 | public static function getDebugLogTempStream() |
||
148 | { |
||
149 | if (self::$debug_log_temp_stream_handle === null) { |
||
150 | if (!self::isDebugLogActive()) { |
||
151 | return false; |
||
152 | } |
||
153 | self::$debug_log_temp_stream_handle = fopen('php://temp', 'w+b'); |
||
154 | } |
||
155 | |||
156 | return self::$debug_log_temp_stream_handle; |
||
157 | } |
||
158 | |||
159 | /** |
||
160 | * Write the temporary debug stream to log and close the stream handle |
||
161 | * |
||
162 | * @param string $message Message (with placeholder) to write to the debug log |
||
163 | */ |
||
164 | public static function endDebugLogTempStream($message = '%s') |
||
165 | { |
||
166 | if (is_resource(self::$debug_log_temp_stream_handle)) { |
||
167 | rewind(self::$debug_log_temp_stream_handle); |
||
168 | self::debug($message, stream_get_contents(self::$debug_log_temp_stream_handle)); |
||
169 | fclose(self::$debug_log_temp_stream_handle); |
||
170 | self::$debug_log_temp_stream_handle = null; |
||
171 | } |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Initialize update log |
||
176 | * |
||
177 | * Initilize monolog instance. Singleton |
||
178 | * Is possbile provide an external monolog instance |
||
179 | * |
||
180 | * @param string $path |
||
181 | * |
||
182 | * @return \Monolog\Logger |
||
183 | * @throws \Longman\TelegramBot\Exception\TelegramLogException |
||
184 | * @throws \InvalidArgumentException |
||
185 | * @throws \Exception |
||
186 | */ |
||
187 | 2 | public static function initUpdateLog($path) |
|
188 | { |
||
189 | 2 | if ($path === null || $path === '') { |
|
190 | 1 | throw new TelegramLogException('Empty path for update log'); |
|
191 | } |
||
192 | 1 | self::$update_log_path = $path; |
|
193 | 1 | if (self::$monolog_update === null) { |
|
194 | 1 | self::$monolog_update = new Logger('bot_update_log'); |
|
195 | // Create a formatter |
||
196 | 1 | $output = '%message%' . PHP_EOL; |
|
197 | 1 | $formatter = new LineFormatter($output); |
|
198 | |||
199 | // Update handler |
||
200 | 1 | $update_handler = new StreamHandler(self::$update_log_path, Logger::INFO); |
|
201 | 1 | $update_handler->setFormatter($formatter); |
|
202 | |||
203 | 1 | self::$monolog_update->pushHandler($update_handler); |
|
204 | } |
||
205 | |||
206 | 1 | return self::$monolog; |
|
207 | } |
||
208 | |||
209 | /** |
||
210 | * Is error log active |
||
211 | * |
||
212 | * @return bool |
||
213 | */ |
||
214 | 4 | public static function isErrorLogActive() |
|
215 | { |
||
216 | 4 | return self::$error_log_path !== null; |
|
217 | } |
||
218 | |||
219 | /** |
||
220 | * Is debug log active |
||
221 | * |
||
222 | * @return bool |
||
223 | */ |
||
224 | 2 | public static function isDebugLogActive() |
|
225 | { |
||
226 | 2 | return self::$debug_log_path !== null; |
|
227 | } |
||
228 | |||
229 | /** |
||
230 | * Is update log active |
||
231 | * |
||
232 | * @return bool |
||
233 | */ |
||
234 | 1 | public static function isUpdateLogActive() |
|
235 | { |
||
236 | 1 | return self::$update_log_path !== null; |
|
237 | } |
||
238 | |||
239 | /** |
||
240 | * Report error log |
||
241 | * |
||
242 | * @param string $text |
||
243 | */ |
||
244 | 4 | public static function error($text) |
|
245 | { |
||
246 | 4 | if (self::isErrorLogActive()) { |
|
247 | 4 | $text = self::getLogText($text, func_get_args()); |
|
248 | 4 | self::$monolog->error($text); |
|
249 | } |
||
250 | 4 | } |
|
251 | |||
252 | /** |
||
253 | * Report debug log |
||
254 | * |
||
255 | * @param string $text |
||
256 | */ |
||
257 | 2 | public static function debug($text) |
|
258 | { |
||
259 | 2 | if (self::isDebugLogActive()) { |
|
260 | 2 | $text = self::getLogText($text, func_get_args()); |
|
261 | 2 | self::$monolog->debug($text); |
|
262 | } |
||
263 | 2 | } |
|
264 | |||
265 | /** |
||
266 | * Report update log |
||
267 | * |
||
268 | * @param string $text |
||
269 | */ |
||
270 | 1 | public static function update($text) |
|
271 | { |
||
272 | 1 | if (self::isUpdateLogActive()) { |
|
273 | 1 | $text = self::getLogText($text, func_get_args()); |
|
274 | 1 | self::$monolog_update->info($text); |
|
275 | } |
||
276 | 1 | } |
|
277 | |||
278 | /** |
||
279 | * Applies vsprintf to the text if placeholder replacements are passed along. |
||
280 | * |
||
281 | * @param string $text |
||
282 | * @param array $args |
||
283 | * |
||
284 | * @return string |
||
285 | */ |
||
286 | 6 | protected static function getLogText($text, array $args = []) |
|
287 | { |
||
288 | // Pop the $text off the array, as it gets passed via func_get_args(). |
||
289 | 6 | array_shift($args); |
|
290 | |||
291 | // If no placeholders have been passed, don't parse the text. |
||
292 | 6 | if (empty($args)) { |
|
293 | 4 | return $text; |
|
294 | } |
||
295 | |||
296 | 6 | return vsprintf($text, $args); |
|
297 | } |
||
298 | } |
||
299 |
Let’s take a look at an example:
In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different implementation of User which does not have a getDisplayName() method, the code will break.
Available Fixes
Change the type-hint for the parameter:
Add an additional type-check:
Add the method to the interface: