Show spam aliases #
This commit is contained in:
29
data/web/rc/plugins/emoticons/composer.json
Normal file
29
data/web/rc/plugins/emoticons/composer.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"name": "roundcube/emoticons",
|
||||
"type": "roundcube-plugin",
|
||||
"description": "Plugin that adds emoticons support.",
|
||||
"license": "GPLv3+",
|
||||
"version": "2.0",
|
||||
"authors": [
|
||||
{
|
||||
"name": "Thomas Bruederli",
|
||||
"email": "roundcube@gmail.com",
|
||||
"role": "Lead"
|
||||
},
|
||||
{
|
||||
"name": "Aleksander Machniak",
|
||||
"email": "alec@alec.pl",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"repositories": [
|
||||
{
|
||||
"type": "composer",
|
||||
"url": "http://plugins.roundcube.net"
|
||||
}
|
||||
],
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"roundcube/plugin-installer": ">=0.1.3"
|
||||
}
|
||||
}
|
7
data/web/rc/plugins/emoticons/config.inc.php.dist
Normal file
7
data/web/rc/plugins/emoticons/config.inc.php.dist
Normal file
@@ -0,0 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Enable emoticons in plain text messages preview
|
||||
$config['emoticons_display'] = false;
|
||||
|
||||
// Enable emoticons in compose editor (HTML)
|
||||
$config['emoticons_compose'] = true;
|
185
data/web/rc/plugins/emoticons/emoticons.php
Normal file
185
data/web/rc/plugins/emoticons/emoticons.php
Normal file
@@ -0,0 +1,185 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Emoticons
|
||||
*
|
||||
* Plugin to replace emoticons in plain text message body with real icons.
|
||||
* Also it enables emoticons in HTML compose editor. Both features are optional.
|
||||
*
|
||||
* @license GNU GPLv3+
|
||||
* @author Thomas Bruederli
|
||||
* @author Aleksander Machniak
|
||||
* @website http://roundcube.net
|
||||
*/
|
||||
class emoticons extends rcube_plugin
|
||||
{
|
||||
public $task = 'mail|settings|utils';
|
||||
|
||||
|
||||
/**
|
||||
* Plugin initilization.
|
||||
*/
|
||||
function init()
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
|
||||
$this->add_hook('message_part_after', array($this, 'message_part_after'));
|
||||
$this->add_hook('message_outgoing_body', array($this, 'message_outgoing_body'));
|
||||
$this->add_hook('html2text', array($this, 'html2text'));
|
||||
$this->add_hook('html_editor', array($this, 'html_editor'));
|
||||
|
||||
if ($rcube->task == 'settings') {
|
||||
$this->add_hook('preferences_list', array($this, 'preferences_list'));
|
||||
$this->add_hook('preferences_save', array($this, 'preferences_save'));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 'message_part_after' hook handler to replace common plain text emoticons
|
||||
* with emoticon images (<img>)
|
||||
*/
|
||||
function message_part_after($args)
|
||||
{
|
||||
if ($args['type'] == 'plain') {
|
||||
$this->load_config();
|
||||
|
||||
$rcube = rcube::get_instance();
|
||||
if (!$rcube->config->get('emoticons_display', false)) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/emoticons_engine.php';
|
||||
|
||||
$args['body'] = emoticons_engine::text2icons($args['body']);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'message_outgoing_body' hook handler to replace image emoticons from TinyMCE
|
||||
* editor with image attachments.
|
||||
*/
|
||||
function message_outgoing_body($args)
|
||||
{
|
||||
if ($args['type'] == 'html') {
|
||||
$this->load_config();
|
||||
|
||||
$rcube = rcube::get_instance();
|
||||
if (!$rcube->config->get('emoticons_compose', true)) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/emoticons_engine.php';
|
||||
|
||||
// look for "emoticon" images from TinyMCE and change their src paths to
|
||||
// be file paths on the server instead of URL paths.
|
||||
$images = emoticons_engine::replace($args['body']);
|
||||
|
||||
// add these images as attachments to the MIME message
|
||||
foreach ($images as $img_name => $img_file) {
|
||||
$args['message']->addHTMLImage($img_file, 'image/gif', '', true, $img_name);
|
||||
}
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'html2text' hook handler to replace image emoticons from TinyMCE
|
||||
* editor with plain text emoticons.
|
||||
*
|
||||
* This is executed on html2text action, i.e. when switching from HTML to text
|
||||
* in compose window (or similiar place). Also when generating alternative
|
||||
* text/plain part.
|
||||
*/
|
||||
function html2text($args)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
|
||||
if ($rcube->action == 'html2text' || $rcube->action == 'send') {
|
||||
$this->load_config();
|
||||
|
||||
if (!$rcube->config->get('emoticons_compose', true)) {
|
||||
return $args;
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/emoticons_engine.php';
|
||||
|
||||
$args['body'] = emoticons_engine::icons2text($args['body']);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'html_editor' hook handler, where we enable emoticons in TinyMCE
|
||||
*/
|
||||
function html_editor($args)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
|
||||
$this->load_config();
|
||||
|
||||
if ($rcube->config->get('emoticons_compose', true)) {
|
||||
$args['extra_plugins'][] = 'emoticons';
|
||||
$args['extra_buttons'][] = 'emoticons';
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'preferences_list' hook handler
|
||||
*/
|
||||
function preferences_list($args)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$dont_override = $rcube->config->get('dont_override', array());
|
||||
|
||||
if ($args['section'] == 'mailview' && !in_array('emoticons_display', $dont_override)) {
|
||||
$this->load_config();
|
||||
$this->add_texts('localization');
|
||||
|
||||
$field_id = 'emoticons_display';
|
||||
$checkbox = new html_checkbox(array('name' => '_' . $field_id, 'id' => $field_id, 'value' => 1));
|
||||
|
||||
$args['blocks']['main']['options']['emoticons_display'] = array(
|
||||
'title' => $this->gettext('emoticonsdisplay'),
|
||||
'content' => $checkbox->show(intval($rcube->config->get('emoticons_display', false)))
|
||||
);
|
||||
}
|
||||
else if ($args['section'] == 'compose' && !in_array('emoticons_compose', $dont_override)) {
|
||||
$this->load_config();
|
||||
$this->add_texts('localization');
|
||||
|
||||
$field_id = 'emoticons_compose';
|
||||
$checkbox = new html_checkbox(array('name' => '_' . $field_id, 'id' => $field_id, 'value' => 1));
|
||||
|
||||
$args['blocks']['main']['options']['emoticons_compose'] = array(
|
||||
'title' => $this->gettext('emoticonscompose'),
|
||||
'content' => $checkbox->show(intval($rcube->config->get('emoticons_compose', true)))
|
||||
);
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
|
||||
/**
|
||||
* 'preferences_save' hook handler
|
||||
*/
|
||||
function preferences_save($args)
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$dont_override = $rcube->config->get('dont_override', array());
|
||||
|
||||
if ($args['section'] == 'mailview' && !in_array('emoticons_display', $dont_override)) {
|
||||
$args['prefs']['emoticons_display'] = rcube_utils::get_input_value('_emoticons_display', rcube_utils::INPUT_POST) ? true : false;
|
||||
}
|
||||
else if ($args['section'] == 'compose' && !in_array('emoticons_compose', $dont_override)) {
|
||||
$args['prefs']['emoticons_compose'] = rcube_utils::get_input_value('_emoticons_compose', rcube_utils::INPUT_POST) ? true : false;
|
||||
}
|
||||
|
||||
return $args;
|
||||
}
|
||||
}
|
152
data/web/rc/plugins/emoticons/emoticons_engine.php
Normal file
152
data/web/rc/plugins/emoticons/emoticons_engine.php
Normal file
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @license GNU GPLv3+
|
||||
* @author Thomas Bruederli
|
||||
* @author Aleksander Machniak
|
||||
*/
|
||||
class emoticons_engine
|
||||
{
|
||||
const IMG_PATH = 'program/js/tinymce/plugins/emoticons/img/';
|
||||
|
||||
/**
|
||||
* Replaces TinyMCE's emoticon images with plain-text representation
|
||||
*
|
||||
* @param string $html HTML content
|
||||
*
|
||||
* @return string HTML content
|
||||
*/
|
||||
public static function icons2text($html)
|
||||
{
|
||||
$emoticons = array(
|
||||
'8-)' => 'smiley-cool',
|
||||
':-#' => 'smiley-foot-in-mouth',
|
||||
':-*' => 'smiley-kiss',
|
||||
':-X' => 'smiley-sealed',
|
||||
':-P' => 'smiley-tongue-out',
|
||||
':-@' => 'smiley-yell',
|
||||
":'(" => 'smiley-cry',
|
||||
':-(' => 'smiley-frown',
|
||||
':-D' => 'smiley-laughing',
|
||||
':-)' => 'smiley-smile',
|
||||
':-S' => 'smiley-undecided',
|
||||
':-$' => 'smiley-embarassed',
|
||||
'O:-)' => 'smiley-innocent',
|
||||
':-|' => 'smiley-money-mouth',
|
||||
':-O' => 'smiley-surprised',
|
||||
';-)' => 'smiley-wink',
|
||||
);
|
||||
|
||||
foreach ($emoticons as $idx => $file) {
|
||||
// <img title="Cry" src="http://.../program/js/tinymce/plugins/emoticons/img/smiley-cry.gif" border="0" alt="Cry" />
|
||||
$file = preg_quote(self::IMG_PATH . $file . '.gif', '/');
|
||||
$search[] = '/<img (title="[a-z ]+" )?src="[^"]+' . $file . '"[^>]+\/>/i';
|
||||
$replace[] = $idx;
|
||||
}
|
||||
|
||||
return preg_replace($search, $replace, $html);
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace common plain text emoticons with empticon <img> tags
|
||||
*
|
||||
* @param string $text Text
|
||||
*
|
||||
* @return string Converted text
|
||||
*/
|
||||
public static function text2icons($text)
|
||||
{
|
||||
// This is a lookbehind assertion which will exclude html entities
|
||||
// E.g. situation when ";)" in "")" shouldn't be replaced by the icon
|
||||
// It's so long because of assertion format restrictions
|
||||
$entity = '(?<!&'
|
||||
. '[a-zA-Z0-9]{2}' . '|' . '#[0-9]{2}' . '|'
|
||||
. '[a-zA-Z0-9]{3}' . '|' . '#[0-9]{3}' . '|'
|
||||
. '[a-zA-Z0-9]{4}' . '|' . '#[0-9]{4}' . '|'
|
||||
. '[a-zA-Z0-9]{5}' . '|'
|
||||
. '[a-zA-Z0-9]{6}' . '|'
|
||||
. '[a-zA-Z0-9]{7}'
|
||||
. ')';
|
||||
|
||||
// map of emoticon replacements
|
||||
$map = array(
|
||||
'/(?<!mailto):D/' => self::img_tag('smiley-laughing.gif', ':D' ),
|
||||
'/:-D/' => self::img_tag('smiley-laughing.gif', ':-D' ),
|
||||
'/:\(/' => self::img_tag('smiley-frown.gif', ':(' ),
|
||||
'/:-\(/' => self::img_tag('smiley-frown.gif', ':-(' ),
|
||||
'/'.$entity.';\)/' => self::img_tag('smiley-wink.gif', ';)' ),
|
||||
'/'.$entity.';-\)/' => self::img_tag('smiley-wink.gif', ';-)' ),
|
||||
'/8\)/' => self::img_tag('smiley-cool.gif', '8)' ),
|
||||
'/8-\)/' => self::img_tag('smiley-cool.gif', '8-)' ),
|
||||
'/(?<!mailto):O/i' => self::img_tag('smiley-surprised.gif', ':O' ),
|
||||
'/(?<!mailto):-O/i' => self::img_tag('smiley-surprised.gif', ':-O' ),
|
||||
'/(?<!mailto):P/i' => self::img_tag('smiley-tongue-out.gif', ':P' ),
|
||||
'/(?<!mailto):-P/i' => self::img_tag('smiley-tongue-out.gif', ':-P' ),
|
||||
'/(?<!mailto):@/i' => self::img_tag('smiley-yell.gif', ':@' ),
|
||||
'/(?<!mailto):-@/i' => self::img_tag('smiley-yell.gif', ':-@' ),
|
||||
'/O:\)/i' => self::img_tag('smiley-innocent.gif', 'O:)' ),
|
||||
'/O:-\)/i' => self::img_tag('smiley-innocent.gif', 'O:-)' ),
|
||||
'/(?<!O):\)/' => self::img_tag('smiley-smile.gif', ':)' ),
|
||||
'/(?<!O):-\)/' => self::img_tag('smiley-smile.gif', ':-)' ),
|
||||
'/(?<!mailto):\$/' => self::img_tag('smiley-embarassed.gif', ':$' ),
|
||||
'/(?<!mailto):-\$/' => self::img_tag('smiley-embarassed.gif', ':-$' ),
|
||||
'/(?<!mailto):\*/i' => self::img_tag('smiley-kiss.gif', ':*' ),
|
||||
'/(?<!mailto):-\*/i' => self::img_tag('smiley-kiss.gif', ':-*' ),
|
||||
'/(?<!mailto):S/i' => self::img_tag('smiley-undecided.gif', ':S' ),
|
||||
'/(?<!mailto):-S/i' => self::img_tag('smiley-undecided.gif', ':-S' ),
|
||||
);
|
||||
|
||||
return preg_replace(array_keys($map), array_values($map), $text);
|
||||
}
|
||||
|
||||
protected static function img_tag($ico, $title)
|
||||
{
|
||||
return html::img(array('src' => './' . self::IMG_PATH . $ico, 'title' => $title));
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace emoticon icons <img> 'src' attribute, so it can
|
||||
* be replaced with real file by Mail_Mime.
|
||||
*
|
||||
* @param string &$html HTML content
|
||||
*
|
||||
* @return array List of image files
|
||||
*/
|
||||
public static function replace(&$html)
|
||||
{
|
||||
// Replace this:
|
||||
// <img src="http[s]://.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... />
|
||||
// with this:
|
||||
// <img src="/path/on/server/.../tinymce/plugins/emoticons/img/smiley-cool.gif" ... />
|
||||
|
||||
$rcube = rcube::get_instance();
|
||||
$assets_dir = $rcube->config->get('assets_dir');
|
||||
$path = unslashify($assets_dir ?: INSTALL_PATH) . '/' . self::IMG_PATH;
|
||||
$offset = 0;
|
||||
$images = array();
|
||||
|
||||
// remove any null-byte characters before parsing
|
||||
$html = preg_replace('/\x00/', '', $html);
|
||||
|
||||
if (preg_match_all('# src=[\'"]([^\'"]+)#', $html, $matches, PREG_OFFSET_CAPTURE)) {
|
||||
foreach ($matches[1] as $m) {
|
||||
// find emoticon image tags
|
||||
if (preg_match('#'. self::IMG_PATH . '(.*)$#', $m[0], $imatches)) {
|
||||
$image_name = $imatches[1];
|
||||
|
||||
// sanitize image name so resulting attachment doesn't leave images dir
|
||||
$image_name = preg_replace('/[^a-zA-Z0-9_\.\-]/i', '', $image_name);
|
||||
$image_file = $path . $image_name;
|
||||
|
||||
// Add the same image only once
|
||||
$images[$image_name] = $image_file;
|
||||
|
||||
$html = substr_replace($html, $image_file, $m[1] + $offset, strlen($m[0]));
|
||||
$offset += strlen($image_file) - strlen($m[0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $images;
|
||||
}
|
||||
}
|
23
data/web/rc/plugins/emoticons/localization/en_US.inc
Normal file
23
data/web/rc/plugins/emoticons/localization/en_US.inc
Normal file
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
+-----------------------------------------------------------------------+
|
||||
| plugins/emoticons/localization/<lang>.inc |
|
||||
| |
|
||||
| Localization file of the Roundcube Webmail Emoticons plugin |
|
||||
| Copyright (C) 2012-2015, 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. |
|
||||
| |
|
||||
+-----------------------------------------------------------------------+
|
||||
|
||||
For translation see https://www.transifex.com/projects/p/roundcube-webmail/resource/plugin-emoticons/
|
||||
*/
|
||||
|
||||
$labels = array();
|
||||
$labels['emoticonsdisplay'] = 'Display emoticons in plain text messages';
|
||||
$labels['emoticonscompose'] = 'Enable emoticons';
|
||||
|
||||
?>
|
22
data/web/rc/plugins/emoticons/tests/Emoticons.php
Normal file
22
data/web/rc/plugins/emoticons/tests/Emoticons.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
class Emoticons_Plugin extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
function setUp()
|
||||
{
|
||||
include_once __DIR__ . '/../emoticons.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin object construction test
|
||||
*/
|
||||
function test_constructor()
|
||||
{
|
||||
$rcube = rcube::get_instance();
|
||||
$plugin = new emoticons($rcube->api);
|
||||
|
||||
$this->assertInstanceOf('emoticons', $plugin);
|
||||
$this->assertInstanceOf('rcube_plugin', $plugin);
|
||||
}
|
||||
}
|
48
data/web/rc/plugins/emoticons/tests/EmoticonsEngine.php
Normal file
48
data/web/rc/plugins/emoticons/tests/EmoticonsEngine.php
Normal file
@@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
class EmoticonsEngine extends PHPUnit_Framework_TestCase
|
||||
{
|
||||
|
||||
function setUp()
|
||||
{
|
||||
include_once __DIR__ . '/../emoticons_engine.php';
|
||||
}
|
||||
|
||||
/**
|
||||
* text2icons() method tests
|
||||
*/
|
||||
function test_text2icons()
|
||||
{
|
||||
$map = array(
|
||||
':D' => array('smiley-laughing.gif', ':D' ),
|
||||
':-D' => array('smiley-laughing.gif', ':-D' ),
|
||||
':(' => array('smiley-frown.gif', ':(' ),
|
||||
':-(' => array('smiley-frown.gif', ':-(' ),
|
||||
'8)' => array('smiley-cool.gif', '8)' ),
|
||||
'8-)' => array('smiley-cool.gif', '8-)' ),
|
||||
':O' => array('smiley-surprised.gif', ':O' ),
|
||||
':-O' => array('smiley-surprised.gif', ':-O' ),
|
||||
':P' => array('smiley-tongue-out.gif', ':P' ),
|
||||
':-P' => array('smiley-tongue-out.gif', ':-P' ),
|
||||
':@' => array('smiley-yell.gif', ':@' ),
|
||||
':-@' => array('smiley-yell.gif', ':-@' ),
|
||||
'O:)' => array('smiley-innocent.gif', 'O:)' ),
|
||||
'O:-)' => array('smiley-innocent.gif', 'O:-)' ),
|
||||
':)' => array('smiley-smile.gif', ':)' ),
|
||||
':-)' => array('smiley-smile.gif', ':-)' ),
|
||||
':$' => array('smiley-embarassed.gif', ':$' ),
|
||||
':-$' => array('smiley-embarassed.gif', ':-$' ),
|
||||
':*' => array('smiley-kiss.gif', ':*' ),
|
||||
':-*' => array('smiley-kiss.gif', ':-*' ),
|
||||
':S' => array('smiley-undecided.gif', ':S' ),
|
||||
':-S' => array('smiley-undecided.gif', ':-S' ),
|
||||
);
|
||||
|
||||
foreach ($map as $body => $expected) {
|
||||
$result = emoticons_engine::text2icons($body);
|
||||
|
||||
$this->assertRegExp('/' . preg_quote($expected[0], '/') . '/', $result);
|
||||
$this->assertRegExp('/title="' . preg_quote($expected[1], '/') . '"/', $result);
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user