Thomas Bruederli
2014-08-18 3ebac0167bf20104fb7a2a55934765117760264c
program/lib/Roundcube/rcube_csv2vcard.php
@@ -47,7 +47,7 @@
        //'business_street_2'     => '',
        //'business_street_3'     => '',
        'car_phone'             => 'phone:car',
        'categories'            => 'categories',
        'categories'            => 'groups',
        //'children'              => '',
        'company'               => 'organization',
        //'company_main_phone'    => '',
@@ -56,7 +56,7 @@
        //'email_2_type'          => '',
        //'email_3_address'       => '', //@TODO
        //'email_3_type'          => '',
        'email_address'         => 'email:main',
        'email_address'         => 'email:pref',
        //'email_type'            => '',
        'first_name'            => 'firstname',
        'gender'                => 'gender',
@@ -124,6 +124,31 @@
        //'work_address_2'        => '',
        'work_country'          => 'country:work',
        'work_zipcode'          => 'zipcode:work',
        'last'                  => 'surname',
        'first'                 => 'firstname',
        'work_city'             => 'locality:work',
        'work_state'            => 'region:work',
        'home_city_short'       => 'locality:home',
        'home_state_short'      => 'region:home',
        // Atmail
        'date_of_birth'         => 'birthday',
        'email'                 => 'email:pref',
        'home_mobile'           => 'phone:cell',
        'home_zip'              => 'zipcode:home',
        'info'                  => 'notes',
        'user_photo'            => 'photo',
        'url'                   => 'website:homepage',
        'work_company'          => 'organization',
        'work_dept'             => 'departament',
        'work_fax'              => 'phone:work,fax',
        'work_mobile'           => 'phone:work,cell',
        'work_title'            => 'jobtitle',
        'work_zip'              => 'zipcode:work',
        'group'                 => 'groups',
        // GMail
        'groups'                => 'groups',
    );
    /**
@@ -224,8 +249,30 @@
        'work_phone'        => "Work Phone",
        'work_address'      => "Work Address",
        //'work_address_2'    => "Work Address 2",
        'work_city'         => "Work City",
        'work_country'      => "Work Country",
        'work_state'        => "Work State",
        'work_zipcode'      => "Work ZipCode",
        // Atmail
        'date_of_birth'     => "Date of Birth",
        'email'             => "Email",
        //'email_2'         => "Email2",
        //'email_3'         => "Email3",
        //'email_4'         => "Email4",
        //'email_5'         => "Email5",
        'home_mobile'       => "Home Mobile",
        'home_zip'          => "Home Zip",
        'info'              => "Info",
        'user_photo'        => "User Photo",
        'url'               => "URL",
        'work_company'      => "Work Company",
        'work_dept'         => "Work Dept",
        'work_fax'          => "Work Fax",
        'work_mobile'       => "Work Mobile",
        'work_title'        => "Work Title",
        'work_zip'          => "Work Zip",
        'groups'            => "Group",
    );
    protected $local_label_map = array();
@@ -262,7 +309,6 @@
    {
        // convert to UTF-8
        $head     = substr($csv, 0, 4096);
        $fallback = rcube::get_instance()->config->get('default_charset', 'ISO-8859-1'); // fallback to Latin-1?
        $charset  = rcube_charset::detect($head, RCUBE_CHARSET);
        $csv      = rcube_charset::convert($csv, $charset);
        $head     = '';
@@ -270,14 +316,8 @@
        $this->map = array();
        // Parse file
        foreach (preg_split("/[\r\n]+/", $csv) as $i => $line) {
            $line = trim($line);
            if (empty($line)) {
                continue;
            }
            $elements = rcube_utils::explode_quoted_string(',', $line);
        foreach (preg_split("/[\r\n]+/", $csv) as $line) {
            $elements = $this->parse_line($line);
            if (empty($elements)) {
                continue;
            }
@@ -305,6 +345,35 @@
    }
    /**
     * Parse CSV file line
     */
    protected function parse_line($line)
    {
        $line = trim($line);
        if (empty($line)) {
            return null;
        }
        $fields = rcube_utils::explode_quoted_string(',', $line);
        // remove quotes if needed
        if (!empty($fields)) {
            foreach ($fields as $idx => $value) {
                if (($len = strlen($value)) > 1 && $value[0] == '"' && $value[$len-1] == '"') {
                    // remove surrounding quotes
                    $value = substr($value, 1, -1);
                    // replace doubled quotes inside the string with single quote
                    $value = str_replace('""', '"', $value);
                    $fields[$idx] = $value;
                }
            }
        }
        return $fields;
    }
    /**
     * Parse CSV header line, detect fields mapping
     */
    protected function parse_header($elements)
@@ -324,6 +393,12 @@
        if (!empty($this->local_label_map)) {
            for ($i = 0; $i < $size; $i++) {
                $label = $this->local_label_map[$elements[$i]];
                // special localization label
                if ($label && $label[0] == '_') {
                    $label = substr($label, 1);
                }
                if ($label && !empty($this->csv2vcard_map[$label])) {
                    $map2[$i] = $this->csv2vcard_map[$label];
                }
@@ -355,9 +430,18 @@
            $contact['birthday'] = $contact['birthday-y'] .'-' .$contact['birthday-m'] . '-' . $contact['birthday-d'];
        }
        // categories/groups separator in vCard is ',' not ';'
        if (!empty($contact['groups'])) {
            $contact['groups'] = str_replace(';', ',', $contact['groups']);
        }
        // Empty dates, e.g. "0/0/00", "0000-00-00 00:00:00"
        foreach (array('birthday', 'anniversary') as $key) {
            if (!empty($contact[$key]) && $contact[$key] == '0/0/00') { // @TODO: localization?
                unset($contact[$key]);
            if (!empty($contact[$key])) {
                $date = preg_replace('/[0[:^word:]]/', '', $contact[$key]);
                if (empty($date)) {
                    unset($contact[$key]);
                }
            }
        }
@@ -367,6 +451,15 @@
            }
        }
        // Convert address(es) to rcube_vcard data
        foreach ($contact as $idx => $value) {
            $name = explode(':', $idx);
            if (in_array($name[0], array('street', 'locality', 'region', 'zipcode', 'country'))) {
                $contact['address:'.$name[1]][$name[0]] = $value;
                unset($contact[$idx]);
            }
        }
        // Create vcard object
        $vcard = new rcube_vcard();
        foreach ($contact as $name => $value) {