diff --git a/plugins/libkolab/bin/modcache.sh b/plugins/libkolab/bin/modcache.sh index 2e671b0c..fc87b1fa 100755 --- a/plugins/libkolab/bin/modcache.sh +++ b/plugins/libkolab/bin/modcache.sh @@ -1,259 +1,272 @@ #!/usr/bin/env php * * Copyright (C) 2012-2014, Kolab Systems AG * * 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 . */ define('INSTALL_PATH', __DIR__ . '/../../../'); ini_set('display_errors', 1); require_once INSTALL_PATH . 'program/include/clisetup.php'; function print_usage() { print "Usage: modcache.sh ACTION [OPTIONS] [USERNAME ARGS ...]\n"; print "Possible actions are: expunge, clear, prewarm\n"; print "-a, --all Clear/expunge all caches\n"; print "-h, --host IMAP host name\n"; print "-u, --user IMAP user name to authenticate\n"; print "-t, --type Object types to clear/expunge cache\n"; print "-l, --limit Limit the number of records to be expunged\n"; } // read arguments $opts = rcube_utils::get_opt(array( 'a' => 'all', 'h' => 'host', 'u' => 'user', 'p' => 'password', 't' => 'type', 'l' => 'limit', 'v' => 'verbose', )); $opts['username'] = !empty($opts[1]) ? $opts[1] : $opts['user']; $action = $opts[0]; $rcmail = rcube::get_instance(rcube::INIT_WITH_DB | rcube::INIT_WITH_PLUGINS); // Make --host argument optional where the default_host is a simple string if (empty($opts['host'])) { $opts['host'] = imap_host(); } // connect to database $db = $rcmail->get_dbh(); $db->db_connect('w'); if (!$db->is_connected() || $db->is_error()) die("No DB connection\n"); ini_set('display_errors', 1); // All supported object types $all_types = array('contact','configuration','event','file','journal','note','task'); /* * Script controller */ switch (strtolower($action)) { /* * Clear/expunge all cache records */ case 'expunge': $folder_types = $opts['type'] ? explode(',', $opts['type']) : $all_types; $folder_types_db = array_map(array($db, 'quote'), $folder_types); $expire = strtotime(!empty($opts[2]) ? $opts[2] : 'now - 10 days'); $sql_where = "type IN (" . join(',', $folder_types_db) . ")"; if ($opts['username']) { $sql_where .= ' AND resource LIKE ?'; } $sql_query = "DELETE FROM %s WHERE folder_id IN (SELECT folder_id FROM kolab_folders WHERE $sql_where) AND created <= " . $db->quote(date('Y-m-d 00:00:00', $expire)); if ($opts['limit']) { $sql_query .= ' LIMIT ' . intval($opts['limit']); } foreach ($folder_types as $type) { $table_name = 'kolab_cache_' . $type; $db->query(sprintf($sql_query, $table_name), resource_prefix($opts).'%'); echo $db->affected_rows() . " records deleted from '$table_name'\n"; } $db->query("UPDATE kolab_folders SET ctag='' WHERE $sql_where", resource_prefix($opts).'%'); break; case 'clear': $folder_types = $opts['type'] ? explode(',', $opts['type']) : $all_types; $folder_types_db = array_map(array($db, 'quote'), $folder_types); if ($opts['all']) { $sql_query = "DELETE FROM kolab_folders WHERE 1"; } else if ($opts['username']) { $sql_query = "DELETE FROM kolab_folders WHERE type IN (" . join(',', $folder_types_db) . ") AND resource LIKE ?"; } if ($sql_query) { $db->query($sql_query, resource_prefix($opts).'%'); echo $db->affected_rows() . " records deleted from 'kolab_folders'\n"; } break; /* * Prewarm cache by synchronizing objects for the given user */ case 'prewarm': // make sure libkolab classes are loaded $rcmail->plugins->load_plugin('libkolab'); if (authenticate($opts)) { $folder_types = $opts['type'] ? explode(',', $opts['type']) : $all_types; foreach ($folder_types as $type) { // sync every folder of the given type foreach (kolab_storage::get_folders($type) as $folder) { echo "Synching " . $folder->name . " ($type) ... "; echo $folder->count($type) . "\n"; // also sync distribution lists in contact folders if ($type == 'contact') { echo "Synching " . $folder->name . " (distribution-list) ... "; echo $folder->count('distribution-list') . "\n"; } } } } else die("Authentication failed for " . $opts['user']); break; /** * Update the cache meta columns from the serialized/xml data * (might be run after a schema update) */ case 'update': // make sure libkolab classes are loaded $rcmail->plugins->load_plugin('libkolab'); $folder_types = $opts['type'] ? explode(',', $opts['type']) : $all_types; foreach ($folder_types as $type) { $class = 'kolab_storage_cache_' . $type; $sql_result = $db->query("SELECT folder_id FROM kolab_folders WHERE type=? AND synclock = 0", $type); while ($sql_result && ($sql_arr = $db->fetch_assoc($sql_result))) { $folder = new $class; $folder->select_by_id($sql_arr['folder_id']); echo "Updating " . $sql_arr['folder_id'] . " ($type) "; foreach ($folder->select() as $object) { $object['_formatobj']->to_array(); // load data $folder->save($object['_msguid'], $object, $object['_msguid']); echo "."; } echo "done.\n"; } } break; /* * Unknown action => show usage */ default: print_usage(); exit; } /** * Compose cache resource URI prefix for the given user credentials */ function resource_prefix($opts) { return 'imap://' . str_replace('%', '\\%', urlencode($opts['username'])) . '@' . $opts['host'] . '/'; } /** * Authenticate to the IMAP server with the given user credentials */ function authenticate(&$opts) { global $rcmail; // prompt for password if (empty($opts['password']) && ($opts['username'] || $opts['user'])) { $opts['password'] = rcube_utils::prompt_silent("Password: "); } // simulate "login as" feature if ($opts['user'] && $opts['user'] != $opts['username']) $_POST['_loginas'] = $opts['username']; else if (empty($opts['user'])) $opts['user'] = $opts['username']; + // parse $host URL + $url = parse_url(trim($opts['host'])); + if (!empty($url['host'])) { + $imap_host = $url['host']; + $imap_ssl = isset($url['scheme']) && in_array($url['scheme'], array('ssl','imaps','tls')) ? $url['scheme'] : false; + $imap_port = isset($url['port']) ? $url['port'] : ($imap_ssl && $imap_ssl != 'tls' ? 993 : 143); + } + else { + $imap_host = trim($opts['host']); + $imap_port = 143; + $imap_ssl = false; + } + // let the kolab_auth plugin do its magic $auth = $rcmail->plugins->exec_hook('authenticate', array( - 'host' => trim($opts['host']), + 'host' => $imap_host, 'user' => trim($opts['user']), 'pass' => $opts['password'], 'cookiecheck' => false, 'valid' => !empty($opts['user']) && !empty($opts['host']), )); if ($auth['valid']) { $storage = $rcmail->get_storage(); - if ($storage->connect($auth['host'], $auth['user'], $auth['pass'], 143, false)) { + if ($storage->connect($imap_host, $auth['user'], $auth['pass'], $imap_port, $imap_ssl)) { if ($opts['verbose']) echo "IMAP login succeeded.\n"; if (($user = rcube_user::query($opts['username'], $auth['host'])) && $user->ID) $rcmail->user = $user; } else die("Login to IMAP server failed!\n"); } else { die("Invalid login credentials!\n"); } return $auth['valid']; } function imap_host() { global $rcmail; $default_host = $rcmail->config->get('default_host'); if (is_array($default_host)) { $key = key($default_host); $imap_host = is_numeric($key) ? $default_host[$key] : $key; } else { $imap_host = $default_host; } // strip protocol prefix $uri = parse_url($imap_host); if (!empty($uri['host'])) { return $uri['host']; } }