Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F4682954
rcube_csv2vcard.php
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
25 KB
Referenced Files
None
Subscribers
None
rcube_csv2vcard.php
View Options
<?php
/**
+-----------------------------------------------------------------------+
| This file is part of the Roundcube Webmail client |
| |
| Copyright (C) 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: |
| CSV to vCard data conversion |
+-----------------------------------------------------------------------+
| Author: Aleksander Machniak <alec@alec.pl> |
+-----------------------------------------------------------------------+
*/
/**
* CSV to vCard data converter
*
* @package Framework
* @subpackage Addressbook
*/
class
rcube_csv2vcard
{
/**
* CSV to vCard fields mapping
*
* @var array
*/
protected
$csv2vcard_map
=
array
(
// MS Outlook 2010
'anniversary'
=>
'anniversary'
,
'assistants_name'
=>
'assistant'
,
'assistants_phone'
=>
'phone:assistant'
,
'birthday'
=>
'birthday'
,
'business_city'
=>
'locality:work'
,
'business_countryregion'
=>
'country:work'
,
'business_fax'
=>
'phone:work,fax'
,
'business_phone'
=>
'phone:work'
,
'business_phone_2'
=>
'phone:work2'
,
'business_postal_code'
=>
'zipcode:work'
,
'business_state'
=>
'region:work'
,
'business_street'
=>
'street:work'
,
//'business_street_2' => '',
//'business_street_3' => '',
'car_phone'
=>
'phone:car'
,
'categories'
=>
'groups'
,
//'children' => '',
'company'
=>
'organization'
,
//'company_main_phone' => '',
'department'
=>
'department'
,
'email_2_address'
=>
'email:other'
,
//'email_2_type' => '',
'email_3_address'
=>
'email:other'
,
//'email_3_type' => '',
'email_address'
=>
'email:pref'
,
//'email_type' => '',
'first_name'
=>
'firstname'
,
'gender'
=>
'gender'
,
'home_city'
=>
'locality:home'
,
'home_countryregion'
=>
'country:home'
,
'home_fax'
=>
'phone:home,fax'
,
'home_phone'
=>
'phone:home'
,
'home_phone_2'
=>
'phone:home2'
,
'home_postal_code'
=>
'zipcode:home'
,
'home_state'
=>
'region:home'
,
'home_street'
=>
'street:home'
,
//'home_street_2' => '',
//'home_street_3' => '',
//'initials' => '',
//'isdn' => '',
'job_title'
=>
'jobtitle'
,
//'keywords' => '',
//'language' => '',
'last_name'
=>
'surname'
,
//'location' => '',
'managers_name'
=>
'manager'
,
'middle_name'
=>
'middlename'
,
//'mileage' => '',
'mobile_phone'
=>
'phone:cell'
,
'notes'
=>
'notes'
,
//'office_location' => '',
'other_city'
=>
'locality:other'
,
'other_countryregion'
=>
'country:other'
,
'other_fax'
=>
'phone:other,fax'
,
'other_phone'
=>
'phone:other'
,
'other_postal_code'
=>
'zipcode:other'
,
'other_state'
=>
'region:other'
,
'other_street'
=>
'street:other'
,
//'other_street_2' => '',
//'other_street_3' => '',
'pager'
=>
'phone:pager'
,
'primary_phone'
=>
'phone:pref'
,
//'profession' => '',
//'radio_phone' => '',
'spouse'
=>
'spouse'
,
'suffix'
=>
'suffix'
,
'title'
=>
'title'
,
'web_page'
=>
'website:homepage'
,
// Thunderbird
'birth_day'
=>
'birthday-d'
,
'birth_month'
=>
'birthday-m'
,
'birth_year'
=>
'birthday-y'
,
'display_name'
=>
'displayname'
,
'fax_number'
=>
'phone:fax'
,
'home_address'
=>
'street:home'
,
//'home_address_2' => '',
'home_country'
=>
'country:home'
,
'home_zipcode'
=>
'zipcode:home'
,
'mobile_number'
=>
'phone:cell'
,
'nickname'
=>
'nickname'
,
'organization'
=>
'organization'
,
'pager_number'
=>
'phone:pager'
,
'primary_email'
=>
'email:pref'
,
'secondary_email'
=>
'email:other'
,
'web_page_1'
=>
'website:homepage'
,
'web_page_2'
=>
'website:other'
,
'work_phone'
=>
'phone:work'
,
'work_address'
=>
'street:work'
,
//'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'
,
'group_membership'
=>
'groups'
,
'given_name'
=>
'firstname'
,
'additional_name'
=>
'middlename'
,
'family_name'
=>
'surname'
,
'name'
=>
'displayname'
,
'name_prefix'
=>
'prefix'
,
'name_suffix'
=>
'suffix'
,
// Format of Letter Hub test files from
// https://letterhub.com/sample-csv-file-with-contacts/
'company_name'
=>
'organization'
,
'address'
=>
'street:home'
,
'city'
=>
'locality:home'
,
//'county' => '',
'state'
=>
'region:home'
,
'zip'
=>
'zipcode:home'
,
'phone1'
=>
'phone:home'
,
'phone'
=>
'phone:work'
,
'email'
=>
'email:home'
,
);
/**
* CSV label to text mapping for English
*
* @var array
*/
protected
$label_map
=
array
(
// MS Outlook 2010
'anniversary'
=>
"Anniversary"
,
'assistants_name'
=>
"Assistant's Name"
,
'assistants_phone'
=>
"Assistant's Phone"
,
'birthday'
=>
"Birthday"
,
'business_city'
=>
"Business City"
,
'business_countryregion'
=>
"Business Country/Region"
,
'business_fax'
=>
"Business Fax"
,
'business_phone'
=>
"Business Phone"
,
'business_phone_2'
=>
"Business Phone 2"
,
'business_postal_code'
=>
"Business Postal Code"
,
'business_state'
=>
"Business State"
,
'business_street'
=>
"Business Street"
,
//'business_street_2' => "Business Street 2",
//'business_street_3' => "Business Street 3",
'car_phone'
=>
"Car Phone"
,
'categories'
=>
"Categories"
,
//'children' => "Children",
'company'
=>
"Company"
,
//'company_main_phone' => "Company Main Phone",
'department'
=>
"Department"
,
//'directory_server' => "Directory Server",
'email_2_address'
=>
"E-mail 2 Address"
,
//'email_2_type' => "E-mail 2 Type",
'email_3_address'
=>
"E-mail 3 Address"
,
//'email_3_type' => "E-mail 3 Type",
'email_address'
=>
"E-mail Address"
,
//'email_type' => "E-mail Type",
'first_name'
=>
"First Name"
,
'gender'
=>
"Gender"
,
'home_city'
=>
"Home City"
,
'home_countryregion'
=>
"Home Country/Region"
,
'home_fax'
=>
"Home Fax"
,
'home_phone'
=>
"Home Phone"
,
'home_phone_2'
=>
"Home Phone 2"
,
'home_postal_code'
=>
"Home Postal Code"
,
'home_state'
=>
"Home State"
,
'home_street'
=>
"Home Street"
,
//'home_street_2' => "Home Street 2",
//'home_street_3' => "Home Street 3",
//'initials' => "Initials",
//'isdn' => "ISDN",
'job_title'
=>
"Job Title"
,
//'keywords' => "Keywords",
//'language' => "Language",
'last_name'
=>
"Last Name"
,
//'location' => "Location",
'managers_name'
=>
"Manager's Name"
,
'middle_name'
=>
"Middle Name"
,
//'mileage' => "Mileage",
'mobile_phone'
=>
"Mobile Phone"
,
'notes'
=>
"Notes"
,
//'office_location' => "Office Location",
'other_city'
=>
"Other City"
,
'other_countryregion'
=>
"Other Country/Region"
,
'other_fax'
=>
"Other Fax"
,
'other_phone'
=>
"Other Phone"
,
'other_postal_code'
=>
"Other Postal Code"
,
'other_state'
=>
"Other State"
,
'other_street'
=>
"Other Street"
,
//'other_street_2' => "Other Street 2",
//'other_street_3' => "Other Street 3",
'pager'
=>
"Pager"
,
'primary_phone'
=>
"Primary Phone"
,
//'profession' => "Profession",
//'radio_phone' => "Radio Phone",
'spouse'
=>
"Spouse"
,
'suffix'
=>
"Suffix"
,
'title'
=>
"Title"
,
'web_page'
=>
"Web Page"
,
// Thunderbird
'birth_day'
=>
"Birth Day"
,
'birth_month'
=>
"Birth Month"
,
'birth_year'
=>
"Birth Year"
,
'display_name'
=>
"Display Name"
,
'fax_number'
=>
"Fax Number"
,
'home_address'
=>
"Home Address"
,
//'home_address_2' => "Home Address 2",
'home_country'
=>
"Home Country"
,
'home_zipcode'
=>
"Home ZipCode"
,
'mobile_number'
=>
"Mobile Number"
,
'nickname'
=>
"Nickname"
,
'organization'
=>
"Organization"
,
'pager_number'
=>
"Pager Namber"
,
'primary_email'
=>
"Primary Email"
,
'secondary_email'
=>
"Secondary Email"
,
'web_page_1'
=>
"Web Page 1"
,
'web_page_2'
=>
"Web Page 2"
,
'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"
,
'group'
=>
"Group"
,
// GMail
'groups'
=>
"Groups"
,
'group_membership'
=>
"Group Membership"
,
'given_name'
=>
"Given Name"
,
'additional_name'
=>
"Additional Name"
,
'family_name'
=>
"Family Name"
,
'name'
=>
"Name"
,
'name_prefix'
=>
"Name Prefix"
,
'name_suffix'
=>
"Name Suffix"
,
);
/**
* Special fields map for GMail format
*
* @var array
*/
protected
$gmail_label_map
=
array
(
'E-mail'
=>
array
(
'Value'
=>
array
(
'home'
=>
'email:home'
,
'work'
=>
'email:work'
,
'*'
=>
'email:other'
,
),
),
'Phone'
=>
array
(
'Value'
=>
array
(
'home'
=>
'phone:home'
,
'homefax'
=>
'phone:homefax'
,
'main'
=>
'phone:pref'
,
'pager'
=>
'phone:pager'
,
'mobile'
=>
'phone:cell'
,
'work'
=>
'phone:work'
,
'workfax'
=>
'phone:workfax'
,
),
),
'Relation'
=>
array
(
'Value'
=>
array
(
'spouse'
=>
'spouse'
,
),
),
'Website'
=>
array
(
'Value'
=>
array
(
'profile'
=>
'website:profile'
,
'blog'
=>
'website:blog'
,
'homepage'
=>
'website:homepage'
,
'work'
=>
'website:work'
,
),
),
'Address'
=>
array
(
'Street'
=>
array
(
'home'
=>
'street:home'
,
'work'
=>
'street:work'
,
),
'City'
=>
array
(
'home'
=>
'locality:home'
,
'work'
=>
'locality:work'
,
),
'Region'
=>
array
(
'home'
=>
'region:home'
,
'work'
=>
'region:work'
,
),
'Postal Code'
=>
array
(
'home'
=>
'zipcode:home'
,
'work'
=>
'zipcode:work'
,
),
'Country'
=>
array
(
'home'
=>
'country:home'
,
'work'
=>
'country:work'
,
),
),
'Organization'
=>
array
(
'Name'
=>
array
(
''
=>
'organization'
,
),
'Title'
=>
array
(
''
=>
'jobtitle'
,
),
'Department'
=>
array
(
''
=>
'department'
,
),
),
);
protected
$local_label_map
=
array
();
protected
$vcards
=
array
();
protected
$map
=
array
();
protected
$gmail_map
=
array
();
/**
* Class constructor
*
* @param string $lang File language
*/
public
function
__construct
(
$lang
=
'en_US'
)
{
// Localize fields map
if
(
$lang
&&
$lang
!=
'en_US'
)
{
if
(
file_exists
(
RCUBE_LOCALIZATION_DIR
.
"$lang/csv2vcard.inc"
))
{
include
RCUBE_LOCALIZATION_DIR
.
"$lang/csv2vcard.inc"
;
}
if
(!
empty
(
$map
))
{
$this
->
local_label_map
=
array_merge
(
$this
->
label_map
,
$map
);
}
}
$this
->
label_map
=
array_flip
(
$this
->
label_map
);
$this
->
local_label_map
=
array_flip
(
$this
->
local_label_map
);
}
/**
* Import contacts from CSV file
*
* @param string $csv Content of the CSV file
*/
public
function
import
(
$csv
)
{
// convert to UTF-8
$head
=
substr
(
$csv
,
0
,
4096
);
$charset
=
rcube_charset
::
detect
(
$head
,
RCUBE_CHARSET
);
$csv
=
rcube_charset
::
convert
(
$csv
,
$charset
);
$csv
=
preg_replace
(
array
(
'/^[
\x
FE
\x
FF]{2}/'
,
'/^
\x
EF
\x
BB
\x
BF/'
,
'/^
\x
00+/'
),
''
,
$csv
);
// also remove BOM
$head
=
''
;
$prev_line
=
false
;
$this
->
map
=
array
();
$this
->
gmail_map
=
array
();
// Parse file
foreach
(
preg_split
(
"/[
\r\n
]+/"
,
$csv
)
as
$line
)
{
if
(!
empty
(
$prev_line
))
{
$line
=
'"'
.
$line
;
}
$elements
=
$this
->
parse_line
(
$line
);
if
(
empty
(
$elements
))
{
continue
;
}
// Parse header
if
(
empty
(
$this
->
map
))
{
$this
->
parse_header
(
$elements
);
if
(
empty
(
$this
->
map
))
{
break
;
}
}
// Parse data row
else
{
// handle multiline elements (e.g. Gmail)
if
(!
empty
(
$prev_line
))
{
$first
=
array_shift
(
$elements
);
if
(
$first
[
0
]
==
'"'
)
{
$prev_line
[
count
(
$prev_line
)-
1
]
=
'"'
.
$prev_line
[
count
(
$prev_line
)-
1
]
.
"
\n
"
.
substr
(
$first
,
1
);
}
else
{
$prev_line
[
count
(
$prev_line
)-
1
]
.=
"
\n
"
.
$first
;
}
$elements
=
array_merge
(
$prev_line
,
$elements
);
}
$last_element
=
$elements
[
count
(
$elements
)-
1
];
if
(
$last_element
[
0
]
==
'"'
)
{
$elements
[
count
(
$elements
)-
1
]
=
substr
(
$last_element
,
1
);
$prev_line
=
$elements
;
continue
;
}
$this
->
csv_to_vcard
(
$elements
);
$prev_line
=
false
;
}
}
}
/**
* Export vCards
*
* @return array rcube_vcard List of vcards
*/
public
function
export
()
{
return
$this
->
vcards
;
}
/**
* Parse CSV file line
*
* @param string $line Line of text from CSV file
*
* @return array CSV data extracted from the 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
*
* @param array $elements Array of field names from a first line in CSV file
*/
protected
function
parse_header
(
$elements
)
{
$map1
=
array
();
$map2
=
array
();
$size
=
count
(
$elements
);
// check English labels
for
(
$i
=
0
;
$i
<
$size
;
$i
++)
{
$label
=
$this
->
label_map
[
$elements
[
$i
]];
if
(
$label
&&
!
empty
(
$this
->
csv2vcard_map
[
$label
]))
{
$map1
[
$i
]
=
$this
->
csv2vcard_map
[
$label
];
}
}
// check localized labels
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
];
}
}
}
// If nothing recognized fallback to simple non-localized labels
if
(
empty
(
$map1
)
&&
empty
(
$map2
))
{
for
(
$i
=
0
;
$i
<
$size
;
$i
++)
{
$label
=
str_replace
(
' '
,
'_'
,
strtolower
(
$elements
[
$i
]));
if
(!
empty
(
$this
->
csv2vcard_map
[
$label
]))
{
$map1
[
$i
]
=
$this
->
csv2vcard_map
[
$label
];
}
}
}
$this
->
map
=
count
(
$map1
)
>=
count
(
$map2
)
?
$map1
:
$map2
;
// support special Gmail format
foreach
(
$this
->
gmail_label_map
as
$key
=>
$items
)
{
$num
=
1
;
while
((
$_key
=
"$key $num - Type"
)
&&
(
$found
=
array_search
(
$_key
,
$elements
))
!==
false
)
{
$this
->
gmail_map
[
"$key:$num"
]
=
array
(
'_key'
=>
$key
,
'_idx'
=>
$found
);
foreach
(
array_keys
(
$items
)
as
$item_key
)
{
$_key
=
"$key $num - $item_key"
;
if
((
$found
=
array_search
(
$_key
,
$elements
))
!==
false
)
{
$this
->
gmail_map
[
"$key:$num"
][
$item_key
]
=
$found
;
}
}
$num
++;
}
}
}
/**
* Convert CSV data row to vCard
*
* @param array $data CSV data array
*/
protected
function
csv_to_vcard
(
$data
)
{
$contact
=
array
();
foreach
(
$this
->
map
as
$idx
=>
$name
)
{
$value
=
$data
[
$idx
];
if
(
$value
!==
null
&&
$value
!==
''
)
{
if
(!
empty
(
$contact
[
$name
]))
{
$contact
[
$name
]
=
(
array
)
$contact
[
$name
];
$contact
[
$name
][]
=
$value
;
}
else
{
$contact
[
$name
]
=
$value
;
}
}
}
// Gmail format support
foreach
(
$this
->
gmail_map
as
$idx
=>
$item
)
{
$type
=
preg_replace
(
'/[^a-z]/'
,
''
,
strtolower
(
$data
[
$item
[
'_idx'
]]));
$key
=
$item
[
'_key'
];
unset
(
$item
[
'_idx'
]);
unset
(
$item
[
'_key'
]);
foreach
(
$item
as
$item_key
=>
$item_idx
)
{
$value
=
$data
[
$item_idx
];
if
(
$value
!==
null
&&
$value
!==
''
)
{
foreach
(
array
(
$type
,
'*'
)
as
$_type
)
{
if
(
$data_idx
=
$this
->
gmail_label_map
[
$key
][
$item_key
][
$_type
])
{
$value
=
explode
(
' ::: '
,
$value
);
if
(!
empty
(
$contact
[
$data_idx
]))
{
$contact
[
$data_idx
]
=
array_merge
((
array
)
$contact
[
$data_idx
],
$value
);
}
else
{
$contact
[
$data_idx
]
=
$value
;
}
break
;
}
}
}
}
}
if
(
empty
(
$contact
))
{
return
;
}
// Handle special values
if
(!
empty
(
$contact
[
'birthday-d'
])
&&
!
empty
(
$contact
[
'birthday-m'
])
&&
!
empty
(
$contact
[
'birthday-y'
]))
{
$contact
[
'birthday'
]
=
$contact
[
'birthday-y'
]
.
'-'
.
$contact
[
'birthday-m'
]
.
'-'
.
$contact
[
'birthday-d'
];
}
if
(!
empty
(
$contact
[
'groups'
]))
{
// categories/groups separator in vCard is ',' not ';'
$contact
[
'groups'
]
=
str_replace
(
','
,
''
,
$contact
[
'groups'
]);
$contact
[
'groups'
]
=
str_replace
(
';'
,
','
,
$contact
[
'groups'
]);
if
(!
empty
(
$this
->
gmail_map
))
{
// remove "* " added by GMail
$contact
[
'groups'
]
=
str_replace
(
'* '
,
''
,
$contact
[
'groups'
]);
// replace strange delimiter
$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
]))
{
$date
=
preg_replace
(
'/[0[:^word:]]/'
,
''
,
$contact
[
$key
]);
if
(
empty
(
$date
))
{
unset
(
$contact
[
$key
]);
}
}
}
if
(!
empty
(
$contact
[
'gender'
])
&&
(
$gender
=
strtolower
(
$contact
[
'gender'
])))
{
if
(!
in_array
(
$gender
,
array
(
'male'
,
'female'
)))
{
unset
(
$contact
[
'gender'
]);
}
}
// 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
)
{
$name
=
explode
(
':'
,
$name
);
if
(
is_array
(
$value
)
&&
$name
[
0
]
!=
'address'
)
{
foreach
((
array
)
$value
as
$val
)
{
$vcard
->
set
(
$name
[
0
],
$val
,
$name
[
1
]);
}
}
else
{
$vcard
->
set
(
$name
[
0
],
$value
,
$name
[
1
]);
}
}
// add to the list
$this
->
vcards
[]
=
$vcard
;
}
}
File Metadata
Details
Attached
Mime Type
text/x-php
Expires
Fri, May 1, 2:14 PM (1 d, 21 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
609489
Default Alt Text
rcube_csv2vcard.php (25 KB)
Attached To
Mode
R3 roundcubemail
Attached
Detach File
Event Timeline
Log In to Comment