thomascube
2011-01-12 f5e7b353079f182d6d57e05b37e1eeb32872bc1a
program/include/rcube_vcard.php
@@ -4,8 +4,8 @@
 +-----------------------------------------------------------------------+
 | program/include/rcube_vcard.php                                       |
 |                                                                       |
 | This file is part of the RoundCube Webmail client                     |
 | Copyright (C) 2008-2009, RoundCube Dev. - Switzerland                 |
 | This file is part of the Roundcube Webmail client                     |
 | Copyright (C) 2008-2009, The Roundcube Dev Team                       |
 | Licensed under the GNU GPL                                            |
 |                                                                       |
 | PURPOSE:                                                              |
@@ -28,6 +28,7 @@
 */
class rcube_vcard
{
  private static $values_decoded = false;
  private $raw = array(
    'FN' => array(),
    'N' => array(array('','','','','')),
@@ -47,10 +48,10 @@
  /**
   * 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 @@
   * 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];
@@ -85,6 +95,13 @@
      $tmp = $this->email[0];
      $this->email[0] = $this->email[$pref_index];
      $this->email[$pref_index] = $tmp;
    }
    // make sure displayname is not empty (required by RFC2426)
    if (!strlen($this->displayname)) {
      // the same method is used in steps/mail/addcontact.inc
      $this->displayname = ucfirst(preg_replace('/[\.\-]/', ' ',
        substr($this->email[0], 0, strpos($this->email[0], '@'))));
    }
  }
@@ -164,13 +181,13 @@
  
  /**
   * 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);
@@ -211,15 +228,17 @@
      if ($in_vcard_block && !empty($line))
        $vcard_block .= $line . "\n";
      if (trim($line) == 'END:VCARD') {
      $line = trim($line);
      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;
        $in_vcard_block = false;
      }
      else if (trim($line) == 'BEGIN:VCARD') {
      else if (preg_match('/^BEGIN:VCARD$/i', $line)) {
        $vcard_block = $line . "\n";
        $in_vcard_block = true;
      }
@@ -354,9 +373,11 @@
  {
    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: