PageRenderTime 39ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/class-pop3.php

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