Issues (4967)

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.

src/wp-includes/class-pop3.php (26 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
 * mail_fetch/setup.php
4
 *
5
 * Copyright (c) 1999-2011 CDI ([email protected]) All Rights Reserved
6
 * Modified by Philippe Mingo 2001-2009 [email protected]
7
 * An RFC 1939 compliant wrapper class for the POP3 protocol.
8
 *
9
 * Licensed under the GNU GPL. For full terms see the file COPYING.
10
 *
11
 * POP3 class
12
 *
13
 * @copyright 1999-2011 The SquirrelMail Project Team
14
 * @license http://opensource.org/licenses/gpl-license.php GNU Public License
15
 * @package plugins
16
 * @subpackage mail_fetch
17
 */
18
19
class POP3 {
20
    var $ERROR      = '';       //  Error string.
21
22
    var $TIMEOUT    = 60;       //  Default timeout before giving up on a
23
                                //  network operation.
24
25
    var $COUNT      = -1;       //  Mailbox msg count
26
27
    var $BUFFER     = 512;      //  Socket buffer for socket fgets() calls.
28
                                //  Per RFC 1939 the returned line a POP3
29
                                //  server can send is 512 bytes.
30
31
    var $FP         = '';       //  The connection to the server's
32
                                //  file descriptor
33
34
    var $MAILSERVER = '';       // Set this to hard code the server name
35
36
    var $DEBUG      = FALSE;    // set to true to echo pop3
37
                                // commands and responses to error_log
38
                                // this WILL log passwords!
39
40
    var $BANNER     = '';       //  Holds the banner returned by the
41
                                //  pop server - used for apop()
42
43
    var $ALLOWAPOP  = FALSE;    //  Allow or disallow apop()
44
                                //  This must be set to true
45
                                //  manually
46
47
	/**
48
	 * PHP5 constructor.
49
	 */
50
    function __construct ( $server = '', $timeout = '' ) {
51
        settype($this->BUFFER,"integer");
52
        if( !empty($server) ) {
53
            // Do not allow programs to alter MAILSERVER
54
            // if it is already specified. They can get around
55
            // this if they -really- want to, so don't count on it.
56
            if(empty($this->MAILSERVER))
57
                $this->MAILSERVER = $server;
58
        }
59
        if(!empty($timeout)) {
60
            settype($timeout,"integer");
61
            $this->TIMEOUT = $timeout;
62
            if (!ini_get('safe_mode'))
63
                set_time_limit($timeout);
64
        }
65
        return true;
0 ignored issues
show
Constructors do not have meaningful return values, anything that is returned from here is discarded. Are you sure this is correct?
Loading history...
66
    }
67
68
	/**
69
	 * PHP4 constructor.
70
	 */
71
	public function POP3( $server = '', $timeout = '' ) {
72
		self::__construct( $server, $timeout );
73
	}
74
75
    function update_timer () {
76
        if (!ini_get('safe_mode'))
77
            set_time_limit($this->TIMEOUT);
78
        return true;
79
    }
80
81
    function connect ($server, $port = 110)  {
82
        //  Opens a socket to the specified server. Unless overridden,
83
        //  port defaults to 110. Returns true on success, false on fail
84
85
        // If MAILSERVER is set, override $server with its value.
86
87
    if (!isset($port) || !$port) {$port = 110;}
88
        if(!empty($this->MAILSERVER))
89
            $server = $this->MAILSERVER;
90
91
        if(empty($server)){
92
            $this->ERROR = "POP3 connect: " . _("No server specified");
93
            unset($this->FP);
94
            return false;
95
        }
96
97
        $fp = @fsockopen("$server", $port, $errno, $errstr);
98
99
        if(!$fp) {
100
            $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]";
101
            unset($this->FP);
102
            return false;
103
        }
104
105
        socket_set_blocking($fp,-1);
106
        $this->update_timer();
107
        $reply = fgets($fp,$this->BUFFER);
108
        $reply = $this->strip_clf($reply);
109
        if($this->DEBUG)
110
            error_log("POP3 SEND [connect: $server] GOT [$reply]",0);
111
        if(!$this->is_ok($reply)) {
112
            $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]";
113
            unset($this->FP);
114
            return false;
115
        }
116
        $this->FP = $fp;
117
        $this->BANNER = $this->parse_banner($reply);
118
        return true;
119
    }
