10) { // exit if nothing happened for 10 seconds error_log("timeout 1"); break; } else if($idle_time > 2) { // start napping when the client is too slow error_log("timeout 2"); sleep(1); } } else { break; } } if($e) { break; } if($read_buffer) { if(preg_match('/(.*?)(?:\s+(.*?))?[\r\n]+/', $read_buffer, $matches)) { $read_buffer = substr($read_buffer, strlen($matches[0])); $tmatches = array_map('trim', $matches); if(DEBUG===true) echo(" [READING FROM CLIENT] ".$tmatches[0]).PHP_EOL; $command = $matches[1]; $argument = $matches[2]; switch($command) { case 'CAPA': $write_buffer = "+OK Capability list follows\r\n"; $write_buffer.= implode("\r\n",["USER","PASS","UIDL"]); $write_buffer .= "\r\n.\r\n"; break; break; case 'USER': $username = $argument; $write_buffer .= "+OK $username is welcome here\r\n"; $messages = getEmailsOfEmail($username); if(DEBUG===true) echo(" [+] Loaded ".count($messages)." for email $username").PHP_EOL; break; case 'PASS': // we'll accept any password $message_count = count($messages); $write_buffer .= "+OK mailbox has $message_count message(s)\r\n"; break; case 'QUIT': $write_buffer .= "+OK POP3 server signing off\r\n"; $active = false; break; case 'STAT': $message_count = count($messages); $mailbox_size = 0; foreach($messages as $message) { $mailbox_size += $message['maillen']; } $write_buffer .= "+OK $message_count $mailbox_size\r\n"; break; case 'LIST': $start_index = (int) $argument; $message_count = count($messages) - $start_index; $total_size = 0; for($i = $start_index; $i < count($messages); $i++) { $msg = array_values(array_slice($messages, $i, 1, true))[0]; $total_size += $msg['maillen']; } $write_buffer .= "+OK $message_count messages ($total_size octets)\r\n"; for($i = $start_index; $i < count($messages); $i++) { $msg = array_values(array_slice($messages, $i, 1, true))[0]; $message_id = $i + 1; $message_size = $msg['maillen']; $write_buffer .= "$message_id $message_size\r\n"; } $write_buffer .= ".\r\n"; break; case 'UIDL': $start_index = (int) $argument; $message_count = count($messages) - $start_index; $write_buffer .= "+OK $message_count messages\r\n"; for($i = $start_index; $i < count($messages); $i++) { $message_id = $i + 1; $msg = array_values(array_slice($messages, $i, 1, true))[0]; $write_buffer .= "$message_id ".$msg['md5']."\r\n"; } $write_buffer .= ".\r\n"; break; case 'RETR': $message_id = (int) $argument; $message = array_values(array_slice($messages, ($message_id-1), 1, true))[0]; $message_size = $message['maillen']; $write_buffer .= "+OK $message_size octets\r\n"; $write_buffer .= getRawEmail($message['email'],$message['id'])."\r\n"; $write_buffer .= ".\r\n"; break; case 'DELE': $message_id = (int) $argument; $msg = array_values(array_slice($messages, ($message_id-1), 1, true))[0]; deleteEmail($msg['email'],$msg['id']); $write_buffer .= "+OK\r\n"; break; case 'NOOP': $write_buffer .= "+OK\r\n"; break; case 'LAST': $message_count = count($messages) - $start_index; $write_buffer .= "+OK $message_count\r\n"; break; case 'RSET': $write_buffer .= "+OK\r\n"; break; default: $write_buffer .= "-ERR Unknown command '$command'\r\n"; } if(DEBUG===true) echo(" [MY ANSWER] ".trim($write_buffer)).PHP_EOL; if(!$active && DEBUG===true) echo("[-] Client disconnected").PHP_EOL; } } } else { break; } } }