Fix function name error in contacts app
[owncloud:owncloud.git] / apps / contacts / lib / vcard.php
1 <?php
2 /**
3  * ownCloud - Addressbook
4  *
5  * @author Jakob Sack
6  * @copyright 2011 Jakob Sack mail@jakobsack.de
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
10  * License as published by the Free Software Foundation; either
11  * version 3 of the License, or any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU AFFERO GENERAL PUBLIC LICENSE for more details.
17  *
18  * You should have received a copy of the GNU Affero General Public
19  * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22 /*
23  *
24  * The following SQL statement is just a help for developers and will not be
25  * executed!
26  *
27  * CREATE TABLE contacts_cards (
28  * id INT(11) UNSIGNED NOT NULL PRIMARY KEY AUTO_INCREMENT,
29  * addressbookid INT(11) UNSIGNED NOT NULL,
30  * fullname VARCHAR(255),
31  * carddata TEXT,
32  * uri VARCHAR(100),
33  * lastmodified INT(11) UNSIGNED
34  * );
35  */
36
37 /**
38  * This class manages our vCards
39  */
40 class OC_Contacts_VCard{
41         /**
42          * @brief Returns all cards of an address book
43          * @param integer $id
44          * @return array
45          *
46          * The cards are associative arrays. You'll find the original vCard in
47          * ['carddata']
48          */
49         public static function all($id){
50                 $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ?' );
51                 $result = $stmt->execute(array($id));
52
53                 $addressbooks = array();
54                 while( $row = $result->fetchRow()){
55                         $addressbooks[] = $row;
56                 }
57
58                 return $addressbooks;
59         }
60
61         /**
62          * @brief Returns a card
63          * @param integer $id
64          * @return associative array
65          */
66         public static function find($id){
67                 $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE id = ?' );
68                 $result = $stmt->execute(array($id));
69
70                 return $result->fetchRow();
71         }
72
73         /**
74          * @brief finds a card by its DAV Data
75          * @param integer $aid Addressbook id
76          * @param string $uri the uri ('filename')
77          * @return associative array
78          */
79         public static function findWhereDAVDataIs($aid,$uri){
80                 $stmt = OC_DB::prepare( 'SELECT * FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri = ?' );
81                 $result = $stmt->execute(array($aid,$uri));
82
83                 return $result->fetchRow();
84         }
85
86         /**
87          * @brief Adds a card
88          * @param integer $id Addressbook id
89          * @param string $data  vCard file
90          * @return insertid
91          */
92         public static function add($id,$data){
93                 $fn = null;
94                 $uri = null;
95
96                 $card = self::parse($data);
97                 if(!is_null($card)){
98                         foreach($card->children as $property){
99                                 if($property->name == 'FN'){
100                                         $fn = $property->value;
101                                 }
102                                 elseif(is_null($uri) && $property->name == 'UID' ){
103                                         $uri = $property->value.'.vcf';
104                                 }
105                         }
106                         if(is_null($uri)){
107                                 $uid = self::createUID();
108                                 $uri = $uid.'.vcf';
109                                 $card->add(new Sabre_VObject_Property('UID',$uid));
110                                 $data = $card->serialize();
111                         };
112                 }
113                 else{
114                         // that's hard. Creating a UID and not saving it
115                         $uid = self::createUID();
116                         $uri = $uid.'.vcf';
117                 };
118
119                 $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' );
120                 $result = $stmt->execute(array($id,$fn,$data,$uri,time()));
121
122                 OC_Contacts_Addressbook::touch($id);
123
124                 return OC_DB::insertid();
125         }
126
127         /**
128          * @brief Adds a card with the data provided by sabredav
129          * @param integer $id Addressbook id
130          * @param string $uri   the uri the card will have
131          * @param string $data  vCard file
132          * @return insertid
133          */
134         public static function addFromDAVData($id,$uri,$data){
135                 $fn = null;
136                 $card = self::parse($data);
137                 if(!is_null($card)){
138                         foreach($card->children as $property){
139                                 if($property->name == 'FN'){
140                                         $fn = $property->value;
141                                 }
142                         }
143                 }
144
145                 $stmt = OC_DB::prepare( 'INSERT INTO *PREFIX*contacts_cards (addressbookid,fullname,carddata,uri,lastmodified) VALUES(?,?,?,?,?)' );
146                 $result = $stmt->execute(array($id,$fn,$data,$uri,time()));
147
148                 OC_Contacts_Addressbook::touch($id);
149
150                 return OC_DB::insertid();
151         }
152
153         /**
154          * @brief edits a card
155          * @param integer $id id of card
156          * @param string $data  vCard file
157          * @return boolean
158          */
159         public static function edit($id, $data){
160                 $oldcard = self::find($id);
161                 $fn = null;
162
163                 $card = self::parse($data);
164                 if(!is_null($card)){
165                         foreach($card->children as $property){
166                                 if($property->name == 'FN'){
167                                         $fn = $property->value;
168                                 }
169                         }
170                 }
171
172                 $stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' );
173                 $result = $stmt->execute(array($fn,$data,time(),$id));
174
175                 OC_Contacts_Addressbook::touch($oldcard['addressbookid']);
176
177                 return true;
178         }
179
180         /**
181          * @brief edits a card with the data provided by sabredav
182          * @param integer $id Addressbook id
183          * @param string $uri   the uri of the card
184          * @param string $data  vCard file
185          * @return boolean
186          */
187         public static function editFromDAVData($aid,$uri,$data){
188                 $oldcard = self::findWhereDAVDataIs($aid,$uri);
189
190                 $fn = null;
191                 $card = self::parse($data);
192                 if(!is_null($card)){
193                         foreach($card->children as $property){
194                                 if($property->name == 'FN'){
195                                         $fn = $property->value;
196                                 }
197                         }
198                 }
199
200                 $stmt = OC_DB::prepare( 'UPDATE *PREFIX*contacts_cards SET fullname = ?,carddata = ?, lastmodified = ? WHERE id = ?' );
201                 $result = $stmt->execute(array($fn,$data,time(),$oldcard['id']));
202
203                 OC_Contacts_Addressbook::touch($oldcard['addressbookid']);
204
205                 return true;
206         }
207
208         /**
209          * @brief deletes a card
210          * @param integer $id id of card
211          * @return boolean
212          */
213         public static function delete($id){
214                 $stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE id = ?' );
215                 $stmt->execute(array($id));
216
217                 return true;
218         }
219
220         /**
221          * @brief Creates a UID
222          * @return string
223          */
224         public static function createUID(){
225                 return substr(md5(rand().time()),0,10);
226         }
227
228         /**
229          * @brief deletes a card with the data provided by sabredav
230          * @param integer $aid Addressbook id
231          * @param string $uri the uri of the card
232          * @return boolean
233          */
234         public static function deleteFromDAVData($aid,$uri){
235                 $stmt = OC_DB::prepare( 'DELETE FROM *PREFIX*contacts_cards WHERE addressbookid = ? AND uri=?' );
236                 $stmt->execute(array($aid,$uri));
237
238                 return true;
239         }
240
241         /**
242          * @brief Escapes semicolons
243          * @param string $value
244          * @return string
245          */
246         public static function escapeSemicolons($value){
247                 foreach($value as &$i ){
248                         $i = implode("\\\\;", explode(';', $i));
249                 }
250                 return implode(';',$value);
251         }
252
253         /**
254          * @brief Creates an array out of a multivalue property
255          * @param string $value
256          * @return array
257          */
258         public static function unescapeSemicolons($value){
259                 $array = explode(';',$value);
260                 for($i=0;$i<count($array);$i++){
261                         if(substr($array[$i],-2,2)=="\\\\"){
262                                 if(isset($array[$i+1])){
263                                         $array[$i] = substr($array[$i],0,count($array[$i])-2).';'.$array[$i+1];
264                                         unset($array[$i+1]);
265                                 }
266                                 else{
267                                         $array[$i] = substr($array[$i],0,count($array[$i])-2).';';
268                                 }
269                                 $i = $i - 1;
270                         }
271                 }
272                 return $array;
273         }
274
275         /**
276          * @brief Add property to vcard object
277          * @param object $vcard
278          * @param object $name of property
279          * @param object $value of property
280          * @param object $paramerters of property
281          */
282         public static function addVCardProperty($vcard, $name, $value, $parameters=array()){
283                 if(is_array($value)){
284                         $value = OC_Contacts_VCard::escapeSemicolons($value);
285                 }
286                 $property = new Sabre_VObject_Property( $name, $value );
287                 $parameternames = array_keys($parameters);
288                 foreach($parameternames as $i){
289                         $property->parameters[] = new Sabre_VObject_Parameter($i,$parameters[$i]);
290                 }
291
292                 $vcard->add($property);
293                 return $property;
294         }
295
296         /**
297          * @brief Data structure of vCard
298          * @param object $property
299          * @return associative array
300          *
301          * look at code ...
302          */
303         public static function structureContact($object){
304                 $details = array();
305                 foreach($object->children as $property){
306                         $temp = self::structureProperty($property);
307                         if(array_key_exists($property->name,$details)){
308                                 $details[$property->name][] = $temp;
309                         }
310                         else{
311                                 $details[$property->name] = array($temp);
312                         }
313                 }
314                 return $details;
315         }
316
317         /**
318          * @brief Data structure of properties
319          * @param object $property
320          * @return associative array
321          *
322          * returns an associative array with
323          * ['name'] name of property
324          * ['value'] htmlspecialchars escaped value of property
325          * ['parameters'] associative array name=>value
326          * ['checksum'] checksum of whole property
327          */
328         public static function structureProperty($property){
329                 $value = $property->value;
330                 $value = htmlspecialchars($value);
331                 if($property->name == 'ADR' || $property->name == 'N'){
332                         $value = self::unescapeSemicolons($value);
333                 }
334                 $temp = array(
335                         'name' => $property->name,
336                         'value' => $value,
337                         'parameters' => array(),
338                         'checksum' => md5($property->serialize()));
339                 foreach($property->parameters as $parameter){
340                         // Faulty entries by kaddressbook
341                         if($parameter->name == 'TYPE' && $parameter->value == 'PREF'){
342                                 $parameter->name = 'PREF';
343                                 $parameter->value = '1';
344                         }
345                         $temp['parameters'][$parameter->name] = $parameter->value;
346                 }
347                 return $temp;
348         }
349
350         /**
351          * @brief Parses a vcard file
352          * @param string vCard
353          * @return Sabre_VObject or null
354          *
355          * Will retun the vobject if sabre DAV is able to parse the file.
356          */
357         public static function parse($data){
358                 try {
359                         $card = Sabre_VObject_Reader::read($data);
360                         return $card;
361                 } catch (Exception $e) {
362                         return null;
363                 }
364         }
365 }