diff --git a/bin/inspect.php b/bin/inspect.php index a7c33e0..00075fc 100755 --- a/bin/inspect.php +++ b/bin/inspect.php @@ -1,215 +1,235 @@ #!/usr/bin/env php | | | | This program is free software: you can redistribute it and/or modify | | it under the terms of the GNU Affero General Public License as published | | by the Free Software Foundation, either version 3 of the License, or | | (at your option) any later version. | | | | This program is distributed in the hope that it will be useful, | | but WITHOUT ANY WARRANTY; without even the implied warranty of | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | GNU Affero General Public License for more details. | | | | You should have received a copy of the GNU Affero General Public License | | along with this program. If not, see | +--------------------------------------------------------------------------+ | Author: Christian Mollekopf | +--------------------------------------------------------------------------+ */ define('RCUBE_INSTALL_PATH', realpath(dirname(__FILE__) . '/../') . '/'); define('RCUBE_PLUGINS_DIR', RCUBE_INSTALL_PATH . 'lib/plugins/'); // Define include path $include_path = RCUBE_INSTALL_PATH . 'lib' . PATH_SEPARATOR; $include_path .= RCUBE_INSTALL_PATH . 'lib/ext' . PATH_SEPARATOR; $include_path .= ini_get('include_path'); set_include_path($include_path); // include composer autoloader (if available) if (@file_exists(RCUBE_INSTALL_PATH . 'vendor/autoload.php')) { require RCUBE_INSTALL_PATH . 'vendor/autoload.php'; } // include global functions from Roundcube Framework require_once 'Roundcube/bootstrap.php'; $opts = rcube_utils::get_opt([ 'e' => 'email', 'p' => 'adminpassword', 'd' => 'debug', ]); if (empty($opts['email'])) { rcube::raise_error("Email address not specified (--email).", false, true); } $email = $opts['email']; if (empty($opts['adminpassword'])) { rcube::raise_error("Admin password not specified (--adminpassword).", false, true); } $password = $opts['adminpassword']; $rcube = rcube::get_instance(); $default_port = $rcube->config->get('default_port', 143); $default_host = $rcube->config->get('default_host'); $user = "cyrus-admin"; $imap = new \rcube_imap_generic(); $options['auth_cid'] = $user; $options['auth_pw'] = $password; $options['auth_type'] = 'PLAIN'; $options['port'] = $default_port; $options['socket_options'] = [ 'ssl' => [ 'verify_peer_name' => false, 'verify_peer' => false, 'allow_self_signed' => true ] ]; ini_set('display_errors', 1); error_reporting(E_ALL); $debug = !empty($opts['debug']); $imap->setDebug($debug); if (!$imap->connect($default_host, $email, $password, $options)) { rcube::raise_error("Failed to connect to imap.", false, true); } $rcube = \rcube::get_instance(); $db = $rcube->get_dbh(); $select = $db->query( "SELECT `user_id` FROM `users`" . " WHERE `username` = ?" . " ORDER BY `user_id` DESC", \strtolower($email) ); if ($data = $db->fetch_assoc($select)) { $userid = $data['user_id']; } else { rcube::raise_error("User not found: $email.", false, true); } print("Found the user with id: $userid\n"); $devicesSelect = $db->query( "SELECT `id`, `deviceid`, `devicetype` FROM `syncroton_device`" . " WHERE `owner_id` = ?", $userid ); $result = []; while ($data = $db->fetch_assoc($devicesSelect)) { $deviceid = $data["deviceid"]; $device_id = $data["id"]; $result[$device_id]['deviceid'] = $deviceid; $result[$device_id]['devicetype'] = $data["devicetype"]; $select = $db->limitquery( "SELECT `counter`, `lastsync` FROM `syncroton_synckey`" . " WHERE `device_id` = ? AND `type` = 'FolderSync'" . " ORDER BY `counter` DESC", 0, 1, $device_id ); if ($data = $db->fetch_assoc($select)) { $result[$device_id]['FolderSync'] = [ "counter" => $data['counter'], "lastsync" => $data['lastsync'], ]; } else { echo("Synckey not found.\n"); } $folderSelect = $db->query( "SELECT * FROM `syncroton_folder`" . " WHERE `device_id` = ?", $device_id ); while ($folder = $db->fetch_assoc($folderSelect)) { $select = $db->limitquery( "SELECT `counter`, `lastsync`, `extra_data` FROM `syncroton_synckey`" . " WHERE `device_id` = ? AND `type` = ?" . " ORDER BY `counter` DESC", 0, 1, $device_id, $folder['id'] ); if ($data = $db->fetch_assoc($select)) { $result[$device_id]['folders'][$folder['id']] = [ "counter" => $data['counter'], "lastsync" => $data['lastsync'], + "lastfiltertype" => $data['lastfiltertype'] ?? null, "modseq" => $data['extra_data'] ? json_decode($data['extra_data'])->modseq : null, ]; } $result[$device_id]['folders'][$folder['id']]['name'] = $folder['displayname']; $imap->select($folder['displayname']); $result[$device_id]['folders'][$folder['id']]['imapModseq'] = $imap->data['HIGHESTMODSEQ'] ?? null; $index = $imap->search($folder['displayname'], 'ALL UNDELETED', false, ['COUNT']); if (!$index->is_error()) { $result[$device_id]['folders'][$folder['id']]['imapMessagecount'] = $index->count(); } $select = $db->query( "SELECT count(*) FROM `syncroton_content`" . " WHERE `device_id` = ? AND `folder_id` = ?", $device_id, $folder['id'] ); if ($data = $db->fetch_assoc($select)) { $result[$device_id]['folders'][$folder['id']]['contentCount'] = array_values($data)[0]; } } } if ($debug) { var_export($result); } function println($output) { print("{$output}\n"); } +function filterType($value) { + if (!$value) { + return "No filter"; + } + switch($value) { + case 0: return "No filter"; + case 1: return "1 day"; + case 2: return "3 days"; + case 3: return "1 week"; + case 4: return "2 weeks"; + case 5: return "1 month"; + case 6: return "3 months"; + case 7: return "6 months"; + case 8: return "Filter by incomplete tasks"; + } + return "Unknown value: $value"; +} + println(""); foreach ($result as $deviceId => $values) { println("Device: $deviceId"); println(" Last folder sync: " . $values['FolderSync']['lastsync']); println(" Folder sync count: " . $values['FolderSync']['counter']); println(" Folders:"); foreach ($values['folders'] ?? [] as $folderId => $folder) { println(" " . $folder['name'] . " ($folderId)"); $messageCount = $folder['contentCount']; $totalCount = $folder['imapMessagecount']; $modseq = $folder['modseq'] ?? "none"; $imapModseq = $folder['imapModseq']; // We're not using modseq for groupware folders if ($messageCount == $totalCount && ($modseq == "none" || $modseq == $imapModseq)) { println(" Status: Fully Synced ($messageCount messages)"); } else { println(" Status: Incomplete ($messageCount/$totalCount messages)"); println(" Modseq: " . $modseq . "/" . $imapModseq); } println(" Last sync: " . ($folder['lastsync'] ?? "None")); println(" Number of syncs: " . ($folder['counter'] ?? "None")); + println(" Filter type: " . filterType($folder['lastfiltertype'] ?? null)); println(""); } }