]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - include/vCard.php
Release 6.5.12
[Github/sugarcrm.git] / include / vCard.php
1 <?php
2 if(!defined('sugarEntry') || !sugarEntry) die('Not A Valid Entry Point');
3 /*********************************************************************************
4  * SugarCRM Community Edition is a customer relationship management program developed by
5  * SugarCRM, Inc. Copyright (C) 2004-2013 SugarCRM Inc.
6  * 
7  * This program is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU Affero General Public License version 3 as published by the
9  * Free Software Foundation with the addition of the following permission added
10  * to Section 15 as permitted in Section 7(a): FOR ANY PART OF THE COVERED WORK
11  * IN WHICH THE COPYRIGHT IS OWNED BY SUGARCRM, SUGARCRM DISCLAIMS THE WARRANTY
12  * OF NON INFRINGEMENT OF THIRD PARTY RIGHTS.
13  * 
14  * This program is distributed in the hope that it will be useful, but WITHOUT
15  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16  * FOR A PARTICULAR PURPOSE.  See the GNU Affero General Public License for more
17  * details.
18  * 
19  * You should have received a copy of the GNU Affero General Public License along with
20  * this program; if not, see http://www.gnu.org/licenses or write to the Free
21  * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22  * 02110-1301 USA.
23  * 
24  * You can contact SugarCRM, Inc. headquarters at 10050 North Wolfe Road,
25  * SW2-130, Cupertino, CA 95014, USA. or at email address contact@sugarcrm.com.
26  * 
27  * The interactive user interfaces in modified source and object code versions
28  * of this program must display Appropriate Legal Notices, as required under
29  * Section 5 of the GNU Affero General Public License version 3.
30  * 
31  * In accordance with Section 7(b) of the GNU Affero General Public License version 3,
32  * these Appropriate Legal Notices must retain the display of the "Powered by
33  * SugarCRM" logo. If the display of the logo is not reasonably feasible for
34  * technical reasons, the Appropriate Legal Notices must display the words
35  * "Powered by SugarCRM".
36  ********************************************************************************/
37
38 /**
39  * vCard implementation
40  * @api
41  */
42 class vCard
43 {
44         protected $properties = array();
45
46         protected $name = 'no_name';
47
48         public function clear()
49         {
50                 $this->properties = array();
51         }
52
53         function loadContact($contactid, $module='Contacts') {
54                 global $app_list_strings;
55
56                 require_once($GLOBALS['beanFiles'][$GLOBALS['beanList'][$module]]);
57                 $contact = new $GLOBALS['beanList'][$module]();
58                 $contact->retrieve($contactid);
59                 // cn: bug 8504 - CF/LB break Outlook's vCard import
60                 $bad = array("\n", "\r");
61                 $good = array("=0A", "=0D");
62                 $encoding = '';
63                 if(strpos($contact->primary_address_street, "\n") || strpos($contact->primary_address_street, "\r")) {
64                         $contact->primary_address_street = str_replace($bad, $good, $contact->primary_address_street);
65                         $encoding = 'QUOTED-PRINTABLE';
66                 }
67
68                 $this->setName(from_html($contact->first_name), from_html($contact->last_name), $app_list_strings['salutation_dom'][from_html($contact->salutation)]);
69                 if ( isset($contact->birthdate) )
70             $this->setBirthDate(from_html($contact->birthdate));
71                 $this->setPhoneNumber(from_html($contact->phone_fax), 'FAX');
72                 $this->setPhoneNumber(from_html($contact->phone_home), 'HOME');
73                 $this->setPhoneNumber(from_html($contact->phone_mobile), 'CELL');
74                 $this->setPhoneNumber(from_html($contact->phone_work), 'WORK');
75                 $this->setEmail(from_html($contact->email1));
76                 $this->setAddress(from_html($contact->primary_address_street), from_html($contact->primary_address_city), from_html($contact->primary_address_state), from_html($contact->primary_address_postalcode), from_html($contact->primary_address_country), 'WORK', $encoding);
77                 if ( isset($contact->account_name) )
78             $this->setORG(from_html($contact->account_name), from_html($contact->department));
79         else
80             $this->setORG('', from_html($contact->department));
81                 $this->setTitle($contact->title);
82         }
83
84         function setTitle($title){
85                 $this->setProperty("TITLE",$title );
86         }
87         function setORG($org, $dep){
88                 $this->setProperty("ORG","$org;$dep" );
89         }
90         function setAddress($address, $city, $state,$postal, $country, $type, $encoding=''){
91                 if(!empty($encoding)) {
92                         $encoding = ";ENCODING={$encoding}";
93                 }
94                 $this->setProperty("ADR;$type$encoding",";;$address;$city;$state;$postal;$country" );
95         }
96
97         function setName($first_name, $last_name, $prefix){
98                 $this->name = strtr($first_name.'_'.$last_name, ' ' , '_');
99                 $this->setProperty('N',$last_name.';'.$first_name.';;'.$prefix );
100                 $this->setProperty('FN',"$prefix $first_name $last_name");
101         }
102
103         function setEmail($address){
104                 $this->setProperty('EMAIL;INTERNET', $address);
105         }
106
107         function setPhoneNumber( $number, $type)
108         {
109                 if($type != 'FAX') {
110                     $this->setProperty("TEL;$type", $number);
111                 }
112                 else {
113                     $this->setProperty("TEL;WORK;$type", $number);
114                 }
115         }
116         function setBirthDate($date){
117                         $this->setProperty('BDAY',$date);
118         }
119         function getProperty($name){
120                 if(isset($this->properties[$name]))
121                         return $this->properties[$name];
122                 return null;
123         }
124
125         function setProperty($name, $value){
126                 $this->properties[$name] = $value;
127         }
128
129         function toString(){
130             global $locale;
131                 $temp = "BEGIN:VCARD\n";
132                 foreach($this->properties as $key=>$value){
133                     if(!empty($value)) {
134                             $temp .= $key. ';CHARSET='.strtolower($locale->getExportCharset()).':'.$value."\n";
135                     } else {
136                         $temp .= $key. ':'.$value."\n";
137                     }
138                 }
139                 $temp.= "END:VCARD\n";
140
141
142                 return $temp;
143         }
144
145         function saveVCard(){
146                 global $locale;
147                 $content = $this->toString();
148                 if ( !defined('SUGAR_PHPUNIT_RUNNER') ) {
149             header("Content-Disposition: attachment; filename={$this->name}.vcf");
150             header("Content-Type: text/x-vcard; charset=".$locale->getExportCharset());
151             header("Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
152             header("Last-Modified: " . TimeDate::httpTime() );
153             header("Cache-Control: max-age=0");
154             header("Pragma: public");
155             //bug45856 IIS Doesn't like this to be set and it causes the vCard to not get saved
156             if (preg_match('/iis/i', $_SERVER['SERVER_SOFTWARE']) === 0) {
157                 header("Content-Length: ".strlen($content));
158             }
159         }
160
161                 print $locale->translateCharset($content, 'UTF-8', $locale->getExportCharset());
162         }
163
164     function importVCard($filename, $module = 'Contacts')
165     {
166         global $current_user;
167         $lines = file($filename);
168         $start = false;
169
170         $bean = BeanFactory::getBean($module);
171         $bean->title = 'imported';
172         $bean->assigned_user_id = $current_user->id;
173         $email_suffix = 1;
174
175         for ($index = 0; $index < sizeof($lines); $index++)
176         {
177             $line = $lines[$index];
178
179             // check the encoding and change it if needed
180             $locale = new Localization();
181             $encoding = false;
182             //detect charset
183             if (preg_match("/CHARSET=([A-Z]+([A-Z0-9]-?)*):/", $line, $matches)) {
184                 //found charset hint in vcard
185                 $encoding = $matches[1];
186             } else {
187                 //use locale to detect charset automatically
188                 $encoding = $locale->detectCharset($line);
189             }
190             if ( $encoding != $GLOBALS['sugar_config']['default_charset'] )
191             {
192                 $line = $locale->translateCharset($line, $encoding);
193             }
194
195             $line = trim($line);
196             if ($start)
197             {
198                 //VCARD is done
199                 if (substr_count(strtoupper($line), 'END:VCARD'))
200                 {
201                     if (!isset($bean->last_name) && !empty($fullname))
202                     {
203                         $bean->last_name = $fullname;
204                     }
205                     break;
206                 }
207
208                 $keyvalue = explode(':', $line);
209                 if (sizeof($keyvalue) == 2)
210                 {
211                     $value = $keyvalue[1];
212                     for ($newindex = $index + 1;  $newindex < sizeof($lines), substr_count($lines[$newindex], ':') == 0; $newindex++)
213                     {
214                         $value .= $lines[$newindex];
215                         $index = $newindex;
216                     }
217                     $values = explode(';', $value);
218                     $key = strtoupper($keyvalue[0]);
219                     $key = strtr($key, '=', '');
220                     $key = strtr($key, ',', ';');
221                     $keys = explode(';', $key);
222
223                     if($keys[0] == 'TEL')
224                     {
225                         if(substr_count($key, 'WORK') > 0)
226                         {
227                             if(substr_count($key, 'FAX') > 0)
228                             {
229                                 if(!isset($bean->phone_fax))
230                                 {
231                                     $bean->phone_fax = $value;
232                                 }
233                             }
234                             else
235                             {
236                                 if(!isset($bean->phone_work))
237                                 {
238                                     $bean->phone_work = $value;
239                                 }
240                             }
241                         }
242
243                         if (substr_count($key, 'HOME') > 0)
244                         {
245                             if (substr_count($key, 'FAX') > 0)
246                             {
247                                 if (!isset($bean->phone_fax))
248                                 {
249                                     $bean->phone_fax = $value;
250                                 }
251                             }
252                             else
253                             {
254                                 if (!isset($bean->phone_home))
255                                 {
256                                     $bean->phone_home = $value;
257                                 }
258                             }
259                         }
260                         if (substr_count($key, 'CELL') > 0)
261                         {
262                             if (!isset($bean->phone_mobile))
263                             {
264                                 $bean->phone_mobile = $value;
265                             }
266                         }
267                         if (substr_count($key, 'FAX') > 0)
268                         {
269                             if (!isset($bean->phone_fax))
270                             {
271                                 $bean->phone_fax = $value;
272                             }
273                         }
274                     }
275
276                     if ($keys[0] == 'N')
277                     {
278                         if (sizeof($values) > 0)
279                         {
280                             $bean->last_name = $values[0];
281                         }
282                         if (sizeof($values) > 1)
283                         {
284                             $bean->first_name = $values[1];
285                         }
286                         if (sizeof($values) > 2)
287                         {
288                             $bean->salutation = $values[2];
289                         }
290                     }
291
292                     if ($keys[0] == 'FN')
293                     {
294                         $fullname = $value;
295                     }
296                 }
297
298                 if ($keys[0] == 'ADR')
299                 {
300                     if (substr_count($key, 'WORK') > 0 && (substr_count($key, 'POSTAL') > 0|| substr_count($key, 'PARCEL') == 0))
301                     {
302                         if (!isset($bean->primary_address_street) && sizeof($values) > 2)
303                         {
304                             $textBreaks = array("\n", "\r");
305                             $vcardBreaks = array("=0A", "=0D");
306                             $bean->primary_address_street = str_replace($vcardBreaks, $textBreaks, $values[2]);
307                         }
308                         if (!isset($bean->primary_address_city) && sizeof($values) > 3)
309                         {
310                             $bean->primary_address_city = $values[3];
311                         }
312                         if (!isset($bean->primary_address_state) && sizeof($values) > 4)
313                         {
314                             $bean->primary_address_state = $values[4];
315                         }
316                         if (!isset($bean->primary_address_postalcode) && sizeof($values) > 5)
317                         {
318                             $bean->primary_address_postalcode = $values[5];
319                         }
320                         if (!isset($bean->primary_address_country) && sizeof($values) > 6)
321                         {
322                             $bean->primary_address_country = $values[6];
323                         }
324                     }
325                 }
326
327                 if ($keys[0] == 'TITLE')
328                 {
329                     $bean->title = $value;
330                 }
331                 if ($keys[0] == 'EMAIL')
332                 {
333                     $field = 'email' . $email_suffix;
334                     if (!isset($bean->$field))
335                     {
336                         $bean->$field = $value;
337                     }
338                     if ($email_suffix == 1)
339                     {
340                         $_REQUEST['email1'] = $value;
341                     }
342                     $email_suffix++;
343                 }
344
345                 if ($keys[0] == 'ORG')
346                 {
347                     $GLOBALS['log']->debug('I found a company name');
348                     if (!empty($value))
349                     {
350                         $GLOBALS['log']->debug('I found a company name (fer real)');
351                         if ( is_a($bean,"Contact") || is_a($bean,"Lead") )
352                         {
353                             $GLOBALS['log']->debug('And Im dealing with a person!');
354                             $accountBean = BeanFactory::getBean('Accounts');
355                             // It's a contact, we better try and match up an account
356                             $full_company_name = trim($values[0]);
357                             // Do we have a full company name match?
358                             $result = $accountBean->retrieve_by_string_fields(array('name' => $full_company_name, 'deleted' => 0));
359                             if ( ! isset($result->id) )
360                             {
361                                 // Try to trim the full company name down, see if we get some other matches
362                                 $vCardTrimStrings = array('/ltd\.*/i'=>'',
363                                                             '/llc\.*/i'=>'',
364                                                             '/gmbh\.*/i'=>'',
365                                                             '/inc\.*/i'=>'',
366                                                             '/\.com/i'=>'',
367                                                     );
368                                 // Allow users to override the trimming strings
369                                 if ( file_exists('custom/include/vCardTrimStrings.php') )
370                                 {
371                                     require_once('custom/include/vCardTrimStrings.php');
372                                 }
373                                 $short_company_name = trim(preg_replace(array_keys($vCardTrimStrings), $vCardTrimStrings,$full_company_name), " ,.");
374
375                                 $GLOBALS['log']->debug('Trying an extended search for: ' . $short_company_name);
376                                 $result = $accountBean->retrieve_by_string_fields(array('name' => $short_company_name, 'deleted' => 0));
377                             }
378
379                             if (  is_a($bean, "Lead") || ! isset($result->id) )
380                             {
381                                 // We could not find a parent account, or this is a lead so only copy the name, no linking
382                                 $GLOBALS['log']->debug("Did not find a matching company ($full_company_name)");
383                                 $bean->account_id = '';
384                                 $bean->account_name = $full_company_name;
385                             }
386                             else
387                             {
388                                 $GLOBALS['log']->debug("Found a matching company: " . $result->name);
389                                 $bean->account_id = $result->id;
390                                 $bean->account_name = $result->name;
391                             }
392                             $bean->department = $values[1];
393                         }
394                         else
395                         {
396                             $bean->department = $value;
397                         }
398                     }
399
400                 }
401
402             }
403
404             //FOUND THE BEGINING OF THE VCARD
405             if (!$start && substr_count(strtoupper($line), 'BEGIN:VCARD'))
406             {
407                 $start = true;
408             }
409         }
410
411         foreach ($bean->get_import_required_fields() as $key => $value)
412         {
413             $GLOBALS['log']->error("Cannot import vCard, required field is not set: $key");
414             if (empty($bean->$key))
415             {
416                 return;
417             }
418         }
419
420         if ( is_a($bean, "Contact") && empty($bean->account_id) && !empty($bean->account_name) )
421         {
422             $GLOBALS['log']->debug("Look ma! I'm creating a new account: " . $bean->account_name);
423             // We need to create a new account
424             $accountBean = BeanFactory::getBean('Accounts');
425             // Populate the newly created account with all of the contact information
426             foreach ( $bean->field_defs as $field_name => $field_def )
427             {
428                 if ( !empty($bean->$field_name) )
429                 {
430                     $accountBean->$field_name = $bean->$field_name;
431                 }
432             }
433             $accountBean->name = $bean->account_name;
434             $accountBean->save();
435             $bean->account_id = $accountBean->id;
436         }
437
438         $beanId = $bean->save();
439         return $beanId;
440         }
441 }
442
443 ?>