2013-11-07 14:47:23 +01:00
#!/usr/bin/env php
2012-06-13 17:57:27 +02:00
<?php
/**
* Kolab storage cache modification script
*
2013-10-15 10:05:32 +02:00
* @version 3.1
2012-06-13 17:57:27 +02:00
* @author Thomas Bruederli <bruederli@kolabsys.com>
*
2014-02-10 11:46:50 +01:00
* Copyright ( C) 2012-2014, Kolab Systems AG <contact@kolabsys.com>
2012-06-13 17:57:27 +02:00
*
* 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 <http://www.gnu.org/licenses/>.
*/
define( 'INSTALL_PATH' , realpath( '.' ) . '/' ) ;
ini_set( 'display_errors' , 1) ;
if ( !file_exists( INSTALL_PATH . 'program/include/clisetup.php' ) )
die( "Execute this from the Roundcube installation dir!\n\n" ) ;
require_once INSTALL_PATH . 'program/include/clisetup.php' ;
function print_usage( )
{
2012-06-20 15:42:16 +02:00
print "Usage: modcache.sh [OPTIONS] ACTION [USERNAME ARGS ...]\n" ;
print "Possible actions are: expunge, clear, prewarm\n" ;
2012-06-13 17:57:27 +02:00
print "-a, --all Clear/expunge all caches\n" ;
print "-h, --host IMAP host name\n" ;
2012-06-20 15:42:16 +02:00
print "-u, --user IMAP user name to authenticate\n" ;
2012-06-13 17:57:27 +02:00
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 = get_opt( array(
'a' = > 'all' ,
'h' = > 'host' ,
'u' = > 'user' ,
'p' = > 'password' ,
't' = > 'type' ,
'l' = > 'limit' ,
'v' = > 'verbose' ,
) ) ;
2012-06-20 15:42:16 +02:00
$opts [ 'username' ] = !empty( $opts [ 1] ) ? $opts [ 1] : $opts [ 'user' ] ;
2012-06-13 17:57:27 +02:00
$action = $opts [ 0] ;
2013-10-15 10:05:32 +02:00
$rcmail = rcube::get_instance( rcube::INIT_WITH_DB | rcube::INIT_WITH_PLUGINS) ;
// connect to database
$db = $rcmail ->get_dbh( ) ;
$db ->db_connect( 'w' ) ;
if ( !$db ->is_connected( ) || $db ->is_error( ) )
die( "No DB connection\n" ) ;
2012-06-13 17:57:27 +02:00
2014-02-10 11:46:50 +01:00
ini_set( 'display_errors' , 1) ;
2012-06-13 17:57:27 +02:00
/*
* Script controller
*/
switch ( strtolower( $action ) ) {
/*
* Clear/expunge all cache records
*/
case 'expunge' :
2013-10-15 10:05:32 +02:00
$folder_types = $opts [ 'type' ] ? explode( ',' , $opts [ 'type' ] ) : array( 'contact' ,'configuration' ,'event' ,'file' ,'journal' ,'note' ,'task' ) ;
$folder_types_db = array_map( array( $db , 'quote' ) , $folder_types ) ;
2012-06-20 15:42:16 +02:00
$expire = strtotime( !empty( $opts [ 2] ) ? $opts [ 2] : 'now - 10 days' ) ;
2013-10-15 10:05:32 +02:00
$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 ) ) ;
2012-06-13 17:57:27 +02:00
if ( $opts [ 'limit' ] ) {
2013-10-15 10:05:32 +02:00
$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 " ;
2012-06-13 17:57:27 +02:00
}
2013-10-15 10:05:32 +02:00
$db ->query( " UPDATE kolab_folders SET ctag='' WHERE $sql_where " , resource_prefix( $opts ) .'%' ) ;
break;
2012-06-13 17:57:27 +02:00
2013-10-15 10:05:32 +02:00
case 'clear' :
$folder_types = $opts [ 'type' ] ? explode( ',' , $opts [ 'type' ] ) : array( 'contact' ,'configuration' ,'event' ,'file' ,'journal' ,'note' ,'task' ) ;
2012-06-13 17:57:27 +02:00
$folder_types_db = array_map( array( $db , 'quote' ) , $folder_types ) ;
if ( $opts [ 'all' ] ) {
2013-10-15 10:05:32 +02:00
$sql_query = "DELETE FROM kolab_folders WHERE 1" ;
2012-06-13 17:57:27 +02:00
}
2012-06-20 15:42:16 +02:00
else if ( $opts [ 'username' ] ) {
2013-10-15 10:05:32 +02:00
$sql_query = "DELETE FROM kolab_folders WHERE type IN (" . join( ',' , $folder_types_db ) . ") AND resource LIKE ?" ;
2012-06-13 17:57:27 +02:00
}
if ( $sql_query ) {
$db ->query( $sql_query . $sql_add , resource_prefix( $opts ) .'%' ) ;
2013-10-15 10:05:32 +02:00
echo $db ->affected_rows( ) . " records deleted from 'kolab_folders'\n" ;
2012-06-13 17:57:27 +02:00
}
break;
/*
* Prewarm cache by synchronizing objects for the given user
*/
case 'prewarm' :
2012-06-20 15:42:16 +02:00
// make sure libkolab classes are loaded
$rcmail ->plugins->load_plugin( 'libkolab' ) ;
if ( authenticate( $opts ) ) {
2013-10-15 10:05:32 +02:00
$folder_types = $opts [ 'type' ] ? explode( ',' , $opts [ 'type' ] ) : array( 'contact' ,'configuration' ,'event' ,'file' ,'task' ) ;
2012-06-20 15:42:16 +02:00
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' ] ) ;
2012-06-13 17:57:27 +02:00
break;
2014-02-10 11:46:50 +01:00
/**
* 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' ] ) : array( 'contact' ,'configuration' ,'event' ,'file' ,'task' ) ;
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;
2012-06-13 17:57:27 +02:00
/*
* Unknown action = > show usage
*/
default:
print_usage( ) ;
exit;
}
/**
* Compose cache resource URI prefix for the given user credentials
*/
function resource_prefix( $opts )
{
2013-10-15 14:11:30 +02:00
return 'imap://' . str_replace( '%' , '\\%' , urlencode( $opts [ 'username' ] ) ) . '@' . $opts [ 'host' ] . '/' ;
2012-06-13 17:57:27 +02:00
}
/**
2012-06-20 15:42:16 +02:00
* Authenticate to the IMAP server with the given user credentials
2012-06-13 17:57:27 +02:00
*/
function authenticate( & $opts )
{
global $rcmail ;
2012-06-20 15:42:16 +02:00
2012-06-13 17:57:27 +02:00
// prompt for password
2012-06-20 15:42:16 +02:00
if ( empty( $opts [ 'password' ] ) && ( $opts [ 'username' ] || $opts [ 'user' ] ) ) {
2012-06-13 17:57:27 +02:00
$opts [ 'password' ] = prompt_silent( "Password: " ) ;
}
2012-06-20 15:42:16 +02:00
// simulate "login as" feature
if ( $opts [ 'user' ] && $opts [ 'user' ] != $opts [ 'username' ] )
$_POST [ '_loginas' ] = $opts [ 'username' ] ;
else if ( empty( $opts [ 'user' ] ) )
$opts [ 'user' ] = $opts [ 'username' ] ;
// let the kolab_auth plugin do its magic
2012-06-13 17:57:27 +02:00
$auth = $rcmail ->plugins->exec_hook( 'authenticate' , array(
'host' = > trim( $opts [ 'host' ] ) ,
'user' = > trim( $opts [ 'user' ] ) ,
'pass' = > $opts [ 'password' ] ,
'cookiecheck' = > false,
'valid' = > !empty( $opts [ 'user' ] ) && !empty( $opts [ 'host' ] ) ,
) ) ;
if ( $auth [ 'valid' ] ) {
2012-06-20 15:42:16 +02:00
$storage = $rcmail ->get_storage( ) ;
if ( $storage ->connect( $auth [ 'host' ] , $auth [ 'user' ] , $auth [ 'pass' ] , 143, false ) ) {
if ( $opts [ 'verbose' ] )
echo "IMAP login succeeded.\n" ;
if ( ( $user = rcube_user::query( $opts [ 'username' ] , $auth [ 'host' ] ) ) && $user ->ID)
$rcmail ->set_user( $user ) ;
2012-06-13 17:57:27 +02:00
}
2012-06-20 15:42:16 +02:00
else
die( "Login to IMAP server failed!\n" ) ;
2012-06-13 17:57:27 +02:00
}
else {
die( "Invalid login credentials!\n" ) ;
}
return $auth [ 'valid' ] ;
}