Bring back unit tests (they should be removed when creating a package)

pull/181/head
Aleksander Machniak 10 years ago
parent e445e0acb5
commit b37954110d

@ -0,0 +1,34 @@
<?php
/**
* Test class to test rcube_base_replacer class
*
* @package Tests
*/
class Framework_BaseReplacer extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_base_replacer('test');
$this->assertInstanceOf('rcube_base_replacer', $object, "Class constructor");
}
/**
* Test replace()
*/
function test_replace()
{
$base = 'http://thisshouldntbetheurl.bob.com/';
$html = '<A href=http://shouldbethislink.com>Test URL</A>';
$replacer = new rcube_base_replacer($base);
$response = $replacer->replace($html);
$this->assertSame('<A href="http://shouldbethislink.com">Test URL</A>', $response);
}
}

@ -0,0 +1,218 @@
<?php
/**
* Test class to test rcube_shared functions
*
* @package Tests
*/
class Framework_Bootstrap extends PHPUnit_Framework_TestCase
{
/**
* bootstrap.php: in_array_nocase()
*/
function test_in_array_nocase()
{
$haystack = array('Test');
$needle = 'test';
$result = in_array_nocase($needle, $haystack);
$this->assertTrue($result, $title);
$result = in_array_nocase($needle, null);
$this->assertFalse($result, $title);
}
/**
* bootstrap.php: parse_bytes()
*/
function test_parse_bytes()
{
$data = array(
'1' => 1,
'1024' => 1024,
'2k' => 2 * 1024,
'2 k' => 2 * 1024,
'2kb' => 2 * 1024,
'2kB' => 2 * 1024,
'2m' => 2 * 1048576,
'2 m' => 2 * 1048576,
'2mb' => 2 * 1048576,
'2mB' => 2 * 1048576,
'2g' => 2 * 1024 * 1048576,
'2 g' => 2 * 1024 * 1048576,
'2gb' => 2 * 1024 * 1048576,
'2gB' => 2 * 1024 * 1048576,
);
foreach ($data as $value => $expected) {
$result = parse_bytes($value);
$this->assertEquals($expected, $result, "Invalid parse_bytes() result for $value");
}
}
/**
* bootstrap.php: slashify()
*/
function test_slashify()
{
$data = array(
'test' => 'test/',
'test/' => 'test/',
'' => '/',
"\\" => "\\/",
);
foreach ($data as $value => $expected) {
$result = slashify($value);
$this->assertEquals($expected, $result, "Invalid slashify() result for $value");
}
}
/**
* bootstrap.php: unslashify()
*/
function test_unslashify()
{
$data = array(
'test' => 'test',
'test/' => 'test',
'/' => '',
"\\/" => "\\",
'test/test' => 'test/test',
'test//' => 'test',
);
foreach ($data as $value => $expected) {
$result = unslashify($value);
$this->assertEquals($expected, $result, "Invalid unslashify() result for $value");
}
}
/**
* bootstrap.php: get_offset_sec()
*/
function test_get_offset_sec()
{
$data = array(
'1s' => 1,
'1m' => 1 * 60,
'1h' => 1 * 60 * 60,
'1d' => 1 * 60 * 60 * 24,
'1w' => 1 * 60 * 60 * 24 * 7,
'1y' => (int) '1y',
100 => 100,
'100' => 100,
);
foreach ($data as $value => $expected) {
$result = get_offset_sec($value);
$this->assertEquals($expected, $result, "Invalid get_offset_sec() result for $value");
}
}
/**
* bootstrap.php: array_keys_recursive()
*/
function test_array_keys_recursive()
{
$input = array(
'one' => array(
'two' => array(
'three' => array(),
'four' => 'something',
),
),
'five' => 'test',
);
$result = array_keys_recursive($input);
$input_str = 'one,two,three,four,five';
$result_str = implode(',', $result);
$this->assertEquals($input_str, $result_str, "Invalid array_keys_recursive() result");
}
/**
* bootstrap.php: format_email()
*/
function test_format_email()
{
$data = array(
'' => '',
'test' => 'test',
'test@test.tld' => 'test@test.tld',
'test@[127.0.0.1]' => 'test@[127.0.0.1]',
'TEST@TEST.TLD' => 'TEST@test.tld',
);
foreach ($data as $value => $expected) {
$result = format_email($value);
$this->assertEquals($expected, $result, "Invalid format_email() result for $value");
}
}
/**
* bootstrap.php: format_email_recipient()
*/
function test_format_email_recipient()
{
$data = array(
'' => array(''),
'test' => array('test'),
'test@test.tld' => array('test@test.tld'),
'test@[127.0.0.1]' => array('test@[127.0.0.1]'),
'TEST@TEST.TLD' => array('TEST@TEST.TLD'),
'TEST <test@test.tld>' => array('test@test.tld', 'TEST'),
'"TEST\"" <test@test.tld>' => array('test@test.tld', 'TEST"'),
);
foreach ($data as $expected => $value) {
$result = format_email_recipient($value[0], $value[1]);
$this->assertEquals($expected, $result, "Invalid format_email_recipient()");
}
}
/**
* bootstrap.php: is_ascii()
*/
function test_is_ascii()
{
$result = is_ascii("0123456789");
$this->assertTrue($result, "Valid ASCII (numbers)");
$result = is_ascii("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
$this->assertTrue($result, "Valid ASCII (letters)");
$result = is_ascii(" !\"#\$%&'()*+,-./:;<=>?@[\\^_`{|}~");
$this->assertTrue($result, "Valid ASCII (special characters)");
$result = is_ascii("\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F"
."\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F");
$this->assertTrue($result, "Valid ASCII (control characters)");
$result = is_ascii("\n", false);
$this->assertFalse($result, "Valid ASCII (control characters)");
$result = is_ascii("ż");
$this->assertFalse($result, "Invalid ASCII (UTF-8 character)");
$result = is_ascii("ż", false);
$this->assertFalse($result, "Invalid ASCII (UTF-8 character [2])");
}
/**
* bootstrap.php: version_parse()
*/
function test_version_parse()
{
$this->assertEquals('0.9.0', version_parse('0.9-stable'));
$this->assertEquals('0.9.99', version_parse('0.9-git'));
}
}

@ -0,0 +1,253 @@
<?php
/**
* Test class to test rcube_browser class
*
* @package Tests
*/
class Framework_Browser extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_browser();
$this->assertInstanceOf('rcube_browser', $object, "Class constructor");
}
/**
* @dataProvider browsers
*/
function test_browser($useragent, $opera, $chrome, $ie, $ns, $safari, $mz)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($opera, $object->opera, 'Check for Opera failed');
$this->assertEquals($chrome, $object->chrome, 'Check for Chrome failed');
$this->assertEquals($ie, $object->ie, 'Check for IE failed');
$this->assertEquals($ns, $object->ns, 'Check for NS failed');
$this->assertEquals($safari, $object->safari, 'Check for Safari failed');
$this->assertEquals($mz, $object->mz, 'Check for MZ failed');
}
/**
* @dataProvider os
*/
function test_os($useragent, $windows, $linux, $unix, $mac)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($windows, $object->win, 'Check Result of Windows');
$this->assertEquals($linux, $object->linux, 'Check Result of Linux');
$this->assertEquals($mac, $object->mac, 'Check Result of Mac');
$this->assertEquals($unix, $object->unix, 'Check Result of Unix');
}
/**
* @dataProvider versions
*/
function test_version($useragent, $version)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($version, $object->ver);
}
/**
* @dataProvider dom
*/
function test_dom($useragent, $dom)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($dom, $object->dom);
}
/**
* @dataProvider pngalpha
*/
function test_pngalpha($useragent, $pngalpha)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($pngalpha, $object->pngalpha);
}
/**
* @dataProvider imgdata
*/
function test_imgdata($useragent, $imgdata)
{
$object = $this->getBrowser($useragent);
$this->assertEquals($imgdata, $object->imgdata);
}
function versions()
{
return $this->extractDataSet(array('version'));
}
function pngalpha()
{
return $this->extractDataSet(array('canPNGALPHA'));
}
function imgdata()
{
return $this->extractDataSet(array('canIMGDATA'));
}
private function extractDataSet($keys)
{
$keys = array_merge(array('useragent'), $keys);
$browser = $this->useragents();
$extracted = array();
foreach ($browser as $label => $data) {
foreach($keys as $key) {
$extracted[$data['useragent']][] = $data[$key];
}
}
return $extracted;
}
function lang()
{
return $this->extractDataSet(array('lang'));
}
function dom()
{
return $this->extractDataSet(array('hasDOM'));
}
function browsers()
{
return $this->extractDataSet(array('isOpera','isChrome','isIE','isNS','isSafari','isMZ'));
}
function useragents()
{
return array(
'WIN: Mozilla Firefox ' => array(
'useragent' => 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.1) Gecko/20060111 Firefox/1.5.0.1',
'version' => '1.8', //Version
'isWin' => true, //isWindows
'isLinux' => false,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => false, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isSafari' => false, //isSafari
'isMZ' => true, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
'LINUX: Bon Echo ' => array(
'useragent' => 'Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.1) Gecko/20070222 BonEcho/2.0.0.1',
'version' => '1.8', //Version
'isWin' => false, //isWindows
'isLinux' => true,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => false, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isSafari' => false, //isSafari
'isMZ' => true, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
'Chrome Mac' => array(
'useragent' => 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.461.0 Safari/534.3',
'version' => '6', //Version
'isWin' => false, //isWindows
'isLinux' => false,
'isMac' => true, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => true, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isSafari' => false, //isSafari
'isMZ' => false, //isMZ
'lang' => 'en-US', //lang
'hasDOM' => false, //hasDOM
'canPNGALPHA' => false, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
'IE 11' => array(
'useragent' => 'Mozilla/5.0 (Windows NT 6.3; Trident/7.0; .NET4.0E; .NET4.0C; rv:11.0) like Gecko',
'version' => '11.0', //Version
'isWin' => true, //isWindows
'isLinux' => false,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => false, //isOpera
'isChrome' => false, //isChrome
'isIE' => true, //isIE
'isNS' => false, //isNS
'isSafari' => false, //isSafari
'isMZ' => false, //isMZ
'lang' => '', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => false, //canIMGDATA
),
'Opera 15' => array(
'useragent' => 'Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/28.0.1500.29 Safari/537.36 OPR/15.0.1147.24',
'version' => '15.0', //Version
'isWin' => true, //isWindows
'isLinux' => false,
'isMac' => false, //isMac
'isUnix' => false, //isUnix
'isOpera' => true, //isOpera
'isChrome' => false, //isChrome
'isIE' => false, //isIE
'isNS' => false, //isNS
'isSafari' => false, //isSafari
'isMZ' => false, //isMZ
'lang' => '', //lang
'hasDOM' => true, //hasDOM
'canPNGALPHA' => true, //canPNGALPHA
'canIMGDATA' => true, //canIMGDATA
),
);
}
function os()
{
return $this->extractDataSet(array('isWin','isLinux','isUnix','isMac'));
}
/**
* @param string $useragent
* @return rcube_browser
*/
private function getBrowser($useragent)
{
/** @var $object rcube_browser */
$_SERVER['HTTP_USER_AGENT'] = $useragent;
$object = new rcube_browser();
return $object;
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_cache class
*
* @package Tests
*/
class Framework_Cache extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_cache('db', 1);
$this->assertInstanceOf('rcube_cache', $object, "Class constructor");
}
}

@ -0,0 +1,180 @@
<?php
/**
* Test class to test rcube_charset class
*
* @package Tests
*/
class Framework_Charset extends PHPUnit_Framework_TestCase
{
/**
* Data for test_clean()
*/
function data_clean()
{
return array(
array('', ''),
array("\xC1", ''),
);
}
/**
* @dataProvider data_clean
*/
function test_clean($input, $output)
{
$this->assertEquals($output, rcube_charset::clean($input));
}
/**
* Data for test_parse_charset()
*/
function data_parse_charset()
{
return array(
array('UTF8', 'UTF-8'),
array('WIN1250', 'WINDOWS-1250'),
);
}
/**
* @dataProvider data_parse_charset
*/
function test_parse_charset($input, $output)
{
$this->assertEquals($output, rcube_charset::parse_charset($input));
}
/**
* Data for test_convert()
*/
function data_convert()
{
return array(
array('ö', 'ö', 'UTF-8', 'UTF-8'),
array('ö', '', 'UTF-8', 'US-ASCII'),
array('aż', 'a', 'UTF-8', 'US-ASCII'),
array('&BCAEMARBBEEESwQ7BDoEOA-', 'РаÑ<C2B0>Ñ<EFBFBD>Ñлки', 'UTF7-IMAP', 'UTF-8'),
array('РаÑ<C2B0>Ñ<EFBFBD>Ñлки', '&BCAEMARBBEEESwQ7BDoEOA-', 'UTF-8', 'UTF7-IMAP'),
);
}
/**
* @dataProvider data_convert
*/
function test_convert($input, $output, $from, $to)
{
$this->assertEquals($output, rcube_charset::convert($input, $from, $to));
}
/**
* Data for test_utf7_to_utf8()
*/
function data_utf7_to_utf8()
{
return array(
array('+BCAEMARBBEEESwQ7BDoEOA-', 'РаÑ<C2B0>Ñ<EFBFBD>Ñлки'),
);
}
/**
* @dataProvider data_utf7_to_utf8
*/
function test_utf7_to_utf8($input, $output)
{
$this->assertEquals($output, rcube_charset::utf7_to_utf8($input));
}
/**
* Data for test_utf7imap_to_utf8()
*/
function data_utf7imap_to_utf8()
{
return array(
array('&BCAEMARBBEEESwQ7BDoEOA-', 'РаÑ<C2B0>Ñ<EFBFBD>Ñлки'),
);
}
/**
* @dataProvider data_utf7imap_to_utf8
*/
function test_utf7imap_to_utf8($input, $output)
{
$this->assertEquals($output, rcube_charset::utf7imap_to_utf8($input));
}
/**
* Data for test_utf8_to_utf7imap()
*/
function data_utf8_to_utf7imap()
{
return array(
array('РаÑ<C2B0>Ñ<EFBFBD>Ñлки', '&BCAEMARBBEEESwQ7BDoEOA-'),
);
}
/**
* @dataProvider data_utf8_to_utf7imap
*/
function test_utf8_to_utf7imap($input, $output)
{
$this->assertEquals($output, rcube_charset::utf8_to_utf7imap($input));
}
/**
* Data for test_utf16_to_utf8()
*/
function data_utf16_to_utf8()
{
return array(
array(base64_decode('BCAEMARBBEEESwQ7BDoEOA=='), 'РаÑ<C2B0>Ñ<EFBFBD>Ñлки'),
);
}
/**
* @dataProvider data_utf16_to_utf8
*/
function test_utf16_to_utf8($input, $output)
{
$this->assertEquals($output, rcube_charset::utf16_to_utf8($input));
}
/**
* Data for test_detect()
*/
function data_detect()
{
return array(
array('', '', 'UTF-8'),
array('a', 'UTF-8', 'UTF-8'),
);
}
/**
* @dataProvider data_detect
*/
function test_detect($input, $fallback, $output)
{
$this->assertEquals($output, rcube_charset::detect($input, $fallback));
}
/**
* Data for test_detect()
*/
function data_detect_with_lang()
{
return array(
array('Åã¥Ü¦WºÙ,¥D­n', 'zh_TW', 'BIG-5'),
);
}
/**
* @dataProvider data_detect_with_lang
*/
function test_detect_with_lang($input, $lang, $output)
{
$this->assertEquals($output, rcube_charset::detect($input, $output, $lang));
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_content_filter class
*
* @package Tests
*/
class Framework_ContentFilter extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_content_filter();
$this->assertInstanceOf('rcube_content_filter', $object, "Class constructor");
}
}

@ -0,0 +1,58 @@
<?php
/**
* Test class to test rcube_csv2vcard class
*
* @package Tests
*/
class Framework_Csv2vcard extends PHPUnit_Framework_TestCase
{
function test_import_generic()
{
$csv = new rcube_csv2vcard;
// empty input
$csv->import('');
$this->assertSame(array(), $csv->export());
}
function test_import_tb_plain()
{
$csv_text = file_get_contents(TESTS_DIR . '/src/Csv2vcard/tb_plain.csv');
$vcf_text = file_get_contents(TESTS_DIR . '/src/Csv2vcard/tb_plain.vcf');
$csv = new rcube_csv2vcard;
$csv->import($csv_text);
$result = $csv->export();
$vcard = $result[0]->export(false);
$this->assertCount(1, $result);
$vcf_text = trim(str_replace("\r\n", "\n", $vcf_text));
$vcard = trim(str_replace("\r\n", "\n", $vcard));
$this->assertEquals($vcf_text, $vcard);
}
function test_import_email()
{
$csv_text = file_get_contents(TESTS_DIR . '/src/Csv2vcard/email.csv');
$vcf_text = file_get_contents(TESTS_DIR . '/src/Csv2vcard/email.vcf');
$csv = new rcube_csv2vcard;
$csv->import($csv_text);
$result = $csv->export();
$this->assertCount(4, $result);
$vcard = '';
foreach ($result as $vcf) {
$vcard .= $vcf->export(false) . "\n";
}
$vcf_text = trim(str_replace("\r\n", "\n", $vcf_text));
$vcard = trim(str_replace("\r\n", "\n", $vcard));
$this->assertEquals($vcf_text, $vcard);
}
}

@ -0,0 +1,74 @@
<?php
/**
* Test class to test rcube_enriched class
*
* @package Tests
*/
class Framework_Enriched extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_enriched();
$this->assertInstanceOf('rcube_enriched', $object, "Class constructor");
}
/**
* Test to_html()
*/
function test_to_html()
{
$enriched = '<bold><italic>the-text</italic></bold>';
$expected = '<b><i>the-text</i></b>';
$result = rcube_enriched::to_html($enriched);
$this->assertSame($expected, $result);
}
/**
* Data for test_formatting()
*/
function data_formatting()
{
return array(
array('<bold>', '<b>'),
array('</bold>', '</b>'),
array('<italic>', '<i>'),
array('</italic>', '</i>'),
array('<fixed>', '<tt>'),
array('</fixed>', '</tt>'),
array('<smaller>', '<font size=-1>'),
array('</smaller>', '</font>'),
array('<bigger>', '<font size=+1>'),
array('</bigger>', '</font>'),
array('<underline>', '<span style="text-decoration: underline">'),
array('</underline>', '</span>'),
array('<flushleft>', '<span style="text-align: left">'),
array('</flushleft>', '</span>'),
array('<flushright>', '<span style="text-align: right">'),
array('</flushright>', '</span>'),
array('<flushboth>', '<span style="text-align: justified">'),
array('</flushboth>', '</span>'),
array('<indent>', '<span style="padding-left: 20px">'),
array('</indent>', '</span>'),
array('<indentright>', '<span style="padding-right: 20px">'),
array('</indentright>', '</span>'),
);
}
/**
* Test formatting conversion
* @dataProvider data_formatting
*/
function test_formatting($enriched, $expected)
{
$result = rcube_enriched::to_html($enriched);
$this->assertSame($expected, $result);
}
}

