mailbox = "{" . "$server:993/ssl}"; // Adminer disallows specifying privileged port in server name $this->imap = @imap_open($this->mailbox, $username, $password, OP_HALFOPEN, 1); return ($this->imap ? '' : imap_last_error()); } function select_db($database) { return ($database == "mail"); } function query($query, $unbuffered = false) { if (preg_match('~DELETE FROM "(.+?)"~', $query)) { preg_match_all('~"uid" = (\d+)~', $query, $matches); return imap_delete($this->imap, implode(",", $matches[1]), FT_UID); } elseif (preg_match('~^SELECT COUNT\(\*\)\sFROM "(.+?)"~s', $query, $match)) { $status = table_status1($match[1]); return new Result(array(array($status["Rows"]))); } elseif (preg_match('~^SELECT (.+)\sFROM "(.+?)"(?:\sWHERE "uid" = (\d+))?.*?(?:\sLIMIT (\d+)(?:\sOFFSET (\d+))?)?~s', $query, $match)) { list(, $columns, $table, $uid, $limit, $offset) = $match; imap_reopen($this->imap, $this->mailbox . $table); if ($uid) { $return = array((array) imap_fetchstructure($this->imap, $uid, FT_UID)); } else { $count = imap_num_msg($this->imap); $range = ($offset + 1) . ":" . ($limit ? min($count, $offset + $limit) : $count); $return = array(); $fields = fields($table); $columns = ($columns == "*" ? $fields : array_flip(explode(", ", $columns))); $empty = array_fill_keys(array_keys($fields), null); foreach (imap_fetch_overview($this->imap, $range) as $row) { // imap_utf8 doesn't work with some strings $row->subject = iconv_mime_decode($row->subject, 2, "utf-8"); $row->from = iconv_mime_decode($row->from, 2, "utf-8"); $row->to = iconv_mime_decode($row->to, 2, "utf-8"); $row->udate = gmdate("Y-m-d H:i:s", $row->udate); $return[] = array_intersect_key(array_merge($empty, (array) $row), $columns); } } return new Result($return); } return false; } function quote($string): string { return $string; } function tables_list() { static $return; if ($return === null) { $return = array(); foreach (imap_list($this->imap, $this->mailbox, "*") as $val) { $return[substr($val, strlen($this->mailbox))] = "table"; } } return array_reverse($return); } function table_status($name, $fast) { if ($fast) { return array("Name" => $name); } $return = imap_status($this->imap, $this->mailbox . $name, SA_ALL); return array( "Name" => $name, "Rows" => $return->messages, "Auto_increment" => $return->uidnext, "Data_length" => $return->messages, // this is used on database overview "Data_free" => $return->unseen, ); } function create($name) { return imap_createmailbox($this->imap, $this->mailbox . $name); } function drop($name) { return imap_deletemailbox($this->imap, $this->mailbox . $name); } function expunge() { return imap_expunge($this->imap); } } class Result { public $num_rows; private $result; private $fields; function __construct($result) { $this->result = $result; $this->num_rows = count($result); $this->fields = array_keys(idx($result, 0, array())); } function fetch_assoc() { $row = current($this->result); next($this->result); return $row; } function fetch_row() { $row = $this->fetch_assoc(); return ($row ? array_values($row) : false); } function fetch_field(): \stdClass { $field = current($this->fields); next($this->fields); return ($field != '' ? (object) array('name' => $field, 'type' => 15, 'charsetnr' => 0) : false); } } } class Driver extends SqlDriver { static $extensions = array("imap"); static $jush = "imap"; public $insertFunctions = array("json"); } function logged_user() { return $_GET["username"]; } function get_databases($flush) { return array("mail"); } function collations() { return array(); } function db_collation($db, $collations) { } function information_schema($db) { } function indexes($table, $connection2 = null) { return array(array("type" => "PRIMARY", "columns" => array("uid"))); } function fields($table) { $return = array(); foreach ( array( // taken from imap_fetch_overview 'subject' => 'the messages subject', 'from' => 'who sent it', 'to' => 'recipient', 'date' => 'when was it sent', 'message_id' => 'Message-ID', 'references' => 'is a reference to this message id', 'in_reply_to' => 'is a reply to this message id', 'size' => 'size in bytes', 'uid' => 'UID the message has in the mailbox', 'msgno' => 'message sequence number in the mailbox', 'recent' => 'flagged as recent', 'flagged' => 'flagged', 'answered' => 'flagged as answered', 'deleted' => 'flagged for deletion', 'seen' => 'flagged as already read', 'draft' => 'flagged as being a draft', 'udate' => 'the GMT time of the arrival date', ) as $name => $comment ) { $return[$name] = array( "field" => $name, "type" => (preg_match('~^(size|uid|msgno)$~', $name) ? "int" : ""), "privileges" => array("select" => 1), "comment" => $comment, ); } return $return; } function convert_field($field) { } function unconvert_field($field, $return) { return $return; } function limit($query, $where, $limit, $offset = 0, $separator = " ") { return " $query$where" . ($limit ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : ""); } function idf_escape($idf) { return '"' . str_replace('"', '""', $idf) . '"'; } function table($idf) { return idf_escape($idf); } function foreign_keys($table) { return array(); } function tables_list() { return connection()->tables_list(); } function table_status($name = "", $fast = false) { $return = array(); foreach (($name != "" ? array($name => 1) : tables_list()) as $table => $type) { $return[$table] = connection()->table_status($table, $fast); } return $return; } function count_tables($databases) { return array(reset($databases) => count(tables_list())); } function error() { return h(connection()->error); } function is_view($table_status) { return false; } function found_rows($table_status, $where) { return $table_status["Rows"]; } function fk_support($table_status) { } function alter_table($table, $name, $fields, $foreign, $comment, $engine, $collation, $auto_increment, $partitioning) { return connection()->create($name); } function drop_tables($tables) { $return = true; foreach ($tables as $name) { $return = $return && connection()->drop($name); } return $return; } function truncate_tables($tables) { return connection()->expunge(); } function support($feature) { return false; } }