[ Index ]

PHP Cross Reference of WordPress Trunk (Updated Daily)

Search

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


Generated : Thu Apr 25 08:20:02 2024 Cross-referenced by PHPXref