summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorthomascube <thomas@roundcube.net>2011-01-04 22:00:35 +0000
committerthomascube <thomas@roundcube.net>2011-01-04 22:00:35 +0000
commit6bdb6102c06c605d18f5d2cfba8ac806875ae13a (patch)
tree5ceffdfcf542f249d2d12c6354c8751d6daac1ac
parent636328483fb1e5e5f3abc10ce70e8f60a2a1f9e4 (diff)
Do charset detection in vcards with encoded values (#1485542)
-rw-r--r--CHANGELOG1
-rw-r--r--program/include/rcube_vcard.php32
-rw-r--r--tests/src/thebat.vcf8
-rw-r--r--tests/vcards.php4
4 files changed, 35 insertions, 10 deletions
diff --git a/CHANGELOG b/CHANGELOG
index 2e20b3ec6..17a6563f3 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -1,6 +1,7 @@
CHANGELOG Roundcube Webmail
===========================
+- Fix charset detection in vcards with encoded values (#1485542)
- Better CSS cursors for splitters (#1486874)
- Show the same message only once (#1487641)
- Fix namespaces handling (#1487649)
diff --git a/program/include/rcube_vcard.php b/program/include/rcube_vcard.php
index 9bbc32b3c..641d61e15 100644
--- a/program/include/rcube_vcard.php
+++ b/program/include/rcube_vcard.php
@@ -28,6 +28,7 @@
*/
class rcube_vcard
{
+ private static $values_decoded = false;
private $raw = array(
'FN' => array(),
'N' => array(array('','','','','')),
@@ -47,10 +48,10 @@ class rcube_vcard
/**
* Constructor
*/
- public function __construct($vcard = null, $charset = RCMAIL_CHARSET)
+ public function __construct($vcard = null, $charset = RCMAIL_CHARSET, $detect = false)
{
if (!empty($vcard))
- $this->load($vcard, $charset);
+ $this->load($vcard, $charset, $detect);
}
@@ -58,14 +59,23 @@ class rcube_vcard
* Load record from (internal, unfolded) vcard 3.0 format
*
* @param string vCard string to parse
+ * @param string Charset of string values
+ * @param boolean True if loading a 'foreign' vcard and extra heuristics for charset detection is required
*/
- public function load($vcard, $charset = RCMAIL_CHARSET)
+ public function load($vcard, $charset = RCMAIL_CHARSET, $detect = false)
{
+ self::$values_decoded = false;
$this->raw = self::vcard_decode($vcard);
-
+
// resolve charset parameters
- if ($charset == null)
- $this->raw = $this->charset_convert($this->raw);
+ if ($charset == null) {
+ $this->raw = self::charset_convert($this->raw);
+ }
+ // vcard has encoded values and charset should be detected
+ else if ($detect && self::$values_decoded &&
+ ($detected_charset = self::detect_encoding(self::vcard_encode($this->raw))) && $detected_charset != RCMAIL_CHARSET) {
+ $this->raw = self::charset_convert($this->raw, $detected_charset);
+ }
// find well-known address fields
$this->displayname = $this->raw['FN'][0][0];
@@ -171,13 +181,13 @@ class rcube_vcard
/**
* Convert a whole vcard (array) to UTF-8.
- * Each member value that has a charset parameter will be converted.
+ * If $force_charset is null, each member value that has a charset parameter will be converted
*/
- private function charset_convert($card)
+ private static function charset_convert($card, $force_charset = null)
{
foreach ($card as $key => $node) {
foreach ($node as $i => $subnode) {
- if (is_array($subnode) && $subnode['charset'] && ($charset = $subnode['charset'][0])) {
+ if (is_array($subnode) && (($charset = $force_charset) || ($subnode['charset'] && ($charset = $subnode['charset'][0])))) {
foreach ($subnode as $j => $value) {
if (is_numeric($j) && is_string($value))
$card[$key][$i][$j] = rcube_charset_convert($value, $charset);
@@ -222,7 +232,7 @@ class rcube_vcard
if (preg_match('/^END:VCARD$/i', $line)) {
// parse vcard
- $obj = new rcube_vcard(self::cleanup($vcard_block), $charset);
+ $obj = new rcube_vcard(self::cleanup($vcard_block), $charset, true);
if (!empty($obj->displayname))
$out[] = $obj;
@@ -363,9 +373,11 @@ class rcube_vcard
{
switch (strtolower($encoding)) {
case 'quoted-printable':
+ self::$values_decoded = true;
return quoted_printable_decode($value);
case 'base64':
+ self::$values_decoded = true;
return base64_decode($value);
default:
diff --git a/tests/src/thebat.vcf b/tests/src/thebat.vcf
new file mode 100644
index 000000000..8179f788d
--- /dev/null
+++ b/tests/src/thebat.vcf
@@ -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
diff --git a/tests/vcards.php b/tests/vcards.php
index 72c687484..3b8f260c4 100644
--- a/tests/vcards.php
+++ b/tests/vcards.php
@@ -48,6 +48,10 @@ class rcube_test_vcards extends UnitTestCase
$this->assertEqual(2, count($vcards), "Detected 2 vcards");
$this->assertEqual("Apple Computer AG", $vcards[0]->displayname, "FN => displayname");
$this->assertEqual("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->assertEqual("Iksiñski", $vcards2[0]->surname, "Detect charset in encoded values");
}
}