1<?
2/***************************************************************************
3
4PHP vCard class v2.0
5(c) Kai Blankenhorn
6www.bitfolge.de/en
7kaib@bitfolge.de
8
9
10This program is free software; you can redistribute it and/or
11modify it under the terms of the GNU General Public License
12as published by the Free Software Foundation; either version 2
13of the License, or (at your option) any later version.
14
15This program is distributed in the hope that it will be useful,
16but WITHOUT ANY WARRANTY; without even the implied warranty of
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18GNU General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program; if not, write to the Free Software
22Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23
24***************************************************************************/
25
26
27function encode($string) {
28	// return escape(quoted_printable_encode($string));
29	return escape($string);
30}
31
32function escape($string) {
33	return str_replace(";","\;",$string);
34}
35
36// taken from PHP documentation comments
37if (!function_exists('quoted_printable_encode')) {
38function quoted_printable_encode($input, $line_max = 76) {
39	$hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
40	$lines = preg_split("/(?:\r\n|\r|\n)/", $input);
41	$eol = "\r\n";
42	$linebreak = "=0D=0A";
43	$escape = "=";
44	$output = "";
45
46	for ($j=0;$j<count($lines);$j++) {
47		$line = $lines[$j];
48		$linlen = strlen($line);
49		$newline = "";
50		for($i = 0; $i < $linlen; $i++) {
51			$c = substr($line, $i, 1);
52			$dec = ord($c);
53			if ( ($dec == 32) && ($i == ($linlen - 1)) ) { // convert space at eol only
54				$c = "=20";
55			} elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
56				$h2 = floor($dec/16); $h1 = floor($dec%16);
57				$c = $escape.$hex["$h2"].$hex["$h1"];
58			}
59			if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
60				$output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
61				$newline = "    ";
62			}
63			$newline .= $c;
64		} // end of for
65		$output .= $newline;
66		if ($j<count($lines)-1) $output .= $linebreak;
67	}
68	return trim($output);
69}
70}
71
72class vCard {
73	var $properties;
74	var $filename;
75
76	function setPhoneNumber($number, $type="") {
77	// type may be PREF | WORK | HOME | VOICE | FAX | MSG | CELL | PAGER | BBS | CAR | MODEM | ISDN | VIDEO or any senseful combination, e.g. "PREF;WORK;VOICE"
78		$key = "TEL";
79		if ($type!="") $key .= ";".$type;
80		$key.= ";ENCODING=UTF-8";
81		$this->properties[$key] = quoted_printable_encode($number);
82	}
83
84	// UNTESTED !!!
85	function setPhoto($type, $photo) { // $type = "GIF" | "JPEG"
86		$this->properties["PHOTO;TYPE=$type;ENCODING=BASE64"] = base64_encode($photo);
87	}
88
89	function setFormattedName($name) {
90		$this->properties["FN"] = quoted_printable_encode($name);
91	}
92
93	function setName($family="", $first="", $additional="", $prefix="", $suffix="") {
94		$this->properties["N"] = "$family;$first;$additional;$prefix;$suffix";
95		$this->filename = "$first-$family.vcf";
96		if ($this->properties["FN"]=="") $this->setFormattedName(trim("$prefix $first $additional $family $suffix"));
97	}
98
99	function setBirthday($date) { // $date format is YYYY-MM-DD
100		$this->properties["BDAY"] = $date;
101	}
102
103	function setAddress($postoffice="", $extended="", $street="", $city="", $region="", $zip="", $country="", $type="HOME;POSTAL") {
104	// $type may be DOM | INTL | POSTAL | PARCEL | HOME | WORK or any combination of these: e.g. "WORK;PARCEL;POSTAL"
105		$key = "ADR";
106		if ($type!="") $key.= ";$type";
107		$key.= ";ENCODING=UTF-8";
108		$this->properties[$key] = encode($name).";".encode($extended).";".encode($street).";".encode($city).";".encode($region).";".encode($zip).";".encode($country);
109
110		if ($this->properties["LABEL;$type;ENCODING=UTF-8"] == "") {
111			//$this->setLabel($postoffice, $extended, $street, $city, $region, $zip, $country, $type);
112		}
113	}
114
115	function setLabel($postoffice="", $extended="", $street="", $city="", $region="", $zip="", $country="", $type="HOME;POSTAL") {
116		$label = "";
117		if ($postoffice!="") $label.= "$postoffice\r\n";
118		if ($extended!="") $label.= "$extended\r\n";
119		if ($street!="") $label.= "$street\r\n";
120		if ($zip!="") $label.= "$zip ";
121		if ($city!="") $label.= "$city\r\n";
122		if ($region!="") $label.= "$region\r\n";
123		if ($country!="") $country.= "$country\r\n";
124
125		$this->properties["LABEL;$type;ENCODING=UTF-8"] = quoted_printable_encode($label);
126	}
127
128	function setEmail($address) {
129		$this->properties["EMAIL;INTERNET"] = $address;
130	}
131
132	function setCompany($company) {
133		$this->properties["ORG"] = $company;
134	}
135
136	function setNote($note) {
137		$this->properties["NOTE;ENCODING=UTF-8"] = quoted_printable_encode($note);
138	}
139
140	function setURL($url, $type="") {
141	// $type may be WORK | HOME
142		$key = "URL";
143		if ($type!="") $key.= ";$type";
144		$this->properties[$key] = $url;
145	}
146
147	function getVCard() {
148		$text = "BEGIN:VCARD\r\n";
149		$text.= "VERSION:2.1\r\n";
150		foreach($this->properties as $key => $value) {
151			$text.= "$key:$value\r\n";
152		}
153		$text.= "REV:".date("Y-m-d")."T".date("H:i:s")."Z\r\n";
154		// $text.= "MAILER:PHP vCard class by Kai Blankenhorn\r\n";
155		$text.= "END:VCARD\r\n";
156		return $text;
157	}
158
159	function getFileName() {
160		return $this->filename;
161	}
162}
163
164/**
165 * output script: let's you download the vCard
166 *
167 * @author Esther Brunner <esther@kaffeehaus.ch>
168 */
169
170$v = new vCard();
171
172$v->setName($_REQUEST['family-name'], $_REQUEST['given-name'], $_REQUEST['additional-name'], '');
173$v->setEmail($_REQUEST['email']);
174$v->setCompany($_REQUEST['org']);
175$v->setURL($_REQUEST['website'], 'WORK');
176$v->setBirthday($_REQUEST['bday']);
177$v->setPhoneNumber($_REQUEST['home'], 'PREF;HOME;VOICE');
178$v->setPhoneNumber($_REQUEST['cell'], 'CELL;VOICE');
179$v->setPhoneNumber($_REQUEST['work'], 'WORK;VOICE');
180$v->setPhoneNumber($_REQUEST['fax'], 'WORK;FAX');
181$v->setAddress('', '', $_REQUEST['street-address'], $_REQUEST['locality'], '', $_REQUEST['postal-code'], $_REQUEST['country-name']);
182
183
184$output = $v->getVCard();
185$filename = $v->getFileName();
186
187header('Content-Disposition: attachment; filename='.$filename);
188header('Content-Length: '.strlen($output));
189header('Connection: close');
190header('Content-Type: text/x-vCard; name='.$filename);
191
192echo $output;
193