120
121 View Code Duplication
    function user ($user = "") {
122
        // Sends the USER command, returns true or false
123
124
        if( empty($user) ) {
125
            $this->ERROR = "POP3 user: " . _("no login ID submitted");
126
            return false;
127
        } elseif(!isset($this->FP)) {
128
            $this->ERROR = "POP3 user: " . _("connection not established");
129
            return false;
130
        } else {
131
            $reply = $this->send_cmd("USER $user");
132
            if(!$this->is_ok($reply)) {
0 ignored issues
show
It seems like $reply defined by $this->send_cmd("USER {$user}") on line 131 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
133
                $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]";
134
                return false;
135
            } else
136
                return true;
137
        }
138
    }
139
140
    function pass ($pass = "")     {
141
        // Sends the PASS command, returns # of msgs in mailbox,
142
        // returns false (undef) on Auth failure
143
144
        if(empty($pass)) {
145
            $this->ERROR = "POP3 pass: " . _("No password submitted");
146
            return false;
147
        } elseif(!isset($this->FP)) {
148
            $this->ERROR = "POP3 pass: " . _("connection not established");
149
            return false;
150 View Code Duplication
        } else {
151
            $reply = $this->send_cmd("PASS $pass");
152
            if(!$this->is_ok($reply)) {
0 ignored issues
show
It seems like $reply defined by $this->send_cmd("PASS {$pass}") on line 151 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
153
                $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]";
154
                $this->quit();
155
                return false;
156
            } else {
157
                //  Auth successful.
158
                $count = $this->last("count");
159
                $this->COUNT = $count;
0 ignored issues
show
Documentation Bug introduced by
It seems like $count can also be of type array<integer,integer,{"...nteger","1":"integer"}>. However, the property $COUNT is declared as type integer. Maybe add an additional type 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 mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
160
                return $count;
161
            }
162
        }
163
    }
164
165
    function apop ($login,$pass) {
166
        //  Attempts an APOP login. If this fails, it'll
167
        //  try a standard login. YOUR SERVER MUST SUPPORT
168
        //  THE USE OF THE APOP COMMAND!
169
        //  (apop is optional per rfc1939)
170
171
        if(!isset($this->FP)) {
172
            $this->ERROR = "POP3 apop: " . _("No connection to server");
173
            return false;
174
        } elseif(!$this->ALLOWAPOP) {
175
            $retVal = $this->login($login,$pass);
176
            return $retVal;
177
        } elseif(empty($login)) {
178
            $this->ERROR = "POP3 apop: " . _("No login ID submitted");
179
            return false;
180
        } elseif(empty($pass)) {
181
            $this->ERROR = "POP3 apop: " . _("No password submitted");
182
            return false;
183
        } else {
184
            $banner = $this->BANNER;
185
            if( (!$banner) or (empty($banner)) ) {
186
                $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort");
187
                $retVal = $this->login($login,$pass);
188
                return $retVal;
189
            } else {
190
                $AuthString = $banner;
191
                $AuthString .= $pass;
192
                $APOPString = md5($AuthString);
193
                $cmd = "APOP $login $APOPString";
194
                $reply = $this->send_cmd($cmd);
195 View Code Duplication
                if(!$this->is_ok($reply)) {
0 ignored issues
show
It seems like $reply defined by $this->send_cmd($cmd) on line 194 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
196
                    $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort");
197
                    $retVal = $this->login($login,$pass);
198
                    return $retVal;
199
                } else {
200
                    //  Auth successful.
201
                    $count = $this->last("count");
202
                    $this->COUNT = $count;
0 ignored issues
show
Documentation Bug introduced by
It seems like $count can also be of type array<integer,integer,{"...nteger","1":"integer"}>. However, the property $COUNT is declared as type integer. Maybe add an additional type 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 mixed type is assigned to a property that is type hinted more strictly.

For example, imagine you have a variable $accountId that can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to the id property of an instance of the Account class. This class holds a proper account, so the id value must no longer be false.

Either this assignment is in error or a type check should be added for that assignment.

class Id
{
    public $id;

    public function __construct($id)
    {
        $this->id = $id;
    }

}

class Account
{
    /** @var  Id $id */
    public $id;
}

$account_id = false;

if (starsAreRight()) {
    $account_id = new Id(42);
}

$account = new Account();
if ($account instanceof Id)
{
    $account->id = $account_id;
}
Loading history...
203
                    return $count;
204
                }
205
            }
206
        }
207
    }
