4 * Handler for exporting webcalendar events to various formats.
7 * All-day events and untimed events are treated differently. An
8 * all-day event is a 12am event with duration 24 hours. We store
9 * untimed events with a start time of -1 in the webcalendar database.
11 *********************************************************************/
12 include_once $gfplugins.'webcalendar/www/includes/init.php';
14 if ( ! empty ( $PROGRAM_VERSION ) ) {
15 $prodid = "PRODID:-//WebCalendar-$PROGRAM_VERSION";
16 } else if ( preg_match ( "/v(\d\S+) /", $GLOBALS['PROGRAM_NAME'], $matches ) ) {
17 $prodid = "PRODID:-//WebCalendar-$matches[1]";
19 $prodid = "PRODID:-//WebCalendar-UnknownVersion";
22 if ( empty ( $user ) || $user == $login )
25 function export_get_event_entry($id) {
26 global $use_all_dates, $include_layers, $fromyear,$frommonth,$fromday,
27 $endyear,$endmonth,$endday,$modyear,$modmonth,$modday,$login;
28 global $DISPLAY_UNAPPROVED, $layers;
30 // We export repeating events only with the pilot-datebook CSV format
31 $sql = "SELECT webcal_entry.cal_id, webcal_entry.cal_name " .
32 ", webcal_entry.cal_priority, webcal_entry.cal_date " .
33 ", webcal_entry.cal_time " .
34 ", webcal_entry_user.cal_status, webcal_entry.cal_create_by " .
35 ", webcal_entry.cal_access, webcal_entry.cal_duration " .
36 ", webcal_entry.cal_description " .
37 ", webcal_entry_user.cal_category " .
38 "FROM webcal_entry, webcal_entry_user ";
41 $sql .= "WHERE webcal_entry.cal_id = webcal_entry_user.cal_id AND " .
42 " ( webcal_entry_user.cal_login = '" . $login . "'";
43 if ( ! empty ( $user ) && $user != $login ) {
44 $sql .= " OR webcal_entry_user.cal_login = '$user'";
45 } else if ( $include_layers && $layers ) {
46 foreach ( $layers as $layer ) {
47 $sql .= " OR webcal_entry_user.cal_login = '" .
48 $layer['cal_layeruser'] . "'";
53 if (!$use_all_dates) {
54 $startdate = sprintf ( "%04d%02d%02d", $fromyear, $frommonth, $fromday );
55 $enddate = sprintf ( "%04d%02d%02d", $endyear, $endmonth, $endday );
56 $sql .= " AND webcal_entry.cal_date >= $startdate " .
57 "AND webcal_entry.cal_date <= $enddate";
58 $moddate = sprintf ( "%04d%02d%02d", $modyear, $modmonth, $modday );
59 $sql .= " AND webcal_entry.cal_mod_date >= $moddate";
62 $sql .= "WHERE webcal_entry.cal_id = '$id' AND " .
63 "webcal_entry_user.cal_id = '$id' AND " .
64 "( webcal_entry_user.cal_login = '" . $login . "'";
65 // TODO: add support for user in URL so we can export from other
66 // calendars, particularly non-user calendars.
67 //"webcal_entry_user.cal_id = '$id'";
68 if ( ! empty ( $user ) && $user != $login ) {
69 $sql .= " OR webcal_entry_user.cal_login = '$user'";
70 } else if ( $layers ) {
71 foreach ( $layers as $layer ) {
72 $sql .= " OR webcal_entry_user.cal_login = '" .
73 $layer['cal_layeruser'] . "'";
79 if ( $DISPLAY_UNAPPROVED == "N" || $login == "__public__" )
80 $sql .= " AND webcal_entry_user.cal_status = 'A'";
82 $sql .= " AND webcal_entry_user.cal_status IN ('W','A')";
84 $sql .= " ORDER BY webcal_entry.cal_date";
86 //echo "SQL: $sql <p>";
87 $res = dbi_query ( $sql );
90 } //end function export_get_event_entry($id)
92 function export_quoted_printable_encode($car) {
95 if ((ord($car) >= 33 && ord($car) <= 60) || (ord($car) >= 62 && ord($car) <= 126) ||
96 ord($car) == 9 || ord($car) == 32) {
99 $res = sprintf("=%02X", ord($car));
103 } //end function export_quoted_printable_encode
105 function export_fold_lines($string, $encoding="none", $limit=76) {
106 $len = strlen($string);
111 $lwsp = 0; // position of the last linear whitespace (where to fold)
112 $res_ind = 0; // row index
113 $start_encode = 0; // we start encoding only after the ":" caracter is encountered
115 if (strcmp($encoding,"quotedprintable") == 0)
116 $fold--; // must take into account the soft line break
118 for ($i = 0; $i < $len; $i++) {
122 if (strcmp($encoding,"quotedprintable") == 0)
123 $enc = export_quoted_printable_encode($string[$i]);
124 else if (strcmp($encoding,"utf8") == 0)
125 $enc = utf8_encode($string[$i]);
128 if ($string[$i] == ":")
131 if ((strlen($row) + strlen($enc)) > $fold) {
135 $lwsp = $fold - 1; // the folding will occur in the middle of a word
137 if ($row[$lwsp] == " " || $row[$lwsp] == "\t")
140 $res[$res_ind] = substr($row, 0, $lwsp+1+$delta);
142 if (strcmp($encoding,"quotedprintable") == 0)
143 $res[$res_ind] .= "="; // soft line break;
145 $row = substr($row, $lwsp+1);
149 if ($delta == -1 && strcmp($encoding,"utf8") == 0)
153 $fold--; //reduce row length of 1 to take into account the whitespace at the beginning of lines
155 $res_ind++; // next line
158 } //end if ((strlen($row) + strlen($enc)) > $fold)
162 if ($string[$i] == " " || $string[$i] == "\t" || $string[$i] == ";" || $string[$i] == ",")
163 $lwsp = strlen($row) - 1;
165 if ($string[$i] == ":" && (strcmp($encoding,"quotedprintable") == 0))
166 $lwsp = strlen($row) - 1; // we cut at ':' only for quoted printable
167 } //end for ($i = 0; $i < $len; $i++)
169 $res[$res_ind] = $row; // Add last row (or first if no folding is necessary)
172 } //end function export_fold_lines($string, $encoding="none", $limit=76)
174 function export_get_attendee($id, $export) {
177 $request = "SELECT webcal_entry_user.cal_login, webcal_entry_user.cal_status, " .
178 " webcal_entry.cal_create_by " .
179 "FROM webcal_entry_user LEFT JOIN webcal_entry " .
180 " ON webcal_entry_user.cal_id = webcal_entry.cal_id " .
181 " WHERE webcal_entry_user.cal_id = '$id' AND webcal_entry_user.cal_status <> 'D'";
183 $att_res = dbi_query($request);
188 $entry_array = array();
190 while ($entry = dbi_fetch_row($att_res)) {
191 $entry_array[$count++] = $entry;
194 dbi_free_result($att_res);
198 while (list($key,$row) = each($entry_array)) {
199 $request = "SELECT cal_firstname, cal_lastname, cal_email, cal_login " .
200 " FROM webcal_user where cal_login = '". $row[0] . "'";
202 $user_res = dbi_query($request);
204 $user = dbi_fetch_row($user_res);
206 dbi_free_result($user_res);
208 if (count($user) > 0) {
209 $attendee[$count] = "ATTENDEE;ROLE=";
210 $attendee[$count] .= ($row[2] == $user[3]) ? "OWNER;" : "ATTENDEE;";
211 $attendee[$count] .= "STATUS=";
215 $attendee[$count] .= "CONFIRMED";
218 $attendee[$count] .= "DECLINED";
221 $attendee[$count] .= "SENT";
227 if (strcmp($export,"vcal") == 0)
228 $attendee[$count] .= ";ENCODING=QUOTED-PRINTABLE";
230 $attendee[$count] .= ":$user[0] $user[1] <$user[2]>";
233 } //end if (count($user) > 0)
237 } //end function export_get_attendee($id, $export)
239 function export_time($date, $duration, $time, $texport) {
240 $year = (int) substr($date,0,-4);
241 $month = (int) substr($date,-4,2);
242 $day = (int) substr($date,-2,2);
249 $duration = 24 * 60 * 60;
250 $str_duration = "1D";
252 $start_tmstamp = mktime($hour, $min, $sec, $month, $day, $year);
254 $start_date = date("Ymd", $start_tmstamp);
255 echo "DTSTART;VALUE=DATE:$start_date\r\n";
257 // timed event or all-day event
258 $hour = (int) substr($time,0,-4);
259 $min = (int) substr($time,-4,2);
260 $sec = (int) substr($time,-2,2);
261 $str_duration = "T" . $duration . "M";
262 $duration = $duration * 60;
264 $start_tmstamp = mktime($hour, $min, $sec, $month, $day, $year);
266 $utc_start = export_get_utc_date($date, $time);
267 echo "DTSTART:$utc_start\r\n";
270 if (strcmp($texport,"ical") == 0) {
271 $utc_dtstamp = export_get_utc_date(date("Ymd", mktime()),
272 date("His", mktime()));
273 echo "DTSTAMP:$utc_dtstamp\r\n";
277 $end_tmstamp = $start_tmstamp + 24*60*60;
278 $utc_end = date("Ymd", $end_tmstamp);
279 echo "DTEND;VALUE=DATE:$utc_end\r\n";
281 $end_tmstamp = $start_tmstamp + $duration;
282 $utc_end = export_get_utc_date(date("Ymd", $end_tmstamp), date("His", $end_tmstamp));
283 echo "DTEND:$utc_end\r\n";
285 } elseif (strcmp($texport,"vcal") == 0) {
287 $end_tmstamp = $start_tmstamp + 24*60*60;
288 $utc_end = date("Ymd", $end_tmstamp);
289 echo "DTEND:$utc_end\r\n";
291 $end_tmstamp = $start_tmstamp + $duration;
292 $utc_end = export_get_utc_date(date("Ymd", $end_tmstamp), date("His", $end_tmstamp));
293 echo "DTEND:$utc_end\r\n";
296 echo "DURATION:P$str_duration\r\n";
300 function export_recurrence_ical($id, $date) {
301 $sql = "SELECT cal_date FROM webcal_entry_repeats_not WHERE cal_id = '$id'";
303 $res = dbi_query($sql);
308 while ($row = dbi_fetch_row($res)) {
309 $exdate[$i] = $row[0];
314 dbi_free_result($res);
316 $sql = "SELECT webcal_entry_repeats.cal_type, webcal_entry_repeats.cal_end, "
317 . "webcal_entry_repeats.cal_frequency, webcal_entry_repeats.cal_days, webcal_entry.cal_time"
318 . " FROM webcal_entry, webcal_entry_repeats WHERE webcal_entry_repeats.cal_id = '$id'"
319 . "AND webcal_entry.cal_id = '$id'";
321 $res = dbi_query($sql);
324 $row = dbi_fetch_row($res);
332 $str_day = array( 'SU','MO','TU','WE','TH','FR','SA' );
337 /* recurrence frequency */
346 case 'monthlyByDate' :
354 echo ";INTERVAL=$freq";
356 if ($type == "weekly") {
357 if ($day != "nnnnnnn") {
359 for ($i = 0; $i < strlen($day); $i++) {
360 if ($day[$i] == 'y') {
361 $byday .= $str_day[$i] .",";
364 $byday = substr($byday, 0, strlen($byday)-1); // suppress last ','
367 } elseif ($type == "monthlyByDate") {
368 $day = (int) substr($date,-2,2);
370 echo ";BYMONTHDAY=$day";
371 } elseif ($type == "monthlyByDay") {
374 $year = (int) substr($date,0,-4);
375 $month = (int) substr($date,-4,2);
376 $day = (int) substr($date,-2,2);
378 $stamp = mktime(0, 0, 0, $month, $day, $year);
380 $date_array = getdate($stamp);
382 echo $str_day[$date_array['wday']];
384 $next_stamp = $stamp + 7 * 24 * 60 * 60;
386 $next_date_array = getdate($next_stamp);
388 if ($date_array['mon'] != $next_date_array['mon'])
391 $pos = (int) ($day / 7);
393 if (($day % 7) > 0) {
397 echo ";BYSETPOS=$pos";
403 $utc = export_get_utc_date($end, $time);
410 if (count($exdate) > 0) {
413 while ($i < count($exdate)) {
414 $date = export_get_utc_date($exdate[$i],$time);
419 $string = substr($string, 0, strlen($string)-1); // suppress last ','
421 $string = export_fold_lines($string);
423 while (list($key,$value) = each($string))
429 function export_recurrence_vcal($id, $date) {
430 $sql = "SELECT cal_date FROM webcal_entry_repeats_not WHERE cal_id = '$id'";
431 $res = dbi_query($sql);
435 while ($row = dbi_fetch_row($res)) {
440 dbi_free_result($res);
442 $sql = "SELECT webcal_entry_repeats.cal_type, webcal_entry_repeats.cal_end, "
443 . "webcal_entry_repeats.cal_frequency, webcal_entry_repeats.cal_days, webcal_entry.cal_time"
444 . " FROM webcal_entry, webcal_entry_repeats WHERE webcal_entry_repeats.cal_id = '$id'"
445 . "AND webcal_entry.cal_id = '$id'";
447 $res = dbi_query($sql);
448 $row = dbi_fetch_row($res);
458 $str_day = array('SU','MO','TU','WE','TH','FR','SA');
463 /* recurrence frequency */
474 case 'monthlyByDayR':
477 case 'monthlyByDate' :
487 if ($type == "weekly") {
488 if ($day != "nnnnnnn") {
489 for ($i=0; $i < strlen($day); $i++) {
490 if ($day[$i] == 'y') {
491 $byday .= $str_day[$i] ." ";
496 } elseif ($type == "monthlyByDate") {
497 $day = (int) substr($date,-2,2);
499 } elseif (($type == "monthlyByDay") || ($type == "monthlyByDayR")) {
500 $year = (int) substr($date,0,-4);
501 $month = (int) substr($date,-4,2);
502 $day = (int) substr($date,-2,2);
504 $stamp = mktime(0, 0, 0, $month, $day, $year);
505 $date_array = getdate($stamp);
506 $day_no = $str_day[$date_array['wday']];
508 $next_stamp = $stamp + 7 * 24 * 60 * 60;
509 $next_date_array = getdate($next_stamp);
511 if ($date_array['mon'] != $next_date_array['mon']) {
514 $pos = (int) ($day / 7);
515 if (($day % 7) > 0) {
519 echo $pos."+ $day_no ";
520 } elseif ($type == "yearly") {
521 $month = (int) substr($date,-4,2);
525 // End Date - For all types
527 //echo export_get_utc_date($end, $time);
535 // Repeating Exceptions
536 $num = count($exdate);
540 for ($i=0;$i<$num;$i++) {
541 $string .= $exdate[$i]."T000000,";
543 echo rtrim($string,",")."\r\n";
551 * Create a date-time format (e.g. "20041130T123000Z") that is
552 * converted from local timezone to GMT.
554 function export_get_utc_date($date, $time=0) {
555 $year = (int) substr($date,0,-4);
556 $month = (int) substr($date,-4,2);
557 $day = (int) substr($date,-2,2);
564 $hour = (int) substr($time,0,-4);
565 $min = (int) substr($time,-4,2);
566 $sec = (int) substr($time,-2,2);
569 $tmstamp = mktime($hour, $min, $sec, $month, $day, $year);
571 $utc_date = gmdate("Ymd", $tmstamp);
572 $utc_hour = gmdate("His", $tmstamp);
574 $utc = sprintf ("%sT%sZ", $utc_date, $utc_hour);
579 function export_alarm_vcal($id,$date,$time=0) {
580 $sql = "SELECT cal_data FROM webcal_site_extras " .
581 "WHERE cal_id = $id AND cal_type = 7 AND cal_remind = 1";
582 $res = dbi_query ( $sql );
583 $row = dbi_fetch_row ( $res );
584 dbi_free_result ( $res );
588 $offset = $row[0] * 60; // How many seconds
589 $year = (int) substr($date,0,-4);
590 $month = (int) substr($date,-4,2);
591 $day = (int) substr($date,-2,2);
592 $hour = ($time > 0) ? (int) substr($time,0,-4) : 0;
593 $min = ($time > 0) ? (int) substr($time,-4,2) : 0;
594 $sec = ($time > 0) ? (int) substr($time,-2,2) : 0;
595 $stamp = mktime($hour, $min, $sec, $month, $day, $year);
596 $atime = $stamp - $offset;
597 echo gmdate("Ymd\THis\Z", $atime)."\r\n";
602 function export_alarm_ical($id, $description) {
603 $sql = "SELECT cal_data FROM webcal_site_extras " .
604 "WHERE cal_id = $id AND cal_type = 7 AND cal_remind = 1";
605 $res = dbi_query ( $sql );
606 $row = dbi_fetch_row ( $res );
607 dbi_free_result ( $res );
610 echo "BEGIN:VALARM\r\n";
611 echo "TRIGGER:-PT".$row[0]."M\r\n";
612 echo "ACTION:DISPLAY\r\n";
614 $array = export_fold_lines($description,"utf8");
615 while (list($key,$value) = each($array)) {
619 echo "END:VALARM\r\n";
624 function generate_uid() {
625 $rand = mt_rand(1000000,9999999);
627 $utc_id_date = gmdate("Ymd", mktime());
628 $utc_id_hour = gmdate("His", mktime());
629 $pid = getmypid() or die ("System error");
630 $host = getenv("SERVER_NAME");
632 return sprintf ("%sT%sZ-%d-%d@%s", $utc_id_date, $utc_id_hour, $rand, $pid, $host);
636 function export_vcal ($id) {
638 header ( "Content-Type: text/x-vcalendar" );
639 //header ( "Content-Type: text/plain" );
641 $res = export_get_event_entry($id);
643 $entry_array = array();
646 while ( $entry = dbi_fetch_row($res) ) {
647 $entry_array[$count++] = $entry;
650 dbi_free_result($res);
652 if (count($entry_array) > 0) {
653 echo "BEGIN:VCALENDAR\r\n";
655 echo "VERSION:1.0\r\n";
659 $gmdate = gmmktime();
660 $tzdiff = ($gmdate - $tzdate) / 60 / 60; //FIXME only hours are represented
662 $tz = sprintf("%02d", $tzdiff);
665 echo ($tzdiff >= 0) ? "+" : "-";
671 while (list($key,$row) = each($entry_array)) {
673 $export_uid = generate_uid();
679 $create_by = $row[6];
682 $description = $row[9];
685 echo "BEGIN:VEVENT\r\n";
687 /* UID of the event (folded to 76 char) */
688 $export_uid = "UID:$export_uid";
689 $array = export_fold_lines($export_uid);
690 while (list($key,$value) = each($array))
693 /* SUMMARY of the event (folded to 76 char) */
694 $name = preg_replace("/\\\\/", "\\\\\\", $name); // ??
695 $name = "SUMMARY;ENCODING=QUOTED-PRINTABLE:" . $name;
696 $array = export_fold_lines($name,"quotedprintable");
698 while (list($key,$value) = each($array))
701 /* DESCRIPTION if any (folded to 76 char) */
702 if ($description != "") {
703 $description = preg_replace("/\\\\/", "\\\\\\", $description); // ??
704 $description = "DESCRIPTION;ENCODING=QUOTED-PRINTABLE:" . $description;
705 $array = export_fold_lines($description,"quotedprintable");
706 while (list($key,$value) = each($array))
708 } //end if ($description != "")
710 /* CLASS either "PRIVATE" or "PUBLIC" (the default) */
711 if ($access == "R") {
712 echo "CLASS:PRIVATE\r\n";
714 echo "CLASS:PUBLIC\r\n";
717 // ATTENDEE of the event
718 $attendee = export_get_attendee($row[0], "vcal");
720 for ($i = 0; $i < count($attendee); $i++) {
721 $attendee[$i] = export_fold_lines($attendee[$i],"quotedprintable");
722 while (list($key,$value) = each($attendee[$i]))
726 /* Time - all times are utc */
727 export_time($date, $duration, $time, "vcal");
729 export_recurrence_vcal($uid, $date);
731 // FIXME: handle alarms
732 export_alarm_vcal($uid,$date,$time);
736 } //end while (list($key,$row) = each($entry_array))
738 if (count($entry_array) > 0)
739 echo "END:VCALENDAR\r\n";
742 function export_ical ($id) {
745 header ( "Content-Type: text/calendar" );
746 //header ( "Content-Type: text/plain" );
748 $res = export_get_event_entry($id);
750 $entry_array = array();
753 while ( $entry = dbi_fetch_row($res) ) {
754 $entry_array[$count++] = $entry;
758 echo "BEGIN:VCALENDAR\r\n";
760 echo "VERSION:2.0\r\n";
761 echo "METHOD:PUBLISH\r\n";
764 while (list($key,$row) = each($entry_array)) {
766 $export_uid = generate_uid();
772 $create_by = $row[6];
775 $description = $row[9];
778 echo "BEGIN:VEVENT\r\n";
780 /* UID of the event (folded to 76 char) */
781 $array = export_fold_lines("UID:$export_uid");
782 while (list($key,$value) = each($array))
785 $name = preg_replace("/\r/", "", $name);
786 //$name = preg_replace("/\n/", "\\n", $name); //PER RFC2445
787 $name = preg_replace("/\\\\/", "\\\\\\", $name); // ??
788 $description = preg_replace("/\r/", "", $description);
789 //$description = preg_replace("/\n/", "\\n", $description); //PER RFC2445
790 $description = preg_replace("/\\\\/", "\\\\\\", $description); // ??
792 /* SUMMARY of the event (folded to 76 char) */
793 $name = "SUMMARY:" . $name;
794 $array = export_fold_lines($name,"utf8");
796 while (list($key,$value) = each($array))
799 /* DESCRIPTION if any (folded to 76 char) */
800 if ($description != "") {
801 $description = "DESCRIPTION:" . $description;
802 $array = export_fold_lines($description,"utf8");
803 while (list($key,$value) = each($array))
807 /* CLASS either "PRIVATE" or "PUBLIC" (the default) */
808 if ($access == "R") {
809 echo "CLASS:PRIVATE\r\n";
811 echo "CLASS:PUBLIC\r\n";
814 // ATTENDEE of the event
815 $attendee = export_get_attendee($row[0], "ical");
817 for ($i = 0; $i < count($attendee); $i++) {
818 $attendee[$i] = export_fold_lines($attendee[$i],"utf8");
819 while (list($key,$value) = each($attendee[$i]))
823 /* Time - all times are utc */
824 export_time($date, $duration, $time, "ical");
827 export_recurrence_ical($uid, $date);
829 // FIXME: handle alarms
830 export_alarm_ical($uid, $description);
833 echo "END:VEVENT\r\n";
834 } //end while (list($key,$row) = each($entry_array))
837 echo "END:VCALENDAR\r\n";
841 // convert time in ("hhmmss") format, plus duration (as a number of
842 // minutes), to end time ($hour = number of hours, $min = number of
844 // FIXME: doesn't handle wrap to next day correctly.
845 function get_end_time ( $time, $duration, &$hour, &$min) {
846 $hour = (int) ( $time / 10000 );
847 $min = ( $time / 100 ) % 100;
848 $minutes = $hour * 60 + $min + $duration;
849 $hour = $minutes / 60;
850 $min = $minutes % 60;
853 // convert calendar date to a format suitable for the install-datebook
854 // utility (part of pilot-link)
855 function pilot_date_time ( $date, $time, $duration, $csv=false ) {
856 $year = (int) ( $date / 10000 );
857 $month = (int) ( $date / 100 ) % 100;
859 get_end_time ( $time, $duration, $hour, $min );
861 // Assume that the user is in the same timezone as server
862 $tz_offset = date ( "Z" ); // in seconds
863 $tzh = (int) ( $tz_offset / 3600 );
864 $tzm = (int) ( $tz_offset / 60 ) % 60;
872 return sprintf ( "%04d-%02d-%02d%s%02d:%02d:00",
873 $year, $month, $mday, $csv, $hour, $min );
875 return sprintf ( "%04d/%02d/%02d %02d%02d GMT%s%d%02d",
876 $year, $month, $mday, $hour, $min, $tzsign, $tzh, $tzm );
879 function export_install_datebook ($id) {
880 $res = export_get_event_entry($id);
882 while ( $row = dbi_fetch_row ( $res ) ) {
883 $start_time = pilot_date_time ( $row[3], $row[4], 0 );
884 $end_time = pilot_date_time ( $row[3], $row[4], $row[8] );
885 printf ( "%s\t%s\t\t%s\n",
886 $start_time, $end_time, $row[1] );
887 echo "Start time: $start_time\n";
888 echo "End time: $end_time\n";
889 echo "Duration: $row[8]\n";
890 echo "Name: $row[1]\n";
894 function get_cal_ent_extras($id, $from, $where = false) {
895 $res = dbi_query( "SELECT * FROM $from WHERE cal_id='$id'". ( $where?"AND ( $where );":';') );
897 return ( dbi_fetch_row($res) );
902 function export_pilot_csv ($id) {
903 /* to be imported to a Palm with:
904 * pilot-datebook -r csv -f webcalendar-export.txt -w hotsync
907 $res = export_get_event_entry($id);
909 echo "uid,attributes,category,untimed,beginDate,beginTime,endDate,endTime,description,note,alarm,advance,advanceUnit,repeatType,repeatForever,repeatEnd,repeatFrequency,repeatDay,repeatWeekdays,repeatWeekstart\n";
910 while ( $row = dbi_fetch_row ( $res ) ) {
914 // 128 = 0x80 : Deleted
917 // 16 = 0x10 : Secret/Private
918 echo ($row[7] == 'R')?'16,':'0,';
919 // category (int: 0=Unfiled)
921 // untimed (int: 0=Appointment, 1=Untimed)
922 // note: Palm "Untimed" is WebCalendar "AllDay"
926 substr($row[3],0,4), '-', // beginDate (str: YYYY-MM-DD) + beginTime
927 substr($row[3],4,2), '-',
928 substr($row[3],6,2), ',00:00:00,',
929 substr($row[3],0,4), '-', // endDate + endTime
930 substr($row[3],4,2), '-',
931 substr($row[3],6,2), ',00:00:00,';
933 echo '0,', // untimed
934 pilot_date_time($row[3], $row[4], 0, ','), ',', // beginDate,beginTime
935 pilot_date_time($row[3], $row[4], $row[8], ','), ','; //endDate,endTime
936 } //end if ( $row[4] < 0 )
938 echo '"', preg_replace("/\x0D?\n/", "\\n", $row[1]), '",';
940 echo '"', preg_replace("/\x0D?\n/", "\\n", $row[9]), '",';
941 // alarm, advance, advanceUnit
942 // alarm (int: 0=no alarm, 1=alarm)
943 // FIXME: verify if WebCal. DB interpreted correctly
944 // advance (int), advanceUnit (int: 0=minutes, 1=hours, 2=days)
945 // FIXME: better adjust unit
946 $ext = get_cal_ent_extras($row[0], 'webcal_site_extras', "cal_name = 'Reminder' AND cal_remind = 1");
948 echo '1,', $ext[5], ',0,';
952 // repeatType (int: 0=none, 1=daily, 2=weekly, 3=monthly, 4=monthly/weekday,
953 // repeatForever (int: 0=not forever, 1=forever) 5=yearly)
955 // repeatFrequency (int)
956 // repeatDay (int: day# or 0..6=Sun..Sat 1st, 7..13 2nd, 14..20 3rd,
957 // 21..27 4th, 28-34 last week)
958 // repeatWeekdays (int: add - 1=Sun,2=Mon,4=Tue,8=Wed,16=Thu,32=Fri,64=Sat)
959 // repeatWeekstart (int)
960 $ext = get_cal_ent_extras($row[0], 'webcal_entry_repeats');
963 case 'daily': $repType = 1; break;
964 case 'weekly': $repType = 2; break;
965 case 'monthlyByDate': $repType = 3; break;
966 case 'monthlyByDay': $repType = 4; break;
967 case 'yearly': $repType = 5; break;
968 default: $repType = 0;
972 echo $repType, ','; // repeatType
974 echo '0,', // repeatForever
975 substr($ext[2],0,4), '-', // repeatEnd
976 substr($ext[2],4,2), '-',
977 substr($ext[2],6,2), ' 00:00:00,';
979 echo '1,,'; // repeatForever,repeatEnd
980 echo $ext[3], ',';// repeatFrequency
981 switch ( $repType ) {
983 echo '0,', bindec(strtr(strrev($ext[4]),'yn','10')) ,",1\n";
985 case 3: // monthly/weekday
986 // repeatDay (0..6=Sun..Sat 1st, 7..13 2nd, 14..20 3rd,
987 // 21..27 4th, 28-34 last week)
988 echo floor( substr($row[3], 6, 2) / 7) *7
989 + date( 'w', date_to_epoch($row[3]) ), ",0,0\n";
997 echo "0,0,,0,0,0,0\n";
998 } //end if ( $repType )
1001 function transmit_header ( $mime, $file ) {
1002 header ( "Content-Type: application/octet-stream" );
1003 //header ( "Content-Type: $mime" );
1004 header ( 'Content-Disposition: attachment; filename="' . $file . '"');
1005 header ( 'Pragma: no-cache');
1006 header ( 'Cache-Control: no-cache' );
1009 /*******************************************/
1011 /*******************************************/
1013 $id = getIntValue ( 'id', true );
1014 $format = getValue ( 'format' );
1015 if ( $format != 'ical' && $format != 'vcal' && $format != 'pilot-csv' &&
1016 $format != 'pilot-text' )
1017 die_miserable_death ( "Invalid format '" . $format . "'" );
1019 $use_all_dates = getPostValue ( 'use_all_dates' );
1020 if ( $use_all_dates != 'y' )
1021 $use_all_dates = '';
1023 $include_layers = getPostValue ( 'include_layers' );
1024 if ( $include_layers != 'y' )
1025 $include_layers = '';
1027 $fromyear = getIntValue ( 'fromyear', true );
1028 $frommonth = getIntValue ( 'frommonth', true );
1029 $fromday = getIntValue ( 'fromday', true );
1030 $endyear = getIntValue ( 'endyear', true );
1031 $endmonth = getIntValue ( 'endmonth', true );
1032 $endday = getIntValue ( 'endday', true );
1033 $modyear = getIntValue ( 'modyear', true );
1034 $modmonth = getIntValue ( 'modmonth', true );
1035 $modday = getIntValue ( 'modday', true );
1037 mt_srand((float) microtime()*1000000);
1043 if ($format == "ical") {
1044 transmit_header ( 'text/ical', "webcalendar-$id.ics" );
1046 } elseif ($format == "vcal") {
1047 transmit_header ( 'text/vcal', "webcalendar-$id.vcs" );
1049 } elseif ($format == "pilot-csv") {
1050 transmit_header ( 'text/csv', "webcalendar-$id.csv" );
1051 export_pilot_csv ( $id );
1052 } elseif ($format == "pilot-text") {
1053 transmit_header('text/plain', "webcalendar-$id.txt" );
1054 export_install_datebook($id);
1061 etranslate("Export");
1063 etranslate("Error");
1065 echo "<span style=\"font-weight:bold;\">";
1066 etranslate("Error");
1068 echo translate("export format not defined or incorrect") . ".";
1075 } //end if ($format == "ical")