dolibarr  7.0.0-beta
xcal.lib.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (C) 2008-2011 Laurent Destailleur <eldy@users.sourceforge.net>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 
35 function build_calfile($format,$title,$desc,$events_array,$outputfile)
36 {
37  global $conf,$langs;
38 
39  dol_syslog("xcal.lib.php::build_calfile Build cal file ".$outputfile." to format ".$format);
40 
41  if (empty($outputfile)) return -1;
42 
43  // Note: A cal file is an UTF8 encoded file
44  $calfileh=fopen($outputfile,'w');
45  if ($calfileh)
46  {
47  include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php';
48  $now=dol_now();
49 
50  $encoding='';
51  if ($format == 'vcal') $encoding='ENCODING=QUOTED-PRINTABLE:';
52 
53  // Print header
54  fwrite($calfileh,"BEGIN:VCALENDAR\n");
55  fwrite($calfileh,"VERSION:2.0\n");
56  fwrite($calfileh,"METHOD:PUBLISH\n");
57  //fwrite($calfileh,"PRODID:-//DOLIBARR ".DOL_VERSION."//EN\n");
58  fwrite($calfileh,"PRODID:-//DOLIBARR ".DOL_VERSION."\n");
59  fwrite($calfileh,"CALSCALE:GREGORIAN\n");
60  fwrite($calfileh,"X-WR-CALNAME:".$encoding.format_cal($format,$title)."\n");
61  fwrite($calfileh,"X-WR-CALDESC:".$encoding.format_cal($format,$desc)."\n");
62  //fwrite($calfileh,"X-WR-TIMEZONE:Europe/Paris\n");
63  if (! empty($conf->global->MAIN_AGENDA_EXPORT_CACHE)
64  && $conf->global->MAIN_AGENDA_EXPORT_CACHE > 60){
65  $hh=convertSecondToTime($conf->global->MAIN_AGENDA_EXPORT_CACHE,'hour');
66  $mm=convertSecondToTime($conf->global->MAIN_AGENDA_EXPORT_CACHE,'min');
67  $ss=convertSecondToTime($conf->global->MAIN_AGENDA_EXPORT_CACHE,'sec');
68  fwrite($calfileh,"X-PUBLISHED-TTL: P".$hh."H".$mm."M".$ss."S\n");
69  }
70 
71  foreach ($events_array as $key => $event)
72  {
73  $eventqualified=true;
74  if ($eventqualified)
75  {
76  // See http://fr.wikipedia.org/wiki/ICalendar for format
77  // See http://www.ietf.org/rfc/rfc2445.txt for RFC
78  $uid = $event['uid'];
79  $type = $event['type'];
80  $startdate = $event['startdate'];
81  $duration = $event['duration'];
82  $enddate = $event['enddate'];
83  $summary = $event['summary'];
84  $category = $event['category'];
85  $priority = $event['priority'];
86  $fulldayevent = $event['fulldayevent'];
87  $location = $event['location'];
88  $email = $event['email'];
89  $url = $event['url'];
90  $transparency = $event['transparency']; // OPAQUE (busy) or TRANSPARENT (not busy)
91  $description=preg_replace('/<br[\s\/]?>/i',"\n",$event['desc']);
92  $description=dol_string_nohtmltag($description,0); // Remove html tags
93  $created = $event['created'];
94  $modified = $event['modified'];
95 
96  // Uncomment for tests
97  //$summary="Resume";
98  //$description="Description";
99  //$description="MemberValidatedInDolibarr gd gdf gd gdff\nNom: tgdf g dfgdf gfd r ter\nType: gdfgfdf dfg fd gfd gd gdf gdf gfd gdfg dfg ddf\nAuteur: AD01fg dgdgdfg df gdf gd";
100 
101  // Format
102  $summary=format_cal($format,$summary);
103  $description=format_cal($format,$description);
104  $category=format_cal($format,$category);
105  $location=format_cal($format,$location);
106 
107  // Output the vCard/iCal VEVENT object
108  /*
109  Example from Google ical export for a 1 hour event:
110  BEGIN:VEVENT
111  DTSTART:20101103T120000Z
112  DTEND:20101103T130000Z
113  DTSTAMP:20101121T144902Z
114  UID:4eilllcsq8r1p87ncg7vc8dbpk@google.com
115  CREATED:20101121T144657Z
116  DESCRIPTION:
117  LAST-MODIFIED:20101121T144707Z
118  LOCATION:
119  SEQUENCE:0
120  STATUS:CONFIRMED
121  SUMMARY:Tâche 1 heure
122  TRANSP:OPAQUE
123  END:VEVENT
124 
125  Example from Google ical export for a 1 day event:
126  BEGIN:VEVENT
127  DTSTART;VALUE=DATE:20101102
128  DTEND;VALUE=DATE:20101103
129  DTSTAMP:20101121T144902Z
130  UID:d09t43kcf1qgapu9efsmmo1m6k@google.com
131  CREATED:20101121T144607Z
132  DESCRIPTION:
133  LAST-MODIFIED:20101121T144607Z
134  LOCATION:
135  SEQUENCE:0
136  STATUS:CONFIRMED
137  SUMMARY:Tâche 1 jour
138  TRANSP:TRANSPARENT
139  END:VEVENT
140  */
141  if ($type == 'event')
142  {
143  fwrite($calfileh,"BEGIN:VEVENT\n");
144  fwrite($calfileh,"UID:".$uid."\n");
145  if (! empty($email))
146  {
147  fwrite($calfileh,"ORGANIZER:MAILTO:".$email."\n");
148  fwrite($calfileh,"CONTACT:MAILTO:".$email."\n");
149  }
150  if (! empty($url))
151  {
152  fwrite($calfileh,"URL:".$url."\n");
153  };
154 
155  if ($created) fwrite($calfileh,"CREATED:".dol_print_date($created,'dayhourxcard',true)."\n");
156  if ($modified) fwrite($calfileh,"LAST-MODIFIED:".dol_print_date($modified,'dayhourxcard',true)."\n");
157  fwrite($calfileh,"SUMMARY:".$encoding.$summary."\n");
158  fwrite($calfileh,"DESCRIPTION:".$encoding.$description."\n");
159 
160  /* Other keys:
161  // Status values for a "VEVENT"
162  statvalue = "TENTATIVE" ;Indicates event is
163  ;tentative.
164  / "CONFIRMED" ;Indicates event is
165  ;definite.
166  / "CANCELLED" ;Indicates event was
167  // Status values for "VTODO".
168  statvalue =/ "NEEDS-ACTION" ;Indicates to-do needs action.
169  / "COMPLETED" ;Indicates to-do completed.
170  / "IN-PROCESS" ;Indicates to-do in process of
171  / "CANCELLED" ;Indicates to-do was cancelled.
172  // Status values for "VJOURNAL".
173  statvalue =/ "DRAFT" ;Indicates journal is draft.
174  / "FINAL" ;Indicates journal is final.
175  / "CANCELLED" ;Indicates journal is removed.
176  */
177  //fwrite($calfileh,"CLASS:PUBLIC\n"); // PUBLIC, PRIVATE, CONFIDENTIAL
178  //fwrite($calfileh,"X-MICROSOFT-CDO-BUSYSTATUS:1\n");
179  //ATTENDEE;CUTYPE=INDIVIDUAL;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Laurent Destailleur;X-NUM-GUESTS=0:mailto:eldy10@gmail.com
180 
181  if (! empty($location)) fwrite($calfileh,"LOCATION:".$encoding.$location."\n");
182  if ($fulldayevent) fwrite($calfileh,"X-FUNAMBOL-ALLDAY:1\n");
183  if ($fulldayevent) fwrite($calfileh,"X-MICROSOFT-CDO-ALLDAYEVENT:1\n");
184 
185  // Date must be GMT dates
186  // Current date
187  fwrite($calfileh,"DTSTAMP:".dol_print_date($now,'dayhourxcard',true)."\n");
188  // Start date
189  $prefix='';
190  $startdatef = dol_print_date($startdate,'dayhourxcard',true);
191  if ($fulldayevent)
192  {
193  $prefix=';VALUE=DATE';
194  $startdatef = dol_print_date($startdate,'dayxcard',false); // Local time
195  }
196  fwrite($calfileh,"DTSTART".$prefix.":".$startdatef."\n");
197  // End date
198  if ($fulldayevent)
199  {
200  if (empty($enddate)) $enddate=dol_time_plus_duree($startdate,1,'d');
201  }
202  else
203  {
204  if (empty($enddate)) $enddate=$startdate+$duration;
205  }
206  $prefix='';
207  $enddatef = dol_print_date($enddate,'dayhourxcard',true);
208  if ($fulldayevent)
209  {
210  $prefix=';VALUE=DATE';
211  $enddatef = dol_print_date($enddate+1,'dayxcard',false);
212  //$enddatef .= dol_print_date($enddate+1,'dayhourxcard',false); // Local time
213  }
214  fwrite($calfileh,"DTEND".$prefix.":".$enddatef."\n");
215  fwrite($calfileh,'STATUS:CONFIRMED'."\n");
216  if (! empty($transparency)) fwrite($calfileh,"TRANSP:".$transparency."\n");
217  if (! empty($category)) fwrite($calfileh,"CATEGORIES:".$encoding.$category."\n");
218  fwrite($calfileh,"END:VEVENT\n");
219  }
220 
221  // Output the vCard/iCal VTODO object
222  // ...
223  //PERCENT-COMPLETE:39
224 
225  // Output the vCard/iCal VJOURNAL object
226  if ($type == 'journal')
227  {
228  fwrite($calfileh,"BEGIN:VJOURNAL\n");
229  fwrite($calfileh,"UID:".$uid."\n");
230  if (! empty($email))
231  {
232  fwrite($calfileh,"ORGANIZER:MAILTO:".$email."\n");
233  fwrite($calfileh,"CONTACT:MAILTO:".$email."\n");
234  }
235  if (! empty($url))
236  {
237  fwrite($calfileh,"URL:".$url."\n");
238  };
239 
240  if ($created) fwrite($calfileh,"CREATED:".dol_print_date($created,'dayhourxcard',true)."\n");
241  if ($modified) fwrite($calfileh,"LAST-MODIFIED:".dol_print_date($modified,'dayhourxcard',true)."\n");
242  fwrite($calfileh,"SUMMARY:".$encoding.$summary."\n");
243  fwrite($calfileh,"DESCRIPTION:".$encoding.$description."\n");
244  fwrite($calfileh,'STATUS:CONFIRMED'."\n");
245  fwrite($calfileh,"CATEGORIES:".$category."\n");
246  fwrite($calfileh,"LOCATION:".$location."\n");
247  fwrite($calfileh,"TRANSP:OPAQUE\n");
248  fwrite($calfileh,"CLASS:CONFIDENTIAL\n");
249  fwrite($calfileh,"DTSTAMP:".dol_print_date($startdatef,'dayhourxcard',true)."\n");
250 
251  fwrite($calfileh,"END:VJOURNAL\n");
252  }
253 
254 
255  // Put other info in comment
256  /*
257  $comment=array();
258  $comment ['eid'] = $eid;
259  $comment ['url'] = $linktoevent;
260  $comment ['date'] = dol_mktime($evttime,"Ymd");
261  $comment ['duration'] = $duration;
262  $comment ['startdate'] = $startdate;
263  $comment ['enddate'] = $enddate;
264  fwrite($calfileh,"COMMENT:" . serialize ($comment) . "\n");
265  */
266 
267  }
268  }
269 
270  // Footer
271  fwrite($calfileh,"END:VCALENDAR");
272 
273  fclose($calfileh);
274  if (! empty($conf->global->MAIN_UMASK))
275  @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
276  }
277  else
278  {
279  dol_syslog("xcal.lib.php::build_calfile Failed to open file ".$outputfile." for writing");
280  return -2;
281  }
282 }
283 
296 function build_rssfile($format,$title,$desc,$events_array,$outputfile,$filter='')
297 {
298  global $user,$conf,$langs;
299  global $dolibarr_main_url_root;
300 
301  dol_syslog("xcal.lib.php::build_rssfile Build rss file ".$outputfile." to format ".$format);
302 
303  if (empty($outputfile)) return -1;
304 
305  $fichier=fopen($outputfile,'w');
306  if ($fichier)
307  {
308  $date=date("r");
309 
310  // Print header
311  $form='<?xml version="1.0" encoding="'.$langs->charset_output.'"?>';
312  fwrite($fichier, $form);
313  fwrite($fichier, "\n");
314  $form='<rss version="2.0">';
315  fwrite($fichier, $form);
316  fwrite($fichier, "\n");
317 
318  $form="<channel>\n<title>".$title."</title>\n";
319  fwrite($fichier, $form);
320 
321  $form='<description><![CDATA['.$desc.'.]]></description>'."\n".
322 // '<language>fr</language>'."\n".
323  '<copyright>Dolibarr</copyright>'."\n".
324  '<lastBuildDate>'.$date.'</lastBuildDate>'."\n".
325  '<generator>Dolibarr</generator>'."\n";
326 
327  // Define $urlwithroot
328  $urlwithouturlroot=preg_replace('/'.preg_quote(DOL_URL_ROOT,'/').'$/i','',trim($dolibarr_main_url_root));
329  $urlwithroot=$urlwithouturlroot.DOL_URL_ROOT; // This is to use external domain name found into config file
330  //$urlwithroot=DOL_MAIN_URL_ROOT; // This is to use same domain name than current
331  $url=$urlwithroot.'/public/agenda/agendaexport.php?format=rss&exportkey='.urlencode($conf->global->MAIN_AGENDA_XCAL_EXPORTKEY);
332  $form.='<link><![CDATA['.$url.']]></link>'."\n";
333 
334  //print $form;
335  fwrite($fichier, $form);
336 
337 
338  foreach ($events_array as $key => $event)
339  {
340  $eventqualified=true;
341  if ($filter)
342  {
343  // TODO Add a filter
344 
345  $eventqualified=false;
346  }
347 
348  if ($eventqualified)
349  {
350  $uid = $event['uid'];
351  $startdate = $event['startdate'];
352  $summary = $event['summary'];
353  $url = $event['url'];
354  $author = $event['author'];
355  $category = $event['category'];
356  /* No place inside a RSS
357  $priority = $event['priority'];
358  $fulldayevent = $event['fulldayevent'];
359  $location = $event['location'];
360  $email = $event['email'];
361  */
362  $description=preg_replace('/<br[\s\/]?>/i',"\n",$event['desc']);
363  $description=dol_string_nohtmltag($description,0); // Remove html tags
364 
365  fwrite($fichier, "<item>\n");
366  fwrite($fichier, "<title><![CDATA[".$summary."]]></title>\n");
367  fwrite($fichier, "<link><![CDATA[".$url."]]></link>\n");
368  fwrite($fichier, "<author><![CDATA[".$author."]]></author>\n");
369  fwrite($fichier, "<category><![CDATA[".$category."]]></category>\n");
370  fwrite($fichier, "<description><![CDATA[");
371  if ($description) fwrite($fichier, $description);
372  //else fwrite($fichier, 'NoDesc');
373  fwrite($fichier, "]]></description>\n");
374  fwrite($fichier, "<pubDate>".date("r", $startdate)."</pubDate>\n");
375  fwrite($fichier, "<guid isPermaLink=\"true\"><![CDATA[".$uid."]]></guid>\n");
376  fwrite($fichier, "<source><![CDATA[Dolibarr]]></source>\n");
377  fwrite($fichier, "</item>\n");
378  }
379  }
380 
381  fwrite($fichier, '</channel>');
382  fwrite($fichier, "\n");
383  fwrite($fichier, '</rss>');
384 
385  fclose($fichier);
386  if (! empty($conf->global->MAIN_UMASK))
387  @chmod($outputfile, octdec($conf->global->MAIN_UMASK));
388  }
389 }
390 
391 
399 function format_cal($format,$string)
400 {
401  global $conf;
402 
403  $newstring=$string;
404 
405  if ($format == 'vcal')
406  {
407  $newstring=quotedPrintEncode($newstring);
408  }
409  if ($format == 'ical')
410  {
411  // Replace new lines chars by '\n'
412  $newstring=preg_replace('/'."\r\n".'/i',"\n",$newstring);
413  $newstring=preg_replace('/'."\n\r".'/i',"\n",$newstring);
414  $newstring=preg_replace('/'."\n".'/i','\n',$newstring);
415  // Must not exceed 75 char. Cut with "\r\n"+Space
416  $newstring=calEncode($newstring);
417  }
418 
419  return $newstring;
420 }
421 
429 function calEncode($line)
430 {
431  $out = '';
432 
433  $newpara = '';
434 
435  // If mb_ functions exists, it's better to use them
436  if (function_exists('mb_strlen'))
437  {
438  $strlength=mb_strlen($line, 'UTF-8');
439  for ($j = 0; $j <= ($strlength - 1); $j++)
440  {
441  $char = mb_substr($line, $j, 1, 'UTF-8'); // Take char at position $j
442 
443  if ((mb_strlen($newpara, 'UTF-8') + mb_strlen($char, 'UTF-8')) >= 75)
444  {
445  $out .= $newpara . "\r\n "; // CRLF + Space for cal
446  $newpara = '';
447  }
448  $newpara .= $char;
449  }
450  $out .= $newpara;
451  }
452  else
453  {
454  $strlength=dol_strlen($line);
455  for ($j = 0; $j <= ($strlength - 1); $j++)
456  {
457  $char = substr($line, $j, 1); // Take char at position $j
458 
459  if ((dol_strlen($newpara) + dol_strlen($char)) >= 75 )
460  {
461  $out .= $newpara . "\r\n "; // CRLF + Space for cal
462  $newpara = '';
463  }
464  $newpara .= $char;
465  }
466  $out .= $newpara;
467  }
468 
469  return trim($out);
470 }
471 
472 
480 function quotedPrintEncode($str,$forcal=0)
481 {
482  $lines = preg_split("/\r\n/", $str);
483  $out = '';
484 
485  foreach ($lines as $line)
486  {
487  $newpara = '';
488 
489  $strlength=strlen($line); // Do not use dol_strlen here, we need number of bytes
490  for ($j = 0; $j <= ($strlength - 1); $j++)
491  {
492  $char = substr($line, $j, 1);
493  $ascii = ord($char);
494 
495  if ( $ascii < 32 || $ascii == 61 || $ascii > 126 )
496  $char = '=' . strtoupper(sprintf("%02X", $ascii));
497 
498  if ((strlen($newpara) + strlen($char)) >= 76 ) // Do not use dol_strlen here, we need number of bytes
499  {
500  $out .= $newpara . '=' . "\r\n"; // CRLF
501  if ($forcal) $out .= " "; // + Space for cal
502  $newpara = '';
503  }
504  $newpara .= $char;
505  }
506  $out .= $newpara;
507  }
508  return trim($out);
509 }
510 
517 function quotedPrintDecode($str)
518 {
519  $out = preg_replace('/=\r?\n/', '', $str);
520  $out = quoted_printable_decode($out); // Available with PHP 4+
521  return trim($out);
522 }
523 
convertSecondToTime($iSecond, $format='all', $lengthOfDay=86400, $lengthOfWeek=7)
Return, in clear text, value of a number of seconds in days, hours and minutes.
Definition: date.lib.php:171
quotedPrintEncode($str, $forcal=0)
Encode into vcal format.
Definition: xcal.lib.php:480
build_rssfile($format, $title, $desc, $events_array, $outputfile, $filter='')
Build a file from an array of events.
Definition: xcal.lib.php:296
build_calfile($format, $title, $desc, $events_array, $outputfile)
Build a file from an array of events All input params and data must be encoded in $conf->charset_outp...
Definition: xcal.lib.php:35
if(empty($reshook)) $form
View.
Definition: perms.php:103
dol_syslog($message, $level=LOG_INFO, $ident=0, $suffixinfilename='', $restricttologhandler='')
Write log message into outputs.
quotedPrintDecode($str)
Decode vcal format.
Definition: xcal.lib.php:517
if($_POST["cancel"]==$langs->trans("Cancel")&&!$id) if($action== 'setdatev'&&$user->rights->tax->charges->creer) if($action== 'add'&&$_POST["cancel"]<> $langs->trans("Cancel")) if($action== 'delete') $title
Actions.
Definition: card.php:183
dol_now($mode='gmt')
Return date for now.
dol_string_nohtmltag($stringtoclean, $removelinefeed=1, $pagecodeto='UTF-8')
Clean a string from all HTML tags and entities.
dol_print_date($time, $format='', $tzoutput='tzserver', $outputlangs='', $encodetooutput=false)
Output date in a string format according to outputlangs (or langs if not defined).
calEncode($line)
Cut string after 75 chars.
Definition: xcal.lib.php:429
format_cal($format, $string)
Encode for cal export.
Definition: xcal.lib.php:399
dol_time_plus_duree($time, $duration_value, $duration_unit)
Add a delay to a date.
Definition: date.lib.php:116
dol_strlen($string, $stringencoding='UTF-8')
Make a strlen call.