[ Index ]

WordPress Cross Reference

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


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu