diff --git a/Example3.0.vcf b/Example3.0.vcf index 7715b21..d0ee600 100644 --- a/Example3.0.vcf +++ b/Example3.0.vcf @@ -8,7 +8,8 @@ PHOTO;VALUE=URL;TYPE=GIF:http://upload.wikimedia.org/wikipedia/commons/thumb/a/a TEL;TYPE=WORK,VOICE:(111) 555-1212 TEL;TYPE=HOME,VOICE:(404) 555-1212 TEL;TYPE=HOME,TYPE=VOICE:(404) 555-1213 -ADR;TYPE=WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America +ADR;TYPE=WORK:;extended;street 1;city;state;zip;country +ADR;TYPE=WORK:;appartement 1;100 Waters Edge;Baytown;LA;30314;United States of America LABEL;TYPE=WORK:100 Waters Edge\nBaytown, LA 30314\nUnited States of America ADR;TYPE=HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America LABEL;TYPE=HOME:42 Plantation St.\nBaytown, LA 30314\nUnited States of America @@ -33,4 +34,4 @@ AGENT:BEGIN:VCARD REV:20080424T195243Z END:VCARD REV:20080424T195243Z -END:VCARD \ No newline at end of file +END:VCARD diff --git a/test.php b/test.php index 7b2ae9b..71015e6 100644 --- a/test.php +++ b/test.php @@ -1,4 +1,4 @@ - + @@ -40,13 +40,13 @@ function OutputvCard(vCard $vCard) { foreach ($vCard -> PHOTO as $Photo) { - if ($Photo['Encoding'] == 'b') + if ($Photo['encoding'] == 'b') { - echo '
'; + echo '
'; } else { - echo '
'; + echo '
'; } /* @@ -69,14 +69,14 @@ function OutputvCard(vCard $vCard) foreach ($vCard -> N as $Name) { - echo '

Name: '.$Name['FirstName'].' '.$Name['LastName'].'

'; + echo '

Name: '.$Name['firstname'].' '.$Name['lastname'].'

'; } foreach ($vCard -> ORG as $Organization) { - echo '

Organization: '.$Organization['Name']. - ($Organization['Unit1'] || $Organization['Unit2'] ? - ' ('.implode(', ', array($Organization['Unit1'], $Organization['Unit2'])).')' : + echo '

Organization: '.$Organization['name']. + ($Organization['unit1'] || $Organization['unit2'] ? + ' ('.implode(', ', array($Organization['unit1'], $Organization['unit2'])).')' : '' ).'

'; } @@ -92,7 +92,7 @@ function OutputvCard(vCard $vCard) } else { - echo $Tel['Value'].' ('.implode(', ', $Tel['Type']).')
'; + echo $Tel['value'].' ('.implode(', ', $Tel['type']).')
'; } } echo '

'; @@ -109,7 +109,7 @@ function OutputvCard(vCard $vCard) } else { - echo $Email['Value'].' ('.implode(', ', $Email['Type']).')
'; + echo $Email['value'].' ('.implode(', ', $Email['type']).')
'; } } echo '

'; @@ -126,7 +126,7 @@ function OutputvCard(vCard $vCard) } else { - echo $URL['Value'].'
'; + echo $URL['value'].'
'; } } echo '

'; @@ -143,7 +143,7 @@ function OutputvCard(vCard $vCard) } else { - echo $IMPP['Value'].'
'; + echo $IMPP['value'].'
'; } } echo '

'; @@ -153,14 +153,14 @@ function OutputvCard(vCard $vCard) { foreach ($vCard -> ADR as $Address) { - echo '

Address ('.implode(', ', $Address['Type']).')

'; - echo 'Street address: '.($Address['StreetAddress'] ? $Address['StreetAddress'] : '-').'
'. - 'PO Box: '.($Address['POBox'] ? $Address['POBox'] : '-').'
'. - 'Extended address: '.($Address['ExtendedAddress'] ? $Address['ExtendedAddress'] : '-').'
'. - 'Locality: '.($Address['Locality'] ? $Address['Locality'] : '-').'
'. - 'Region: '.($Address['Region'] ? $Address['Region'] : '-').'
'. - 'ZIP/Post code: '.($Address['PostalCode'] ? $Address['PostalCode'] : '-').'
'. - 'Country: '.($Address['Country'] ? $Address['Country'] : '-').''; + echo '

Address ('.implode(', ', $Address['type']).')

'; + echo 'Street address: '.($Address['streetaddress'] ? $Address['streetaddress'] : '-').'
'. + 'PO Box: '.($Address['pobox'] ? $Address['pobox'] : '-').'
'. + 'Extended address: '.($Address['extendedaddress'] ? $Address['extendedaddress'] : '-').'
'. + 'Locality: '.($Address['locality'] ? $Address['locality'] : '-').'
'. + 'Region: '.($Address['region'] ? $Address['region'] : '-').'
'. + 'ZIP/Post code: '.($Address['postalcode'] ? $Address['postalcode'] : '-').'
'. + 'Country: '.($Address['country'] ? $Address['country'] : '-').''; } echo '

'; } @@ -213,4 +213,4 @@ function OutputvCard(vCard $vCard) } ?> - \ No newline at end of file + diff --git a/test2.php b/test2.php new file mode 100644 index 0000000..0169cc5 --- /dev/null +++ b/test2.php @@ -0,0 +1,12 @@ +getKeyList(); +foreach($keylist as $key => $val) +{ + printf("Properties:%s\n",$val); + print_r($vCard->$val); +} diff --git a/vCard.php b/vCard.php index b2f0476..ac90779 100644 --- a/vCard.php +++ b/vCard.php @@ -5,7 +5,7 @@ * @link https://github.com/nuovo/vCard-parser * @author Martins Pilsetnieks, Roberts Bruveris * @see RFC 2426, RFC 2425 - * @version 0.4.8 + * @version 0.4.9 */ class vCard implements Countable, Iterator { @@ -41,15 +41,15 @@ class vCard implements Countable, Iterator * @static Parts of structured elements according to the spec. */ private static $Spec_StructuredElements = array( - 'n' => array('LastName', 'FirstName', 'AdditionalNames', 'Prefixes', 'Suffixes'), - 'adr' => array('POBox', 'ExtendedAddress', 'StreetAddress', 'Locality', 'Region', 'PostalCode', 'Country'), - 'geo' => array('Latitude', 'Longitude'), - 'org' => array('Name', 'Unit1', 'Unit2') + 'n' => array('lastname', 'firstname', 'additionalnames', 'prefixes', 'suffixes'), + 'adr' => array('pobox', 'extendedaddress', 'streetaddress', 'locality', 'region', 'postalcode', 'country'), + 'geo' => array('latitude', 'longitude'), + 'org' => array('name', 'unit1', 'unit2') ); private static $Spec_MultipleValueElements = array('nickname', 'categories'); private static $Spec_ElementTypes = array( - 'email' => array('internet', 'x400', 'pref'), + 'email' => array('internet', 'x400', 'pref', 'home', 'work'), 'adr' => array('dom', 'intl', 'postal', 'parcel', 'home', 'work', 'pref'), 'label' => array('dom', 'intl', 'postal', 'parcel', 'home', 'work', 'pref'), 'tel' => array('home', 'msg', 'work', 'pref', 'voice', 'fax', 'cell', 'video', 'pager', 'bbs', 'modem', 'car', 'isdn', 'pcs'), @@ -120,21 +120,26 @@ public function __construct($Path = false, $RawData = false, array $Options = nu $this -> Mode = $vCardBeginCount == 1 ? vCard::MODE_SINGLE : vCard::MODE_MULTIPLE; // Removing/changing inappropriate newlines, i.e., all CRs or multiple newlines are changed to a single newline - $this -> RawData = str_replace("\r", "\n", $this -> RawData); - $this -> RawData = preg_replace('{(\n+)}', "\n", $this -> RawData); + + // MCA: removed, this break crlf vcard specification, all line dilimiter are CRLF + //$this -> RawData = str_replace("\r", "\n", $this -> RawData); + //$this -> RawData = preg_replace('{(\n)+}', "\n", $this -> RawData); // In multiple card mode the raw text is split at card beginning markers and each // fragment is parsed in a separate vCard object. if ($this -> Mode == self::MODE_MULTIPLE) { - $this -> RawData = explode('BEGIN:VCARD', $this -> RawData); + //Cannot use "explode", because we need to ignore, for example, 'AGENT:BEGIN:VCARD' + $this -> RawData = preg_split('{^BEGIN\:VCARD}miS', $this -> RawData); $this -> RawData = array_filter($this -> RawData); foreach ($this -> RawData as $SinglevCardRawData) { + // mca: remove \n and \r at start + //$SinglevCardRawData=ltrim($SinglevCardRawData); // Prepending "BEGIN:VCARD" to the raw string because we exploded on that one. // If there won't be the BEGIN marker in the new object, it will fail. - $SinglevCardRawData = 'BEGIN:VCARD'."\n".$SinglevCardRawData; + $SinglevCardRawData = 'BEGIN:VCARD'.$SinglevCardRawData; $ClassName = get_class($this); $this -> Data[] = new $ClassName(false, $SinglevCardRawData); @@ -142,20 +147,20 @@ public function __construct($Path = false, $RawData = false, array $Options = nu } else { - // Protect the BASE64 final = sign (detected by the line beginning with whitespace), otherwise the next replace will get rid of it - $this -> RawData = preg_replace('{(\n\s.+)=(\n)}', '$1-base64=-$2', $this -> RawData); - // Joining multiple lines that are split with a hard wrap and indicated by an equals sign at the end of line // (quoted-printable-encoded values in v2.1 vCards) - $this -> RawData = str_replace("=\n", '', $this -> RawData); + $this -> RawData = str_replace("=\r\n", '', $this -> RawData); + + // Protect the BASE64 final = sign (detected by the line beginning with whitespace), otherwise the next replace will get rid of it + $this -> RawData = preg_replace('{(\r\n\s.+)=(\r\n)}', '$1-base64=-$2', $this -> RawData); // Joining multiple lines that are split with a soft wrap (space or tab on the beginning of the next line - $this -> RawData = str_replace(array("\n ", "\n\t"), '-wrap-', $this -> RawData); + $this -> RawData = str_replace(array("\r\n ", "\r\n\t"), '-wrap-', $this -> RawData); // Restoring the BASE64 final equals sign (see a few lines above) - $this -> RawData = str_replace("-base64=-\n", "=\n", $this -> RawData); + $this -> RawData = str_replace("-base64=-\r\n", "=\r\n", $this -> RawData); - $Lines = explode("\n", $this -> RawData); + $Lines = explode("\r\n", $this -> RawData); foreach ($Lines as $Line) { @@ -211,6 +216,7 @@ public function __construct($Path = false, $RawData = false, array $Options = nu $ItemIndex = (int)str_ireplace('item', '', $TmpKey[0]); } + if (count($KeyParts) > 1) { $Parameters = self::ParseParameters($Key, array_slice($KeyParts, 1)); @@ -261,7 +267,7 @@ public function __construct($Path = false, $RawData = false, array $Options = nu $Value = self::ParseStructuredValue($Value, $Key); if ($Type) { - $Value['Type'] = $Type; + $Value['type'] = $Type; } } else @@ -274,15 +280,15 @@ public function __construct($Path = false, $RawData = false, array $Options = nu if ($Type) { $Value = array( - 'Value' => $Value, - 'Type' => $Type + 'value' => $Value, + 'type' => $Type ); } } if (is_array($Value) && $Encoding) { - $Value['Encoding'] = $Encoding; + $Value['encoding'] = $Encoding; } if (!isset($this -> Data[$Key])) @@ -295,6 +301,22 @@ public function __construct($Path = false, $RawData = false, array $Options = nu } } + /** + * method to get key list of the current vcard + * + * @return array list of key + */ + public function getKeyList() + { + $keylist=array(); + if (isset($this -> Data)) + { + foreach($this -> Data as $key => $val) + $keylist[]=$key; + } + return $keylist; + } + /** * Magic method to get the various vCard values as object members, e.g. * a call to $vCard -> N gets the "N" value @@ -317,10 +339,10 @@ public function __get($Key) $Value = $this -> Data[$Key]; foreach ($Value as $K => $V) { - if (stripos($V['Value'], 'uri:') === 0) + if (isset($V['Value']) && stripos($V['Value'], 'uri:') === 0) { - $Value[$K]['Value'] = substr($V, 4); - $Value[$K]['Encoding'] = 'uri'; + $Value[$K]['value'] = substr($V, 4); + $Value[$K]['encoding'] = 'uri'; } } return $Value; @@ -339,6 +361,20 @@ public function __get($Key) return array(); } + /** + * Magic method to check isset for the various vCard values as object members, e.g. + * a call to isset( $vCard -> fn ) checks existence of a value. + * + * @param string Key + * + * @return bool isset + */ + public function __isset($Key) { + $Key = strtolower($Key); + $val = $this->$Key; + return isset($val); + } + /** * Saves an embedded file * @@ -360,15 +396,15 @@ public function SaveFile($Key, $Index = 0, $TargetPath = '') } // Returing false if it is an image URL - if (stripos($this -> Data[$Key][$Index]['Value'], 'uri:') === 0) + if (stripos($this -> Data[$Key][$Index]['value'], 'uri:') === 0) { return false; } if (is_writable($TargetPath) || (!file_exists($TargetPath) && is_writable(dirname($TargetPath)))) { - $RawContent = $this -> Data[$Key][$Index]['Value']; - if (isset($this -> Data[$Key][$Index]['Encoding']) && $this -> Data[$Key][$Index]['Encoding'] == 'b') + $RawContent = $this -> Data[$Key][$Index]['value']; + if (isset($this -> Data[$Key][$Index]['encoding']) && $this -> Data[$Key][$Index]['encoding'] == 'b') { $RawContent = base64_decode($RawContent); } @@ -403,10 +439,10 @@ public function __call($Key, $Arguments) if (count($Arguments) > 1) { - $Types = array_values(array_slice($Arguments, 1)); + $Types = array_map('strtolower', array_values(array_slice($Arguments, 1))); if (isset(self::$Spec_StructuredElements[$Key]) && - in_array($Arguments[1], self::$Spec_StructuredElements[$Key]) + in_array(strtolower($Arguments[1]), self::$Spec_StructuredElements[$Key]) ) { $LastElementIndex = 0; @@ -438,8 +474,8 @@ public function __call($Key, $Arguments) elseif (isset(self::$Spec_ElementTypes[$Key])) { $this -> Data[$Key][] = array( - 'Value' => $Value, - 'Type' => $Types + 'value' => $Value, + 'type' => $Types ); } } @@ -474,9 +510,9 @@ public function __toString() foreach ($Values as $Index => $Value) { $Text .= $KeyUC; - if (is_array($Value) && isset($Value['Type'])) + if (is_array($Value) && isset($Value['type'])) { - $Text .= ';TYPE='.self::PrepareTypeStrForOutput($Value['Type']); + $Text .= ';TYPE='.self::PrepareTypeStrForOutput($Value['type']); } $Text .= ':'; @@ -491,7 +527,7 @@ public function __toString() } elseif (is_array($Value) && isset(self::$Spec_ElementTypes[$Key])) { - $Text .= $Value['Value']; + $Text .= $Value['value']; } else { @@ -573,7 +609,8 @@ private static function ParseParameters($Key, array $RawParams = null) $Parameters = array(); foreach ($RawParams as $Item) { - $Parameters[] = explode('=', strtolower($Item)); + // try to correct issue https://github.com/nuovo/vCard-parser/issues/20 + $Parameters[] = explode('=', strtolower($Item),2); } $Type = array(); @@ -603,10 +640,13 @@ private static function ParseParameters($Key, array $RawParams = null) } elseif (count($Parameter) > 2) { - $TempTypeParams = self::ParseParameters($Key, explode(',', $RawParams[$Index])); - if ($TempTypeParams['type']) + if(count(explode(',', $RawParams[$Index], -1)) > 0) { - $Type = array_merge($Type, $TempTypeParams['type']); + $TempTypeParams = self::ParseParameters($Key, explode(',', $RawParams[$Index])); + if ($TempTypeParams['type']) + { + $Type = array_merge($Type, $TempTypeParams['type']); + } } } else @@ -686,4 +726,4 @@ public function key() return key($this -> Data); } } -?> \ No newline at end of file +?>