1<?php 2 3/** 4 * SquirrelMail Shared Calendar Plugin 5 * Copyright (C) 2004-2005 Paul Lesneiwski <pdontthink@angrynerds.com> 6 * This program is licensed under GPL. See COPYING for details 7 * 8 */ 9 10 11 12include_once(SM_PATH . 'functions/date.php'); 13include_once(SM_PATH . 'plugins/calendar/constants.php'); 14include_once(SM_PATH . 'plugins/calendar/classes/calendar.php'); 15include_once(SM_PATH . 'plugins/calendar/classes/event.php'); 16include_once(SM_PATH . 'plugins/calendar/classes/property.php'); 17include_once(SM_PATH . 'plugins/calendar/backend_functions.php'); 18include_once(SM_PATH . 'plugins/calendar/data/config.php'); 19include_once(SM_PATH . 'plugins/calendar/timezone_offsets.php'); 20include_once(SM_PATH . 'plugins/calendar/load_prefs.php'); 21 22 23 24// load prefs (can't use loading_prefs hook due to a chicken-and-egg 25// problems with i18n'd strings in constants file (that is needed by 26// config file) 27// 28cal_load_prefs_do(); 29 30 31 32global $externalCalendars; 33if (!is_array($externalCalendars)) $externalCalendars = array(); 34 35 36 37/** 38 * Because there will always be someone who forgets 39 * to enable a backend, check for one here. Errors 40 * otherwise are hard to diagnose 41 * 42 */ 43global $squirrelmail_plugin_hooks, $color; 44if (empty($squirrelmail_plugin_hooks['get_calendar'])) 45{ 46 plain_error_message('ERROR: Please enable a calendar backend', $color); 47 exit; 48} 49 50 51 52/** 53 * Can we use JavaScript-enabled display elements? 54 * 55 * Ideally, this function would just be replaced with a 56 * call to checkForJavascript() but we need newest version 57 * of the Compatibility plugin for that, so we just do the 58 * dirty work ourselves (it's not much trouble anyway) 59 * 60 * @return mixed TRUE (or non-zero) if JavaScript is allowable, 61 * FALSE (or zero) otherwise. 62 * 63 */ 64function cal_use_javascript() 65{ 66 67 // only in 1.5.x 68 // 69 if (function_exists('checkForJavascript')) 70 return checkForJavascript(); 71 72 73 // distilled from checkForJavascript() 74 // 75 if (sqGetGlobalVar('javascript_on', $javascript_on, SQ_SESSION)) 76 return $javascript_on; 77 78 global $javascript_setting; 79 if (!isset($javascript_setting)) 80 $javascript_setting = getPref($data_dir, $username, 'javascript_setting', SMPREF_JS_OFF); 81 return $javascript_setting; 82 83} 84 85 86 87/** 88 * Get list of all external calendar from user prefs 89 * 90 * @return array Returns a list of all external calendars 91 * 92 */ 93function get_all_external_calendars() 94{ 95 96 global $username, $data_dir; 97 98 // get external calendars 99 // 100 $external_calendars = getPref($data_dir, $username, 'external_calendars', ''); 101 $externalCals = explode('||||', $external_calendars); 102 $external_list = array(); 103 foreach ($externalCals as $externalCal) 104 { 105 if (empty($externalCal)) continue; 106 107 list($id, $name, $uri) = explode('^^^^', $externalCal); 108 $cal = loadExternalCalendar($uri); 109//TODO: if just a temporary network outage, we might not want to just remove this... too harsh 110// so figure out how to deal with that better 111 if ($cal == FALSE) 112 { 113 removeExternalCalendarFromUserPrefs($id); 114 continue; 115 } 116 $external_list[] = $cal; 117 } 118 119 return $external_list; 120 121} 122 123 124 125/** 126 * Load calendar from user prefs 127 * 128 * @param string $calendarID The ID of the calendar to be loaded 129 * 130 * @return mixed Returns the Calendar object that represents the 131 * loaded calendar, or FALSE if the calendar could 132 * not be loaded 133 * 134 */ 135function loadExternalCalendarFromUserPrefs($calendarID) 136{ 137 138 global $username, $data_dir; 139 $external_calendars = getPref($data_dir, $username, 'external_calendars', ''); 140 141 $externalCals = explode('||||', $external_calendars); 142 foreach ($externalCals as $externalCal) 143 { 144 if (empty($externalCal)) continue; 145 146 list($id, $name, $uri) = explode('^^^^', $externalCal); 147 148 if ($id == $calendarID) 149 return loadExternalCalendar($uri); 150 } 151 152 return FALSE; 153 154} 155 156 157 158/** 159 * Load event from external calendar 160 * 161 * @param string $calendarID The ID of the calendar from which to get the event 162 * @param string $eventID The ID of the event to be loaded 163 * 164 * @return mixed Returns the Event object that represents the 165 * loaded event, or FALSE if the event could 166 * not be loaded 167 * 168 */ 169function loadExternalEvent($calendarID, $eventID) 170{ 171 172 $cal = loadExternalCalendarFromUserPrefs($calendarID); 173 if ($cal === FALSE) return FALSE; 174 175 return $cal->getEvent($eventID); 176 177} 178 179 180 181/** 182 * Load calendar from external URI 183 * 184 * @param string $URI The location of the calendar to be loaded 185 * 186 * @return mixed Returns the Calendar object that represents the 187 * loaded calendar, or FALSE if the calendar could 188 * not be loaded 189 * 190 */ 191function loadExternalCalendar($URI, $calID='') 192{ 193 194 global $username, $data_dir, $external_calendar_clock_skew, 195 $externalCalendars; 196 sqgetGlobalVar('externalCalendars', $externalCalendars, SQ_SESSION); 197 198 199 // since calendar IDs are date/time-encoded (based on creation 200 // date), we need to manually override the ID to what is given 201 // in user's prefs for when it was first linked (only if found 202 // in user prefs, that is) 203 // 204 $correctID = ''; 205 $correctName = ''; 206 $external_calendars = getPref($data_dir, $username, 'external_calendars', ''); 207 208 $externalCals = explode('||||', $external_calendars); 209 foreach ($externalCals as $externalCal) 210 { 211 if (empty($externalCal)) continue; 212 213 list($id, $name, $calUri) = explode('^^^^', $externalCal); 214 215 if ($calUri == $URI) 216 { 217 $correctID = $id; 218 $correctName = $name; 219 break; 220 } 221 } 222 223 224 $headers = get_headers($URI, 1); 225 if ($headers === FALSE) $headers = array(); 226 227 228 // look in cache first 229 // 230 if (!empty($correctID) && isset($externalCalendars[$correctID])) 231 { 232 $cal = unserialize($externalCalendars[$correctID]); 233 234 // check if URI has since been modified... 235 // 236 if (!isset($headers['Last-Modified'])) 237 $mtime = $cal->createdOn(); 238 else 239 $mtime = strtotime($headers['Last-Modified']); 240// don't need the clock skew here, since mod time on the calendar object 241// itself should have come from the original file's mtime 242// and if not, we add it below 243// if ($mtime - ($external_calendar_clock_skew * 60) > $cal->lastUpdatedOn()) 244 if ($mtime > $cal->lastUpdatedOn()) 245 { 246 unset($externalCalendars[$cal->getID()]); 247 sqsession_register($externalCalendars, 'externalCalendars'); 248 } 249 else 250 return $cal; 251 252 } 253 254 255 $CAL = @fopen($URI, 'rb'); 256 if ($CAL === FALSE) return FALSE; 257 258 $calContents = ''; 259 while (!feof($CAL)) $calContents .= fread($CAL, 4096); 260 261 fclose($CAL); 262 263 $calContentArray = explode("\r\n", $calContents); 264 if (sizeof($calContentArray) == 1) $calContentArray = explode("\n", $calContents); 265 266 $cal = Calendar::getCalendarFromICal($calContentArray); 267 $cal->setExternal(TRUE); 268 if (!empty($correctID)) $cal->setID($correctID); 269 if (!empty($correctName)) $cal->setName($correctName); 270 if (!isset($headers['Last-Modified'])) 271 $mtime = $cal->createdOn() + ($external_calendar_clock_skew * 60); 272 else 273 $mtime = strtotime($headers['Last-Modified']); 274 $cal->setLastUpdateDate(gmdate('Ymd\THis\Z', $mtime)); 275 276 277 // cache it 278 // 279 $externalCalendars[$cal->getID()] = serialize($cal); 280 sqsession_register($externalCalendars, 'externalCalendars'); 281 282 283 return $cal; 284 285} 286 287 288 289/** 290 * Remove calendar from user prefs 291 * 292 * @param string $calendarID The ID of the calendar to be removed 293 * 294 */ 295function removeExternalCalendarFromUserPrefs($calendarID) 296{ 297 298 global $username, $data_dir, $externalCalendars, $small_calendar_calID, 299 $small_calendar_calID_default; 300 301 $external_calendars = getPref($data_dir, $username, 'external_calendars', ''); 302 sqgetGlobalVar('externalCalendars', $externalCalendars, SQ_SESSION); 303 $new_external_list = ''; 304 305 $first = TRUE; 306 $externalCals = explode('||||', $external_calendars); 307 foreach ($externalCals as $externalCal) 308 { 309 if (empty($externalCal)) continue; 310 311 list($id, $name, $uri) = explode('^^^^', $externalCal); 312 313 if ($id == $calendarID) 314 { 315 // remove from cache 316 // 317 if (isset($externalCalendars[$id])) 318 { 319 unset($externalCalendars[$id]); 320 sqsession_register($externalCalendars, 'externalCalendars'); 321 } 322 323 continue; 324 } 325 326 if (!$first) $new_external_list .= '||||'; 327 328 $new_external_list .= $externalCal; 329 330 $first = FALSE; 331 } 332 333 setPref($data_dir, $username, 'external_calendars', $new_external_list); 334 335 336 // if small calendar was using this calendar, just 337 // fall back to default calendar 338 // 339 if ($small_calendar_calID == $calendarID) 340 { 341 setPref($data_dir, $username, 'small_calendar_calID', $small_calendar_calID_default); 342 } 343 344} 345 346 347 348/** 349 * Get calendar ID for personal calendar 350 * 351 * Retrieves the calendar ID for the given user's 352 * personal calendar 353 * 354 * This function also checks to make sure that this personal 355 * calendar actually exists and creates it if it does not. 356 * 357 * @param string $user The user whose personal calendar ID is being retrieved 358 * @param string $domain The user's domain 359 * @param boolean $dontCheckExists If TRUE, this function will not check 360 * to make sure the calendar exists (optional; 361 * default = FALSE) 362 * 363 * @return string The desired calendar ID 364 * 365 */ 366function get_personal_cal_id($user, $domain, $dontCheckExists=FALSE) 367{ 368 369 global $useDomainInCalID; 370 371 $calID = strtr('sm_cal_' . $user . ($useDomainInCalID ? '__' . $domain : ''), 372 '@|_-.:/\ ', '________'); 373 374 375 // if calendar data file doesn't exist, create it 376 // 377 if (!$dontCheckExists && get_calendar($calID, TRUE) === FALSE) 378 { 379 380 bindtextdomain ('calendar', SM_PATH . 'locale'); 381 textdomain ('calendar'); 382 383 $calendar = new Calendar($calID, 0, $domain, '', SM_CAL_TYPE_PERSONAL, 384 sprintf(_("Personal Calendar for %s"), $user), 385 $user, gmdate('Ymd\THis\Z'), '', '', array($user)); 386 387 bindtextdomain ('squirrelmail', SM_PATH . 'locale'); 388 textdomain ('squirrelmail'); 389 390 create_calendar($calendar); 391 392 } 393 394 return $calID; 395 396} 397 398 399 400/** 401 * Build event start/end time string for display 402 * 403 * For example, "[Oct 14, 2004 10:00 - Oct 24, 2004 12:00]" 404 * or "[All Day]" 405 * 406 * @param object $event The event object for which to build 407 * the start/end time string for display 408 * @param int $year The year where this event is being displayed 409 * @param int $month The month where this event is being displayed 410 * @param int $day The day where this event is being displayed 411 * 412 * @return string The start/end time string, ready for display 413 * 414 */ 415function buildEventTimeDisplayText($event, $year, $month, $day) 416{ 417 418 global $hour_format, $always_show_full_event_date_and_time; 419 420 $text = ' ['; 421 422 $startsToday = $event->startsOnDay($year, $month, $day); 423 $endsToday = $event->endsOnDay($year, $month, $day); 424 425 // NOTE: should not need to switch gettext domain here, since 426 // this function should be being called from within an 427 // interface function that is already in the correct calendar 428 // gettext domain.... right? 429 430 // all-day events render differently 431 // 432 if ($event->isAllDay()) 433 { 434 435 if (!$startsToday && !$endsToday 436 || ($always_show_full_event_date_and_time && 437 (!$startsToday || !$endsToday))) 438 $text .= $event->formattedStartDate('', $year, $month, $day) . ' - ' 439 . $event->formattedEndDate('', $year, $month, $day); 440 441 else if (!$startsToday) 442 $text .= $event->formattedStartDate('', $year, $month, $day) . ' - ' 443 . _("Today"); 444 445 else if (!$endsToday) 446 $text .= _("Today") . ' - ' 447 . $event->formattedEndDate('', $year, $month, $day); 448 449 else 450 $text .= _("All Day"); 451 452 $text .= "]"; 453 454 } 455 456 457 // regular non-all-day events 458 // 459 else 460 { 461 462 if (!$startsToday || $always_show_full_event_date_and_time) 463 $text .= $event->formattedStartDate('', $year, $month, $day) . ' '; 464 465 $text .= $event->formattedStartTime($hour_format == SMPREF_TIME_24HR ? 'H:i' : 'g:ia') . ' - '; 466 467 if (!$endsToday || $always_show_full_event_date_and_time) 468 $text .= $event->formattedEndDate('', $year, $month, $day) . ' '; 469 470 $text .= $event->formattedEndTime($hour_format == SMPREF_TIME_24HR ? 'H:i' : 'g:ia') . "]"; 471 472 } 473 474 return $text; 475} 476 477 478 479/** 480 * Inserts link to calendar module in main menu bar 481 * 482 */ 483function cal_menu_link_do() 484{ 485 486 bindtextdomain ('calendar', SM_PATH . 'locale'); 487 textdomain ('calendar'); 488 489 displayInternalLink("plugins/calendar/list_calendars.php", _("Calendar")); 490 echo "  \n"; 491 492 bindtextdomain ('squirrelmail', SM_PATH . 'locale'); 493 textdomain ('squirrelmail'); 494 495} 496 497 498 499/** 500 * Inserts link to calendar admin module and user settings 501 * page in options page 502 * 503 */ 504function cal_options_block_do() 505{ 506 507 global $username, $optpage_blocks, $cal_user_can_override_defaults; 508 509 510 bindtextdomain ('calendar', SM_PATH . 'locale'); 511 textdomain ('calendar'); 512 513 if ($cal_user_can_override_defaults) 514 $optpage_blocks[] = array( 515 'name' => _("Calendar Preferences"), 516 'url' => SM_PATH . 'plugins/calendar/calendar_options.php', 517 'desc' => _("Change the way your calendars behave and are displayed, including the miniature calendar beneath the folder list."), 518 'js' => false 519 ); 520 521 522 $userType = check_cal_user_type($username); 523 524 if (!($userType == SM_CAL_SUPERUSER || $userType == SM_CAL_LIMITED_ADMIN)) 525 { 526 bindtextdomain ('squirrelmail', SM_PATH . 'locale'); 527 textdomain ('squirrelmail'); 528 return; 529 } 530 531 532 $optpage_blocks[] = array( 533 'name' => _("Calendar Administration"), 534 'url' => SM_PATH . 'plugins/calendar/admin_options.php', 535 'desc' => _("Create and maintain shared calendars. Edit holidays, assign calendar access by user, or create publicly available calendars."), 536 'js' => false 537 ); 538 539 bindtextdomain ('squirrelmail', SM_PATH . 'locale'); 540 textdomain ('squirrelmail'); 541 542} 543 544 545 546/** 547 * Sort events by (start) time 548 * 549 * @param object $a Event A 550 * @param object $b Event B 551 * 552 * @return -1 if event A comes before event B, 1 if event 553 * B comes before event A, or zero if the two are equal. 554 * 555 */ 556function sortEventsByTime($a, $b) 557{ 558 559 return $a->compareTo($b); 560 561} 562 563 564 565//TODO -- do we need a version of this that doesn't work by reference??? 566/** 567 * Fold text (by reference) for iCal data stream 568 * 569 * Text is folded after every 75 characters by using 570 * a CRLF and one space. These can be overridden 571 * using the parameters for this function. 572 * 573 * @param string $text The text value to be folded 574 * @param int $maxLineLength The maximum allowable 575 * length of any one line 576 * (optional; default = 75) 577 * @param string $foldDelimiter The character sequence 578 * used to insert a fold 579 * (optional; default = 580 * CRLF + SPACE) 581 * 582 */ 583function foldICalStreamByRef(&$text, $maxLineLength=75, $foldDelimiter='') 584{ 585 586 if (empty($foldDelimiter)) $foldDelimiter = ICAL_LINE_DELIM . ' '; 587 $newText = ''; 588 while (strlen($text) > 0) 589 { 590 591 $EOL = strpos($text, ICAL_LINE_DELIM); 592 593 if ($EOL <= $maxLineLength) 594 $cutoff = $EOL + strlen(ICAL_LINE_DELIM); 595 else 596 $cutoff = $maxLineLength; 597 598 $newText .= substr($text, 0, $cutoff); 599 $text = substr($text, $cutoff); 600 601 if ($EOL > $maxLineLength) 602 $newText .= $foldDelimiter; 603 604 } 605 $text = $newText; 606 607} 608 609 610 611//TODO -- do we need a version of this that doesn't work by reference??? 612/** 613 * Unfold an iCal data stream (by reference) 614 * 615 * Text is unfolded based on the presence of CRLF followed 616 * by one whitespace character (space or tab). These (but 617 * not the CRLF) can be overridden using this function's 618 * parameters. 619 * 620 * @param array $iCalData The text value to be unfolded, 621 * one text line in each array value. 622 * NOTE that it is assumed that the 623 * CRLF characters have already been 624 * stripped from each line! 625 * @param array $foldDelimiters An array of characters which, 626 * when immediately following a 627 * CRLF, indicate a text fold 628 * (optional; default = space 629 * and tab) 630 * 631 */ 632function unfoldICalStreamByRef(&$iCalData, $foldDelimiters='') 633{ 634 635 if (empty($foldDelimiters) || !is_array($foldDelimiters)) 636 $foldDelimiters = array(' ', "\t"); 637 $newData = array(); 638 $x = -1; 639 foreach ($iCalData as $line) 640 { 641 642 $fold = FALSE; 643 foreach ($foldDelimiters as $delim) 644 if (strpos($line, $delim) === 0) 645 { 646 $fold = TRUE; 647 break; 648 } 649 if ($fold) 650 $newData[$x] .= substr($line, 1); 651 else 652 $newData[++$x] = $line; 653 654 } 655 $iCalData = $newData; 656 657} 658 659 660 661/** 662 * Utility function for sorting PERIOD iCal values 663 * given as two arrays, each array containing two 664 * elements: a starting timestamp and and ending 665 * timestamp. 666 * 667 * @param array $a First PERIOD array to compare 668 * @param array $b Second PERIOD array to compare 669 * 670 * @return -1 if the first PERIOD comes first, 1 if 671 * the second PERIOD comes first, or 0 if 672 * the two are equal 673 * 674 */ 675function sortPeriods($a, $b) 676{ 677 678 if ($a[0] < $b[0]) return -1; 679 if ($a[0] > $b[0]) return 1; 680 if ($a[1] < $b[1]) return -1; 681 if ($a[1] > $b[1]) return 1; 682 return 0; 683 684} 685 686 687 688/** 689 * Get timestamp in correct timezone 690 * 691 * @param int $time Original timestamp 692 * @param string $zone Requested timezone 693 * 694 * @return int Modified timestamp, or same timestamp 695 * if timezone was unknown 696 * 697 */ 698function convertTimestampToTimezone($time, $zone) 699{ 700 701 global $tz_array, $color; 702 703 $isDST = date('I', $time); 704 705 // try to guess when dash was used instead of forward slash: 706 // US-Eastern --> US/Eastern 707 // 708 $dash = strpos($zone, '-'); 709 if (!array_key_exists($zone, $tz_array) && $dash !== FALSE) 710 $zone = substr($zone, 0, $dash) . '/' . substr($zone, $dash + 1); 711 712 if (array_key_exists($zone, $tz_array)) 713 $offset = $tz_array[$zone][$isDST]; 714 else 715 $offset = '+0000'; 716 717 return getGMTSeconds($time, $offset); 718 719} 720 721 722 723/** 724 * Determines what kind of calendar user the given username is; checks 725 * the user's privelege level. 726 * 727 * @param string $user The username to check for admin permission 728 * 729 * @return string Gives back one of the calendar user type constants: 730 * SM_CAL_SUPERUSER (user can edit any and all calendars), 731 * SM_CAL_LIMITED_ADMIN (user can edit calendars they own), 732 * or SM_CAL_REGULAR_USER (no administrative permissions). 733 * 734 */ 735function check_cal_user_type($user) 736{ 737 738 global $cal_admins, $cal_debug; 739 740 foreach ($cal_admins as $admin => $perms) 741 { 742 743 if ($cal_debug) 744 echo "current username is \"$user\"; admin username is \"$admin\"; are they equal? " 745 . (strtolower($admin) == strtolower($user) ? 'YES' : 'NO') . '<br />'; 746 747 748 if (preg_match('/^' . str_replace(array('?', '*'), array('\w{1}', '.*?'), 749 strtoupper($admin)) . '$/', strtoupper($user))) 750 { 751 $perms = trim($perms); 752 if (strtolower($perms) == 'yes') 753 return SM_CAL_SUPERUSER; 754 else 755 return SM_CAL_LIMITED_ADMIN; 756 } 757 758 } 759 760 return SM_CAL_REGULAR_USER; 761 762} 763 764 765 766/** 767 * Determine the week of the month for a date 768 * 769 * The date in question may be given as a timestamp 770 * or as separate day, month and year numbers 771 * 772 * @param timestamp $timestamp The date in question 773 * @param int $year The year of the date in question 774 * @param int $month The month of the date in question 775 * @param int $day The day of the date in question 776 * 777 * @return int The week of the month that the given 778 * date falls within, or zero if error 779 * 780 */ 781function weekOfMonth($timestamp=0, $year=0, $month=0, $day=0) 782{ 783 784 // bunch of junk to figure out parameters 785 // skip to last line to see what you really 786 // wanted... 787 // 788 if ($month == 0 || $year == 0 || $day == 0) 789 { 790 if ($timestamp == 0) 791 return 0; // error 792 else 793 list($month, $year) = explode(',', date('m,Y', $timestamp)); 794 } 795 else if ($month == 0 || $year == 0 || $day == 0) 796 return 0; // error 797 else 798 $timestamp = mktime(0, 0, 0, $month, $day, $year); 799 800 801 // not much to it; just subtract week of year 802 // for the first of the month from the week of 803 // the year for the target timestamp 804 // 805 return date('W', $timestamp) 806 - date('W', mktime(0, 0, 0, $month, 1, $year)); 807 808} 809 810 811 812// ========================================================================== 813// Handy function to get a timestamp when all you have 814// is a week number (of the year), a day (Monday - Sunday) 815// and a year number -- taken from php.net 816// 817// TODO: what is not clear is if Sunday is considered day 7 or day 0??? 818// if the former, we need to make some mods here, since PHP considers 819// Sunday as 0 820// After just a trivial look at the code, it looks like it considers 821// Sunday as 7, so I inserted code at the beginning of the function 822// to make the correct conversion. 823 824/** 825 * Get a date by providing a week number, day of week and a year. 826 * 827 * Be careful! There are different definitions for weeks. Here the European definition is used. 828 * In Europe a week starts on Monday. 829 * Also the start of the first week in a year is defined differently in different countries. 830 * Here the ISO 8601 definition is used. This is the standard in Europe. 831 * 832 * I got the information from http://home.t-online.de/home/PeterJHaas/delphi.htm 833 * There are many websites with information on week numbers. 834 * An excellent site on this subject is http://www.pjh2.de/datetime/weeknumber/index.php 835 * 836 * This PHP source was based on the Delphi source code by Peter J. Haas 837 * 838 * 839 * //give me the date of Friday week 20 of the year 2004 (Should result in Friday May 14 2004) 840 * $aWeek=20; $aDay=05; $aYear=2004; 841 * $adate=datefromweeknr($aYear, $aWeek, $aDay); 842 * echo 'The date (week='.$aWeek.' day='.$aDay.' year= '.$aYear.') is '.date('D d-m-Y',$adate).'<br>'; 843 * 844 */ 845 function datefromweeknr($aYear, $aWeek, $aDay) 846 { 847 // correct for PHP Sundays 848 if ($aDay == 0) $aDay = 7; 849 850 $FirstDayOfWeek=1; //First day of week is Monday 851 $BaseDate=4; //We calculate from 4/1 which is always in week 1 852 $CJDDelta=2415019; //Based on start of Chronological Julian Day 853 $StartDate = DelphiDate(mktime(1,0,0,01,$BaseDate,$aYear)); //The date to start with 854 $Offset = ($aWeek-1) * 7 - mod(floor($StartDate) + $CJDDelta + 8 - $FirstDayOfWeek,7) + $aDay - 1; 855 return PHPUnixTimeStamp($StartDate + $Offset); 856 } 857 858 #---------extra functions used---------- 859 860 function DelphiDate($aPHPTime) 861 { 862 # The Unix Timestamp holds the number of seconds after January 1 1970 01:00:00 863 return div($aPHPTime,86400)+25569; 864 } 865 866 function PHPUnixTimeStamp($aDelphiDate) 867 { 868 # Delphi's TDate holds number of days after December 30 1899 869 return ($aDelphiDate-25569)*86400-3600; 870 } 871 872 function mod($number, $div) 873 { 874 return $number - floor($number/$div)*$div; 875 } 876 877 function div($number, $div) 878 { 879 return floor($number/$div); 880 } 881// ========================================================================== 882 883 884 885/** 886 * Determines what occurrence number the day of 887 * the week is in its month for a given date. 888 * That is, is this the 2nd Friday of the month? 889 * Or the 1st Wednesday? 890 * 891 * The date in question may be given as a timestamp 892 * or as separate day, month and year numbers 893 * 894 * @param timestamp $timestamp The date in question 895 * @param int $year The year of the date in question 896 * @param int $month The month of the date in question 897 * @param int $day The day of the date in question 898 * 899 * @return int The occurrence number of the day in 900 * the month, or zero if error. 901 * 902 */ 903function dayOcurrenceInMonth($timestamp=0, $year=0, $month=0, $day=0) 904{ 905 906 // bunch of junk to figure out parameters 907 // skip to last line to see what you really 908 // wanted... 909 // 910 if ($month == 0 || $year == 0 || $day == 0) 911 { 912 if ($timestamp == 0) 913 return 0; // error 914 else 915 list($day, $month, $year) = explode(',', date('j,m,Y', $timestamp)); 916 } 917 else if ($month == 0 || $year == 0 || $day == 0) 918 return 0; // error 919 else 920 $timestamp = mktime(0, 0, 0, $month, $day, $year); 921 922 923 // manually count day occurrences 924 // 925 $count = 0; 926 list($dayOfWeek, $daysThisMonth) = explode(',', date('w,t', $timestamp)); 927 for ($i = 1; $i < $daysThisMonth + 1 && $i <= $day; $i++) 928 { 929 if (date('w', mktime(0, 0, 0, $month, $i, $year)) == $dayOfWeek) 930 $count++; 931 } 932 933 return $count; 934 935} 936 937 938 939/** 940 * Checks if the given date is within any two 941 * timestamps (inclusive). 942 * 943 * Note that granularity only goes to DAYS. Hours 944 * and seconds of the start and end times are ignored. 945 * 946 * @param int $year The year of the day to check 947 * @param int $month The month of the day to check 948 * @param int $day The day to check 949 * @param timestamp $start Beginning of date range for check 950 * @param timestamp $end End of date range for check 951 * @param timestamp $theDay Timestamp corresponding to the 952 * $year, $month and $day parameters 953 * (optional, but gives performance 954 * boost if provided) 955 * 956 * @return boolean TRUE if the target date is between the 957 * given date range (inclusive), FALSE otherwise. 958 * 959 */ 960function dayIsBetween($year, $month, $day, $start, $end, $theDay=0) 961{ 962 963 // just verify that start day doesn't come after target day 964 // and that end day doesn't come before target day 965 966 967 // we need this to be as fast as possible, so check everything 968 // we can before we start making dates (make dates one at a time, 969 // as little as needed to just return outta here) 970 // 971 // the order below is important! this is the fastest combination 972 // 973 $endYear = date('Y', $end); 974 if ($endYear < $year) 975 return FALSE; 976 977 978 $startYear = date('Y', $start); 979 if ($startYear > $year) 980 return FALSE; 981 982 983 if ($theDay == 0) 984 $yearDay = date('z', mktime(0, 0, 0, $month, $day, $year)); 985 else 986 $yearDay = date('z', $theDay); 987 988 989 $endYearDay = date('z', $end); 990 if ($endYear == $year && $endYearDay < $yearDay) 991 return FALSE; 992 993 994 $startYearDay = date('z', $start); 995 if ($startYear == $year && $startYearDay > $yearDay) 996 return FALSE; 997 998 999 return TRUE; 1000 1001} 1002 1003 1004 1005/** 1006 * clean/encode a string for output in HTML pages by reference 1007 * 1008 * If the parameter is an array, any and all of the array's values that are 1009 * strings are cleaned/encoded, and if it contains any nested arrays, those 1010 * will be recursively scanned for string values to clean/encode. 1011 * 1012 * @param mixed $item The string (or array) to be encoded 1013 * @param boolean $convertNewlines If TRUE, all newlines are converted to <br /> tags; 1014 * if FALSE, newlines are left as is (optional; default = TRUE) 1015 * 1016 */ 1017function cal_encode_output_by_ref(&$item, $convertNewlines=TRUE) 1018{ 1019 if (is_string($item)) $item = ($convertNewlines ? nl2br(htmlspecialchars($item, ENT_QUOTES)) 1020 : htmlspecialchars($item, ENT_QUOTES)); 1021 else if (is_array($item)) 1022 foreach ($item as $index => $value) cal_encode_output_by_ref($item[$index], $convertNewlines); 1023} 1024 1025 1026 1027/** 1028 * clean/encode and return a string for output in HTML pages 1029 * 1030 * If the parameter is an array, any and all of the array's values that are 1031 * strings are cleaned/encoded, and if it contains any nested arrays, those 1032 * will be recursively scanned for string values to clean/encode. 1033 * 1034 * @param mixed $item The string (or array) to be encoded 1035 * @param boolean $convertNewlines If TRUE, all newlines are converted to <br /> tags; 1036 * if FALSE, newlines are left as is (optional; default = TRUE) 1037 * 1038 */ 1039function cal_encode_output($item, $convertNewlines=TRUE) 1040{ 1041 if (is_string($item)) return ($convertNewlines ? nl2br(htmlspecialchars($item, ENT_QUOTES)) 1042 : htmlspecialchars($item, ENT_QUOTES)); 1043 else if (is_array($item)) 1044 { 1045 $newItem = array(); 1046 foreach ($item as $index => $value) 1047 $newItem[$index] = cal_encode_output($value, $convertNewlines); 1048 return $newItem; 1049 } 1050 else return $item; 1051} 1052 1053 1054 1055/** 1056 * Sorts a list of calendars 1057 * 1058 * Sorts by calendar name, using case insensitive comparisons 1059 * 1060 * @param object $a Calendar A 1061 * @param object $b Calendar B 1062 * 1063 * @return -1 if calendar A comes before calendar B, 1 if calendar 1064 * B comes before calendar A, or zero if the two are equal. 1065 * 1066 */ 1067function calendar_sort($a, $b) 1068{ 1069 1070 return $a->compareTo($b); 1071 1072} 1073 1074 1075 1076/** 1077 * Sort and organize events for one day 1078 * 1079 * Takes a flat array of events and places them into 1080 * a nested array structure (based on start time) as such: 1081 * 1082 * Hour 1083 * | 1084 * |--- Quarter Hour 1085 * | | 1086 * | |--- Event 1087 * | |--- Event 1088 * | 1089 * |--- Quarter Hour 1090 * | 1091 * |--- Event 1092 * 1093 * For example, one event at 3:30pm and two at 8pm: 1094 * 1095 * Array 1096 * ( 1097 * [15] => Array 1098 * ( 1099 * [30] => Array 1100 * ( 1101 * [0] => event Object 1102 * ( 1103 * .... 1104 * ) 1105 * ) 1106 * ) 1107 * [20] => Array 1108 * ( 1109 * [0] => Array 1110 * ( 1111 * [0] => event Object 1112 * ( 1113 * .... 1114 * ) 1115 * [1] => event Object 1116 * ( 1117 * .... 1118 * ) 1119 * ) 1120 * ) 1121 * ) 1122 * 1123 * NOTE: events that start before this day are all 1124 * placed at midnight ([0][0]) in the return array 1125 * unless the $startHour parameter is given, in 1126 * which case they are placed at minute zero for 1127 * that hour. 1128 * 1129 * @param array $events The events that are to be organized 1130 * @param int $year The year of the day for which events are being organized. 1131 * @param int $month The month of the day for which events are being organized. 1132 * @param int $day The day for which events are being organized. 1133 * @param int $startHour The hour that the returned array should start 1134 * with - any events starting before that time are 1135 * pushed into the zero-minute slot for this hour 1136 * (optional; if not given, all hours of the day 1137 * (that have events) are returned) 1138 * 1139 * @return array Those same events, organized per above. 1140 * 1141 */ 1142function organizeEvents($events, $year, $month, $day, $startHour=0) 1143{ 1144 1145 if (!is_numeric($startHour) || $startHour < 0 || $startHour > 23) 1146 { 1147 global $color; 1148 plain_error_message('ERROR (organizeEvents): Bad start hour: ' . $startHour, $color); 1149 exit; 1150 } 1151 1152 1153 $returnArray = array(); 1154 1155 foreach ($events as $event) 1156 { 1157 1158 $eventStartHour = $event->startHour($year, $month, $day); 1159 1160 if ($startHour && $eventStartHour < $startHour) 1161 $returnArray[$startHour][$event->startQuarterHour($year, $month, $day)][] = $event; 1162 1163 else 1164 $returnArray[$eventStartHour][$event->startQuarterHour($year, $month, $day)][] = $event; 1165 1166 } 1167 1168 return $returnArray; 1169 1170} 1171 1172 1173 1174/** 1175 * Generates generic set of <option> tags for inclusion 1176 * in a <select> tag for a list of years 1177 * 1178 * @param int $selected The year that should be preselected (optional) 1179 * 1180 * @return string The list of <option> tags, ready to be 1181 * output to the HTML page 1182 * 1183 */ 1184function select_option_year($selected='') 1185{ 1186 1187 $html = ''; 1188 1189 for ($i = 1970; $i < 2038; $i++) 1190 { 1191 if (!empty($selected) && $i == $selected) 1192 { 1193 $html .= "<option value=\"$i\" selected>$i</option>\n"; 1194 } 1195 else 1196 { 1197 $html .= "<option value=\"$i\">$i</option>\n"; 1198 } 1199 } 1200 1201 return $html; 1202 1203} 1204 1205 1206 1207/** 1208 * Generates generic set of <option> tags for inclusion 1209 * in a <select> tag for a list of months 1210 * 1211 * @param int $selected The month that should be preselected (optional) 1212 * 1213 * @return string The list of <option> tags, ready to be 1214 * output to the HTML page 1215 * 1216 */ 1217function select_option_month($selected='') 1218{ 1219 1220 // NOTE: should not need to switch gettext domain here, since 1221 // this function should be being called from within an 1222 // interface function that is already in the correct calendar 1223 // gettext domain.... right? 1224 1225 $html = ''; 1226 1227 for ($i = 1; $i < 13; $i++) 1228 { 1229 $monthName = getMonthAbrv($i); 1230 1231 if (!empty($selected) && $i == $selected) 1232 { 1233 $html .= "<option value=\"$i\" SELECTED>$monthName</option>\n"; 1234 } 1235 else 1236 { 1237 $html .= "<option value=\"$i\">$monthName</option>\n"; 1238 } 1239 } 1240 1241 return $html; 1242 1243} 1244 1245 1246 1247/** 1248 * Generates generic set of <option> tags for inclusion 1249 * in a <select> tag for a list of days 1250 * 1251 * @param int $selected The day that should be preselected (optional) 1252 * 1253 * @return string The list of <option> tags, ready to be 1254 * output to the HTML page 1255 * 1256 */ 1257function select_option_day($selected='') 1258{ 1259 1260 $html = ''; 1261 1262 for ($i = 1; $i < 32; $i++) 1263 { 1264 1265 if (!empty($selected) && $i == $selected) 1266 { 1267 $html .= "<option value=\"$i\" SELECTED>$i</option>\n"; 1268 } 1269 else 1270 { 1271 $html .= "<option value=\"$i\">$i</option>\n"; 1272 } 1273 1274 } 1275 1276 return $html; 1277 1278} 1279 1280 1281 1282/** 1283 * Generates generic set of <option> tags for inclusion 1284 * in a <select> tag for a list of days of the week 1285 * 1286 * @param int $selected The day of the week that should 1287 * be preselected (optional) 1288 * 1289 * @return string The list of <option> tags, ready to be 1290 * output to the HTML page 1291 * 1292 */ 1293function select_option_day_of_week($selected=0) 1294{ 1295 1296 // NOTE: should not need to switch gettext domain here, since 1297 // this function should be being called from within an 1298 // interface function that is already in the correct calendar 1299 // gettext domain.... right? 1300 1301 $html = ''; 1302 1303 1304 $html .= '<option value="0"' . ($selected == 0 ? ' SELECTED' : '') 1305 . '>' . _("Sunday") . "</option>\n"; 1306 $html .= '<option value="1"' . ($selected == 1 ? ' SELECTED' : '') 1307 . '>' . _("Monday") . "</option>\n"; 1308 $html .= '<option value="2"' . ($selected == 2 ? ' SELECTED' : '') 1309 . '>' . _("Tuesday") . "</option>\n"; 1310 $html .= '<option value="3"' . ($selected == 3 ? ' SELECTED' : '') 1311 . '>' . _("Wednesday") . "</option>\n"; 1312 $html .= '<option value="4"' . ($selected == 4 ? ' SELECTED' : '') 1313 . '>' . _("Thursday") . "</option>\n"; 1314 $html .= '<option value="5"' . ($selected == 5 ? ' SELECTED' : '') 1315 . '>' . _("Friday") . "</option>\n"; 1316 $html .= '<option value="6"' . ($selected == 6 ? ' SELECTED' : '') 1317 . '>' . _("Saturday") . "</option>\n"; 1318 1319 1320 return $html; 1321 1322} 1323 1324 1325 1326/** 1327 * Generates generic set of <option> tags for inclusion 1328 * in a <select> tag for a list of integers with the given range 1329 * 1330 * @param int $startValue The integer from which option values should start 1331 * @param int $endValue The integer up to which option values should reach 1332 * @param int $selected The integer that should be preselected (optional) 1333 * 1334 * @return string The list of <option> tags, ready to be 1335 * output to the HTML page 1336 * 1337 */ 1338function select_option_integer($startValue, $endValue, $selected='') 1339{ 1340 1341 $html = ''; 1342 1343 for ($i = $startValue; $i < $endValue + 1; $i++) 1344 { 1345 1346 if (!empty($selected) && $i == $selected) 1347 { 1348 $html .= "<option value=\"$i\" SELECTED>$i</option>\n"; 1349 } 1350 else 1351 { 1352 $html .= "<option value=\"$i\">$i</option>\n"; 1353 } 1354 1355 } 1356 1357 return $html; 1358 1359} 1360 1361 1362 1363/** 1364 * Generates generic set of <option> tags for inclusion 1365 * in a <select> tag for a list of time lengths 1366 * 1367 * @param int $selected The length value that should be preselected (optional) 1368 * Note that this parameter need not match the exact 1369 * length minute value - the nearest length greater than 1370 * the given default value will be preselected if there 1371 * is not an exact match. 1372 * 1373 * @return string The list of <option> tags, ready to be 1374 * output to the HTML page 1375 * 1376 */ 1377function select_option_length($selected='') 1378{ 1379 1380 // NOTE: should not need to switch gettext domain here, since 1381 // this function should be being called from within an 1382 // interface function that is already in the correct calendar 1383 // gettext domain.... right? 1384 1385 $html = ''; 1386 1387/* see below... 1388 $lengths = array( 1389 '0' => '0 ' . _("min."), 1390 '15' => '15 ' . _("min."), 1391 '30' => '30 ' . _("min."), 1392 '45' => '45 ' . _("min."), 1393 '60' => '1 ' . _("hr."), 1394 '90' => '1.5 ' . _("hr."), 1395 '120' => '2 ' . _("hr."), 1396 '150' => '2.5 ' . _("hr."), 1397 '180' => '3 ' . _("hr."), 1398 '210' => '3.5 ' . _("hr."), 1399 '240' => '4 ' . _("hr."), 1400 '270' => '4.5 ' . _("hr."), 1401 '300' => '5 ' . _("hr."), 1402 '330' => '5.5 ' . _("hr."), 1403 '360' => '6 ' . _("hr."), 1404 '420' => '7 ' . _("hr."), 1405 '480' => '8 ' . _("hr."), 1406 '540' => '9 ' . _("hr."), 1407 '600' => '10 ' . _("hr."), 1408 '660' => '11 ' . _("hr."), 1409 '720' => '12 ' . _("hr."), 1410 '1440' => '1 ' . _("day"), 1411 '2880' => '2 ' . _("days"), 1412 '4320' => '3 ' . _("days"), 1413 '5760' => '4 ' . _("days"), 1414 '7200' => '5 ' . _("days"), 1415 '8640' => '6 ' . _("days"), 1416 '10080' => '1 ' . _("wk."), 1417 '20160' => '2 ' . _("wk."), 1418 '30240' => '3 ' . _("wk."), 1419 '40320' => '4 ' . _("wk."), 1420 '50400' => '5 ' . _("wk."), 1421 '60480' => '6 ' . _("wk."), 1422 '70560' => '7 ' . _("wk."), 1423 '80640' => '8 ' . _("wk."), 1424 ); 1425*/ 1426 $lengths=array(); 1427 foreach (array(0,15,30,45, 1428 60,90,120,150,180,210,240,270,300,330,360,420,480,540, 1429 600,660,720,1440,2880,4320,5760,7200,8640, 1430 10080,20160,30240,40320,50400,60480,70560,80640) as $length) 1431 { 1432 if ($length < 60) 1433 { 1434 // event length in minutes. Use abbreviation, that works with any numeric value 1435 // 1436 $lengths[$length] = sprintf(_("%d min."), $length); 1437 } 1438 else if ($length < 1440) 1439 { 1440 // event length in hours. Use abbreviation, that works with any numeric value 1441 // length is float number. 1442 // %s is used instead of %.1f in order to suppress zero padding. 1443 // if php implements strict variable format checking, all ($length/something) calls 1444 // used in sprintf, should be converted to strings. 1445 // floating point delimiter depends on used squirrelmail version. Some SM versions 1446 // revert to C float delimiter (.) in order to solve issues with other plugins 1447 // 1448 $lengths[$length] = sprintf(_("%s hr."), ($length / 60)); 1449 } 1450 else if ($length < 10080) 1451 { 1452 // event length in days. 1453 // 1454//TODO: wait until SM (and/or compatibility plugin) has ngettext wrapper 1455// $lengths[$length] = sprintf(ngettext("%s day", "%s days", ($length / 1440)), ($length / 1440)); 1456 if ($length < 2880) 1457 $lengths[$length] = sprintf(_("%s day"), ($length / 1440)); 1458 else 1459 $lengths[$length] = sprintf(_("%s days"), ($length / 1440)); 1460 } 1461 else 1462 { 1463 // event length in weeks. Use abbreviation, that works with any numeric value 1464 // 1465 $lengths[$length] = sprintf(_("%s wk."), ($length / 10080)); 1466 } 1467 } 1468 1469 1470 $noDefaultYet = TRUE; 1471 foreach ($lengths as $min => $text) 1472 { 1473 1474 if (!empty($selected) && ($min == $selected || ($min > $selected && $noDefaultYet))) 1475 { 1476 $html .= "<option value=\"$min\" selected>$text</option>\n"; 1477 $noDefaultYet = FALSE; 1478 } 1479 else 1480 { 1481 $html .= "<option value=\"$min\">$text</option>\n"; 1482 } 1483 1484 } 1485 1486 return $html; 1487 1488} 1489 1490 1491 1492/** 1493 * Generates generic set of <option> tags for inclusion 1494 * in a <select> tag for a list of hours 1495 * 1496 * @param int $selected The hour that should be preselected (optional) 1497 * 1498 * @return string The list of <option> tags, ready to be 1499 * output to the HTML page 1500 * 1501 */ 1502function select_option_hour($selected='') 1503{ 1504 1505 // NOTE: should not need to switch gettext domain here, since 1506 // this function should be being called from within an 1507 // interface function that is already in the correct calendar 1508 // gettext domain.... right? 1509 1510 global $hour_format; 1511 1512 $html = ''; 1513 1514 if ($hour_format == SMPREF_TIME_24HR) 1515 $hours = array( 1516 '0' => 0, 1517 '1' => 1, 1518 '2' => 2, 1519 '3' => 3, 1520 '4' => 4, 1521 '5' => 5, 1522 '6' => 6, 1523 '7' => 7, 1524 '8' => 8, 1525 '9' => 9, 1526 '10' => 10, 1527 '11' => 11, 1528 '12' => 12, 1529 '13' => 13, 1530 '14' => 14, 1531 '15' => 15, 1532 '16' => 16, 1533 '17' => 17, 1534 '18' => 18, 1535 '19' => 19, 1536 '20' => 20, 1537 '21' => 21, 1538 '22' => 22, 1539 '23' => 23, 1540 ); 1541 1542 else 1543 $hours = array( 1544 '0' => sprintf(_("%sam"), '12'), 1545 '1' => sprintf(_("%sam"), '1'), 1546 '2' => sprintf(_("%sam"), '2'), 1547 '3' => sprintf(_("%sam"), '3'), 1548 '4' => sprintf(_("%sam"), '4'), 1549 '5' => sprintf(_("%sam"), '5'), 1550 '6' => sprintf(_("%sam"), '6'), 1551 '7' => sprintf(_("%sam"), '7'), 1552 '8' => sprintf(_("%sam"), '8'), 1553 '9' => sprintf(_("%sam"), '9'), 1554 '10' => sprintf(_("%sam"), '10'), 1555 '11' => sprintf(_("%sam"), '11'), 1556 '12' => sprintf(_("%spm"), '12'), 1557 '13' => sprintf(_("%spm"), '1'), 1558 '14' => sprintf(_("%spm"), '2'), 1559 '15' => sprintf(_("%spm"), '3'), 1560 '16' => sprintf(_("%spm"), '4'), 1561 '17' => sprintf(_("%spm"), '5'), 1562 '18' => sprintf(_("%spm"), '6'), 1563 '19' => sprintf(_("%spm"), '7'), 1564 '20' => sprintf(_("%spm"), '8'), 1565 '21' => sprintf(_("%spm"), '9'), 1566 '22' => sprintf(_("%spm"), '10'), 1567 '23' => sprintf(_("%spm"), '11'), 1568 ); 1569 1570 1571 foreach ($hours as $hour => $text) 1572 { 1573 1574 if (!empty($selected) && $hour == $selected) 1575 { 1576 $html .= "<option value=\"$hour\" SELECTED>$text</option>\n"; 1577 } 1578 else 1579 { 1580 $html .= "<option value=\"$hour\">$text</option>\n"; 1581 } 1582 1583 } 1584 1585 return $html; 1586 1587} 1588 1589 1590 1591/** 1592 * Generates generic set of <option> tags for inclusion 1593 * in a <select> tag for a list of minutes 1594 * 1595 * @param int $selected The minute that should be preselected (optional) 1596 * 1597 * @return string The list of <option> tags, ready to be 1598 * output to the HTML page 1599 * 1600 */ 1601function select_option_minute($selected='') 1602{ 1603 1604 $html = ''; 1605 1606 $minutes = array(); 1607 1608 for ($i = 0; $i < 60; $i++) 1609 $minutes[$i] = ($i < 10 ? '0' . $i : $i); 1610 1611/* 1612 $minutes = array( 1613 '0'=>'00', 1614 '5'=>'05', 1615 '10'=>'10', 1616 '15'=>'15', 1617 '20'=>'20', 1618 '25'=>'25', 1619 '30'=>'30', 1620 '35'=>'35', 1621 '40'=>'40', 1622 '45'=>'45', 1623 '50'=>'50', 1624 '55'=>'55' 1625 ); 1626*/ 1627 1628 1629 foreach ($minutes as $min => $text) 1630 { 1631 1632 if (!empty($selected) && $min == $selected) 1633 { 1634 $html .= "<option value=\"$min\" SELECTED>$text</option>\n"; 1635 } 1636 else 1637 { 1638 $html .= "<option value=\"$min\">$text</option>\n"; 1639 } 1640 1641 } 1642 1643 return $html; 1644 1645} 1646 1647 1648 1649/** 1650 * Generates generic set of <option> tags for inclusion 1651 * in a <select> tag for a list of priorities 1652 * 1653 * @param int $selected The priority that should be 1654 * preselected (optional; default 1655 * is Normal priority) 1656 * 1657 * @return string The list of <option> tags, ready to be 1658 * output to the HTML page 1659 * 1660 */ 1661function select_option_priority($selected='') 1662{ 1663 1664 // NOTE: should not need to switch gettext domain here, since 1665 // this function should be being called from within an 1666 // interface function that is already in the correct calendar 1667 // gettext domain.... right? 1668 1669 $html = ''; 1670 1671 global $EVENT_PRIORITIES; 1672 1673 1674 foreach ($EVENT_PRIORITIES as $num => $text) 1675 { 1676 1677 // skip unknown so we can put it at the end of the list, 1678 // where it is more intuiitive 1679 // 1680 if ($num == 0) continue; 1681 1682 if (($selected !== '' && $num == $selected) 1683 || ($selected === '' && $num == SM_CAL_EVENT_PRIORITY_NORMAL)) 1684 { 1685 $html .= "<option value=\"$num\" SELECTED>$text</option>\n"; 1686 } 1687 else 1688 { 1689 $html .= "<option value=\"$num\">$text</option>\n"; 1690 } 1691 1692 } 1693 if ($selected === 0) 1694 $html .= "<option SELECTED value=\"0\">" . _("Unknown") . "</option>\n"; 1695 else 1696 $html .= "<option value=\"0\">" . _("Unknown") . "</option>\n"; 1697 1698 return $html; 1699 1700} 1701 1702 1703 1704/** 1705 * Generates generic set of <option> tags for inclusion 1706 * in a <select> tag for a list of recurrence types 1707 * 1708 * @param int $selected The recurrence type that should be 1709 * preselected 1710 * 1711 * @return string The list of <option> tags, ready to be 1712 * output to the HTML page 1713 * 1714 */ 1715function select_option_recurrence_type($selected='') 1716{ 1717 1718 $html = ''; 1719 1720 global $RECURRENCE_TYPES; 1721 1722 1723 foreach ($RECURRENCE_TYPES as $code => $text) 1724 { 1725 1726 if (!empty($selected) && $code == $selected) 1727 { 1728 $html .= "<option value=\"$code\" SELECTED>$text</option>\n"; 1729 } 1730 else 1731 { 1732 $html .= "<option value=\"$code\">$text</option>\n"; 1733 } 1734 1735 } 1736 1737 return $html; 1738 1739} 1740 1741 1742 1743/** 1744 * get_headers() implementation for php4 1745 * 1746 * Swiped from http://www.php.net/manual/function.get-headers.php 1747 * 1748 */ 1749if (!function_exists('get_headers')) 1750{ 1751 1752 /** 1753 * @return array 1754 * @param string $url 1755 * @param int $format 1756 * @desc Fetches all the headers 1757 * @author cpurruc fh-landshut de 1758 * @modified by dotpointer 1759 * @modified by aeontech 1760 */ 1761 function get_headers($url,$format=0) 1762 { 1763 $url_info=parse_url($url); 1764 $port = isset($url_info['port']) ? $url_info['port'] : 80; 1765 $fp=fsockopen($url_info['host'], $port, $errno, $errstr, 30); 1766 1767 if($fp) 1768 { 1769 $head = "HEAD ".@$url_info['path']."?".@$url_info['query']." HTTP/1.0\r\nHost: ".@$url_info['host']."\r\n\r\n"; 1770 fputs($fp, $head); 1771 while(!feof($fp)) 1772 { 1773 if($header=trim(fgets($fp, 1024))) 1774 { 1775 if($format == 1) 1776 { 1777 $key = array_shift(explode(':',$header)); 1778 // the first element is the http header type, such as HTTP 200 OK, 1779 // it doesn't have a separate name, so we have to check for it. 1780 if($key == $header) 1781 { 1782 $headers[] = $header; 1783 } 1784 else 1785 { 1786 $headers[$key]=substr($header,strlen($key)+2); 1787 } 1788 unset($key); 1789 } 1790 else 1791 { 1792 $headers[] = $header; 1793 } 1794 } 1795 } 1796 return $headers; 1797 } 1798 else 1799 { 1800 return false; 1801 } 1802 } 1803 1804} 1805 1806 1807 1808?> 1809