@ -0,0 +1,45 @@
<?php
/**
* Test class to test rcube_html class
*
* @package Tests
*/
class Framework_Html extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new html;
$this->assertInstanceOf('html', $object, "Class constructor");
}
/**
* Data for test_quote()
*/
function data_quote()
{
return array(
array('abc', 'abc'),
array('?', '?'),
array('"', '&quot;'),
array('<', '&lt;'),
array('>', '&gt;'),
array('&', '&amp;'),
array('&amp;', '&amp;amp;'),
);
}
/**
* Test for quote()
* @dataProvider data_quote
*/
function test_quote($str, $result)
{
$this->assertEquals(html::quote($str), $result);
}
}

@ -0,0 +1,106 @@
<?php
/**
* Test class to test rcube_html2text class
*
* @package Tests
*/
class rc_html2text extends PHPUnit_Framework_TestCase
{
function data_html2text()
{
return array(
0 => array(
'title' => 'Test entry',
'in' => '',
'out' => '',
),
1 => array(
'title' => 'Basic HTML entities',
'in' => '&quot;&amp;',
'out' => '"&',
),
2 => array(
'title' => 'HTML entity string',
'in' => '&amp;quot;',
'out' => '&quot;',
),
3 => array(
'title' => 'HTML entity in STRONG tag',
'in' => '<strong>&#347;</strong>', // ś
'out' => 'Ś', // upper ś
),
4 => array(
'title' => 'STRONG tag to upper-case conversion',
'in' => '<strong>ś</strong>',
'out' => 'Ś',
),
5 => array(
'title' => 'STRONG inside B tag',
'in' => '<b><strong>&#347;</strong></b>',
'out' => 'Ś',
),
);
}
/**
* @dataProvider data_html2text
*/
function test_html2text($title, $in, $out)
{
$ht = new rcube_html2text(null, false, false);
$ht->set_html($in);
$res = $ht->get_text();
$this->assertEquals($out, $res, $title);
}
/**
*
*/
function test_multiple_blockquotes()
{
$html = <<<EOF
<br>Begin<br><blockquote>OUTER BEGIN<blockquote>INNER 1<br></blockquote><div><br></div><div>Par 1</div>
<blockquote>INNER 2</blockquote><div><br></div><div>Par 2</div>
<div><br></div><div>Par 3</div><div><br></div>
<blockquote>INNER 3</blockquote>OUTER END</blockquote>
EOF;
$ht = new rcube_html2text($html, false, false);
$res = $ht->get_text();
$this->assertContains('>> INNER 1', $res, 'Quote inner');
$this->assertContains('>> INNER 3', $res, 'Quote inner');
$this->assertContains('> OUTER END', $res, 'Quote outer');
}
function test_broken_blockquotes()
{
// no end tag
$html = <<<EOF
Begin<br>
<blockquote>QUOTED TEXT
<blockquote>
NO END TAG FOUND
EOF;
$ht = new rcube_html2text($html, false, false);
$res = $ht->get_text();
$this->assertContains('QUOTED TEXT NO END TAG FOUND', $res, 'No quoating on invalid html');
// with some (nested) end tags
$html = <<<EOF
Begin<br>
<blockquote>QUOTED TEXT
<blockquote>INNER 1</blockquote>
<blockquote>INNER 2</blockquote>
NO END TAG FOUND
EOF;
$ht = new rcube_html2text($html, false, false);
$res = $ht->get_text();
$this->assertContains('QUOTED TEXT INNER 1 INNER 2 NO END', $res, 'No quoating on invalid html');
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_image class
*
* @package Tests
*/
class Framework_Image extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_image('test');
$this->assertInstanceOf('rcube_image', $object, "Class constructor");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_imap class
*
* @package Tests
*/
class Framework_Imap extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_imap;
$this->assertInstanceOf('rcube_imap', $object, "Class constructor");
}
}

@ -0,0 +1,61 @@
<?php
/**
* Test class to test rcube_imap_generic class
*
* @package Tests
*/
class Framework_ImapGeneric extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_imap_generic;
$this->assertInstanceOf('rcube_imap_generic', $object, "Class constructor");
}
/**
* Test for uncompressMessageSet
*/
function test_uncompressMessageSet()
{
$result = rcube_imap_generic::uncompressMessageSet(null);
$this->assertSame(array(), $result);
$this->assertCount(0, $result);
$result = rcube_imap_generic::uncompressMessageSet('1');
$this->assertSame(array(1), $result);
$this->assertCount(1, $result);
$result = rcube_imap_generic::uncompressMessageSet('1:3');
$this->assertSame(array(1, 2, 3), $result);
$this->assertCount(3, $result);
}
/**
* Test for tokenizeResponse
*/
function test_tokenizeResponse()
{
$response = "test brack[et] {1}\r\na {0}\r\n (item1 item2)";
$result = rcube_imap_generic::tokenizeResponse($response, 1);
$this->assertSame("test", $result);
$result = rcube_imap_generic::tokenizeResponse($response, 1);
$this->assertSame("brack[et]", $result);
$result = rcube_imap_generic::tokenizeResponse($response, 1);
$this->assertSame("a", $result);
$result = rcube_imap_generic::tokenizeResponse($response, 1);
$this->assertSame("", $result);
$result = rcube_imap_generic::tokenizeResponse($response, 1);
$this->assertSame(array('item1', 'item2'), $result);
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_message_header class
*
* @package Tests
*/
class Framework_MessageHeader extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_message_header;
$this->assertInstanceOf('rcube_message_header', $object, "Class constructor");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_message_part class
*
* @package Tests
*/
class Framework_MessagePart extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_message_part;
$this->assertInstanceOf('rcube_message_part', $object, "Class constructor");
}
}

