[ Index ]

PHP Cross Reference of WordPress

title

Body

[close]

/wp-includes/ -> class-pop3.php (source)

   1  <?php
   2  /**
   3   * mail_fetch/setup.php
   4   *
   5   * Copyright (c) 1999-2011 CDI (cdi@thewebmasters.net) All Rights Reserved
   6   * Modified by Philippe Mingo 2001-2009 mingo@rotedic.com
   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              set_time_limit($timeout);
  63          }
  64          return true;
  65      }
  66  
  67      /**
  68       * PHP4 constructor.
  69       */
  70  	public function POP3( $server = '', $timeout = '' ) {
  71          self::__construct( $server, $timeout );
  72      }
  73  
  74      function update_timer () {
  75          set_time_limit($this->TIMEOUT);
  76          return true;
  77      }
  78  
  79      function connect ($server, $port = 110)  {
  80          //  Opens a socket to the specified server. Unless overridden,
  81          //  port defaults to 110. Returns true on success, false on fail
  82  
  83          // If MAILSERVER is set, override $server with its value.
  84  
  85      if (!isset($port) || !$port) {$port = 110;}
  86          if(!empty($this->MAILSERVER))
  87              $server = $this->MAILSERVER;
  88  
  89          if(empty($server)){
  90              $this->ERROR = "POP3 connect: " . _("No server specified");
  91              unset($this->FP);
  92              return false;
  93          }
  94  
  95          $fp = @fsockopen("$server", $port, $errno, $errstr);
  96  
  97          if(!$fp) {
  98              $this->ERROR = "POP3 connect: " . _("Error ") . "[$errno] [$errstr]";
  99              unset($this->FP);
 100              return false;
 101          }
 102  
 103          socket_set_blocking($fp,-1);
 104          $this->update_timer();
 105          $reply = fgets($fp,$this->BUFFER);
 106          $reply = $this->strip_clf($reply);
 107          if($this->DEBUG)
 108              error_log("POP3 SEND [connect: $server] GOT [$reply]",0);
 109          if(!$this->is_ok($reply)) {
 110              $this->ERROR = "POP3 connect: " . _("Error ") . "[$reply]";
 111              unset($this->FP);
 112              return false;
 113          }
 114          $this->FP = $fp;
 115          $this->BANNER = $this->parse_banner($reply);
 116          return true;
 117      }
 118  
 119      function user ($user = "") {
 120          // Sends the USER command, returns true or false
 121  
 122          if( empty($user) ) {
 123              $this->ERROR = "POP3 user: " . _("no login ID submitted");
 124              return false;
 125          } elseif(!isset($this->FP)) {
 126              $this->ERROR = "POP3 user: " . _("connection not established");
 127              return false;
 128          } else {
 129              $reply = $this->send_cmd("USER $user");
 130              if(!$this->is_ok($reply)) {
 131                  $this->ERROR = "POP3 user: " . _("Error ") . "[$reply]";
 132                  return false;
 133              } else
 134                  return true;
 135          }
 136      }
 137  
 138      function pass ($pass = "")     {
 139          // Sends the PASS command, returns # of msgs in mailbox,
 140          // returns false (undef) on Auth failure
 141  
 142          if(empty($pass)) {
 143              $this->ERROR = "POP3 pass: " . _("No password submitted");
 144              return false;
 145          } elseif(!isset($this->FP)) {
 146              $this->ERROR = "POP3 pass: " . _("connection not established");
 147              return false;
 148          } else {
 149              $reply = $this->send_cmd("PASS $pass");
 150              if(!$this->is_ok($reply)) {
 151                  $this->ERROR = "POP3 pass: " . _("Authentication failed") . " [$reply]";
 152                  $this->quit();
 153                  return false;
 154              } else {
 155                  //  Auth successful.
 156                  $count = $this->last("count");
 157                  $this->COUNT = $count;
 158                  return $count;
 159              }
 160          }
 161      }
 162  
 163      function apop ($login,$pass) {
 164          //  Attempts an APOP login. If this fails, it'll
 165          //  try a standard login. YOUR SERVER MUST SUPPORT
 166          //  THE USE OF THE APOP COMMAND!
 167          //  (apop is optional per rfc1939)
 168  
 169          if(!isset($this->FP)) {
 170              $this->ERROR = "POP3 apop: " . _("No connection to server");
 171              return false;
 172          } elseif(!$this->ALLOWAPOP) {
 173              $retVal = $this->login($login,$pass);
 174              return $retVal;
 175          } elseif(empty($login)) {
 176              $this->ERROR = "POP3 apop: " . _("No login ID submitted");
 177              return false;
 178          } elseif(empty($pass)) {
 179              $this->ERROR = "POP3 apop: " . _("No password submitted");
 180              return false;
 181          } else {
 182              $banner = $this->BANNER;
 183              if( (!$banner) or (empty($banner)) ) {
 184                  $this->ERROR = "POP3 apop: " . _("No server banner") . ' - ' . _("abort");
 185                  $retVal = $this->login($login,$pass);
 186                  return $retVal;
 187              } else {
 188                  $AuthString = $banner;
 189                  $AuthString .= $pass;
 190                  $APOPString = md5($AuthString);
 191                  $cmd = "APOP $login $APOPString";
 192                  $reply = $this->send_cmd($cmd);
 193                  if(!$this->is_ok($reply)) {
 194                      $this->ERROR = "POP3 apop: " . _("apop authentication failed") . ' - ' . _("abort");
 195                      $retVal = $this->login($login,$pass);
 196                      return $retVal;
 197                  } else {
 198                      //  Auth successful.
 199                      $count = $this->last("count");
 200                      $this->COUNT = $count;
 201                      return $count;
 202                  }
 203              }
 204          }
 205      }
 206  
 207      function login ($login = "", $pass = "") {
 208          // Sends both user and pass. Returns # of msgs in mailbox or
 209          // false on failure (or -1, if the error occurs while getting
 210          // the number of messages.)
 211  
 212          if( !isset($this->FP) ) {
 213              $this->ERROR = "POP3 login: " . _("No connection to server");
 214              return false;
 215          } else {
 216              $fp = $this->FP;
 217              if( !$this->user( $login ) ) {
 218                  //  Preserve the error generated by user()
 219                  return false;
 220              } else {
 221                  $count = $this->pass($pass);
 222                  if( (!$count) || ($count == -1) ) {
 223                      //  Preserve the error generated by last() and pass()
 224                      return false;
 225                  } else
 226                      return $count;
 227              }
 228          }
 229      }
 230  
 231      function top ($msgNum, $numLines = "0") {
 232          //  Gets the header and first $numLines of the msg body
 233          //  returns data in an array with each returned line being
 234          //  an array element. If $numLines is empty, returns
 235          //  only the header information, and none of the body.
 236  
 237          if(!isset($this->FP)) {
 238              $this->ERROR = "POP3 top: " . _("No connection to server");
 239              return false;
 240          }
 241          $this->update_timer();
 242  
 243          $fp = $this->FP;
 244          $buffer = $this->BUFFER;
 245          $cmd = "TOP $msgNum $numLines";
 246          fwrite($fp, "TOP $msgNum $numLines\r\n");
 247          $reply = fgets($fp, $buffer);
 248          $reply = $this->strip_clf($reply);
 249          if($this->DEBUG) {
 250              @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
 251          }
 252          if(!$this->is_ok($reply))
 253          {
 254              $this->ERROR = "POP3 top: " . _("Error ") . "[$reply]";
 255              return false;
 256          }
 257  
 258          $count = 0;
 259          $MsgArray = array();
 260  
 261          $line = fgets($fp,$buffer);
 262          while ( !preg_match('/^\.\r\n/',$line))
 263          {
 264              $MsgArray[$count] = $line;
 265              $count++;
 266              $line = fgets($fp,$buffer);
 267              if(empty($line))    { break; }
 268          }
 269  
 270          return $MsgArray;
 271      }
 272  
 273      function pop_list ($msgNum = "") {
 274          //  If called with an argument, returns that msgs' size in octets
 275          //  No argument returns an associative array of undeleted
 276          //  msg numbers and their sizes in octets
 277  
 278          if(!isset($this->FP))
 279          {
 280              $this->ERROR = "POP3 pop_list: " . _("No connection to server");
 281              return false;
 282          }
 283          $fp = $this->FP;
 284          $Total = $this->COUNT;
 285          if( (!$Total) or ($Total == -1) )
 286          {
 287              return false;
 288          }
 289          if($Total == 0)
 290          {
 291              return array("0","0");
 292              // return -1;   // mailbox empty
 293          }
 294  
 295          $this->update_timer();
 296  
 297          if(!empty($msgNum))
 298          {
 299              $cmd = "LIST $msgNum";
 300              fwrite($fp,"$cmd\r\n");
 301              $reply = fgets($fp,$this->BUFFER);
 302              $reply = $this->strip_clf($reply);
 303              if($this->DEBUG) {
 304                  @error_log("POP3 SEND [$cmd] GOT [$reply]",0);
 305              }
 306              if(!$this->is_ok($reply))
 307              {
 308                  $this->ERROR = "POP3 pop_list: " . _("Error ") . "[$reply]";
 309                  return false;
 310              }
 311              list($junk,$num,$size) = preg_split('/\s+/',$reply);
 312              return $size;
 313          }
 314          $cmd = "LIST";
 315          $reply = $this->send_cmd($cmd);
 316          if(!$this->is_ok($reply))
 317          {
 318              $reply = $this->strip_clf($reply);
 319              $this->ERROR = "POP3 pop_list: " . _("Error ") .  "[$reply]";
 320              return false;
 321          }
 322          $MsgArray = array();
 323          $MsgArray[0] = $Total;
 324          for($msgC=1;$msgC <= $Total; $msgC++)
 325          {
 326              if($msgC > $Total) { break; }
 327              $line = fgets($fp,$this->BUFFER);
 328              $line = $this->strip_clf($line);
 329              if(strpos($line, '.') === 0)
 330              {
 331                  $this->ERROR = "POP3 pop_list: " . _("Premature end of list");
 332                  return false;
 333              }
 334              list($thisMsg,$msgSize) = preg_split('/\s+/',$line);
 335              settype($thisMsg,"integer");
 336              if($thisMsg != $msgC)
 337              {
 338                  $MsgArray[$msgC] = "deleted";
 339              }
 340              else
 341              {
 342                  $MsgArray[$msgC] = $msgSize;
 343              }
 344          }
 345          return $MsgArray;
 346      }
 347  
 348      function get ($msgNum) {
 349          //  Retrieve the specified msg number. Returns an array
 350          //  where each line of the msg is an array element.
 351  
 352          if(!isset($this->FP))
 353          {
 354              $this->ERROR = "POP3 get: " . _("No connection to server");
 355              return false;
 356          }
 357  
 358          $this->update_timer();
 359  
 360          $fp = $this->FP;
 361          $buffer = $this->BUFFER;
 362          $cmd = "RETR $msgNum";
 363          $reply = $this->send_cmd($cmd);
 364  
 365          if(!$this->is_ok($reply))
 366          {
 367              $this->ERROR = "POP3 get: " . _("Error ") . "[$reply]";
 368              return false;
 369          }
 370  
 371          $count = 0;
 372          $MsgArray = array();
 373  
 374          $line = fgets($fp,$buffer);
 375          while ( !preg_match('/^\.\r\n/',$line))
 376          {
 377              if ( $line[0] == '.' ) { $line = substr($line,1); }
 378              $MsgArray[$count] = $line;
 379              $count++;
 380              $line = fgets($fp,$buffer);
 381              if(empty($line))    { break; }
 382          }
 383          return $MsgArray;
 384      }
 385  
 386      function last ( $type = "count" ) {
 387          //  Returns the highest msg number in the mailbox.
 388          //  returns -1 on error, 0+ on success, if type != count
 389          //  results in a popstat() call (2 element array returned)
 390  
 391          $last = -1;
 392          if(!isset($this->FP))
 393          {
 394              $this->ERROR = "POP3 last: " . _("No connection to server");
 395              return $last;
 396          }
 397  
 398          $reply = $this->send_cmd("STAT");
 399          if(!$this->is_ok($reply))
 400          {
 401              $this->ERROR = "POP3 last: " . _("Error ") . "[$reply]";
 402              return $last;
 403          }
 404  
 405          $Vars = preg_split('/\s+/',$reply);
 406          $count = $Vars[1];
 407          $size = $Vars[2];
 408          settype($count,"integer");
 409          settype($size,"integer");
 410          if($type != "count")
 411          {
 412              return array($count,$size);
 413          }
 414          return $count;
 415      }
 416  
 417      function reset () {
 418          //  Resets the status of the remote server. This includes
 419          //  resetting the status of ALL msgs to not be deleted.
 420          //  This method automatically closes the connection to the server.
 421  
 422          if(!isset($this->FP))
 423          {
 424              $this->ERROR = "POP3 reset: " . _("No connection to server");
 425              return false;
 426          }
 427          $reply = $this->send_cmd("RSET");
 428          if(!$this->is_ok($reply))
 429          {
 430              //  The POP3 RSET command -never- gives a -ERR
 431              //  response - if it ever does, something truly
 432              //  wild is going on.
 433  
 434              $this->ERROR = "POP3 reset: " . _("Error ") . "[$reply]";
 435              @error_log("POP3 reset: ERROR [$reply]",0);
 436          }
 437          $this->quit();
 438          return true;
 439      }
 440  
 441      function send_cmd ( $cmd = "" )
 442      {
 443          //  Sends a user defined command string to the
 444          //  POP server and returns the results. Useful for
 445          //  non-compliant or custom POP servers.
 446          //  Do NOT includ the \r\n as part of your command
 447          //  string - it will be appended automatically.
 448  
 449          //  The return value is a standard fgets() call, which
 450          //  will read up to $this->BUFFER bytes of data, until it
 451          //  encounters a new line, or EOF, whichever happens first.
 452  
 453          //  This method works best if $cmd responds with only
 454          //  one line of data.
 455  
 456          if(!isset($this->FP))
 457          {
 458              $this->ERROR = "POP3 send_cmd: " . _("No connection to server");
 459              return false;
 460          }
 461  
 462          if(empty($cmd))
 463          {
 464              $this->ERROR = "POP3 send_cmd: " . _("Empty command string");
 465              return "";
 466          }
 467  
 468          $fp = $this->FP;
 469          $buffer = $this->BUFFER;
 470          $this->update_timer();
 471          fwrite($fp,"$cmd\r\n");
 472          $reply = fgets($fp,$buffer);
 473          $reply = $this->strip_clf($reply);
 474          if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
 475          return $reply;
 476      }
 477  
 478      function quit() {
 479          //  Closes the connection to the POP3 server, deleting
 480          //  any msgs marked as deleted.
 481  
 482          if(!isset($this->FP))
 483          {
 484              $this->ERROR = "POP3 quit: " . _("connection does not exist");
 485              return false;
 486          }
 487          $fp = $this->FP;
 488          $cmd = "QUIT";
 489          fwrite($fp,"$cmd\r\n");
 490          $reply = fgets($fp,$this->BUFFER);
 491          $reply = $this->strip_clf($reply);
 492          if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
 493          fclose($fp);
 494          unset($this->FP);
 495          return true;
 496      }
 497  
 498      function popstat () {
 499          //  Returns an array of 2 elements. The number of undeleted
 500          //  msgs in the mailbox, and the size of the mbox in octets.
 501  
 502          $PopArray = $this->last("array");
 503  
 504          if($PopArray == -1) { return false; }
 505  
 506          if( (!$PopArray) or (empty($PopArray)) )
 507          {
 508              return false;
 509          }
 510          return $PopArray;
 511      }
 512  
 513      function uidl ($msgNum = "")
 514      {
 515          //  Returns the UIDL of the msg specified. If called with
 516          //  no arguments, returns an associative array where each
 517          //  undeleted msg num is a key, and the msg's uidl is the element
 518          //  Array element 0 will contain the total number of msgs
 519  
 520          if(!isset($this->FP)) {
 521              $this->ERROR = "POP3 uidl: " . _("No connection to server");
 522              return false;
 523          }
 524  
 525          $fp = $this->FP;
 526          $buffer = $this->BUFFER;
 527  
 528          if(!empty($msgNum)) {
 529              $cmd = "UIDL $msgNum";
 530              $reply = $this->send_cmd($cmd);
 531              if(!$this->is_ok($reply))
 532              {
 533                  $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
 534                  return false;
 535              }
 536              list ($ok,$num,$myUidl) = preg_split('/\s+/',$reply);
 537              return $myUidl;
 538          } else {
 539              $this->update_timer();
 540  
 541              $UIDLArray = array();
 542              $Total = $this->COUNT;
 543              $UIDLArray[0] = $Total;
 544  
 545              if ($Total < 1)
 546              {
 547                  return $UIDLArray;
 548              }
 549              $cmd = "UIDL";
 550              fwrite($fp, "UIDL\r\n");
 551              $reply = fgets($fp, $buffer);
 552              $reply = $this->strip_clf($reply);
 553              if($this->DEBUG) { @error_log("POP3 SEND [$cmd] GOT [$reply]",0); }
 554              if(!$this->is_ok($reply))
 555              {
 556                  $this->ERROR = "POP3 uidl: " . _("Error ") . "[$reply]";
 557                  return false;
 558              }
 559  
 560              $line = "";
 561              $count = 1;
 562              $line = fgets($fp,$buffer);
 563              while ( !preg_match('/^\.\r\n/',$line)) {
 564                  list ($msg,$msgUidl) = preg_split('/\s+/',$line);
 565                  $msgUidl = $this->strip_clf($msgUidl);
 566                  if($count == $msg) {
 567                      $UIDLArray[$msg] = $msgUidl;
 568                  }
 569                  else
 570                  {
 571                      $UIDLArray[$count] = 'deleted';
 572                  }
 573                  $count++;
 574                  $line = fgets($fp,$buffer);
 575              }
 576          }
 577          return $UIDLArray;
 578      }
 579  
 580      function delete ($msgNum = "") {
 581          //  Flags a specified msg as deleted. The msg will not
 582          //  be deleted until a quit() method is called.
 583  
 584          if(!isset($this->FP))
 585          {
 586              $this->ERROR = "POP3 delete: " . _("No connection to server");
 587              return false;
 588          }
 589          if(empty($msgNum))
 590          {
 591              $this->ERROR = "POP3 delete: " . _("No msg number submitted");
 592              return false;
 593          }
 594          $reply = $this->send_cmd("DELE $msgNum");
 595          if(!$this->is_ok($reply))
 596          {
 597              $this->ERROR = "POP3 delete: " . _("Command failed ") . "[$reply]";
 598              return false;
 599          }
 600          return true;
 601      }
 602  
 603      //  *********************************************************
 604  
 605      //  The following methods are internal to the class.
 606  
 607      function is_ok ($cmd = "") {
 608          //  Return true or false on +OK or -ERR
 609  
 610          if( empty($cmd) )
 611              return false;
 612          else
 613              return( stripos($cmd, '+OK') !== false );
 614      }
 615  
 616      function strip_clf ($text = "") {
 617          // Strips \r\n from server responses
 618  
 619          if(empty($text))
 620              return $text;
 621          else {
 622              $stripped = str_replace(array("\r","\n"),'',$text);
 623              return $stripped;
 624          }
 625      }
 626  
 627      function parse_banner ( $server_text ) {
 628          $outside = true;
 629          $banner = "";
 630          $length = strlen($server_text);
 631          for($count =0; $count < $length; $count++)
 632          {
 633              $digit = substr($server_text,$count,1);
 634              if(!empty($digit))             {
 635                  if( (!$outside) && ($digit != '<') && ($digit != '>') )
 636                  {
 637                      $banner .= $digit;
 638                  }
 639                  if ($digit == '<')
 640                  {
 641                      $outside = false;
 642                  }
 643                  if($digit == '>')
 644                  {
 645                      $outside = true;
 646                  }
 647              }
 648          }
 649          $banner = $this->strip_clf($banner);    // Just in case
 650          return "<$banner>";
 651      }
 652  
 653  }   // End class
 654  
 655  // For php4 compatibility
 656  if (!function_exists("stripos")) {
 657      function stripos($haystack, $needle){
 658          return strpos($haystack, stristr( $haystack, $needle ));
 659      }
 660  }


Generated: Sat Jul 4 01:00:03 2020 Cross-referenced by PHPXref 0.7.1