"Fossies" - the Fresh Open Source Software Archive 
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) PHP source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "groupe.php" see the
Fossies "Dox" file reference documentation.
1 <?php
2 /***********************************************
3 * File : vcarddir.php
4 * Project : Z-Push
5 * Descr : This backend is for vcard
6 * directories.
7 *
8 * Created : 01.10.2007
9 *
10 * � Zarafa Deutschland GmbH, www.zarafaserver.de
11 * This file is distributed under GPL v2.
12 * Consult LICENSE file for details
13 ************************************************/
14 include_once('diffbackend.php');
15 include_once('mime.php');
16 include_once('mimeDecode.php');
17 include_once('z_RFC822.php');
18
19 function setMessageBody ($message,$tmpBody,$bodypreference) {
20 if ($bodypreference == false) {
21 $message->body = $tmpBody;
22 $message->bodysize = strlen($message->body);
23 $message->bodytruncated = 0;
24 } else {
25 $message->airsyncbasebody = new SyncAirSyncBaseBody();
26 debugLog("airsyncbasebody!");
27 $message->airsyncbasenativebodytype=1;
28 if (isset($bodypreference[2])) {
29 debugLog("HTML Body");
30 // Send HTML if requested and native type was html
31 $message->airsyncbasebody->type = 2;
32 $html='<html>';
33 $html.='<head>';
34 $html.='<meta name="Generator" content="Z-Push">';
35 $html.='<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
36 $html.='</head>';
37 $html.='<body>';
38 $html.=nl2br($tmpBody);
39 $html.='</body>';
40 $html.='</html>';
41 if (isset($bodypreference[2]["TruncationSize"]) && strlen($html) > $bodypreference[2]["TruncationSize"]) {
42 $html = utf8_truncate($html,$bodypreference[2]["TruncationSize"]);
43 $message->airsyncbasebody->truncated = 1;
44 }
45 $message->airsyncbasebody->data = $html;
46 $message->airsyncbasebody->estimateddatasize = strlen($html);
47 } else {
48 // Send Plaintext as Fallback or if original body is plaintext
49 debugLog("Plaintext Body");
50 $message->airsyncbasebody->type = 1;
51 if(isset($bodypreference[1]["TruncationSize"]) && strlen($tmpBody) > $bodypreference[1]["TruncationSize"]) {
52 $plain = utf8_truncate($tmpBody, $bodypreference[1]["TruncationSize"]);
53 $message->airsyncbasebody->truncated = 1;
54 }
55 $message->airsyncbasebody->estimateddatasize = strlen($tmpBody);
56 $message->airsyncbasebody->data = $tmpBody;
57 }
58 // In case we have nothing for the body, send at least a blank...
59 // dw2412 but only in case the body is not rtf!
60 if ($message->airsyncbasebody->type != 3 && (!isset($message->airsyncbasebody->data) || strlen($message->airsyncbasebody->data) == 0)) {
61 $message->airsyncbasebody->data = " ";
62 $message->airsyncbasebody->estimateddatasize = 1;
63 }
64 }
65 }
66 function convertMessageBody($message) {
67 if (isset($message->airsyncbasebody)) {
68 switch($message->airsyncbasebody->type) {
69 case '3' : $message->rtf = $message->airsyncbasebody->data; break;
70 case '1' : $message->body = $message->airsyncbasebody->data; break;
71 }
72 }
73 if (isset($message->rtf)) {
74 // Nokia MfE 2.9.158 sends contact notes with RTF and Body element.
75 // The RTF is empty, the body contains the note therefore we need to unpack the rtf
76 // to see if it is realy empty and in case not, take the appointment body.
77 $rtf_body = new rtf ();
78 $rtf_body->loadrtf(base64_decode($message->rtf));
79 $rtf_body->output("ascii");
80 $rtf_body->parse();
81 if (isset($message->body) &&
82 isset($rtf_body->out) &&
83 $rtf_body->out == "" && $message->body != "") {
84 unset($message->rtf);
85 }
86 debugLog('iConDir::RTFDATA:' . $message->rtf);
87 $rtf_body = new rtf ();
88 $rtf_body->loadrtf(base64_decode($message->rtf));
89 $rtf_body->output("ascii");
90 $rtf_body->parse();
91 debugLog('iConDir::RTFDATA-parsed:' . $rtf_body->out);
92 //put rtf into body
93 if($rtf_body->out <> "") $message->body=$rtf_body->out;
94 }
95 }
96 class GroupeContact {
97 public $_deviceProperties;
98 public $_syncSettings;
99 public $_mapping = array();
100 function __construct() {
101 global $protocolversion;
102 $this->_mapping=array(
103 array("body",'Notiz'),
104 array("fileas",'Name'),
105 array("companyname",'Firma'),
106 array("firstname",'Vorname'),
107 array("lastname",'Nachname'),
108 array("businesscity",'AOrt'),
109 array("businesscountry",'AProv'),
110 array("businesspostalcode",'APlz'),
111 array("businessstate",'ALand'),
112 array("businessstreet",'AStrasse'),
113 array("businessfaxnumber",array('Fax',0)),
114 array("businessphonenumber",array('ATel',0)),
115 array("business2phonenumber",array('ATel',1)),
116 array("categories",'Categories'),
117 array("email1address",array('Email',0)),
118 array("email2address",array('Email',1)),
119 array("email3address",array('Email',2)),
120 array("homephonenumber",array('PTel',0)),
121 array("home2phonenumber",array('PTel',1)),
122 array("homecity",'POrt'),
123 array("homecountry",'PProv'),
124 array("homepostalcode",'PPlz'),
125 array("homestate",'PLand'),
126 array("homestreet",'PStrasse'),
127 array("homefaxnumber",array('Fax',1)),
128 array("jobtitle",'Beruf'),
129 array("title",'Titel'),
130 //array("middlename",''),
131 array("mobilephonenumber",array('Mobil',0)),
132 array("radiophonenumber",array('Mobil',1)),
133 array("pagernumber",array('Intern',0)),
134 array("carphonenumber",array('Andere',0)),
135 array("webpage",array('Url',0)),
136 );
137 if(isset($protocolversion) && $protocolversion >= 2.5) {
138 $this->_mapping+= array(
139 array("imaddress",'Iptel'),
140 array("governmentid",'Iva'),
141 array("customerid",'Mwst'),
142 array("nickname",'Nickname'),
143 );
144 }
145 }
146 function setDeviceProperties($val) {
147 $this->_deviceProperties=$val;
148 }
149 function setSyncSettings($val) {
150 $this->_syncSettings=$val;
151 }
152 function groupe2message($groupe, $truncsize,$bodypreference=false,$optionbodypreference=false, $mimesupport=0) {
153 debugLog('groupe2contact');
154 $message=new SyncContact();
155 foreach ($this->_mapping as $val) {
156 $msgKey=$val[0];$grpKey=$val[1];
157 switch($msgKey) {
158 case 'body':
159 setMessageBody($message,isset($groupe->$grpKey)?$groupe->$grpKey:'',$bodypreference);
160 break;
161 default:
162 if (is_array($grpKey)) {
163 if (isset($groupe->{$grpKey[0]})) {
164 $tmpData=explode('||',$groupe->{$grpKey[0]});
165 $message->$msgKey=isset($tmpData[$grpKey[1]])?$tmpData[$grpKey[1]]:'';
166 }
167 } else {
168 if (isset($groupe->$grpKey)) {
169 $message->$msgKey=$groupe->$grpKey;
170 }
171 }
172 break;
173 }
174 }
175 //debugLog(print_r($message,1));
176 return $message;
177 }
178 function message2groupe($message,$groupe) {
179 debugLog('contact2groupe');
180 //$message=(array)$message;
181 //debugLog(print_r($message,1));
182 //debugLog(print_r($groupe,1));
183 convertMessageBody($message);
184
185 foreach ($this->_mapping as $val) {
186 $msgKey=$val[0];$grpKey=$val[1];
187 switch($msgKey) {
188 case 'email1address':
189 case 'email2address':
190 case 'email3address':
191 $regs=array();
192 if(isset($message->$msgKey) && preg_match("/.*<(.+)>/", $message->$msgKey, $regs ) ) {
193 $message->$msgKey = $regs[1];
194 }
195 break;
196 }
197 if (is_array($grpKey)) {
198 if (isset($groupe->{$grpKey[0]})) {
199 $tmpData=explode('||',$groupe->{$grpKey[0]});
200 } else {
201 $tmpData=array();
202 }
203 if(isset($message->$msgKey)) {
204 $tmpData[$grpKey[1]]=$message->$msgKey;
205 }
206 $groupe->{$grpKey[0]}=implode('||',$tmpData);
207 } else {
208 $groupe->$grpKey=isset($message->$msgKey)?$message->$msgKey:'';
209 }
210 }
211 //debugLog(print_r($groupe,1));
212 return $groupe;
213 }
214 }
215 class GroupeAppointment {
216 public $_mapping = array();
217 public $_deviceProperties;
218 public $_syncSettings;
219 public $_timeZone =array();
220 function __construct() {
221
222 }
223 function setDeviceProperties($val) {
224 $this->_deviceProperties=$val;
225 }
226 function setSyncSettings($val) {
227 $this->_syncSettings=$val;
228 }
229 function setTimeZone($val) {
230 $this->_timeZone=$val;
231 }
232
233 function groupe2message($groupe, $truncsize,$bodypreference=false,$optionbodypreference=false, $mimesupport=0) {
234 debugLog('groupe2appointment');
235
236 $message=new SyncAppointment();
237 $message->uid=bin2hex($groupe->UID);
238 $message->starttime=$groupe->StartDate;
239 $message->endtime=$groupe->EndDate;
240 $message->subject=$groupe->Title;
241
242 setMessageBody($message,isset($groupe->Text)?$groupe->Text:'',$bodypreference);
243 $message->location=$groupe->Place;
244 $message->categories=$groupe->Categories;
245 if (isset($groupe->OwnerEmail)) $message->organizeremail=$groupe->OwnerEmail;
246 if (isset($groupe->OwnerName)) $message->organizername=$groupe->OwnerName;
247 if (isset($groupe->MyInvitStatus) && $groupe->MyInvitStatus==5) {
248 $message->busystatus=1;
249 } else {
250 $message->busystatus=$groupe->Unsecure?1:2;
251 }
252 $message->alldayevent=($groupe->TimeMode==1?1:0);
253 if ($message->alldayevent && date('His',$message->endtime)=='235959') {
254 $message->endtime+=1;
255 }
256 $message->dtstamp=$groupe->TimeModify;
257 if ($groupe->AlarmTime) $message->reminder=intval($groupe->AlarmTime/60);
258 $message->sensitivity=$groupe->EvtPrivat?2:(($groupe->GrantUsers || $groupe->GrantGroups)?0:1);
259
260
261 if ($groupe->Unsecure && isset($this->_syncSettings['cal/no_status']) && $this->_syncSettings['cal/no_status']) {
262 $message->subject='?'.$message->subject;
263 }
264 if ($groupe->EvtPrivat && isset($this->_syncSettings['cal/no_privat']) && $this->_syncSettings['cal/no_privat']) {
265 $message->subject='#'.$message->subject;
266 }
267
268
269 $tz = $this->_getLocalTZ();
270 $message->timezone = base64_encode($this->_getSyncBlobFromTZ($tz));
271
272 //debugLog(print_r($groupe->Attendees,1));
273 if (!empty($groupe->Attendees)) {
274 foreach ($groupe->Attendees as $val) {
275 $attendee=new SyncAttendee();
276 $attendee->email=$val['Email'];
277 $attendee->name=$val['Name'];
278 $attendee->status=$val['Status'];
279 switch($val['Type']) {
280 case 'u':
281 $attendee->type=1;
282 break;
283 case 'a':
284 $attendee->type=1;
285 break;
286 case 'r':
287 $attendee->type=3;
288 break;
289 }
290 $message->attendees[]=$attendee;
291 }
292 }
293 if ($groupe->RecType && $groupe->RecInt) {
294 $message->recurrence=new SyncRecurrence();
295 $message->recurrence->interval=$groupe->RecInt;
296 $message->recurrence->until=($groupe->RecEnd==-1)?0:$groupe->RecEnd;
297 switch($groupe->RecType) {
298 case 1:
299 $message->recurrence->type=0;
300 break;
301 case 2:
302 $message->recurrence->type=1;
303 $message->recurrence->dayofweek=pow(2,date('w',$groupe->StartDate));
304 break;
305 case 3:
306 $message->recurrence->type=2;
307 $message->recurrence->dayofmonth=date('d',$groupe->StartDate);
308 break;
309 case 5:
310 $message->recurrence->type=5;
311 $message->recurrence->dayofmonth=date('d',$groupe->StartDate);
312 $message->recurrence->monthofyear=date('m',$groupe->StartDate);
313 break;
314 }
315 if (isset($groupe->Exceptions) && !empty($groupe->Exceptions)) {
316 $message->exceptions=array();
317 foreach ($groupe->Exceptions as $val) {
318 $exception=new SyncAppointment();
319 $exception->deleted=1;
320 $exception->exceptionstarttime=$val['ExceptionDate'];
321 $message->exceptions[]=$exception;
322 }
323 }
324 }
325 //debugLog(print_r($message,1));
326 return $message;
327 }
328
329 /*
330 [RecType] => 2
331 [RecInt] => 1
332 [RecCfg] =>
333 [RecEnd] => -1
334 [Exception] =>
335
336 [NoOwner] => 1
337 */
338
339 function message2groupe($message,$groupe) {
340 //global $user;
341 debugLog('appointment2groupe');
342 //debugLog(print_r($message,1));
343 convertMessageBody($message);
344
345 if(isset($message->timezone)) {
346 $binData=base64_decode($message->timezone);
347 $tz = $this->_getTZFromSyncBlob($binData);
348 } else {
349 $tz = false;
350 }
351 if (isset($message->uid) && trim($message->uid)) $groupe->UID=base64_encode(hex2bin(preg_replace('/[^0-9a-f]/i','',$message->uid)));
352 //debugLog('h2b'.preg_replace('/[^0-9a-f]/i','',$message->uid));
353
354 if (isset($message->alldayevent) && $message->alldayevent) {
355 if (date('His',$message->endtime)=='000000' && date('d',$message->endtime)!=date('d',$message->starttime)) $message->endtime-=1;
356 }
357 $groupe->StartDate=$message->starttime;
358 $groupe->EndDate=$message->endtime;
359
360
361 $groupe->Text=isset($message->body)?$message->body:'';
362 $groupe->Place=isset($message->location)?$message->location:'';
363 $groupe->Categories=isset($message->categories)?$message->categories:array();
364 /*$groupe->OwnerEmail=$message->organizeremail;
365 $groupe->OwnerName=$message->organizername;*/
366 $groupe->TimeMode=(isset($message->alldayevent) && $message->alldayevent)?1:0;
367 $groupe->AlarmTime=isset($message->reminder)?$message->reminder*60:0;
368
369 if (isset($this->_syncSettings['cal/no_status']) && $this->_syncSettings['cal/no_status']) {
370 $groupe->Unsecure=0;
371 } else {
372 $groupe->Unsecure=(isset($message->busystatus) && $message->busystatus==1)?1:0;
373 }
374 if (isset($this->_syncSettings['cal/no_privat']) && $this->_syncSettings['cal/no_privat']) {
375 debugLog('NoPrivateSupport');
376 $groupe->EvtPrivat=0;
377 $groupe->_setDefaultGrant=1;
378 } else {
379 if (!isset($message->sensitivity)) $message->sensitivity=0;
380 debugLog('Sensitivity:'.$message->sensitivity);
381 if (isset($message->sensitivity) && in_array($message->sensitivity,array(2,3))) {
382 $groupe->EvtPrivat=1;
383 debugLog('SetPrivate:'.$message->sensitivity);
384 } else {
385 $groupe->EvtPrivat=0;
386 }
387 if (in_array($message->sensitivity,array(0,1,2))) {
388 $groupe->_setDefaultGrant=1;
389 debugLog('SetDefaultGrant:'.$message->sensitivity);
390 } else {
391 $groupe->_setDefaultGrant=0;
392 }
393 }
394
395 $testTitle=trim($message->subject);
396 do {
397 $check=false;
398 if (substr($testTitle,0,1)=='#') {
399 $testTitle=substr($testTitle,1);
400 $groupe->EvtPrivat=1;
401 debugLog('SetPrivate:FromTitle');
402 $check=true;
403 }
404 if (substr($testTitle,0,1)=='?') {
405 $testTitle=substr($testTitle,1);
406 $groupe->Unsecure=1;
407 debugLog('SetUnsure:FromTitle');
408 $check=true;
409 }
410 } while ($check);
411 $groupe->Title=trim($testTitle);
412
413 $groupe->Attendees=array();
414 if (!empty($message->attendees)) {
415 foreach ($message->attendees as $val) {
416 if (!trim($val->email)) continue;
417 $groupe->Attendees[]=array(
418 'Email'=>$val->email,
419 'Name'=>trim($val->name),
420 'Status'=>isset($val->status)?$val->status:0,
421 'Type'=>(isset($val->type) && $val->type==3)?'r':'',
422 );
423 }
424 }
425 $groupe->Exceptions=array();
426 $groupe->RecType=0;
427 $groupe->RecInt=0;
428 if (isset($message->recurrence)) {
429 $badRecur=false;
430 switch($message->recurrence->type) {
431 case 0:
432 $groupe->RecType=1;
433 break;
434 case 1:
435 $groupe->RecType=2;
436 //$message->recurrence->dayofweek=pow(2,date('w',$groupe->StartDate));
437 break;
438 case 2:
439 $groupe->RecType=3;
440 //$message->recurrence->dayofmonth=date('d',$groupe->StartDate);
441 break;
442 case 5:
443 $groupe->RecType=5;
444 //$message->recurrence->dayofmonth=date('d',$groupe->StartDate);
445 //$message->recurrence->monthofyear=date('m',$groupe->StartDate);
446 break;
447 default:
448 $badRecur=true;
449 break;
450 }
451 if (!$badRecur) {
452 if (isset($message->recurrence->interval) && $message->recurrence->interval) {
453 $groupe->RecInt=$message->recurrence->interval;
454 } else {
455 $groupe->RecInt=1;
456 }
457 if (isset($message->recurrence->until) && $message->recurrence->until) {
458 $groupe->RecEnd=($message->recurrence->until>=2147385000)?-1:$message->recurrence->until;
459 } else {
460 $groupe->RecEnd=-1;
461 if (isset($message->recurrence->occurrences) && $message->recurrence->occurrences) {
462 $recCount=$message->recurrence->occurrences-1;
463 $year=date('Y',$groupe->StartDate);
464 $month=date('m',$groupe->StartDate);
465 $day=date('d',$groupe->StartDate);
466 switch ($groupe->RecType) {
467 case 1:
468 $groupe->RecEnd=mktime(23,59,59,$month,$day+$groupe->RecInt*$recCount,$year);
469 break;
470 case 2:
471 $groupe->RecEnd=mktime(23,59,59,$month,$day+$groupe->RecInt*7*$recCount,$year);
472 break;
473 case 3:
474 $groupe->RecEnd=mktime(23,59,59,$month+$groupe->RecInt*$recCount,$day,$year);
475 break;
476 case 5:
477 $groupe->RecEnd=mktime(23,59,59,$month,$day,$year+$groupe->RecInt*$recCount);
478 break;
479 }
480 }
481 }
482
483 if (isset($message->exceptions) && !empty($message->exceptions)) {
484 foreach ($message->exceptions as $val) {
485 $exception=array(
486 'Deleted'=>$val->deleted,
487 'ExceptionDate'=>$val->exceptionstarttime,
488 );
489 if (!$val->deleted) {
490 if (isset($val->subject)) $exception['Title']=$val->subject;
491 if (isset($val->body)) $exception['Text']=$val->body;
492 if (isset($val->location)) $exception['Place']=$val->location;
493 if (isset($val->starttime)) $exception['StartDate']=$val->starttime;
494 if (isset($val->endtime)) $exception['EndDate']=$val->endtime;
495 if (isset($val->reminder)) $exception['AlarmTime']=$val->reminder*60;
496 if (isset($val->alldayevent)) $exception['TimeMode']=$val->alldayevent?1:0;
497 if (isset($val->busystatus)) $exception['Unsecure']=$val->busystatus==1?1:0;
498 }
499 $groupe->Exceptions[]=$exception;
500 }
501 }
502 } else {
503 $groupe->RecType=0;
504 }
505 }
506
507 //debugLog(print_r($groupe,1));
508 return $groupe;
509
510 //nokia sends an yearly event with 0 mins duration but as all day event,
511 //so make it end next day
512 /*if ($message->starttime == $message->endtime && isset($message->alldayevent) && $message->alldayevent) {
513 $message->endtime = $message->starttime + 24 * 60 * 60;
514 }*/
515
516 //debugLog(print_r($message,1));
517
518 //return $groupe;
519 }
520
521 // Unpack timezone info from Sync
522 function _getTZFromSyncBlob($data) {
523 $tz = unpack("lbias/a64name/vdstendyear/vdstendmonth/vdstendday/vdstendweek/vdstendhour/vdstendminute/vdstendsecond/vdstendmillis/" .
524 "lstdbias/a64name/vdststartyear/vdststartmonth/vdststartday/vdststartweek/vdststarthour/vdststartminute/vdststartsecond/vdststartmillis/" .
525 "ldstbias", $data);
526 // Make the structure compatible with class.recurrence.php
527 $tz["timezone"] = $tz["bias"];
528 $tz["timezonedst"] = $tz["dstbias"];
529 return $tz;
530 }
531
532 // Pack timezone info for Sync
533 function _getSyncBlobFromTZ($tz) {
534 $packed = pack("la64vvvvvvvv" . "la64vvvvvvvv" . "l",
535 $tz["bias"], "", 0, $tz["dstendmonth"], $tz["dstendday"], $tz["dstendweek"], $tz["dstendhour"], $tz["dstendminute"], $tz["dstendsecond"], $tz["dstendmillis"],
536 $tz["stdbias"], "", 0, $tz["dststartmonth"], $tz["dststartday"], $tz["dststartweek"], $tz["dststarthour"], $tz["dststartminute"], $tz["dststartsecond"], $tz["dststartmillis"],
537 $tz["dstbias"]);
538
539 return $packed;
540 }
541
542 // Checks the date to see if it is in DST, and returns correct GMT date accordingly
543 function _getGMTTimeByTZ($localtime, $tz) {
544 if(!isset($tz) || !is_array($tz))
545 return $localtime;
546
547 if($this->_isDST($localtime, $tz))
548 return $localtime + $tz["bias"]*60 + $tz["dstbias"]*60;
549 else
550 return $localtime + $tz["bias"]*60;
551 }
552
553 // Returns the local time for the given GMT time, taking account of the given timezone
554 function _getLocaltimeByTZ($gmttime, $tz) {
555 if(!isset($tz) || !is_array($tz))
556 return $gmttime;
557
558 if($this->_isDST($gmttime - $tz["bias"]*60, $tz)) // may bug around the switch time because it may have to be 'gmttime - bias - dstbias'
559 return $gmttime - $tz["bias"]*60 - $tz["dstbias"]*60;
560 else
561 return $gmttime - $tz["bias"]*60;
562 }
563
564 // Returns TRUE if it is the summer and therefore DST is in effect
565 function _isDST($localtime, $tz) {
566 if(!isset($tz) || !is_array($tz))
567 return false;
568
569 $year = gmdate("Y", $localtime);
570 $start = $this->_getTimestampOfWeek($year, $tz["dststartmonth"], $tz["dststartweek"], $tz["dststartday"], $tz["dststarthour"], $tz["dststartminute"], $tz["dststartsecond"]);
571 $end = $this->_getTimestampOfWeek($year, $tz["dstendmonth"], $tz["dstendweek"], $tz["dstendday"], $tz["dstendhour"], $tz["dstendminute"], $tz["dstendsecond"]);
572
573 if($start < $end) {
574 // northern hemisphere (july = dst)
575 if($localtime >= $start && $localtime < $end)
576 $dst = true;
577 else
578 $dst = false;
579 } else {
580 // southern hemisphere (january = dst)
581 if($localtime >= $end && $localtime < $start)
582 $dst = false;
583 else
584 $dst = true;
585 }
586
587 return $dst;
588 }
589 function _getGMTTZ() {
590 $tz = array(
591 "bias" => 0,
592 "stdbias" => 0,
593 "dstbias" => 0,
594 "dstendyear" => 0,
595 "dstendmonth" =>0,
596 "dstendday" =>0,
597 "dstendweek" => 0,
598 "dstendhour" => 0,
599 "dstendminute" => 0,
600 "dstendsecond" => 0,
601 "dstendmillis" => 0,
602 "dststartyear" => 0,
603 "dststartmonth" =>0,
604 "dststartday" =>0,
605 "dststartweek" => 0,
606 "dststarthour" => 0,
607 "dststartminute" => 0,
608 "dststartsecond" => 0,
609 "dststartmillis" => 0
610 );
611 return $tz;
612 }
613 function _getLocalTZ() {
614 if (is_array($this->_timeZone) && !empty($this->_timeZone)) {
615 return $this->_timeZone;
616 } else {
617 return $this->_getGMTTZ();
618 }
619 }
620 // Returns the local timestamp for the $week'th $wday of $month in $year at $hour:$minute:$second
621 function _getTimestampOfWeek($year, $month, $week, $wday, $hour, $minute, $second)
622 {
623 $date = gmmktime($hour, $minute, $second, $month, 1, $year);
624
625 // Find first day in month which matches day of the week
626 while(1) {
627 $wdaynow = gmdate("w", $date);
628 if($wdaynow == $wday)
629 break;
630 $date += 24 * 60 * 60;
631 }
632
633 // Forward $week weeks (may 'overflow' into the next month)
634 $date = $date + $week * (24 * 60 * 60 * 7);
635
636 // Reverse 'overflow'. Eg week '10' will always be the last week of the month in which the
637 // specified weekday exists
638 while(1) {
639 $monthnow = gmdate("n", $date) - 1; // gmdate returns 1-12
640 if($monthnow > $month)
641 $date = $date - (24 * 7 * 60 * 60);
642 else
643 break;
644 }
645
646 return $date;
647 }
648
649 // Normalize the given timestamp to the start of the day
650 function _getDayStartOfTimestamp($timestamp) {
651 return $timestamp - ($timestamp % (60 * 60 * 24));
652 }
653
654
655
656 }
657 class GroupeTask {
658 public $_mapping = array();
659 public $_deviceProperties;
660 public $_syncSettings;
661 function __construct() {
662
663 }
664 function setDeviceProperties($val) {
665 $this->_deviceProperties=$val;
666 }
667 function setSyncSettings($val) {
668 $this->_syncSettings=$val;
669 }
670 function groupe2message($groupe, $truncsize,$bodypreference=false,$optionbodypreference=false, $mimesupport=0) {
671
672 debugLog('groupe2task');
673 //"meetingstatus"
674
675
676 /*
677 var $utcduedate;
678 var $utcstartdate;
679
680 var $recurrence;
681 var $regenerate;
682 var $deadoccur;*/
683
684
685 $message=new SyncTask();
686 setMessageBody($message,isset($groupe->Text)?$groupe->Text:'',$bodypreference);
687 $message->subject=$groupe->Title;
688 $message->categories=$groupe->Categories;
689
690
691 $message->utcstartdate=$groupe->StartDate;
692 $message->utcduedate=$groupe->EndDate;
693 $message->startdate=$groupe->StartDate+date('Z');
694 $message->duedate=$groupe->EndDate+date('Z');
695 //debugLog('StartDate:'.date('d.m.Y H:i',$message->startdate));
696
697 switch($groupe->Priority) {
698 case 0:
699 $message->importance=2;
700 break;
701 case 1:
702 $message->importance=1;
703 break;
704 case 2:
705 $message->importance=0;
706 break;
707 }
708 if ($groupe->UserDone==4 || $groupe->Status==4) {
709 $message->complete=1;
710 $message->datecompleted=$groupe->StatusDate;
711 } else {
712 $message->complete=0;
713 }
714 if ($groupe->Alarm) {
715 $message->reminderset=0;
716 $message->remindertime=$groupe->EndDate-$groupe->Alarm*3600*38;
717 }
718 switch($groupe->UserTaskType) {
719 case 't':
720 $message->sensitivity=0;
721 break;
722 case 'd':
723 $message->sensitivity=0;
724 break;
725 case 'p':
726 $message->sensitivity=2;
727 break;
728 case 'o':
729 $message->sensitivity=2;
730 break;
731 }
732
733
734 if ($groupe->RecType && $groupe->RecInt) {
735 $message->recurrence=new SyncTaskRecurrence();
736 $message->recurrence->start=$message->startdate;
737 $message->recurrence->interval=$groupe->RecInt;
738 //$message->recurrence->regenerate=1;
739 if ($groupe->RecDate!=-1) $message->recurrence->until=$groupe->RecDate;
740 switch($groupe->RecType) {
741 case 1:
742 $message->recurrence->type=0;
743 break;
744 case 2:
745 $message->recurrence->type=1;
746 $message->recurrence->dayofweek=pow(2,date('w',$groupe->StartDate));
747 break;
748 case 3:
749 $message->recurrence->type=2;
750 $message->recurrence->dayofmonth=date('d',$groupe->StartDate);
751 break;
752 case 5:
753 $message->recurrence->type=5;
754 $message->recurrence->dayofmonth=date('d',$groupe->StartDate);
755 $message->recurrence->monthofyear=date('m',$groupe->StartDate);
756 break;
757 }
758 }
759 //debugLog(print_r($message,1));
760 return $message;
761 }
762 function message2groupe($message,$groupe) {
763 //global $user;
764 debugLog('task2groupe');
765
766 convertMessageBody($message);
767
768 //debugLog(print_r($message,1));
769
770 if (!isset($message->utcstartdate) || !$message->utcstartdate) {
771 $groupe->StartDate=mktime(0,0,0);
772 } else {
773 $groupe->StartDate=$message->utcstartdate;
774 }
775 if (!isset($message->utcduedate) || !$message->utcduedate) {
776 $groupe->EndDate=$groupe->StartDate;
777 } else {
778 $groupe->EndDate=$message->utcduedate;
779 }
780 $groupe->Title=$message->subject;
781 $groupe->Text=isset($message->body)?$message->body:'';
782 $groupe->Categories=isset($message->categories)?$message->categories:array();
783
784 switch($message->importance) {
785 case 0:
786 $groupe->Priority=2;
787 break;
788 case 1:
789 $groupe->Priority=1;
790 break;
791 case 2:
792 $groupe->Priority=0;
793 break;
794 }
795 if ($message->complete) {
796 $groupe->UserDone=4;
797 //$groupe->UserDone=4;
798 } else {
799 $groupe->UserDone=1;
800 }
801 if (isset($message->remindertime) && $message->remindertime) {
802 $groupe->Alarm=floor(($message->duedate-$message->remindertime)/3600/24);
803 } else {
804 $groupe->Alarm=0;
805 }
806
807 $groupe->RecType=0;
808 $groupe->RecInt=0;
809 if (isset($message->recurrence)) {
810 $badRecur=false;
811 switch($message->recurrence->type) {
812 case 0:
813 $groupe->RecType=1;
814 break;
815 case 1:
816 $groupe->RecType=2;
817 //$message->recurrence->dayofweek=pow(2,date('w',$groupe->StartDate));
818 break;
819 case 2:
820 $groupe->RecType=3;
821 //$message->recurrence->dayofmonth=date('d',$groupe->StartDate);
822 break;
823 case 5:
824 $groupe->RecType=5;
825 //$message->recurrence->dayofmonth=date('d',$groupe->StartDate);
826 //$message->recurrence->monthofyear=date('m',$groupe->StartDate);
827 break;
828 default:
829 $badRecur=true;
830 break;
831 }
832 if (!$badRecur) {
833 if (isset($message->recurrence->interval) && $message->recurrence->interval) {
834 $groupe->RecInt=$message->recurrence->interval;
835 } else {
836 $groupe->RecInt=0;
837 }
838 if (isset($message->recurrence->until) && $message->recurrence->until) {
839 $groupe->RecDate=$message->recurrence->until;
840 } else {
841 $groupe->RecDate=-1;
842 if (isset($message->recurrence->occurrences) && $message->recurrence->occurrences) {
843 $recCount=$message->recurrence->occurrences-1;
844 $year=date('Y',$groupe->StartDate);
845 $month=date('m',$groupe->StartDate);
846 $day=date('d',$groupe->StartDate);
847 switch ($groupe->RecType) {
848 case 1:
849 $groupe->RecDate=mktime(23,59,59,$month,$day+$groupe->RecInt*$recCount,$year);
850 break;
851 case 2:
852 $groupe->RecDate=mktime(23,59,59,$month,$day+$groupe->RecInt*7*$recCount,$year);
853 break;
854 case 3:
855 $groupe->RecDate=mktime(23,59,59,$month+$groupe->RecInt*$recCount,$day,$year);
856 break;
857 case 5:
858 $groupe->RecDate=mktime(23,59,59,$month,$day,$year+$groupe->RecInt*$recCount);
859 break;
860 }
861 }
862 }
863 } else {
864 $groupe->RecType=0;
865 }
866 }
867 //debugLog(print_r($groupe,1));
868 return $groupe;
869 }
870
871 }
872 class GroupeMail {
873 public $_mapping = array();
874 public $_deviceProperties;
875 public $_syncSettings;
876 function __construct() {
877
878 }
879 function setDeviceProperties($val) {
880 $this->_deviceProperties=$val;
881 }
882 function setSyncSettings($val) {
883 $this->_syncSettings=$val;
884 }
885 function getBodyPreferenceBestMatch($bodypreference) {
886 // The best choice is RTF, then HTML and then MIME in order to save bandwidth
887 // because MIME is a complete message including the headers and attachments
888 //if (isset($bodypreference[3])) return 'RTF';
889 if (isset($bodypreference[2])) return 'HTML';
890 if (isset($bodypreference[4])) return 'MIME';
891 return 'PLAIN';
892 }
893 function groupe2message($groupe, $truncsize,$bodypreference=false,$optionbodypreference=false, $mimesupport=0) {
894 debugLog('groupe2mail: truncsize:'.$truncsize.' bodypreference:'.print_r($bodypreference,1).' optionbodypreference:'.print_r($optionbodypreference,1).' mimesupport:'.$mimesupport);
895 //debugLog(print_r($this->_syncSettings,1));
896
897 $mail=array(
898 base64_decode($groupe->MimeHeader),
899 base64_decode($groupe->MimeBody),
900 );
901 $mobj = new Mail_mimeDecode($mail);
902 debugLog("RAW Message ".substr($mail[0],0,200));
903 $message = $mobj->decode(array('decode_headers' => true, 'decode_bodies' => true, 'include_bodies' => true, 'crlf' => "\n", 'charset' => BACKEND_CHARSET));
904 //debugLog("RAW Message ".print_r($message,true));
905 $output = new SyncMail();
906
907 // start AS12 Stuff (bodypreference === false) case = old behaviour
908 if ($bodypreference===false) {
909 $body = BackendGroupe::getBody($message);
910 $body = str_replace("\n","\r\n", str_replace("\r","",$body));
911 $output->bodysize = strlen($body);
912 if (!$truncsize) $truncsize=MAX_EMBEDDED_SIZE;
913 if(strlen($body) > $truncsize) {
914 $body = utf8_truncate($body, $truncsize);
915 $output->bodytruncated = 1;
916 } else {
917 $body = $body;
918 $output->bodytruncated = 0;
919 }
920 $output->body = $body;
921 } else {
922 if ($mimesupport==0 && isset($bodypreference[4])) {
923 unset($bodypreference[4]);
924 debugLog('Remove mime body preference type because the device required no mime support');
925 }
926 $mailType = $this->getBodyPreferenceBestMatch($bodypreference);
927
928 if (isset($bodypreference[1]) && !isset($bodypreference[1]["TruncationSize"]))
929 $bodypreference[1]["TruncationSize"] = MAX_EMBEDDED_SIZE;
930 if (isset($bodypreference[2]) && !isset($bodypreference[2]["TruncationSize"]))
931 $bodypreference[2]["TruncationSize"] = MAX_EMBEDDED_SIZE;
932 if (isset($bodypreference[3]) && !isset($bodypreference[3]["TruncationSize"]))
933 $bodypreference[3]["TruncationSize"] = MAX_EMBEDDED_SIZE;
934 if (isset($bodypreference[4]) && !isset($bodypreference[4]["TruncationSize"]))
935 $bodypreference[4]["TruncationSize"] = MAX_EMBEDDED_SIZE;
936 $output->airsyncbasebody = new SyncAirSyncBaseBody();
937 debugLog("airsyncbasebody!");
938 $body="";
939 BackendGroupe::getBodyRecursive($message, "html", $body);
940 if ($body != "") {
941 $output->airsyncbasenativebodytype=2;
942 } else {
943 $output->airsyncbasenativebodytype=1;
944 BackendGroupe::getBodyRecursive($message, "plain", $body);
945 }
946 $body = str_replace("\n","\r\n", str_replace("\r","",$body));
947 if ($mailType=='MIME') {
948 debugLog("MIME Body");
949 $output->airsyncbasebody->type = 4;
950 $rawmessage = $mobj->decode(array('decode_headers' => false, 'decode_bodies' => true, 'include_bodies' => true, 'crlf' => "\n", 'charset' => BACKEND_CHARSET));
951 $body = "";
952 foreach($rawmessage->headers as $key=>$value) {
953 if ($key != "content-type" && $key != "mime-version" && $key != "content-transfer-encoding" &&
954 !is_array($value)) {
955 $body .= $key.":";
956 $tokens = explode(" ",trim($value));
957 $line = "";
958 foreach($tokens as $valu) {
959 if ((strlen($line)+strlen($valu)+2) > 60) {
960 $line .= "\n";
961 $body .= $line;
962 $line = " ".$valu;
963 } else {
964 $line .= " ".$valu;
965 }
966 }
967 $body .= $line."\n";
968 }
969 }
970 unset($rawmessage);
971 $mimemsg = new Mail_mime(array( 'head_encoding' => 'quoted-printable',
972 'text_encoding' => 'quoted-printable',
973 'html_encoding' => 'base64',
974 'head_charset' => 'utf-8',
975 'text_charset' => 'utf-8',
976 'html_charset' => 'utf-8',
977 'eol' => "\n",
978 'delay_file_io' => false,
979 )
980 );
981 BackendGroupe::GetAttachmentsRecursive($message,$mimemsg);
982 if ($output->airsyncbasenativebodytype==1) {
983 BackendGroupe::getBodyRecursive($message, "plain", $plain);
984 BackendGroupe::getBodyRecursive($message, "html", $html);
985 if ($html == "") {
986 BackendGroupe::getBodyRecursive($message, "plain", $html);
987 }
988 if ($html == "" && $plain == "" && strlen($mobj->_body) != "") {
989 // debugLog("mobj->_body = ".$mobj->_body);
990 // $plain = $html = $mobj->_quotedPrintableDecode($mobj->_body);
991 $body .= "Content-Type:".$message->headers['content-type']."\r\n";
992 $body .= "Content-Transfer-Encoding:".$message->headers['content-transfer-encoding']."\r\n";
993 $body .= "\n\n".$mobj->_body;
994 $output->airsyncbasebody->data = $body;
995 }
996 $mimemsg->setTXTBody(str_replace("\n","\r\n", str_replace("\r","",w2u($plain))));
997 $html = '<html>'.
998 '<head>'.
999 '<meta name="Generator" content="Z-Push">'.
1000 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'.
1001 '</head>'.
1002 '<body>'.
1003 str_replace("\n","<BR>",str_replace("\r","", str_replace("\r\n","<BR>",w2u($html)))).
1004 '</body>'.
1005 '</html>';
1006 $mimemsg->setHTMLBody(str_replace("\n","\r\n", str_replace("\r","",$html)));
1007 }
1008 if ($output->airsyncbasenativebodytype==2) {
1009 BackendGroupe::getBodyRecursive($message, "plain", $plain);
1010 if ($plain == "") {
1011 BackendGroupe::getBodyRecursive($message, "html", $plain);
1012 // remove css-style tags
1013 $plain = preg_replace("/<style.*?<\/style>/is", "", $plain);
1014 // remove all other html
1015 $plain = preg_replace("/<br.*>/is","<br>",$plain);
1016 $plain = preg_replace("/<br >/is","<br>",$plain);
1017 $plain = preg_replace("/<br\/>/is","<br>",$plain);
1018 $plain = str_replace("<br>","\r\n",$plain);
1019 $plain = strip_tags($plain);
1020 }
1021 $mimemsg->setTXTBody(str_replace("\n","\r\n", str_replace("\r","",w2u($plain))));
1022 BackendGroupe::getBodyRecursive($message, "html", $html);
1023 $mimemsg->setHTMLBody(str_replace("\n","\r\n", str_replace("\r","",w2u($html))));
1024 }
1025 if (!isset($output->airsyncbasebody->data))
1026 $output->airsyncbasebody->data = $body.$mimemsg->txtheaders()."\n\n".$mimemsg->get();
1027 $output->airsyncbasebody->estimateddatasize = strlen($output->airsyncbasebody->data);
1028 } elseif ($mailType=='HTML') {
1029 debugLog("HTML Body");
1030 // Send HTML if requested and native type was html
1031 $output->airsyncbasebody->type = 2;
1032 BackendGroupe::getBodyRecursive($message, "plain", $plain);
1033 BackendGroupe::getBodyRecursive($message, "html", $html);
1034 if ($html == "") {
1035 BackendGroupe::getBodyRecursive($message, "plain", $html);
1036 }
1037 if ($html == "" && $plain == "" && strlen($mobj->_body) > 0) {
1038 $plain = $html = $mobj->_quotedPrintableDecode($mobj->_body);
1039 }
1040 //debugLog(print_r($html,1));
1041 if ($output->airsyncbasenativebodytype==2) {
1042 $html = w2u($html);
1043 } else {
1044 $html = '<html>'.
1045 '<head>'.
1046 '<meta name="Generator" content="Z-Push">'.
1047 '<meta http-equiv="Content-Type" content="text/html; charset=utf-8">'.
1048 '</head>'.
1049 '<body>'.
1050 str_replace("\n","<BR>",str_replace("\r","<BR>", str_replace("\r\n","<BR>",w2u($plain)))).
1051 '</body>'.
1052 '</html>';
1053 }
1054 if(isset($bodypreference[2]["TruncationSize"]) &&
1055 strlen($html) > $bodypreference[2]["TruncationSize"]) {
1056 $html = utf8_truncate($html,$bodypreference[2]["TruncationSize"]);
1057 $output->airsyncbasebody->truncated = 1;
1058 }
1059 $output->airsyncbasebody->data = $html;
1060 $output->airsyncbasebody->estimateddatasize = strlen($html);
1061 } else {
1062 // Send Plaintext as Fallback or if original body is plaintext
1063 debugLog("Plaintext Body");
1064 BackendGroupe::getBodyRecursive($message, "plain", $plain);
1065 if ($plain == "" && strlen($mobj->_body) > 0) {
1066 // $plain = $mobj->_quotedPrintableDecode($mobj->_body);
1067 $plain="";
1068 }
1069 $plain = w2u(str_replace("\n","\r\n",str_replace("\r","",$plain)));
1070 $output->airsyncbasebody->type = 1;
1071 if(isset($bodypreference[1]["TruncationSize"]) &&
1072 strlen($plain) > $bodypreference[1]["TruncationSize"]) {
1073 $plain = utf8_truncate($plain, $bodypreference[1]["TruncationSize"]);
1074 $output->airsyncbasebody->truncated = 1;
1075 }
1076 $output->airsyncbasebody->estimateddatasize = strlen($plain);
1077 $output->airsyncbasebody->data = $plain;
1078 }
1079 // In case we have nothing for the body, send at least a blank...
1080 // dw2412 but only in case the body is not rtf!
1081 if ($output->airsyncbasebody->type != 3 && (!isset($output->airsyncbasebody->data) || strlen($output->airsyncbasebody->data) == 0))
1082 $output->airsyncbasebody->data = " ";
1083 }
1084 // end AS12 Stuff
1085 // small dirty correction for (i.e. Tobit David) since it has the opinion the UTC Timezone abbreviation is UT :-(
1086 $output->datereceived = isset($message->headers["date"]) ? strtotime($message->headers["date"].(substr($message->headers["date"],-3)==" UT" ? "C" : "")) : null;
1087 $output->displayto = isset($message->headers["to"]) ? trim(w2u($message->headers["to"])) : null;
1088 $output->importance = isset($message->headers["x-priority"]) ? preg_replace("/\D+/", "", $message->headers["x-priority"]) : null;
1089 $output->messageclass = "IPM.Note";
1090 if (strtolower($message->ctype_primary) == "multipart") {
1091 switch(strtolower($message->ctype_secondary)) {
1092 case 'signed' :
1093 $output->messageclass = "IPM.Note.SMIME.MultipartSigned"; break;
1094 default :
1095 $output->messageclass = "IPM.Note";
1096 }
1097 }
1098 if (isset($message->headers["subject"])) {
1099 if (is_array($message->headers["subject"])) $message->headers["subject"]=$message->headers["subject"][0];
1100 $output->subject = trim(w2u($message->headers["subject"]));
1101 } else {
1102 $output->subject = "";
1103 }
1104 $output->read =$groupe->New?0:1;
1105 $output->to = isset($message->headers["to"]) ? trim(w2u($message->headers["to"])) : null;
1106 $output->cc = isset($message->headers["cc"]) ? trim(w2u($message->headers["cc"])) : null;
1107 $output->from = isset($message->headers["from"]) ? trim(w2u($message->headers["from"])) : null;
1108 $output->reply_to = isset($message->headers["reply-to"]) ? trim(w2u($message->headers["reply-to"])) : null;
1109 // start AS12 Stuff
1110 $output->poommailflag = new SyncPoommailFlag();
1111 $output->poommailflag->flagstatus = 0;
1112 $output->internetcpid = 65001;
1113 $output->contentclass="urn:content-classes:message";
1114 // end AS12 Stuff
1115 if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) {
1116 BackendGroupe::setAttachmentsRecursive($groupe->box . ":" . $groupe->id,$message,$output);
1117 }
1118 // unset mimedecoder & mail
1119 unset($mobj);
1120 unset($mail);
1121 unset($message);
1122 //debugLog('groupe2mail:'.print_r($output,1));
1123 return $output;
1124 }
1125 function message2groupe($message,$groupe) {
1126 //debugLog(print_r($groupe,1));
1127 return $groupe;
1128 }
1129
1130 }
1131
1132 class BackendGroupe extends BackendDiff {
1133 public $_user;
1134 public $_devid;
1135 public $_protocolversion;
1136 public $_GroupeFolders=array("VIRTUAL/calendar","VIRTUAL/contacts","VIRTUAL/tasks");
1137 public $_deviceProperties=array();
1138 public $_syncSettings=array();
1139 public $_statMessages=array();
1140 public $_soap;
1141 public $_messages;
1142 public $_mailLimit=100;
1143
1144 public function __construct() {
1145 $this->_soap=new GroupeSoapClient();
1146 $this->_map['contact']=new GroupeContact();
1147 $this->_map['appointment']=new GroupeAppointment();
1148 $this->_map['task']=new GroupeTask();
1149 $this->_map['mail']=new GroupeMail();
1150 if (defined('GROUP_MAIL_LIMIT')) {
1151 $this->_mailLimit=GROUP_MAIL_LIMIT;
1152 }
1153 }
1154
1155 function Logon($username, $domain, $password) {
1156 $this->_wasteID = false;
1157 $this->_soap->initUser($username,$password);
1158 if ($this->_soap->call('logon')) {
1159 debugLog('Groupe::'.$username.' logged in');
1160 $this->_importedFolders = array();
1161 $this->_loggedin = TRUE;
1162 return true;
1163 } else {
1164 debugLog('Groupe::Logon('.$username.','.$domain.',****) failed!!');
1165 return false;
1166 }
1167 }
1168 // completing protocol
1169 function Logoff() {
1170 global $cmd;
1171 debugLog('Groupe::Logoff / cmd:'.$cmd);
1172 //do not update last sync time on ping and provision
1173 if (isset($cmd) && $cmd != '' && $cmd != 'Ping' && $cmd != 'Provision' ) {
1174 $this->setLastSyncTime();
1175 debugLog('Groupe::FolderChanges:'.print_r($this->_importedFolders,1));
1176 foreach($this->_importedFolders as $folderid=>$changes) {
1177 //debugLog('Groupe::FolderStatus:'.$folderid);
1178 }
1179 $this->_loggedin = FALSE;
1180
1181 }
1182 return true;
1183 }
1184 function Setup($user, $devid, $protocolversion) {
1185 debugLog('Groupe::Setup('.$user.','.$devid.','.$protocolversion.')');
1186 $this->_user = $user;
1187 $this->_devid = $devid;
1188 $this->_protocolversion = $protocolversion;
1189 if ($this->_devid) {
1190 $this->_deviceProperties=$this->getDeviceProperties($this->_devid);
1191 $this->_syncSettings=$this->getSyncSettings($this->_devid);
1192
1193 //$this->_mailProperties=$this->_soap->call('getActiveSyncMailPoperties',array());
1194 //debugLog(print_r($this->_mailProperties,true));
1195
1196 $this->_map['contact']->setDeviceProperties($this->_deviceProperties);
1197 $this->_map['contact']->setSyncSettings($this->_syncSettings);
1198
1199 $this->_map['appointment']->setDeviceProperties($this->_deviceProperties);
1200 $this->_map['appointment']->setSyncSettings($this->_syncSettings);
1201 $this->_map['appointment']->setTimeZone($this->_soap->call('getActiveSyncTimeZone',array()));
1202
1203 $this->_map['task']->setDeviceProperties($this->_deviceProperties);
1204 $this->_map['task']->setSyncSettings($this->_syncSettings);
1205
1206 $this->_map['mail']->setDeviceProperties($this->_deviceProperties);
1207 $this->_map['mail']->setSyncSettings($this->_syncSettings);
1208 }
1209 return true;
1210 }
1211 function getDeviceProperties($devid) {
1212 $soapResult=$this->_soap->call('getActiveSyncDevicePoperties',array($devid));
1213 if (!$soapResult) {
1214 $deviceProperties=array(
1215 'Type'=>$_REQUEST["DeviceType"],
1216 'Agent'=>$_SERVER["HTTP_USER_AGENT"],
1217 'LastSync'=>0,
1218 );
1219 $this->_soap->call('setActiveSyncDevicePoperties',array($devid,(object)$this->_deviceProperties));
1220 } else {
1221 $deviceProperties=(array)$soapResult;
1222 }
1223 return $deviceProperties;
1224 }
1225 function getSyncSettings($devid) {
1226 $soapResult=$this->_soap->call('getActiveSyncSyncSettings',array($devid));
1227 if (!$soapResult) {
1228 $result=array();
1229 } else {
1230 $result=(array)$soapResult;
1231 }
1232 return $result;
1233 }
1234 function GetFolderList() {
1235 debugLog('Groupe::GetFolderList()');
1236 $folders = array();
1237 foreach ($this->_GroupeFolders as $val) {
1238 $folder = $this->StatFolder($val);
1239 if ($folder) {
1240 $folders[]=$folder;
1241 }
1242 }
1243 $mailFolders=$this->_soap->call('getActiveSyncMailFolders',array($this->_devid));
1244 foreach ($mailFolders as $val) {
1245 $this->_mailFolders[$val->Box]=$val;
1246 $folder = $this->StatFolder($val->Box);
1247 if ($folder) {
1248 $folders[]=$folder;
1249 }
1250 }
1251
1252 return $folders;
1253 }
1254
1255 function GetFolder($id) {
1256 debugLog('Groupe::GetFolder('.$id.')');
1257 $folder = new SyncFolder();
1258 $folder->serverid = $id;
1259 switch($id) {
1260 case "VIRTUAL/calendar":
1261 $folder->parentid ="0";
1262 $folder->displayname = "Calendar";
1263 $folder->type = SYNC_FOLDER_TYPE_APPOINTMENT;
1264 break;
1265 case "VIRTUAL/contacts":
1266 $folder->parentid ="0";
1267 $folder->displayname = "Contacts";
1268 $folder->type = SYNC_FOLDER_TYPE_CONTACT;
1269 break;
1270 case "VIRTUAL/tasks":
1271 $folder->parentid ="0";
1272 $folder->displayname = "Tasks";
1273 $folder->type = SYNC_FOLDER_TYPE_TASK;
1274 break;
1275 default:
1276 if (isset($this->_mailFolders[$id])) {
1277 $folder->parentid=$this->_mailFolders[$id]->ParentBox?$this->_mailFolders[$id]->ParentBox:'0';
1278 $folder->displayname=$this->_mailFolders[$id]->Name;
1279 switch($this->_mailFolders[$id]->Type) {
1280 case 'I':
1281 $folder->type = SYNC_FOLDER_TYPE_INBOX;
1282 //debugLog(print_r($folder,1));
1283 break;
1284 case 'T':
1285 $folder->type = SYNC_FOLDER_TYPE_WASTEBASKET;
1286 $this->_wasteID = $id;
1287 break;
1288 case 'S':
1289 $folder->type = SYNC_FOLDER_TYPE_SENTMAIL;
1290 break;
1291 case 'D':
1292 $folder->type = SYNC_FOLDER_TYPE_DRAFTS;
1293 break;
1294 default:
1295 $folder->type = SYNC_FOLDER_TYPE_USER_MAIL;
1296 break;
1297 }
1298 //debugLog($folder->displayname.':'.$folder->type);
1299 } else {
1300 return false;
1301 }
1302 break;
1303 }
1304 //debugLog(print_r($folder,1));
1305 return $folder;
1306 }
1307
1308 function StatFolder($id) {
1309 debugLog('Groupe::StatFolder('.$id.')');
1310 $stat = array();
1311 $folder = $this->GetFolder($id);
1312 if ($folder) {
1313 $stat["id"] = $id;
1314 $stat["parent"] = $folder->parentid;
1315 $stat["mod"] = $folder->displayname;
1316 }
1317 return $stat;
1318 }
1319 function ChangeFolder($parent, $id, $displayname, $type) {
1320 debugLog('Groupe::ChangeFolder('.$parent.', '.$id.', '.$displayname.', '.$type.')');
1321 return false;
1322 }
1323 function DeleteFolder($parent, $id) {
1324 debugLog('Groupe::DeleteFolder('.$parent.', '.$id.')');
1325 return false;
1326 }
1327 function GetMessageList($folderid, $cutoffdate) {
1328 debugLog('Groupe::GetMessageList('.$folderid.','.$cutoffdate.')');
1329 $messages = array();
1330 switch($folderid) {
1331 case 'VIRTUAL/contacts':
1332 $messages=$this->_soap->call('getActiveSyncContacts',array($this->_devid));
1333 //debugLog(print_r($messages,1));
1334 break;
1335 case 'VIRTUAL/calendar':
1336 if (!intval($cutoffdate)) {
1337 $cutoffdate=time()-3600*24*30;
1338 debugLog('SetCutoffDate:'.$cutoffdate);
1339 }
1340 $messages=$this->_soap->call('getActiveSyncAppointments',array($this->_devid,intval($cutoffdate)));
1341 //debugLog(var_export($messages,1));
1342 break;
1343 case 'VIRTUAL/tasks':
1344 if (!intval($cutoffdate)) {
1345 $cutoffdate=time()-3600*24*30;
1346 debugLog('SetCutoffDate:'.$cutoffdate);
1347 }
1348 $messages=$this->_soap->call('getActiveSyncTasks',array($this->_devid,intval($cutoffdate)));
1349 //debugLog(print_r($messages,1));
1350 break;
1351 default:
1352 if (!intval($cutoffdate)) {
1353 $cutoffdate=time()-3600*24*30;
1354 debugLog('SetCutoffDate:'.$cutoffdate);
1355 }
1356 $messages=$this->_soap->call('getActiveSyncMail',array($folderid,intval($cutoffdate),$this->_mailLimit));
1357 //debugLog(print_r($messages,1));
1358 break;
1359 }
1360 $this->_statMessages[$folderid]=array();
1361 foreach($messages as $v) {
1362 $this->_statMessages[$folderid][$v['id']]=$v;
1363 }
1364 return $messages;
1365 }
1366
1367 function StatMessage($folderid, $id) {
1368 debugLog('Groupe::StatMessage('.$folderid.', '.$id.')');
1369 if (!isset($this->_statMessages[$folderid][$id])) {
1370 $this->loadMessage($folderid,$id);
1371 }
1372 if (isset($this->_statMessages[$folderid][$id])) {
1373 return $this->_statMessages[$folderid][$id];
1374 }
1375 return false;
1376 }
1377 function LoadMessage($folderid, $id, $mimesupport = 0) {
1378 debugLog('Groupe::LoadMessage('.$folderid.', '.$id.', '.$mimesupport.')');
1379 switch($folderid) {
1380 case 'VIRTUAL/contacts':
1381 $this->_messages[$folderid][$id]=$this->_soap->call('getActiveSyncContactByID',array($id));
1382 if ($this->_messages[$folderid][$id]) {
1383 $this->_statMessages[$folderid][$id]=array(
1384 'id'=>$id,
1385 'mod'=>$this->_messages[$folderid][$id]->TimeModify,
1386 'flags'=>1,
1387 'acl'=>$this->_messages[$folderid][$id]->_acl,
1388 );
1389 }
1390 //debugLog(print_r($messages,1));
1391 break;
1392 case 'VIRTUAL/calendar':
1393 $this->_messages[$folderid][$id]=$this->_soap->call('getActiveSyncAppointmentByID',array($id));
1394 if ($this->_messages[$folderid][$id]) {
1395 $this->_statMessages[$folderid][$id]=array(
1396 'id'=>$id,
1397 'mod'=>$this->_messages[$folderid][$id]->TimeModify,
1398 'flags'=>1,
1399 'acl'=>$this->_messages[$folderid][$id]->_acl,
1400 );
1401 }
1402 //debugLog(print_r($this->_messages[$folderid][$id],1));
1403 break;
1404 case 'VIRTUAL/tasks':
1405 $this->_messages[$folderid][$id]=$this->_soap->call('getActiveSyncTaskByID',array($id));
1406 if ($this->_messages[$folderid][$id]) {
1407 $this->_statMessages[$folderid][$id]=array(
1408 'id'=>$id,
1409 'mod'=>$this->_messages[$folderid][$id]->TimeModify,
1410 'flags'=>1,
1411 'acl'=>$this->_messages[$folderid][$id]->_acl,
1412 );
1413 }
1414 //debugLog(print_r($messages,1));
1415 break;
1416 default:
1417 //debugLog('MemoryUsage BeforeLoad:'.number_format(memory_get_usage(true)/(1024*1024),2));
1418 $this->_messages[$folderid][$id]=$this->_soap->call('getActiveSyncMailMimeByID',array($folderid,$id));
1419 //debugLog('MemoryUsage AfterLoad:'.number_format(memory_get_usage(true)/(1024*1024),2));
1420 //debugLog('Groupe::LoadMessage: Result:'.substr(print_r($this->_messages[$folderid][$id],1),0,300));
1421 if ($this->_messages[$folderid][$id]) {
1422 $this->_statMessages[$folderid][$id]=array(
1423 'id'=>$id,
1424 'mod'=>$this->_messages[$folderid][$id]->Date,
1425 'flags'=>$this->_messages[$folderid][$id]->New?0:1,
1426 'olflags'=>0,
1427 'acl'=>7,
1428 );
1429 }
1430 break;
1431 }
1432 }
1433 function GetMessage($folderid, $id, $truncsize, $bodypreference=false, $optionbodypreference=false, $mimesupport = 0) {
1434 debugLog('Groupe::GetMessage('.$folderid.', '.$id.','.$truncsize.','.$mimesupport.')');
1435 switch($folderid) {
1436 case 'VIRTUAL/contacts':
1437 if (!isset($this->_messages[$folderid][$id])) {
1438 $this->loadMessage($folderid,$id,$mimesupport);
1439 }
1440 if ($this->_messages[$folderid][$id]) {
1441 return $this->_map['contact']->groupe2message($this->_messages[$folderid][$id], $truncsize, $bodypreference,$optionbodypreference, $mimesupport);
1442 }
1443 break;
1444 case 'VIRTUAL/calendar':
1445 if (!isset($this->_messages[$folderid][$id])) {
1446 $this->loadMessage($folderid,$id,$mimesupport);
1447 }
1448 if ($this->_messages[$folderid][$id]) {
1449 return $this->_map['appointment']->groupe2message($this->_messages[$folderid][$id], $truncsize, $bodypreference,$optionbodypreference, $mimesupport);
1450 }
1451 break;
1452 case 'VIRTUAL/tasks':
1453 if (!isset($this->_messages[$folderid][$id])) {
1454 $this->loadMessage($folderid,$id,$mimesupport);
1455 }
1456 if ($this->_messages[$folderid][$id]) {
1457 return $this->_map['task']->groupe2message($this->_messages[$folderid][$id], $truncsize, $bodypreference,$optionbodypreference, $mimesupport);
1458 }
1459 break;
1460 default:
1461 if (!isset($this->_messages[$folderid][$id])) {
1462 $this->loadMessage($folderid,$id, $mimesupport);
1463 }
1464 //debugLog('MemoryUsage BeforeDecode:'.number_format(memory_get_usage(true)/(1024*1024),2));
1465 if ($this->_messages[$folderid][$id]) {
1466 return $this->_map['mail']->groupe2message($this->_messages[$folderid][$id], $truncsize, $bodypreference,$optionbodypreference, $mimesupport);
1467 }
1468 break;
1469 }
1470 return false;
1471 }
1472
1473 function DeleteMessage($folderid, $id) {
1474 debugLog('Groupe::DeleteMessage('.$folderid.', '.$id.')');
1475 $stat=$this->StatMessage($folderid, $id);
1476 // debugLog(print_r($stat,1));
1477 if ($stat===false) {
1478 debugLog('Message not exists:'.$id);
1479 return true;
1480 } elseif ($stat['acl']&4) {
1481 switch($folderid) {
1482 case 'VIRTUAL/contacts':
1483 if ($id && $this->_soap->call('deleteActiveSyncContact',array($id))) {
1484 unset($this->_messages[$folderid][$id]);
1485 unset($this->_statMessages[$folderid][$id]);
1486 $this->_importedFolders[$folderid]['r']+=1;
1487 return true;
1488 }
1489 break;
1490 case 'VIRTUAL/calendar':
1491 if ($id && $this->_soap->call('deleteActiveSyncAppointment',array($id))) {
1492 unset($this->_messages[$folderid][$id]);
1493 unset($this->_statMessages[$folderid][$id]);
1494 $this->_importedFolders[$folderid]['r']+=1;
1495 return true;
1496 }
1497 break;
1498 case 'VIRTUAL/tasks':
1499 if ($id && $this->_soap->call('deleteActiveSyncTask',array($id))) {
1500 unset($this->_messages[$folderid][$id]);
1501 unset($this->_statMessages[$folderid][$id]);
1502 $this->_importedFolders[$folderid]['r']+=1;
1503 return true;
1504 }
1505 break;
1506 default:
1507 if ($id && $this->_soap->call('deleteMail',array($folderid,$id))) {
1508 unset($this->_messages[$folderid][$id]);
1509 unset($this->_statMessages[$folderid][$id]);
1510 $this->_importedFolders[$folderid]['r']+=1;
1511 return true;
1512 }
1513 break;
1514 }
1515 } else {
1516 debugLog('NO DELETE Permissions:'.$id);
1517 }
1518 return false;
1519 }
1520
1521 function SetReadFlag($folderid, $id, $flags) {
1522 debugLog('Groupe::SetReadFlag('.$folderid.','.$id.','.$flags.')');
1523 if ($flags == 0) {
1524 return $this->_soap->call('clearMailFlag',array($folderid,$id,"\\Seen"));
1525 } else {
1526 return $this->_soap->call('setMailFlag',array($folderid,$id,"\\Seen"));
1527 }
1528 }
1529 function ChangeMessage($folderid, $id, $message) {
1530 debugLog('Groupe::ChangeMessage('.$folderid.', '.$id.', ..)');
1531 if ($id) {
1532 $stat=$this->StatMessage($folderid, $id);
1533 } else {
1534 $stat=array('acl'=>7);
1535 }
1536 if ($stat['acl']&2) {
1537 switch($folderid) {
1538 case 'VIRTUAL/contacts':
1539 if ($id && !isset($this->_messages[$folderid][$id])) {
1540 $this->loadMessage($folderid,$id);
1541 }
1542 if ($id && $this->_messages[$folderid][$id]) {
1543 $groupeMsg=$this->_messages[$folderid][$id];
1544 $mode='c';
1545 } else {
1546 $groupeMsg=(object)array();
1547 $mode='a';
1548 }
1549 $groupeMsg=$this->_map['contact']->message2groupe($message,$groupeMsg);
1550 $result=$this->_soap->call('updateActiveSyncContact',array($id,$groupeMsg));
1551 debugLog('updateActiveSyncContact:'.print_r($result,1));
1552 if (isset($result['error']) && $result['error']==0) {
1553 $this->_importedFolders[$folderid][$mode]+=1;
1554 if (!$result['reload'] && $result['id'] && isset($this->_messages[$folderid][$result['id']])) {
1555 unset($this->_messages[$folderid][$result['id']]);
1556 unset($this->_statMessages[$folderid][$result['id']]);
1557 }
1558 return $this->StatMessage($folderid, $result['id']);
1559 } else {
1560 return false;
1561 }
1562 break;
1563 case 'VIRTUAL/calendar':
1564 if ($id && !isset($this->_messages[$folderid][$id])) {
1565 $this->loadMessage($folderid,$id);
1566 }
1567 if ($id && $this->_messages[$folderid][$id]) {
1568 $groupeMsg=$this->_messages[$folderid][$id];
1569 $mode='c';
1570 } else {
1571 $groupeMsg=(object)array();
1572 $mode='a';
1573 }
1574 $groupeMsg=$this->_map['appointment']->message2groupe($message,$groupeMsg);
1575 //debugLog(print_r($groupeMsg,1));
1576 $result=$this->_soap->call('updateActiveSyncAppointment',array($id,$groupeMsg));
1577 debugLog('updateActiveSyncAppointment:'.print_r($result,1));
1578 if (isset($result['error']) && $result['error']==0) {
1579 $this->_importedFolders[$folderid][$mode]+=1;
1580 if (!$result['reload'] && $result['id'] && isset($this->_messages[$folderid][$result['id']])) {
1581 unset($this->_messages[$folderid][$result['id']]);
1582 unset($this->_statMessages[$folderid][$result['id']]);
1583 }
1584 return $this->StatMessage($folderid, $result['id']);
1585 } else {
1586 return false;
1587 }
1588 break;
1589 case 'VIRTUAL/tasks':
1590 if ($id && !isset($this->_messages[$folderid][$id])) {
1591 $this->loadMessage($folderid,$id);
1592 }
1593 if ($id && $this->_messages[$folderid][$id]) {
1594 $groupeMsg=$this->_messages[$folderid][$id];
1595 $mode='c';
1596 } else {
1597 $groupeMsg=(object)array();
1598 $mode='a';
1599 }
1600 $groupeMsg=$this->_map['task']->message2groupe($message,$groupeMsg);
1601 //debugLog(print_r($groupeMsg,1));
1602 $result=$this->_soap->call('updateActiveSyncTask',array($id,$groupeMsg));
1603 debugLog('updateActiveSyncTask:'.print_r($result,1));
1604 if (isset($result['error']) && $result['error']==0) {
1605 $this->_importedFolders[$folderid][$mode]+=1;
1606 if (!$result['reload'] && $result['id'] && isset($this->_messages[$folderid][$result['id']])) {
1607 unset($this->_messages[$folderid][$result['id']]);
1608 unset($this->_statMessages[$folderid][$result['id']]);
1609 }
1610 return $this->StatMessage($folderid, $result['id']);
1611 } else {
1612 return false;
1613 }
1614 break;
1615 }
1616 } else {
1617 debugLog('NO CHANGE Permissions:'.$id);
1618 }
1619 return false;
1620 }
1621
1622 function MoveMessage($folderid, $id, $newfolderid) {
1623 debugLog('Groupe::MoveMessage('.$folderid.', '.$id.', '.$newfolderid.')');
1624 $stat=$this->StatMessage($folderid, $id);
1625 // debugLog(print_r($stat,1));
1626 if ($stat===false) {
1627 debugLog('Message not exists:'.$id);
1628 return true;
1629 } elseif ($stat['acl']&2) {
1630 switch($folderid) {
1631 case 'VIRTUAL/contacts':
1632 case 'VIRTUAL/calendar':
1633 case 'VIRTUAL/tasks':
1634 return false;
1635 break;
1636 default:
1637 if ($id && $newfolderid && $this->_soap->call('moveMail',array($folderid,$id,$newfolderid))) {
1638 unset($this->_messages[$folderid][$id]);
1639 unset($this->_statMessages[$folderid][$id]);
1640 $this->_importedFolders[$folderid]['r']+=1;
1641 return true;
1642 }
1643 break;
1644 }
1645 } else {
1646 debugLog('NO MOVE Permissions:'.$id);
1647 }
1648 return false;
1649 }
1650 function GetAttachmentData($attname) {
1651 debugLog('Groupe::GetAttachmentData('.$attname.')');
1652 $data=explode(':',$attname);
1653 $message=$this->_soap->call('getMailAttachment',$data);
1654 if ($message!==false && $message['body']) {
1655 print base64_decode($message['body']);
1656 unset($message);
1657 return true;
1658 }
1659 return false;
1660 }
1661 function ItemOperationsGetAttachmentData($attname) {
1662 debugLog('Groupe::ItemOperationsGetAttachmentData('.$attname.')');
1663 $data=explode(':',$attname);
1664 $attachment = new SyncAirSyncBaseFileAttachment();
1665 $message=$this->_soap->call('getMailAttachment',$data);
1666 if ($message!==false && $message['body']) {
1667 $attachment->_data = base64_decode($message['body']);
1668 $attachment->total = strlen($message['body']);
1669 $attachment->contenttype = trim($message['type']);
1670 }
1671 unset($message);
1672 return $attachment;
1673 }
1674
1675 function SendMail($rfc822, $smartdata=array(), $protocolversion = false) {
1676 debugLog("Groupe::SendMail: smartdata:".print_r($smartdata,1));
1677 //debugLog("Groupe::SendMail: \n $rfc822" );
1678 if (preg_match('@Content-Type:\s*text/calendar;\s*charset=[^;]+;\s*name=[a-z]+\.ics;\s*method=(REQUEST|REPLY)@i',$rfc822)) {
1679 debugLog("Groupe::SendMail: Ignore Invitations");
1680 return true;
1681 }
1682 if (preg_match('@Content-Type:\s*text/calendar;\s*charset=[^;]+;\s*method=(REQUEST|REPLY)@i',$rfc822)) {
1683 debugLog("Groupe::SendMail: Ignore Invitations");
1684 return true;
1685 }
1686
1687 $mailPlain='';
1688 $mailHtml='';
1689 $hdrs=array();
1690
1691 $buildParams = array(
1692 'eol' => "\n",
1693 'charset' => 'utf-8',
1694 'text_encoding' => 'base64',
1695 'html_encoding' => 'base64',
1696 'text_charset' => 'utf-8',
1697 'html_charset' => 'utf-8',
1698 'head_charset' => 'utf-8',
1699 );
1700 $newMail = new Mail_mime($buildParams);
1701 $newMail->setParam('text_charset','utf-8');
1702
1703 $mimeParams = array(
1704 'decode_headers' => true,
1705 'decode_bodies' => true,
1706 'include_bodies' => true,
1707 'charset' => 'utf-8'
1708 );
1709 $mailObj = new Mail_mimeDecode($rfc822);
1710 $mailMsg = $mailObj->decode($mimeParams);
1711
1712
1713 foreach($mailMsg->headers as $k => $v) {
1714 $k=strtolower($k);
1715 if ($k == "sender") continue;
1716 if ($k == "content-type") continue;
1717 if ($k == "content-transfer-encoding") continue;
1718 if ($k == "content-transfer-encoding") continue;
1719 if ($k == "mime-version") continue;
1720 // all other headers stay
1721 $hdrs[ucfirst($k)]=trim($v);
1722 }
1723 debugLog("SendMail: parsed message headers: ". print_r($hdrs,1));
1724 //debugLog("SendMail: parsed message: ". print_r($mailMsg,1));
1725
1726 $this->combineMessage($mailMsg,$newMail,$mailPlain,$mailHtml,'new');
1727 if (trim($mailHtml)) {
1728 $mode='HTML';
1729 } else {
1730 $mode='PLAIN';
1731 }
1732 debugLog("SendMail Format: ".$mode);
1733 if (($smartdata['task'] == 'reply' || $smartdata['task'] == 'forward') && $smartdata['folderid'] && $smartdata['itemid']) {
1734 if ($smartObj=$this->_soap->call('getActiveSyncMailMimeByID',array($smartdata['folderid'],$smartdata['itemid']))) {
1735 $origMime=array(base64_decode($smartObj->MimeHeader),base64_decode($smartObj->MimeBody));
1736
1737 $mimeParams = array(
1738 'decode_headers' => true,
1739 'decode_bodies' => true,
1740 'include_bodies' => true,
1741 'charset' => 'utf-8'
1742 );
1743 $origObj = new Mail_mimeDecode($origMime);
1744 $origMsg = $origObj->decode($mimeParams);
1745 //debugLog("IMAP-SendMail: : parsed message Orig: ". print_r($origMsg,1));
1746
1747 $body_sep= "\r\n\r\n-----Original Message-----\r\n";
1748 if(isset($origMsg->headers['from'])) {
1749 $body_sep.= "From: " .$origMsg->headers['from']. "\r\n";
1750 }
1751 if(isset($origMsg->headers['to']) && strlen($origMsg->headers['to']) > 0) {
1752 $body_sep.= "To: " . $origMsg->headers['to'] . "\r\n";
1753 }
1754 if(isset($origMsg->headers['cc']) && strlen($origMsg->headers['cc']) > 0) {
1755 $body_sep.= "Cc: " . $origMsg->headers['cc'] . "\r\n";
1756 }
1757 if(isset($origMsg->headers['date'])) {
1758 $body_sep.= "Sent: " . $origMsg->headers['date'] . "\r\n";
1759 }
1760 if(isset($origMsg->headers['subject'])) {
1761 $body_sep.= "Subject: " . $origMsg->headers['subject'] . "\r\n";
1762 }
1763 $body_sep.="\r\n"."\r\n";
1764 $mailPlain.=$body_sep;
1765
1766 if ($mode=='HTML') {
1767 $mailHtml.=nl2br($body_sep);
1768 }
1769 $this->combineMessage($origMsg,$newMail,$mailPlain,$mailHtml,$smartdata['task']);
1770 //debugLog("IMAP-SendMail: new Message Smart mailPlain: ".$mailPlain);
1771 //debugLog("IMAP-SendMail: new Message Smart mailHtml: ".$mailHtml);
1772 //$mailHtml='';
1773 }
1774 }
1775 $newMail->setTXTBody($mailPlain);
1776 if ($mode=='HTML') {
1777 $newMail->setHTMLBody($mailHtml);
1778 }
1779 $body = $newMail->getMessageBody();
1780 $hdrs = $newMail->headers($hdrs);
1781 //advanced debugging
1782 debugLog("IMAP-SendMail: headers: ".print_r($hdrs,1));
1783 //debugLog("IMAP-SendMail: body: $body");
1784
1785 return $this->_soap->call('sendActiveSyncMail',array($hdrs,$body));
1786 }
1787 function combineMessage(&$mailMsg,&$newMail,&$mailPlain,&$mailHtml,$task='') {
1788 $bodyHtml='';
1789 $bodyPlain='';
1790
1791 if($mailMsg->ctype_primary == "multipart" && ($mailMsg->ctype_secondary == "mixed" || $mailMsg->ctype_secondary == "alternative")) {
1792 $mparts = $mailMsg->parts;
1793 for($i=0; $i<count($mparts); $i++) {
1794 $part = $mparts[$i];
1795 // palm pre & iPhone send forwarded messages in another subpart which are also parsed
1796 if($part->ctype_primary == "multipart" && ($part->ctype_secondary == "mixed" || $part->ctype_secondary == "alternative" || $part->ctype_secondary == "related")) {
1797 foreach($part->parts as $spart) {
1798 $mparts[] = $spart;
1799 }
1800 continue;
1801 }
1802 // standard body
1803 if($part->ctype_primary == "text" && $part->ctype_secondary == "plain" && isset($part->body) && (!isset($part->disposition) || $part->disposition != "attachment")) {
1804 $bodyPlain.=$part->body; // assume only one text body
1805 } elseif($part->ctype_primary == "text" && $part->ctype_secondary == "html" && isset($part->body) && (!isset($part->disposition) || $part->disposition != "attachment")) {
1806 // html body
1807 $bodyHtml.=nl2br(preg_replace("@>\s+<@", "><", $part->body));
1808 } elseif ($task!='reply') {
1809 if(isset($part->d_parameters['filename']))
1810 $attname = $part->d_parameters['filename'];
1811 else if(isset($part->ctype_parameters['name']))
1812 $attname = $part->ctype_parameters['name'];
1813 else if(isset($part->headers['content-description']))
1814 $attname = $part->headers['content-description'];
1815 else $attname = "unknown attachment";
1816 // any other type, store as attachment
1817 $newMail->addAttachment($part->body,$part->ctype_primary.'/'.$part->ctype_secondary,$attname,false);
1818 }
1819 }
1820 } elseif($mailMsg->ctype_primary == "text" && $mailMsg->ctype_secondary == "html") {
1821 $bodyHtml.=nl2br(preg_replace("@>\s+<@", "><", $mailMsg->body));
1822 } else {
1823 $bodyPlain.=$mailMsg->body;
1824 }
1825 if (!trim($bodyPlain)) {
1826 $bodyPlain = preg_replace("/<br(\s+)?\/?>/i", "\n", $bodyHtml);
1827 // remove css-style tags
1828 $bodyPlain = preg_replace("/<style.*?<\/style>/is", "", $bodyHtml);
1829 // remove all other html
1830 $bodyPlain = strip_tags($bodyPlain);
1831 }
1832 if (!trim($bodyHtml)) {
1833 $bodyHtml=nl2br($bodyPlain);
1834 }
1835 $mailPlain.=$bodyPlain;
1836 $mailHtml.=$bodyHtml;
1837 }
1838
1839
1840 static function getAttachmentsRecursive($message,&$export_msg) {
1841
1842 if(!isset($message->ctype_primary)) return;
1843
1844 if(isset($message->disposition)) {
1845 // debugLog(print_r($message->headers,true));
1846 // debugLog($message->ctype_primary." ".$message->ctype_secondary." ".(isset($message->ctype_parameters['charset']) ? trim($message->ctype_parameters['charset']) : ""));
1847 if (isset($message->headers['content-id']) &&
1848 strtolower($message->disposition) == 'inline') {
1849 $export_msg->addHTMLImage( $message->body,
1850 trim($message->headers['content-type']),
1851 trim($message->d_parameters['filename']),
1852 false,
1853 substr(trim($message->headers['content-id']),1,-1));
1854 } else {
1855 $export_msg->addAttachment( $message->body,
1856 trim($message->ctype_primary)."/".trim($message->ctype_secondary),
1857 trim($message->d_parameters['filename']),
1858 false,
1859 trim($message->headers['content-transfer-encoding']),
1860 trim($message->disposition),
1861 (isset($message->ctype_parameters['charset']) ? trim($message->ctype_parameters['charset']) : ""));
1862 }
1863 }
1864
1865 if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) {
1866 foreach($message->parts as $part) {
1867 BackendGroupe::getAttachmentsRecursive($part,$export_msg);
1868 }
1869 }
1870 }
1871 static function setAttachmentsRecursive($msgid,$message,$output,$partno='0') {
1872 if ($partno=='0') {
1873 $mno='';
1874 if (!isset($message->parts)) $partno='1';
1875 } else $mno=$partno.'.';
1876
1877 //debugLog('Part:'.print_r($message->headers,1));
1878 if (isset($message->headers['content-id']) || (isset($message->disposition) && ($message->disposition == "attachment" || $message->disposition == "inline"))) {
1879 if(isset($output->_mapping['POOMMAIL:Attachments'])) {
1880 $attachment = new SyncAttachment();
1881 } else if(isset($output->_mapping['AirSyncBase:Attachments'])) {
1882 $attachment = new SyncAirSyncBaseAttachment();
1883 }
1884 if (isset($message->body)) {
1885 $attachment->attsize = strlen($message->body);
1886 }
1887 if (isset($message->d_parameters['filename'])) {
1888 $attname = $message->d_parameters['filename'];
1889 } elseif(isset($message->ctype_parameters['name'])) {
1890 $attname = $message->ctype_parameters['name'];
1891 } elseif(isset($message->headers['content-description'])) {
1892 $attname = $message->headers['content-description'];
1893 } else {
1894 $attname = "unknown attachment";
1895 }
1896 $attachment->displayname = w2u($attname);
1897 $attachment->attmethod = 1;
1898 $attachment->attoid = isset($message->headers['content-id']) ? trim($message->headers['content-id']) : "";
1899 if ((isset($message->disposition) && $message->disposition == "inline") || isset($message->headers['content-id'])) {
1900 $attachment->isinline=true;
1901 $attachment->attmethod=6;
1902 //$attachment->contentid= isset($message->headers['content-id']) ? trim(substr($message->headers['content-id'],2,strlen($message->headers['content-id'])-3)) : "";
1903 $attachment->contentid= $attachment->attoid;
1904 $attachment->contenttype = trim($message->headers['content-type']);
1905 } else {
1906 $attachment->attmethod=1;
1907 }
1908
1909 if (isset($output->_mapping['POOMMAIL:Attachments'])) {
1910 $attachment->attname = $msgid . ":" . $partno;
1911 array_push($output->attachments, $attachment);
1912 } else if(isset($output->_mapping['AirSyncBase:Attachments'])) {
1913 $attachment->attname = $msgid . ":" . $partno;
1914 array_push($output->airsyncbaseattachments, $attachment);
1915 }
1916 }
1917 //debugLog(print_r($message->ctype_primary,1));
1918 //debugLog(print_r($message->parts,1));
1919
1920 if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) {
1921 foreach($message->parts as $count=>$part) {
1922 BackendGroupe::setAttachmentsRecursive($msgid,$part,$output,$mno.($count+1));
1923 }
1924 }
1925
1926 }
1927 /* Parse the message and return only the plaintext body
1928 */
1929 static function getBody($message) {
1930 $body = "";
1931 $htmlbody = "";
1932
1933 BackendGroupe::getBodyRecursive($message, "plain", $body);
1934
1935 if(!isset($body) || $body === "") {
1936 BackendGroupe::getBodyRecursive($message, "html", $body);
1937 // remove css-style tags
1938 $body = preg_replace("/<style.*?<\/style>/is", "", $body);
1939 // remove all other html
1940 $body = strip_tags($body);
1941 }
1942
1943 return $body;
1944 }
1945
1946 // Get all parts in the message with specified type and concatenate them together, unless the
1947 // Content-Disposition is 'attachment', in which case the text is apparently an attachment
1948 static function getBodyRecursive($message, $subtype, &$body) {
1949 if(!isset($message->ctype_primary)) return;
1950 if(strcasecmp($message->ctype_primary,"text")==0 && strcasecmp($message->ctype_secondary,$subtype)==0 && isset($message->body))
1951 $body .= $message->body;
1952
1953 if(strcasecmp($message->ctype_primary,"multipart")==0 && isset($message->parts) && is_array($message->parts)) {
1954 foreach($message->parts as $part) {
1955 if(!isset($part->disposition) || strcasecmp($part->disposition,"attachment")) {
1956 BackendGroupe::getBodyRecursive($part, $subtype, $body);
1957 }
1958 }
1959 }
1960 }
1961 function enc_multipart($boundary, $body, $body_ct, $body_cte) {
1962 $mail_body = "This is a multi-part message in MIME format\n\n";
1963 $mail_body .= "--$boundary\n";
1964 $mail_body .= "Content-Type: $body_ct\n";
1965 $mail_body .= "Content-Transfer-Encoding: $body_cte\n\n";
1966 $mail_body .= "$body\n\n";
1967
1968 return $mail_body;
1969 }
1970
1971
1972 function enc_attach_file($boundary, $filenm, $filesize, $file_cont, $content_type = "") {
1973 if (!$content_type) $content_type = "text/plain";
1974 $mail_body = "--$boundary\n";
1975 $mail_body .= "Content-Type: $content_type; name=\"$filenm\"\n";
1976 $mail_body .= "Content-Transfer-Encoding: base64\n";
1977 $mail_body .= "Content-Disposition: attachment; filename=\"$filenm\"\n";
1978 $mail_body .= "Content-Description: $filenm\n\n";
1979 $mail_body .= base64_encode($file_cont) . "\n\n";
1980
1981 return $mail_body;
1982 }
1983 function GetWasteBasket() {
1984 /*
1985 * debugLog('Groupe::GetWasteBasket');
1986 * return $this->_wasteID;
1987 */
1988 return false;
1989 }
1990
1991
1992 function GetHierarchyImporter() {
1993 debugLog('Groupe::GetHierarchyImporter()');
1994 return new ImportHierarchyChangesDiff($this);
1995 }
1996
1997 function GetContentsImporter($folderid) {
1998 debugLog('Groupe::GetContentsImporter('.$folderid.')');
1999 $this->_importedFolders[$folderid] = array(
2000 'r'=>0,
2001 'a'=>0,
2002 'c'=>0,
2003 );
2004 return new ImportContentsChangesDiff($this, $folderid);
2005 }
2006
2007 function GetExporter($folderid = false) {
2008 debugLog('Groupe::GetExporter('.$folderid.')');
2009 return new ExportChangesDiff($this, $folderid);
2010 }
2011
2012 function GetHierarchy() {
2013 debugLog('Groupe::GetHierarchy()');
2014 $folders = array();
2015
2016 $fl = $this->getFolderList();
2017 foreach($fl as $f){
2018 $folders[] = $this->GetFolder($f['id']);
2019 }
2020
2021 return $folders;
2022 }
2023
2024 function Fetch($folderid, $id, $bodypreference=false, $optionbodypreference=false, $mimesupport = 0) {
2025 debugLog('Groupe::Fetch('.$folderid.','.$id.','.$mimesupport.')');
2026 return $this->GetMessage($folderid, $id, 1024*1024,$bodypreference,$optionbodypreference, $mimesupport); // Forces entire message (up to 1Mb)
2027 }
2028 function MeetingResponse($requestid, $folderid, $error, &$calendarid) {
2029 debugLog('Groupe::MeetingResponse('.$requestid.','.$folderid.','.$error.','.$calendarid.')');
2030 return false;
2031 }
2032
2033 function getTruncSize($truncation) {
2034 debugLog('Groupe::getTruncSize('.$truncation.')');
2035 switch($truncation) {
2036 case SYNC_TRUNCATION_HEADERS:
2037 return 0;
2038 case SYNC_TRUNCATION_512B:
2039 return 512;
2040 case SYNC_TRUNCATION_1K:
2041 return 1024;
2042 case SYNC_TRUNCATION_5K:
2043 return 5*1024;
2044 case SYNC_TRUNCATION_SEVEN:
2045 case SYNC_TRUNCATION_ALL:
2046 return 1024*1024; // We'll limit to 1MB anyway
2047 default:
2048 return 1024; // Default to 1Kb
2049 }
2050 }
2051
2052 /**
2053 * Returns array of items which contain contact information
2054 *
2055 * @param string $searchquery
2056 *
2057 * @return array
2058 */
2059 function getSearchResults($searchquery,$searchname) {
2060 debugLog('Groupe::getSearchResults('.$searchquery.','.$searchname.')');
2061 return false;
2062 }
2063
2064 function CheckPolicy($policykey, $devid) {
2065 global $user, $auth_pw;
2066
2067 $status = SYNC_PROVISION_STATUS_SUCCESS;
2068
2069 $user_policykey = $this->getPolicyKey($user, $auth_pw, $devid);
2070
2071 if ($user_policykey != $policykey) {
2072 $status = SYNC_PROVISION_STATUS_POLKEYMISM;
2073 }
2074
2075 if (!$policykey) $policykey = $user_policykey;
2076 return $status;
2077 }
2078
2079 /**
2080 * Return a policy key for given user with a given device id.
2081 * If there is no combination user-deviceid available, a new key
2082 * should be generated.
2083 *
2084 * @param string $user
2085 * @param string $pass
2086 * @param string $devid
2087 *
2088 * @return unknown
2089 */
2090 function getPolicyKey($user, $pass, $devid) {
2091 if($this->_loggedin === false) {
2092 debugLog("logon failed for user $user");
2093 return false;
2094 }
2095 $this->_device_filename = STATE_DIR . '/' . strtolower($devid) . '/device_info_'.$devid;
2096
2097 if (file_exists($this->_device_filename)) {
2098 $this->_device_info = unserialize(file_get_contents($this->_device_filename));
2099 if (isset($this->_device_info['policy_key'])) {
2100 return $this->_device_info['policy_key'];
2101 } else {
2102 return $this->setPolicyKey(0, $devid);
2103 }
2104 } else {
2105 return $this->setPolicyKey(0, $devid);
2106 }
2107 return false;
2108 }
2109
2110 /**
2111 * Generate a random policy key. Right now it's a 10-digit number.
2112 *
2113 * @return unknown
2114 */
2115 function generatePolicyKey() {
2116 // AS14 transmit Policy Key in URI on MS Phones.
2117 // In the base64 encoded binary string only 4 Bytes being reserved for
2118 // policy key and works in signed mode... Thats why we need here the max...
2119 // return mt_rand(1000000000, 9999999999);
2120 return mt_rand(1000000000, 2147483647);
2121 }
2122
2123 /**
2124 * Set a new policy key for the given device id.
2125 *
2126 * @param string $policykey
2127 * @param string $devid
2128 * @return unknown
2129 */
2130 function setPolicyKey($policykey, $devid) {
2131 $this->_device_filename = STATE_DIR . '/' . strtolower($devid) . '/device_info_'.$devid;
2132 // create device directory, if not yet existing
2133 if (!file_exists(dirname($this->_device_filename)))
2134 {
2135 mkdir(dirname($this->_device_filename),0700,true);
2136 }
2137
2138 if($this->_loggedin !== false) {
2139 if (!$policykey)
2140 $policykey = $this->generatePolicyKey();
2141 $this->_device_info['policy_key'] = $policykey;
2142 file_put_contents($this->_device_filename,serialize($this->_device_info));
2143 return $policykey;
2144 }
2145 return false;
2146 }
2147
2148 /**
2149 * Return a device wipe status
2150 *
2151 * @param string $user
2152 * @param string $pass
2153 * @param string $devid
2154 * @return int
2155 */
2156 function getDeviceRWStatus($user, $pass, $devid) {
2157 debugLog('Groupe::getDeviceRWStatus('.$user.',***,'.$devid.')');
2158 if (!empty($this->_deviceProperties) || $this->Logon($user, "", $pass)) {
2159 if (empty($this->_deviceProperties)) $this->_deviceProperties=$this->getDeviceProperties($this->_devid);
2160 if (isset($this->_deviceProperties['RwStatus'])) {
2161 return $this->_deviceProperties['RwStatus'];
2162 } else {
2163 return SYNC_PROVISION_RWSTATUS_NA;
2164 }
2165 }
2166 return false;
2167 }
2168
2169 /**
2170 * Set a new rw status for the device
2171 *
2172 * @param string $user
2173 * @param string $pass
2174 * @param string $devid
2175 * @param string $status
2176 *
2177 * @return boolean
2178 */
2179 function setDeviceRWStatus($user, $pass, $devid, $status) {
2180 debugLog('Groupe::setDeviceRWStatus('.$user.',***,'.$devid.','.$status.')');
2181 if (!empty($this->_deviceProperties) || $this->Logon($user, "", $pass)) {
2182 if (empty($this->_deviceProperties)) $this->_deviceProperties=$this->getDeviceProperties($this->_devid);
2183 $this->_deviceProperties['RwStatus']=$status;
2184 if ($this->_soap->call('setActiveSyncDevicePoperties',array($devid,(object)$this->_deviceProperties))) {
2185 return true;
2186 }
2187 }
2188 return false;
2189 }
2190 function setLastSyncTime () {
2191 debugLog('Groupe::setLastSyncTime()');
2192 if (!empty($this->_deviceProperties)) {
2193 $this->_deviceProperties['LastSync']=time();
2194 if ($this->_soap->call('setActiveSyncDevicePoperties',array($this->_devid,(object)$this->_deviceProperties))) {
2195 return true;
2196 }
2197 }
2198 }
2199
2200 function setSettings($request,$devid) {
2201 if (isset($request["oof"])) {
2202 if ($request["oof"]["oofstate"] == 1) {
2203 // in case oof should be switched on do it here
2204 // store somehow your oofmessage in case your system supports.
2205 // response["oof"]["status"] = true per default and should be false in case
2206 // the oof message could not be set
2207 $response["oof"]["status"] = true;
2208 } else {
2209 // in case oof should be switched off do it here
2210 $response["oof"]["status"] = true;
2211 }
2212 }
2213 if (isset($request["deviceinformation"])) {
2214 //error_log(print_r($request["deviceinformation"]));
2215 // in case you'd like to store device informations do it here.
2216 $response["deviceinformation"]["status"] = true;
2217 }
2218 if (isset($request["devicepassword"])) {
2219 // in case you'd like to store device informations do it here.
2220 $response["devicepassword"]["status"] = true;
2221 }
2222
2223 return $response;
2224 }
2225
2226 function getSettings ($request,$devid) {
2227 if (isset($request["userinformation"])) {
2228 $response["userinformation"]["status"] = 1;
2229 //$response["userinformation"]["emailaddresses"][] = $GLOBALS['egw_info']['user']['email'];
2230 } else {
2231 $response["userinformation"]["status"] = false;
2232 }
2233 if (isset($request["oof"])) {
2234 $response["oof"]["status"] = 0;
2235 }
2236 return $response;
2237 }
2238
2239 function AlterPing($folderid='') {
2240 debugLog('Groupe::AlterPing('.$folderid.')');
2241 if ($folderid) {
2242 switch($folderid) {
2243 case 'VIRTUAL/contacts':
2244 case 'VIRTUAL/calendar':
2245 case 'VIRTUAL/tasks':
2246
2247 break;
2248 default:
2249 /*
2250 return true;
2251 */
2252 break;
2253 }
2254 }
2255 return false;
2256 }
2257
2258 function AlterPingChanges($folderid, &$syncstate) {
2259 debugLog('Groupe::AlterPingChanges('.$folderid.','.$syncstate.')');
2260 switch($folderid) {
2261 case 'VIRTUAL/contacts':
2262 case 'VIRTUAL/calendar':
2263 case 'VIRTUAL/tasks':
2264
2265 break;
2266 default:
2267 /*if ($folderid) {
2268 $status=$this->_soap->call('statMailBox',array($folderid));
2269 if (!$status) {
2270 debugLog("AlterPingChanges: could not stat folder $folderid");
2271 return false;
2272 }
2273 else {
2274 $newstate = "M:". $status->NumMsg ."-R:". $status->NumRec ."-U:". $status->NextUid;
2275 if ($syncstate!=$newstate) {
2276 $syncstate = $newstate;
2277 debugLog("AlterPingChanges: Change FOUND!");
2278 // build a dummy change
2279 return array(array("type" => "fakeChange"));
2280 }
2281 }
2282 }*/
2283 break;
2284 }
2285 return array();
2286 }
2287
2288
2289 function escape($data){
2290 if (is_array($data)) {
2291 foreach ($data as $key => $val) {
2292 $data[$key] = $this->escape($val);
2293 }
2294 return $data;
2295 }
2296 $data = str_replace("\r\n", "\n", $data);
2297 $data = str_replace("\r", "\n", $data);
2298 $data = str_replace(array('\\', ';', ',', "\n"), array('\\\\', '\\;', '\\,', '\\n'), $data);
2299 return u2wi($data);
2300 }
2301
2302 function unescape($data){
2303 $data = str_replace(array('\\\\', '\\;', '\\,', '\\n','\\N'),array('\\', ';', ',', "\n", "\n"),$data);
2304 return $data;
2305 }
2306
2307
2308 };
2309 class SoapHeaderUsernameToken {
2310 public $Password;
2311 public $Username;
2312 public function __construct($l, $p) {
2313 $this->Password = $p;
2314 $this->Username = $l;
2315 }
2316 }
2317 class GroupeSoapClient {
2318 private $_soapClient;
2319 public function __construct() {
2320 if (defined('GROUP_URL_DOMAIN') && GROUP_URL_DOMAIN) {
2321 $location=GROUP_URL_DOMAIN.GROUP_URL_PATH;
2322 } else {
2323 $location=((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'])?'https://':'http://').$_SERVER['SERVER_NAME'].GROUP_URL_PATH;
2324 }
2325 debugLog('Groupe::InitSoap: '.$location);
2326 $this->_soapClient = new SoapClient(null,array(
2327 'location' => $location,
2328 'uri' => "http://localhost/SoapServer/",
2329 //'trace'=>true,
2330 ));
2331 }
2332 public function initUser($username,$password) {
2333 $UsernameToken = new SoapHeaderUsernameToken($username, $password);
2334 $soapHeaders[] = new SoapHeader('http://schemas.xmlsoap.org/ws/2002/07/utility', 'UsernameToken', $UsernameToken);
2335 $this->_soapClient->__setSoapHeaders($soapHeaders);
2336 }
2337 public function call($function,$params=array()) {
2338 try {
2339 return $this->_soapClient->__soapCall($function, $params);
2340 } catch (Exception $e) {
2341 debugLog(print_r($e,1));
2342 $this->debug();
2343 }
2344 }
2345 public function debug() {
2346 //debugLog(print_r($this->_soapClient->__getLastRequest(),1));
2347 //debugLog(print_r($this->_soapClient->__getLastResponseHeaders(),1));
2348 //debugLog(print_r($this->_soapClient->__getLastResponse(),1));
2349 }
2350 }
2351
2352 ?>