208
209
    function login ($login = "", $pass = "") {
210
        // Sends both user and pass. Returns # of msgs in mailbox or
211
        // false on failure (or -1, if the error occurs while getting
212
        // the number of messages.)
213
214
        if( !isset($this->FP) ) {
215
            $this->ERROR = "POP3 login: " . _("No connection to server");
216
            return false;
217
        } else {
218
            $fp = $this->FP;
219
            if( !$this->user( $login ) ) {
220
                //  Preserve the error generated by user()
221
                return false;
222
            } else {
223
                $count = $this->pass($pass);
224
                if( (!$count) || ($count == -1) ) {
225
                    //  Preserve the error generated by last() and pass()
226
                    return false;
227
                } else
228
                    return $count;
229
            }
230
        }
231
    }
232
233
    function top ($msgNum, $numLines = "0") {
234
        //  Gets the header and first $numLines of the msg body
235
        //  returns data in an array with each returned line being
236
        //  an array element. If $numLines is empty, returns
237
        //  only the header information, and none of the body.
238
239
        if(!isset($this->FP)) {
240
            $this->ERROR = "POP3 top: " . _("No connection to server");
241
            return false;
242
        }
243
        $this->update_timer();
244
245
        $fp = $this->FP;
246
        $buffer = $this->BUFFER;
247
        $cmd = "TOP $msgNum $numLines";
248
        fwrite($fp, "TOP $msgNum $numLines\r\n");
249
        $reply = fgets($fp, $buffer);
250
        $reply = $this->strip_clf($reply);
251
        if($this->DEBUG) {
252
            @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
253
        }
254
        if(!$this->is_ok($reply))
255
        {
256
            $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]";
257
            return false;
258
        }
259
260
        $count = 0;
261
        $MsgArray = array();
262
263
        $line = fgets($fp,$buffer);
264
        while ( !preg_match('/^\.\r\n/',$line))
265
        {
266
            $MsgArray[$count] = $line;
267
            $count++;
268
            $line = fgets($fp,$buffer);
269
            if(empty($line))    { break; }
270
        }
271
272
        return $MsgArray;
273
    }
274
275
    function pop_list ($msgNum = "") {
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
276
        //  If called with an argument, returns that msgs' size in octets
277
        //  No argument returns an associative array of undeleted
278
        //  msg numbers and their sizes in octets
279
280
        if(!isset($this->FP))
281
        {
282
            $this->ERROR = "POP3 pop_list: " . _("No connection to server");
283
            return false;
284
        }
285
        $fp = $this->FP;
286
        $Total = $this->COUNT;
287
        if( (!$Total) or ($Total == -1) )
288
        {
289
            return false;
290
        }
291
        if($Total == 0)
292
        {
293
            return array("0","0");
294
            // return -1;   // mailbox empty
295
        }
296
297
        $this->update_timer();
298
299
        if(!empty($msgNum))
300
        {
301
            $cmd = "LIST $msgNum";
302
            fwrite($fp,"$cmd\r\n");
303
            $reply = fgets($fp,$this->BUFFER);
304
            $reply = $this->strip_clf($reply);
305
            if($this->DEBUG) {
306
                @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
307
            }
308
            if(!$this->is_ok($reply))
309
            {
310
                $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]";
311
                return false;
312
            }
313
            list($junk,$num,$size) = preg_split('/\s+/',$reply);
0 ignored issues
show
The assignment to $junk is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
The assignment to $num is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
314
            return $size;
315
        }