@ -0,0 +1,213 @@
<?php
/**
* Test class to test rcube_mime class
*
* @package Tests
*/
class Framework_Mime extends PHPUnit_Framework_TestCase
{
/**
* Test decoding of single e-mail address strings
* Uses rcube_mime::decode_address_list()
*/
function test_decode_single_address()
{
$headers = array(
0 => 'test@domain.tld',
1 => '<test@domain.tld>',
2 => 'Test <test@domain.tld>',
3 => 'Test Test <test@domain.tld>',
4 => 'Test Test<test@domain.tld>',
5 => '"Test Test" <test@domain.tld>',
6 => '"Test Test"<test@domain.tld>',
7 => '"Test \\" Test" <test@domain.tld>',
8 => '"Test<Test" <test@domain.tld>',
9 => '=?ISO-8859-1?B?VGVzdAo=?= <test@domain.tld>',
10 => '=?ISO-8859-1?B?VGVzdAo=?=<test@domain.tld>', // #1487068
// comments in address (#1487673)
11 => 'Test (comment) <test@domain.tld>',
12 => '"Test" (comment) <test@domain.tld>',
13 => '"Test (comment)" (comment) <test@domain.tld>',
14 => '(comment) <test@domain.tld>',
15 => 'Test <test@(comment)domain.tld>',
16 => 'Test Test ((comment)) <test@domain.tld>',
17 => 'test@domain.tld (comment)',
18 => '"Test,Test" <test@domain.tld>',
// 1487939
19 => 'Test <"test test"@domain.tld>',
20 => '<"test test"@domain.tld>',
21 => '"test test"@domain.tld',
// invalid (#1489092)
22 => '"John Doe @ SomeBusinessName" <MAILER-DAEMON>',
23 => '=?UTF-8?B?IlRlc3QsVGVzdCI=?= <test@domain.tld>',
);
$results = array(
0 => array(1, '', 'test@domain.tld'),
1 => array(1, '', 'test@domain.tld'),
2 => array(1, 'Test', 'test@domain.tld'),
3 => array(1, 'Test Test', 'test@domain.tld'),
4 => array(1, 'Test Test', 'test@domain.tld'),
5 => array(1, 'Test Test', 'test@domain.tld'),
6 => array(1, 'Test Test', 'test@domain.tld'),
7 => array(1, 'Test " Test', 'test@domain.tld'),
8 => array(1, 'Test<Test', 'test@domain.tld'),
9 => array(1, 'Test', 'test@domain.tld'),
10 => array(1, 'Test', 'test@domain.tld'),
11 => array(1, 'Test', 'test@domain.tld'),
12 => array(1, 'Test', 'test@domain.tld'),
13 => array(1, 'Test (comment)', 'test@domain.tld'),
14 => array(1, '', 'test@domain.tld'),
15 => array(1, 'Test', 'test@domain.tld'),
16 => array(1, 'Test Test', 'test@domain.tld'),
17 => array(1, '', 'test@domain.tld'),
18 => array(1, 'Test,Test', 'test@domain.tld'),
19 => array(1, 'Test', '"test test"@domain.tld'),
20 => array(1, '', '"test test"@domain.tld'),
21 => array(1, '', '"test test"@domain.tld'),
// invalid (#1489092)
22 => array(1, 'John Doe @ SomeBusinessName', 'MAILER-DAEMON'),
23 => array(1, 'Test,Test', 'test@domain.tld'),
);
foreach ($headers as $idx => $header) {
$res = rcube_mime::decode_address_list($header);
$this->assertEquals($results[$idx][0], count($res), "Rows number in result for header: " . $header);
$this->assertEquals($results[$idx][1], $res[1]['name'], "Name part decoding for header: " . $header);
$this->assertEquals($results[$idx][2], $res[1]['mailto'], "Email part decoding for header: " . $header);
}
}
/**
* Test decoding of header values
* Uses rcube_mime::decode_mime_string()
*/
function test_header_decode_qp()
{
$test = array(
// #1488232: invalid character "?"
'quoted-printable (1)' => array(
'in' => '=?utf-8?Q?Certifica=C3=A7=C3=A3??=',
'out' => 'Certifica=C3=A7=C3=A3?',
),
'quoted-printable (2)' => array(
'in' => '=?utf-8?Q?Certifica=?= =?utf-8?Q?C3=A7=C3=A3?=',
'out' => 'Certifica=C3=A7=C3=A3',
),
'quoted-printable (3)' => array(
'in' => '=?utf-8?Q??= =?utf-8?Q??=',
'out' => '',
),
'quoted-printable (4)' => array(
'in' => '=?utf-8?Q??= a =?utf-8?Q??=',
'out' => ' a ',
),
'quoted-printable (5)' => array(
'in' => '=?utf-8?Q?a?= =?utf-8?Q?b?=',
'out' => 'ab',
),
'quoted-printable (6)' => array(
'in' => '=?utf-8?Q? ?= =?utf-8?Q?a?=',
'out' => ' a',
),
'quoted-printable (7)' => array(
'in' => '=?utf-8?Q?___?= =?utf-8?Q?a?=',
'out' => ' a',
),
);
foreach ($test as $idx => $item) {
$res = rcube_mime::decode_mime_string($item['in'], 'UTF-8');
$res = quoted_printable_encode($res);
$this->assertEquals($item['out'], $res, "Header decoding for: " . $idx);
}
}
/**
* Test format=flowed unfolding
*/
function test_format_flowed()
{
$raw = file_get_contents(TESTS_DIR . 'src/format-flowed-unfolded.txt');
$flowed = file_get_contents(TESTS_DIR . 'src/format-flowed.txt');
$this->assertEquals($flowed, rcube_mime::format_flowed($raw, 80), "Test correct folding and space-stuffing");
}
/**
* Test format=flowed unfolding
*/
function test_unfold_flowed()
{
$flowed = file_get_contents(TESTS_DIR . 'src/format-flowed.txt');
$unfolded = file_get_contents(TESTS_DIR . 'src/format-flowed-unfolded.txt');
$this->assertEquals($unfolded, rcube_mime::unfold_flowed($flowed), "Test correct unfolding of quoted lines");
}
/**
* Test wordwrap()
*/
function test_wordwrap()
{
$samples = array(
array(
array("aaaa aaaa\n aaaa"),
"aaaa aaaa\n aaaa",
),
array(
array("123456789 123456789 123456789 123", 29),
"123456789 123456789 123456789\n123",
),
array(
array("123456789 3456789 123456789", 29),
"123456789 3456789 123456789",
),
array(
array("123456789 123456789 123456789 123", 29),
"123456789 123456789 123456789\n 123",
),
array(
array("abc", 1, "\n", true),
"a\nb\nc",
),
array(
array("ąść", 1, "\n", true, 'UTF-8'),
"ą\nś\nć",
),
array(
array(">abc\n>def", 2, "\n", true),
">abc\n>def",
),
array(
array("abc def", 3, "-"),
"abc-def",
),
array(
array("----------------------------------------------------------------------------------------\nabc def123456789012345", 76),
"----------------------------------------------------------------------------------------\nabc def123456789012345",
),
array(
array("-------\nabc def", 5),
"-------\nabc\ndef",
),
array(
array("http://xx.xxx.xx.xxx:8080/addressbooks/roundcubexxxxx%40xxxxxxxxxxxxxxxxxxxxxxx.xx.xx/testing/", 70),
"http://xx.xxx.xx.xxx:8080/addressbooks/roundcubexxxxx%40xxxxxxxxxxxxxxxxxxxxxxx.xx.xx/testing/",
),
array(
array("this-is-just-some-blabla-to-make-this-more-than-seventy-five-characters-in-a-row -- this line should be wrapped", 20, "\n"),
"this-is-just-some-blabla-to-make-this-more-than-seventy-five-characters-in-a-row\n-- this line should\nbe wrapped",
),
);
foreach ($samples as $sample) {
$this->assertEquals($sample[1], call_user_func_array(array('rcube_mime', 'wordwrap'), $sample[0]), "Test text wrapping");
}
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube class
*
* @package Tests
*/
class Framework_Rcube extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = rcube::get_instance();
$this->assertInstanceOf('rcube', $object, "Class singleton");
}
}

@ -0,0 +1,67 @@
<?php
/**
* Test class to test rcube_result_index class
*
* @package Tests
*/
class Framework_ResultIndex extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_result_index;
$this->assertInstanceOf('rcube_result_index', $object, "Class constructor");
}
/**
* thread parser test
*/
function test_parse()
{
$text = "* SORT 2001 2002 2035 2036 2037 2038 2044 2046 2043 2045 2226 2225 2224 2223";
$object = new rcube_result_index('INBOX', $text);
$this->assertSame(false, $object->is_empty(), "Object is empty");
$this->assertSame(false, $object->is_error(), "Object is error");
$this->assertSame(2226, $object->max(), "Max message UID");
$this->assertSame(2001, $object->min(), "Min message UID");
$this->assertSame(14, $object->count_messages(), "Messages count");
$this->assertSame(14, $object->count(), "Messages count");
$this->assertSame(1, $object->exists(2002, true), "Message exists");
$this->assertSame(true, $object->exists(2002), "Message exists (bool)");
$this->assertSame(2001, $object->get_element('FIRST'), "Get first element");
$this->assertSame(2223, $object->get_element('LAST'), "Get last element");
$this->assertSame(2035, (int) $object->get_element(2), "Get specified element");
$this->assertSame("2001:2002,2035:2038,2043:2046,2223:2226", $object->get_compressed(), "Get compressed index");
$this->assertSame('INBOX', $object->get_parameters('MAILBOX'), "Get parameter");
$clone = clone $object;
$clone->filter(array(2035, 2002));
$this->assertSame(2, $clone->count(), "Messages count (filtered)");
$this->assertSame(2002, $clone->get_element('FIRST'), "Get first element (filtered)");
$clone = clone $object;
$clone->revert();
$this->assertSame(14, $clone->count(), "Messages count (reverted)");
$this->assertSame(12, $clone->exists(2002, true), "Message exists (reverted)");
$this->assertSame(true, $clone->exists(2002), "Message exists (bool) (reverted)");
$this->assertSame(2223, $clone->get_element('FIRST'), "Get first element (reverted)");
$this->assertSame(2001, $clone->get_element('LAST'), "Get last element (reverted)");
$this->assertSame(2225, (int) $clone->get_element(2), "Get specified element (reverted)");
$clone = clone $object;
$clone->slice(2, 3);
$this->assertSame(3, $clone->count(), "Messages count (sliced)");
$this->assertSame(2035, $clone->get_element('FIRST'), "Get first element (sliced)");
$this->assertSame(2037, $clone->get_element('LAST'), "Get last element (sliced)");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_result_set class
*
* @package Tests
*/
class Framework_ResultSet extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_result_set;
$this->assertInstanceOf('rcube_result_set', $object, "Class constructor");
}
}

@ -0,0 +1,59 @@
<?php
/**
* Test class to test rcube_result_thread class
*
* @package Tests
*/
class Framework_ResultThread extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_result_thread;
$this->assertInstanceOf('rcube_result_thread', $object, "Class constructor");
}
/**
* thread parser test
*/
function test_parse_thread()
{
$text = file_get_contents(__DIR__ . '/../src/imap_thread.txt');
$object = new rcube_result_thread('INBOX', $text);
$this->assertSame(false, $object->is_empty(), "Object is empty");
$this->assertSame(false, $object->is_error(), "Object is error");
$this->assertSame(1721, $object->max(), "Max message UID");
$this->assertSame(1, $object->min(), "Min message UID");
$this->assertSame(1721, $object->count_messages(), "Messages count");
$this->assertSame(1691, $object->exists(1720, true), "Message exists");
$this->assertSame(true, $object->exists(1720), "Message exists (bool)");
$this->assertSame(1, $object->get_element('FIRST'), "Get first element");
$this->assertSame(1719, $object->get_element('LAST'), "Get last element");
$this->assertSame(14, (int) $object->get_element(2), "Get specified element");
$clone = clone $object;
$clone->filter(array(7));
$clone = $clone->get_tree();
$this->assertSame(1, count($clone), "Structure check");
$this->assertSame(3, count($clone[7]), "Structure check");
$this->assertSame(0, count($clone[7][12]), "Structure check");
$this->assertSame(1, count($clone[7][167]), "Structure check");
$this->assertSame(0, count($clone[7][167][197]), "Structure check");
$this->assertSame(2, count($clone[7][458]), "Structure check");
$this->assertSame(1, count($clone[7][458][460]), "Structure check");
$this->assertSame(0, count($clone[7][458][460][463]), "Structure check");
$this->assertSame(1, count($clone[7][458][464]), "Structure check");
$this->assertSame(0, count($clone[7][458][464][471]), "Structure check");
$object->filter(array(784));
$this->assertSame(118, $object->count_messages(), "Messages filter");
$this->assertSame(1, $object->count(), "Messages filter (count)");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_smtp class
*
* @package Tests
*/
class Framework_Smtp extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_smtp;
$this->assertInstanceOf('rcube_smtp', $object, "Class constructor");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_spellchecker class
*
* @package Tests
*/
class Framework_Spellchecker extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$object = new rcube_spellchecker;
$this->assertInstanceOf('rcube_spellchecker', $object, "Class constructor");
}
}

@ -0,0 +1,75 @@
<?php
/**
* Test class to test rcube_string_replacer class
*
* @package Tests
*/
class Framework_StringReplacer extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$sr = new rcube_string_replacer;
$this->assertInstanceOf('rcube_string_replacer', $sr, "Class constructor");
}
/**
* Data for test_replace()
*/
function data_replace()
{
return array(
array('http://domain.tld/path*path2', '<a href="http://domain.tld/path*path2">http://domain.tld/path*path2</a>'),
array("Click this link:\nhttps://mail.xn--brderli-o2a.ch/rc/ EOF", "Click this link:\n<a href=\"https://mail.xn--brderli-o2a.ch/rc/\">https://mail.xn--brderli-o2a.ch/rc/</a> EOF"),
array('Start http://localhost/?foo End', 'Start <a href="http://localhost/?foo">http://localhost/?foo</a> End'),
array('http://localhost/?foo=bar. Period', '<a href="http://localhost/?foo=bar">http://localhost/?foo=bar</a>. Period'),
array('www.domain.tld', '<a href="http://www.domain.tld">www.domain.tld</a>'),
array('WWW.DOMAIN.TLD', '<a href="http://WWW.DOMAIN.TLD">WWW.DOMAIN.TLD</a>'),
array('[http://link.com]', '[<a href="http://link.com">http://link.com</a>]'),
array('http://link.com?a[]=1', '<a href="http://link.com?a[]=1">http://link.com?a[]=1</a>'),
array('http://link.com?a[]', '<a href="http://link.com?a[]">http://link.com?a[]</a>'),
array('(http://link.com)', '(<a href="http://link.com">http://link.com</a>)'),
array('http://link.com?a(b)c', '<a href="http://link.com?a(b)c">http://link.com?a(b)c</a>'),
array('http://link.com?(link)', '<a href="http://link.com?(link)">http://link.com?(link)</a>'),
array('https://github.com/a/b/compare/3a0f82...1f4b2a after', '<a href="https://github.com/a/b/compare/3a0f82...1f4b2a">https://github.com/a/b/compare/3a0f82...1f4b2a</a> after'),
array('http://<test>', 'http://<test>'),
array('http://', 'http://'),
array('1@1.com www.domain.tld', '<a href="mailto:1@1.com">1@1.com</a> <a href="http://www.domain.tld">www.domain.tld</a>'),
array(' www.domain.tld ', ' <a href="http://www.domain.tld">www.domain.tld</a> '),
array(' www.domain.tld/#!download|856p1|2 ', ' <a href="http://www.domain.tld/#!download|856p1|2">www.domain.tld/#!download|856p1|2</a> '),
);
}
/**
* @dataProvider data_replace
*/
function test_replace($input, $output)
{
$replacer = new rcube_string_replacer;
$result = $replacer->replace($input);
$result = $replacer->resolve($result);
$this->assertEquals($output, $result);
}
function test_linkrefs()
{
$input = "This is a sample message [1] to test the new linkref [ref0] replacement feature of [Roundcube].\n";
$input.= "\n";
$input.= "[1] http://en.wikipedia.org/wiki/Email\n";
$input.= "[ref0] www.link-ref.com\n";
$replacer = new rcube_string_replacer;
$result = $replacer->replace($input);
$result = $replacer->resolve($result);
$this->assertContains('[<a href="http://en.wikipedia.org/wiki/Email">1</a>] to', $result, "Numeric linkref replacements");
$this->assertContains('[<a href="http://www.link-ref.com">ref0</a>] repl', $result, "Alphanum linkref replacements");
$this->assertContains('of [Roundcube].', $result, "Don't touch strings wihtout an index entry");
}
}

@ -0,0 +1,20 @@
<?php
/**
* Test class to test rcube_user class
*
* @package Tests
*/
class Framework_User extends PHPUnit_Framework_TestCase
{
/**
* Class constructor
*/
function test_class()
{
$user = new rcube_user;
$this->assertInstanceOf('rcube_user', $user, "Class constructor");
}
}

