Import Ruty

This commit is contained in:
2024-03-11 00:58:34 +01:00
parent 34a31bb184
commit 985f1ab418
618 changed files with 225414 additions and 0 deletions
+31
View File
@@ -0,0 +1,31 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Finally remove all db records marked as deleted some time ago |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
if (!empty($_SERVER['argv'][1])) {
$days = intval($_SERVER['argv'][1]);
}
else {
$days = 7;
}
rcmail_utils::db_clean($days);
+44
View File
@@ -0,0 +1,44 @@
#!/bin/sh
set -e
PWD=`dirname "$0"`
do_shrink() {
rm -f "$2"
csso $1 -o $2 --no-restructure
}
if which csso > /dev/null 2>&1; then
:
else
echo "csso not found. Please install e.g. 'npm install -g csso-cli'."
exit 1
fi
# compress single file from argument
if [ $# -gt 0 ]; then
CSS_FILE="$1"
echo "Shrinking $CSS_FILE"
minfile=`echo $CSS_FILE | sed -e 's/\.css$/\.min\.css/'`
do_shrink "$CSS_FILE" "$minfile"
exit
fi
DIRS="$PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/* $PWD/../plugins/*/themes/*"
# default: compress application scripts
for dir in $DIRS; do
for file in $dir/*.css; do
if echo "$file" | grep -q -e '.min.css$'; then
continue
fi
if [ ! -f "$file" ]; then
continue
fi
echo "Shrinking $file"
minfile=`echo $file | sed -e 's/\.css$/\.min\.css/'`
do_shrink "$file" "$minfile"
done
done
+65
View File
@@ -0,0 +1,65 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Decrypt the encrypted parts of the HTTP Received: headers |
+-----------------------------------------------------------------------+
| Author: Tomas Tevesz <ice@extreme.hu> |
+-----------------------------------------------------------------------+
*/
/**
* If http_received_header_encrypt is configured, the IP address and the
* host name of the added Received: header is encrypted with 3DES, to
* protect information that some could consider sensitive, yet their
* availability is a must in some circumstances.
*
* Such an encrypted Received: header might look like:
*
* Received: from DzgkvJBO5+bw+oje5JACeNIa/uSI4mRw2cy5YoPBba73eyBmjtyHnQ==
* [my0nUbjZXKtl7KVBZcsvWOxxtyVFxza4]
* with HTTP/1.1 (POST); Thu, 14 May 2009 19:17:28 +0200
*
* In this example, the two encrypted components are the sender host name
* (DzgkvJBO5+bw+oje5JACeNIa/uSI4mRw2cy5YoPBba73eyBmjtyHnQ==) and the IP
* address (my0nUbjZXKtl7KVBZcsvWOxxtyVFxza4).
*
* Using this tool, they can be decrypted into plain text:
*
* $ bin/decrypt.sh 'my0nUbjZXKtl7KVBZcsvWOxxtyVFxza4' \
* > 'DzgkvJBO5+bw+oje5JACeNIa/uSI4mRw2cy5YoPBba73eyBmjtyHnQ=='
* 84.3.187.208
* 5403BBD0.catv.pool.telekom.hu
* $
*
* Thus it is known that this particular message was sent by 84.3.187.208,
* having, at the time of sending, the name of 5403BBD0.catv.pool.telekom.hu.
*
* If (most likely binary) junk is shown, then
* - either the encryption password has, between the time the mail was sent
* and 'now', changed, or
* - you are dealing with counterfeit header data.
*/
define('INSTALL_PATH', realpath(__DIR__ .'/..') . '/');
require INSTALL_PATH . 'program/include/clisetup.php';
if ($argc < 2) {
die("Usage: " . basename($argv[0]) . " encrypted-hdr-part [encrypted-hdr-part ...]\n");
}
$RCMAIL = rcube::get_instance();
for ($i = 1; $i < $argc; $i++) {
printf("%s\n", $RCMAIL->decrypt($argv[$i]));
};
+141
View File
@@ -0,0 +1,141 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Utility script to remove all data related to a certain user |
| from the local database. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
function print_usage()
{
print "Usage: deluser.sh [--host=HOST][--age=DAYS][--dry-run] [username]\n";
print "--host=HOST The IMAP hostname or IP the given user is related to\n";
print "--age=DAYS Delete all users who have not logged in for more than X days\n";
print "--dry-run List users but do not delete them (for use with --age)\n";
}
function _die($msg, $usage=false)
{
fwrite(STDERR, $msg . "\n");
if ($usage) print_usage();
exit(1);
}
$rcmail = rcube::get_instance();
// get arguments
$args = rcube_utils::get_opt(['h' => 'host', 'a' => 'age', 'd' => 'dry-run:bool']);
if (!empty($args['age']) && ($age = intval($args['age']))) {
$db = $rcmail->get_dbh();
$db->db_connect('r');
$query = $db->query("SELECT `username`, `mail_host` FROM " . $db->table_name('users', true)
. " WHERE `last_login` < " . $db->now($age * -1 * 86400)
. ($args['host'] ? " AND `mail_host` = " . $db->quote($args['host']) : '')
);
while ($user = $db->fetch_assoc($query)) {
if (!empty($args['dry-run'])) {
printf("%s (%s)\n", $user['username'], $user['mail_host']);
continue;
}
system(sprintf("php %s/deluser.sh --host=%s %s", INSTALL_PATH . 'bin', escapeshellarg($user['mail_host']), escapeshellarg($user['username'])));
}
exit(0);
}
$username = isset($args[0]) ? trim($args[0]) : null;
if (empty($username)) {
_die("Missing required parameters", true);
}
if (empty($args['host'])) {
$hosts = $rcmail->config->get('imap_host', '');
if (is_string($hosts)) {
$args['host'] = $hosts;
}
else if (is_array($hosts) && count($hosts) == 1) {
$args['host'] = reset($hosts);
}
else {
_die("Specify a host name", true);
}
// host can be a URL like tls://192.168.12.44
$host_url = parse_url($args['host']);
if ($host_url['host']) {
$args['host'] = $host_url['host'];
}
}
// connect to DB
$db = $rcmail->get_dbh();
$db->db_connect('w');
$transaction = false;
if (!$db->is_connected() || $db->is_error()) {
_die("No DB connection\n" . $db->is_error());
}
// find user in local database
$user = rcube_user::query($username, $args['host']);
if (!$user) {
die("User not found.\n");
}
// inform plugins about approaching user deletion
$plugin = $rcmail->plugins->exec_hook('user_delete_prepare', ['user' => $user, 'username' => $username, 'host' => $args['host']]);
// let plugins cleanup their own user-related data
if (!$plugin['abort']) {
$transaction = $db->startTransaction();
$plugin = $rcmail->plugins->exec_hook('user_delete', $plugin);
}
if ($plugin['abort']) {
unset($plugin['abort']);
if ($transaction) {
$db->rollbackTransaction();
}
_die("User deletion aborted by plugin");
}
$db->query('DELETE FROM ' . $db->table_name('users', true) . ' WHERE `user_id` = ?', $user->ID);
if ($db->is_error()) {
$rcmail->plugins->exec_hook('user_delete_rollback', $plugin);
_die("DB error occurred: " . $db->is_error());
}
else {
// inform plugins about executed user deletion
$plugin = $rcmail->plugins->exec_hook('user_delete_commit', $plugin);
if ($plugin['abort']) {
unset($plugin['abort']);
$db->rollbackTransaction();
$rcmail->plugins->exec_hook('user_delete_rollback', $plugin);
}
else {
$db->endTransaction();
echo "Successfully deleted user $user->ID\n";
}
}
+37
View File
@@ -0,0 +1,37 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Trigger garbage collecting routines manually (e.g. via cronjob) |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require INSTALL_PATH.'program/include/clisetup.php';
$rcmail = rcube::get_instance();
$session_driver = $rcmail->config->get('session_storage', 'db');
$session_lifetime = $rcmail->config->get('session_lifetime', 0) * 60 * 2;
// Clean expired SQL sessions
if ($session_driver == 'db' && $session_lifetime) {
$db = $rcmail->get_dbh();
$db->query("DELETE FROM " . $db->table_name('session')
. " WHERE changed < " . $db->now(-$session_lifetime));
}
// Clean caches and temp directory
$rcmail->gc();
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Update the fulltext index for all contacts of the internal |
| address book. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH.'program/include/clisetup.php';
ini_set('memory_limit', -1);
rcmail_utils::indexcontacts();
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| Copyright (C) Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Create database schema |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt([
'd' => 'dir',
'u' => 'update'
]);
if (empty($opts['dir'])) {
rcube::raise_error("Database schema directory not specified (--dir).", false, true);
}
// Check if directory exists
if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified database schema directory doesn't exist.", false, true);
}
$db = rcmail_utils::db();
if (!empty($opts['update']) && in_array($db->table_name('system'), (array)$db->list_tables())) {
echo "Checking for database schema updates..." . PHP_EOL;
rcmail_utils::db_update($opts['dir'], 'roundcube', null, ['errors' => true]);
} else {
rcmail_utils::db_init($opts['dir']);
}
+148
View File
@@ -0,0 +1,148 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Update an existing Roundcube installation with files from |
| this version |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
if (!function_exists('system')) {
rcube::raise_error("PHP system() function is required. Check disable_functions in php.ini.", false, true);
}
$target_dir = unslashify(end($_SERVER['argv']));
$accept = in_array('-y', $_SERVER['argv']) ? 'y' : null;
if (empty($target_dir) || !is_dir(realpath($target_dir))) {
rcube::raise_error("Invalid target: not a directory\nUsage: installto.sh [-y] <TARGET>", false, true);
}
// read version from iniset.php
$iniset = @file_get_contents($target_dir . '/program/include/iniset.php');
if (!preg_match('/define\(.RCMAIL_VERSION.,\s*.([0-9.]+[a-z0-9-]*)/', $iniset, $m)) {
rcube::raise_error("No valid Roundcube installation found at $target_dir", false, true);
}
$oldversion = $m[1];
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '>')) {
rcube::raise_error("Target installation already in version $oldversion.", false, true);
}
if (version_compare(version_parse($oldversion), version_parse(RCMAIL_VERSION), '==')) {
echo "Target installation already in version $oldversion. Do you want to update again? (y/N)\n";
}
else {
echo "Upgrading from $oldversion. Do you want to continue? (y/N)\n";
}
$input = $accept ?: trim(fgets(STDIN));
if (strtolower($input) == 'y') {
echo "Copying files to target location...";
$adds = [];
$dirs = ['bin','SQL','plugins','skins','program'];
if (is_dir(INSTALL_PATH . 'vendor') && (!is_file("$target_dir/composer.json") || rcmail_install::vendor_dir_untouched($target_dir))) {
$dirs[] = 'vendor';
}
if (file_exists("$target_dir/installer")) {
$dirs[] = 'installer';
}
foreach ($dirs as $dir) {
// @FIXME: should we use --delete for all directories?
$delete = in_array($dir, ['program', 'vendor', 'installer']) ? '--delete ' : '';
$command = "rsync -aC --out-format=%n " . $delete . INSTALL_PATH . "$dir/ $target_dir/$dir/";
if (system($command, $ret) === false || $ret > 0) {
rcube::raise_error("Failed to execute command: $command", false, true);
}
}
foreach (['index.php','config/defaults.inc.php','composer.json-dist','jsdeps.json','CHANGELOG.md','README.md','UPGRADING','LICENSE','INSTALL'] as $file) {
$command = "rsync -a --out-format=%n " . INSTALL_PATH . "$file $target_dir/$file";
if (file_exists(INSTALL_PATH . $file) && (system($command, $ret) === false || $ret > 0)) {
rcube::raise_error("Failed to execute command: $command", false, true);
}
}
// Copy .htaccess or .user.ini if needed
foreach (['.htaccess','.user.ini'] as $file) {
if (file_exists(INSTALL_PATH . $file)) {
if (!file_exists("$target_dir/$file") || file_get_contents(INSTALL_PATH . $file) != file_get_contents("$target_dir/$file")) {
if (copy(INSTALL_PATH . $file, "$target_dir/$file.new")) {
echo "$file.new\n";
$adds[] = "NOTICE: New $file file saved as $file.new.";
}
}
}
}
// remove old (<1.0) .htaccess file
@unlink("$target_dir/program/.htaccess");
echo "done.\n\n";
if (is_dir("$target_dir/skins/default")) {
echo "Removing old default skin...";
system("rm -rf $target_dir/skins/default $target_dir/plugins/jqueryui/themes/default");
foreach (glob(INSTALL_PATH . "plugins/*/skins") as $plugin_skin_dir) {
$plugin_skin_dir = preg_replace('!^.*' . INSTALL_PATH . '!', '', $plugin_skin_dir);
if (is_dir("$target_dir/$plugin_skin_dir/classic")) {
system("rm -rf $target_dir/$plugin_skin_dir/default");
}
}
echo "done.\n\n";
}
// Warn about situation when using "complete" package to update "custom" installation (#7087)
// Note: "Complete" package do not include jsdeps.json nor install-jsdeps.sh
if (file_exists("$target_dir/jsdeps.json") && !file_exists(INSTALL_PATH . "jsdeps.json")) {
$adds[] = "WARNING: JavaScript dependencies update skipped. New jsdeps.json file not found.";
}
// check if js-deps are up-to-date
else if (file_exists("$target_dir/jsdeps.json") && file_exists("$target_dir/bin/install-jsdeps.sh")) {
$jsdeps = json_decode(file_get_contents("$target_dir/jsdeps.json"));
$package = $jsdeps->dependencies[0];
$dest_file = $target_dir . '/' . $package->dest;
if (!file_exists($dest_file) || sha1_file($dest_file) !== $package->sha1) {
echo "Installing JavaScript dependencies...";
system("cd $target_dir && bin/install-jsdeps.sh");
echo "done.\n\n";
}
}
if (file_exists("$target_dir/installer")) {
$adds[] = "NOTICE: The 'installer' directory still exists. You should remove it after the upgrade.";
}
if (!empty($adds)) {
echo implode("\n", $adds) . "\n\n";
}
echo "Running update script at target...\n";
system("cd $target_dir && php bin/update.sh --version=$oldversion" . ($accept ? ' -y' : ''));
echo "All done.\n";
}
else {
echo "Update cancelled. See ya!\n";
}
+51
View File
@@ -0,0 +1,51 @@
#!/bin/sh
set -e
PWD=`dirname "$0"`
LANG_IN='ECMASCRIPT5'
do_shrink() {
rm -f "$2"
# copy the first comment block with license information for LibreJS
grep -q '@lic' $1 && sed -n '/\/\*/,/\*\// { p; /\*\//q; }' $1 > $2
uglifyjs --compress --mangle -- $1 >> $2
}
if which uglifyjs > /dev/null 2>&1; then
:
else
echo "uglifyjs not found. Please install e.g. 'npm install -g uglify-js'."
exit 1
fi
# compress single file from argument
if [ $# -gt 0 ]; then
JS_FILE="$1"
if [ $# -gt 1 ]; then
LANG_IN="$2"
fi
echo "Shrinking $JS_FILE"
minfile=`echo $JS_FILE | sed -e 's/\.js$/\.min\.js/'`
do_shrink "$JS_FILE" "$minfile" "$LANG_IN"
exit
fi
DIRS="$PWD/../program/js $PWD/../skins/* $PWD/../plugins/* $PWD/../plugins/*/skins/* $PWD/../plugins/managesieve/codemirror/lib"
# default: compress application scripts
for dir in $DIRS; do
for file in $dir/*.js; do
if echo "$file" | grep -q -e '.min.js$'; then
continue
fi
if [ ! -f "$file" ]; then
continue
fi
echo "Shrinking $file"
minfile=`echo $file | sed -e 's/\.js$/\.min\.js/'`
do_shrink "$file" "$minfile" "$LANG_IN"
done
done
+24
View File
@@ -0,0 +1,24 @@
#!/bin/sh
set -x
BIN_PHPDOC=`/usr/bin/which phpdoc`
if [ ! -x "$BIN_PHPDOC" ]
then
echo "phpdoc not found"
exit 1
fi
INSTALL_PATH="`dirname $0`/.."
PATH_PROJECT=$INSTALL_PATH/program/include
PATH_FRAMEWORK=$INSTALL_PATH/program/lib/Roundcube
PATH_DOCS=$INSTALL_PATH/doc/phpdoc
TITLE="Roundcube Webmail"
PACKAGES="Webmail"
OUTPUTFORMAT=HTML
TEMPLATE=responsive-twig
# make documentation
$BIN_PHPDOC -d $PATH_PROJECT,$PATH_FRAMEWORK -t $PATH_DOCS --title "$TITLE" \
--defaultpackagename $PACKAGES --template=$TEMPLATE
+68
View File
@@ -0,0 +1,68 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Bulk-change settings stored in user preferences |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: moduserprefs.sh [options] pref-name [pref-value]\n";
print "Options:\n";
print " --user=user-id User ID in local database\n";
print " --config=path Location of additional configuration file\n";
print " --delete Unset the given preference\n";
print " --type=type Pref-value type: int, bool, string\n";
}
// get arguments
$args = rcube_utils::get_opt([
'u' => 'user',
'd' => 'delete:bool',
't' => 'type',
'c' => 'config',
]);
if (empty($_SERVER['argv'][1]) || $_SERVER['argv'][1] == 'help') {
print_usage();
exit;
}
else if (empty($args[0]) || (empty($args[1]) && empty($args['delete']))) {
print "Missing required parameters.\n";
print_usage();
exit;
}
$pref_name = trim($args[0]);
$pref_value = !empty($args['delete']) ? null : trim($args[1]);
if ($pref_value === null) {
$args['type'] = null;
}
if (!empty($args['config'])) {
$rcube = rcube::get_instance();
$rcube->config->load_from_file($args['config']);
}
$type = isset($args['type']) ? $args['type'] : null;
$user = isset($args['user']) ? $args['user'] : null;
rcmail_utils::mod_pref($pref_name, $pref_value, $user, $type);
+149
View File
@@ -0,0 +1,149 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
ini_set('memory_limit', -1);
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: msgexport.sh -h imap-host -u user-name -m mailbox name\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Folder name, set to '*' for all\n";
print "--file Output file\n";
}
function vputs($str)
{
$out = !empty($GLOBALS['args']['file']) ? STDOUT : STDERR;
fwrite($out, $str);
}
function progress_update($pos, $max)
{
$percent = round(100 * $pos / $max);
vputs(sprintf("%3d%% [%-51s] %d/%d\033[K\r", $percent, @str_repeat('=', $percent / 2) . '>', $pos, $max));
}
function export_mailbox($mbox, $filename)
{
global $IMAP;
$IMAP->set_folder($mbox);
vputs("Getting message list of {$mbox}...");
$index = $IMAP->index($mbox, null, 'ASC');
$count = $index->count();
$index = $index->get();
vputs("$count messages\n");
if ($filename) {
if (!($out = fopen($filename, 'w'))) {
vputs("Cannot write to output file\n");
return;
}
vputs("Writing to $filename\n");
}
else {
$out = STDOUT;
}
for ($i = 0; $i < $count; $i++) {
$headers = $IMAP->get_message_headers($index[$i]);
$from = current(rcube_mime::decode_address_list($headers->from, 1, false));
fwrite($out, sprintf("From %s %s UID %d\n", $from['mailto'], $headers->date, $headers->uid));
$IMAP->get_raw_body($headers->uid, $out);
fwrite($out, "\n\n\n");
progress_update($i+1, $count);
}
vputs("\ncomplete.\n");
if ($filename) {
fclose($out);
}
}
// get arguments
$opts = ['h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file'];
$args = rcube_utils::get_opt($opts) + ['host' => 'localhost', 'mbox' => 'INBOX'];
if (!isset($_SERVER['argv'][1]) || $_SERVER['argv'][1] == 'help') {
print_usage();
exit;
}
else if (!$args['host']) {
vputs("Missing required parameters.\n");
print_usage();
exit;
}
// prompt for username if not set
if (empty($args['user'])) {
vputs("IMAP user: ");
$args['user'] = trim(fgets(STDIN));
}
// prompt for password
$args['pass'] = rcube_utils::prompt_silent("Password: ");
// parse $host URL
$a_host = parse_url($args['host']);
if (!empty($a_host['host'])) {
$host = $a_host['host'];
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], ['ssl','imaps','tls'])) ? TRUE : FALSE;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
}
else {
$host = $args['host'];
$imap_port = 143;
$imap_ssl = false;
}
// instantiate IMAP class
$IMAP = new rcube_imap(null);
// try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) {
vputs("IMAP login successful.\n");
$filename = null;
$mailboxes = $args['mbox'] == '*' ? $IMAP->list_folders(null) : [$args['mbox']];
foreach ($mailboxes as $mbox) {
if (!empty($args['file'])) {
$filename = preg_replace('/\.[a-z0-9]{3,4}$/i', '', $args['file']) . asciiwords($mbox) . '.mbox';
}
else if ($args['mbox'] == '*') {
$filename = asciiwords($mbox) . '.mbox';
}
if ($args['mbox'] == '*' && in_array(strtolower($mbox), ['junk','spam','trash'])) {
continue;
}
export_mailbox($mbox, $filename);
}
}
else {
vputs("IMAP login failed.\n");
}
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <thomas@roundcube.net> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
ini_set('memory_limit', -1);
require_once INSTALL_PATH.'program/include/clisetup.php';
function print_usage()
{
print "Usage: msgimport.sh -h imap-host -u user-name -m mailbox -f message-file\n";
print "--host IMAP host\n";
print "--user IMAP user name\n";
print "--mbox Target mailbox\n";
print "--file Message file to upload\n";
}
// get arguments
$opts = ['h' => 'host', 'u' => 'user', 'p' => 'pass', 'm' => 'mbox', 'f' => 'file'];
$args = rcube_utils::get_opt($opts) + ['host' => 'localhost', 'mbox' => 'INBOX'];
if (!isset($_SERVER['argv'][1]) || $_SERVER['argv'][1] == 'help') {
print_usage();
exit;
}
else if (empty($args['host']) || empty($args['file'])) {
print "Missing required parameters.\n";
print_usage();
exit;
}
else if (!is_file($args['file'])) {
rcube::raise_error("Cannot read message file.", false, true);
}
// prompt for username if not set
if (empty($args['user'])) {
//fwrite(STDOUT, "Please enter your name\n");
echo "IMAP user: ";
$args['user'] = trim(fgets(STDIN));
}
// prompt for password
if (empty($args['pass'])) {
$args['pass'] = rcube_utils::prompt_silent("Password: ");
}
// parse $host URL
$a_host = parse_url($args['host']);
if (!empty($a_host['host'])) {
$host = $a_host['host'];
$imap_ssl = (isset($a_host['scheme']) && in_array($a_host['scheme'], ['ssl','imaps','tls'])) ? TRUE : FALSE;
$imap_port = isset($a_host['port']) ? $a_host['port'] : ($imap_ssl ? 993 : 143);
}
else {
$host = $args['host'];
$imap_port = 143;
$imap_ssl = false;
}
// instantiate IMAP class
$IMAP = new rcube_imap(null);
// try to connect to IMAP server
if ($IMAP->connect($host, $args['user'], $args['pass'], $imap_port, $imap_ssl)) {
print "IMAP login successful.\n";
print "Uploading messages...\n";
$count = 0;
$message = $lastline = '';
$fp = fopen($args['file'], 'r');
while (($line = fgets($fp)) !== false) {
if (preg_match('/^From\s+-/', $line) && $lastline == '') {
if (!empty($message)) {
if ($IMAP->save_message($args['mbox'], rtrim($message))) {
$count++;
}
else {
rcube::raise_error("Failed to save message to {$args['mbox']}", false, true);
}
$message = '';
}
continue;
}
$message .= $line;
$lastline = rtrim($line);
}
if (!empty($message) && $IMAP->save_message($args['mbox'], rtrim($message))) {
$count++;
}
// upload message from file
if ($count) {
print "$count messages successfully added to {$args['mbox']}.\n";
}
else {
print "Adding messages failed!\n";
}
}
else {
rcube::raise_error("IMAP login failed.", false, true);
}
+328
View File
@@ -0,0 +1,328 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Check local configuration and database schema after upgrading |
| to a new version |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt(['v' => 'version', 'y' => 'accept:bool']);
// ask user if no version is specified
if (empty($opts['version'])) {
echo "What version are you upgrading from? Type '?' if you don't know.\n";
if (($input = trim(fgets(STDIN))) && preg_match('/^[0-9.]+[a-z0-9-]*$/', $input)) {
$opts['version'] = $input;
}
else {
$opts['version'] = RCMAIL_VERSION;
}
}
$RCI = rcmail_install::get_instance();
$RCI->load_config();
if ($RCI->configured) {
$success = true;
if (($messages = $RCI->check_config($opts['version'])) || $RCI->legacy_config) {
$success = false;
$err = 0;
// list old/replaced config options
if (!empty($messages['replaced'])) {
echo "WARNING: Replaced config options:\n";
echo "(These config options have been replaced or renamed)\n";
foreach ($messages['replaced'] as $msg) {
echo "- '" . $msg['prop'] . "' was replaced by '" . $msg['replacement'] . "'\n";
$err++;
}
}
// list obsolete config options (just a notice)
if (!empty($messages['obsolete'])) {
echo "NOTICE: Obsolete config options:\n";
echo "(You still have some obsolete or inexistent properties set."
. " This isn't a problem but should be noticed)\n";
foreach ($messages['obsolete'] as $msg) {
echo "- '" . $msg['prop'] . (!empty($msg['explain']) ? "': " . $msg['explain'] : "'") . "\n";
$err++;
}
}
if (!$err && $RCI->legacy_config) {
echo "WARNING: Your configuration needs to be migrated!\n";
echo "We changed the configuration files structure and your two config files "
. "main.inc.php and db.inc.php have to be merged into one single file.\n";
$err++;
}
// ask user to update config files
if ($err) {
if (empty($opts['accept'])) {
echo "Do you want me to fix your local configuration? (y/N)\n";
$input = trim(fgets(STDIN));
}
// positive: merge the local config with the defaults
if (!empty($opts['accept']) || strtolower($input) == 'y') {
$error = $written = false;
echo "- backing up the current config file(s)...\n";
foreach (['config', 'main', 'db'] as $file) {
if (file_exists(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php')) {
if (!copy(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php', RCMAIL_CONFIG_DIR . '/' . $file . '.old.php')) {
$error = true;
}
}
}
if (!$error) {
$RCI->merge_config();
echo "- writing " . RCMAIL_CONFIG_DIR . "/config.inc.php...\n";
$written = $RCI->save_configfile($RCI->create_config(false));
}
// Success!
if ($written) {
echo "Done.\n";
echo "Your configuration files are now up-to-date!\n";
if (!empty($messages['missing'])) {
echo "But you still need to add the following missing options:\n";
foreach ($messages['missing'] as $msg) {
echo "- '" . $msg['prop'] . ($msg['name'] ? "': " . $msg['name'] : "'") . "\n";
}
}
if ($RCI->legacy_config) {
foreach (['main', 'db'] as $file) {
@unlink(RCMAIL_CONFIG_DIR . '/' . $file . '.inc.php');
}
}
}
else {
echo "Failed to write config file(s)!\n";
echo "Grant write privileges to the current user or update the files manually "
. "according to the above messages.\n";
}
}
else {
echo "Please update your config files manually according to the above messages.\n";
}
}
// list of config options with changed default (just a notice)
if (!empty($messages['defaults'])) {
echo "WARNING: Changed defaults (These config options have new default values):\n";
foreach ($messages['defaults'] as $opt) {
echo "- '{$opt}'\n";
}
}
// check dependencies based on the current configuration
if (!empty($messages['dependencies'])) {
echo "WARNING: Dependency check failed!\n";
echo "(Some of your configuration settings require other options to be configured "
. "or additional PHP modules to be installed)\n";
foreach ($messages['dependencies'] as $msg) {
echo "- " . $msg['prop'] . ': ' . $msg['explain'] . "\n";
}
echo "Please fix your config files and run this script again!\n";
echo "See ya.\n";
}
}
// check file type detection
if ($RCI->check_mime_detection()) {
echo "WARNING: File type detection doesn't work properly!\n";
echo "Please check the 'mime_magic' config option or the finfo functions of PHP and run this script again.\n";
}
if ($RCI->check_mime_extensions()) {
echo "WARNING: Mimetype to file extension mapping doesn't work properly!\n";
echo "Please check the 'mime_types' config option and run this script again.\n";
}
// check database schema
if (!empty($RCI->config['db_dsnw'])) {
echo "Executing database schema update.\n";
$success = rcmail_utils::db_update(INSTALL_PATH . 'SQL', 'roundcube', $opts['version'], ['errors' => true]);
}
// update composer dependencies
if (is_file(INSTALL_PATH . 'composer.json') && is_readable(INSTALL_PATH . 'composer.json-dist')) {
$composer_data = json_decode(file_get_contents(INSTALL_PATH . 'composer.json'), true);
$composer_template = json_decode(file_get_contents(INSTALL_PATH . 'composer.json-dist'), true);
$composer_json = null;
// update the require section with the new dependencies
if (!empty($composer_data['require']) && !empty($composer_template['require'])) {
$composer_data['require'] = array_merge($composer_data['require'], $composer_template['require']);
// remove obsolete packages
$old_packages = [
'pear-pear.php.net/net_socket',
'pear-pear.php.net/auth_sasl',
'pear-pear.php.net/net_idna2',
'pear-pear.php.net/mail_mime',
'pear-pear.php.net/net_smtp',
'pear-pear.php.net/crypt_gpg',
'pear-pear.php.net/net_sieve',
'pear/mail_mime-decode',
'roundcube/net_sieve',
'endroid/qrcode',
'endroid/qr-code',
];
foreach ($old_packages as $pkg) {
if (array_key_exists($pkg, $composer_data['require'])) {
unset($composer_data['require'][$pkg]);
}
}
}
// update the repositories section with the new dependencies
if (!empty($composer_template['repositories'])) {
if (empty($composer_data['repositories'])) {
$composer_data['repositories'] = [];
}
foreach ($composer_template['repositories'] as $repo) {
$rkey = repo_key($repo);
$existing = false;
foreach ($composer_data['repositories'] as $k => $_repo) {
if ($rkey == repo_key($_repo)) {
// switch to https://
if (isset($_repo['url']) && strpos($_repo['url'], 'http://') === 0) {
$composer_data['repositories'][$k]['url'] = 'https:' . substr($_repo['url'], 5);
}
$existing = true;
break;
}
// remove old repos
if (isset($_repo['url']) && strpos($_repo['url'], 'git://git.kolab.org') === 0) {
unset($composer_data['repositories'][$k]);
}
else if (
$_repo['type'] == 'package'
&& !empty($_repo['package']['name'])
&& $_repo['package']['name'] == 'Net_SMTP'
) {
unset($composer_data['repositories'][$k]);
}
}
if (!$existing) {
$composer_data['repositories'][] = $repo;
}
}
$composer_data['repositories'] = array_values($composer_data['repositories']);
}
$composer_json = json_encode($composer_data, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
// write updated composer.json back to disk
if ($composer_json && is_writeable(INSTALL_PATH . 'composer.json')) {
$success &= (bool)file_put_contents(INSTALL_PATH . 'composer.json', $composer_json);
}
else {
echo "WARNING: unable to update composer.json!\n";
echo "Please replace the 'require' section in your composer.json with the following:\n";
$require_json = '';
foreach ($composer_data['require'] as $pkg => $ver) {
$require_json .= sprintf(' "%s": "%s",'."\n", $pkg, $ver);
}
echo ' "require": {'."\n";
echo rtrim($require_json, ",\n");
echo "\n }\n\n";
}
if (!rcmail_install::vendor_dir_untouched(INSTALL_PATH)) {
$exit_code = 1;
if ($composer_bin = find_composer()) {
echo "Executing " . $composer_bin . " to update dependencies...\n";
echo system("$composer_bin update -d " . escapeshellarg(INSTALL_PATH) . " --no-dev", $exit_code);
}
if ($exit_code != 0) {
echo "-----------------------------------------------------------------------------\n";
echo "ATTENTION: Update dependencies by running `php composer.phar update --no-dev`\n";
echo "-----------------------------------------------------------------------------\n";
}
}
}
// index contacts for fulltext searching
if ($opts['version'] && version_compare(version_parse($opts['version']), '0.6.0', '<')) {
rcmail_utils::indexcontacts();
}
if ($success) {
echo "This instance of Roundcube is up-to-date.\n";
echo "Have fun!\n";
}
}
else {
echo "This instance of Roundcube is not yet configured!\n";
echo "Open http://url-to-roundcube/installer/ in your browser and follow the instructions.\n";
}
function repo_key($repo)
{
$key = $repo['type'];
if (!empty($repo['url'])) {
$key .= preg_replace('/^https?:/', '', $repo['url']);
}
if (!empty($repo['package']['name'])) {
$key .= $repo['package']['name'];
}
return $key;
}
function find_composer()
{
if (is_file(INSTALL_PATH . 'composer.phar')) {
return 'php composer.phar';
}
foreach (['composer', 'composer.phar'] as $check_file) {
$which = trim(system("which $check_file"));
if (!empty($which)) {
return $which;
}
}
return null;
}
+117
View File
@@ -0,0 +1,117 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Update cache-baster marks for css background images |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt(['d' => 'dir']);
if (empty($opts['dir'])) {
print "Skin directory not specified (--dir). Using skins/ and plugins/*/skins/.\n";
$dir = INSTALL_PATH . 'skins';
$dir_p = INSTALL_PATH . 'plugins';
$skins = glob("$dir/*", GLOB_ONLYDIR);
$skins_p = glob("$dir_p/*/skins/*", GLOB_ONLYDIR);
$dirs = array_merge($skins, $skins_p);
}
// Check if directory exists
else if (!file_exists($opts['dir'])) {
rcube::raise_error("Specified directory doesn't exist.", false, true);
}
else {
$dirs = [$opts['dir']];
}
foreach ($dirs as $dir) {
$img_dir = $dir . '/images';
if (!file_exists($img_dir)) {
continue;
}
$files = get_files($dir);
$images = get_images($img_dir);
$find = [];
$replace = [];
// build regexps array
foreach ($images as $path => $sum) {
$path_ex = str_replace('.', '\\.', $path);
$find[] = "#url\(['\"]?images/$path_ex(\?v=[a-f0-9-\.]+)?['\"]?\)#";
$replace[] = "url(images/$path?v=$sum)";
}
foreach ($files as $file) {
$file = $dir . '/' . $file;
print "File: $file\n";
$content = file_get_contents($file);
$content = preg_replace($find, $replace, $content, -1, $count);
if ($count) {
file_put_contents($file, $content);
}
}
}
function get_images($dir)
{
$images = [];
$dh = opendir($dir);
while ($file = readdir($dh)) {
if (preg_match('/^(.+)\.(gif|ico|png|jpg|jpeg)$/', $file, $m)) {
$filepath = "$dir/$file";
$images[$file] = substr(md5_file($filepath), 0, 4) . '.' . filesize($filepath);
print "Image: $filepath ({$images[$file]})\n";
}
else if ($file != '.' && $file != '..' && is_dir($dir . '/' . $file)) {
foreach (get_images($dir . '/' . $file) as $img => $sum) {
$images[$file . '/' . $img] = $sum;
}
}
}
closedir($dh);
return $images;
}
function get_files($dir)
{
$files = [];
$dh = opendir($dir);
while ($file = readdir($dh)) {
if (preg_match('/^(.+)\.(css|html)$/', $file, $m)) {
$files[] = $file;
}
else if ($file != '.' && $file != '..' && is_dir($dir . '/' . $file)) {
foreach (get_files($dir . '/' . $file) as $f) {
$files[] = $file . '/' . $f;
}
}
}
closedir($dh);
return $files;
}
+39
View File
@@ -0,0 +1,39 @@
#!/usr/bin/env php
<?php
/*
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) The Roundcube Dev Team |
| Copyright (C) Kolab Systems AG |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Update database schema |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
define('INSTALL_PATH', realpath(__DIR__ . '/..') . '/' );
require_once INSTALL_PATH . 'program/include/clisetup.php';
// get arguments
$opts = rcube_utils::get_opt([
'v' => 'version',
'd' => 'dir',
'p' => 'package',
]);
if (empty($opts['dir'])) {
rcube::raise_error("Database schema directory not specified (--dir).", false, true);
}
if (empty($opts['package'])) {
rcube::raise_error("Database schema package name not specified (--package).", false, true);
}
rcmail_utils::db_update($opts['dir'], $opts['package'], $opts['version'] ?? null, ['errors' => true]);