316
        $cmd = "LIST";
317
        $reply = $this->send_cmd($cmd);
318
        if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd($cmd) on line 317 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
319
        {
320
            $reply = $this->strip_clf($reply);
0 ignored issues
show
It seems like $reply can also be of type false; however, POP3::strip_clf() does only seem to accept string, did you maybe forget to handle an error condition?
Loading history...
321
            $this->ERROR = "POP3 pop_list: " . _("Error ") .  "[$reply]";
322
            return false;
323
        }
324
        $MsgArray = array();
325
        $MsgArray[0] = $Total;
326
        for($msgC=1;$msgC <= $Total; $msgC++)
327
        {
328
            if($msgC > $Total) { break; }
329
            $line = fgets($fp,$this->BUFFER);
330
            $line = $this->strip_clf($line);
331
            if(strpos($line, '.') === 0)
332
            {
333
                $this->ERROR = "POP3 pop_list: " . _("Premature end of list");
334
                return false;
335
            }
336
            list($thisMsg,$msgSize) = preg_split('/\s+/',$line);
337
            settype($thisMsg,"integer");
338
            if($thisMsg != $msgC)
339
            {
340
                $MsgArray[$msgC] = "deleted";
341
            }
342
            else
343
            {
344
                $MsgArray[$msgC] = $msgSize;
345
            }
346
        }
347
        return $MsgArray;
348
    }
349
350
    function get ($msgNum) {
351
        //  Retrieve the specified msg number. Returns an array
352
        //  where each line of the msg is an array element.
353
354
        if(!isset($this->FP))
355
        {
356
            $this->ERROR = "POP3 get: " . _("No connection to server");
357
            return false;
358
        }
359
360
        $this->update_timer();
361
362
        $fp = $this->FP;
363
        $buffer = $this->BUFFER;
364
        $cmd = "RETR $msgNum";
365
        $reply = $this->send_cmd($cmd);
366
367
        if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd($cmd) on line 365 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
368
        {
369
            $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]";
370
            return false;
371
        }
372
373
        $count = 0;
374
        $MsgArray = array();
375
376
        $line = fgets($fp,$buffer);
377
        while ( !preg_match('/^\.\r\n/',$line))
378
        {
379
            if ( $line{0} == '.' ) { $line = substr($line,1); }
380
            $MsgArray[$count] = $line;
381
            $count++;
382
            $line = fgets($fp,$buffer);
383
            if(empty($line))    { break; }
384
        }
385
        return $MsgArray;
386
    }
387
388
    function last ( $type = "count" ) {
389
        //  Returns the highest msg number in the mailbox.
390
        //  returns -1 on error, 0+ on success, if type != count
391
        //  results in a popstat() call (2 element array returned)
392
393
        $last = -1;
394
        if(!isset($this->FP))
395
        {
396
            $this->ERROR = "POP3 last: " . _("No connection to server");
397
            return $last;
398
        }
399
400
        $reply = $this->send_cmd("STAT");
401
        if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd('STAT') on line 400 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
402
        {
403
            $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]";
404
            return $last;
405
        }
406
407
        $Vars = preg_split('/\s+/',$reply);
408
        $count = $Vars[1];
409
        $size = $Vars[2];
410
        settype($count,"integer");
411
        settype($size,"integer");
412
        if($type != "count")
413
        {
414
            return array($count,$size);
415
        }
416
        return $count;
417
    }
418
419
    function reset () {
420
        //  Resets the status of the remote server. This includes
421
        //  resetting the status of ALL msgs to not be deleted.
422
        //  This method automatically closes the connection to the server.
423
424
        if(!isset($this->FP))
425
        {
426
            $this->ERROR = "POP3 reset: " . _("No connection to server");
427
            return false;
428
        }
429
        $reply = $this->send_cmd("RSET");
430
        if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd('RSET') on line 429 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
431
        {
432
            //  The POP3 RSET command -never- gives a -ERR
433
            //  response - if it ever does, something truly
434
            //  wild is going on.
435
436
            $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]";
437
            @error_log("POP3 reset: ERROR [$reply]",0);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
438
        }