@ -0,0 +1,337 @@
<?php
/**
* Test class to test rcube_utils class
*
* @package Tests
*/
class Framework_Utils extends PHPUnit_Framework_TestCase
{
/**
* Valid email addresses for test_valid_email()
*/
function data_valid_email()
{
return array(
array('email@domain.com', 'Valid email'),
array('firstname.lastname@domain.com', 'Email contains dot in the address field'),
array('email@subdomain.domain.com', 'Email contains dot with subdomain'),
array('firstname+lastname@domain.com', 'Plus sign is considered valid character'),
array('email@[123.123.123.123]', 'Square bracket around IP address'),
array('email@[IPv6:::1]', 'Square bracket around IPv6 address (1)'),
array('email@[IPv6:::1.2.3.4]', 'Square bracket around IPv6 address (2)'),
array('email@[IPv6:2001:2d12:c4fe:5afe::1]', 'Square bracket around IPv6 address (3)'),
array('"email"@domain.com', 'Quotes around email is considered valid'),
array('1234567890@domain.com', 'Digits in address are valid'),
array('email@domain-one.com', 'Dash in domain name is valid'),
array('_______@domain.com', 'Underscore in the address field is valid'),
array('email@domain.name', '.name is valid Top Level Domain name'),
array('email@domain.co.jp', 'Dot in Top Level Domain name also considered valid (use co.jp as example here)'),
array('firstname-lastname@domain.com', 'Dash in address field is valid'),
);
}
/**
* Invalid email addresses for test_invalid_email()
*/
function data_invalid_email()
{
return array(
array('plainaddress', 'Missing @ sign and domain'),
array('#@%^%#$@#$@#.com', 'Garbage'),
array('@domain.com', 'Missing username'),
array('Joe Smith <email@domain.com>', 'Encoded html within email is invalid'),
array('email.domain.com', 'Missing @'),
array('email@domain@domain.com', 'Two @ sign'),
array('.email@domain.com', 'Leading dot in address is not allowed'),
array('email.@domain.com', 'Trailing dot in address is not allowed'),
array('email..email@domain.com', 'Multiple dots'),
array('あいうえお@domain.com', 'Unicode char as address'),
array('email@domain.com (Joe Smith)', 'Text followed email is not allowed'),
array('email@domain', 'Missing top level domain (.com/.net/.org/etc)'),
array('email@-domain.com', 'Leading dash in front of domain is invalid'),
// array('email@domain.web', '.web is not a valid top level domain'),
array('email@123.123.123.123', 'IP address without brackets'),
array('email@2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets'),
array('email@IPv6:2001:2d12:c4fe:5afe::1', 'IPv6 address without brackets (2)'),
array('email@[111.222.333.44444]', 'Invalid IP format'),
array('email@[111.222.255.257]', 'Invalid IP format (2)'),
array('email@[.222.255.257]', 'Invalid IP format (3)'),
array('email@[::1]', 'Invalid IPv6 format (1)'),
array('email@[IPv6:2001:23x2:1]', 'Invalid IPv6 format (2)'),
array('email@[IPv6:1111:2222:33333::4444:5555]', 'Invalid IPv6 format (3)'),
array('email@[IPv6:1111::3333::4444:5555]', 'Invalid IPv6 format (4)'),
array('email@domain..com', 'Multiple dot in the domain portion is invalid'),
);
}
/**
* @dataProvider data_valid_email
*/
function test_valid_email($email, $title)
{
$this->assertTrue(rcube_utils::check_email($email, false), $title);
}
/**
* @dataProvider data_invalid_email
*/
function test_invalid_email($email, $title)
{
$this->assertFalse(rcube_utils::check_email($email, false), $title);
}
/**
* Valid IP addresses for test_valid_ip()
*/
function data_valid_ip()
{
return array(
array('0.0.0.0'),
array('123.123.123.123'),
array('::'),
array('::1'),
array('::1.2.3.4'),
array('2001:2d12:c4fe:5afe::1'),
);
}
/**
* Valid IP addresses for test_invalid_ip()
*/
function data_invalid_ip()
{
return array(
array(''),
array(0),
array('123.123.123.1234'),
array('1.1.1.1.1'),
array('::1.2.3.260'),
array('::1.0'),
array('2001::c4fe:5afe::1'),
);
}
/**
* @dataProvider data_valid_ip
*/
function test_valid_ip($ip)
{
$this->assertTrue(rcube_utils::check_ip($ip));
}
/**
* @dataProvider data_invalid_ip
*/
function test_invalid_ip($ip)
{
$this->assertFalse(rcube_utils::check_ip($ip));
}
/**
* Data for test_rep_specialchars_output()
*/
function data_rep_specialchars_output()
{
return array(
array('', '', 'abc', 'abc'),
array('', '', '?', '?'),
array('', '', '"', '&quot;'),
array('', '', '<', '&lt;'),
array('', '', '>', '&gt;'),
array('', '', '&', '&amp;'),
array('', '', '&amp;', '&amp;amp;'),
array('', '', '<a>', '&lt;a&gt;'),
array('', 'remove', '<a>', ''),
);
}
/**
* Test for rep_specialchars_output
* @dataProvider data_rep_specialchars_output
*/
function test_rep_specialchars_output($type, $mode, $str, $res)
{
$result = rcube_utils::rep_specialchars_output(
$str, $type ? $type : 'html', $mode ? $mode : 'strict');
$this->assertEquals($result, $res);
}
/**
* rcube_utils::mod_css_styles()
*/
function test_mod_css_styles()
{
$css = file_get_contents(TESTS_DIR . 'src/valid.css');
$mod = rcube_utils::mod_css_styles($css, 'rcmbody');
$this->assertRegExp('/#rcmbody\s+\{/', $mod, "Replace body style definition");
$this->assertRegExp('/#rcmbody h1\s\{/', $mod, "Prefix tag styles (single)");
$this->assertRegExp('/#rcmbody h1, #rcmbody h2, #rcmbody h3, #rcmbody textarea\s+\{/', $mod, "Prefix tag styles (multiple)");
$this->assertRegExp('/#rcmbody \.noscript\s+\{/', $mod, "Prefix class styles");
$css = file_get_contents(TESTS_DIR . 'src/media.css');
$mod = rcube_utils::mod_css_styles($css, 'rcmbody');
$this->assertContains('#rcmbody table[class=w600]', $mod, 'Replace styles nested in @media block');
$this->assertContains('#rcmbody {width:600px', $mod, 'Replace body selector nested in @media block');
}
/**
* rcube_utils::mod_css_styles()
*/
function test_mod_css_styles_xss()
{
$mod = rcube_utils::mod_css_styles("body.main2cols { background-image: url('../images/leftcol.png'); }", 'rcmbody');
$this->assertEquals("/* evil! */", $mod, "No url() values allowed");
$mod = rcube_utils::mod_css_styles("@import url('http://localhost/somestuff/css/master.css');", 'rcmbody');
$this->assertEquals("/* evil! */", $mod, "No import statements");
$mod = rcube_utils::mod_css_styles("left:expression(document.body.offsetWidth-20)", 'rcmbody');
$this->assertEquals("/* evil! */", $mod, "No expression properties");
$mod = rcube_utils::mod_css_styles("left:exp/* */ression( alert(&#039;xss3&#039;) )", 'rcmbody');
$this->assertEquals("/* evil! */", $mod, "Don't allow encoding quirks");
$mod = rcube_utils::mod_css_styles("background:\\0075\\0072\\006c( javascript:alert(&#039;xss&#039;) )", 'rcmbody');
$this->assertEquals("/* evil! */", $mod, "Don't allow encoding quirks (2)");
}
/**
* Check rcube_utils::explode_quoted_string()
*/
function test_explode_quoted_string()
{
$data = array(
'"a,b"' => array('"a,b"'),
'"a,b","c,d"' => array('"a,b"','"c,d"'),
'"a,\\"b",d' => array('"a,\\"b"', 'd'),
);
foreach ($data as $text => $res) {
$result = rcube_utils::explode_quoted_string(',', $text);
$this->assertSame($res, $result);
}
}
/**
* Check rcube_utils::explode_quoted_string() compat. with explode()
*/
function test_explode_quoted_string_compat()
{
$data = array('', 'a,b,c', 'a', ',', ',a');
foreach ($data as $text) {
$result = rcube_utils::explode_quoted_string(',', $text);
$this->assertSame(explode(',', $text), $result);
}
}
/**
* rcube_utils::get_boolean()
*/
function test_get_boolean()
{
$input = array(
false, 'false', '0', 'no', 'off', 'nein', 'FALSE', '', null,
);
foreach ($input as $idx => $value) {
$this->assertFalse(get_boolean($value), "Invalid result for $idx test item");
}
$input = array(
true, 'true', '1', 1, 'yes', 'anything', 1000,
);
foreach ($input as $idx => $value) {
$this->assertTrue(get_boolean($value), "Invalid result for $idx test item");
}
}
/**
* rcube:utils::file2class()
*/
function test_file2class()
{
$test = array(
array('', '', 'unknown'),
array('text', 'text', 'text'),
array('image/png', 'image.png', 'image png'),
);
foreach ($test as $v) {
$result = rcube_utils::file2class($v[0], $v[1]);
$this->assertSame($v[2], $result);
}
}
/**
* rcube:utils::strtotime()
*/
function test_strtotime()
{
$test = array(
'1' => 1,
'' => 0,
'2013-04-22' => 1366581600,
'2013/04/22' => 1366581600,
'2013.04.22' => 1366581600,
'22-04-2013' => 1366581600,
'22/04/2013' => 1366581600,
'22.04.2013' => 1366581600,
'22.4.2013' => 1366581600,
'20130422' => 1366581600,
);
foreach ($test as $datetime => $ts) {
$result = rcube_utils::strtotime($datetime);
$this->assertSame($ts, $result, "Error parsing date: $datetime");
}
}
/**
* rcube:utils::anytodatetime()
*/
function test_anytodatetime()
{
$test = array(
'2013-04-22' => '2013-04-22',
'2013/04/22' => '2013-04-22',
'2013.04.22' => '2013-04-22',
'22-04-2013' => '2013-04-22',
'22/04/2013' => '2013-04-22',
'22.04.2013' => '2013-04-22',
'04/22/2013' => '2013-04-22',
'22.4.2013' => '2013-04-22',
'20130422' => '2013-04-22',
'1900-10-10' => '1900-10-10',
'01-01-1900' => '1900-01-01',
'01/30/1960' => '1960-01-30'
);
foreach ($test as $datetime => $ts) {
$result = rcube_utils::anytodatetime($datetime);
$this->assertSame($ts, $result ? $result->format('Y-m-d') : '', "Error parsing date: $datetime");
}
}
/**
* rcube:utils::normalize _string()
*/
function test_normalize_string()
{
$test = array(
'' => '',
'abc def' => 'abc def',
);
foreach ($test as $input => $output) {
$result = rcube_utils::normalize_string($input);
$this->assertSame($output, $result);
}
}
}

@ -0,0 +1,119 @@
<?php
/**
* Unit tests for class rcube_vcard
*
* @package Tests
*/
class Framework_VCard extends PHPUnit_Framework_TestCase
{
function _srcpath($fn)
{
return realpath(dirname(__FILE__) . '/../src/' . $fn);
}
function test_parse_one()
{
$vcard = new rcube_vcard(file_get_contents($this->_srcpath('apple.vcf')));
$this->assertTrue($vcard->business, "Identify as business record");
$this->assertEquals("Apple Computer AG", $vcard->displayname, "FN => displayname");
$this->assertEquals("", $vcard->firstname, "No person name set");
}
function test_parse_two()
{
$vcard = new rcube_vcard(file_get_contents($this->_srcpath('johndoe.vcf')), null);
$this->assertFalse($vcard->business, "Identify as private record");
$this->assertEquals("John Doë", $vcard->displayname, "Decode according to charset attribute");
$this->assertEquals("roundcube.net", $vcard->organization, "Test organization field");
$this->assertCount(2, $vcard->email, "List two e-mail addresses");
$this->assertEquals("roundcube@gmail.com", $vcard->email[0], "Use PREF e-mail as primary");
}
/**
* Make sure MOBILE phone is returned as CELL (as specified in standard)
*/
function test_parse_three()
{
$vcard = new rcube_vcard(file_get_contents($this->_srcpath('johndoe.vcf')), null);
$vcf = $vcard->export();
$this->assertRegExp('/TEL;CELL:\+987654321/', $vcf, "Return CELL instead of MOBILE (import)");
$vcard = new rcube_vcard();
$vcard->set('phone', '+987654321', 'MOBILE');
$vcf = $vcard->export();
$this->assertRegExp('/TEL;TYPE=CELL:\+987654321/', $vcf, "Return CELL instead of MOBILE (set)");
}
/**
* Backslash escaping test (#1488896)
*/
function test_parse_four()
{
$vcard = "BEGIN:VCARD\nVERSION:3.0\nN:last\\;;first\\\\;middle\\\\\\;\\\\;prefix;\nFN:test\nEND:VCARD";
$vcard = new rcube_vcard($vcard, null);
$vcard = $vcard->get_assoc();
$this->assertEquals("last;", $vcard['surname'], "Decode backslash character");
$this->assertEquals("first\\", $vcard['firstname'], "Decode backslash character");
$this->assertEquals("middle\\;\\", $vcard['middlename'], "Decode backslash character");
$this->assertEquals("prefix", $vcard['prefix'], "Decode backslash character");
}
/**
* Backslash parsing test (#1489085)
*/
function test_parse_five()
{
$vcard = "BEGIN:VCARD\nVERSION:3.0\nN:last\\\\\\a;fir\\nst\nURL:http\\://domain.tld\nEND:VCARD";
$vcard = new rcube_vcard($vcard, null);
$vcard = $vcard->get_assoc();
$this->assertEquals("last\\a", $vcard['surname'], "Decode dummy backslash character");
$this->assertEquals("fir\nst", $vcard['firstname'], "Decode backslash character");
$this->assertEquals("http://domain.tld", $vcard['website:other'][0], "Decode dummy backslash character");
}
function test_import()
{
$input = file_get_contents($this->_srcpath('apple.vcf'));
$input .= file_get_contents($this->_srcpath('johndoe.vcf'));
$vcards = rcube_vcard::import($input);
$this->assertCount(2, $vcards, "Detected 2 vcards");
$this->assertEquals("Apple Computer AG", $vcards[0]->displayname, "FN => displayname");
$this->assertEquals("John Doë", $vcards[1]->displayname, "Displayname with correct charset");
// http://trac.roundcube.net/ticket/1485542
$vcards2 = rcube_vcard::import(file_get_contents($this->_srcpath('thebat.vcf')));
$this->assertEquals("Iksiñski", $vcards2[0]->surname, "Detect charset in encoded values");
}
function test_import_photo_encoding()
{
$input = file_get_contents($this->_srcpath('photo.vcf'));
$vcards = rcube_vcard::import($input);
$vcard = $vcards[0]->get_assoc();
$this->assertCount(1, $vcards, "Detected 1 vcard");
// ENCODING=b case (#1488683)
$this->assertEquals("/9j/4AAQSkZJRgABAQA", substr(base64_encode($vcard['photo']), 0, 19), "Photo decoding");
$this->assertEquals("Müller", $vcard['surname'], "Unicode characters");
}
function test_encodings()
{
$input = file_get_contents($this->_srcpath('utf-16_sample.vcf'));
$vcards = rcube_vcard::import($input);
$this->assertEquals("Ǽgean ĽdaMonté", $vcards[0]->displayname, "Decoded from UTF-16");
}
}

