Merged branch devel-api (from r2208 to r2387) back into trunk (omitting some sample plugins)
parent
fb253ee9a8
commit
cc97ea0559
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Additional Message Headers
|
||||
*
|
||||
* Very simple plugin which will read additional headers for outgoing messages from the config file.
|
||||
*
|
||||
* Enable the plugin in config/main.inc.php and add your desired headers.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Ziba Scott
|
||||
* @website http://roundcube.net
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* $rcmail_config['additional_message_headers']['X-Remote-Browser'] = $_SERVER['HTTP_USER_AGENT'];
|
||||
* $rcmail_config['additional_message_headers']['X-Originating-IP'] = $_SERVER['REMOTE_ADDR'];
|
||||
* $rcmail_config['additional_message_headers']['X-RoundCube-Server'] = $_SERVER['SERVER_ADDR'];
|
||||
* if( isset( $_SERVER['MACHINE_NAME'] )) {
|
||||
* $rcmail_config['additional_message_headers']['X-RoundCube-Server'] .= ' (' . $_SERVER['MACHINE_NAME'] . ')';
|
||||
* }
|
||||
*/
|
||||
class additional_message_headers extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->add_hook('outgoing_message_headers', array($this, 'message_headers'));
|
||||
}
|
||||
|
||||
function message_headers($args){
|
||||
|
||||
// additional email headers
|
||||
$additional_headers = rcmail::get_instance()->config->get('additional_message_headers',array());
|
||||
foreach($additional_headers as $header=>$value){
|
||||
$args['headers'][$header] = $value;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sample plugin to try out some hooks.
|
||||
* This performs an automatic login if accessed from localhost
|
||||
*/
|
||||
class autologon extends rcube_plugin
|
||||
{
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->add_hook('startup', array($this, 'startup'));
|
||||
$this->add_hook('authenticate', array($this, 'authenticate'));
|
||||
}
|
||||
|
||||
function startup($args)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
// change action to login
|
||||
if ($args['task'] == 'mail' && empty($args['action']) && empty($_SESSION['user_id']) && !empty($_GET['_autologin']) && $this->is_localhost())
|
||||
$args['action'] = 'login';
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
function authenticate($args)
|
||||
{
|
||||
if (!empty($_GET['_autologin']) && $this->is_localhost()) {
|
||||
$args['user'] = 'me';
|
||||
$args['pass'] = '******';
|
||||
$args['host'] = 'localhost';
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
function is_localhost()
|
||||
{
|
||||
return $_SERVER['REMOTE_ADDR'] == '::1' || $_SERVER['REMOTE_ADDR'] == '127.0.0.1';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/**
|
||||
* Filesystem Attachments
|
||||
*
|
||||
* This plugin which provides database backed storage for temporary
|
||||
* attachment file handling. The primary advantage of this plugin
|
||||
* is its compatibility with round-robin dns multi-server roundcube
|
||||
* installations.
|
||||
*
|
||||
* This plugin relies on the core filesystem_attachments plugin
|
||||
*
|
||||
* @author Ziba Scott <ziba@umich.edu>
|
||||
*
|
||||
*/
|
||||
require_once('plugins/filesystem_attachments/filesystem_attachments.php');
|
||||
class database_attachments extends filesystem_attachments
|
||||
{
|
||||
|
||||
// A prefix for the cache key used in the session and in the key field of the cache table
|
||||
private $cache_prefix = "db_attach";
|
||||
|
||||
/**
|
||||
* Helper method to generate a unique key for the given attachment file
|
||||
*/
|
||||
private function _key($filepath)
|
||||
{
|
||||
return $this->cache_prefix.md5(mktime().$filepath.$_SESSION['user_id']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a newly uploaded attachment
|
||||
*/
|
||||
function upload($args)
|
||||
{
|
||||
$args['status'] = false;
|
||||
$rcmail = rcmail::get_instance();
|
||||
$key = $this->_key($args['path']);
|
||||
$data = base64_encode(file_get_contents($args['path']));
|
||||
|
||||
$status = $rcmail->db->query(
|
||||
"INSERT INTO ".get_table_name('cache')."
|
||||
(created, user_id, cache_key, data)
|
||||
VALUES (".$rcmail->db->now().", ?, ?, ?)",
|
||||
$_SESSION['user_id'],
|
||||
$key,
|
||||
$data);
|
||||
|
||||
if ($status) {
|
||||
$args['id'] = $key;
|
||||
$args['status'] = true;
|
||||
unset($args['path']);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an attachment from a non-upload source (draft or forward)
|
||||
*/
|
||||
function save($args)
|
||||
{
|
||||
$args['status'] = false;
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$key = $this->_key($args['name']);
|
||||
$data = base64_encode($args['data']);
|
||||
|
||||
$status = $rcmail->db->query(
|
||||
"INSERT INTO ".get_table_name('cache')."
|
||||
(created, user_id, cache_key, data)
|
||||
VALUES (".$rcmail->db->now().", ?, ?, ?)",
|
||||
$_SESSION['user_id'],
|
||||
$key,
|
||||
$data);
|
||||
|
||||
if ($status) {
|
||||
$args['id'] = $key;
|
||||
$args['status'] = true;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an attachment from storage
|
||||
* This is triggered by the remove attachment button on the compose screen
|
||||
*/
|
||||
function remove($args)
|
||||
{
|
||||
$args['status'] = false;
|
||||
$rcmail = rcmail::get_instance();
|
||||
$status = $rcmail->db->query(
|
||||
"DELETE FROM ".get_table_name('cache')."
|
||||
WHERE user_id=?
|
||||
AND cache_key=?",
|
||||
$_SESSION['user_id'],
|
||||
$args['id']);
|
||||
|
||||
if ($status) {
|
||||
$args['status'] = true;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* When composing an html message, image attachments may be shown
|
||||
* For this plugin, $this->get_attachment will check the file and
|
||||
* return it's contents
|
||||
*/
|
||||
function display($args)
|
||||
{
|
||||
return $this->get_attachment($args);
|
||||
}
|
||||
|
||||
/**
|
||||
* When displaying or sending the attachment the file contents are fetched
|
||||
* using this method. This is also called by the display_attachment hook.
|
||||
*/
|
||||
function get_attachment($args)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$sql_result = $rcmail->db->query(
|
||||
"SELECT cache_id, data
|
||||
FROM ".get_table_name('cache')."
|
||||
WHERE user_id=?
|
||||
AND cache_key=?",
|
||||
$_SESSION['user_id'],
|
||||
$args['id']);
|
||||
|
||||
if ($sql_arr = $rcmail->db->fetch_assoc($sql_result)) {
|
||||
$args['data'] = base64_decode($sql_arr['data']);
|
||||
$args['status'] = true;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all temp files associated with this user
|
||||
*/
|
||||
function cleanup($args)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->db->query(
|
||||
"DELETE FROM ".get_table_name('cache')."
|
||||
WHERE user_id=?
|
||||
AND cache_key like '{$this->cache_prefix}%'",
|
||||
$_SESSION['user_id']);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,146 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Debug Logger
|
||||
*
|
||||
* Enhanced logging for debugging purposes. It is not recommened
|
||||
* to be enabled on production systems without testing because of
|
||||
* the somewhat increased memory, cpu and disk i/o overhead.
|
||||
*
|
||||
* Debug Logger listens for existing console("message") calls and
|
||||
* introduces start and end tags as well as free form tagging
|
||||
* which can redirect messages to files. The resulting log files
|
||||
* provide timing and tag quantity results.
|
||||
*
|
||||
* Enable the plugin in config/main.inc.php and add your desired
|
||||
* log types and files.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Ziba Scott
|
||||
* @website http://roundcube.net
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* config/main.inc.php:
|
||||
*
|
||||
* // $rcmail_config['debug_logger'][type of logging] = name of file in log_dir
|
||||
* // The 'master' log includes timing information
|
||||
* $rcmail_config['debug_logger']['master'] = 'master';
|
||||
* // If you want sql messages to also go into a separate file
|
||||
* $rcmail_config['debug_logger']['sql'] = 'sql';
|
||||
*
|
||||
* index.php (just after $RCMAIL->plugins->init()):
|
||||
*
|
||||
* console("my test","start");
|
||||
* console("my message");
|
||||
* console("my sql calls","start");
|
||||
* console("cp -r * /dev/null","shell exec");
|
||||
* console("select * from example","sql");
|
||||
* console("select * from example","sql");
|
||||
* console("select * from example","sql");
|
||||
* console("end");
|
||||
* console("end");
|
||||
*
|
||||
*
|
||||
* logs/master (after reloading the main page):
|
||||
*
|
||||
* [17-Feb-2009 16:51:37 -0500] start: Task: mail.
|
||||
* [17-Feb-2009 16:51:37 -0500] start: my test
|
||||
* [17-Feb-2009 16:51:37 -0500] my message
|
||||
* [17-Feb-2009 16:51:37 -0500] shell exec: cp -r * /dev/null
|
||||
* [17-Feb-2009 16:51:37 -0500] start: my sql calls
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
* [17-Feb-2009 16:51:37 -0500] end: my sql calls - 0.0018 seconds shell exec: 1, sql: 3,
|
||||
* [17-Feb-2009 16:51:37 -0500] end: my test - 0.0055 seconds shell exec: 1, sql: 3,
|
||||
* [17-Feb-2009 16:51:38 -0500] end: Task: mail. - 0.8854 seconds shell exec: 1, sql: 3,
|
||||
*
|
||||
* logs/sql (after reloading the main page):
|
||||
*
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
* [17-Feb-2009 16:51:37 -0500] sql: select * from example
|
||||
*/
|
||||
class debug_logger extends rcube_plugin
|
||||
{
|
||||
function init()
|
||||
{
|
||||
require_once(dirname(__FILE__).'/runlog/runlog.php');
|
||||
$this->runlog = new runlog();
|
||||
|
||||
if(!rcmail::get_instance()->config->get('log_dir')){
|
||||
rcmail::get_instance()->config->set('log_dir',INSTALL_PATH.'logs');
|
||||
}
|
||||
|
||||
$log_config = rcmail::get_instance()->config->get('debug_logger',array());
|
||||
|
||||
foreach($log_config as $type=>$file){
|
||||
$this->runlog->set_file(rcmail::get_instance()->config->get('log_dir').'/'.$file, $type);
|
||||
}
|
||||
|
||||
$start_string = "";
|
||||
$action = rcmail::get_instance()->action;
|
||||
$task = rcmail::get_instance()->task;
|
||||
if($action){
|
||||
$start_string .= "Action: ".$action.". ";
|
||||
}
|
||||
if($task){
|
||||
$start_string .= "Task: ".$task.". ";
|
||||
}
|
||||
$this->runlog->start($start_string);
|
||||
|
||||
$this->add_hook('console', array($this, 'console'));
|
||||
$this->add_hook('authenticate', array($this, 'authenticate'));
|
||||
}
|
||||
|
||||
function authenticate($args){
|
||||
$this->runlog->note('Authenticating '.$args['user'].'@'.$args['host']);
|
||||
return $args;
|
||||
}
|
||||
|
||||
function console($args){
|
||||
$note = $args[0];
|
||||
$type = $args[1];
|
||||
|
||||
|
||||
if(!isset($args[1])){
|
||||
// This could be extended to detect types based on the
|
||||
// file which called console. For now only rcube_imap.inc is supported
|
||||
$bt = debug_backtrace(true);
|
||||
$file = $bt[3]['file'];
|
||||
switch(basename($file)){
|
||||
case 'rcube_imap.php':
|
||||
$type = 'imap';
|
||||
break;
|
||||
default:
|
||||
$type = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
switch($note){
|
||||
case 'end':
|
||||
$type = 'end';
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
switch($type){
|
||||
case 'start':
|
||||
$this->runlog->start($note);
|
||||
break;
|
||||
case 'end':
|
||||
$this->runlog->end();
|
||||
break;
|
||||
default:
|
||||
$this->runlog->note($note, $type);
|
||||
break;
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
function __destruct(){
|
||||
$this->runlog->end();
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -0,0 +1,227 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* runlog
|
||||
*
|
||||
* @author Ziba Scott <ziba@umich.edu>
|
||||
*/
|
||||
class runlog {
|
||||
|
||||
private $start_time = FALSE;
|
||||
|
||||
private $parent_stack = array();
|
||||
|
||||
public $print_to_console = FALSE;
|
||||
|
||||
private $file_handles = array();
|
||||
|
||||
private $indent = 0;
|
||||
|
||||
public $threshold = 0;
|
||||
|
||||
public $tag_count = array();
|
||||
|
||||
public $timestamp = "d-M-Y H:i:s O";
|
||||
|
||||
public $max_line_size = 150;
|
||||
|
||||
private $run_log = array();
|
||||
|
||||
function runlog()
|
||||
{
|
||||
$this->start_time = microtime( TRUE );
|
||||
}
|
||||
|
||||
public function start( $name, $tag = FALSE )
|
||||
{
|
||||
$this->run_log[] = array( 'type' => 'start',
|
||||
'tag' => $tag,
|
||||
'index' => count($this->run_log),
|
||||
'value' => $name,
|
||||
'time' => microtime( TRUE ),
|
||||
'parents' => $this->parent_stack,
|
||||
'ended' => false,
|
||||
);
|
||||
$this->parent_stack[] = $name;
|
||||
|
||||
$this->print_to_console("start: ".$name, $tag, 'start');
|
||||
$this->print_to_file("start: ".$name, $tag, 'start');
|
||||
$this->indent++;
|
||||
}
|
||||
|
||||
public function end()
|
||||
{
|
||||
$name = array_pop( $this->parent_stack );
|
||||
foreach ( $this->run_log as $k => $entry ) {
|
||||
if ( $entry['value'] == $name && $entry['type'] == 'start' && $entry['ended'] == false) {
|
||||
$lastk = $k;
|
||||
}
|
||||
}
|
||||
$start = $this->run_log[$lastk]['time'];
|
||||
$this->run_log[$lastk]['duration'] = microtime( TRUE ) - $start;
|
||||
$this->run_log[$lastk]['ended'] = true;
|
||||
|
||||
$this->run_log[] = array( 'type' => 'end',
|
||||
'tag' => $this->run_log[$lastk]['tag'],
|
||||
'index' => $lastk,
|
||||
'value' => $name,
|
||||
'time' => microtime( TRUE ),
|
||||
'duration' => microtime( TRUE ) - $start,
|
||||
'parents' => $this->parent_stack,
|
||||
);
|
||||
$this->indent--;
|
||||
if($this->run_log[$lastk]['duration'] >= $this->threshold){
|
||||
$tag_report = "";
|
||||
foreach($this->tag_count as $tag=>$count){
|
||||
$tag_report .= "$tag: $count, ";
|
||||
}
|
||||
if(!empty($tag_report)){
|
||||
// $tag_report = "\n$tag_report\n";
|
||||
}
|
||||
$end_txt = sprintf("end: $name - %0.4f seconds $tag_report", $this->run_log[$lastk]['duration'] );
|
||||
$this->print_to_console($end_txt, $this->run_log[$lastk]['tag'] , 'end');
|
||||
$this->print_to_file($end_txt, $this->run_log[$lastk]['tag'], 'end');
|
||||
}
|
||||
}
|
||||
|
||||
public function increase_tag_count($tag){
|
||||
if(!isset($this->tag_count[$tag])){
|
||||
$this->tag_count[$tag] = 0;
|
||||
}
|
||||
$this->tag_count[$tag]++;
|
||||
}
|
||||
|
||||
public function get_text(){
|
||||
$text = "";
|
||||
foreach($this->run_log as $entry){
|
||||
$text .= str_repeat(" ",count($entry['parents']));
|
||||
if($entry['tag'] != 'text'){
|
||||
$text .= $entry['tag'].': ';
|
||||
}
|
||||
$text .= $entry['value'];
|
||||
|
||||
if($entry['tag'] == 'end'){
|
||||
$text .= sprintf(" - %0.4f seconds", $entry['duration'] );
|
||||
}
|
||||
|
||||
$text .= "\n";
|
||||
}
|
||||
return $text;
|
||||
}
|
||||
|
||||
public function set_file($filename, $tag = 'master'){
|
||||
if(!isset($this->file_handle[$tag])){
|
||||
$this->file_handles[$tag] = fopen($filename, 'a');
|
||||
if(!$this->file_handles[$tag]){
|
||||
trigger_error('Could not open file for writing: '.$filename);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function note( $msg, $tag = FALSE )
|
||||
{
|
||||
if($tag){
|
||||
$this->increase_tag_count($tag);
|
||||
}
|
||||
if ( is_array( $msg )) {
|
||||
$msg = '<pre>' . print_r( $msg, TRUE ) . '</pre>';
|
||||
}
|
||||
$this->debug_messages[] = $msg;
|
||||
$this->run_log[] = array( 'type' => 'note',
|
||||
'tag' => $tag ? $tag:"text",
|
||||
'value' => htmlentities($msg),
|
||||
'time' => microtime( TRUE ),
|
||||
'parents' => $this->parent_stack,
|
||||
);
|
||||
|
||||
$this->print_to_file($msg, $tag);
|
||||
$this->print_to_console($msg, $tag);
|
||||
|
||||
}
|
||||
|
||||
public function print_to_file($msg, $tag = FALSE, $type = FALSE){
|
||||
if(!$tag){
|
||||
$file_handle_tag = 'master';
|
||||
}
|
||||
else{
|
||||
$file_handle_tag = $tag;
|
||||
}
|
||||
if($file_handle_tag != 'master' && isset($this->file_handles[$file_handle_tag])){
|
||||
$buffer = $this->get_indent();
|
||||
$buffer .= "$msg\n";
|
||||
if(!empty($this->timestamp)){
|
||||
$buffer = sprintf("[%s] %s",date($this->timestamp, mktime()), $buffer);
|
||||
}
|
||||
fwrite($this->file_handles[$file_handle_tag], wordwrap($buffer, $this->max_line_size, "\n "));
|
||||
}
|
||||
if(isset($this->file_handles['master']) && $this->file_handles['master']){
|
||||
$buffer = $this->get_indent();
|
||||
if($tag){
|
||||
$buffer .= "$tag: ";
|
||||
}
|
||||
$msg = str_replace("\n","",$msg);
|
||||
$buffer .= "$msg";
|
||||
if(!empty($this->timestamp)){
|
||||
$buffer = sprintf("[%s] %s",date($this->timestamp, mktime()), $buffer);
|
||||
}
|
||||
if(strlen($buffer) > $this->max_line_size){
|
||||
$buffer = substr($buffer,0,$this->max_line_size - 3)."...";
|
||||
}
|
||||
fwrite($this->file_handles['master'], $buffer."\n");
|
||||
}
|
||||
}
|
||||
|
||||
public function print_to_console($msg, $tag=FALSE){
|
||||
if($this->print_to_console){
|
||||
if(is_array($this->print_to_console)){
|
||||
if(in_array($tag, $this->print_to_console)){
|
||||
echo $this->get_indent();
|
||||
if($tag){
|
||||
echo "$tag: ";
|
||||
}
|
||||
echo "$msg\n";
|
||||
}
|
||||
}
|
||||
else{
|
||||
echo $this->get_indent();
|
||||
if($tag){
|
||||
echo "$tag: ";
|
||||
}
|
||||
echo "$msg\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function print_totals(){
|
||||
$totals = array();
|
||||
foreach ( $this->run_log as $k => $entry ) {
|
||||
if ( $entry['type'] == 'start' && $entry['ended'] == true) {
|
||||
$totals[$entry['value']]['duration'] += $entry['duration'];
|
||||
$totals[$entry['value']]['count'] += 1;
|
||||
}
|
||||
}
|
||||
if($this->file_handle){
|
||||
foreach($totals as $name=>$details){
|
||||
fwrite($this->file_handle,$name.": ".number_format($details['duration'],4)."sec, ".$details['count']." calls \n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function get_indent(){
|
||||
$buf = "";
|
||||
for($i = 0; $i < $this->indent; $i++){
|
||||
$buf .= " ";
|
||||
}
|
||||
return $buf;
|
||||
}
|
||||
|
||||
|
||||
function __destruct(){
|
||||
foreach($this->file_handles as $handle){
|
||||
fclose($handle);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@ -0,0 +1,39 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Display Emoticons
|
||||
*
|
||||
* Sample plugin to replace emoticons in plain text message body with real icons
|
||||
*
|
||||
* @version 1.0.1
|
||||
* @author Thomas Bruederli
|
||||
* @website http://roundcube.net
|
||||
*/
|
||||
class emoticons extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
private $map;
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->task = 'mail';
|
||||
$this->add_hook('message_part_after', array($this, 'replace'));
|
||||
|
||||
$this->map = array(
|
||||
':)' => html::img(array('src' => './program/js/tiny_mce/plugins/emotions/img/smiley-smile.gif', 'alt' => ':)')),
|
||||
':-)' => html::img(array('src' => './program/js/tiny_mce/plugins/emotions/img/smiley-smile.gif', 'alt' => ':-)')),
|
||||
':(' => html::img(array('src' => './program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif', 'alt' => ':(')),
|
||||
':-(' => html::img(array('src' => './program/js/tiny_mce/plugins/emotions/img/smiley-cry.gif', 'alt' => ':-(')),
|
||||
);
|
||||
}
|
||||
|
||||
function replace($args)
|
||||
{
|
||||
if ($args['type'] == 'plain')
|
||||
return array('body' => strtr($args['body'], $this->map));
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sample plugin to add a new address book
|
||||
* with just a static list of contacts
|
||||
*/
|
||||
class example_addressbook extends rcube_plugin
|
||||
{
|
||||
private $abook_id = 'static';
|
||||
|
||||
public function init()
|
||||
{
|
||||
$this->add_hook('address_sources', array($this, 'address_sources'));
|
||||
$this->add_hook('get_address_book', array($this, 'get_address_book'));
|
||||
|
||||
// use this address book for autocompletion queries
|
||||
// (maybe this should be configurable by the user?)
|
||||
$config = rcmail::get_instance()->config;
|
||||
$sources = $config->get('autocomplete_addressbooks', array('sql'));
|
||||
if (!in_array($this->abook_id, $sources)) {
|
||||
$sources[] = $this->abook_id;
|
||||
$config->set('autocomplete_addressbooks', $sources);
|
||||
}
|
||||
}
|
||||
|
||||
public function address_sources($p)
|
||||
{
|
||||
$p['sources'][$this->abook_id] = array('id' => $this->abook_id, 'name' => 'Static List', 'readonly' => true);
|
||||
return $p;
|
||||
}
|
||||
|
||||
public function get_address_book($p)
|
||||
{
|
||||
if ($p['id'] == $this->abook_id) {
|
||||
require_once(dirname(__FILE__) . '/example_addressbook_backend.php');
|
||||
$p['instance'] = new example_addressbook_backend;
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Example backend class for a custom address book
|
||||
*
|
||||
* This one just holds a static list of address records
|
||||
*
|
||||
* @author Thomas Bruederli
|
||||
*/
|
||||
class example_addressbook_backend extends rcube_addressbook
|
||||
{
|
||||
public $primary_key = 'ID';
|
||||
public $readonly = true;
|
||||
|
||||
private $filter;
|
||||
private $result;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->ready = true;
|
||||
}
|
||||
|
||||
public function set_search_set($filter)
|
||||
{
|
||||
$this->filter = $filter;
|
||||
}
|
||||
|
||||
public function get_search_set()
|
||||
{
|
||||
return $this->filter;
|
||||
}
|
||||
|
||||
public function reset()
|
||||
{
|
||||
$this->result = null;
|
||||
$this->filter = null;
|
||||
}
|
||||
|
||||
public function list_records($cols=null, $subset=0)
|
||||
{
|
||||
$this->result = $this->count();
|
||||
$this->result->add(array('ID' => '111', 'name' => "Example Contact", 'firstname' => "Example", 'surname' => "Contact", 'email' => "example@roundcube.net"));
|
||||
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function search($fields, $value, $strict=false, $select=true)
|
||||
{
|
||||
// no search implemented, just list all records
|
||||
return $this->list_records();
|
||||
}
|
||||
|
||||
public function count()
|
||||
{
|
||||
return new rcube_result_set(1, ($this->list_page-1) * $this->page_size);
|
||||
}
|
||||
|
||||
public function get_result()
|
||||
{
|
||||
return $this->result;
|
||||
}
|
||||
|
||||
public function get_record($id, $assoc=false)
|
||||
{
|
||||
$this->list_records();
|
||||
$first = $this->result->first();
|
||||
$sql_arr = $first['ID'] == $id ? $first : null;
|
||||
|
||||
return $assoc && $sql_arr ? $sql_arr : $this->result;
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,144 @@
|
||||
<?php
|
||||
/**
|
||||
* Filesystem Attachments
|
||||
*
|
||||
* This is a core plugin which provides basic, filesystem based
|
||||
* attachment temporary file handling. This includes storing
|
||||
* attachments of messages currently being composed, writing attachments
|
||||
* to disk when drafts with attachments are re-opened and writing
|
||||
* attachments to disk for inline display in current html compositions.
|
||||
*
|
||||
* Developers may wish to extend this class when creating attachment
|
||||
* handler plugins:
|
||||
* require_once('plugins/filesystem_attachments/filesystem_attachments.php');
|
||||
* class myCustom_attachments extends filesystem_attachments
|
||||
*
|
||||
* @author Ziba Scott <ziba@umich.edu>
|
||||
* @author Thomas Bruederli <roundcube@gmail.com>
|
||||
*
|
||||
*/
|
||||
class filesystem_attachments extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
function init()
|
||||
{
|
||||
// Save a newly uploaded attachment
|
||||
$this->add_hook('upload_attachment', array($this, 'upload'));
|
||||
|
||||
// Save an attachment from a non-upload source (draft or forward)
|
||||
$this->add_hook('save_attachment', array($this, 'save'));
|
||||
|
||||
// Remove an attachment from storage
|
||||
$this->add_hook('remove_attachment', array($this, 'remove'));
|
||||
|
||||
// When composing an html message, image attachments may be shown
|
||||
$this->add_hook('display_attachment', array($this, 'display'));
|
||||
|
||||
// Get the attachment from storage and place it on disk to be sent
|
||||
$this->add_hook('get_attachment', array($this, 'get_attachment'));
|
||||
|
||||
// Delete all temp files associated with this user
|
||||
$this->add_hook('cleanup_attachments', array($this, 'cleanup'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a newly uploaded attachment
|
||||
*/
|
||||
function upload($args)
|
||||
{
|
||||
$args['status'] = false;
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
// use common temp dir for file uploads
|
||||
// #1484529: we need absolute path on Windows for move_uploaded_file()
|
||||
$temp_dir = realpath($rcmail->config->get('temp_dir'));
|
||||
$tmpfname = tempnam($temp_dir, 'rcmAttmnt');
|
||||
|
||||
if (move_uploaded_file($args['path'], $tmpfname) && file_exists($tmpfname)) {
|
||||
$args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1;
|
||||
$args['path'] = $tmpfname;
|
||||
$args['status'] = true;
|
||||
|
||||
// Note the file for later cleanup
|
||||
$_SESSION['plugins']['filesystem_attachments']['tmp_files'][] = $tmpfname;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save an attachment from a non-upload source (draft or forward)
|
||||
*/
|
||||
function save($args)
|
||||
{
|
||||
$args['status'] = false;
|
||||
$rcmail = rcmail::get_instance();
|
||||
$temp_dir = unslashify($rcmail->config->get('temp_dir'));
|
||||
$tmp_path = tempnam($temp_dir, 'rcmAttmnt');
|
||||
|
||||
if ($fp = fopen($tmp_path, 'w')) {
|
||||
fwrite($fp, $args['data']);
|
||||
fclose($fp);
|
||||
|
||||
$args['id'] = count($_SESSION['plugins']['filesystem_attachments']['tmp_files'])+1;
|
||||
$args['path'] = $tmp_path;
|
||||
$args['status'] = true;
|
||||
|
||||
// Note the file for later cleanup
|
||||
$_SESSION['plugins']['filesystem_attachments']['tmp_files'][] = $tmp_path;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an attachment from storage
|
||||
* This is triggered by the remove attachment button on the compose screen
|
||||
*/
|
||||
function remove($args)
|
||||
{
|
||||
$args['status'] = @unlink($args['path']);
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* When composing an html message, image attachments may be shown
|
||||
* For this plugin, the file is already in place, just check for
|
||||
* the existance of the proper metadata
|
||||
*/
|
||||
function display($args)
|
||||
{
|
||||
$args['status'] = file_exists($args['path']);
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* This attachment plugin doesn't require any steps to put the file
|
||||
* on disk for use. This stub function is kept here to make this
|
||||
* class handy as a parent class for other plugins which may need it.
|
||||
*/
|
||||
function get_attachment($args)
|
||||
{
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete all temp files associated with this user
|
||||
*/
|
||||
function cleanup($args)
|
||||
{
|
||||
// $_SESSION['compose']['attachments'] is not a complete record of
|
||||
// temporary files because loading a draft or starting a forward copies
|
||||
// the file to disk, but does not make an entry in that array
|
||||
if (is_array($_SESSION['plugins']['filesystem_attachments']['tmp_files'])){
|
||||
foreach ($_SESSION['plugins']['filesystem_attachments']['tmp_files'] as $filename){
|
||||
if(file_exists($filename)){
|
||||
unlink($filename);
|
||||
}
|
||||
}
|
||||
unset($_SESSION['plugins']['filesystem_attachments']['tmp_files']);
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* HTTP Basic Authentication
|
||||
*
|
||||
* Make use of an existing HTTP authentication and perform login with the existing user credentials
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Thomas Bruederli
|
||||
*/
|
||||
class http_authentication extends rcube_plugin
|
||||
{
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->add_hook('startup', array($this, 'startup'));
|
||||
$this->add_hook('authenticate', array($this, 'authenticate'));
|
||||
}
|
||||
|
||||
function startup($args)
|
||||
{
|
||||
// change action to login
|
||||
if ($args['task'] == 'mail' && empty($args['action']) && empty($_SESSION['user_id'])
|
||||
&& !empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW']))
|
||||
$args['action'] = 'login';
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
function authenticate($args)
|
||||
{
|
||||
if (!empty($_SERVER['PHP_AUTH_USER']) && !empty($_SERVER['PHP_AUTH_PW'])) {
|
||||
$args['user'] = $_SERVER['PHP_AUTH_USER'];
|
||||
$args['pass'] = $_SERVER['PHP_AUTH_PW'];
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 1.9 KiB |
@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['buttontitle'] = 'Mark as Junk';
|
||||
$labels['reportedasjunk'] = 'Successfully reported as Junk';
|
||||
|
||||
?>
|
||||
@ -0,0 +1,28 @@
|
||||
/* Mark-as-Junk plugin script */
|
||||
|
||||
function rcmail_markasjunk(prop)
|
||||
{
|
||||
if (!rcmail.env.uid && (!rcmail.message_list || !rcmail.message_list.get_selection().length))
|
||||
return;
|
||||
|
||||
var uids = rcmail.env.uid ? rcmail.env.uid : rcmail.message_list.get_selection().join(',');
|
||||
|
||||
rcmail.set_busy(true, 'loading');
|
||||
rcmail.http_post('plugin.markasjunk', '_uid='+uids+'&_mbox='+urlencode(rcmail.env.mailbox), true);
|
||||
}
|
||||
|
||||
// callback for app-onload event
|
||||
if (window.rcmail) {
|
||||
rcmail.addEventListener('init', function(evt) {
|
||||
|
||||
// register command (directly enable in message view mode)
|
||||
rcmail.register_command('plugin.markasjunk', rcmail_markasjunk, rcmail.env.uid);
|
||||
|
||||
// add event-listener to message list
|
||||
if (rcmail.message_list)
|
||||
rcmail.message_list.addEventListener('select', function(list){
|
||||
rcmail.enable_command('plugin.markasjunk', list.get_selection().length > 0);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
@ -0,0 +1,47 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Mark as Junk
|
||||
*
|
||||
* Sample plugin that adds a new button to the mailbox toolbar
|
||||
* to mark the selected messages as Junk and move them to the Junk folder
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Thomas Bruederli
|
||||
*/
|
||||
class markasjunk extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->register_action('plugin.markasjunk', array($this, 'request_action'));
|
||||
$GLOBALS['IMAP_FLAGS']['JUNK'] = 'Junk';
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
if ($rcmail->action == '' || $rcmail->action == 'show') {
|
||||
$this->include_script('markasjunk.js');
|
||||
$this->add_texts('localization', true);
|
||||
$this->add_button(array('command' => 'plugin.markasjunk', 'imagepas' => 'junk_pas.png', 'imageact' => 'junk_act.png'), 'toolbar');
|
||||
}
|
||||
}
|
||||
|
||||
function request_action()
|
||||
{
|
||||
$this->add_texts('localization');
|
||||
|
||||
$uids = get_input_value('_uid', RCUBE_INPUT_POST);
|
||||
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->imap->set_flag($uids, 'JUNK');
|
||||
|
||||
if (($junk_mbox = $rcmail->config->get('junk_mbox')) && $mbox != $junk_mbox) {
|
||||
$rcmail->output->command('move_messages', $junk_mbox);
|
||||
}
|
||||
|
||||
$rcmail->output->command('display_message', $this->gettext('reportedasjunk'), 'confirmation');
|
||||
$rcmail->output->send();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
/**
|
||||
* New user identity
|
||||
*
|
||||
* Populates a new user's default identity from LDAP on their first visit.
|
||||
*
|
||||
* This plugin requires that a working public_ldap directory be configured.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Kris Steinhoff
|
||||
*
|
||||
* Example configuration:
|
||||
*
|
||||
* // The id of the address book to use to automatically set a new
|
||||
* // user's full name in their new identity. (This should be an
|
||||
* // string, which refers to the $rcmail_config['ldap_public'] array.)
|
||||
* $rcmail_config['new_user_identity_addressbook'] = 'People';
|
||||
*
|
||||
* // When automatically setting a new users's full name in their
|
||||
* // new identity, match the user's login name against this field.
|
||||
* $rcmail_config['new_user_identity_match'] = 'uid';
|
||||
*
|
||||
* // Use the value in this field to automatically set a new users's
|
||||
* // full name in their new identity.
|
||||
* $rcmail_config['new_user_identity_field'] = 'name';
|
||||
*/
|
||||
class new_user_identity extends rcube_plugin
|
||||
{
|
||||
function init()
|
||||
{
|
||||
$this->add_hook('create_user', array($this, 'lookup_user_name'));
|
||||
}
|
||||
|
||||
function lookup_user_name($args)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
if ($addressbook = $rcmail->config->get('new_user_identity_addressbook')) {
|
||||
$match = $rcmail->config->get('new_user_identity_match');
|
||||
$ldap = $rcmail->get_address_book($addressbook);
|
||||
$ldap->prop['search_fields'] = array($match);
|
||||
$results = $ldap->search($match, $args['user'], TRUE);
|
||||
if (count($results->records) == 1) {
|
||||
$args['user_name'] = $results->records[0][$rcmail->config->get('new_user_identity_field')];
|
||||
}
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
?>
|
||||
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['changepasswd'] = 'Change Password';
|
||||
$labels['curpasswd'] = 'Current Password:';
|
||||
$labels['newpasswd'] = 'New Password:';
|
||||
$labels['confpasswd'] = 'Confirm New Password:';
|
||||
|
||||
$messages = array();
|
||||
$messages['nopassword'] = "Please input new password.";
|
||||
$messages['nocurpassword'] = "Please input current password.";
|
||||
$messages['passwordincorrectly'] = "Current password incorrectly.";
|
||||
$messages['passwordinconsistency'] = "Inconsistency of password, please try again.";
|
||||
|
||||
?>
|
||||
@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['changepasswd'] = 'Zmiana hasła';
|
||||
$labels['curpasswd'] = 'Aktualne hasło:';
|
||||
$labels['newpasswd'] = 'Nowe hasło:';
|
||||
$labels['confpasswd'] = 'Potwierdź hasło:';
|
||||
|
||||
$messages = array();
|
||||
$messages['nopassword'] = 'Wprowadź nowe hasło.';
|
||||
$messages['nocurpassword'] = 'Wprowadź aktualne hasło.';
|
||||
$messages['passwordincorrect'] = 'Błędne aktualne hasło, spróbuj ponownie.';
|
||||
$messages['passwordinconsistency'] = 'Hasła nie pasują, spróbuj ponownie.';
|
||||
|
||||
?>
|
||||
@ -0,0 +1,44 @@
|
||||
/* Password change interface (tab) */
|
||||
|
||||
if (window.rcmail) {
|
||||
rcmail.addEventListener('init', function(evt) {
|
||||
// <span id="settingstabdefault" class="tablink"><roundcube:button command="preferences" type="link" label="preferences" title="editpreferences" /></span>
|
||||
var tab = $('<span>').attr('id', 'settingstabpluginpassword').addClass('tablink');
|
||||
|
||||
var button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.password').html(rcmail.gettext('password')).appendTo(tab);
|
||||
button.bind('click', function(e){ return rcmail.command('plugin.password', this) });
|
||||
|
||||
// add button and register commands
|
||||
rcmail.add_element(tab, 'tabs');
|
||||
rcmail.register_command('plugin.password', function() { rcmail.goto_url('plugin.password') }, true);
|
||||
rcmail.register_command('plugin.password-save', function() {
|
||||
var input_curpasswd = rcube_find_object('_curpasswd');
|
||||
var input_newpasswd = rcube_find_object('_newpasswd');
|
||||
var input_confpasswd = rcube_find_object('_confpasswd');
|
||||
|
||||
if (input_curpasswd && input_curpasswd.value=='') {
|
||||
alert(rcmail.gettext('nocurpassword', 'password'));
|
||||
input_curpasswd.focus();
|
||||
} else if (input_newpasswd && input_newpasswd.value=='') {
|
||||
alert(rcmail.gettext('nopassword', 'password'));
|
||||
input_newpasswd.focus();
|
||||
} else if (input_confpasswd && input_confpasswd.value=='') {
|
||||
alert(rcmail.gettext('nopassword', 'password'));
|
||||
input_confpasswd.focus();
|
||||
} else if ((input_newpasswd && input_confpasswd) && (input_newpasswd.value != input_confpasswd.value)) {
|
||||
alert(rcmail.gettext('passwordinconsistency', 'password'));
|
||||
input_newpasswd.focus();
|
||||
} else {
|
||||
rcmail.gui_objects.passform.submit();
|
||||
}
|
||||
}, true);
|
||||
})
|
||||
|
||||
// set page title
|
||||
if (rcmail.env.action == 'plugin.password' && rcmail.env.task == 'settings') {
|
||||
var title = rcmail.gettext('changepasswd','password')
|
||||
if (rcmail.env.product_name)
|
||||
title = rcmail.env.product_name + ' :: ' + title;
|
||||
rcmail.set_pagetitle(title);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,160 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Change Password
|
||||
*
|
||||
* Sample plugin that adds a possibility to change password
|
||||
* (Settings -> Password tab)
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Aleksander 'A.L.E.C' Machniak
|
||||
*/
|
||||
class password extends rcube_plugin
|
||||
{
|
||||
public $task = 'settings';
|
||||
|
||||
function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
// add Tab label
|
||||
$rcmail->output->add_label('password');
|
||||
$this->register_action('plugin.password', array($this, 'password_init'));
|
||||
$this->register_action('plugin.password-save', array($this, 'password_save'));
|
||||
$this->register_handler('plugin.body', array($this, 'password_form'));
|
||||
$this->include_script('password.js');
|
||||
}
|
||||
|
||||
function password_init()
|
||||
{
|
||||
$this->add_texts('localization/');
|
||||
rcmail::get_instance()->output->send('plugin');
|
||||
}
|
||||
|
||||
function password_save()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
$this->add_texts('localization/');
|
||||
|
||||
if (!isset($_POST['_curpasswd']) || !isset($_POST['_newpasswd']))
|
||||
$rcmail->output->command('display_message', $this->gettext('nopassword'), 'error');
|
||||
else {
|
||||
$curpwd = get_input_value('_curpasswd', RCUBE_INPUT_POST);
|
||||
$newpwd = get_input_value('_newpasswd', RCUBE_INPUT_POST);
|
||||
|
||||
if ($_SESSION['password'] != $rcmail->encrypt_passwd($curpwd))
|
||||
$rcmail->output->command('display_message', $this->gettext('passwordincorrect'), 'error');
|
||||
else if ($res = $this->_save($newpwd)) {
|
||||
$rcmail->output->command('display_message', $this->gettext('successfullysaved'), 'confirmation');
|
||||
$_SESSION['password'] = $rcmail->encrypt_passwd($newpwd);
|
||||
} else
|
||||
$rcmail->output->command('display_message', $this->gettext('errorsaving'), 'error');
|
||||
}
|
||||
|
||||
rcmail_overwrite_action('plugin.password');
|
||||
rcmail::get_instance()->output->send('plugin');
|
||||
}
|
||||
|
||||
function password_form()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
|
||||
// add some labels to client
|
||||
$rcmail->output->add_label(
|
||||
'password.nopassword',
|
||||
'password.nocurpassword',
|
||||
'password.passwordinconsistency',
|
||||
'password.changepasswd'
|
||||
);
|
||||
// $rcmail->output->set_pagetitle($this->gettext('changepasswd'));
|
||||
$rcmail->output->set_env('product_name', $rcmail->config->get('product_name'));
|
||||
|
||||
// allow the following attributes to be added to the <table> tag
|
||||
$attrib_str = create_attrib_string($attrib, array('style', 'class', 'id', 'cellpadding', 'cellspacing', 'border', 'summary'));
|
||||
|
||||
// return the complete edit form as table
|
||||
$out = '<table' . $attrib_str . ">\n\n";
|
||||
|
||||
$a_show_cols = array('curpasswd' => array('type' => 'text'),
|
||||
'newpasswd' => array('type' => 'text'),
|
||||
'confpasswd' => array('type' => 'text'));
|
||||
|
||||
// show current password selection
|
||||
$field_id = 'curpasswd';
|
||||
$input_newpasswd = new html_passwordfield(array('name' => '_curpasswd', 'id' => $field_id, 'size' => 20));
|
||||
|
||||
$out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
|
||||
$field_id,
|
||||
rep_specialchars_output($this->gettext('curpasswd')),
|
||||
$input_newpasswd->show($rcmail->config->get('curpasswd')));
|
||||
|
||||
// show new password selection
|
||||
$field_id = 'newpasswd';
|
||||
$input_newpasswd = new html_passwordfield(array('name' => '_newpasswd', 'id' => $field_id, 'size' => 20));
|
||||
|
||||
$out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
|
||||
$field_id,
|
||||
rep_specialchars_output($this->gettext('newpasswd')),
|
||||
$input_newpasswd->show($rcmail->config->get('newpasswd')));
|
||||
|
||||
// show confirm password selection
|
||||
$field_id = 'confpasswd';
|
||||
$input_confpasswd = new html_passwordfield(array('name' => '_confpasswd', 'id' => $field_id, 'size' => 20));
|
||||
|
||||
$out .= sprintf("<tr><td class=\"title\"><label for=\"%s\">%s</label></td><td>%s</td></tr>\n",
|
||||
$field_id,
|
||||
rep_specialchars_output($this->gettext('confpasswd')),
|
||||
$input_confpasswd->show($rcmail->config->get('confpasswd')));
|
||||
|
||||
$out .= "\n</table>";
|
||||
|
||||
$out .= '<br />';
|
||||
|
||||
$out .= $rcmail->output->button(array(
|
||||
'command' => 'plugin.password-save',
|
||||
'type' => 'input',
|
||||
'class' => 'button mainaction',
|
||||
'label' => 'save'
|
||||
));
|
||||
|
||||
$rcmail->output->add_gui_object('passform', 'password-form');
|
||||
|
||||
return $rcmail->output->form_tag(array(
|
||||
'id' => 'password-form',
|
||||
'name' => 'password-form',
|
||||
'method' => 'post',
|
||||
'action' => './?_task=settings&_action=plugin.password-save',
|
||||
), $out);
|
||||
}
|
||||
|
||||
|
||||
private function _save($passwd)
|
||||
{
|
||||
$cfg = rcmail::get_instance()->config;
|
||||
|
||||
if (!($sql = $cfg->get('password_query')))
|
||||
$sql = "SELECT update_passwd('%p', '%u')";
|
||||
|
||||
$sql = str_replace('%u', $_SESSION['username'], $sql);
|
||||
$sql = str_replace('%p', crypt($passwd), $sql);
|
||||
|
||||
if ($dsn = $cfg->get('db_passwd_dsn')) {
|
||||
$db = new rcube_mdb2($dsn, '', FALSE);
|
||||
$db->set_debug((bool)$cfg->get('sql_debug'));
|
||||
$db->db_connect('w');
|
||||
} else {
|
||||
$db = rcmail::get_instance()->get_dbh();
|
||||
}
|
||||
|
||||
if (!$db->db_connected)
|
||||
return false;
|
||||
|
||||
$res = $db->query($sql);
|
||||
$res = $db->fetch_array($res);
|
||||
|
||||
return $res;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@ -0,0 +1,49 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Show additional message headers
|
||||
*
|
||||
* Proof-of-concept plugin which will fetch additional headers
|
||||
* and display them in the message view.
|
||||
*
|
||||
* Enable the plugin in config/main.inc.php and add your desired headers:
|
||||
* $rcmail_config['show_additional_headers'] = array('User-Agent');
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Thomas Bruederli
|
||||
* @website http://roundcube.net
|
||||
*/
|
||||
class show_additional_headers extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
if ($rcmail->action == 'show' || $rcmail->action == 'preview') {
|
||||
$this->add_hook('imap_init', array($this, 'imap_init'));
|
||||
$this->add_hook('message_headers_output', array($this, 'message_headers'));
|
||||
}
|
||||
}
|
||||
|
||||
function imap_init($p)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
if ($add_headers = $rcmail->config->get('show_additional_headers', array()))
|
||||
$p['fetch_headers'] = trim($p['fetch_headers'].' ' . strtoupper(join(' ', $add_headers)));
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
function message_headers($p)
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
foreach ($rcmail->config->get('show_additional_headers', array()) as $header) {
|
||||
$key = strtolower($header);
|
||||
if ($value = $p['headers']->others[$key])
|
||||
$p['output'][$key] = array('title' => $header, 'value' => $value);
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,6 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['useimapsubscriptions'] = 'Use IMAP Subscriptions';
|
||||
|
||||
?>
|
||||
@ -0,0 +1,84 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Subscription Options
|
||||
*
|
||||
* A plugin which can enable or disable the use of imap subscriptions.
|
||||
* It includes a toggle on the settings page under "Server Settings".
|
||||
* The preference can also be locked
|
||||
*
|
||||
* Add it to the plugins list in config/main.inc.php to enable the user option
|
||||
* The user option can be hidden and set globally by adding 'use_subscriptions'
|
||||
* to the the 'dont_override' configure line:
|
||||
* $rcmail_config['dont_override'] = array('use_subscriptions');
|
||||
* and then set the global preference"
|
||||
* $rcmail_config['use_subscriptions'] = true; // or false
|
||||
*
|
||||
* Roundcube caches folder lists. When a user changes this option or visits
|
||||
* their folder list, this cache is refreshed. If the option is on the
|
||||
* 'dont_override' list and the global option has changed, don't expect
|
||||
* to see the change until the folder list cache is refreshed.
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Ziba Scott
|
||||
*/
|
||||
class subscriptions_option extends rcube_plugin
|
||||
{
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->add_texts('localization/', false);
|
||||
$dont_override = rcmail::get_instance()->config->get('dont_override', array());
|
||||
if (!in_array('use_subscriptions', $dont_override)){
|
||||
$this->add_hook('user_preferences', array($this, 'settings_table'));
|
||||
$this->add_hook('save_preferences', array($this, 'save_prefs'));
|
||||
}
|
||||
$this->add_hook('list_mailboxes', array($this, 'list_mailboxes'));
|
||||
$this->add_hook('manage_folders', array($this, 'manage_folders'));
|
||||
}
|
||||
|
||||
function settings_table($args)
|
||||
{
|
||||
if ($args['section'] == 'server') {
|
||||
$use_subscriptions = rcmail::get_instance()->config->get('use_subscriptions');
|
||||
$field_id = 'rcmfd_use_subscriptions';
|
||||
$use_subscriptions = new html_checkbox(array('name' => '_use_subscriptions', 'id' => $field_id, 'value' => 1));
|
||||
|
||||
$args['table']->add('title', html::label($field_id, Q($this->gettext('useimapsubscriptions'))));
|
||||
$args['table']->add(null, $use_subscriptions->show($use_subscriptions?1:0));
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
function save_prefs($args){
|
||||
$rcmail = rcmail::get_instance();
|
||||
$use_subscriptions = $rcmail->config->get('use_subscriptions');
|
||||
|
||||
$args['prefs']['use_subscriptions'] = isset($_POST['_use_subscriptions']) ? true : false;
|
||||
// if the use_subscriptions preference changes, flush the folder cache
|
||||
if (($use_subscriptions && !isset($_POST['_use_subscriptions'])) ||
|
||||
(!$use_subscriptions && isset($_POST['_use_subscriptions']))) {
|
||||
$rcmail->imap_init(true);
|
||||
$rcmail->imap->clear_cache('mailboxes');
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
function list_mailboxes($args){
|
||||
$rcmail = rcmail::get_instance();
|
||||
if (!$rcmail->config->get('use_subscriptions', true)) {
|
||||
$args['folders'] = iil_C_ListMailboxes($rcmail->imap->conn, $rcmail->imap->_mod_mailbox($args['root']), $args['filter']);
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
|
||||
function manage_folders($args){
|
||||
$rcmail = rcmail::get_instance();
|
||||
if (!$rcmail->config->get('use_subscriptions', true)) {
|
||||
$args['table']->remove_column('subscribed');
|
||||
}
|
||||
return $args;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['userinfo'] = 'Benutzerinfo';
|
||||
$labels['created'] = 'Erstellt';
|
||||
$labels['lastlogin'] = 'Letztes Login';
|
||||
$labels['defaultidentity'] = 'Standard-Absender';
|
||||
|
||||
?>
|
||||
@ -0,0 +1,9 @@
|
||||
<?php
|
||||
|
||||
$labels = array();
|
||||
$labels['userinfo'] = 'User info';
|
||||
$labels['created'] = 'Created';
|
||||
$labels['lastlogin'] = 'Last Login';
|
||||
$labels['defaultidentity'] = 'Default Identity';
|
||||
|
||||
?>
|
||||
@ -0,0 +1,16 @@
|
||||
/* Show user-info plugin script */
|
||||
|
||||
if (window.rcmail) {
|
||||
rcmail.addEventListener('init', function(evt) {
|
||||
// <span id="settingstabdefault" class="tablink"><roundcube:button command="preferences" type="link" label="preferences" title="editpreferences" /></span>
|
||||
var tab = $('<span>').attr('id', 'settingstabpluginuserinfo').addClass('tablink');
|
||||
|
||||
var button = $('<a>').attr('href', rcmail.env.comm_path+'&_action=plugin.userinfo').html(rcmail.gettext('userinfo', 'userinfo')).appendTo(tab);
|
||||
button.bind('click', function(e){ return rcmail.command('plugin.userinfo', this) });
|
||||
|
||||
// add button and register command
|
||||
rcmail.add_element(tab, 'tabs');
|
||||
rcmail.register_command('plugin.userinfo', function(){ rcmail.goto_url('plugin.userinfo') }, true);
|
||||
})
|
||||
}
|
||||
|
||||
@ -0,0 +1,53 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Sample plugin that adds a new tab to the settings section
|
||||
* to display some information about the current user
|
||||
*/
|
||||
class userinfo extends rcube_plugin
|
||||
{
|
||||
public $task = 'settings';
|
||||
|
||||
function init()
|
||||
{
|
||||
$this->add_texts('localization/', array('userinfo'));
|
||||
$this->register_action('plugin.userinfo', array($this, 'infostep'));
|
||||
$this->include_script('userinfo.js');
|
||||
}
|
||||
|
||||
function infostep()
|
||||
{
|
||||
$this->register_handler('plugin.body', array($this, 'infohtml'));
|
||||
rcmail::get_instance()->output->send('plugin');
|
||||
}
|
||||
|
||||
function infohtml()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$user = $rcmail->user;
|
||||
|
||||
$table = new html_table(array('cols' => 2, 'cellpadding' => 3));
|
||||
|
||||
$table->add('title', 'ID');
|
||||
$table->add('', Q($user->ID));
|
||||
|
||||
$table->add('title', Q($this->gettext('username')));
|
||||
$table->add('', Q($user->data['username']));
|
||||
|
||||
$table->add('title', Q($this->gettext('server')));
|
||||
$table->add('', Q($user->data['mail_host']));
|
||||
|
||||
$table->add('title', Q($this->gettext('created')));
|
||||
$table->add('', Q($user->data['created']));
|
||||
|
||||
$table->add('title', Q($this->gettext('lastlogin')));
|
||||
$table->add('', Q($user->data['last_login']));
|
||||
|
||||
$identity = $user->get_identity();
|
||||
$table->add('title', Q($this->gettext('defaultidentity')));
|
||||
$table->add('', Q($identity['name'] . ' <' . $identity['email'] . '>'));
|
||||
|
||||
return html::tag('h4', null, Q('Infos for ' . $user->get_username())) . $table->show();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Detect VCard attachments and show a button to add them to address book
|
||||
*
|
||||
* @version 1.0
|
||||
* @author Thomas Bruederli
|
||||
*/
|
||||
class vcard_attachments extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail';
|
||||
|
||||
private $message;
|
||||
private $vcard_part;
|
||||
|
||||
function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
if ($rcmail->action == 'show' || $rcmail->action == 'preview') {
|
||||
$this->add_hook('message_load', array($this, 'message_load'));
|
||||
$this->add_hook('template_object_messagebody', array($this, 'html_output'));
|
||||
}
|
||||
|
||||
$this->register_action('plugin.savevcard', array($this, 'save_vcard'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check message attachments for vcards
|
||||
*/
|
||||
function message_load($p)
|
||||
{
|
||||
$this->message = $p['object'];
|
||||
|
||||
foreach ((array)$this->message->attachments as $attachment) {
|
||||
if (in_array($attachment->mimetype, array('text/vcard', 'text/x-vcard')))
|
||||
$this->vcard_part = $attachment->mime_id;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This callback function adds a box below the message content
|
||||
* if there is a vcard attachment available
|
||||
*/
|
||||
function html_output($p)
|
||||
{
|
||||
if ($this->vcard_part) {
|
||||
$vcard = new rcube_vcard($this->message->get_part_content($this->vcard_part));
|
||||
|
||||
// successfully parsed vcard
|
||||
if ($vcard->displayname) {
|
||||
$display = $vcard->displayname;
|
||||
if ($vcard->email[0])
|
||||
$display .= ' <'.$vcard->email[0].'>';
|
||||
|
||||
// add box below messsage body
|
||||
$p['content'] .= html::p(array('style' => "margin:1em; padding:0.5em; border:1px solid #999; width: auto;"),
|
||||
html::a(array(
|
||||
'href' => "#",
|
||||
'onclick' => "return plugin_vcard_save_contact('".JQ($this->vcard_part)."')",
|
||||
'title' => "Save contact in local address book"), // TODO: localize this title
|
||||
html::img(array('src' => '/images/buttons/add_contact_act.png', 'align' => "middle")))
|
||||
. ' ' . html::span(null, Q($display)));
|
||||
|
||||
$this->include_script('vcardattach.js');
|
||||
}
|
||||
}
|
||||
|
||||
return $p;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handler for request action
|
||||
*/
|
||||
function save_vcard()
|
||||
{
|
||||
$uid = get_input_value('_uid', RCUBE_INPUT_POST);
|
||||
$mbox = get_input_value('_mbox', RCUBE_INPUT_POST);
|
||||
$mime_id = get_input_value('_part', RCUBE_INPUT_POST);
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$part = $uid && $mime_id ? $rcmail->imap->get_message_part($uid, $mime_id) : null;
|
||||
|
||||
$error_msg = 'Failed to saved vcard'; // TODO: localize this text
|
||||
|
||||
if ($part && ($vcard = new rcube_vcard($part)) && $vcard->displayname && $vcard->email) {
|
||||
$contacts = $rcmail->get_address_book(null, true);
|
||||
|
||||
// check for existing contacts
|
||||
$existing = $contacts->search('email', $vcard->email[0], true, false);
|
||||
if ($done = $existing->count) {
|
||||
$rcmail->output->command('display_message', $this->gettext('contactexists'), 'warning');
|
||||
}
|
||||
else {
|
||||
// add contact
|
||||
$success = $contacts->insert(array(
|
||||
'name' => $vcard->displayname,
|
||||
'firstname' => $vcard->firstname,
|
||||
'surname' => $vcard->surname,
|
||||
'email' => $vcard->email[0],
|
||||
'vcard' => $vcard->export(),
|
||||
));
|
||||
|
||||
if ($success)
|
||||
$rcmail->output->command('display_message', $this->gettext('addedsuccessfully'), 'confirmation');
|
||||
else
|
||||
$rcmail->output->command('display_message', $error_msg, 'error');
|
||||
}
|
||||
}
|
||||
else
|
||||
$rcmail->output->command('display_message', $error_msg, 'error');
|
||||
|
||||
$rcmail->output->send();
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,10 @@
|
||||
|
||||
function plugin_vcard_save_contact(mime_id)
|
||||
{
|
||||
rcmail.set_busy(true, 'loading');
|
||||
rcmail.http_post('plugin.savevcard', '_uid='+rcmail.env.uid+'&_mbox='+urlencode(rcmail.env.mailbox)+'&_part='+urlencode(mime_id), true);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,169 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/include/rcube_addressbook.php |
|
||||
| |
|
||||
| This file is part of the RoundCube Webmail client |
|
||||
| Copyright (C) 2006-2009, RoundCube Dev. - Switzerland |
|
||||
| Licensed under the GNU GPL |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Interface to the local address book database |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
$Id: $
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Abstract skeleton of an address book/repository
|
||||
*
|
||||
* @package Addressbook
|
||||
*/
|
||||
abstract class rcube_addressbook
|
||||
{
|
||||
/** public properties */
|
||||
var $primary_key;
|
||||
var $readonly = true;
|
||||
var $ready = false;
|
||||
var $list_page = 1;
|
||||
var $page_size = 10;
|
||||
|
||||
/**
|
||||
* Save a search string for future listings
|
||||
*
|
||||
* @param mixed Search params to use in listing method, obtained by get_search_set()
|
||||
*/
|
||||
abstract function set_search_set($filter);
|
||||
|
||||
/**
|
||||
* Getter for saved search properties
|
||||
*
|
||||
* @return mixed Search properties used by this class
|
||||
*/
|
||||
abstract function get_search_set();
|
||||
|
||||
/**
|
||||
* Reset saved results and search parameters
|
||||
*/
|
||||
abstract function reset();
|
||||
|
||||
/**
|
||||
* List the current set of contact records
|
||||
*
|
||||
* @param array List of cols to show
|
||||
* @param int Only return this number of records, use negative values for tail
|
||||
* @return array Indexed list of contact records, each a hash array
|
||||
*/
|
||||
abstract function list_records($cols=null, $subset=0);
|
||||
|
||||
/**
|
||||
* Search records
|
||||
*
|
||||
* @param array List of fields to search in
|
||||
* @param string Search value
|
||||
* @param boolean True if results are requested, False if count only
|
||||
* @return Indexed list of contact records and 'count' value
|
||||
*/
|
||||
abstract function search($fields, $value, $strict=false, $select=true);
|
||||
|
||||
/**
|
||||
* Count number of available contacts in database
|
||||
*
|
||||
* @return object rcube_result_set Result set with values for 'count' and 'first'
|
||||
*/
|
||||
abstract function count();
|
||||
|
||||
/**
|
||||
* Return the last result set
|
||||
*
|
||||
* @return object rcube_result_set Current result set or NULL if nothing selected yet
|
||||
*/
|
||||
abstract function get_result();
|
||||
|
||||
/**
|
||||
* Get a specific contact record
|
||||
*
|
||||
* @param mixed record identifier(s)
|
||||
* @param boolean True to return record as associative array, otherwise a result set is returned
|
||||
* @return mixed Result object with all record fields or False if not found
|
||||
*/
|
||||
abstract function get_record($id, $assoc=false);
|
||||
|
||||
/**
|
||||
* Close connection to source
|
||||
* Called on script shutdown
|
||||
*/
|
||||
function close() { }
|
||||
|
||||
/**
|
||||
* Set internal list page
|
||||
*
|
||||
* @param number Page number to list
|
||||
* @access public
|
||||
*/
|
||||
function set_page($page)
|
||||
{
|
||||
$this->list_page = (int)$page;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set internal page size
|
||||
*
|
||||
* @param number Number of messages to display on one page
|
||||
* @access public
|
||||
*/
|
||||
function set_pagesize($size)
|
||||
{
|
||||
$this->page_size = (int)$size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new contact record
|
||||
*
|
||||
* @param array Assoziative array with save data
|
||||
* @param boolean True to check for duplicates first
|
||||
* @return The created record ID on success, False on error
|
||||
*/
|
||||
function insert($save_data, $check=false)
|
||||
{
|
||||
/* empty for read-only address books */
|
||||
}
|
||||
|
||||
/**
|
||||
* Update a specific contact record
|
||||
*
|
||||
* @param mixed Record identifier
|
||||
* @param array Assoziative array with save data
|
||||
* @return True on success, False on error
|
||||
*/
|
||||
function update($id, $save_cols)
|
||||
{
|
||||
/* empty for read-only address books */
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark one or more contact records as deleted
|
||||
*
|
||||
* @param array Record identifiers
|
||||
*/
|
||||
function delete($ids)
|
||||
{
|
||||
/* empty for read-only address books */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove all records from the database
|
||||
*/
|
||||
function delete_all()
|
||||
{
|
||||
/* empty for read-only address books */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,196 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/include/rcube_plugin.php |
|
||||
| |
|
||||
| This file is part of the RoundCube Webmail client |
|
||||
| Copyright (C) 2008-2009, RoundCube Dev. - Switzerland |
|
||||
| Licensed under the GNU GPL |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Abstract plugins interface/class |
|
||||
| All plugins need to extend this class |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
$Id: $
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* Plugin interface class
|
||||
*
|
||||
* @package Core
|
||||
*/
|
||||
abstract class rcube_plugin
|
||||
{
|
||||
public $ID;
|
||||
public $api;
|
||||
public $task;
|
||||
protected $home;
|
||||
protected $urlbase;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public function __construct($api)
|
||||
{
|
||||
$this->ID = get_class($this);
|
||||
$this->api = $api;
|
||||
$this->home = $api->dir . DIRECTORY_SEPARATOR . $this->ID;
|
||||
$this->urlbase = $api->url . $this->ID . '/';
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialization method, needs to be implemented by the plugin itself
|
||||
*/
|
||||
abstract function init();
|
||||
|
||||
/**
|
||||
* Register a callback function for a specific (server-side) hook
|
||||
*
|
||||
* @param string Hook name
|
||||
* @param mixed Callback function as string or array with object reference and method name
|
||||
*/
|
||||
public function add_hook($hook, $callback)
|
||||
{
|
||||
$this->api->register_hook($hook, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load localized texts from the plugins dir
|
||||
*
|
||||
* @param string Directory to search in
|
||||
* @param mixed Make texts also available on the client (array with list or true for all)
|
||||
*/
|
||||
public function add_texts($dir, $add2client = false)
|
||||
{
|
||||
$domain = $this->ID;
|
||||
|
||||
$lang = $_SESSION['language'];
|
||||
$locdir = slashify(realpath(slashify($this->home) . $dir));
|
||||
$texts = array();
|
||||
|
||||
foreach (array('en_US', $lang) as $lng) {
|
||||
@include($locdir . $lng . '.inc');
|
||||
$texts = (array)$labels + (array)$messages + (array)$texts;
|
||||
}
|
||||
|
||||
// prepend domain to text keys and add to the application texts repository
|
||||
if (!empty($texts)) {
|
||||
$add = array();
|
||||
foreach ($texts as $key => $value)
|
||||
$add[$domain.'.'.$key] = $value;
|
||||
|
||||
$rcmail = rcmail::get_instance();
|
||||
$rcmail->load_language($lang, $add);
|
||||
|
||||
// add labels to client
|
||||
if ($add2client) {
|
||||
$js_labels = is_array($add2client) ? array_map(array($this, 'label_map_callback'), $add2client) : array_keys($add);
|
||||
$rcmail->output->add_label($js_labels);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper for rcmail::gettext() adding the plugin ID as domain
|
||||
*
|
||||
* @return string Localized text
|
||||
* @see rcmail::gettext()
|
||||
*/
|
||||
function gettext($p)
|
||||
{
|
||||
return rcmail::get_instance()->gettext($p, $this->ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler for a specific client-request action
|
||||
*
|
||||
* The callback will be executed upon a request like /?_task=mail&_action=plugin.myaction
|
||||
*
|
||||
* @param string Action name (should be unique)
|
||||
* @param mixed Callback function as string or array with object reference and method name
|
||||
*/
|
||||
public function register_action($action, $callback)
|
||||
{
|
||||
$this->api->register_action($action, $this->ID, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a handler function for a template object
|
||||
*
|
||||
* When parsing a template for display, tags like <roundcube:object name="plugin.myobject" />
|
||||
* will be replaced by the return value if the registered callback function.
|
||||
*
|
||||
* @param string Object name (should be unique and start with 'plugin.')
|
||||
* @param mixed Callback function as string or array with object reference and method name
|
||||
*/
|
||||
public function register_handler($name, $callback)
|
||||
{
|
||||
$this->api->register_handler($name, $this->ID, $callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this javascipt file available on the client
|
||||
*
|
||||
* @param string File path; absolute or relative to the plugin directory
|
||||
*/
|
||||
public function include_script($fn)
|
||||
{
|
||||
$this->api->include_script($this->ressource_url($fn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Make this stylesheet available on the client
|
||||
*
|
||||
* @param string File path; absolute or relative to the plugin directory
|
||||
*/
|
||||
public function include_stylesheet($fn)
|
||||
{
|
||||
$this->api->include_stylesheet($this->ressource_url($fn));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a button to a certain container
|
||||
*
|
||||
* @param array Hash array with named parameters (as used in skin templates)
|
||||
* @param string Container name where the buttons should be added to
|
||||
* @see rcube_remplate::button()
|
||||
*/
|
||||
public function add_button($p, $container)
|
||||
{
|
||||
if ($this->api->output->type == 'html') {
|
||||
// fix relative paths
|
||||
foreach (array('imagepas', 'imageact', 'imagesel') as $key)
|
||||
if ($p[$key])
|
||||
$p[$key] = $this->api->url . $this->ressource_url($p[$key]);
|
||||
|
||||
$this->api->add_content($this->api->output->button($p), $container);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given file name link into the plugin directory
|
||||
*/
|
||||
private function ressource_url($fn)
|
||||
{
|
||||
if ($fn[0] != '/' && !eregi('^https?://', $fn))
|
||||
return $this->ID . '/' . $fn;
|
||||
else
|
||||
return $fn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback function for array_map
|
||||
*/
|
||||
private function label_map_callback($key)
|
||||
{
|
||||
return $this->ID.'.'.$key;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,312 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
+-----------------------------------------------------------------------+
|
||||
| program/include/rcube_plugin_api.php |
|
||||
| |
|
||||
| This file is part of the RoundCube Webmail client |
|
||||
| Copyright (C) 2008-2009, RoundCube Dev. - Switzerland |
|
||||
| Licensed under the GNU GPL |
|
||||
| |
|
||||
| PURPOSE: |
|
||||
| Plugins repository |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
| Author: Thomas Bruederli <roundcube@gmail.com> |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
$Id: $
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* The plugin loader and global API
|
||||
*
|
||||
* @package Core
|
||||
*/
|
||||
class rcube_plugin_api
|
||||
{
|
||||
static private $instance;
|
||||
|
||||
public $dir;
|
||||
public $url = 'plugins/';
|
||||
public $output;
|
||||
|
||||
public $handlers = array();
|
||||
private $plugins = array();
|
||||
private $actions = array();
|
||||
private $actionmap = array();
|
||||
private $objectsmap = array();
|
||||
private $template_contents = array();
|
||||
|
||||
private $required_plugins = array('filesystem_attachments');
|
||||
|
||||
/**
|
||||
* This implements the 'singleton' design pattern
|
||||
*
|
||||
* @return object rcube_plugin_api The one and only instance if this class
|
||||
*/
|
||||
static function get_instance()
|
||||
{
|
||||
if (!self::$instance) {
|
||||
self::$instance = new rcube_plugin_api();
|
||||
}
|
||||
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Private constructor
|
||||
*/
|
||||
private function __construct()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$this->dir = realpath($rcmail->config->get('plugins_dir'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Load and init all enabled plugins
|
||||
*
|
||||
* This has to be done after rcmail::load_gui() or rcmail::init_json()
|
||||
* was called because plugins need to have access to rcmail->output
|
||||
*/
|
||||
public function init()
|
||||
{
|
||||
$rcmail = rcmail::get_instance();
|
||||
$this->output = $rcmail->output;
|
||||
|
||||
$plugins_dir = dir($this->dir);
|
||||
$plugins_enabled = (array)$rcmail->config->get('plugins', array());
|
||||
|
||||
foreach ($plugins_enabled as $plugin_name) {
|
||||
$fn = $plugins_dir->path . DIRECTORY_SEPARATOR . $plugin_name . DIRECTORY_SEPARATOR . $plugin_name . '.php';
|
||||
|
||||
if (file_exists($fn)) {
|
||||
include($fn);
|
||||
|
||||
// instantiate class if exists
|
||||
if (class_exists($plugin_name, false)) {
|
||||
$plugin = new $plugin_name($this);
|
||||
// check inheritance and task specification
|
||||
if (is_subclass_of($plugin, 'rcube_plugin') && (!$plugin->task || $plugin->task == $rcmail->task)) {
|
||||
$plugin->init();
|
||||
$this->plugins[] = $plugin;
|
||||
}
|
||||
}
|
||||
else {
|
||||
raise_error(array('code' => 520, 'type' => 'php', 'message' => "No plugin class $plugin_name found in $fn"), true, false);
|
||||
}
|
||||
}
|
||||
else {
|
||||
raise_error(array('code' => 520, 'type' => 'php', 'message' => "Failed to load plugin file $fn"), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
// check existance of all required core plugins
|
||||
foreach ($this->required_plugins as $plugin_name) {
|
||||
$loaded = false;
|
||||
foreach ($this->plugins as $plugin) {
|
||||
if ($plugin instanceof $plugin_name) {
|
||||
$loaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// load required core plugin if no derivate was found
|
||||
if (!$loaded) {
|
||||
$fn = $plugins_dir->path . DIRECTORY_SEPARATOR . $plugin_name . DIRECTORY_SEPARATOR . $plugin_name . '.php';
|
||||
if (file_exists($fn)) {
|
||||
include($fn);
|
||||
|
||||
if (class_exists($plugin_name, false)) {
|
||||
$plugin = new $plugin_name($this);
|
||||
// check inheritance
|
||||
if (is_subclass_of($plugin, 'rcube_plugin')) {
|
||||
$plugin->init();
|
||||
$this->plugins[] = $plugin;
|
||||
$loaded = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// trigger fatal error if still not loaded
|
||||
if (!$loaded) {
|
||||
raise_error(array('code' => 520, 'type' => 'php', 'message' => "Requried plugin $plugin_name was not loaded"), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
// register an internal hook
|
||||
$this->register_hook('template_container', array($this, 'template_container_hook'));
|
||||
|
||||
// maybe also register a shudown function which triggers shutdown functions of all plugin objects
|
||||
|
||||
|
||||
// call imap_init right now
|
||||
// (should actually be done in rcmail::imap_init() but plugins are not initialized then)
|
||||
if ($rcmail->imap) {
|
||||
$hook = $this->exec_hook('imap_init', array('fetch_headers' => $rcmail->imap->fetch_add_headers));
|
||||
if ($hook['fetch_headers'])
|
||||
$rcmail->imap->fetch_add_headers = $hook['fetch_headers'];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Allows a plugin object to register a callback for a certain hook
|
||||
*
|
||||
* @param string Hook name
|
||||
* @param mixed String with global function name or array($obj, 'methodname')
|
||||
*/
|
||||
public function register_hook($hook, $callback)
|
||||
{
|
||||
if (is_callable($callback))
|
||||
$this->handlers[$hook][] = $callback;
|
||||
else
|
||||
raise_error(array('code' => 521, 'type' => 'php', 'message' => "Invalid callback function for $hook"), true, false);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Triggers a plugin hook.
|
||||
* This is called from the application and executes all registered handlers
|
||||
*
|
||||
* @param string Hook name
|
||||
* @param array Named arguments (key->value pairs)
|
||||
* @return array The (probably) altered hook arguments
|
||||
*/
|
||||
public function exec_hook($hook, $args = array())
|
||||
{
|
||||
$args += array('abort' => false);
|
||||
|
||||
foreach ((array)$this->handlers[$hook] as $callback) {
|
||||
$ret = call_user_func($callback, $args);
|
||||
if ($ret && is_array($ret))
|
||||
$args = $ret + $args;
|
||||
|
||||
if ($args['abort'])
|
||||
break;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Let a plugin register a handler for a specific request
|
||||
*
|
||||
* @param string Action name (_task=mail&_action=plugin.foo)
|
||||
* @param string Plugin name that registers this action
|
||||
* @param mixed Callback: string with global function name or array($obj, 'methodname')
|
||||
*/
|
||||
public function register_action($action, $owner, $callback)
|
||||
{
|
||||
// check action name
|
||||
if (strpos($action, 'plugin.') !== 0)
|
||||
$action = 'plugin.'.$action;
|
||||
|
||||
// can register action only if it's not taken or registered by myself
|
||||
if (!isset($this->actionmap[$action]) || $this->actionmap[$action] == $owner) {
|
||||
$this->actions[$action] = $callback;
|
||||
$this->actionmap[$action] = $owner;
|
||||
}
|
||||
else {
|
||||
raise_error(array('code' => 523, 'type' => 'php', 'message' => "Cannot register action $action; already taken by another plugin"), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method handles requests like _task=mail&_action=plugin.foo
|
||||
* It executes the callback function that was registered with the given action.
|
||||
*
|
||||
* @param string Action name
|
||||
*/
|
||||
public function exec_action($action)
|
||||
{
|
||||
if (isset($this->actions[$action])) {
|
||||
call_user_func($this->actions[$action]);
|
||||
}
|
||||
else {
|
||||
raise_error(array('code' => 524, 'type' => 'php', 'message' => "No handler found for action $action"), true, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register a handler function for template objects
|
||||
*
|
||||
* @param string Object name
|
||||
* @param string Plugin name that registers this action
|
||||
* @param mixed Callback: string with global function name or array($obj, 'methodname')
|
||||
*/
|
||||
public function register_handler($name, $owner, $callback)
|
||||
{
|
||||
// check name
|
||||
if (strpos($name, 'plugin.') !== 0)
|
||||
$name = 'plugin.'.$name;
|
||||
|
||||
// can register handler only if it's not taken or registered by myself
|
||||
if (!isset($this->objectsmap[$name]) || $this->objectsmap[$name] == $owner) {
|
||||
$this->output->add_handler($name, $callback);
|
||||
$this->objectsmap[$name] = $owner;
|
||||
}
|
||||
else {
|
||||
raise_error(array('code' => 525, 'type' => 'php', 'message' => "Cannot register template handler $name; already taken by another plugin"), true, false);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Include a plugin script file in the current HTML page
|
||||
*/
|
||||
public function include_script($fn)
|
||||
{
|
||||
if ($this->output->type == 'html') {
|
||||
$src = $this->ressource_url($fn);
|
||||
$this->output->add_header(html::tag('script', array('type' => "text/javascript", 'src' => $src)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Include a plugin stylesheet in the current HTML page
|
||||
*/
|
||||
public function include_stylesheet($fn)
|
||||
{
|
||||
if ($this->output->type == 'html') {
|
||||
$src = $this->ressource_url($fn);
|
||||
$this->output->add_header(html::tag('link', array('rel' => "stylesheet", 'type' => "text/css", 'href' => $src)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the given HTML content to be added to a template container
|
||||
*/
|
||||
public function add_content($html, $container)
|
||||
{
|
||||
$this->template_contents[$container] .= $html . "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback for template_container hooks
|
||||
*/
|
||||
private function template_container_hook($attrib)
|
||||
{
|
||||
$container = $attrib['name'];
|
||||
return array('content' => $this->template_contents[$container]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given file name link into the plugins directory
|
||||
*/
|
||||
private function ressource_url($fn)
|
||||
{
|
||||
if ($fn[0] != '/' && !eregi('^https?://', $fn))
|
||||
return $this->url . $fn;
|
||||
else
|
||||
return $fn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,24 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title><roundcube:object name="pagetitle" /></title>
|
||||
<roundcube:include file="/includes/links.html" />
|
||||
<link rel="stylesheet" type="text/css" href="/<roundcube:var name='env:task'/>.css" />
|
||||
<script type="text/javascript" src="/functions.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<roundcube:include file="/includes/taskbar.html" />
|
||||
<roundcube:include file="/includes/header.html" />
|
||||
<roundcube:if condition="env:task == 'settings'" />
|
||||
<roundcube:include file="/includes/settingstabs.html" />
|
||||
<roundcube:endif />
|
||||
|
||||
<div id="pagecontent">
|
||||
<roundcube:object name="plugin.body" />
|
||||
</div>
|
||||
|
||||
<roundcube:object name="plugin.footer" />
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Reference in New Issue