/**
 * Returns TRUE on success FALSE on errors (contact NOT saved -> check errorHandler then)
 * SPECIAL: $post['URLtoMugshot'] is path / URL to mugshot (must be accessible by fopen PHP restrictions!).
 * The pic referenced by URLtoMugshot will be uploaded into the DB after resampling (shrinking).
 
   An address must have a refid or it will be added to the DB.
   Example Post: array(9) {
      ["contact"]=>
      array(12) {
        ["id"]=>
        string(1) "4"
        ["lastname"]=>
        string(5) "Lastname"
        ["firstname"]=>
        string(8) "Firstname"
        ["middlename"]=>
        string(0) ""
        ["namePrefix"]=>
        string(4) "Ing."
        ["nameSuffix"]=>
        string(0) ""
        ["nickname"]=>
        string(0) ""
        ["sex"]=>
        string(4) "male"
        ["pictureURL"]=>
        string(41) "/gallery/People/medium/w.jpg"
        ["notes"]=>
        string(0) ""
        ["xsltDisplayType"]=>
        string(9) "expertise"
        ["hidden"]=>
        string(1) "0"
      }
      ["address"]=>
      array(4) {
        [0]=>
        array(10) {
          ["refid"]=>
          string(1) "3"
          ["type"]=>
          string(16) "Employer Address"
          ["line1"]=>
          string(12) "Zich 8"
          ["line2"]=>
          string(0) ""
          ["city"]=>
          string(4) "Nashville"
          ["state"]=>
          string(0) ""
          ["zip"]=>
          string(6) "1010"
          ["phone1"]=>
          string(0) ""
          ["phone2"]=>
          string(0) ""
          ["country"]=>
          string(2) "de"
        }
        [1]=> ...
        [2]=> ...
        [3]=> ...
      }
      ["email"]=>
      array(1) {
        [0]=>
        array(4) {
          ["type"]=>
          string(5) "email"
          ["label"]=>
          string(4) "work"
          ["value"]=>
          string(25) "*****@*****.**"
          ["visibility"]=>
          string(7) "visible"
        }
      }
      ["phone"]=>
      array(3) {
        [0]=>
        array(4) {
          ["type"]=>
          string(5) "phone"
          ["label"]=>
          string(3) "fax"
          ["value"]=>
          string(13) "+12345"
          ["visibility"]=>
          string(7) "visible"
        }
        [1]=> ...
      }
      ["blank"]=> // new entries will be sorted into groups
      array(4) {
        [0]=>
        array(4) {
          ["type"]=>
          string(5) "email"
          ["label"]=>
          string(0) ""
          ["value"]=>
          string(0) ""
          ["visibility"]=>
          string(7) "visible"
        }
        [1]=> ...
      }
      ["www"]=>
      array(1) {
        [0]=>
        array(4) {
          ["type"]=>
          string(3) "www"
          ["label"]=>
          string(3) "www"
          ["value"]=>
          string(14) "www.example.com"
          ["visibility"]=>
          string(7) "visible"
        }
      }
      ["other"]=>
      array(7) {
        [0]=>
        array(4) {
          ["type"]=>
          string(5) "other"
          ["label"]=>
          string(16) "Company Position"
          ["value"]=>
          string(28) "Development"
          ["visibility"]=>
          string(7) "visible"
        }
        [1]=> ...
      }
      ["date"]=>
      array(4) {
        [0]=>
        array(5) {
          ["type"]=>
          string(6) "yearly"
          ["label"]=>
          string(13) "Date of Birth"
          ["value1"]=>
          string(10) "1956-07-28"
          ["value2"]=>
          string(0) ""
          ["visibility"]=>
          string(7) "visible"
        }
        [1]=> ...
      }
      ["newgroup"]=>
      string(0) ""
    }
 * @param array $post value groups array
 * @param boolean $adminsave true skips setting the whoModifiedFlag and modifiedDate to avoid 
 * being target for INCORRECT notifications and listing on recently changed list.
 * @global Options to determite whether to allow Upload or not
 * @global ErrorHandler
 */
 function saveContactFromArray(&$post, $adminsave = false)
 {
     global $options, $errorHandler;
     $data = $post['contact'];
     foreach ($data as $k => $v) {
         if ($k == 'pictureData') {
             // NEEDS TO BE REMOVED FOR VCARD IMPORT avoid post. Will be obsoleted by Media Class!!
             continue;
         }
         $this->contact[$k] = $v;
     }
     if ($options->getOption('picAllowUpload')) {
         if (isset($post['URLtoMugshot']) && $post['URLtoMugshot']) {
             $img = new ContactImage($this);
             $this->contact['pictureData'] = $img->resampleAndReturn($post['URLtoMugshot']);
         } elseif (isset($post['contact']['pictureData']['remove']) && $post['contact']['pictureData']['remove']) {
             $this->contact['pictureData'] = '';
         }
     }
     $addr = $post['address'];
     if (isset($post['address_primary'])) {
         $addr[intval($post['address_primary'])]['primary'] = true;
     }
     if (isset($post['address'])) {
         foreach ($addr as $k => $v) {
             $empty = true;
             foreach ($v as $d) {
                 if (!empty($d)) {
                     $empty = false;
                     break;
                 }
             }
             if ($empty) {
                 unset($addr[$k]);
             }
         }
         $this->setValueGroup('addresses', $addr);
     }
     $this->saveValueGroupsFromArray($post);
     if (isset($post['groups']) || isset($post['newgroup'])) {
         $valGroup = array();
         if (isset($post['groups'])) {
             foreach ($post['groups'] as $k => $v) {
                 if ($v == '1') {
                     $valGroup[]['groupname'] = $k;
                 }
             }
         }
         if (isset($post['newgroup']) && $post['newgroup']) {
             $valGroup[]['groupname'] = $post['newgroup'];
         }
         $this->setValueGroup('groups', $valGroup);
     }
     if ($errorHandler->getErrors('formVal') || $errorHandler->getErrors('image')) {
         return false;
     }
     $this->save(true, $adminsave);
     if ($errorHandler->getErrors('formVal') || $errorHandler->getErrors('image')) {
         return false;
     }
     return true;
 }
 /**
  * Encode a contact as XML to be rendered by a stylesheet
  * @todo Check if this exports private/admin hidden values only if allowed.
  * @param Contact $contact
  * @return string XML
  * @global $CONFIG_TAB_ROOT, $country
  */
 function xmlExport($contact)
 {
     global $CONFIG_TAB_ROOT, $country, $addressFormatter;
     $output = '<?xml version="1.0" encoding="utf-8" ?>' . "\n";
     $output .= "<contact>\n";
     $output .= "<id>" . $contact->contact['id'] . "</id>\n";
     $output .= '<fullname>' . htmlspecialchars($contact->contact['namePrefix'] . ' ' . $contact->contact['firstname'] . ' ' . $contact->contact['lastname'] . ' ' . $contact->contact['nameSuffix'], ENT_NOQUOTES, 'UTF-8') . "</fullname>\n";
     $output .= '<name><family>' . htmlspecialchars($contact->contact['lastname'], ENT_NOQUOTES, 'UTF-8') . '</family><given>' . htmlspecialchars($contact->contact['firstname'], ENT_NOQUOTES, 'UTF-8') . '</given><middlename>' . htmlspecialchars($contact->contact['middlename'], ENT_NOQUOTES, 'UTF-8') . '</middlename><prefix>' . htmlspecialchars($contact->contact['namePrefix'], ENT_NOQUOTES, 'UTF-8') . '</prefix><suffix>' . htmlspecialchars($contact->contact['nameSuffix'], ENT_NOQUOTES, 'UTF-8') . "</suffix></name>\n";
     if ($contact->contact['nickname']) {
         $output .= '<nickname>' . $contact->contact['nickname'] . "</nickname>\n";
     }
     //if($contact->contact['birthday'] != '0000-00-00') $output .= 'BDAY:' . ?? . "\n";
     $vg = $contact->getValueGroup('addresses');
     $output .= "<address-list>\n";
     foreach ($vg as $adr) {
         $output .= "<address>\n";
         $output .= "<dbid>" . $adr['refid'] . "</dbid>\n";
         $output .= "<type>" . htmlspecialchars($adr['type'], ENT_NOQUOTES, 'UTF-8') . "</type>\n";
         $output .= '<line1>' . htmlspecialchars($adr['line1'], ENT_NOQUOTES, 'UTF-8') . "</line1>\n";
         $output .= '<line2>' . htmlspecialchars($adr['line2'], ENT_NOQUOTES, 'UTF-8') . "</line2>\n";
         $output .= '<city>' . htmlspecialchars($adr['city'], ENT_NOQUOTES, 'UTF-8') . "</city>\n";
         $output .= '<zip>' . htmlspecialchars($adr['zip'], ENT_NOQUOTES, 'UTF-8') . "</zip>\n";
         $output .= '<state>' . htmlspecialchars($adr['city'], ENT_NOQUOTES, 'UTF-8') . "</state>\n";
         $output .= '<countrycode>' . htmlspecialchars($adr['country'], ENT_NOQUOTES, 'UTF-8') . "</countrycode>\n";
         $output .= '<formatted>' . $addressFormatter->formatAddress($adr) . '</formatted>';
         global $VALUE_GROUP_TYPES_ARRAY;
         foreach ($VALUE_GROUP_TYPES_ARRAY as $t) {
             $output .= "<{$t}-list>\n";
             $vg = $contact->getValueGroup($t, $adr['refid']);
             foreach ($vg as $v) {
                 if ($v['visibility'] != 'visible') {
                     continue;
                 }
                 if ($t != 'date') {
                     $output .= "<{$t}>" . '<label>' . htmlspecialchars($v['label'], ENT_NOQUOTES, 'UTF-8') . '</label><value>' . htmlspecialchars($v['value'], ENT_COMPAT, 'UTF-8') . "</value></{$t}>\n";
                 } else {
                     $output .= "<{$t}>" . '<label>' . htmlspecialchars($v['label'], ENT_NOQUOTES, 'UTF-8') . '</label><value1>' . htmlspecialchars($v['value1'], ENT_NOQUOTES, 'UTF-8') . '</value1><value2>' . htmlspecialchars($v['value2'], ENT_NOQUOTES, 'UTF-8') . '</value2><type>' . htmlspecialchars($v['type'], ENT_NOQUOTES, 'UTF-8') . "</type></{$t}>\n";
                 }
             }
             $output .= "</{$t}-list>\n\n";
         }
         $output .= "</address>\n";
     }
     $output .= "</address-list>\n\n";
     global $VALUE_GROUP_TYPES_ARRAY;
     foreach ($VALUE_GROUP_TYPES_ARRAY as $t) {
         $output .= "<{$t}-list>\n";
         $vg = $contact->getValueGroup($t, null);
         foreach ($vg as $v) {
             if ($v['visibility'] != 'visible') {
                 continue;
             }
             if ($t != 'date') {
                 $output .= "<{$t}>" . '<label>' . htmlspecialchars($v['label'], ENT_NOQUOTES, 'UTF-8') . '</label><value>' . htmlspecialchars($v['value'], ENT_COMPAT, 'UTF-8') . "</value></{$t}>\n";
             } else {
                 $output .= "<{$t}>" . '<label>' . htmlspecialchars($v['label'], ENT_NOQUOTES, 'UTF-8') . '</label><value1>' . htmlspecialchars($v['value1'], ENT_NOQUOTES, 'UTF-8') . '</value1><value2>' . htmlspecialchars($v['value2'], ENT_COMPAT, 'UTF-8') . '</value2><type>' . htmlspecialchars($v['type'], ENT_NOQUOTES, 'UTF-8') . "</type></{$t}>\n";
             }
         }
         $output .= "</{$t}-list>\n\n";
     }
     $ci = new ContactImage($contact);
     $output .= "<pictureURL>" . $ci->uri() . "</pictureURL>\n";
     $output .= "<notes>\n";
     $output .= $contact->contact['notes'];
     // htmlspecialchars does not work here!! (XML processing!)
     $output .= "</notes>\n";
     global $pluginManager;
     $output .= $pluginManager->xmlExport($contact);
     $output .= "</contact>\n";
     $output .= "\n";
     return $output;
 }