@ -0,0 +1,127 @@
<?php
/**
* Test class to test rcube_washtml class
*
* @package Tests
*/
class Framework_Washtml extends PHPUnit_Framework_TestCase
{
/**
* Test the elimination of some XSS vulnerabilities
*/
function test_html_xss3()
{
// #1488850
$html = '<p><a href="data:text/html,&lt;script&gt;alert(document.cookie)&lt;/script&gt;">Firefox</a>'
.'<a href="vbscript:alert(document.cookie)">Internet Explorer</a></p>';
$washer = new rcube_washtml;
$washed = $washer->wash($html);
$this->assertNotRegExp('/data:text/', $washed, "Remove data:text/html links");
$this->assertNotRegExp('/vbscript:/', $washed, "Remove vbscript: links");
}
/**
* Test fixing of invalid href (#1488940)
*/
function test_href()
{
$html = "<p><a href=\"\nhttp://test.com\n\">Firefox</a>";
$washer = new rcube_washtml;
$washed = $washer->wash($html);
$this->assertRegExp('|href="http://test.com">|', $washed, "Link href with newlines (#1488940)");
}
/**
* Test handling HTML comments
*/
function test_comments()
{
$washer = new rcube_washtml;
$html = "<!--[if gte mso 10]><p>p1</p><!--><p>p2</p>";
$washed = $washer->wash($html);
$this->assertEquals('<!-- node type 8 --><!-- html ignored --><!-- body ignored --><p>p2</p>', $washed, "HTML conditional comments (#1489004)");
$html = "<!--TestCommentInvalid><p>test</p>";
$washed = $washer->wash($html);
$this->assertEquals('<!-- html ignored --><!-- body ignored --><p>test</p>', $washed, "HTML invalid comments (#1487759)");
}
/**
* Test fixing of invalid self-closing elements (#1489137)
*/
function test_self_closing()
{
$html = "<textarea>test";
$washer = new rcube_washtml;
$washed = $washer->wash($html);
$this->assertRegExp('|<textarea>test</textarea>|', $washed, "Self-closing textarea (#1489137)");
}
/**
* Test fixing of invalid closing tags (#1489446)
*/
function test_closing_tag_attrs()
{
$html = "<a href=\"http://test.com\">test</a href>";
$washer = new rcube_washtml;
$washed = $washer->wash($html);
$this->assertRegExp('|</a>|', $washed, "Invalid closing tag (#1489446)");
}
/**
* Test fixing of invalid lists nesting (#1488768)
*/
function test_lists()
{
$data = array(
array(
"<ol><li>First</li><li>Second</li><ul><li>First sub</li></ul><li>Third</li></ol>",
"<ol><li>First</li><li>Second<ul><li>First sub</li></ul></li><li>Third</li></ol>"
),
array(
"<ol><li>First<ul><li>First sub</li></ul></li></ol>",
"<ol><li>First<ul><li>First sub</li></ul></li></ol>",
),
array(
"<ol><li>First<ol><li>First sub</li></ol></li></ol>",
"<ol><li>First<ol><li>First sub</li></ol></li></ol>",
),
array(
"<ul><li>First</li><ul><li>First sub</li><ul><li>sub sub</li></ul></ul><li></li></ul>",
"<ul><li>First<ul><li>First sub<ul><li>sub sub</li></ul></li></ul></li><li></li></ul>",
),
array(
"<ul><li>First</li><li>second</li><ul><ul><li>sub sub</li></ul></ul></ul>",
"<ul><li>First</li><li>second<ul><ul><li>sub sub</li></ul></ul></li></ul>",
),
array(
"<ol><ol><ol></ol></ol></ol>",
"<ol><ol><ol></ol></ol></ol>",
),
array(
"<div><ol><ol><ol></ol></ol></ol></div>",
"<div><ol><ol><ol></ol></ol></ol></div>",
),
);
foreach ($data as $element) {
rcube_washtml::fix_broken_lists($element[0]);
$this->assertSame($element[1], $element[0], "Broken nested lists (#1488768)");
}
}
}