439
        $this->quit();
440
        return true;
441
    }
442
443
    function send_cmd ( $cmd = "" )
444
    {
445
        //  Sends a user defined command string to the
446
        //  POP server and returns the results. Useful for
447
        //  non-compliant or custom POP servers.
448
        //  Do NOT includ the \r\n as part of your command
449
        //  string - it will be appended automatically.
450
451
        //  The return value is a standard fgets() call, which
452
        //  will read up to $this->BUFFER bytes of data, until it
453
        //  encounters a new line, or EOF, whichever happens first.
454
455
        //  This method works best if $cmd responds with only
456
        //  one line of data.
457
458
        if(!isset($this->FP))
459
        {
460
            $this->ERROR = "POP3 send_cmd: " . _("No connection to server");
461
            return false;
462
        }
463
464
        if(empty($cmd))
465
        {
466
            $this->ERROR = "POP3 send_cmd: " . _("Empty command string");
467
            return "";
468
        }
469
470
        $fp = $this->FP;
471
        $buffer = $this->BUFFER;
472
        $this->update_timer();
473
        fwrite($fp,"$cmd\r\n");
474
        $reply = fgets($fp,$buffer);
475
        $reply = $this->strip_clf($reply);
476
        if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
477
        return $reply;
478
    }
479
480
    function quit() {
481
        //  Closes the connection to the POP3 server, deleting
482
        //  any msgs marked as deleted.
483
484
        if(!isset($this->FP))
485
        {
486
            $this->ERROR = "POP3 quit: " . _("connection does not exist");
487
            return false;
488
        }
489
        $fp = $this->FP;
490
        $cmd = "QUIT";
491
        fwrite($fp,"$cmd\r\n");
492
        $reply = fgets($fp,$this->BUFFER);
493
        $reply = $this->strip_clf($reply);
494
        if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
495
        fclose($fp);
496
        unset($this->FP);
497
        return true;
498
    }
499
500
    function popstat () {
501
        //  Returns an array of 2 elements. The number of undeleted
502
        //  msgs in the mailbox, and the size of the mbox in octets.
503
504
        $PopArray = $this->last("array");
505
506
        if($PopArray == -1) { return false; }
507
508
        if( (!$PopArray) or (empty($PopArray)) )
509
        {
510
            return false;
511
        }
512
        return $PopArray;
513
    }
514
515
    function uidl ($msgNum = "")
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
516
    {
517
        //  Returns the UIDL of the msg specified. If called with
518
        //  no arguments, returns an associative array where each
519
        //  undeleted msg num is a key, and the msg's uidl is the element
520
        //  Array element 0 will contain the total number of msgs
521
522
        if(!isset($this->FP)) {
523
            $this->ERROR = "POP3 uidl: " . _("No connection to server");
524
            return false;
525
        }
526
527
        $fp = $this->FP;
528
        $buffer = $this->BUFFER;
529
530
        if(!empty($msgNum)) {
531
            $cmd = "UIDL $msgNum";
532
            $reply = $this->send_cmd($cmd);
533
            if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd($cmd) on line 532 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
534
            {
535
                $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
536
                return false;
537
            }
538
            list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply);
0 ignored issues
show
The assignment to $ok is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
The assignment to $num is unused. Consider omitting it like so list($first,,$third).

This checks looks for assignemnts to variables using the list(...) function, where not all assigned variables are subsequently used.

Consider the following code example.

<?php

function returnThreeValues() {
    return array('a', 'b', 'c');
}

list($a, $b, $c) = returnThreeValues();

print $a . " - " . $c;

Only the variables $a and $c are used. There was no need to assign $b.

Instead, the list call could have been.

list($a,, $c) = returnThreeValues();
Loading history...
539
            return $myUidl;
540
        } else {
541
            $this->update_timer();
542
543
            $UIDLArray = array();
544
            $Total = $this->COUNT;
545
            $UIDLArray[0] = $Total;
546
547
            if ($Total < 1)
548
            {
549
                return $UIDLArray;
550
            }
551
            $cmd = "UIDL";
552
            fwrite($fp, "UIDL\r\n");
553
            $reply = fgets($fp, $buffer);
554
            $reply = $this->strip_clf($reply);
555
            if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
556
            if(!$this->is_ok($reply))
557
            {
558
                $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
559
                return false;
560
            }
561
562
            $line = "";
563
            $count = 1;
564
            $line = fgets($fp,$buffer);
565
            while ( !preg_match('/^\.\r\n/',$line)) {
566
                list ($msg,$msgUidl) = preg_split('/\s+/',$line);
567
                $msgUidl = $this->strip_clf($msgUidl);
568
                if($count == $msg) {
569
                    $UIDLArray[$msg] = $msgUidl;
570
                }
571
                else
572
                {
573
                    $UIDLArray[$count] = 'deleted';
574
                }
575
                $count++;
576
                $line = fgets($fp,$buffer);
577
            }
578
        }
