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 | /** |
||
4 | * This file is part of Peachy MediaWiki Bot API |
||
5 | * |
||
6 | * Peachy is free software: you can redistribute it and/or modify |
||
7 | * it under the terms of the GNU General Public License as published by |
||
8 | * the Free Software Foundation, either version 3 of the License, or |
||
9 | * (at your option) any later version. |
||
10 | * |
||
11 | * This program is distributed in the hope that it will be useful, |
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
14 | * GNU General Public License for more details. |
||
15 | * |
||
16 | * You should have received a copy of the GNU General Public License |
||
17 | * along with this program. If not, see <http://www.gnu.org/licenses/>. |
||
18 | */ |
||
19 | |||
20 | class IRC { |
||
21 | |||
22 | /** |
||
23 | * IRC Socket connection |
||
24 | * |
||
25 | * @var object |
||
26 | * @access public |
||
27 | */ |
||
28 | public $f; |
||
29 | |||
30 | /** |
||
31 | * Channel(s) |
||
32 | * |
||
33 | * @var string|array |
||
34 | * @access private |
||
35 | */ |
||
36 | private $chan; |
||
37 | |||
38 | /** |
||
39 | * Construct function, front-end for fsockopen. |
||
40 | * @param string $User Username to send to IRC |
||
41 | * @param string $Nick Nick to use |
||
42 | * @param string $Pass Password to send |
||
43 | * @param string $Server Server to connect to |
||
44 | * @param string $pgPort Port to use |
||
45 | * @param string $Gecos AKA Real Name, Information field, etc. |
||
46 | * @param string|array Channel (s) to connect to |
||
47 | */ |
||
48 | function __construct( $User, $Nick, $Pass, $Server, $pgPort, $Gecos, $Channel ) { |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
It is recommend to declare an explicit visibility for
__construct .
Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed. If you are not sure which visibility to choose, it is a good idea to start with
the most restrictive visibility, and then raise visibility as needed, i.e.
start with ![]() |
|||
49 | $this->f = fsockopen( $Server, $pgPort, $errno, $errstr, 30 ); |
||
0 ignored issues
–
show
It seems like
fsockopen($Server, $pgPort, $errno, $errstr, 30) of type resource is incompatible with the declared type object of property $f .
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.. ![]() |
|||
50 | |||
51 | if( !$this->f ) { |
||
52 | die( $errstr . ' (' . $errno . ")\n" ); |
||
0 ignored issues
–
show
The method
__construct() contains an exit expression.
An exit expression should only be used in rare cases. For example, if you write a short command line script. In most cases however, using an ![]() |
|||
53 | } |
||
54 | |||
55 | pecho( "Logging into IRC as $User into $Server:$pgPort\n\n", PECHO_NOTICE ); |
||
56 | |||
57 | $this->sendToIrc( 'USER ' . $User . ' "' . $Server . '" "localhost" :' . $Gecos . "\n" ); |
||
58 | $this->sendToIrc( 'PASS ' . $Pass . "\n" ); |
||
59 | $this->sendToIrc( 'NICK ' . $Nick . "\n" ); |
||
60 | |||
61 | if( !is_array( $Channel ) ) { |
||
62 | $this->chan = array( $Channel ); |
||
63 | } else { |
||
64 | $this->chan = $Channel; |
||
65 | } |
||
66 | $this->joinChan( $Channel ); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * Destruct function, quits from IRC |
||
71 | * @return void |
||
72 | */ |
||
73 | public function quit() { |
||
74 | fwrite( $this->f, 'QUIT ' . "\n" ); |
||
75 | } |
||
76 | |||
77 | /** |
||
78 | * Sends a raw message to IRC |
||
79 | * @param string $msg Message to send |
||
80 | * @return void |
||
81 | */ |
||
82 | public function sendToIrc( $msg ) { |
||
83 | fwrite( $this->f, $msg ); |
||
84 | } |
||
85 | |||
86 | /** |
||
87 | * Send a message to a channel, formatted in PRIVMSG format |
||
88 | * @param string $msg Message to send |
||
89 | * @param string $chan Channel to send to |
||
90 | * @return void |
||
91 | */ |
||
92 | public function sendPrivmsg( $msg, $chan ) { |
||
93 | pecho( "Sending $msg to $chan...\n\n", PECHO_VERBOSE ); |
||
94 | fwrite( $this->f, "PRIVMSG " . $chan . " :$msg\n" ); |
||
95 | } |
||
96 | |||
97 | /** |
||
98 | * Return the pingpong game |
||
99 | * @param string $payload Data from the PING message |
||
100 | * @return void |
||
101 | */ |
||
102 | public function sendPong( $payload ) { |
||
103 | fwrite( $this->f, "PONG " . $payload . "\r\n" ); |
||
104 | } |
||
105 | |||
106 | /** |
||
107 | * Joins a channel, or the locally stored channel(s) |
||
108 | * @param string $chan Channel to join. Default null. |
||
109 | * @return void |
||
110 | */ |
||
111 | public function joinChan( $chan = null ) { |
||
112 | if( !is_null( $chan ) && !is_array( $chan ) ) { |
||
113 | pecho( "Joining $chan...\n", PECHO_VERBOSE ); |
||
114 | fwrite( $this->f, 'JOIN ' . $chan . "\n" ); |
||
115 | usleep( 5000 ); |
||
116 | } elseif( !is_null( $chan ) ) { |
||
117 | foreach( $chan as $channel ){ |
||
118 | pecho( "Joining $channel...\n", PECHO_VERBOSE ); |
||
119 | fwrite( $this->f, 'JOIN ' . $channel . "\n" ); |
||
120 | usleep( 5000 ); |
||
121 | } |
||
122 | } |
||
123 | } |
||
124 | |||
125 | /** |
||
126 | * Leaves a channel, or the locally stored channel(s) |
||
127 | * @param string $chan Channel to part. Default null |
||
128 | * @return void |
||
129 | */ |
||
130 | public function partChan( $chan = null ) { |
||
131 | if( !is_null( $chan ) ) { |
||
132 | pecho( "Parting $chan...\n", PECHO_VERBOSE ); |
||
133 | fwrite( $this->f, 'PART ' . $chan . "\n" ); |
||
134 | usleep( 5000 ); |
||
135 | } else { |
||
136 | foreach( $this->chan as $chan ){ |
||
0 ignored issues
–
show
The expression
$this->chan of type string|array is not guaranteed to be traversable. How about adding an additional type check?
There are different options of fixing this problem.
![]() |
|||
137 | pecho( "Parting $chan...\n", PECHO_VERBOSE ); |
||
138 | fwrite( $this->f, 'PART ' . $chan . "\n" ); |
||
139 | usleep( 5000 ); |
||
140 | } |
||
141 | } |
||
142 | } |
||
143 | |||
144 | /** |
||
145 | * Splits apart the various parts of an IRC line into usable sections, e.g. !commands, cloaks, etc. |
||
146 | * @param string $line Line that IRC sent |
||
147 | * @param array $trigger Trigger character for !commands (e.g. !, ., @, etc) |
||
148 | * @param bool $feed Whether or not the IRC server is a MediaWiki RC channel |
||
149 | * @return array Parsed line |
||
150 | * @static |
||
151 | */ |
||
152 | public static function parseLine( $line, $trigger, $feed = false ) { |
||
153 | $return = array(); |
||
154 | $return['trueraw'] = $line; |
||
155 | $return['truerawmsg'] = explode( " ", $line ); |
||
156 | unset( $return['truerawmsg'][0], $return['truerawmsg'][1], $return['truerawmsg'][2] ); |
||
157 | $return['truerawmsg'] = substr( implode( ' ', $return['truerawmsg'] ), 1 ); |
||
158 | |||
159 | if( $feed ) { |
||
160 | $line = str_replace( array( "\n", "\r", "\002" ), '', $line ); |
||
161 | $line = preg_replace( '/\003(\d\d?(,\d\d?)?)?/', '', $line ); |
||
162 | } else { |
||
163 | $line = str_replace( array( "\n", "\r" ), '', $line ); |
||
164 | $line = preg_replace( '/' . chr( 3 ) . '.{2,}/i', '', $line ); |
||
165 | } |
||
166 | |||
167 | $return['raw'] = $line; |
||
168 | |||
169 | /* |
||
170 | Data for a privmsg: |
||
171 | $d[0] = Nick!User@Host format. |
||
172 | $d[1] = Action, e.g. "PRIVMSG", "MODE", etc. If it's a message from the server, it's the numerial code |
||
173 | $d[2] = The channel somethign was spoken in |
||
174 | $d[3] = The text that was spoken |
||
175 | */ |
||
176 | $d = $return['message'] = explode( ' ', $line ); |
||
177 | $return['n!u@h'] = $d[0]; |
||
178 | |||
179 | unset( $return['message'][0], $return['message'][1], $return['message'][2] ); |
||
180 | $return['message'] = substr( implode( ' ', $return['message'] ), 1 ); |
||
181 | |||
182 | $return['nick'] = substr( $d[0], 1 ); |
||
183 | $return['nick'] = explode( '!', $return['nick'] ); |
||
184 | $return['nick'] = $return['nick'][0]; |
||
185 | |||
186 | $return['cloak'] = explode( '@', $d[0] ); |
||
187 | $return['cloak'] = @$return['cloak'][1]; |
||
188 | |||
189 | $return['user'] = explode( '!', $d[0] ); |
||
190 | $return['user'] = explode( '@', $return['user'][1] ); |
||
191 | $return['user'] = $return['user'][0]; |
||
192 | |||
193 | $return['chan'] = strtolower( $d[2] ); |
||
194 | |||
195 | $return['type'] = $return['payload'] = $d[1]; |
||
196 | |||
197 | if( in_array( substr( $return['message'], 0, 1 ), $trigger ) ) { |
||
198 | $return['command'] = explode( ' ', substr( strtolower( $return['message'] ), 1 ) ); |
||
199 | $return['command'] = $return['command'][0]; |
||
200 | |||
201 | //Get the parameters |
||
202 | $return['param'] = explode( ' ', $return['message'] ); |
||
203 | unset( $return['param'][0] ); |
||
204 | $return['param'] = implode( ' ', $return['param'] ); |
||
205 | $return['param'] = trim( $return['param'] ); |
||
206 | } |
||
207 | |||
208 | /* |
||
209 | End result: |
||
210 | $return['raw'] = Raw data |
||
211 | $return['message'] = The text that appears in the channel |
||
212 | $return['n!u@h'] = The person who said the line, in N!U@H format |
||
213 | $return['nick'] = The nick who said the line |
||
214 | $return['cloak'] = The cloak of the person who said the line |
||
215 | $return['user'] = The username who said the line |
||
216 | $return['chan'] = The channel the line was said in |
||
217 | $return['type'] = The action that was done (eg PRIVMSG, MODE) |
||
218 | $return['payload'] = For pings, this is $d[1] |
||
219 | $return['command'] = The command that was said, eg !status (excuding !) |
||
220 | $return['param'] = Parameters of the command |
||
221 | */ |
||
222 | return $return; |
||
223 | } |
||
224 | |||
225 | /** |
||
226 | * Parses the title, user, etc from a MediaWiki RC feed |
||
227 | * @link http://www.mediawiki.org/wiki/Manual:IRC_RC_Bot |
||
228 | * @param string $msg Message from feed |
||
229 | * @return array Parsed line |
||
230 | * @static |
||
231 | */ |
||
232 | public static function parseRC( $msg ) { |
||
233 | if( preg_match( '/^\[\[((Talk|User|Wikipedia|Image|MediaWiki|Template|Help|Category|Portal|Special)(( |_)talk)?:)?([^\x5d]*)\]\] (\S*) (http:\/\/en\.wikipedia\.org\/w\/index\.php\?(oldid|diff)=(\d*)&(rcid|oldid)=(\d*).*|http:\/\/en\.wikipedia\.org\/wiki\/\S+)? \* ([^*]*) \* (\(([^)]*)\))? (.*)$/S', $msg, $m ) ) { |
||
234 | |||
235 | $return = array(); |
||
236 | |||
237 | //print_r($m); |
||
238 | |||
239 | $return['namespace'] = $m[2]; |
||
240 | $return['pagename'] = $m[5]; |
||
241 | $return['fullpagename'] = $m[1] . $m[5]; |
||
242 | $return['basepagename'] = explode( '/', $return['fullpagename'] ); |
||
243 | $return['basepagename'] = $return['basepagename'][0]; |
||
244 | $return['subpagename'] = str_replace( $return['basepagename'] . '/', '', $return['fullpagename'] ); |
||
245 | $return['flags'] = str_split( $m[6] ); |
||
246 | $return['action'] = $m[6]; |
||
247 | $return['url'] = $m[7]; |
||
248 | $return['revid'] = $m[9]; |
||
249 | $return['oldid'] = $m[11]; |
||
250 | $return['username'] = $m[12]; |
||
251 | $return['len'] = $m[14]; |
||
252 | $return['comment'] = $m[15]; |
||
253 | $return['timestamp'] = time(); |
||
254 | $return['is_new'] = false; |
||
255 | $return['is_minor'] = false; |
||
256 | $return['is_bot'] = false; |
||
257 | $return['is_delete'] = false; |
||
258 | $return['actionpage'] = null; |
||
259 | |||
260 | if( in_array( 'N', $return['flags'] ) ) { |
||
261 | $return['is_new'] = true; |
||
262 | } |
||
263 | |||
264 | if( in_array( 'M', $return['flags'] ) ) { |
||
265 | $return['is_minor'] = true; |
||
266 | } |
||
267 | |||
268 | if( in_array( 'B', $return['flags'] ) ) { |
||
269 | $return['is_bot'] = true; |
||
270 | } |
||
271 | |||
272 | if( $return['action'] == 'delete' ) { |
||
273 | $return['is_delete'] = true; |
||
274 | $tmp = explode( '[[', $return['comment'] ); |
||
275 | $tmp = explode( ']]', $tmp[1] ); |
||
276 | $return['actionpage'] = $tmp[0]; |
||
277 | $return['actionpageprefix'] = explode( '/', $return['actionpage'] ); |
||
278 | $return['actionpageprefix'] = $return['actionpageprefix'][0]; |
||
279 | } |
||
280 | |||
281 | return $return; |
||
282 | } |
||
283 | } |
||
284 | |||
285 | /** |
||
286 | * @param $errno |
||
287 | * @return bool|string |
||
288 | */ |
||
289 | public static function get_error($errno) |
||
290 | { |
||
291 | if ($errno != null) { |
||
292 | switch ($errno) { |
||
293 | case 401: |
||
294 | return "Nickname/Channel is currently unused"; |
||
295 | case 402: |
||
296 | return "Server not found"; |
||
297 | case 403: |
||
298 | return "Channel not found"; |
||
299 | case 404: |
||
300 | return "Cannot send to channel"; |
||
301 | case 405: |
||
302 | return "Too many channels joined"; |
||
303 | case 406: |
||
304 | return "There was no such nickname"; |
||
305 | } |
||
306 | } else { |
||
307 | return false; |
||
308 | } |
||
309 | } |
||
310 | } |
||
311 | |||
312 | class SimpleIRC { |
||
313 | |||
314 | private $server; |
||
315 | private $pgPort; |
||
0 ignored issues
–
show
|
|||
316 | private $user; |
||
317 | private $pass; |
||
318 | private $nick; |
||
319 | private $channel; |
||
320 | private $callback; |
||
321 | |||
322 | function __construct( $server, $pgPort = 6667, $user, $pass, $nick, $channel, $callback = null ) { |
||
0 ignored issues
–
show
Comprehensibility
Best Practice
introduced
by
It is recommend to declare an explicit visibility for
__construct .
Generally, we recommend to declare visibility for all methods in your source code. This has the advantage of clearly communication to other developers, and also yourself, how this method should be consumed. If you are not sure which visibility to choose, it is a good idea to start with
the most restrictive visibility, and then raise visibility as needed, i.e.
start with ![]() |
|||
323 | global $pgIRCTrigger, $pgHooks; |
||
324 | |||
325 | if( func_num_args() > 6 ) { |
||
326 | $this->server = $server; |
||
327 | $this->port = $pgPort; |
||
0 ignored issues
–
show
The property
port does not exist. Did you maybe forget to declare it?
In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code: class MyClass { }
$x = new MyClass();
$x->foo = true;
Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion: class MyClass {
public $foo;
}
$x = new MyClass();
$x->foo = true;
![]() |
|||
328 | $this->user = $user; |
||
329 | $this->pass = $pass; |
||
330 | $this->nick = $nick; |
||
331 | $this->channel = $channel; |
||
332 | $this->callback = $callback; |
||
333 | } else { |
||
334 | $this->server = $server; |
||
335 | $this->port = 6667; |
||
336 | $this->user = $pgPort; |
||
337 | $this->pass = $user; |
||
338 | $this->nick = $pass; |
||
339 | $this->channel = $nick; |
||
340 | $this->callback = $channel; |
||
341 | } |
||
342 | |||
343 | $pgHooks['SimpleIRCPrivMSG'][] = $callback; |
||
344 | |||
345 | $irc = new IRC( $this->user, $this->nick, $this->pass, $this->server, $this->port, "Peachy IRC Bot Version " . PEACHYVERSION, $this->channel ); |
||
346 | |||
347 | while( !feof( $irc->f ) ){ |
||
348 | |||
349 | $parsed = IRC::parseLine( fgets( $irc->f, 1024 ), $pgIRCTrigger, true ); |
||
350 | |||
351 | if( @$parsed['n!u@h'] == 'PING' ) { |
||
352 | $irc->sendPong( $parsed['payload'] ); |
||
353 | } |
||
354 | |||
355 | if( @$parsed['type'] == '376' || @$parser['type'] == '422' ) { |
||
0 ignored issues
–
show
|
|||
356 | $feed->joinChan(); |
||
0 ignored issues
–
show
|
|||
357 | sleep( 5 ); |
||
358 | } |
||
359 | |||
360 | if( @$parsed['type'] == 'PRIVMSG' ) { |
||
361 | Hooks::runHook( 'SimpleIRCPrivMSG', array( &$parsed, &$irc, &$this ) ); |
||
362 | } |
||
363 | } |
||
364 | } |
||
365 | |||
366 | } |
||
367 |
Adding explicit visibility (
private
,protected
, orpublic
) is generally recommend to communicate to other developers how, and from where this method is intended to be used.