function query_events($user, $want_repeated, $date_filter, $cat_id = '', $is_task = false) { global $db_connection_info, $jumpdate, $layers, $login, $max_until, $PUBLIC_ACCESS_DEFAULT_VISIBLE, $result, $thismonth, $thisyear; global $OVERRIDE_PUBLIC, $OVERRIDE_PUBLIC_TEXT; // New multiple categories requires some checking to see if this cat_id is // valid for this cal_id. It could be done with nested SQL, // but that may not work for all databases. This might be quicker also. $catlist = $cloneRepeats = $layers_byuser = $result = array(); $sql = 'SELECT DISTINCT( cal_id ) FROM webcal_entry_categories '; // None was selected...return only events without categories. if ($cat_id == -1) { $rows = dbi_get_cached_rows($sql, array()); } elseif (!empty($cat_id)) { $cat_array = explode(',', $cat_id); $placeholders = ''; for ($p_i = 0, $cnt = count($cat_array); $p_i < $cnt; $p_i++) { $placeholders .= $p_i == 0 ? '?' : ', ?'; } $rows = dbi_get_cached_rows($sql . 'WHERE cat_id IN ( ' . $placeholders . ' )', $cat_array); } if (!empty($cat_id)) { // $rows = dbi_get_cached_rows ( $sql, array ( $cat_id ) ); if ($rows) { for ($i = 0, $cnt = count($rows); $i < $cnt; $i++) { $row = $rows[$i]; $catlist[$i] = $row[0]; } } } $catlistcnt = count($catlist); $query_params = array(); $sql = 'SELECT we.cal_name, we.cal_description, we.cal_date, we.cal_time, we.cal_id, we.cal_ext_for_id, we.cal_priority, we.cal_access, we.cal_duration, weu.cal_status, we.cal_create_by, weu.cal_login, we.cal_type, we.cal_location, we.cal_url, we.cal_due_date, we.cal_due_time, weu.cal_percent, we.cal_mod_date, we.cal_mod_time ' . ($want_repeated ? ', wer.cal_type, wer.cal_end, wer.cal_frequency, wer.cal_days, wer.cal_bymonth, wer.cal_bymonthday, wer.cal_byday, wer.cal_bysetpos, wer.cal_byweekno, wer.cal_byyearday, wer.cal_wkst, wer.cal_count, wer.cal_endtime FROM webcal_entry we, webcal_entry_repeats wer, webcal_entry_user weu WHERE we.cal_id = wer.cal_id AND ' : 'FROM webcal_entry we, webcal_entry_user weu WHERE ') . 'we.cal_id = weu.cal_id AND weu.cal_status IN ( \'A\',\'W\' ) '; if ($catlistcnt > 0) { $placeholders = ''; for ($p_i = 0; $p_i < $catlistcnt; $p_i++) { $placeholders .= $p_i == 0 ? '?' : ', ?'; $query_params[] = $catlist[$p_i]; } if ($cat_id > 0) { $sql .= 'AND we.cal_id IN ( ' . $placeholders . ' ) '; } elseif ($cat_id == -1) { // Eliminate events with categories. $sql .= 'AND we.cal_id NOT IN ( ' . $placeholders . ' ) '; } } else { if (!empty($cat_id)) { // Force no rows to be returned. No matching entries in category. $sql .= 'AND 1 = 0 '; } } $sql .= 'AND we.cal_type IN ' . ($is_task == false ? '( \'E\',\'M\' ) ' : '( \'N\',\'T\' ) AND ( we.cal_completed IS NULL ) ') . (strlen($user) > 0 ? 'AND ( weu.cal_login = ? ' : ''); $query_params[] = $user; if ($user == $login && strlen($user) > 0 && $layers) { foreach ($layers as $layer) { $layeruser = $layer['cal_layeruser']; $sql .= 'OR weu.cal_login = ? '; $query_params[] = $layeruser; // While we are parsing the whole layers array, build ourselves // a new array that will help when we have to check for dups. $layers_byuser[$layeruser] = $layer['cal_dups']; } } $rows = dbi_get_cached_rows($sql . ($user == $login && strlen($user) && $PUBLIC_ACCESS_DEFAULT_VISIBLE == 'Y' ? 'OR weu.cal_login = \'__public__\' ' : '') . (strlen($user) > 0 ? ') ' : '') . $date_filter . (!$is_task ? ' ORDER BY we.cal_time, we.cal_name' : ''), $query_params); if ($rows) { $i = 0; $checkdup_id = $first_i_this_id = -1; for ($ii = 0, $cnt = count($rows); $ii < $cnt; $ii++) { $row = $rows[$ii]; if ($row[9] == 'D' || $row[9] == 'R') { continue; } // Don't show deleted/rejected ones. // Get primary category for this event, used for icon and color. $categories = get_categories_by_id($row[4], $user); $cat_keys = array_keys($categories); $primary_cat = empty($cat_keys[0]) ? '' : $cat_keys[0]; if ($login == '__public__' && !empty($OVERRIDE_PUBLIC) && $OVERRIDE_PUBLIC == 'Y') { $evt_name = $OVERRIDE_PUBLIC_TEXT; $evt_descr = $OVERRIDE_PUBLIC_TEXT; } else { $evt_name = $row[0]; $evt_descr = $row[1]; } if ($want_repeated && !empty($row[20])) { // row[20] = cal_type $item = new RepeatingEvent($evt_name, $evt_descr, $row[2], $row[3], $row[4], $row[5], $row[6], $row[7], $row[8], $row[9], $row[10], $primary_cat, $row[11], $row[12], $row[13], $row[14], $row[15], $row[16], $row[17], $row[18], $row[19], $row[20], $row[21], $row[22], $row[23], $row[24], $row[25], $row[26], $row[27], $row[28], $row[29], $row[30], $row[31], $row[32], array(), array(), array()); } else { $item = new Event($evt_name, $evt_descr, $row[2], $row[3], $row[4], $row[5], $row[6], $row[7], $row[8], $row[9], $row[10], $primary_cat, $row[11], $row[12], $row[13], $row[14], $row[15], $row[16], $row[17], $row[18], $row[19]); } if ($item->getID() != $checkdup_id) { $checkdup_id = $item->getID(); $first_i_this_id = $i; } if ($item->getLogin() == $user) { // Insert this one before all other ones with this ID. array_splice($result, $first_i_this_id, 0, array($item)); $i++; if ($first_i_this_id + 1 < $i) { // There's another one with the same ID as the one we inserted. // Check for dup and if so, delete it. $other_item = $result[$first_i_this_id + 1]; if (!empty($layers_byuser[$other_item->getLogin()]) && $layers_byuser[$other_item->getLogin()] == 'N') { // NOTE: array_splice requires PHP4 array_splice($result, $first_i_this_id + 1, 1); $i--; } } } else { if ($i == $first_i_this_id || !empty($layers_byuser[$item->getLogin()]) && $layers_byuser[$item->getLogin()] != 'N') { // This item either is the first one with its ID, or allows dups. // Add it to the end of the array. $result[$i++] = $item; } } // Does event go past midnight? if (date('Ymd', $item->getDateTimeTS()) != date('Ymd', $item->getEndDateTimeTS()) && !$item->isAllDay() && $item->getCalTypeName() == 'event') { getOverLap($item, $i, true); $i = count($result); } } } if ($want_repeated) { // Now load event exceptions/inclusions and store as array. // TODO: Allow passing this max_until as param in case we create // a custom report that shows N years of events. if (empty($max_until)) { $max_until = mktime(0, 0, 0, $thismonth + 2, 1, $thisyear); } for ($i = 0, $resultcnt = count($result); $i < $resultcnt; $i++) { if ($result[$i]->getID() != '') { $rows = dbi_get_cached_rows('SELECT cal_date, cal_exdate FROM webcal_entry_repeats_not WHERE cal_id = ?', array($result[$i]->getID())); for ($ii = 0, $rowcnt = count($rows); $ii < $rowcnt; $ii++) { $row = $rows[$ii]; // If this is not a clone, add exception date. if (!$result[$i]->getClone()) { $except_date = $row[0]; } if ($row[1] == 1) { $result[$i]->addRepeatException($except_date, $result[$i]->getID()); } else { $result[$i]->addRepeatInclusion($except_date); } } // Get all dates for this event. // If clone, we'll get the dates from parent later. if (!$result[$i]->getClone()) { $until = $result[$i]->getRepeatEndDateTimeTS() ? $result[$i]->getRepeatEndDateTimeTS() : $max_until; // Try to minimize the repeat search by shortening // until if BySetPos is not used. if (!$result[$i]->getRepeatBySetPos() && $until > $max_until) { $until = $max_until; } $rpt_count = 999; //Some BIG number. // End date... for year view and some reports we need whole year... // So, let's do up to 365 days after current month. // TODO: Add this end time as a parameter in case someone creates // a custom report that asks for N years of events. // $jump = mktime ( 0, 0, 0, $thismonth -1, 1, $thisyear); if ($result[$i]->getRepeatCount()) { $rpt_count = $result[$i]->getRepeatCount() - 1; } $date = $result[$i]->getDateTimeTS(); if ($result[$i]->isAllDay() || $result[$i]->isUntimed()) { $date += 43200; } //A simple hack to prevent DST problems. // TODO get this to work // C heck if this event id has been cached. // $file = ''; // if ( ! empty ( $db_connection_info['cachedir'] ) ){ // $hash = md5 ( $result[$i]->getId () . $until . $jump ); // $file = $db_connection_info['cachedir'] . '/' . $hash . '.dat'; // } // if ( file_exists ( $file ) ) { // $dates = unserialize ( file_get_contents ( $file ) ); // } else { $dates = get_all_dates($date, $result[$i]->getRepeatType(), $result[$i]->getRepeatFrequency(), array($result[$i]->getRepeatByMonth(), $result[$i]->getRepeatByWeekNo(), $result[$i]->getRepeatByYearDay(), $result[$i]->getRepeatByMonthDay(), $result[$i]->getRepeatByDay(), $result[$i]->getRepeatBySetPos()), $rpt_count, $until, $result[$i]->getRepeatWkst(), $result[$i]->getRepeatExceptions(), $result[$i]->getRepeatInclusions(), $jumpdate); $result[$i]->addRepeatAllDates($dates); // Serialize and save in cache for later use. // if ( ! empty ( $db_connection_info['cachedir'] ) ) { // $fd = @fopen ( $file, 'w+b', false ); // if ( empty ( $fd ) ) { // dbi_fatal_error ( "Cache error: could not write file $file" ); // } // fwrite ( $fd, serialize ( $dates ) ); // fclose ( $fd ); // chmod ( $file, 0666 ); // } // } } else { // Process clones if any. if (count($result[$i - 1]->getRepeatAllDates()) > 0) { $parentRepeats = $result[$i - 1]->getRepeatAllDates(); $cloneRepeats = array(); for ($j = 0, $parentRepeatscnt = count($parentRepeats); $j < $parentRepeatscnt; $j++) { $cloneRepeats[] = gmdate('Ymd', date_to_epoch($parentRepeats[$j]) + ONE_DAY); } $result[$i]->addRepeatAllDates($cloneRepeats); } } } } } return $result; }
// Confidential and not user's and not assistant, // then they cannot see name or description. // if ( $row[8] == "R" && ! $is_my_event && ! $is_admin ) { if ($cal_access == 'R' && !$is_my_event && !access_is_enabled()) { $is_private = true; $description = $name = '[' . translate('Private') . ']'; } else { if ($cal_access == 'C' && !$is_my_event && !$is_assistant && !access_is_enabled()) { $is_confidential = true; $description = $name = '[' . translate('Confidential') . ']'; } } $event_date = $event_repeats && !empty($date) ? $date : ($event_time > 0 ? date('Ymd', date_to_epoch($orig_date . sprintf("%06d", $event_time))) : $orig_date); // Get category Info if ($CATEGORIES_ENABLED == 'Y') { $categories = get_categories_by_id($id, !empty($user) && strlen($user) && ($is_assistant || $is_admin) ? $user : $login, true); $category = implode(', ', $categories); } // get reminders $reminder = getReminders($id, true); echo ' <h2>' . $name . ($is_nonuser_admin || $is_admin && !empty($user) && $user == '__public__' ? ' ( ' . translate('Admin mode') . ' )' : '') . ($is_assistant ? ' ( ' . translate('Assistant mode') . ' )' : '') . '</h2> <table width="100%" summary=""> <tr> <td class="aligntop bold" width="10%">' . translate('Description') . ':</td> <td>'; if (!empty($ALLOW_HTML_DESCRIPTION) && $ALLOW_HTML_DESCRIPTION == 'Y') { $str = $description; // $str = str_replace ( '&', '&', $description ); $str = str_replace('&amp;', '&', $str); // If there is no HTML found, then go ahead and replace
$error = print_not_auth(31); } } else { // Not a participant for this event. $error = print_not_auth(32); } dbi_free_result($res); } else { $error = db_error(); } $cat_id = getValue('cat_id', '-?[0-9,\\-]*', true); $cat_ids = $cat_name = array(); $catNames = ''; // Get user's categories for this event. $globals_found = false; $categories = get_categories_by_id($id, $login, true); if (!empty($categories)) { $catNames = implode(', ', $categories); $keys = array_keys($categories); $catList = implode(',', $keys); sort($keys); if ($keys[0] < 0) { $globals_found = true; } } // Get event name and make sure event exists. $event_name = ''; $res = dbi_execute('SELECT cal_name FROM webcal_entry WHERE cal_id = ?', array($id)); if ($res) { if ($row = dbi_fetch_row($res)) { $event_name = $row[0];
function print_upcoming_event($e, $date) { global $display_link, $link_target, $SERVER_URL, $charset, $login, $display_tzid, $showTime, $showPopups, $eventinfo, $username, $hcalendar_output, $UPCOMING_DISPLAY_CAT_ICONS; $popupid = 'pop' . $e->getId() . '-' . $date; $private = $confidential = false; // Access: P=Public, R=Private, C=Confidential if ($e->getAccess() == 'R') { // not a public event, so we will just display "Private" $private = true; } else { if ($e->getAccess() == 'C') { // not a public event, so we will just display "Confidential" $confidential = true; } } if (!empty($SERVER_URL) && !$private && !$confidential) { echo "<div class=\"vevent\">\n"; if ($display_link) { if ($showPopups) { $timestr = ''; if ($e->isAllDay()) { $timestr = translate('All day event'); } else { if ($e->getTime() >= 0) { $timestr = display_time($e->getDatetime()); if ($e->getDuration() > 0) { $timestr .= ' - ' . display_time($e->getEndDateTime()); } } } $eventinfo .= build_entry_popup('eventinfo-' . $popupid, $username, $e->getDescription(), $timestr, site_extras_for_popup($e->getId()), $e->getLocation(), $e->getName(), $e->getId()); } $link = "<a class=\"entry\" id=\"{$popupid}\" title=\"" . htmlspecialchars($e->getName()) . '" href="' . $SERVER_URL . 'view_entry.php?id=' . $e->getID() . "&date={$date}&user="******"\" target=\"{$link_target}\""; } $link .= '>'; if (empty($UPCOMING_DISPLAY_CAT_ICONS) || $UPCOMING_DISPLAY_CAT_ICONS != 'N') { $catNum = abs($e->getCategory()); if ($catNum > 0) { $catIcon = 'icons/cat-' . $catNum . '.gif'; if (file_exists($catIcon)) { echo $link . '<img src="' . $catIcon . '" alt="category icon" border="0"/></a>'; } } } echo $link; } } if ($private) { echo '[' . translate('Private') . ']'; } else { if ($confidential) { echo '[' . translate('Confidential') . ']'; } else { echo '<span class="summary">' . htmlspecialchars($e->getName()) . '</span>'; } } if ($display_link && !empty($SERVER_URL) && !$private) { echo '</a>'; } //added for hCalendar if ($hcalendar_output) { echo '<abbr class="dtstart" title="' . export_ts_utc_date($e->getDateTimeTS()) . '">' . $e->getDateTime() . "</abbr>\n"; echo '<abbr class="dtend" title="' . export_ts_utc_date($e->getEndDateTimeTS()) . '">' . $e->getEndDateTimeTS() . "</abbr>\n"; echo '<span class="description">' . $e->getDescription() . "</span>\n"; if (strlen($e->getLocation()) > 0) { echo '<span class="location">' . $e->getLocation() . "</span>\n"; } $categories = get_categories_by_id($e->getId(), $username); $category = implode(', ', $categories); if (strlen($category) > 0) { echo '<span class="categories">' . htmlentities($category) . "</span>\n"; } if (strlen($e->getUrl()) > 0) { echo '<span class="url">' . $e->getUrl() . "</span>\n"; } $rrule = export_recurrence_ical($e->getId()); if (strlen($rrule) > 6) { echo '<span class="rrule">' . substr($rrule, 6) . "</span>\n"; } } if ($showTime) { //show event time if requested (default=don't show) if ($e->isAllDay()) { echo ' (' . translate('All day event') . ")\n"; } else { if ($e->getTime() != -1) { echo ' (' . display_time($e->getDateTime(), $display_tzid) . ")\n"; } } } echo "</div>\n"; }
// Get Repeat Exceptions. $res = dbi_execute('SELECT cal_date, cal_exdate FROM webcal_entry_repeats_not WHERE cal_id = ?', array($id)); if ($res) { while ($row = dbi_fetch_row($res)) { if ($row[1] == 1) { $exceptions[] = $row[0]; } else { $inclusions[] = $row[0]; } } dbi_free_result($res); } } if ($CATEGORIES_ENABLED == 'Y') { $catById = get_categories_by_id($id, $real_user, true); if (!empty($catById)) { $catNames = implode(', ', $catById); $catList = implode(',', array_keys($catById)); } } //end CATEGORIES_ENABLED test // Get reminders. $reminder = getReminders($id); $reminder_offset = empty($reminder) ? 0 : $reminder['offset']; $rem_status = count($reminder); $rem_use_date = !empty($reminder['date']); // Get participants. $res = dbi_execute('SELECT cal_login, cal_status FROM webcal_entry_user WHERE cal_id = ? AND cal_status IN ( \'A\', \'W\' )', array($id)); if ($res) {
function export_ical($id = 'all', $attachment = false) { global $publish_fullname, $login, $cal_type, $cat_filter, $vtimezone_data, $use_vtimezone; $exportId = -1; $ret = $Vret = $vtimezone_data = $use_vtimezone = ''; $res = export_get_event_entry($id, $attachment); $entry_array = array(); $count = 0; while ($entry = dbi_fetch_row($res)) { $entry_array[$count++] = $entry; } dbi_free_result($res); //abort if no records to output if ($count == 0) { return; } // Always output something, even if no records come back // This prevents errors on the iCal client $ret = "BEGIN:VCALENDAR\r\n"; $title = utf8_encode('X-WR-CALNAME;VALUE=TEXT:' . (empty($publish_fullname) ? $login : translate($publish_fullname))); $title = str_replace(',', "\\,", $title); $ret .= "{$title}\r\n"; $ret .= generate_prodid('ics'); $ret .= "VERSION:2.0\r\n"; $ret .= "METHOD:PUBLISH\r\n"; while (list($key, $row) = each($entry_array)) { $id = $row[0]; $event_uid = generate_uid($id); $name = $row[1]; $priority = $row[2]; $date = $row[3]; $time = sprintf("%06d", $row[4]); $status = $row[5]; $create_by = $row[6]; $access = $row[7]; $duration = $row[8]; $description = $row[9]; // New columns to support tasks $percent = empty($row[10]) ? 0 : $row[10]; $completed = empty($row[11]) ? '' : substr($row[11], 0, 8) . 'T' . sprintf("%06d", substr($row[11], 9, 6)); $due_date = $row[12]; $due_time = $row[13]; $location = $row[14]; $url = $row[15]; $cal_type = $row[16]; $moddate = $row[17]; $modtime = $row[18]; // Figure out Categories $categories = get_categories_by_id($id, $login); // Add entry in webcal_import_data if it does not exist. // Even thought we're exporting, this data needs to be valid // for proper parsing of response from iCal client. // If this is the first event that has never been published, // then create a new import instance to associate with what we are doing. $sql = 'SELECT wid.cal_external_id FROM webcal_import_data wid, webcal_entry_user weu WHERE wid.cal_id = weu.cal_id AND wid.cal_id = ? AND weu.cal_login = ?'; $res = dbi_execute($sql, array($id, $login)); if ($res) { if ($row = dbi_fetch_row($res)) { // event has been published (or imported) before $event_uid = $row[0]; } else { if ($exportId < 0) { // This is first event that has not been published before. // Create an entry in webcal_import. // It would be nice if we could put a name in here of who // or where the remote cal subscription is coming from in case // they update some of our events. But, I cannot see a way to // do that. $exportId = create_import_instance(); } if ($attachment == false) { save_uid_for_event($exportId, $id, $event_uid); } } dbi_free_result($res); } // get recurrance info $recurrance = export_recurrence_ical($id); if (!empty($recurrance)) { $use_vtimezone = true; } /* snippet from RFC2445 The "VTIMEZONE" calendar component MUST be present if the iCalendar object contains an RRULE that generates dates on both sides of a time zone shift (e.g. both in Standard Time and Daylight Saving Time) unless the iCalendar object intends to convey a floating time (See the section "4.1.10.11 Time" for proper interpretation of floating time). It can be present if the iCalendar object does not contain such a RRULE. In addition, if a RRULE is present, there MUST be valid time zone information for all recurrence instances. However, this is not possible to implement at this time */ // if Categories were selected as an export filter, then abort this // event if it does not contain that category if (!empty($cat_filter)) { if (count($categories) == 0 || !array_key_exists($cat_filter, $categories)) { continue; } } if ($cal_type == 'E' || $cal_type == 'M') { $exporting_event = true; /* Start of event */ $Vret .= "BEGIN:VEVENT\r\n"; } else { if ($cal_type == 'T' || $cal_type == 'N') { $exporting_event = false; /* Start of VTODO */ $Vret .= "BEGIN:VTODO\r\n"; } else { if ($cal_type == 'J' || $cal_type == 'O') { $exporting_event = false; /* Start of VJOURNAL */ $Vret .= "BEGIN:VJOURNAL\r\n"; } } } /* UID of the event (folded to 76 char) */ $array = export_fold_lines("UID:{$event_uid}"); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } $Vret .= 'LAST-MODIFIED:' . export_get_utc_date($moddate, $modtime) . "\r\n"; $name = preg_replace("/\r/", ' ', $name); // escape,; \ in octal ascii $name = addcslashes($name, ",;\\"); $description = preg_replace("/\r/", ' ', $description); $description = addcslashes($description, ",;\\"); $description = str_replace(chr(10), chr(92) . chr(110), $description); /* SUMMARY of the event (folded to 76 char) */ $name = 'SUMMARY:' . $name; $array = export_fold_lines($name, 'utf8'); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } /* DESCRIPTION if any (folded to 76 char) */ if ($description != '') { $description = 'DESCRIPTION:' . $description; $array = export_fold_lines($description, 'utf8'); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } } /* LOCATION if any (folded to 76 char) */ if ($location != '') { $location = 'LOCATION:' . $location; $array = export_fold_lines($location, 'utf8'); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } } /* URL if any (folded to 76 char) */ if ($url != '') { $url = 'URL:' . $url; $array = export_fold_lines($url, 'utf8'); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } } /* CATEGORIES if any (folded to 76 char) */ if (isset($categories) && count($categories)) { $categories = 'CATEGORIES:' . implode(',', $categories); $array = export_fold_lines($categories, 'utf8'); while (list($key, $value) = each($array)) { $Vret .= "{$value}\r\n"; } } /* CLASS either "PRIVATE", "CONFIDENTIAL", or "PUBLIC" (the default) */ if ($access == 'R') { $Vret .= "CLASS:PRIVATE\r\n"; } else { if ($access == 'C') { $Vret .= "CLASS:CONFIDENTIAL\r\n"; } else { $Vret .= "CLASS:PUBLIC\r\n"; } } /* STATUS */ if ($cal_type == 'E' || $cal_type == 'M') { if ($status == 'A') { $Vret .= "STATUS:CONFIRMED\r\n"; } else { if ($status == 'W') { $Vret .= "STATUS:TENTATIVE\r\n"; } else { if ($status == 'D') { $Vret .= "STATUS:CANCELLED\r\n"; } } } } else { if ($cal_type == 'T' || $cal_type == 'N') { if ($status == 'A' && empty($completed)) { $Vret .= "STATUS:IN-PROCESS\r\n"; } else { if ($status == 'A') { $Vret .= "STATUS:COMPLETED\r\n"; } else { if ($status == 'W') { $Vret .= "STATUS:NEEDS-ACTION\r\n"; } else { if ($status == 'D') { $Vret .= "STATUS:CANCELLED\r\n"; } } } } } } // ATTENDEE of the event $attendee = export_get_attendee($id, 'ical'); $attendcnt = count($attendee); for ($i = 0; $i < $attendcnt; $i++) { $attendee[$i] = export_fold_lines($attendee[$i], 'utf8'); while (list($key, $value) = each($attendee[$i])) { $Vret .= "{$value}\r\n"; } } /* Time - all times are utc */ $Vret .= export_time($date, $duration, $time, 'ical', $cal_type); // VTODO specific items $task_complete = false; if ($cal_type == 'T' || $cal_type == 'N') { $Vret .= 'DUE:' . $due_date . 'T' . sprintf("%06d", $due_time) . "Z\r\n"; if (!empty($completed)) { $Vret .= 'COMPLETED:' . $completed . "\r\n"; $task_complete = true; } $Vret .= 'PERCENT-COMPLETE:' . $percent . "\r\n"; } /* Recurrence */ $Vret .= $recurrance; /* handle alarms */ $Vret .= export_alarm_ical($id, $date, $description, $task_complete); if ($cal_type == 'E' || $cal_type == 'M') { /* End of event */ $Vret .= "END:VEVENT\r\n"; } else { if ($cal_type == 'T' || $cal_type == 'N') { /* Start of VTODO */ $Vret .= "END:VTODO\r\n"; } else { if ($cal_type == 'J' || $cal_type == 'O') { /* Start of VJOURNAL */ $Vret .= "END:VJOURNAL\r\n"; } } } } /* VTIMEZONE Set in export_time () if needed */ $ret .= $vtimezone_data . $Vret; $ret .= "END:VCALENDAR\r\n"; // attachment will be true if called during email creation if (!$attachment) { echo $ret; } else { return $ret; } }