579
        return $UIDLArray;
580
    }
581
582 View Code Duplication
    function delete ($msgNum = "") {
583
        //  Flags a specified msg as deleted. The msg will not
584
        //  be deleted until a quit() method is called.
585
586
        if(!isset($this->FP))
587
        {
588
            $this->ERROR = "POP3 delete: " . _("No connection to server");
589
            return false;
590
        }
591
        if(empty($msgNum))
592
        {
593
            $this->ERROR = "POP3 delete: " . _("No msg number submitted");
594
            return false;
595
        }
596
        $reply = $this->send_cmd("DELE $msgNum");
597
        if(!$this->is_ok($reply))
0 ignored issues
show
It seems like $reply defined by $this->send_cmd("DELE {$msgNum}") on line 596 can also be of type false; however, POP3::is_ok() does only seem to accept string, did you maybe forget to handle an error condition?

This check looks for type mismatches where the missing type is false. This is usually indicative of an error condtion.

Consider the follow example

<?php

function getDate($date)
{
    if ($date !== null) {
        return new DateTime($date);
    }

    return false;
}

This function either returns a new DateTime object or false, if there was an error. This is a typical pattern in PHP programming to show that an error has occurred without raising an exception. The calling code should check for this returned false before passing on the value to another function or method that may not be able to handle a false.

Loading history...
598
        {
599
            $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]";
600
            return false;
601
        }
602
        return true;
603
    }
604
605
    //  *********************************************************
606
607
    //  The following methods are internal to the class.
608
609
    function is_ok ($cmd = "") {
610
        //  Return true or false on +OK or -ERR
611
612
        if( empty($cmd) )
613
            return false;
614
        else
615
            return( stripos($cmd, '+OK') !== false );
616
    }
617
618
    function strip_clf ($text = "") {
619
        // Strips \r\n from server responses
620
621
        if(empty($text))
622
            return $text;
623
        else {
624
            $stripped = str_replace(array("\r","\n"),'',$text);
625
            return $stripped;
626
        }
627
    }
628
629
    function parse_banner ( $server_text ) {
0 ignored issues
show
The return type could not be reliably inferred; please add a @return annotation.

Our type inference engine in quite powerful, but sometimes the code does not provide enough clues to go by. In these cases we request you to add a @return annotation as described here.

Loading history...
630
        $outside = true;
631
        $banner = "";
632
        $length = strlen($server_text);
633
        for($count =0; $count < $length; $count++)
634
        {
635
            $digit = substr($server_text,$count,1);
636
            if(!empty($digit))             {
637
                if( (!$outside) && ($digit != '<') && ($digit != '>') )
638
                {
639
                    $banner .= $digit;
640
                }
641
                if ($digit == '<')
642
                {
643
                    $outside = false;
644
                }
645
                if($digit == '>')
646
                {
647
                    $outside = true;
648
                }
649
            }
650
        }
651
        $banner = $this->strip_clf($banner);    // Just in case
652
        return "<$banner>";
653
    }
654
655
}   // End class
656
657
// For php4 compatibility
658
if (!function_exists("stripos")) {
659
    function stripos($haystack, $needle){
660
        return strpos($haystack, stristr( $haystack, $needle ));
661
    }
662
}
663