@ -0,0 +1,268 @@
<?php
/**
* Test class to test steps/mail/func.inc functions
*
* @package Tests
*/
class MailFunc extends PHPUnit_Framework_TestCase
{
function setUp()
{
// simulate environment to successfully include func.inc
$GLOBALS['RCMAIL'] = $RCMAIL = rcmail::get_instance();
$GLOBALS['OUTPUT'] = $OUTPUT = $RCMAIL->load_gui();
$RCMAIL->action = 'autocomplete';
$RCMAIL->storage_init(false);
require_once INSTALL_PATH . 'program/steps/mail/func.inc';
}
/**
* Helper method to create a HTML message part object
*/
function get_html_part($body)
{
$part = new rcube_message_part;
$part->ctype_primary = 'text';
$part->ctype_secondary = 'html';
$part->body = file_get_contents(TESTS_DIR . $body);
$part->replaces = array();
return $part;
}
/**
* Test sanitization of a "normal" html message
*/
function test_html()
{
$part = $this->get_html_part('src/htmlbody.txt');
$part->replaces = array('ex1.jpg' => 'part_1.2.jpg', 'ex2.jpg' => 'part_1.2.jpg');
// render HTML in normal mode
$html = rcmail_html4inline(rcmail_print_body($part, array('safe' => false)), 'foo');
$this->assertRegExp('/src="'.$part->replaces['ex1.jpg'].'"/', $html, "Replace reference to inline image");
$this->assertRegExp('#background="./program/resources/blocked.gif"#', $html, "Replace external background image");
$this->assertNotRegExp('/ex3.jpg/', $html, "No references to external images");
$this->assertNotRegExp('/<meta [^>]+>/', $html, "No meta tags allowed");
//$this->assertNoPattern('/<style [^>]+>/', $html, "No style tags allowed");
$this->assertNotRegExp('/<form [^>]+>/', $html, "No form tags allowed");
$this->assertRegExp('/Subscription form/', $html, "Include <form> contents");
$this->assertRegExp('/<!-- link ignored -->/', $html, "No external links allowed");
$this->assertRegExp('/<a[^>]+ target="_blank"/', $html, "Set target to _blank");
$this->assertTrue($GLOBALS['REMOTE_OBJECTS'], "Remote object detected");
// render HTML in safe mode
$html2 = rcmail_html4inline(rcmail_print_body($part, array('safe' => true)), 'foo');
$this->assertRegExp('/<style [^>]+>/', $html2, "Allow styles in safe mode");
$this->assertRegExp('#src="http://evilsite.net/mailings/ex3.jpg"#', $html2, "Allow external images in HTML (safe mode)");
$this->assertRegExp("#url\('?http://evilsite.net/newsletter/image/bg/bg-64.jpg'?\)#", $html2, "Allow external images in CSS (safe mode)");
$css = '<link rel="stylesheet" .+_u=tmp-[a-z0-9]+\.css.+_action=modcss';
$this->assertRegExp('#'.$css.'#Ui', $html2, "Filter (anonymized) external styleseehts with utils/modcss.inc");
}
/**
* Test the elimination of some trivial XSS vulnerabilities
*/
function test_html_xss()
{
$part = $this->get_html_part('src/htmlxss.txt');
$washed = rcmail_print_body($part, array('safe' => true));
$this->assertNotRegExp('/src="skins/', $washed, "Remove local references");
$this->assertNotRegExp('/\son[a-z]+/', $washed, "Remove on* attributes");
$html = rcmail_html4inline($washed, 'foo');
$this->assertNotRegExp('/onclick="return rcmail.command(\'compose\',\'xss@somehost.net\',this)"/', $html, "Clean mailto links");
$this->assertNotRegExp('/alert/', $html, "Remove alerts");
}
/**
* Test HTML sanitization to fix the CSS Expression Input Validation Vulnerability
* reported at http://www.securityfocus.com/bid/26800/
*/
function test_html_xss2()
{
$part = $this->get_html_part('src/BID-26800.txt');
$washed = rcmail_html4inline(rcmail_print_body($part, array('safe' => true)), 'dabody', '', $attr, true);
$this->assertNotRegExp('/alert|expression|javascript|xss/', $washed, "Remove evil style blocks");
$this->assertNotRegExp('/font-style:italic/', $washed, "Allow valid styles");
}
/**
* Test the elimination of some XSS vulnerabilities
*/
function test_html_xss3()
{
// #1488850
$html = '<p><a href="data:text/html,&lt;script&gt;alert(document.cookie)&lt;/script&gt;">Firefox</a>'
.'<a href="vbscript:alert(document.cookie)">Internet Explorer</a></p>';
$washed = rcmail_wash_html($html, array('safe' => true), array());
$this->assertNotRegExp('/data:text/', $washed, "Remove data:text/html links");
$this->assertNotRegExp('/vbscript:/', $washed, "Remove vbscript: links");
}
/**
* Test washtml class on non-unicode characters (#1487813)
*/
function test_washtml_utf8()
{
$part = $this->get_html_part('src/invalidchars.html');
$washed = rcmail_print_body($part);
$this->assertRegExp('/<p>символ<\/p>/', $washed, "Remove non-unicode characters from HTML message body");
}
/**
* Test links pattern replacements in plaintext messages
*/
function test_plaintext()
{
$part = new rcube_message_part;
$part->ctype_primary = 'text';
$part->ctype_secondary = 'plain';
$part->body = quoted_printable_decode(file_get_contents(TESTS_DIR . 'src/plainbody.txt'));
$html = rcmail_print_body($part, array('safe' => true));
$this->assertRegExp('/<a href="mailto:nobody@roundcube.net" onclick="return rcmail.command\(\'compose\',\'nobody@roundcube.net\',this\)">nobody@roundcube.net<\/a>/', $html, "Mailto links with onclick");
$this->assertRegExp('#<a rel="noreferrer" target="_blank" href="http://www.apple.com/legal/privacy">http://www.apple.com/legal/privacy</a>#', $html, "Links with target=_blank");
$this->assertRegExp('#\\[<a rel="noreferrer" target="_blank" href="http://example.com/\\?tx\\[a\\]=5">http://example.com/\\?tx\\[a\\]=5</a>\\]#', $html, "Links with square brackets");
}
/**
* Test mailto links in html messages
*/
function test_mailto()
{
$part = $this->get_html_part('src/mailto.txt');
// render HTML in normal mode
$html = rcmail_html4inline(rcmail_print_body($part, array('safe' => false)), 'foo');
$mailto = '<a href="mailto:me@me.com"'
.' onclick="return rcmail.command(\'compose\',\'me@me.com?subject=this is the subject&amp;body=this is the body\',this)" rel="noreferrer">e-mail</a>';
$this->assertRegExp('|'.preg_quote($mailto, '|').'|', $html, "Extended mailto links");
}
/**
* Test the elimination of HTML comments
*/
function test_html_comments()
{
$part = $this->get_html_part('src/htmlcom.txt');
$washed = rcmail_print_body($part, array('safe' => true));
// #1487759
$this->assertRegExp('|<p>test1</p>|', $washed, "Buggy HTML comments");
// but conditional comments (<!--[if ...) should be removed
$this->assertNotRegExp('|<p>test2</p>|', $washed, "Conditional HTML comments");
}
/**
* Test URI base resolving in HTML messages
*/
function test_resolve_base()
{
$html = file_get_contents(TESTS_DIR . 'src/htmlbase.txt');
$html = rcube_washtml::resolve_base($html);
$this->assertRegExp('|src="http://alec\.pl/dir/img1\.gif"|', $html, "URI base resolving [1]");
$this->assertRegExp('|src="http://alec\.pl/dir/img2\.gif"|', $html, "URI base resolving [2]");
$this->assertRegExp('|src="http://alec\.pl/img3\.gif"|', $html, "URI base resolving [3]");
// base resolving exceptions
$this->assertRegExp('|src="cid:theCID"|', $html, "URI base resolving exception [1]");
$this->assertRegExp('|src="http://other\.domain\.tld/img3\.gif"|', $html, "URI base resolving exception [2]");
}
/**
* Test identities selection using Return-Path header
*/
function test_rcmail_identity_select()
{
$identities = array(
array(
'name' => 'Test',
'email_ascii' => 'addr@domain.tld',
'ident' => 'Test <addr@domain.tld>',
),
array(
'name' => 'Test',
'email_ascii' => 'thing@domain.tld',
'ident' => 'Test <thing@domain.tld>',
),
array(
'name' => 'Test',
'email_ascii' => 'other@domain.tld',
'ident' => 'Test <other@domain.tld>',
),
);
$message = new stdClass;
$message->headers = new rcube_message_header;
$message->headers->set('Return-Path', '<some_thing@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[0], $res);
$message->headers->set('Return-Path', '<thing@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[1], $res);
}
/**
* Test identities selection (#1489378)
*/
function test_rcmail_identity_select2()
{
$identities = array(
array(
'name' => 'Test 1',
'email_ascii' => 'addr1@domain.tld',
'ident' => 'Test 1 <addr1@domain.tld>',
),
array(
'name' => 'Test 2',
'email_ascii' => 'addr2@domain.tld',
'ident' => 'Test 2 <addr2@domain.tld>',
),
array(
'name' => 'Test 3',
'email_ascii' => 'addr3@domain.tld',
'ident' => 'Test 3 <addr3@domain.tld>',
),
array(
'name' => 'Test 4',
'email_ascii' => 'addr2@domain.tld',
'ident' => 'Test 4 <addr2@domain.tld>',
),
);
$message = new stdClass;
$message->headers = new rcube_message_header;
$message->headers->set('From', '<addr2@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[1], $res);
$message->headers->set('From', 'Test 2 <addr2@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[1], $res);
$message->headers->set('From', 'Other <addr2@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[1], $res);
$message->headers->set('From', 'Test 4 <addr2@domain.tld>');
$res = rcmail_identity_select($message, $identities);
$this->assertSame($identities[3], $res);
}
}

@ -0,0 +1,21 @@
<?php
class Selenium_Addressbook_Addressbook extends Selenium_Test
{
public function testAddressbook()
{
$this->go('addressbook');
// check task
$env = $this->get_env();
$this->assertEquals('addressbook', $env['task']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('qsearchbox', $objects);
$this->assertContains('folderlist', $objects);
$this->assertContains('contactslist', $objects);
$this->assertContains('countdisplay', $objects);
}
}

@ -0,0 +1,29 @@
<?php
class Selenium_Addressbook_Import extends Selenium_Test
{
public function testImport()
{
$this->go('addressbook', 'import');
// check task and action
$env = $this->get_env();
$this->assertEquals('addressbook', $env['task']);
$this->assertEquals('import', $env['action']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('importform', $objects);
}
public function testImport2()
{
$this->go('addressbook', 'import');
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('importform', $objects);
}
}

@ -0,0 +1,21 @@
<?php
class Selenium_Login extends Selenium_Test
{
public function testLogin()
{
// first test, we're already on the login page
$this->url(TESTS_URL);
// task should be set to 'login'
$env = $this->get_env();
$this->assertEquals('login', $env['task']);
// test valid login
$this->login();
// task should be set to 'mail' now
$env = $this->get_env();
$this->assertEquals('mail', $env['task']);
}
}

@ -0,0 +1,20 @@
<?php
class Selenium_Logout extends Selenium_Test
{
public function testLogout()
{
$this->go('mail');
$this->click_button('logout');
sleep(TESTS_SLEEP);
// task should be set to 'login'
$env = $this->get_env();
$this->assertEquals('login', $env['task']);
// form should exist
$user_input = $this->byCssSelector('form input[name="_user"]');
}
}

@ -0,0 +1,14 @@
<?php
class Selenium_Mail_CheckRecent extends Selenium_Test
{
public function testCheckRecent()
{
$this->go('mail');
$res = $this->ajaxResponse('check-recent', "rcmail.command('checkmail')");
$this->assertEquals('check-recent', $res['action']);
$this->assertRegExp('/this\.set_unread_count/', $res['exec']);
}
}

@ -0,0 +1,25 @@
<?php
class Selenium_Mail_Compose extends Selenium_Test
{
public function testCompose()
{
$this->go('mail', 'compose');
// check task and action
$env = $this->get_env();
$this->assertEquals('mail', $env['task']);
$this->assertEquals('compose', $env['action']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('qsearchbox', $objects);
$this->assertContains('addressbookslist', $objects);
$this->assertContains('contactslist', $objects);
$this->assertContains('messageform', $objects);
$this->assertContains('attachmentlist', $objects);
$this->assertContains('filedrop', $objects);
$this->assertContains('uploadform', $objects);
}
}

@ -0,0 +1,13 @@
<?php
class Selenium_Mail_Getunread extends Selenium_Test
{
public function testGetunread()
{
$this->go('mail');
$res = $this->ajaxResponse('getunread', "rcmail.http_request('getunread')");
$this->assertEquals('getunread', $res['action']);
}
}

@ -0,0 +1,25 @@
<?php
class Selenium_Mail_List extends Selenium_Test
{
public function testCheckRecent()
{
$this->go('mail');
$res = $this->ajaxResponse('list', "rcmail.command('list')");
$this->assertEquals('list', $res['action']);
$this->assertRegExp('/this\.set_pagetitle/', $res['exec']);
$this->assertRegExp('/this\.set_unread_count/', $res['exec']);
$this->assertRegExp('/this\.set_rowcount/', $res['exec']);
$this->assertRegExp('/this\.set_message_coltypes/', $res['exec']);
// $this->assertRegExp('/this\.add_message_row/', $res['exec']);
$this->assertContains('current_page', $res['env']);
$this->assertContains('exists', $res['env']);
$this->assertContains('pagecount', $res['env']);
$this->assertContains('pagesize', $res['env']);
$this->assertContains('messagecount', $res['env']);
$this->assertContains('mailbox', $res['env']);
}
}

@ -0,0 +1,23 @@
<?php
class Selenium_Mail_Mail extends Selenium_Test
{
public function testMail()
{
$this->go('mail');
// check task
$env = $this->get_env();
$this->assertEquals('mail', $env['task']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('qsearchbox', $objects);
$this->assertContains('mailboxlist', $objects);
$this->assertContains('messagelist', $objects);
$this->assertContains('quotadisplay', $objects);
$this->assertContains('search_filter', $objects);
$this->assertContains('countdisplay', $objects);
}
}

@ -0,0 +1,14 @@
<?php
class Selenium_Settings_About extends Selenium_Test
{
public function testAbout()
{
$this->url(TESTS_URL . '/?_task=settings&_action=about');
// check task and action
$env = $this->get_env();
$this->assertEquals('settings', $env['task']);
$this->assertEquals('about', $env['action']);
}
}

@ -0,0 +1,20 @@
<?php
class Selenium_Settings_Folders extends Selenium_Test
{
public function testFolders()
{
$this->go('settings', 'folders');
// task should be set to 'settings' and action to 'folders'
$env = $this->get_env();
$this->assertEquals('settings', $env['task']);
$this->assertEquals('folders', $env['action']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('quotadisplay', $objects);
$this->assertContains('subscriptionlist', $objects);
}
}

@ -0,0 +1,19 @@
<?php
class Selenium_Settings_Identities extends Selenium_Test
{
public function testIdentities()
{
$this->go('settings', 'identities');
// check task and action
$env = $this->get_env();
$this->assertEquals('settings', $env['task']);
$this->assertEquals('identities', $env['action']);
$objects = $this->get_objects();
// these objects should be there always
$this->assertContains('identitieslist', $objects);
}
}

@ -0,0 +1,17 @@
<?php
class Selenium_Settings_Settings extends Selenium_Test
{
public function testSettings()
{
$this->go('settings');
// task should be set to 'settings'
$env = $this->get_env();
$this->assertEquals('settings', $env['task']);
$objects = $this->get_objects();
$this->assertContains('sectionslist', $objects);
}
}

@ -0,0 +1,185 @@
<?php
/*
+-----------------------------------------------------------------------+
| tests/Selenium/bootstrap.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2009-2013, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Environment initialization script for unit tests |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
if (php_sapi_name() != 'cli')
die("Not in shell mode (php-cli)");
if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(dirname(__FILE__) . '/../../') . '/' );
define('TESTS_DIR', dirname(__FILE__) . '/');
if (@is_dir(TESTS_DIR . 'config')) {
define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config');
}
require_once(INSTALL_PATH . 'program/include/iniset.php');
// Extend include path so some plugin test won't fail
$include_path = ini_get('include_path') . PATH_SEPARATOR . TESTS_DIR . '..';
if (set_include_path($include_path) === false) {
die("Fatal error: ini_set/set_include_path does not work.");
}
$rcmail = rcube::get_instance('test');
define('TESTS_URL', $rcmail->config->get('tests_url'));
define('TESTS_BROWSER', $rcmail->config->get('tests_browser', 'firefox'));
define('TESTS_USER', $rcmail->config->get('tests_username'));
define('TESTS_PASS', $rcmail->config->get('tests_password'));
define('TESTS_SLEEP', $rcmail->config->get('tests_sleep', 5));
PHPUnit_Extensions_Selenium2TestCase::shareSession(true);
// @TODO: remove user record from DB before running tests
// @TODO: make sure mailbox has some content (always the same) or is empty
// @TODO: plugins: enable all?
/**
* Base class for all tests in this directory
*/
class Selenium_Test extends PHPUnit_Extensions_Selenium2TestCase
{
protected function setUp()
{
// $this->rc = rcube::get_instance();
$this->setBrowser(TESTS_BROWSER);
// Set root to our index.html, for better performance
// See https://github.com/sebastianbergmann/phpunit-selenium/issues/217
$this->setBrowserUrl(TESTS_URL . '/tests/Selenium');
}
protected function login()
{
$this->go('mail');
$user_input = $this->byCssSelector('form input[name="_user"]');
$pass_input = $this->byCssSelector('form input[name="_pass"]');
$submit = $this->byCssSelector('form input[type="submit"]');
$user_input->value(TESTS_USER);
$pass_input->value(TESTS_PASS);
// submit login form
$submit->click();
// wait after successful login
sleep(TESTS_SLEEP);
}
protected function go($task = 'mail', $action = null)
{
$this->url(TESTS_URL . '/?_task=' . $task);
// wait for interface load (initial ajax requests, etc.)
sleep(TESTS_SLEEP);
if ($action) {
$this->click_button($action);
sleep(TESTS_SLEEP);
}
}
protected function get_env()
{
return $this->execute(array(
'script' => 'return rcmail.env;',
'args' => array(),
));
}
protected function get_buttons($action)
{
$buttons = $this->execute(array(
'script' => "return rcmail.buttons['$action'];",
'args' => array(),
));
if (is_array($buttons)) {
foreach ($buttons as $idx => $button) {
$buttons[$idx] = $button['id'];
}
}
return (array) $buttons;
}
protected function get_objects()
{
return $this->execute(array(
'script' => "var i,r = []; for (i in rcmail.gui_objects) r.push(i); return r;",
'args' => array(),
));
}
protected function click_button($action)
{
$buttons = $this->get_buttons($action);
$id = array_shift($buttons);
// this doesn't work for me
$this->byId($id)->click();
}
protected function ajaxResponse($action, $script = '', $button = false)
{
if (!$script && !$button) {
$script = "rcmail.command('$action')";
}
$script =
"if (!window.test_ajax_response) {
window.test_ajax_response_object = {};
function test_ajax_response(response)
{
if (response.response && response.response.action) {
window.test_ajax_response_object[response.response.action] = response.response;
}
}
rcmail.addEventListener('responsebefore', test_ajax_response);
}
window.test_ajax_response_object['$action'] = null;
$script;
";
// run request
$this->execute(array(
'script' => $script,
'args' => array(),
));
if ($button) {
$this->click_button($action);
}
// wait
sleep(TESTS_SLEEP);
// get response
$response = $this->execute(array(
'script' => "return window.test_ajax_response_object['$action'];",
'args' => array(),
));
return $response;
}
}

@ -0,0 +1,8 @@
<html>
<head>
<title>Roundcube Webmail Tests</title>
</head>
<body>
Testing...
</body>
</html>

@ -0,0 +1,21 @@
<phpunit backupGlobals="false"
bootstrap="bootstrap.php"
colors="true">
<testsuites>
<testsuite name="All Tests">
<file>Login.php</file><!-- Login.php test must be first -->
<file>Addressbook/Addressbook.php</file>
<file>Addressbook/Import.php</file>
<file>Mail/Mail.php</file>
<file>Mail/CheckRecent.php</file>
<file>Mail/Compose.php</file>
<file>Mail/Getunread.php</file>
<file>Mail/List.php</file>
<file>Settings/About.php</file>
<file>Settings/Folders.php</file>
<file>Settings/Identities.php</file>
<file>Settings/Settings.php</file>
<file>Logout.php</file><!-- Logout.php test must be last -->
</testsuite>
</testsuites>
</phpunit>

@ -0,0 +1,41 @@
<?php
/*
+-----------------------------------------------------------------------+
| tests/bootstrap.php |
| |
| This file is part of the Roundcube Webmail client |
| Copyright (C) 2009-2012, The Roundcube Dev Team |
| |
| Licensed under the GNU General Public License version 3 or |
| any later version with exceptions for skins & plugins. |
| See the README file for a full license statement. |
| |
| PURPOSE: |
| Environment initialization script for unit tests |
+-----------------------------------------------------------------------+
| Author: Thomas Bruederli <roundcube@gmail.com> |
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
if (php_sapi_name() != 'cli')
die("Not in shell mode (php-cli)");
if (!defined('INSTALL_PATH')) define('INSTALL_PATH', realpath(dirname(__FILE__) . '/..') . '/' );
define('TESTS_DIR', dirname(__FILE__) . '/');
if (@is_dir(TESTS_DIR . 'config')) {
define('RCUBE_CONFIG_DIR', TESTS_DIR . 'config');
}
require_once(INSTALL_PATH . 'program/include/iniset.php');
rcmail::get_instance('test')->config->set('devel_mode', false);
// Extend include path so some plugin test won't fail
$include_path = ini_get('include_path') . PATH_SEPARATOR . TESTS_DIR . '..';
if (set_include_path($include_path) === false) {
die("Fatal error: ini_set/set_include_path does not work.");
}

@ -0,0 +1,70 @@
<phpunit backupGlobals="false"
bootstrap="bootstrap.php"
colors="true">
<testsuites>
<testsuite name="All Tests">
<file>Framework/BaseReplacer.php</file>
<file>Framework/Bootstrap.php</file>
<file>Framework/Browser.php</file>
<file>Framework/Cache.php</file>
<file>Framework/Charset.php</file>
<file>Framework/ContentFilter.php</file>
<file>Framework/Csv2vcard.php</file>
<file>Framework/Enriched.php</file>
<file>Framework/Html.php</file>
<file>Framework/Html2text.php</file>
<file>Framework/Imap.php</file>
<file>Framework/ImapGeneric.php</file>
<file>Framework/Image.php</file>
<file>Framework/MessageHeader.php</file>
<file>Framework/MessagePart.php</file>
<file>Framework/Mime.php</file>
<file>Framework/Rcube.php</file>
<file>Framework/ResultIndex.php</file>
<file>Framework/ResultSet.php</file>
<file>Framework/ResultThread.php</file>
<file>Framework/Smtp.php</file>
<file>Framework/Spellchecker.php</file>
<file>Framework/StringReplacer.php</file>
<file>Framework/User.php</file>
<file>Framework/Utils.php</file>
<file>Framework/VCard.php</file>
<file>Framework/Washtml.php</file>
<file>MailFunc.php</file>
</testsuite>
<testsuite name="Plugins Tests">
<file>./../plugins/acl/tests/Acl.php</file>
<file>./../plugins/additional_message_headers/tests/AdditionalMessageHeaders.php</file>
<file>./../plugins/archive/tests/Archive.php</file>
<file>./../plugins/autologon/tests/Autologon.php</file>
<file>./../plugins/database_attachments/tests/DatabaseAttachments.php</file>
<file>./../plugins/debug_logger/tests/DebugLogger.php</file>
<file>./../plugins/emoticons/tests/Emoticons.php</file>
<file>./../plugins/enigma/tests/Enigma.php</file>
<file>./../plugins/example_addressbook/tests/ExampleAddressbook.php</file>
<file>./../plugins/filesystem_attachments/tests/FilesystemAttachments.php</file>
<file>./../plugins/help/tests/Help.php</file>
<file>./../plugins/hide_blockquote/tests/HideBlockquote.php</file>
<file>./../plugins/http_authentication/tests/HttpAuthentication.php</file>
<file>./../plugins/identity_select/tests/IdentitySelect.php</file>
<file>./../plugins/jqueryui/tests/Jqueryui.php</file>
<file>./../plugins/managesieve/tests/Managesieve.php</file>
<file>./../plugins/managesieve/tests/Parser.php</file>
<file>./../plugins/managesieve/tests/Tokenizer.php</file>
<file>./../plugins/markasjunk/tests/Markasjunk.php</file>
<file>./../plugins/new_user_dialog/tests/NewUserDialog.php</file>
<file>./../plugins/new_user_identity/tests/NewUserIdentity.php</file>
<file>./../plugins/newmail_notifier/tests/NewmailNotifier.php</file>
<file>./../plugins/password/tests/Password.php</file>
<file>./../plugins/redundant_attachments/tests/RedundantAttachments.php</file>
<file>./../plugins/show_additional_headers/tests/ShowAdditionalHeaders.php</file>
<file>./../plugins/squirrelmail_usercopy/tests/Squirrelmail_usercopy.php</file>
<file>./../plugins/subscriptions_option/tests/SubscriptionsOption.php</file>
<file>./../plugins/userinfo/tests/Userinfo.php</file>
<file>./../plugins/vcard_attachments/tests/VcardAttachments.php</file>
<file>./../plugins/virtuser_file/tests/VirtuserFile.php</file>
<file>./../plugins/virtuser_query/tests/VirtuserQuery.php</file>
<file>./../plugins/zipdownload/tests/Zipdownload.php</file>
</testsuite>
</testsuites>
</phpunit>

@ -0,0 +1,53 @@
<html>
<head>
</head>
<body>
<h1>1 test</h1>
<p>&lt;style&gt; block</p>
<style>input { left:expression( alert(&#039;expression!&#039;) ) }</style>
<style>div { background:url(alert(&#039;URL!&#039;) ) }</style>
<h1>2 test</h1>
<p>&lt;div&gt; block</p>
<div style="font-style:italic">valid css</div>
<div style="color:red; background:url('//somedomain.com/somepath/somefile.png')">
<div style="{ left:expression( alert(&#039;expression!&#039;) ) }">
<div style="{ background:url( alert(&#039;URL!&#039;) ) }">
<h1>3 test</h1>
<p>Inject comment text</p>
<div style="{ left:exp/* */ression( alert(&#039;xss3&#039;) ) }">
<div style=" background:u/* */rl( alert(&#039;xssurl3&#039;) ) ">
<h1>4 test</h1>
<p>Using reverse solid to directe the codepoint</p>
<div style="{ left:\0065\0078pression( alert(&#039;xss4&#039;) ) }">
<div style="{ background:\0075rl( alert(&#039;xssurl4&#039;) ) }">
<h1>5 test</h1>
<p>Character entity references</p>
<p>Character entity references is acceptable in "inline styles"</p>
<div style="{ left:&#x0065;xpression( alert(&#039;xss&#039;) ) }">
<div style="{ left:&#101;xpression( alert(&#039;xss&#039;) ) }">
<div style="{ background:&#x0075;rl( alert(&#039;URL!&#039;) ) }">
<div style="{ background:&#117;rl( alert(&#039;URL!&#039;) ) }">
<div style="{ left:&#x0065xpression( alert(&#039;xss&#039;) ) }">
<div style="{ left:ï½.ï½.ï½<C3AF>ï½.ï½.ï½.ï½.ï½.ï½<C3AF>ï½.( alert(&#039;xss&#039;) ) }">
<div style="{ left:ï½.ï½.&#x2f;**/pression( alert(&#039;xss&#039;) ) }">
<div style="{ left:exp&#x0280;essio&#x0274;( alert(&#039;xss&#039;) ) }">
<div style="{ left:&#x5c;0065&#x5c;0078pression( alert(&#039;xss&#039;) ) }">
<div style="{ left:ex p ression( alert(&#039;xss&#039;) ) }">
<div style="{ background:ï½.ï½.ï½.( javascript:alert(&#039;xss&#039;) ) }">
<div style="{ background:&#x0075;/**/rl( javascript:alert(&#039;xss&#039;) ) }">
<div style="{ background:\0075\0072\006c( javascript:alert(&#039;xss&#039;) ) }">
<div style="{ background:u&#x0280;&#x029F;( javascript:alert(&#039;xss&#039;) )
}">
<div style="{ background:&#x5c;0075&#x5c;0280l( javascript:alert(&#039;xss&#039;)
) }">
<div style="{ background:u r l( javascript:alert(&#039;xss&#039;) ) }">
</body>
</html>

@ -0,0 +1,5 @@
Primary Email
test1@domain.tld
test2@domain.tld
test3@domain.tld
test4@domain.tld
1 Primary Email
2 test1@domain.tld
3 test2@domain.tld
4 test3@domain.tld
5 test4@domain.tld

@ -0,0 +1,20 @@
BEGIN:VCARD
VERSION:3.0
FN:test1@domain.tld
EMAIL;TYPE=INTERNET;TYPE=PREF:test1@domain.tld
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:test2@domain.tld
EMAIL;TYPE=INTERNET;TYPE=PREF:test2@domain.tld
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:test3@domain.tld
EMAIL;TYPE=INTERNET;TYPE=PREF:test3@domain.tld
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:test4@domain.tld
EMAIL;TYPE=INTERNET;TYPE=PREF:test4@domain.tld
END:VCARD

@ -0,0 +1,2 @@
First Name,Last Name,Display Name,Nickname,Primary Email,Secondary Email,Screen Name,Work Phone,Home Phone,Fax Number,Pager Number,Mobile Number,Home Address,Home Address 2,Home City,Home State,Home ZipCode,Home Country,Work Address,Work Address 2,Work City,Work State,Work ZipCode,Work Country,Job Title,Department,Organization,Web Page 1,Web Page 2,Birth Year,Birth Month,Birth Day,Custom 1,Custom 2,Custom 3,Custom 4,Notes,
Firstname,Lastname,Displayname,Nick,test@domain.tld,next@domain.tld,,phone work,phone home,fax,pager,mobile,Priv address,,City,region,xx-xxx,USA,Addr work,,Wcity,Wstate,33-333,Poland,title,department,Organization,http://page.com,http://webpage.tld,1970,11,15,,,,,,
1 First Name Last Name Display Name Nickname Primary Email Secondary Email Screen Name Work Phone Home Phone Fax Number Pager Number Mobile Number Home Address Home Address 2 Home City Home State Home ZipCode Home Country Work Address Work Address 2 Work City Work State Work ZipCode Work Country Job Title Department Organization Web Page 1 Web Page 2 Birth Year Birth Month Birth Day Custom 1 Custom 2 Custom 3 Custom 4 Notes
2 Firstname Lastname Displayname Nick test@domain.tld next@domain.tld phone work phone home fax pager mobile Priv address City region xx-xxx USA Addr work Wcity Wstate 33-333 Poland title department Organization http://page.com http://webpage.tld 1970 11 15

@ -0,0 +1,20 @@
BEGIN:VCARD
VERSION:3.0
FN:Displayname
N:Lastname;Firstname;;;
NICKNAME:Nick
EMAIL;TYPE=INTERNET;TYPE=PREF:test@domain.tld
EMAIL;TYPE=INTERNET;TYPE=OTHER:next@domain.tld
TEL;TYPE=work:phone work
TEL;TYPE=home:phone home
TEL;TYPE=fax:fax
TEL;TYPE=cell:mobile
TITLE:title
X-DEPARTMENT:department
ORG:Organization
URL;TYPE=homepage:http://page.com
URL;TYPE=other:http://webpage.tld
BDAY;VALUE=date:1970-11-15
ADR;TYPE=home:;;Priv address;City;region;xx-xxx;USA
ADR;TYPE=work:;;Addr work;Wcity;Wstate;33-333;Poland
END:VCARD

@ -0,0 +1,49 @@
BEGIN:VCARD
VERSION:3.0
N:;;;;
FN:Apple Computer AG
ORG:Apple Computer AG;
item1.ADR;type=WORK;type=pref:;;Birgistrasse 4a;Wallisellen-Zürich;;8304;Switzerland
item1.X-ABADR:ch
item2.URL;type=pref:http\://www.apple.ch
item2.X-ABLabel:_$!<HomePage>!$_
PHOTO;BASE64:
/9j/4AAQSkZJRgABAQAAAQABAAD/7QAcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAD/2wBDAAEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQH/wAARCAAwADADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAA
AAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEI
I0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlq
c3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW
19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL
/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLR
ChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn
6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKAPmH43ftT+CfgzqNt4bNjeeLvGV2IHXw7
pVxDbLZx3LBbdtU1GVLhbN7jIMFvHa3VzIpWRoY4mWQ9dDCTrrmuoQ/mavfvZXV7dW2jkr4ynQfL
Zzn1inZL1lZ6+ST87H0lp1zLe6fY3k9s1nNd2dtczWjv5j2ss8KSyWzybU3tA7mJn2JuKk7Vzgcr
Vm1e9m1fvrv8zqi+aKbVm0nbtdXt8i5SGFAHHeOfH3hH4b6DP4k8Z61a6JpUBCCW4LPNdTsCUtbK
1iD3F5dSYO2C3jd8AuwVFZhdOnOrLlhFyf4Lzb6IzqVYUo81SSiundvslu3/AEz5i0n9u74Fanqo
064m8UaNbvII49X1TRUGnnORvmFje3t5BGTjDtatwcyCPBrreArpX9xvqlJ3/FJP7zlWYUHKzVRL
+ZxVvnaTa+4+QLvVPgJ4U+LutfFXx78QJfi3q954iuvEOieHvBmkyzaVbO1x5ulPruq6pLawTvp1
uLdIrK08xFmgXzl2oI67LV50o0qdP2K5VGUptKXnyxi29XfVtb6HDehGtKpUm6zcnNKCfK9brnlK
3pZJ37pH3/8ACj9qb4T/ABd1FdD0TUr3SPETozwaJ4ht47C5vQgLONOnjnuLS8dVBYwJOt1tDMIN
oLV51XCVqK5pJSj1cW3b1uk1vvqvM9Kji6VZ8qbjJ7KVlf0abTf4n0dXMdQUAfhf+2J8UNW8ffFz
W9Cnlki0XwDqOp+GdNsFdhB9qsr6a31DUDHu2tcXbwojSEbhFCka4Uc+9hKUadGMl8VRKcn11V0v
RJng4urKpWkntTlKCXTRtN+re58n11HKFAH6PfsGfBvQfEl3rHxR8Q2y38vhrUrfT/DNpIT5FvqY
iF1carIgI8ye2R4Y7RXykbySTbS6xlfOx9aUVGlF2503N+W1vnrc9HAUYzlKrJX5GuVf3t7+dvu3
vc/WKvIPXCgD8FP2s/BF/wCC/jd4wlu0It/Fmp6h4usJf4JINZ1G7ndVbu0UpZZBztY446V9BhZq
dCnZ/DFQfrFJHz+Kg4V6l/tSc15qTb/rzPmqug5woA++v2J/j74d+HN9rHgLxndrpmjeJr62vtJ1
mbP2Sw1dY/s0ltfOM+Rb30Yh8u5ZTHFPEFlZEk3Dgx2HlVUZw1lBNOPVp9vNa6X22137sFiI0ZSh
N2jNpqXSLSe/k+/R+p+w1eMe0FAHxz+2P8DLr4r+CIPEPhy2Nx4y8FJdXVnaxrmfWdGlAk1DSosK
WkuozEt5p8fHmTLNADuuQR24KuqU3GTtCpbXtLo32T2b9GcWNw7qwU4q84X06yi9Wl531XfXyPxK
ME4nNsYZRciUwG3MbicTh/LMJix5glD/ACGPbv3/AC4zxXtniFvUNJ1XSmjXVNM1DTWmUvCuoWVz
ZtKgxloxcRxmRRkZZcgZGTzSTT2afo7hqtz6w/ZB+BV78UPHtl4n1eykHgfwdewajfXE0bCDVtVt
mE+n6PAzAJOBOkdxqAUssdsnlSDNwoPLi66pU3FP95NNJdk95P06d35XOvCUHWqJtfu4NOT7vdR8
7vfsvVH7gV4R7oUAFAHKReA/A8Gsy+IofBnhSHxBO7ST67F4d0iPWZnb7zy6mlmL2R2/iZ5yT3NX
7Spbl9pPl/l55W+69iPZUubm9nDmvfm5I81+97XuX9a8MeGvEtsLLxF4e0PX7MMGFprWk2Gq2wZe
jCC+t54tw7HZkdqUZzg7wlKL7xk4v700OUIT0lCMl2lFS/NMuaXpOlaHZQ6Zoumafo+nW4It9P0u
yttPsoATkiG1tI4oIgTyQkagnmk5Sk7ybk+7bb+96jjGMVaMVFdopJfcjQpDP//Z
X-ABShowAs:COMPANY
X-ABUID:2E4CB084-4767-4C85-BBCA-805B1DCB1C8E\:ABPerson
END:VCARD

@ -0,0 +1,19 @@
I'm replying on this with a very long line which is then wrapped and space-stuffed because the draft is saved as format=flowed.
From what's specified in RFC 2646 some lines need to be space-stuffed to avoid muning during transport.
X
On XX.YY.YYYY Y:YY, Somebody wrote:
> This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
>> has to be careful with empty quoted lines because they might end with a
> space but still shouldn't be considered as flowed!
>
> The above empty line should persist after unfolding.
> xxxxxxxxxx. xxxx xxxxx xxxxx xxxx xx xx.xx. xxxxxx xxxxxxxxxxxx, xxxx xx
>
> ... and this one as well.
> > text
--
Sig

@ -0,0 +1,21 @@
I'm replying on this with a very long line which is then wrapped and
space-stuffed because the draft is saved as format=flowed.
From what's specified in RFC 2646 some lines need to be space-stuffed to avoid
muning during transport.
X
On XX.YY.YYYY Y:YY, Somebody wrote:
> This part is a reply wihtout any flowing lines. rcube_mime::unfold_flowed()
>> has to be careful with empty quoted lines because they might end with a
> space but still shouldn't be considered as flowed!
>
> The above empty line should persist after unfolding.
> xxxxxxxxxx. xxxx xxxxx xxxxx xxxx xx xx.xx. xxxxxx xxxxxxxxxxxx, xxxx xx
>
> ... and this one as well.
> > text
--
Sig

@ -0,0 +1,12 @@
<html>
<head>
<base href="http://alec.pl/dir/" />
</head>
<body>
<img src="img1.gif" />
<img src="./img2.gif" />
<img src="../img3.gif" />
<img src="cid:theCID" />
<img src="http://other.domain.tld/img3.gif" />
</body>
</html>

@ -0,0 +1,51 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=ISO-8859-1">
<title>Roundcube Test Message</title>
<link rel="stylesheet" type="text/css" href="http://anysite.net/styles/mail.css">
<style type="text/css">
p, a {
font-family: Arial, 'Bitstream Vera Sans', Helvetica;
margin-top: 0px;
margin-bottom: 0px;
padding-top: 0px;
padding-bottom: 0px;
}
</style>
</head>
<body style="margin: 0 0 0 0;">
<table width="100%" cellpadding="0" cellspacing="20" style="background-image:url(http://evilsite.net/newsletter/image/bg/bg-64.jpg);background-attachment:fixed;" background="http://evilsite.net/newsletter/image/bg/bg-64.jpg" border="0">
<tr>
<td>
<h1>This is a HTML message</h1>
<p>See nice pictures like the following:</p>
<div>
<img src="ex1.jpg" width="320" height="320" alt="Example 1">
<img src="ex2.jpg" width="320" height="320" alt="Example 2">
<img src="http://evilsite.net/mailings/ex3.jpg" width="320" height="320" alt="Example 3">
</div>
<form action="http://evilsite.net/subscribe.php">
<p>Subscription form</p>
E-Mail: <input type="text" name="mail" value=""><br/>
<input type="submit" value="Subscribe">
</form>
<p>To unsubscribe click here <a href="http://evilsite.net/unsubscribe.php?mail=foo@bar.com"> or
send a mail to <a href="mailto:unsubscribe@evilsite.net">unsubscribe@evilsite.net</a></p>
</td>
</tr>
</table>
</body>
</html>

@ -0,0 +1,16 @@
<html>
<head>
<title>Roundcube Test Message</title>
</head>
<body>
<!--REF>
<p>test1</p>
<!--DEREF>
<!--[if gte mso 9]><xml>
<p>test2</p>
</xml><![endif]-->
</body>
</html>

@ -0,0 +1,22 @@
<html>
<body>
<p><img onLoad.="alert(document.cookie)" src="skins/default/images/roundcube_logo.png" /></p>
<p><a href="mailto:xss@somehost.net') && alert(document.cookie) || ignore('">mail me!</a>
<a href="http://roundcube.net" target="_self">roundcube.net</a>
<a href="http://roundcube.net" \onmouseover="alert('XSS')">roundcube.net (2)</a>
</p>
<div>Brilliant!</div>
<table><tbody><tr><td background="javascript:alert('XSS')">BBBBBB</td></tr></tbody></table>
<p>
Have a nice Christmas time.<br />
Thomas
</p>
</body>
</html>

File diff suppressed because one or more lines are too long

@ -0,0 +1 @@
<p><EFBFBD>クミシミミイミセミサ</p>

@ -0,0 +1,12 @@
BEGIN:VCARD
VERSION:2.1
N;CHARSET=windows-1252:Doë;John;;;
FN;CHARSET=windows-1252:John Doë
ORG:roundcube.net;
EMAIL;INTERNET;WORK:inbox@roundcube.net
EMAIL;INTERNET;HOME;TYPE=pref:roundcube@gmail.com
TEL;WORK:+123456789
TEL;CELL:+987654321
ADR;WORK:;;The street;Hometown;;5555;Cayman Islands
NOTE:The notes...
END:VCARD

@ -0,0 +1,8 @@
<html>
<head></head>
<body>
<a href="mailto:me@me.com?subject=this is the subject&body=this is the body">e-mail</a>
</body>
</html>

@ -0,0 +1,22 @@
.ReadMsgBody{width: 100%;}
.ExternalClass{width: 100%;}
div, p, a, li, td { -webkit-text-size-adjust:none; }
@media (max-width: 450px){
table[class=w600], td[class=w600], table[class=w540], td[class=w540], img[class=w600]{ width:100% !important; }
table[class=w30], td[class=w30]{ width:20px !important; }
.pict img {max-width:260px; height:auto !important;}
}
@media (min-width: 450px) and (max-width: 600px){
table[class=w600], td[class=w600], table[class=w540], td[class=w540], img[class=w600]{ width:100% !important; }
table[class=w30], td[class=w30]{ width:20px !important; }
.pict img {max-width:410px; height:auto !important;}
}
@media (min-width:600px){
body {width:600px !important; margin:auto !important;}
.pict img {max-width:540px !important; height:auto !important;}
}
h1{ font-weight:bold; font-size:14px;color:#3c3c3c ;margin:0px; }
h2{ color:#8DB048 ; font-size:14px; font-weight:bold; margin-top:20px; border-bottom:1px solid #d6d6d6; padding-bottom:4px; }
h3{ color:#7e7e7e ; font-size:14px; font-weight:bold; margin:20px 0px 0px 0px; border-bottom:1px solid #d6d6d6; padding-bottom:0px 0px 4px 0px; }
h4{ color:#8DB048 ; font-size:12px; font-weight:bold; margin:0px; padding:0px; }
a:visited{cursor:pointer; color:#8DB048; text-decoration:none; border:none;}

@ -0,0 +1,45 @@
BEGIN:VCARD
VERSION:3.0
N:Müller;Jörg;;;
FN:Apple Computer AG
ORG:Apple Computer AG;
PHOTO;ENCODING=b:
/9j/4AAQSkZJRgABAQAAAQABAAD/7QAcUGhvdG9zaG9wIDMuMAA4QklNBAQAAAAAAAD/2wBDAAEB
AQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQH/2wBDAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEB
AQEBAQEBAQEBAQEBAQEBAQH/wAARCAAwADADAREAAhEBAxEB/8QAHwAAAQUBAQEBAQEAAAAAAAAA
AAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEI
I0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlq
c3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW
19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL
/8QAtREAAgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAVYnLR
ChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hpanN0dXZ3eHl6goOE
hYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPExcbHyMnK0tPU1dbX2Nna4uPk5ebn
6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwD+/igAoAKAPmH43ftT+CfgzqNt4bNjeeLvGV2IHXw7
pVxDbLZx3LBbdtU1GVLhbN7jIMFvHa3VzIpWRoY4mWQ9dDCTrrmuoQ/mavfvZXV7dW2jkr4ynQfL
Zzn1inZL1lZ6+ST87H0lp1zLe6fY3k9s1nNd2dtczWjv5j2ss8KSyWzybU3tA7mJn2JuKk7Vzgcr
Vm1e9m1fvrv8zqi+aKbVm0nbtdXt8i5SGFAHHeOfH3hH4b6DP4k8Z61a6JpUBCCW4LPNdTsCUtbK
1iD3F5dSYO2C3jd8AuwVFZhdOnOrLlhFyf4Lzb6IzqVYUo81SSiundvslu3/AEz5i0n9u74Fanqo
064m8UaNbvII49X1TRUGnnORvmFje3t5BGTjDtatwcyCPBrreArpX9xvqlJ3/FJP7zlWYUHKzVRL
+ZxVvnaTa+4+QLvVPgJ4U+LutfFXx78QJfi3q954iuvEOieHvBmkyzaVbO1x5ulPruq6pLawTvp1
uLdIrK08xFmgXzl2oI67LV50o0qdP2K5VGUptKXnyxi29XfVtb6HDehGtKpUm6zcnNKCfK9brnlK
3pZJ37pH3/8ACj9qb4T/ABd1FdD0TUr3SPETozwaJ4ht47C5vQgLONOnjnuLS8dVBYwJOt1tDMIN
oLV51XCVqK5pJSj1cW3b1uk1vvqvM9Kji6VZ8qbjJ7KVlf0abTf4n0dXMdQUAfhf+2J8UNW8ffFz
W9Cnlki0XwDqOp+GdNsFdhB9qsr6a31DUDHu2tcXbwojSEbhFCka4Uc+9hKUadGMl8VRKcn11V0v
RJng4urKpWkntTlKCXTRtN+re58n11HKFAH6PfsGfBvQfEl3rHxR8Q2y38vhrUrfT/DNpIT5FvqY
iF1carIgI8ye2R4Y7RXykbySTbS6xlfOx9aUVGlF2503N+W1vnrc9HAUYzlKrJX5GuVf3t7+dvu3
vc/WKvIPXCgD8FP2s/BF/wCC/jd4wlu0It/Fmp6h4usJf4JINZ1G7ndVbu0UpZZBztY446V9BhZq
dCnZ/DFQfrFJHz+Kg4V6l/tSc15qTb/rzPmqug5woA++v2J/j74d+HN9rHgLxndrpmjeJr62vtJ1
mbP2Sw1dY/s0ltfOM+Rb30Yh8u5ZTHFPEFlZEk3Dgx2HlVUZw1lBNOPVp9vNa6X22137sFiI0ZSh
N2jNpqXSLSe/k+/R+p+w1eMe0FAHxz+2P8DLr4r+CIPEPhy2Nx4y8FJdXVnaxrmfWdGlAk1DSosK
WkuozEt5p8fHmTLNADuuQR24KuqU3GTtCpbXtLo32T2b9GcWNw7qwU4q84X06yi9Wl531XfXyPxK
ME4nNsYZRciUwG3MbicTh/LMJix5glD/ACGPbv3/AC4zxXtniFvUNJ1XSmjXVNM1DTWmUvCuoWVz
ZtKgxloxcRxmRRkZZcgZGTzSTT2afo7hqtz6w/ZB+BV78UPHtl4n1eykHgfwdewajfXE0bCDVtVt
mE+n6PAzAJOBOkdxqAUssdsnlSDNwoPLi66pU3FP95NNJdk95P06d35XOvCUHWqJtfu4NOT7vdR8
7vfsvVH7gV4R7oUAFAHKReA/A8Gsy+IofBnhSHxBO7ST67F4d0iPWZnb7zy6mlmL2R2/iZ5yT3NX
7Spbl9pPl/l55W+69iPZUubm9nDmvfm5I81+97XuX9a8MeGvEtsLLxF4e0PX7MMGFprWk2Gq2wZe
jCC+t54tw7HZkdqUZzg7wlKL7xk4v700OUIT0lCMl2lFS/NMuaXpOlaHZQ6Zoumafo+nW4It9P0u
yttPsoATkiG1tI4oIgTyQkagnmk5Sk7ybk+7bb+96jjGMVaMVFdopJfcjQpDP//Z
X-ABShowAs:COMPANY
X-ABUID:2E4CB084-4767-4C85-BBCA-805B1DCB1C8E\:ABPerson
END:VCARD

@ -0,0 +1,38 @@
From: iPhone Developer Program <noreply-iphonedev@apple.com>
To: nobody@roundcube.net
*iPhone Developer Program*
-----------------------------------
iPhone SDK 2.2.1 is now available
https://daw.apple.com/cgi-bin/WebObjects/DSAuthWeb.woa/wa/login?appIdKey=3D=
D635F5C417E087A3B9864DAC5D25920C4E9442C9339FA9277951628F0291F620&path=3D//i=
phone/login.action
Log in to the iPhone Dev Center to download iPhone SDK for iPhone OS 2.2.1.=
Installation of iPhone SDK 2.2.1 is required for development with devices =
updated to iPhone OS 2.2.1. Please view the Read Me before installing the n=
ew version of the iPhone SDK.
Log in now
https://daw.apple.com/cgi-bin/WebObjects/DSAuthWeb.woa/wa/login?appIdKey=3D=
D635F5C417E087A3B9864DAC5D25920C4E9442C9339FA9277951628F0291F620&path=3D//i=
phone/login.action
-----------------------------------
Copyright (c) 2009 Apple Inc. 1 Infinite Loop, MS 303-3DM, Cupertino, CA 95=
014.
All Rights Reserved
http://www.apple.com/legal/default.html
Keep Informed
http://www.apple.com/enews/subscribe/
Privacy Policy
http://www.apple.com/legal/privacy.
My Info
https://myinfo.apple.com/cgi-bin/WebObjects/MyInfo
-[http://example.com/?tx[a]=5]-

@ -0,0 +1,8 @@
BEGIN:VCARD
VERSION:2.1
N;ENCODING=QUOTED-PRINTABLE:Iksi=F1ski;Piotr
FN;ENCODING=QUOTED-PRINTABLE:Piotr Iksi=F1ski
EMAIL;PREF;INTERNET:piotr.iksinski@somedomain.com
X-GENDER:Male
REV:20080716T203548Z
END:VCARD

Binary file not shown.

@ -0,0 +1,30 @@
/** Master style definitions **/
body, p, div, h1, h2, h3, textarea {
font-family: "Lucida Grande", Helvetica, sans-serif;
font-size: 8.8pt;
color: #333;
}
body {
background-color: white;
margin: 0;
}
h1 {
color: #1F519A;
font-size: 1.7em;
font-weight: normal;
margin-top: 0;
margin-bottom: 1em;
}
.noscript {
display: none;
}
.hint, .username {
color: #999;
}
Loading…
Cancel
Save