1
0
mirror of https://github.com/vrana/adminer.git synced 2025-08-07 23:27:17 +02:00

IMAP: New driver created just for fun

This commit is contained in:
Jakub Vrana
2025-03-18 11:28:20 +01:00
parent 5069e5a400
commit ebb31bdac8
2 changed files with 236 additions and 1 deletions

View File

@@ -6,7 +6,7 @@ to the target server. **Adminer Editor** offers data manipulation for end-users.
https://www.adminer.org/
- **Supports:** MySQL, MariaDB, PostgreSQL, CockroachDB, SQLite, MS SQL, Oracle
- **Plugins for:** Elasticsearch, SimpleDB, MongoDB, Firebird, ClickHouse
- **Plugins for:** Elasticsearch, SimpleDB, MongoDB, Firebird, ClickHouse, IMAP
- **Requirements:** PHP 5.3+
## Screenshot

235
plugins/drivers/imap.php Normal file
View File

@@ -0,0 +1,235 @@
<?php
/** Experimental driver for IMAP created just for fun. Features:
* - list mailboxes with number of messages (Rows) and unread messages (Data Free)
* - list messages in each mailbox - limit and offset works but there's no search and order
* - for each message, there's subject, from, to, date and some flags
* - editing the message shows some other information
* - inserting, deleting or updating the message does nothing
*/
namespace Adminer;
add_driver("imap", "IMAP");
if (isset($_GET["imap"])) {
define('Adminer\DRIVER', "imap");
if (extension_loaded("imap")) {
class Db {
public $extension = "IMAP";
public $error;
public $server_info = "?"; // imap_mailboxmsginfo() doesn't return anything useful
private $mailbox;
private $imap;
function connect($server, $username, $password) {
$this->mailbox = "{" . "$server:993/ssl}"; // Adminer disallows specifying privileged port in server name
$this->imap = @imap_open($this->mailbox, $username, $password, 0, 1);
if (!$this->imap) {
$this->error = imap_last_error();
}
return $this->imap;
}
function select_db($database) {
return ($database == "imap");
}
function query($query, $unbuffered = false) {
preg_match('~\sFROM (\w+).*?(?:\sWHERE uid = (\d+))?.*?(?:\sLIMIT (\d+)(?:\sOFFSET (\d+))?)?~s', $query, $match);
list(, $table, $uid, $limit, $offset) = $match;
if ($uid) {
$return = array((array) imap_fetchstructure($this->imap, $uid, FT_UID));
} else {
imap_reopen($this->imap, "$this->mailbox$table");
$check = imap_check($this->imap);
$range = ($offset + 1) . ":" . ($limit ? min($check->Nmsgs, $offset + $limit) : $check->Nmsgs);
$return = array();
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_merge(array_fill_keys(array_keys(fields($table)), null), (array) $row);
}
}
return new Result($return);
}
function quote($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_free" => $return->unseen,
);
}
}
class Result {
public $num_rows;
private $result;
function __construct($result) {
$this->result = $result;
$this->num_rows = count($result);
}
function fetch_assoc() {
$row = current($this->result);
next($this->result);
return $row;
}
}
}
class Driver extends SqlDriver {
static $possibleDrivers = array("imap");
static $jush = "imap";
public $editFunctions = array(array("json"));
}
function logged_user() {
return $_GET["username"];
}
function get_databases($flush) {
return array("imap");
}
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 !== null ? $separator . "LIMIT $limit" . ($offset ? " OFFSET $offset" : "") : "");
}
function idf_escape($idf) {
return $idf; //! maybe {}
}
function table($idf) {
return idf_escape($idf);
}
function foreign_keys($table) {
return array();
}
function tables_list() {
global $connection;
return $connection->tables_list();
}
function table_status($name = "", $fast = false) {
global $connection;
if ($name != "") {
return $connection->table_status($name, $fast);
}
$return = array();
foreach (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() {
global $connection;
return h($connection->error);
}
function is_view($table_status) {
return false;
}
function found_rows($table_status, $where) {
return $table_status["Rows"];
}
function connect($credentials) {
$connection = new Db;
if ($connection->connect($credentials[0], $credentials[1], $credentials[2])) {
return $connection;
}
return $connection->error;
}
function support($feature) {
return preg_match("~^()$~", $feature);
}
}