/**
  * Decode a contact as vCard version 3.0.
  * @param string $vCardString string holding the vCard text
  * @return Contact $contact already stored in database or NULL on error
  */
 function vCardImport($vCardString)
 {
     global $errorHandler;
     require_once 'lib/vcard/vcardclass.inc';
     $vc = new VCARD('3.0');
     $vc->setvCard($vCardString);
     if ($vc->lasterror_num != 0) {
         $errorHandler->error('import', $vc->lasterror_msg, basename($_SERVER['SCRIPT_NAME']));
         return null;
     }
     $data['contact']['lastname'] = $vc->getName('LAST');
     $data['contact']['firstname'] = $vc->getName('FIRST');
     $data['contact']['middlename'] = $vc->getName('MIDDLE');
     $data['contact']['namePrefix'] = $vc->getName('PREF');
     $data['contact']['nameSuffix'] = $vc->getName('SUFF');
     $data['contact']['nickname'] = $vc->getNickName();
     // ADDRESSES
     list($key, $a) = each($vc->getAdr('CITY', 'WORK', 'OR'));
     // this retrieval is strannnnge
     if ($a != null) {
         $data['address'][0]['type'] = 'work';
         list($key, $a) = each($vc->getAdr('STREET', 'WORK', 'OR'));
         $data['address'][0]['line1'] = $a;
         list($key, $a) = each($vc->getAdr('POBOX', 'WORK', 'OR'));
         $data['address'][0]['line2'] = $a;
         list($key, $a) = each($vc->getAdr('CITY', 'WORK', 'OR'));
         $data['address'][0]['city'] = $a;
         list($key, $a) = each($vc->getAdr('PROVINCE', 'WORK', 'OR'));
         $data['address'][0]['state'] = $a;
         list($key, $a) = each($vc->getAdr('POSTAL', 'WORK', 'OR'));
         $data['address'][0]['zip'] = $a;
         /*     list($key,$a) = each($vc->getAdr('COUNTRY','WORK','OR'));*/
         //$data['address'][0]['country'] = $a['COUNTRY']; // decode how?
     }
     list($key, $a) = each($vc->getAdr('CITY', 'HOME', 'OR'));
     if ($a != null) {
         $data['address'][1]['type'] = 'home';
         list($key, $a) = each($vc->getAdr('STREET', 'HOME', 'OR'));
         $data['address'][1]['line1'] = $a;
         list($key, $a) = each($vc->getAdr('POBOX', 'HOME', 'OR'));
         $data['address'][1]['line2'] = $a;
         list($key, $a) = each($vc->getAdr('CITY', 'HOME', 'OR'));
         $data['address'][1]['city'] = $a;
         list($key, $a) = each($vc->getAdr('PROVINCE', 'HOME', 'OR'));
         $data['address'][1]['state'] = $a;
         list($key, $a) = each($vc->getAdr('POSTAL', 'HOME', 'OR'));
         $data['address'][1]['zip'] = $a;
         /*     list($key,$a) = each($vc->getAdr('COUNTRY','HOME','OR'));*/
         //$data['address'][1]['country'] = $a['COUNTRY']; // decode how?
     }
     $i = 0;
     // other data email OR www OR other OR chat OR phone;
     // 5. TELECOMMUNICATIONS ADDRESSING TYPES methods:
     $x = $vc->getTel('WORK');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'work';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getTel('HOME');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'home';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getTel('CELL');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'cell';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getTel('FAX');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'fax';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getTel('PAGER');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'pager';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getTel('VIDEO');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'phone';
         $data['blank'][$i]['label'] = 'video';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     // delivers only one result!!
     list($key, $x) = each($vc->getEmail('INTERNET', 'OR'));
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'email';
         $data['blank'][$i]['label'] = '';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     // 7. ORGANIZATIONAL TYPES methods:
     $x = $vc->getTitle();
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'other';
         $data['blank'][$i]['label'] = 'Job Title';
         $data['blank'][$i]['value'] = $vc->getTitle();
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getRole();
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'other';
         $data['blank'][$i]['label'] = 'Role';
         $data['blank'][$i]['value'] = $vc->getRole();
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getOrg();
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'other';
         $data['blank'][$i]['label'] = 'Organization';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     // cannot go into OU of SSL_CA bacause may not be admin importer here
     $x = $vc->getOrg('ORGUNIT');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'other';
         $data['blank'][$i]['label'] = 'Organizational Unit';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     // what is ORGUNITS ???
     // 8. EXPLANATORY TYPES methods:
     $x = $vc->getUrl('WORK');
     $y = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'www';
         $data['blank'][$i]['label'] = 'Work';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     $x = $vc->getUrl('HOME');
     $x = ContactImportExport::vCardUnEscape($x);
     if (!empty($x)) {
         $data['blank'][$i]['type'] = 'www';
         $data['blank'][$i]['label'] = 'Home';
         $data['blank'][$i]['value'] = $x;
         $data['blank'][$i++]['visibility'] = 'visible';
     }
     //$data['contact']['notes'] = $vc->getNote();
     // Attach picture ...
     $url = $vc->getBinary('PHOTO', 'URL');
     if (!empty($url)) {
         $data['contact']['pictureURL'] = $url;
     }
     //import_change_encoding(&$data);
     // save it to the DB
     $contact = Contact::newContact();
     // curretly this must go before save! When we have the Media class it may need to go after save (?)
     $pic = $vc->getBinary('PHOTO', 'JPEG');
     if (!empty($pic) && $options->getOption('picAllowUpload')) {
         $binaryPicture = base64_decode($pic);
         //  future:  $contact->setMedia('pictureData');
         $contact->setMedia('pictureData', 'image/jpeg', $binaryPicture);
     }
     $contact->saveContactFromArray($data);
     $errorHandler->success('Imported: ' . $data['contact']['firstname'] . ' ' . $data['contact']['lastname'], basename($_SERVER['SCRIPT_NAME']));
     return $contact;
 }