PageRenderTime 135ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 1ms

/Branch_4_6dev/gforge/plugins/webcalendar/www/includes/functions.php

https://gitlab.com/oslc-cm-server/olbergers-ff5-oslc
PHP | 5204 lines | 3337 code | 381 blank | 1486 comment | 1142 complexity | 9d32c58484ced9b4a4a052d06ed5e590 MD5 | raw file
Possible License(s): GPL-2.0, MPL-2.0-no-copyleft-exception
  1. <?php
  2. /**
  3. * All of WebCalendar's functions
  4. *
  5. * @author Craig Knudsen <cknudsen@cknudsen.com>
  6. * @copyright Craig Knudsen, <cknudsen@cknudsen.com>, http://www.k5n.us/cknudsen
  7. * @license http://www.gnu.org/licenses/gpl.html GNU GPL
  8. * @package WebCalendar
  9. */
  10. if ( empty ( $PHP_SELF ) && ! empty ( $_SERVER ) &&
  11. ! empty ( $_SERVER['PHP_SELF'] ) ) {
  12. $PHP_SELF = $_SERVER['PHP_SELF'];
  13. }
  14. if ( ! empty ( $PHP_SELF ) && preg_match ( "/\/includes\//", $PHP_SELF ) ) {
  15. die ( "You can't access this file directly!" );
  16. }
  17. /**#@+
  18. * Used for activity log
  19. * @global string
  20. */
  21. $LOG_CREATE = "C";
  22. $LOG_APPROVE = "A";
  23. $LOG_REJECT = "X";
  24. $LOG_UPDATE = "U";
  25. $LOG_DELETE = "D";
  26. $LOG_NOTIFICATION = "N";
  27. $LOG_REMINDER = "R";
  28. /**#@-*/
  29. /**
  30. *File to log
  31. *
  32. */
  33. global $log_file;
  34. $log_file="/var/lib/gforge/chroot/home/users/placoste/webcalendar/webcalendar.txt";
  35. /**
  36. * Number of seconds in a day
  37. *
  38. * @global int $ONE_DAY
  39. */
  40. $ONE_DAY = 86400;
  41. /**
  42. * Array containing the number of days in each month in a non-leap year
  43. *
  44. * @global array $days_per_month
  45. */
  46. $days_per_month = array ( 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
  47. /**
  48. * Array containing the number of days in each month in a leap year
  49. *
  50. * @global array $ldays_per_month
  51. */
  52. $ldays_per_month = array ( 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 );
  53. /**
  54. * Array of global variables which are not allowed to by set via HTTP GET/POST
  55. *
  56. * This is a security precaution to prevent users from overriding any global
  57. * variables
  58. *
  59. * @global array $noSet
  60. */
  61. $noSet = array (
  62. "is_admin" => 1,
  63. "db_type" => 1,
  64. "db_host" => 1,
  65. "db_login" => 1,
  66. "db_password" => 1,
  67. "db_persistent" => 1,
  68. "PROGRAM_NAME" => 1,
  69. "PROGRAM_URL" => 1,
  70. "readonly" => 1,
  71. "single_user" => 1,
  72. "single_user_login" => 1,
  73. "use_http_auth" => 1,
  74. "user_inc" => 1,
  75. "includedir" => 1,
  76. "NONUSER_PREFIX" => 1,
  77. "languages" => 1,
  78. "browser_languages" => 1,
  79. "pub_acc_enabled" => 1,
  80. "user_can_update_password" => 1,
  81. "admin_can_add_user" => 1,
  82. "admin_can_delete_user" => 1,
  83. );
  84. // This code is a temporary hack to make the application work when
  85. // register_globals is set to Off in php.ini (the default setting in
  86. // PHP 4.2.0 and after).
  87. if ( empty ( $HTTP_GET_VARS ) ) $HTTP_GET_VARS = $_GET;
  88. if ( ! empty ( $HTTP_GET_VARS ) ) {
  89. while (list($key, $val) = @each($HTTP_GET_VARS)) {
  90. // don't allow anything to have <script> in it...
  91. if ( ! is_array ( $val ) ) {
  92. if ( preg_match ( "/<\s*script/i", $val ) ) {
  93. echo "Security violation!"; exit;
  94. }
  95. }
  96. if ( $key == "login" ) {
  97. if ( strstr ( $PHP_SELF, "login.php" ) ) {
  98. //$GLOBALS[$key] = $val;
  99. $GLOBALS[$key] = $val;
  100. }
  101. } else {
  102. if ( empty ( $noSet[$key] ) ) {
  103. $GLOBALS[$key] = $val;
  104. //echo "XXX $key<br />\n";
  105. }
  106. }
  107. //echo "GET var '$key' = '$val' <br />\n";
  108. }
  109. reset ( $HTTP_GET_VARS );
  110. }
  111. if ( empty ( $HTTP_POST_VARS ) ) $HTTP_POST_VARS = $_POST;
  112. if ( ! empty ( $HTTP_POST_VARS ) ) {
  113. while (list($key, $val) = @each($HTTP_POST_VARS)) {
  114. // don't allow anything to have <script> in it... except 'template'
  115. if ( ! is_array ( $val ) && $key != 'template' ) {
  116. if ( preg_match ( "/<\s*script/i", $val ) ) {
  117. echo "Security violation!"; exit;
  118. }
  119. }
  120. if ( empty ( $noSet[$key] ) ) {
  121. $GLOBALS[$key] = $val;
  122. }
  123. }
  124. reset ( $HTTP_POST_VARS );
  125. }
  126. //while (list($key, $val) = @each($HTTP_POST_FILES)) {
  127. // $GLOBALS[$key] = $val;
  128. //}
  129. //while (list($key, $val) = @each($HTTP_SESSION_VARS)) {
  130. // $GLOBALS[$key] = $val;
  131. //}
  132. if ( empty ( $HTTP_COOKIE_VARS ) ) $HTTP_COOKIE_VARS = $_COOKIE;
  133. if ( ! empty ( $HTTP_COOKIE_VARS ) ) {
  134. while (list($key, $val) = @each($HTTP_COOKIE_VARS)) {
  135. if ( empty ( $noSet[$key] ) && substr($key,0,12) == "webcalendar_" ) {
  136. $GLOBALS[$key] = $val;
  137. }
  138. //echo "COOKIE var '$key' = '$val' <br />\n";
  139. }
  140. reset ( $HTTP_COOKIE_VARS );
  141. }
  142. // Don't allow a user to put "login=XXX" in the URL if they are not
  143. // coming from the login.php page.
  144. if ( empty ( $PHP_SELF ) && ! empty ( $_SERVER['PHP_SELF'] ) )
  145. $PHP_SELF = $_SERVER['PHP_SELF']; // backward compatibility
  146. if ( empty ( $PHP_SELF ) )
  147. $PHP_SELF = ''; // this happens when running send_reminders.php from CL
  148. if ( ! strstr ( $PHP_SELF, "login.php" ) && ! empty ( $GLOBALS["login"] ) ) {
  149. $GLOBALS["login"] = "";
  150. }
  151. // Define an array to use to jumble up the key: $offsets
  152. // We define a unique key to scramble the cookie we generate.
  153. // We use the admin install password that the user set to make
  154. // the salt unique for each WebCalendar install.
  155. if ( ! empty ( $settings ) && ! empty ( $settings['install_password'] ) ) {
  156. $salt = $settings['install_password'];
  157. } else {
  158. $salt = md5 ( $db_login );
  159. }
  160. $salt_len = strlen ( $salt );
  161. if ( ! empty ( $db_password ) ) {
  162. $salt2 = md5 ( $db_password );
  163. } else {
  164. $salt2 = md5 ( "oogabooga" );
  165. }
  166. $salt2_len = strlen ( $salt2 );
  167. $offsets = array ();
  168. for ( $i = 0; $i < $salt_len || $i < $salt2_len; $i++ ) {
  169. $offsets[$i] = 0;
  170. if ( $i < $salt_len )
  171. $offsets[$i] += ord ( substr ( $salt, $i, 1 ) );
  172. if ( $i < $salt2_len )
  173. $offsets[$i] += ord ( substr ( $salt2, $i, 1 ) );
  174. $offsets[$i] %= 128;
  175. }
  176. /* debugging code...
  177. for ( $i = 0; $i < count ( $offsets ); $i++ ) {
  178. echo "offset $i: $offsets[$i] <br />\n";
  179. }
  180. */
  181. function logs($logs_file, $msg){
  182. /*$log=fopen($logs_file,"a+");
  183. fputs($log,$msg."\n");
  184. fclose($log);*/
  185. }
  186. /*
  187. * Functions start here. All non-function code should be above this
  188. *
  189. * Note to developers:
  190. * Documentation is generated from the function comments below.
  191. * When adding/updating functions, please follow the following conventions
  192. * seen below. Your cooperation in this matter is appreciated :-)
  193. *
  194. * If you want your documentation to link to the db documentation,
  195. * just make sure you mention the db table name followed by "table"
  196. * on the same line. Here's an example:
  197. * Retrieve preferences from the webcal_user_pref table.
  198. *
  199. */
  200. /**
  201. * Gets the value resulting from an HTTP POST method.
  202. *
  203. * <b>Note:</b> The return value will be affected by the value of
  204. * <var>magic_quotes_gpc</var> in the php.ini file.
  205. *
  206. * @param string $name Name used in the HTML form
  207. *
  208. * @return string The value used in the HTML form
  209. *
  210. * @see getGetValue
  211. */
  212. function getPostValue ( $name ) {
  213. global $HTTP_POST_VARS;
  214. if ( isset ( $_POST ) && is_array ( $_POST ) && ! empty ( $_POST[$name] ) ) {
  215. $HTTP_POST_VARS[$name] = $_POST[$name];
  216. return $_POST[$name];
  217. } else if ( ! isset ( $HTTP_POST_VARS ) ) {
  218. return null;
  219. } else if ( ! isset ( $HTTP_POST_VARS[$name] ) ) {
  220. return null;
  221. }
  222. return ( $HTTP_POST_VARS[$name] );
  223. }
  224. /**
  225. * Gets the value resulting from an HTTP GET method.
  226. *
  227. * <b>Note:</b> The return value will be affected by the value of
  228. * <var>magic_quotes_gpc</var> in the php.ini file.
  229. *
  230. * If you need to enforce a specific input format (such as numeric input), then
  231. * use the {@link getValue()} function.
  232. *
  233. * @param string $name Name used in the HTML form or found in the URL
  234. *
  235. * @return string The value used in the HTML form (or URL)
  236. *
  237. * @see getPostValue
  238. */
  239. function getGetValue ( $name ) {
  240. global $HTTP_GET_VARS;
  241. if ( isset ( $_GET ) && is_array ( $_GET ) && ! empty ( $_GET[$name] ) ) {
  242. $HTTP_GET_VARS[$name] = $_GET[$name];
  243. return $_GET[$name];
  244. } else if ( ! isset ( $HTTP_GET_VARS ) ) {
  245. return null;
  246. } else if ( ! isset ( $HTTP_GET_VARS[$name] ) ) {
  247. return null;
  248. }
  249. return ( $HTTP_GET_VARS[$name] );
  250. }
  251. /**
  252. * Gets the value resulting from either HTTP GET method or HTTP POST method.
  253. *
  254. * <b>Note:</b> The return value will be affected by the value of
  255. * <var>magic_quotes_gpc</var> in the php.ini file.
  256. *
  257. * <b>Note:</b> If you need to get an integer value, yuou can use the
  258. * getIntValue function.
  259. *
  260. * @param string $name Name used in the HTML form or found in the URL
  261. * @param string $format A regular expression format that the input must match.
  262. * If the input does not match, an empty string is
  263. * returned and a warning is sent to the browser. If The
  264. * <var>$fatal</var> parameter is true, then execution
  265. * will also stop when the input does not match the
  266. * format.
  267. * @param bool $fatal Is it considered a fatal error requiring execution to
  268. * stop if the value retrieved does not match the format
  269. * regular expression?
  270. *
  271. * @return string The value used in the HTML form (or URL)
  272. *
  273. * @uses getGetValue
  274. * @uses getPostValue
  275. */
  276. function getValue ( $name, $format="", $fatal=false ) {
  277. $val = getPostValue ( $name );
  278. if ( ! isset ( $val ) )
  279. $val = getGetValue ( $name );
  280. // for older PHP versions...
  281. if ( ! isset ( $val ) && get_magic_quotes_gpc () == 1 &&
  282. ! empty ( $GLOBALS[$name] ) )
  283. $val = $GLOBALS[$name];
  284. if ( ! isset ( $val ) )
  285. return "";
  286. if ( ! empty ( $format ) && ! preg_match ( "/^" . $format . "$/", $val ) ) {
  287. // does not match
  288. if ( $fatal ) {
  289. die_miserable_death ( "Fatal Error: Invalid data format for $name" );
  290. }
  291. // ignore value
  292. return "";
  293. }
  294. return $val;
  295. }
  296. /**
  297. * Gets an integer value resulting from an HTTP GET or HTTP POST method.
  298. *
  299. * <b>Note:</b> The return value will be affected by the value of
  300. * <var>magic_quotes_gpc</var> in the php.ini file.
  301. *
  302. * @param string $name Name used in the HTML form or found in the URL
  303. * @param bool $fatal Is it considered a fatal error requiring execution to
  304. * stop if the value retrieved does not match the format
  305. * regular expression?
  306. *
  307. * @return string The value used in the HTML form (or URL)
  308. *
  309. * @uses getValue
  310. */
  311. function getIntValue ( $name, $fatal=false ) {
  312. $val = getValue ( $name, "-?[0-9]+", $fatal );
  313. return $val;
  314. }
  315. /**
  316. * Loads default system settings (which can be updated via admin.php).
  317. *
  318. * System settings are stored in the webcal_config table.
  319. *
  320. * <b>Note:</b> If the setting for <var>server_url</var> is not set, the value
  321. * will be calculated and stored in the database.
  322. *
  323. * @global string User's login name
  324. * @global bool Readonly
  325. * @global string HTTP hostname
  326. * @global int Server's port number
  327. * @global string Request string
  328. * @global array Server variables
  329. */
  330. function load_global_settings () {
  331. global $login, $readonly, $HTTP_HOST, $SERVER_PORT, $REQUEST_URI, $_SERVER;
  332. // Note: when running from the command line (send_reminders.php),
  333. // these variables are (obviously) not set.
  334. // TODO: This type of checking should be moved to a central locationm
  335. // like init.php.
  336. if ( isset ( $_SERVER ) && is_array ( $_SERVER ) ) {
  337. if ( empty ( $HTTP_HOST ) && isset ( $_SERVER["HTTP_POST"] ) )
  338. $HTTP_HOST = $_SERVER["HTTP_HOST"];
  339. if ( empty ( $SERVER_PORT ) && isset ( $_SERVER["SERVER_PORT"] ) )
  340. $SERVER_PORT = $_SERVER["SERVER_PORT"];
  341. if ( empty ( $REQUEST_URI ) && isset ( $_SERVER["REQUEST_URI"] ) )
  342. $REQUEST_URI = $_SERVER["REQUEST_URI"];
  343. }
  344. $res = dbi_query ( "SELECT cal_setting, cal_value FROM webcal_config" );
  345. if ( $res ) {
  346. while ( $row = dbi_fetch_row ( $res ) ) {
  347. $setting = $row[0];
  348. $value = $row[1];
  349. //echo "Setting '$setting' to '$value' <br />\n";
  350. $GLOBALS[$setting] = $value;
  351. }
  352. dbi_free_result ( $res );
  353. }
  354. // If app name not set.... default to "Title". This gets translated
  355. // later since this function is typically called before translate.php
  356. // is included.
  357. // Note: We usually use translate($application_name) instead of
  358. // translate("Title").
  359. if ( empty ( $GLOBALS["application_name"] ) )
  360. $GLOBALS["application_name"] = "Title";
  361. // If $server_url not set, then calculate one for them, then store it
  362. // in the database.
  363. if ( empty ( $GLOBALS["server_url"] ) ) {
  364. if ( ! empty ( $HTTP_HOST ) && ! empty ( $REQUEST_URI ) ) {
  365. $ptr = strrpos ( $REQUEST_URI, "/" );
  366. if ( $ptr > 0 ) {
  367. $uri = substr ( $REQUEST_URI, 0, $ptr + 1 );
  368. $server_url = "http://" . $HTTP_HOST;
  369. if ( ! empty ( $SERVER_PORT ) && $SERVER_PORT != 80 )
  370. $server_url .= ":" . $SERVER_PORT;
  371. $server_url .= $uri;
  372. dbi_query ( "INSERT INTO webcal_config ( cal_setting, cal_value ) ".
  373. "VALUES ( 'server_url', '$server_url' )" );
  374. $GLOBALS["server_url"] = $server_url;
  375. }
  376. }
  377. }
  378. // If no font settings, then set some
  379. if ( empty ( $GLOBALS["FONTS"] ) ) {
  380. if ( $GLOBALS["LANGUAGE"] == "Japanese" )
  381. $GLOBALS["FONTS"] = "Osaka, Arial, Helvetica, sans-serif";
  382. else
  383. $GLOBALS["FONTS"] = "Arial, Helvetica, sans-serif";
  384. }
  385. }
  386. /**
  387. * Gets the list of active plugins.
  388. *
  389. * Should be called after {@link load_global_settings()} and {@link load_user_preferences()}.
  390. *
  391. * @internal cek: ignored since I am not sure this will ever be used...
  392. *
  393. * @return array Active plugins
  394. *
  395. * @ignore
  396. */
  397. function get_plugin_list ( $include_disabled=false ) {
  398. // first get list of available plugins
  399. $sql = "SELECT cal_setting FROM webcal_config " .
  400. "WHERE cal_setting LIKE '%.plugin_status'";
  401. if ( ! $include_disabled )
  402. $sql .= " AND cal_value = 'Y'";
  403. $sql .= " ORDER BY cal_setting";
  404. $res = dbi_query ( $sql );
  405. $plugins = array ();
  406. if ( $res ) {
  407. while ( $row = dbi_fetch_row ( $res ) ) {
  408. $e = explode ( ".", $row[0] );
  409. if ( $e[0] != "" ) {
  410. $plugins[] = $e[0];
  411. }
  412. }
  413. dbi_free_result ( $res );
  414. } else {
  415. echo translate("Database error") . ": " . dbi_error (); exit;
  416. }
  417. if ( count ( $plugins ) == 0 ) {
  418. $plugins[] = "webcalendar";
  419. }
  420. return $plugins;
  421. }
  422. /**
  423. * Get plugins available to the current user.
  424. *
  425. * Do this by getting a list of all plugins that are not disabled by the
  426. * administrator and make sure this user has not disabled any of them.
  427. *
  428. * It's done this was so that when an admin adds a new plugin, it shows up on
  429. * each users system automatically (until they disable it).
  430. *
  431. * @return array Plugins available to current user
  432. *
  433. * @ignore
  434. */
  435. function get_user_plugin_list () {
  436. $ret = array ();
  437. $all_plugins = get_plugin_list ();
  438. for ( $i = 0; $i < count ( $all_plugins ); $i++ ) {
  439. if ( $GLOBALS[$all_plugins[$i] . ".disabled"] != "N" )
  440. $ret[] = $all_plugins[$i];
  441. }
  442. return $ret;
  443. }
  444. /**
  445. * Identify user's browser.
  446. *
  447. * Returned value will be one of:
  448. * - "Mozilla/5" = Mozilla (open source Mozilla 5.0)
  449. * - "Mozilla/[3,4]" = Netscape (3.X, 4.X)
  450. * - "MSIE 4" = MSIE (4.X)
  451. *
  452. * @return string String identifying browser
  453. *
  454. * @ignore
  455. */
  456. function get_web_browser () {
  457. if ( ereg ( "MSIE [0-9]", getenv ( "HTTP_USER_AGENT" ) ) )
  458. return "MSIE";
  459. if ( ereg ( "Mozilla/[234]", getenv ( "HTTP_USER_AGENT" ) ) )
  460. return "Netscape";
  461. if ( ereg ( "Mozilla/[5678]", getenv ( "HTTP_USER_AGENT" ) ) )
  462. return "Mozilla";
  463. return "Unknown";
  464. }
  465. /**
  466. * Logs a debug message.
  467. *
  468. * Generally, we do not leave calls to this function in the code. It is used
  469. * for debugging only.
  470. *
  471. * @param string $msg Text to be logged
  472. */
  473. function do_debug ( $msg ) {
  474. // log to /tmp/webcal-debug.log
  475. //error_log ( date ( "Y-m-d H:i:s" ) . "> $msg\n",
  476. // 3, "/tmp/webcal-debug.log" );
  477. //error_log ( date ( "Y-m-d H:i:s" ) . "> $msg\n",
  478. // 2, "sockieman:2000" );
  479. }
  480. /**
  481. * Gets user's preferred view.
  482. *
  483. * The user's preferred view is stored in the $STARTVIEW global variable. This
  484. * is loaded from the user preferences (or system settings if there are no user
  485. * prefererences.)
  486. *
  487. * @param string $indate Date to pass to preferred view in YYYYMMDD format
  488. * @param string $args Arguments to include in the URL (such as "user=joe")
  489. *
  490. * @return string URL of the user's preferred view
  491. */
  492. function get_preferred_view ( $indate="", $args="" ) {
  493. global $STARTVIEW, $thisdate;
  494. $url = empty ( $STARTVIEW ) ? "month.php" : $STARTVIEW;
  495. // We used to just store "month" in $STARTVIEW without the ".php"
  496. // This is just to prevent users from getting a "404 not found" if
  497. // they have not updated their preferences.
  498. if ( $url == "month" || $url == "day" || $url == "week" || $url == "year" )
  499. $url .= ".php";
  500. $url = str_replace ( '&amp;', '&', $url );
  501. $url = str_replace ( '&', '&amp;', $url );
  502. $xdate = empty ( $indate ) ? $thisdate : $indate;
  503. if ( ! empty ( $xdate ) ) {
  504. if ( strstr ( $url, "?" ) )
  505. $url .= '&amp;' . "date=$xdate";
  506. else
  507. $url .= '?' . "date=$xdate";
  508. }
  509. if ( ! empty ( $args ) ) {
  510. if ( strstr ( $url, "?" ) )
  511. $url .= '&amp;' . $args;
  512. else
  513. $url .= '?' . $args;
  514. }
  515. return $url;
  516. }
  517. /**
  518. * Sends a redirect to the user's preferred view.
  519. *
  520. * The user's preferred view is stored in the $STARTVIEW global variable. This
  521. * is loaded from the user preferences (or system settings if there are no user
  522. * prefererences.)
  523. *
  524. * @param string $indate Date to pass to preferred view in YYYYMMDD format
  525. * @param string $args Arguments to include in the URL (such as "user=joe")
  526. */
  527. function send_to_preferred_view ( $indate="", $args="" ) {
  528. $url = get_preferred_view ( $indate, $args );
  529. do_redirect ( $url );
  530. }
  531. /** Sends a redirect to the specified page.
  532. *
  533. * The database connection is closed and execution terminates in this function.
  534. *
  535. * <b>Note:</b> MS IIS/PWS has a bug in which it does not allow us to send a
  536. * cookie and a redirect in the same HTTP header. When we detect that the web
  537. * server is IIS, we accomplish the redirect using meta-refresh. See the
  538. * following for more info on the IIS bug:
  539. *
  540. * {@link http://www.faqts.com/knowledge_base/view.phtml/aid/9316/fid/4}
  541. *
  542. * @param string $url The page to redirect to. In theory, this should be an
  543. * absolute URL, but all browsers accept relative URLs (like
  544. * "month.php").
  545. *
  546. * @global string Type of webserver
  547. * @global array Server variables
  548. * @global resource Database connection
  549. */
  550. function do_redirect ( $url ) {
  551. //Debug
  552. //$log=fopen("/var/lib/gforge/chroot/home/users/placoste/webcalendar/webcalendar.txt","a+");
  553. //fputs($log,"####### functions.php #######\n------- do_redirect -------\n");
  554. //fclose($log);
  555. //Debug
  556. //Debug
  557. //$log=fopen("/var/lib/gforge/chroot/home/users/placoste/webcalendar/webcalendar.txt","a+");
  558. //fputs($log,"url : ".$url."\n");
  559. //fclose($log);
  560. //Debug
  561. global $SERVER_SOFTWARE, $_SERVER, $c;
  562. // Replace any '&amp;' with '&' since we don't want that in the HTTP
  563. // header.
  564. $url = str_replace ( '&amp;', '&', $url );
  565. if ( empty ( $SERVER_SOFTWARE ) )
  566. $SERVER_SOFTWARE = $_SERVER["SERVER_SOFTWARE"];
  567. //echo "SERVER_SOFTWARE = $SERVER_SOFTWARE <br />\n"; exit;
  568. if ( ( substr ( $SERVER_SOFTWARE, 0, 5 ) == "Micro" ) || ( substr ( $SERVER_SOFTWARE, 0, 3 ) == "WN/" ) ) {
  569. echo "<?xml version=\"1.0\" encoding=\"utf-8\"\n
  570. <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"\"DTD/xhtml1-transitional.dtd\">
  571. <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  572. <head>\n
  573. <title>Redirect</title>\n
  574. <meta http-equiv=\"refresh\" content=\"0; url=\"".$url."\" />\n
  575. </head>\n
  576. <body>\n
  577. Redirecting to.. <a href=\"".$url."\">here</a>
  578. </body>\n
  579. </html>";
  580. }else {
  581. Header ( "Location: ".$url );
  582. print "<script>window.location.href=\"".$url."\";</script>" ;
  583. echo "<?xml version=\"1.0\" encoding=\"utf-8\"\n
  584. <!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">
  585. <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  586. <head>\n
  587. <title>Redirect</title>\n
  588. </head>\n
  589. <body>\n
  590. Redirecting to ... <a href=\"".$url."\">here</a>.
  591. </body>\n
  592. </html>";
  593. }
  594. dbi_close ( $c );
  595. exit;
  596. }
  597. /**
  598. * Sends an HTTP login request to the browser and stops execution.
  599. */
  600. function send_http_login () {
  601. global $lang_file, $application_name;
  602. if ( strlen ( $lang_file ) ) {
  603. Header ( "WWW-Authenticate: Basic realm=\"" . translate("Title") . "\"");
  604. Header ( "HTTP/1.0 401 Unauthorized" );
  605. echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html
  606. PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
  607. \"DTD/xhtml1-transitional.dtd\">
  608. <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  609. <head>\n<title>Unauthorized</title>\n</head>\n<body>\n" .
  610. "<h2>" . translate("Title") . "</h2>\n" .
  611. translate("You are not authorized") .
  612. "\n</body>\n</html>";
  613. } else {
  614. Header ( "WWW-Authenticate: Basic realm=\"WebCalendar\"");
  615. Header ( "HTTP/1.0 401 Unauthorized" );
  616. echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!DOCTYPE html
  617. PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
  618. \"DTD/xhtml1-transitional.dtd\">
  619. <html xmlns=\"http://www.w3.org/1999/xhtml\" xml:lang=\"en\" lang=\"en\">
  620. <head>\n<title>Unauthorized</title>\n</head>\n<body>\n" .
  621. "<h2>WebCalendar</h2>\n" .
  622. "You are not authorized" .
  623. "\n</body>\n</html>";
  624. }
  625. exit;
  626. }
  627. /**
  628. * Generates a cookie that saves the last calendar view.
  629. *
  630. * Cookie is based on the current <var>$REQUEST_URI</var>.
  631. *
  632. * We save this cookie so we can return to this same page after a user
  633. * edits/deletes/etc an event.
  634. *
  635. * @global string Request string
  636. */
  637. function remember_this_view () {
  638. global $REQUEST_URI;
  639. if ( empty ( $REQUEST_URI ) )
  640. $REQUEST_URI = $_SERVER["REQUEST_URI"];
  641. // do not use anything with friendly in the URI
  642. if ( strstr ( $REQUEST_URI, "friendly=" ) )
  643. return;
  644. SetCookie ( "webcalendar_last_view", $REQUEST_URI );
  645. }
  646. /**
  647. * Gets the last page stored using {@link remember_this_view()}.
  648. *
  649. * @return string The URL of the last view or an empty string if it cannot be
  650. * determined.
  651. *
  652. * @global array Cookies
  653. */
  654. function get_last_view () {
  655. global $HTTP_COOKIE_VARS;
  656. $val = '';
  657. if ( isset ( $_COOKIE["webcalendar_last_view"] ) ) {
  658. $HTTP_COOKIE_VARS["webcalendar_last_view"] = $_COOKIE["webcalendar_last_view"];
  659. $val = $_COOKIE["webcalendar_last_view"];
  660. } else if ( isset ( $HTTP_COOKIE_VARS["webcalendar_last_view"] ) ) {
  661. $val = $HTTP_COOKIE_VARS["webcalendar_last_view"];
  662. }
  663. $val = str_replace ( "&", "&amp;", $val );
  664. return $val;
  665. }
  666. /**
  667. * Sends HTTP headers that tell the browser not to cache this page.
  668. *
  669. * Different browser use different mechanisms for this, so a series of HTTP
  670. * header directives are sent.
  671. *
  672. * <b>Note:</b> This function needs to be called before any HTML output is sent
  673. * to the browser.
  674. */
  675. function send_no_cache_header () {
  676. header ( "Expires: Mon, 26 Jul 1997 05:00:00 GMT" );
  677. header ( "Last-Modified: " . gmdate ( "D, d M Y H:i:s" ) . " GMT" );
  678. header ( "Cache-Control: no-store, no-cache, must-revalidate" );
  679. header ( "Cache-Control: post-check=0, pre-check=0", false );
  680. header ( "Pragma: no-cache" );
  681. }
  682. /**
  683. * Loads the current user's preferences as global variables from the webcal_user_pref table.
  684. *
  685. * Also loads the list of views for this user (not really a preference, but
  686. * this is a convenient place to put this...)
  687. *
  688. * <b>Notes:</b>
  689. * - If <var>$allow_color_customization</var> is set to 'N', then we ignore any
  690. * color preferences.
  691. * - Other default values will also be set if the user has not saved a
  692. * preference and no global value has been set by the administrator in the
  693. * system settings.
  694. */
  695. function load_user_preferences () {
  696. global $login, $browser, $views, $prefarray, $is_assistant,
  697. $has_boss, $user, $is_nonuser_admin, $allow_color_customization;
  698. $lang_found = false;
  699. $colors = array (
  700. "BGCOLOR" => 1,
  701. "H2COLOR" => 1,
  702. "THBG" => 1,
  703. "THFG" => 1,
  704. "CELLBG" => 1,
  705. "TODAYCELLBG" => 1,
  706. "WEEKENDBG" => 1,
  707. "POPUP_BG" => 1,
  708. "POPUP_FG" => 1,
  709. );
  710. $browser = get_web_browser ();
  711. $browser_lang = get_browser_language ();
  712. $prefarray = array ();
  713. // Note: default values are set in config.php
  714. $res = dbi_query (
  715. "SELECT cal_setting, cal_value FROM webcal_user_pref " .
  716. "WHERE cal_login = '$login'" );
  717. if ( $res ) {
  718. while ( $row = dbi_fetch_row ( $res ) ) {
  719. $setting = $row[0];
  720. $value = $row[1];
  721. if ( $allow_color_customization == 'N' ) {
  722. if ( isset ( $colors[$setting] ) )
  723. continue;
  724. }
  725. $sys_setting = "sys_" . $setting;
  726. // save system defaults
  727. if ( ! empty ( $GLOBALS[$setting] ) )
  728. $GLOBALS["sys_" . $setting] = $GLOBALS[$setting];
  729. $GLOBALS[$setting] = $value;
  730. $prefarray[$setting] = $value;
  731. if ( $setting == "LANGUAGE" )
  732. $lang_found = true;
  733. }
  734. dbi_free_result ( $res );
  735. }
  736. // get views for this user and global views
  737. $res = dbi_query (
  738. "SELECT cal_view_id, cal_name, cal_view_type, cal_is_global " .
  739. "FROM webcal_view " .
  740. "WHERE cal_owner = '$login' OR cal_is_global = 'Y' " .
  741. "ORDER BY cal_name" );
  742. if ( $res ) {
  743. $views = array ();
  744. while ( $row = dbi_fetch_row ( $res ) ) {
  745. if ( $row[2] == 'S' )
  746. $url = "view_t.php?timeb=1&amp;id=$row[0]";
  747. else if ( $row[2] == 'T' )
  748. $url = "view_t.php?timeb=0&amp;id=$row[0]";
  749. else
  750. $url = "view_" . strtolower ( $row[2] ) . ".php?id=$row[0]";
  751. $v = array (
  752. "cal_view_id" => $row[0],
  753. "cal_name" => $row[1],
  754. "cal_view_type" => $row[2],
  755. "cal_is_global" => $row[3],
  756. "url" => $url
  757. );
  758. $views[] = $v;
  759. }
  760. dbi_free_result ( $res );
  761. }
  762. // If user has not set a language preference, then use their browser
  763. // settings to figure it out, and save it in the database for future
  764. // use (email reminders).
  765. if ( ! $lang_found && strlen ( $login ) && $login != "__public__" ) {
  766. $LANGUAGE = $browser_lang;
  767. dbi_query ( "INSERT INTO webcal_user_pref " .
  768. "( cal_login, cal_setting, cal_value ) VALUES " .
  769. "( '$login', 'LANGUAGE', '$LANGUAGE' )" );
  770. }
  771. if ( empty ( $GLOBALS["DATE_FORMAT_MY"] ) )
  772. $GLOBALS["DATE_FORMAT_MY"] = "__month__ __yyyy__";
  773. if ( empty ( $GLOBALS["DATE_FORMAT_MD"] ) )
  774. $GLOBALS["DATE_FORMAT_MD"] = "__month__ __dd__";
  775. $is_assistant = empty ( $user ) ? false :
  776. user_is_assistant ( $login, $user );
  777. $has_boss = user_has_boss ( $login );
  778. $is_nonuser_admin = ($user) ? user_is_nonuser_admin ( $login, $user ) : false;
  779. if ( $is_nonuser_admin ) load_nonuser_preferences ($user);
  780. }
  781. /**
  782. * Gets the list of external users for an event from the webcal_entry_ext_user table in an HTML format.
  783. *
  784. * @param int $event_id Event ID
  785. * @param int $use_mailto When set to 1, email address will contain an href
  786. * link with a mailto URL.
  787. *
  788. * @return string The list of external users for an event formatte in HTML.
  789. */
  790. function event_get_external_users ( $event_id, $use_mailto=0 ) {
  791. global $error;
  792. $ret = "";
  793. $res = dbi_query ( "SELECT cal_fullname, cal_email " .
  794. "FROM webcal_entry_ext_user " .
  795. "WHERE cal_id = $event_id " .
  796. "ORDER by cal_fullname" );
  797. if ( $res ) {
  798. while ( $row = dbi_fetch_row ( $res ) ) {
  799. if ( strlen ( $ret ) )
  800. $ret .= "\n";
  801. // Remove [\d] if duplicate name
  802. $trow = trim( preg_replace( '/\[[\d]]/' , "", $row[0] ) );
  803. $ret .= $trow;
  804. if ( strlen ( $row[1] ) ) {
  805. if ( $use_mailto ) {
  806. $ret .= " <a href=\"mailto:$row[1]\">&lt;" .
  807. htmlentities ( $row[1] ) . "&gt;</a>";
  808. } else {
  809. $ret .= " &lt;". htmlentities ( $row[1] ) . "&gt;";
  810. }
  811. }
  812. }
  813. dbi_free_result ( $res );
  814. } else {
  815. echo translate("Database error") .": " . dbi_error ();
  816. echo "<br />\nSQL:<br />\n$sql";
  817. exit;
  818. }
  819. return $ret;
  820. }
  821. /**
  822. * Adds something to the activity log for an event.
  823. *
  824. * The information will be saved to the webcal_entry_log table.
  825. *
  826. * @param int $event_id Event ID
  827. * @param string $user Username of user doing this
  828. * @param string $user_cal Username of user whose calendar is affected
  829. * @param string $type Type of activity we are logging:
  830. * - $LOG_CREATE
  831. * - $LOG_APPROVE
  832. * - $LOG_REJECT
  833. * - $LOG_UPDATE
  834. * - $LOG_DELETE
  835. * - $LOG_NOTIFICATION
  836. * - $LOG_REMINDER
  837. * @param string $text Text comment to add with activity log entry
  838. */
  839. function activity_log ( $event_id, $user, $user_cal, $type, $text ) {
  840. $next_id = 1;
  841. if ( empty ( $type ) ) {
  842. echo "Error: type not set for activity log!";
  843. // but don't exit since we may be in mid-transaction
  844. return;
  845. }
  846. $res = dbi_query ( "SELECT MAX(cal_log_id) FROM webcal_entry_log" );
  847. if ( $res ) {
  848. if ( $row = dbi_fetch_row ( $res ) ) {
  849. $next_id = $row[0] + 1;
  850. }
  851. dbi_free_result ( $res );
  852. }
  853. $date = date ( "Ymd" );
  854. $time = date ( "Gis" );
  855. $sql_text = empty ( $text ) ? "NULL" : "'$text'";
  856. $sql_user_cal = empty ( $user_cal ) ? "NULL" : "'$user_cal'";
  857. $sql = "INSERT INTO webcal_entry_log ( " .
  858. "cal_log_id, cal_entry_id, cal_login, cal_user_cal, cal_type, " .
  859. "cal_date, cal_time, cal_text ) VALUES ( $next_id, $event_id, " .
  860. "'$user', $sql_user_cal, '$type', $date, $time, $sql_text )";
  861. if ( ! dbi_query ( $sql ) ) {
  862. echo "Database error: " . dbi_error ();
  863. echo "<br />\nSQL:<br />\n$sql";
  864. exit;
  865. }
  866. }
  867. /**
  868. * Gets a list of users.
  869. *
  870. * If groups are enabled, this will restrict the list of users to only those
  871. * users who are in the same group(s) as the user (unless the user is an admin
  872. * user). We allow admin users to see all users because they can also edit
  873. * someone else's events (so they may need access to users who are not in the
  874. * same groups that they are in).
  875. *
  876. * @return array Array of users, where each element in the array is an array
  877. * with the following keys:
  878. * - cal_login
  879. * - cal_lastname
  880. * - cal_firstname
  881. * - cal_is_admin
  882. * - cal_is_admin
  883. * - cal_email
  884. * - cal_password
  885. * - cal_fullname
  886. */
  887. function get_my_users () {
  888. global $login, $is_admin, $groups_enabled, $user_sees_only_his_groups;
  889. if ( $groups_enabled == "Y" && $user_sees_only_his_groups == "Y" &&
  890. ! $is_admin ) {
  891. // get groups that current user is in
  892. $res = dbi_query ( "SELECT cal_group_id FROM webcal_group_user " .
  893. "WHERE cal_login = '$login'" );
  894. $groups = array ();
  895. if ( $res ) {
  896. while ( $row = dbi_fetch_row ( $res ) ) {
  897. $groups[] = $row[0];
  898. }
  899. dbi_fetch_row ( $res );
  900. }
  901. $u = user_get_users ();
  902. $u_byname = array ();
  903. for ( $i = 0; $i < count ( $u ); $i++ ) {
  904. $name = $u[$i]['cal_login'];
  905. $u_byname[$name] = $u[$i];
  906. }
  907. $ret = array ();
  908. if ( count ( $groups ) == 0 ) {
  909. // Eek. User is in no groups... Return only themselves
  910. $ret[] = $u_byname[$login];
  911. return $ret;
  912. }
  913. // get list of users in the same groups as current user
  914. $sql = "SELECT DISTINCT(webcal_group_user.cal_login), cal_lastname, cal_firstname from webcal_group_user " .
  915. "LEFT JOIN webcal_user ON webcal_group_user.cal_login = webcal_user.cal_login " .
  916. "WHERE cal_group_id ";
  917. if ( count ( $groups ) == 1 )
  918. $sql .= "= " . $groups[0];
  919. else {
  920. $sql .= "IN ( " . implode ( ", ", $groups ) . " )";
  921. }
  922. $sql .= " ORDER BY cal_lastname, cal_firstname, webcal_group_user.cal_login";
  923. //echo "SQL: $sql <br />\n";
  924. $res = dbi_query ( $sql );
  925. if ( $res ) {
  926. while ( $row = dbi_fetch_row ( $res ) ) {
  927. $ret[] = $u_byname[$row[0]];
  928. }
  929. dbi_free_result ( $res );
  930. }
  931. return $ret;
  932. } else {
  933. // groups not enabled... return all users
  934. //echo "No groups. ";
  935. return user_get_users ();
  936. }
  937. }
  938. /**
  939. * Gets a preference setting for the specified user.
  940. *
  941. * If no value is found in the database, then the system default setting will
  942. * be returned.
  943. *
  944. * @param string $user User login we are getting preference for
  945. * @param string $setting Name of the setting
  946. *
  947. * @return string The value found in the webcal_user_pref table for the
  948. * specified setting or the sytem default if no user settings
  949. * was found.
  950. */
  951. function get_pref_setting ( $user, $setting ) {
  952. $ret = '';
  953. // set default
  954. if ( ! isset ( $GLOBALS["sys_" .$setting] ) ) {
  955. // this could happen if the current user has not saved any pref. yet
  956. if ( ! empty ( $GLOBALS[$setting] ) )
  957. $ret = $GLOBALS[$setting];
  958. } else {
  959. $ret = $GLOBALS["sys_" .$setting];
  960. }
  961. $sql = "SELECT cal_value FROM webcal_user_pref " .
  962. "WHERE cal_login = '" . $user . "' AND " .
  963. "cal_setting = '" . $setting . "'";
  964. //echo "SQL: $sql <br />\n";
  965. $res = dbi_query ( $sql );
  966. if ( $res ) {
  967. if ( $row = dbi_fetch_row ( $res ) )
  968. $ret = $row[0];
  969. dbi_free_result ( $res );
  970. }
  971. return $ret;
  972. }
  973. /**
  974. * Gets browser-specified language preference.
  975. *
  976. * @return string Preferred language
  977. *
  978. * @ignore
  979. */
  980. function get_browser_language () {
  981. global $HTTP_ACCEPT_LANGUAGE, $browser_languages;
  982. $ret = "";
  983. if ( empty ( $HTTP_ACCEPT_LANGUAGE ) &&
  984. isset ( $_SERVER["HTTP_ACCEPT_LANGUAGE"] ) )
  985. $HTTP_ACCEPT_LANGUAGE = $_SERVER["HTTP_ACCEPT_LANGUAGE"];
  986. if ( empty ( $HTTP_ACCEPT_LANGUAGE ) ) {
  987. return "none";
  988. } else {
  989. $langs = explode ( ",", $HTTP_ACCEPT_LANGUAGE );
  990. for ( $i = 0; $i < count ( $langs ); $i++ ) {
  991. $l = strtolower ( trim ( ereg_replace(';.*', '', $langs[$i] ) ) );
  992. $ret .= "\"$l\" ";
  993. if ( ! empty ( $browser_languages[$l] ) ) {
  994. return $browser_languages[$l];
  995. }
  996. }
  997. }
  998. //if ( strlen ( $HTTP_ACCEPT_LANGUAGE ) )
  999. // return "none ($HTTP_ACCEPT_LANGUAGE not supported)";
  1000. //else
  1001. return "none";
  1002. }
  1003. /**
  1004. * Loads current user's layer info into layer global variable.
  1005. *
  1006. * If the system setting <var>$allow_view_other</var> is not set to 'Y', then
  1007. * we ignore all layer functionality. If <var>$force</var> is 0, we only load
  1008. * layers if the current user preferences have layers turned on.
  1009. *
  1010. * @param string $user Username of user to load layers for
  1011. * @param int $force If set to 1, then load layers for this user even if
  1012. * user preferences have layers turned off.
  1013. */
  1014. function load_user_layers ($user="",$force=0) {
  1015. global $login;
  1016. global $layers;
  1017. global $LAYERS_STATUS, $allow_view_other;
  1018. if ( $user == "" )
  1019. $user = $login;
  1020. $layers = array ();
  1021. if ( empty ( $allow_view_other ) || $allow_view_other != 'Y' )
  1022. return; // not allowed to view others' calendars, so cannot use layers
  1023. if ( $force || ( ! empty ( $LAYERS_STATUS ) && $LAYERS_STATUS != "N" ) ) {
  1024. $res = dbi_query (
  1025. "SELECT cal_layerid, cal_layeruser, cal_color, cal_dups " .
  1026. "FROM webcal_user_layers " .
  1027. "WHERE cal_login = '$user' ORDER BY cal_layerid" );
  1028. if ( $res ) {
  1029. $count = 1;
  1030. while ( $row = dbi_fetch_row ( $res ) ) {
  1031. $layers[$row[0]] = array (
  1032. "cal_layerid" => $row[0],
  1033. "cal_layeruser" => $row[1],
  1034. "cal_color" => $row[2],
  1035. "cal_dups" => $row[3]
  1036. );
  1037. $count++;
  1038. }
  1039. dbi_free_result ( $res );
  1040. }
  1041. } else {
  1042. //echo "Not loading!";
  1043. }
  1044. }
  1045. /**
  1046. * Generates the HTML used in an event popup for the site_extras fields of an event.
  1047. *
  1048. * @param int $id Event ID
  1049. *
  1050. * @return string The HTML to be used within the event popup for any site_extra
  1051. * fields found for the specified event
  1052. */
  1053. function site_extras_for_popup ( $id ) {
  1054. global $site_extras_in_popup, $site_extras;
  1055. // These are needed in case the site_extras.php file was already
  1056. // included.
  1057. global $EXTRA_TEXT, $EXTRA_MULTILINETEXT, $EXTRA_URL, $EXTRA_DATE,
  1058. $EXTRA_EMAIL, $EXTRA_USER, $EXTRA_REMINDER, $EXTRA_SELECTLIST;
  1059. global $EXTRA_REMINDER_WITH_DATE, $EXTRA_REMINDER_WITH_OFFSET,
  1060. $EXTRA_REMINDER_DEFAULT_YES;
  1061. $ret = '';
  1062. if ( $site_extras_in_popup != 'Y' )
  1063. return '';
  1064. include_once 'includes/site_extras.php';
  1065. $extras = get_site_extra_fields ( $id );
  1066. for ( $i = 0; $i < count ( $site_extras ); $i++ ) {
  1067. $extra_name = $site_extras[$i][0];
  1068. $extra_type = $site_extras[$i][2];
  1069. $extra_arg1 = $site_extras[$i][3];
  1070. $extra_arg2 = $site_extras[$i][4];
  1071. if ( ! empty ( $extras[$extra_name]['cal_name'] ) ) {
  1072. $ret .= "<dt>" . translate ( $site_extras[$i][1] ) . ":</dt>\n<dd>";
  1073. if ( $extra_type == $EXTRA_DATE ) {
  1074. if ( $extras[$extra_name]['cal_date'] > 0 )
  1075. $ret .= date_to_str ( $extras[$extra_name]['cal_date'] );
  1076. } else if ( $extra_type == $EXTRA_TEXT ||
  1077. $extra_type == $EXTRA_MULTILINETEXT ) {
  1078. $ret .= nl2br ( $extras[$extra_name]['cal_data'] );
  1079. } else if ( $extra_type == $EXTRA_REMINDER ) {
  1080. if ( $extras[$extra_name]['cal_remind'] <= 0 )
  1081. $ret .= translate ( "No" );
  1082. else {
  1083. $ret .= translate ( "Yes" );
  1084. if ( ( $extra_arg2 & $EXTRA_REMINDER_WITH_DATE ) > 0 ) {
  1085. $ret .= "&nbsp;&nbsp;-&nbsp;&nbsp;";
  1086. $ret .= date_to_str ( $extras[$extra_name]['cal_date'] );
  1087. } else if ( ( $extra_arg2 & $EXTRA_REMINDER_WITH_OFFSET ) > 0 ) {
  1088. $ret .= "&nbsp;&nbsp;-&nbsp;&nbsp;";
  1089. $minutes = $extras[$extra_name]['cal_data'];
  1090. $d = (int) ( $minutes / ( 24 * 60 ) );
  1091. $minutes -= ( $d * 24 * 60 );
  1092. $h = (int) ( $minutes / 60 );
  1093. $minutes -= ( $h * 60 );
  1094. if ( $d > 0 )
  1095. $ret .= $d . "&nbsp;" . translate("days") . "&nbsp;";
  1096. if ( $h > 0 )
  1097. $ret .= $h . "&nbsp;" . translate("hours") . "&nbsp;";
  1098. if ( $minutes > 0 )
  1099. $ret .= $minutes . "&nbsp;" . translate("minutes");
  1100. $ret .= "&nbsp;" . translate("before event" );
  1101. }
  1102. }
  1103. } else {
  1104. $ret .= $extras[$extra_name]['cal_data'];
  1105. }
  1106. $ret .= "</dd>\n";
  1107. }
  1108. }
  1109. return $ret;
  1110. }
  1111. /**
  1112. * Builds the HTML for the event popup.
  1113. *
  1114. * @param string $popupid CSS id to use for event popup
  1115. * @param string $user Username of user the event pertains to
  1116. * @param string $description Event description
  1117. * @param string $time Time of the event (already formatted in a display format)
  1118. * @param string $site_extras HTML for any site_extras for this event
  1119. *
  1120. * @return string The HTML for the event popup
  1121. */
  1122. function build_event_popup ( $popupid, $user, $description, $time, $site_extras='' ) {
  1123. global $login, $popup_fullnames, $popuptemp_fullname;
  1124. $ret = "<dl id=\"$popupid\" class=\"popup\">\n";
  1125. if ( empty ( $popup_fullnames ) )
  1126. $popup_fullnames = array ();
  1127. if ( $user != $login ) {
  1128. if ( empty ( $popup_fullnames[$user] ) ) {
  1129. user_load_variables ( $user, "popuptemp_" );
  1130. $popup_fullnames[$user] = $popuptemp_fullname;
  1131. }
  1132. $ret .= "<dt>" . translate ("User") .
  1133. ":</dt>\n<dd>$popup_fullnames[$user]</dd>\n";
  1134. }
  1135. if ( strlen ( $time ) )
  1136. $ret .= "<dt>" . translate ("Time") . ":</dt>\n<dd>$time</dd>\n";
  1137. $ret .= "<dt>" . translate ("Description") . ":</dt>\n<dd>";
  1138. if ( ! empty ( $GLOBALS['allow_html_description'] ) &&
  1139. $GLOBALS['allow_html_description'] == 'Y' ) {
  1140. $str = str_replace ( "&", "&amp;", $description );
  1141. $str = str_replace ( "&amp;amp;", "&amp;", $str );
  1142. // If there is no html found, then go ahead and replace
  1143. // the line breaks ("\n") with the html break.
  1144. if ( strstr ( $str, "<" ) && strstr ( $str, ">" ) ) {
  1145. // found some html...
  1146. $ret .= $str;
  1147. } else {
  1148. // no html, replace line breaks
  1149. $ret .= nl2br ( $str );
  1150. }
  1151. } else {
  1152. // html not allowed in description, escape everything
  1153. $ret .= nl2br ( htmlspecialchars ( $description ) );
  1154. }
  1155. $ret .= "</dd>\n";
  1156. if ( ! empty ( $site_extras ) )
  1157. $ret .= $site_extras;
  1158. $ret .= "</dl>\n";
  1159. return $ret;
  1160. }
  1161. /**
  1162. * Prints out a date selection box for use in a form.
  1163. *
  1164. * @param string $prefix Prefix to use in front of form element names
  1165. * @param int $date Currently selected date (in YYYYMMDD format)
  1166. *
  1167. * @uses date_selection_html
  1168. */
  1169. function print_date_selection ( $prefix, $date ) {
  1170. print date_selection_html ( $prefix, $date );
  1171. }
  1172. /**
  1173. * Generate HTML for a date selection for use in a form.
  1174. *
  1175. * @param string $prefix Prefix to use in front of form element names
  1176. * @param int $date Currently selected date (in YYYYMMDD format)
  1177. *
  1178. * @return string HTML for the selection box
  1179. */
  1180. function date_selection_html ( $prefix, $date ) {
  1181. $ret = "";
  1182. $num_years = 20;
  1183. if ( strlen ( $date ) != 8 )
  1184. $date = date ( "Ymd" );
  1185. $thisyear = $year = substr ( $date, 0, 4 );
  1186. $thismonth = $month = substr ( $date, 4, 2 );
  1187. $thisday = $day = substr ( $date, 6, 2 );
  1188. if ( $thisyear - date ( "Y" ) >= ( $num_years - 1 ) )
  1189. $num_years = $thisyear - date ( "Y" ) + 2;
  1190. $ret .= "<select name=\"" . $prefix . "day\">\n";
  1191. for ( $i = 1; $i <= 31; $i++ )
  1192. $ret .= "<option value=\"$i\"" .
  1193. ( $i == $thisday ? " selected=\"selected\"" : "" ) . ">$i</option>\n";
  1194. $ret .= "</select>\n<select name=\"" . $prefix . "month\">\n";
  1195. for ( $i = 1; $i <= 12; $i++ ) {
  1196. $m = month_short_name ( $i - 1 );
  1197. $ret .= "<option value=\"$i\"" .
  1198. ( $i == $thismonth ? " selected=\"selected\"" : "" ) . ">$m</option>\n";
  1199. }
  1200. $ret .= "</select>\n<select name=\"" . $prefix . "year\">\n";
  1201. for ( $i = -10; $i < $num_years; $i++ ) {
  1202. $y = $thisyear + $i;
  1203. $ret .= "<option value=\"$y\"" .
  1204. ( $y == $thisyear ? " selected=\"selected\"" : "" ) . ">$y</option>\n";
  1205. }
  1206. $ret .= "</select>\n";
  1207. $ret .= "<input type=\"button\" onclick=\"selectDate( '" .
  1208. $prefix . "day','" . $prefix . "month','" . $prefix . "year',$date, event)\" value=\"" .
  1209. translate("Select") . "...\" />\n";
  1210. return $ret;
  1211. }
  1212. /**
  1213. * Prints out a minicalendar for a month.
  1214. *
  1215. * @todo Make day.php NOT be a special case
  1216. *
  1217. * @param int $thismonth Number of the month to print
  1218. * @param int $thisyear Number of the year
  1219. * @param bool $showyear Show the year in the calendar's title?
  1220. * @param bool $show_weeknums Show week numbers to the left of each row?
  1221. * @param string $minical_id id attribute for the minical table
  1222. * @param string $month_link URL and query string for month link that should
  1223. * come before the date specification (e.g.
  1224. * month.php? or view_l.php?id=7&amp;)
  1225. */
  1226. function display_small_month ( $thismonth, $thisyear, $showyear,
  1227. $show_weeknums=false, $minical_id='', $month_link='month.php?', $info_type='&type_param=user' ) {
  1228. global $WEEK_START, $user, $login, $boldDays, $get_unapproved;
  1229. global $DISPLAY_WEEKNUMBER;
  1230. global $SCRIPT, $thisday; // Needed for day.php
  1231. global $caturl, $today;
  1232. global $log_file;
  1233. //Debug
  1234. logs($log_file,"####### function.php #######\n------- display_small_month -------\n");
  1235. if(isset($get_unapproved)){
  1236. logs($log_file, "1\n");
  1237. }else{
  1238. logs($log_file, "0\n");
  1239. }
  1240. //Debug
  1241. //Debug
  1242. logs($log_file, "UNAPPROVED : ".$GLOBALS['DISPLAY_UNAPPROVED']." get_unapproved : ".($get_unapproved?"1":"0")."\n");
  1243. //Debug
  1244. if ( $user != $login && ! empty ( $user ) ) {
  1245. $u_url = "user=$user" . "&amp;";
  1246. } else {
  1247. $u_url = '';
  1248. }
  1249. $u_url .= $info_type."&";
  1250. //start the minical table for each month
  1251. echo "\n<table class=\"minical\"";
  1252. if ( $minical_id != '' ) {
  1253. echo " id=\"$minical_id\"";
  1254. }
  1255. echo ">\n";
  1256. $monthstart = mktime(2,0,0,$thismonth,1,$thisyear);
  1257. $monthend = mktime(2,0,0,$thismonth + 1,0,$thisyear);
  1258. if ( $SCRIPT == 'day.php' ) {
  1259. $month_ago = date ( "Ymd",
  1260. mktime ( 3, 0, 0, $thismonth - 1, $thisday, $thisyear ) );
  1261. $month_ahead = date ( "Ymd",
  1262. mktime ( 3, 0, 0, $thismonth + 1, $thisday, $thisyear ) );
  1263. echo "<caption>$thisday</caption>\n";
  1264. echo "<thead>\n";
  1265. echo "<tr class=\"monthnav\"><th colspan=\"7\">\n";
  1266. echo "<a title=\"" .
  1267. translate("Previous") . "\" class=\"prev\" href=\"day.php?" . $u_url .
  1268. "date=$month_ago$caturl\"><img src=\"leftarrowsmall.gif\" alt=\"" .
  1269. translate("Previous") . "\" /></a>\n";
  1270. echo "<a title=\"" .
  1271. translate("Next") . "\" class=\"next\" href=\"day.php?" . $u_url .
  1272. "date=$month_ahead$caturl\"><img src=\"rightarrowsmall.gif\" alt=\"" .
  1273. translate("Next") . "\" /></a>\n";
  1274. echo month_name ( $thismonth - 1 );
  1275. if ( $showyear != '' ) {
  1276. echo " $thisyear";
  1277. }
  1278. echo "</th></tr>\n<tr>\n";
  1279. } else { //not day script
  1280. //print the month name
  1281. echo "<caption><a href=\"{$month_link}{$u_url}year=$thisyear&amp;month=$thismonth\">";
  1282. echo month_name ( $thismonth - 1 ) .
  1283. ( $showyear ? " $thisyear" : "" );
  1284. echo "</a></caption>\n";
  1285. echo "<thead>\n<tr>\n";
  1286. }
  1287. //determine if the week starts on sunday or monday
  1288. if ( $WEEK_START == "1" ) {
  1289. $wkstart = get_monday_before ( $thisyear, $thismonth, 1 );
  1290. } else {
  1291. $wkstart = get_sunday_before ( $thisyear, $thismonth, 1 );
  1292. }
  1293. //print the headers to display the day of the week (sun, mon, tues, etc.)
  1294. // if we're showing week numbers we need an extra column
  1295. if ( $show_weeknums && $DISPLAY_WEEKNUMBER == 'Y' )
  1296. echo "<th class=\"empty\">&nbsp;</th>\n";
  1297. //if the week doesn't start on monday, print the day
  1298. if ( $WEEK_START == 0 ) echo "<th>" .
  1299. weekday_short_name ( 0 ) . "</th>\n";
  1300. //cycle through each day of the week until gone
  1301. for ( $i = 1; $i < 7; $i++ ) {
  1302. echo "<th>" . weekday_short_name ( $i ) . "</th>\n";
  1303. }
  1304. //if the week DOES start on monday, print sunday
  1305. if ( $WEEK_START == 1 )
  1306. echo "<th>" . weekday_short_name ( 0 ) . "</th>\n";
  1307. //end the header row
  1308. echo "</tr>\n</thead>\n<tbody>\n";
  1309. for ($i = $wkstart; date("Ymd",$i) <= date ("Ymd",$monthend);
  1310. $i += (24 * 3600 * 7) ) {
  1311. echo "<tr>\n";
  1312. if ( $show_weeknums && $DISPLAY_WEEKNUMBER == 'Y' ) {
  1313. echo "<td class=\"weeknumber\"><a href=\"week.php?" . $u_url .
  1314. "date=".date("Ymd", $i)."\">(" . week_number($i) . ")</a></td>\n";
  1315. }
  1316. for ($j = 0; $j < 7; $j++) {
  1317. $date = $i + ($j * 24 * 3600);
  1318. $dateYmd = date ( "Ymd", $date );
  1319. $hasEvents = false;
  1320. if ( $boldDays ) {
  1321. $ev = get_entries ( $user, $dateYmd, $get_unapproved );
  1322. if ( count ( $ev ) > 0 ) {
  1323. $hasEvents = true;
  1324. } else {
  1325. $rep = get_repeating_entries ( $user, $dateYmd, $get_unapproved );
  1326. if ( count ( $rep ) > 0 )
  1327. $hasEvents = true;
  1328. }
  1329. }
  1330. if ( $dateYmd >= date ("Ymd",$monthstart) &&
  1331. $dateYmd <= date ("Ymd",$monthend) ) {
  1332. echo "<td";
  1333. $wday = date ( 'w', $date );
  1334. $class = '';
  1335. //add class="weekend" if it's saturday or sunday
  1336. if ( $wday == 0 || $wday == 6 ) {
  1337. $class = "weekend";
  1338. }
  1339. //if the day being viewed is today's date AND script = day.php
  1340. if ( $dateYmd == $thisyear . $thismonth . $thisday &&
  1341. $SCRIPT == 'day.php' ) {
  1342. //if it's also a weekend, add a space between class names to combine styles
  1343. if ( $class != '' ) {
  1344. $class .= ' ';
  1345. }
  1346. $class .= "selectedday";
  1347. }
  1348. if ( $hasEvents ) {
  1349. if ( $class != '' ) {
  1350. $class .= ' ';
  1351. }
  1352. $class .= "hasevents";
  1353. }
  1354. if ( $class != '' ) {
  1355. echo " class=\"$class\"";
  1356. }
  1357. if ( date ( "Ymd", $date ) == date ( "Ymd", $today ) ){
  1358. echo " id=\"today\"";
  1359. }
  1360. echo "><a href=\"day.php?" .$u_url . "date=" . $dateYmd .
  1361. "\">";
  1362. echo date ( "d", $date ) . "</a></td>\n";
  1363. } else {
  1364. echo "<td class=\"empty\">&nbsp;</td>\n";
  1365. }
  1366. } // end for $j
  1367. echo "</tr>\n";
  1368. } // end for $i
  1369. echo "</tbody>\n</table>\n";
  1370. }
  1371. /**
  1372. * Prints the HTML for one day's events in the month view.
  1373. *
  1374. * @param int $id Event ID
  1375. * @param int $date Date of event (relevant in repeating events) in
  1376. * YYYYMMDD format
  1377. * @param int $time Time (in HHMMSS format)
  1378. * @param int $duration Event duration in minutes
  1379. * @param string $name Event name
  1380. * @param string $description Long description of event
  1381. * @param string $status Event status
  1382. * @param int $pri Event priority
  1383. * @param string $access Event access
  1384. * @param string $event_owner Username of user associated with this event
  1385. * @param int $event_cat Category of event for <var>$event_owner</var>
  1386. *
  1387. * @staticvar int Used to ensure all event popups have a unique id
  1388. *
  1389. * @uses build_event_popup
  1390. */
  1391. function print_entry ( $id, $date, $time, $duration,
  1392. $name, $description, $status,
  1393. $pri, $access, $event_owner, $event_cat=-1 ) {
  1394. global $eventinfo, $login, $user, $PHP_SELF, $TZ_OFFSET;
  1395. static $key = 0;
  1396. global $layers;
  1397. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  1398. $class = "layerentry";
  1399. } else {
  1400. $class = "entry";
  1401. if ( $status == "W" ) $class = "unapprovedentry";
  1402. }
  1403. // if we are looking at a view, then always use "entry"
  1404. if ( strstr ( $PHP_SELF, "view_m.php" ) ||
  1405. strstr ( $PHP_SELF, "view_w.php" ) ||
  1406. strstr ( $PHP_SELF, "view_v.php" ) ||
  1407. strstr ( $PHP_SELF, "view_t.php" ) )
  1408. $class = "entry";
  1409. if($GLOBALS['type_param'] == 'group'){
  1410. $info_type = "&type_param=group&group_param=".$GLOBALS['group_param'];
  1411. }else{
  1412. $info_type = "&type_param=user";
  1413. }
  1414. if ( $pri == 3 ) echo "<strong>";
  1415. $popupid = "eventinfo-$id-$key";
  1416. $key++;
  1417. echo "<a title=\"" .
  1418. translate("View this entry") . "\" class=\"$class\" href=\"view_entry.php?id=$id&amp;date=$date".$info_type;
  1419. if ( strlen ( $user ) > 0 )
  1420. echo "&amp;user=" . $user;
  1421. echo "\" onmouseover=\"window.status='" .
  1422. translate("View this entry") .
  1423. "'; show(event, '$popupid'); return true;\" onmouseout=\"window.status=''; hide('$popupid'); return true;\">";
  1424. $icon = "circle.gif";
  1425. $catIcon = '';
  1426. if ( $event_cat > 0 ) {
  1427. $catIcon = "icons/cat-" . $event_cat . ".gif";
  1428. if ( ! file_exists ( $catIcon ) )
  1429. $catIcon = '';
  1430. }
  1431. if ( empty ( $catIcon ) ) {
  1432. echo "<img src=\"$icon\" class=\"bullet\" alt=\"" .
  1433. translate("View this entry") . "\" />";
  1434. } else {
  1435. // Use category icon
  1436. echo "<img src=\"$catIcon\" alt=\"" .
  1437. translate("View this entry") . "\" /><br />";
  1438. }
  1439. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  1440. if ($layers) foreach ($layers as $layer) {
  1441. if ($layer['cal_layeruser'] == $event_owner) {
  1442. echo("<span style=\"color:" . $layer['cal_color'] . ";\">");
  1443. }
  1444. }
  1445. }
  1446. $timestr = "";
  1447. if ( $duration == ( 24 * 60 ) ) {
  1448. $timestr = translate("All day event");
  1449. } else if ( $time != -1 ) {
  1450. $timestr = display_time ( $time );
  1451. $time_short = preg_replace ("/(:00)/", '', $timestr);
  1452. echo $time_short . "&raquo;&nbsp;";
  1453. if ( $duration > 0 ) {
  1454. // calc end time
  1455. $h = (int) ( $time / 10000 );
  1456. $m = ( $time / 100 ) % 100;
  1457. $m += $duration;
  1458. $d = $duration;
  1459. while ( $m >= 60 ) {
  1460. $h++;
  1461. $m -= 60;
  1462. }
  1463. $end_time = sprintf ( "%02d%02d00", $h, $m );
  1464. $timestr .= " - " . display_time ( $end_time );
  1465. }
  1466. }
  1467. if ( $login != $user && $access == 'R' && strlen ( $user ) ) {
  1468. echo "(" . translate("Private") . ")";
  1469. } else if ( $login != $event_owner && $access == 'R' &&
  1470. strlen ( $event_owner ) ) {
  1471. echo "(" . translate("Private") . ")";
  1472. } else {
  1473. echo htmlspecialchars ( $name );
  1474. }
  1475. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  1476. if ($layers) foreach ($layers as $layer) {
  1477. if($layer['cal_layeruser'] == $event_owner) {
  1478. echo "</span>";
  1479. }
  1480. }
  1481. }
  1482. echo "</a>\n";
  1483. if ( $pri == 3 ) echo "</strong>\n"; //end font-weight span
  1484. echo "<br />";
  1485. if ( $login != $user && $access == 'R' && strlen ( $user ) )
  1486. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  1487. translate("This event is confidential"), "" );
  1488. else
  1489. if ( $login != $event_owner && $access == 'R' && strlen ( $event_owner ) )
  1490. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  1491. translate("This event is confidential"), "" );
  1492. else
  1493. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  1494. $description, $timestr, site_extras_for_popup ( $id ) );
  1495. }
  1496. /**
  1497. * Gets any site-specific fields for an entry that are stored in the database in the webcal_site_extras table.
  1498. *
  1499. * @param int $eventid Event ID
  1500. *
  1501. * @return array Array with the keys as follows:
  1502. * - <var>cal_name</var>
  1503. * - <var>cal_type</var>
  1504. * - <var>cal_date</var>
  1505. * - <var>cal_remind</var>
  1506. * - <var>cal_data</var>
  1507. */
  1508. function get_site_extra_fields ( $eventid ) {
  1509. $sql = "SELECT cal_name, cal_type, cal_date, cal_remind, cal_data " .
  1510. "FROM webcal_site_extras " .
  1511. "WHERE cal_id = $eventid";
  1512. $res = dbi_query ( $sql );
  1513. $extras = array ();
  1514. if ( $res ) {
  1515. while ( $row = dbi_fetch_row ( $res ) ) {
  1516. // save by cal_name (e.g. "URL")
  1517. $extras[$row[0]] = array (
  1518. "cal_name" => $row[0],
  1519. "cal_type" => $row[1],
  1520. "cal_date" => $row[2],
  1521. "cal_remind" => $row[3],
  1522. "cal_data" => $row[4]
  1523. );
  1524. }
  1525. dbi_free_result ( $res );
  1526. }
  1527. return $extras;
  1528. }
  1529. /**
  1530. * Reads all the events for a user for the specified range of dates.
  1531. *
  1532. * This is only called once per page request to improve performance. All the
  1533. * events get loaded into the array <var>$events</var> sorted by time of day
  1534. * (not date).
  1535. *
  1536. * @param string $user Username
  1537. * @param string $startdate Start date range, inclusive (in YYYYMMDD format)
  1538. * @param string $enddate End date range, inclusive (in YYYYMMDD format)
  1539. * @param int $cat_id Category ID to filter on
  1540. *
  1541. * @return array Array of events
  1542. *
  1543. * @uses query_events
  1544. */
  1545. function read_events ( $user, $startdate, $enddate, $cat_id = '' ) {
  1546. global $login;
  1547. global $layers;
  1548. global $TZ_OFFSET;
  1549. global $log_file;
  1550. //debug
  1551. logs($log_file,"function.php : read_event \n");
  1552. //debug
  1553. $sy = substr ( $startdate, 0, 4 );
  1554. $sm = substr ( $startdate, 4, 2 );
  1555. $sd = substr ( $startdate, 6, 2 );
  1556. $ey = substr ( $enddate, 0, 4 );
  1557. $em = substr ( $enddate, 4, 2 );
  1558. $ed = substr ( $enddate, 6, 2 );
  1559. if ( $startdate == $enddate ) {
  1560. if ( $TZ_OFFSET == 0 ) {
  1561. $date_filter = " AND webcal_entry.cal_date = $startdate";
  1562. } else if ( $TZ_OFFSET > 0 ) {
  1563. $prev_day = mktime ( 3, 0, 0, $sm, $sd - 1, $sy );
  1564. $cutoff = 24 - $TZ_OFFSET . "0000";
  1565. $date_filter = " AND ( ( webcal_entry.cal_date = $startdate AND " .
  1566. "( webcal_entry.cal_time <= $cutoff OR " .
  1567. "webcal_entry.cal_time = -1 ) ) OR " .
  1568. "( webcal_entry.cal_date = " . date("Ymd", $prev_day ) .
  1569. " AND webcal_entry.cal_time >= $cutoff ) )";
  1570. } else {
  1571. $next_day = mktime ( 3, 0, 0, $sm, $sd + 1, $sy );
  1572. $cutoff = ( 0 - $TZ_OFFSET ) * 10000;
  1573. $date_filter = " AND ( ( webcal_entry.cal_date = $startdate AND " .
  1574. "( webcal_entry.cal_time > $cutoff OR " .
  1575. "webcal_entry.cal_time = -1 ) ) OR " .
  1576. "( webcal_entry.cal_date = " . date("Ymd", $next_day ) .
  1577. " AND webcal_entry.cal_time <= $cutoff ) )";
  1578. }
  1579. } else {
  1580. if ( $TZ_OFFSET == 0 ) {
  1581. $date_filter = " AND webcal_entry.cal_date >= $startdate " .
  1582. "AND webcal_entry.cal_date <= $enddate";
  1583. } else if ( $TZ_OFFSET > 0 ) {
  1584. $prev_day = date ( ( "Ymd" ), mktime ( 3, 0, 0, $sm, $sd - 1, $sy ) );
  1585. $enddate_minus1 = date ( ( "Ymd" ), mktime ( 3, 0, 0, $em, $ed - 1, $ey ) );
  1586. $cutoff = 24 - $TZ_OFFSET . "0000";
  1587. $date_filter = " AND ( ( webcal_entry.cal_date >= $startdate " .
  1588. "AND webcal_entry.cal_date <= $enddate AND " .
  1589. "webcal_entry.cal_time = -1 ) OR " .
  1590. "( webcal_entry.cal_date = $prev_day AND " .
  1591. "webcal_entry.cal_time >= $cutoff ) OR " .
  1592. "( webcal_entry.cal_date = $enddate AND " .
  1593. "webcal_entry.cal_time < $cutoff ) OR " .
  1594. "( webcal_entry.cal_date >= $startdate AND " .
  1595. "webcal_entry.cal_date <= $enddate_minus1 ) )";
  1596. } else {
  1597. // TZ_OFFSET < 0
  1598. $next_day = date ( ( "Ymd" ), mktime ( 3, 0, 0, $sm, $sd + 1, $sy ) );
  1599. $enddate_plus1 =
  1600. date ( ( "Ymd" ), mktime ( 3, 0, 0, $em, $ed + 1, $ey ) );
  1601. $cutoff = ( 0 - $TZ_OFFSET ) * 10000;
  1602. $date_filter = " AND ( ( webcal_entry.cal_date >= $startdate " .
  1603. "AND webcal_entry.cal_date <= $enddate AND " .
  1604. "webcal_entry.cal_time = -1 ) OR " .
  1605. "( webcal_entry.cal_date = $startdate AND " .
  1606. "webcal_entry.cal_time > $cutoff ) OR " .
  1607. "( webcal_entry.cal_date = $enddate_plus1 AND " .
  1608. "webcal_entry.cal_time <= $cutoff ) OR " .
  1609. "( webcal_entry.cal_date > $startdate AND " .
  1610. "webcal_entry.cal_date < $enddate_plus1 ) )";
  1611. }
  1612. }
  1613. //debug
  1614. //logs($log_file,"function.php : read_event : ".$date_filter."\n");
  1615. //debug
  1616. return query_events ( $user, false, $date_filter, $cat_id );
  1617. }
  1618. /**
  1619. * Gets all the events for a specific date.
  1620. *
  1621. * Events are retreived from the array of pre-loaded events (which was loaded
  1622. * all at once to improve performance).
  1623. *
  1624. * The returned events will be sorted by time of day.
  1625. *
  1626. * @param string $user Username
  1627. * @param string $date Date to get events for in YYYYMMDD format
  1628. * @param bool $get_unapproved Load unapproved events?
  1629. *
  1630. * @return array Array of events
  1631. */
  1632. function get_entries ( $user, $date, $get_unapproved=true ) {
  1633. global $events, $TZ_OFFSET;
  1634. global $log_file;
  1635. $n = 0;
  1636. $ret = array ();
  1637. //echo "<br />\nChecking " . count ( $events ) . " events. TZ_OFFSET = $TZ_OFFSET, get_unapproved=" . $get_unapproved . "<br />\n";
  1638. //print_r ( $events );
  1639. //Debug
  1640. //logs($log_file,"######## function.php #######\n-------- get_entries -------\n");
  1641. //logs($log_file,"date : ".$date."\n");
  1642. //if($get_unapproved){
  1643. // logs($log_file,"get unapproved\n");
  1644. //}else{
  1645. // logs($log_file,"don't get unapproved\n");
  1646. //}
  1647. //logs($log_file,print_r($events,true)."\n");
  1648. //Debug
  1649. for ( $i = 0; $i < count ( $events ); $i++ ) {
  1650. // In case of data corruption (or some other bug...)
  1651. if ( empty ( $events[$i] ) || empty ( $events[$i]['cal_id'] ) )
  1652. continue;
  1653. if ( ( ! $get_unapproved ) && $events[$i]['cal_status'] == 'W' ) {
  1654. // ignore this event
  1655. //debug
  1656. logs($log_file,"ignore this event\n");
  1657. //debug
  1658. //don't adjust anything if no TZ offset or ALL Day Event or Untimed
  1659. } else if ( empty ( $TZ_OFFSET) || ( $events[$i]['cal_time'] <= 0 ) ) {
  1660. if ( $events[$i]['cal_date'] == $date )
  1661. $ret[$n++] = $events[$i];
  1662. } else if ( $TZ_OFFSET > 0 ) {
  1663. $cutoff = ( 24 - $TZ_OFFSET ) * 10000;
  1664. //echo "<br /> cal_time " . $events[$i]['cal_time'] . "<br />\n";
  1665. $sy = substr ( $date, 0, 4 );
  1666. $sm = substr ( $date, 4, 2 );
  1667. $sd = substr ( $date, 6, 2 );
  1668. $prev_day = date ( ( "Ymd" ), mktime ( 3, 0, 0, $sm, $sd - 1, $sy ) );
  1669. //echo "prev_date = $prev_day <br />\n";
  1670. if ( $events[$i]['cal_date'] == $date &&
  1671. $events[$i]['cal_time'] == -1 ) {
  1672. $ret[$n++] = $events[$i];
  1673. //echo "added event $events[$i][cal_id] <br />\n";
  1674. } else if ( $events[$i]['cal_date'] == $date &&
  1675. $events[$i]['cal_time'] < $cutoff ) {
  1676. $ret[$n++] = $events[$i];
  1677. //echo "added event {$events[$i][cal_id]} <br />\n";
  1678. } else if ( $events[$i]['cal_date'] == $prev_day &&
  1679. $events[$i]['cal_time'] >= $cutoff ) {
  1680. $ret[$n++] = $events[$i];
  1681. //echo "added event {$events[$i][cal_id]} <br />\n";
  1682. }
  1683. } else {
  1684. //TZ < 0
  1685. $cutoff = ( 0 - $TZ_OFFSET ) * 10000;
  1686. //echo "<br />\ncal_time " . $events[$i]['cal_time'] . "<br />\n";
  1687. $sy = substr ( $date, 0, 4 );
  1688. $sm = substr ( $date, 4, 2 );
  1689. $sd = substr ( $date, 6, 2 );
  1690. $next_day = date ( ( "Ymd" ), mktime ( 3, 0, 0, $sm, $sd + 1, $sy ) );
  1691. //echo "next_date = $next_day <br />\n";
  1692. if ( $events[$i]['cal_time'] == -1 ) {
  1693. if ( $events[$i]['cal_date'] == $date ) {
  1694. $ret[$n++] = $events[$i];
  1695. //echo "added event $events[$i][cal_id] <br />\n";
  1696. }
  1697. } else {
  1698. if ( $events[$i]['cal_date'] == $date &&
  1699. $events[$i]['cal_time'] > $cutoff ) {
  1700. $ret[$n++] = $events[$i];
  1701. //echo "added event $events[$i][cal_id] <br />\n";
  1702. } else if ( $events[$i]['cal_date'] == $next_day &&
  1703. $events[$i]['cal_time'] <= $cutoff ) {
  1704. $ret[$n++] = $events[$i];
  1705. //echo "added event $events[$i][cal_id] <br />\n";
  1706. }
  1707. }
  1708. }
  1709. }
  1710. //Debug
  1711. //logs($log_file,"ret : ".print_r($ret,true)."\n");
  1712. //Debug
  1713. return $ret;
  1714. }
  1715. /**
  1716. * Reads events visible to a user.
  1717. *
  1718. * Includes layers and possibly public access if enabled
  1719. *
  1720. * @param string $user Username
  1721. * @param bool $want_repeated Get repeating events?
  1722. * @param string $date_filter SQL phrase starting with AND, to be appended to
  1723. * the WHERE clause. May be empty string.
  1724. * @param int $cat_id Category ID to filter on. May be empty.
  1725. *
  1726. * @return array Array of events sorted by time of day
  1727. */
  1728. function query_events ( $user, $want_repeated, $date_filter, $cat_id = '' ) {
  1729. global $login;
  1730. global $layers, $public_access_default_visible;
  1731. global $log_file;
  1732. $result = array ();
  1733. $layers_byuser = array ();
  1734. $sql = "SELECT distinct e.cal_name, e.cal_description,e.cal_date, e.cal_time,e.cal_id,"
  1735. ." e.cal_ext_for_id,e.cal_priority,e.cal_access,e.cal_duration, "
  1736. ." eu1.cal_status,eu1.cal_category, eu1.cal_login ";
  1737. if ( $want_repeated ) {
  1738. $sql .= ", "
  1739. . "er.cal_type, er.cal_end, "
  1740. . "er.cal_frequency, er.cal_days "
  1741. . "FROM webcal_entry e, webcal_entry_repeats er, webcal_entry_user eu1 "
  1742. . "WHERE e.cal_id = er.cal_id AND ";
  1743. } else {
  1744. $sql .= "FROM webcal_entry e, webcal_entry_user eu1 "
  1745. . " WHERE ";
  1746. }
  1747. $sql .= "e.cal_id = eu1.cal_id AND eu1.cal_status IN ('A','W') AND ".
  1748. "(eu1.cal_group_status NOT LIKE ('%,R:".$user.",%') ".
  1749. " OR eu1.cal_group_status is null)";
  1750. if ( $cat_id != '' ) $sql .= "AND eu1.cal_category LIKE '$cat_id' ";
  1751. if ( strlen ( $user ) > 0 )
  1752. $sql .= "AND (eu1.cal_login = '" . $user . "' ";
  1753. if ( $user == $login && strlen ( $user ) > 0 ) {
  1754. if ($layers) foreach ($layers as $layer) {
  1755. $layeruser = $layer['cal_layeruser'];
  1756. $sql .= "OR eu1.cal_login = '" . $layeruser . "' ";
  1757. // while we are parsing the whole layers array, build ourselves
  1758. // a new array that will help when we have to check for dups
  1759. $layers_byuser["$layeruser"] = $layer['cal_dups'];
  1760. }
  1761. }
  1762. if ( $user == $login && strlen ( $user ) &&
  1763. $public_access_default_visible == 'Y' ) {
  1764. $sql .= "OR eu1.cal_login = '__public__' ";
  1765. }
  1766. if ( strlen ( $user ) > 0 )
  1767. $sql .= " OR ".
  1768. "eu1.cal_login in ( ".
  1769. "select ".
  1770. "eu2.cal_login ".
  1771. "from ".
  1772. "webcal_entry e, ".
  1773. "webcal_entry_user eu2, ".
  1774. "webcal_group_user gu, ".
  1775. "webcal_group g ".
  1776. "where ".
  1777. "e.cal_id = eu2.cal_id AND ".
  1778. "eu2.cal_login = g.cal_name AND ".
  1779. "g.cal_group_id = gu.cal_group_id AND ".
  1780. "eu2.cal_status IN ('A','W') AND ".
  1781. "gu.cal_login = '".$user."' AND ".
  1782. "(eu2.cal_group_status NOT LIKE ('%,R:".$user.",%') ".
  1783. " OR eu2.cal_group_status is null)".
  1784. ")
  1785. OR e.cal_create_by='".$user."')";
  1786. $sql .= $date_filter;
  1787. // now order the results by time and by entry id.
  1788. $sql .= " ORDER BY e.cal_time, e.cal_id";
  1789. //echo "<strong>SQL:</strong> $sql<br />\n";
  1790. //debug
  1791. logs($log_file,"function.php : query_events : ".$sql."\n");
  1792. //debug
  1793. $res = dbi_query ( $sql );
  1794. if ( $res ) {
  1795. $i = 0;
  1796. $checkdup_id = -1;
  1797. $first_i_this_id = -1;
  1798. while ( $row = dbi_fetch_row ( $res ) ) {
  1799. if ($row[9] == 'R' || $row[9] == 'D') {
  1800. continue; // don't show rejected/deleted ones
  1801. }
  1802. $item = array (
  1803. "cal_name" => $row[0],
  1804. "cal_description" => $row[1],
  1805. "cal_date" => $row[2],
  1806. "cal_time" => $row[3],
  1807. "cal_id" => $row[4],
  1808. "cal_ext_for_id" => $row[5],
  1809. "cal_priority" => $row[6],
  1810. "cal_access" => $row[7],
  1811. "cal_duration" => $row[8],
  1812. "cal_status" => $row[9],
  1813. "cal_category" => $row[10],
  1814. "cal_login" => $row[11],
  1815. "cal_exceptions" => array()
  1816. );
  1817. if ( $want_repeated && ! empty ( $row[12] ) ) {
  1818. $item['cal_type'] = empty ( $row[12] ) ? "" : $row[12];
  1819. $item['cal_end'] = empty ( $row[13] ) ? "" : $row[13];
  1820. $item['cal_frequency'] = empty ( $row[14] ) ? "" : $row[14];
  1821. $item['cal_days'] = empty ( $row[15] ) ? "" : $row[15];
  1822. }
  1823. if ( $item['cal_id'] != $checkdup_id ) {
  1824. $checkdup_id = $item['cal_id'];
  1825. $first_i_this_id = $i;
  1826. }
  1827. if ( $item['cal_login'] == $user ) {
  1828. // Insert this one before all other ones with this ID.
  1829. my_array_splice ( $result, $first_i_this_id, 0, array($item) );
  1830. $i++;
  1831. if ($first_i_this_id + 1 < $i) {
  1832. // There's another one with the same ID as the one we inserted.
  1833. // Check for dup and if so, delete it.
  1834. $other_item = $result[$first_i_this_id + 1];
  1835. if ($layers_byuser[$other_item['cal_login']] == 'N') {
  1836. // NOTE: array_splice requires PHP4
  1837. my_array_splice ( $result, $first_i_this_id + 1, 1, "" );
  1838. $i--;
  1839. }
  1840. }
  1841. } else {
  1842. if ($i == $first_i_this_id
  1843. || ( ! empty ( $layers_byuser[$item['cal_login']] ) &&
  1844. $layers_byuser[$item['cal_login']] != 'N' ) ) {
  1845. // This item either is the first one with its ID, or allows dups.
  1846. // Add it to the end of the array.
  1847. $result [$i++] = $item;
  1848. }
  1849. }
  1850. }
  1851. dbi_free_result ( $res );
  1852. }
  1853. // Now load event exceptions and store as array in 'cal_exceptions' field
  1854. if ( $want_repeated ) {
  1855. for ( $i = 0; $i < count ( $result ); $i++ ) {
  1856. if ( ! empty ( $result[$i]['cal_id'] ) ) {
  1857. $res = dbi_query ( "SELECT cal_date FROM webcal_entry_repeats_not " .
  1858. "WHERE cal_id = " . $result[$i]['cal_id'] );
  1859. while ( $row = dbi_fetch_row ( $res ) ) {
  1860. $result[$i]['cal_exceptions'][] = $row[0];
  1861. }
  1862. }
  1863. }
  1864. }
  1865. return $result;
  1866. }
  1867. /**
  1868. * Reads all the repeated events for a user.
  1869. *
  1870. * This is only called once per page request to improve performance. All the
  1871. * events get loaded into the array <var>$repeated_events</var> sorted by time of day (not
  1872. * date).
  1873. *
  1874. * This will load all the repeated events into memory.
  1875. *
  1876. * <b>Notes:</b>
  1877. * - To get which events repeat on a specific date, use
  1878. * {@link get_repeating_entries()}.
  1879. * - To get all the dates that one specific event repeats on, call
  1880. * {@link get_all_dates()}.
  1881. *
  1882. * @param string $user Username
  1883. * @param int $cat_id Category ID to filter on (May be empty)
  1884. * @param string $date Cutoff date for repeating event endtimes in YYYYMMDD
  1885. * format (may be empty)
  1886. *
  1887. * @return Array of repeating events sorted by time of day
  1888. *
  1889. * @uses query_events
  1890. */
  1891. function read_repeated_events ( $user, $cat_id = '', $date = '' ) {
  1892. global $login;
  1893. global $layers;
  1894. $filter = ($date != '') ? "AND (webcal_entry_repeats.cal_end >= $date OR webcal_entry_repeats.cal_end IS NULL) " : '';
  1895. return query_events ( $user, true, $filter, $cat_id );
  1896. }
  1897. /**
  1898. * Returns all the dates a specific event will fall on accounting for the repeating.
  1899. *
  1900. * Any event with no end will be assigned one.
  1901. *
  1902. * @param string $date Initial date in raw format
  1903. * @param string $rpt_type Repeating type as stored in the database
  1904. * @param string $end End date
  1905. * @param string $days Days events occurs on (for weekly)
  1906. * @param array $ex_dates Array of exception dates for this event in YYYYMMDD format
  1907. * @param int $freq Frequency of repetition
  1908. *
  1909. * @return array Array of dates (in UNIX time format)
  1910. */
  1911. function get_all_dates ( $date, $rpt_type, $end, $days, $ex_days, $freq=1 ) {
  1912. global $conflict_repeat_months, $days_per_month, $ldays_per_month;
  1913. global $ONE_DAY;
  1914. //echo "get_all_dates ( $date, '$rpt_type', $end, '$days', [array], $freq ) <br>\n";
  1915. $currentdate = floor($date/$ONE_DAY)*$ONE_DAY;
  1916. $realend = floor($end/$ONE_DAY)*$ONE_DAY;
  1917. $dateYmd = date ( "Ymd", $date );
  1918. if ($end=='NULL') {
  1919. // Check for $conflict_repeat_months months into future for conflicts
  1920. $thismonth = substr($dateYmd, 4, 2);
  1921. $thisyear = substr($dateYmd, 0, 4);
  1922. $thisday = substr($dateYmd, 6, 2);
  1923. $thismonth += $conflict_repeat_months;
  1924. if ($thismonth > 12) {
  1925. $thisyear++;
  1926. $thismonth -= 12;
  1927. }
  1928. $realend = mktime(3,0,0,$thismonth,$thisday,$thisyear);
  1929. }
  1930. $ret = array();
  1931. $ret[0] = $date;
  1932. //do iterative checking here.
  1933. //I floored the $realend so I check it against the floored date
  1934. if ($rpt_type && $currentdate < $realend) {
  1935. $cdate = $date;
  1936. if (!$freq) $freq = 1;
  1937. $n = 1;
  1938. if ($rpt_type == 'daily') {
  1939. //we do inclusive counting on end dates.
  1940. $cdate += $ONE_DAY * $freq;
  1941. while ($cdate <= $realend+$ONE_DAY) {
  1942. if ( ! is_exception ( $cdate, $ex_days ) )
  1943. $ret[$n++]=$cdate;
  1944. $cdate += $ONE_DAY * $freq;
  1945. }
  1946. } else if ($rpt_type == 'weekly') {
  1947. $daysarray = array();
  1948. $r=0;
  1949. $dow = date("w",$date);
  1950. $cdate = $date - ($dow * $ONE_DAY);
  1951. for ($i = 0; $i < 7; $i++) {
  1952. $isDay = substr($days, $i, 1);
  1953. if (strcmp($isDay,"y")==0) {
  1954. $daysarray[$r++]=$i * $ONE_DAY;
  1955. }
  1956. }
  1957. //we do inclusive counting on end dates.
  1958. while ($cdate <= $realend+$ONE_DAY) {
  1959. //add all of the days of the week.
  1960. for ($j=0; $j<$r;$j++) {
  1961. $td = $cdate + $daysarray[$j];
  1962. if ($td >= $date) {
  1963. if ( ! is_exception ( $td, $ex_days ) )
  1964. $ret[$n++] = $td;
  1965. }
  1966. }
  1967. //skip to the next week in question.
  1968. $cdate += ( $ONE_DAY * 7 ) * $freq;
  1969. }
  1970. } else if ($rpt_type == 'monthlyByDay') {
  1971. $dow = date('w', $date);
  1972. $thismonth = substr($dateYmd, 4, 2);
  1973. $thisyear = substr($dateYmd, 0, 4);
  1974. $week = floor(date("d", $date)/7);
  1975. $thismonth+=$freq;
  1976. //dow1 is the weekday that the 1st of the month falls on
  1977. $dow1 = date('w',mktime (3,0,0,$thismonth,1,$thisyear));
  1978. $t = $dow - $dow1;
  1979. if ($t < 0) $t += 7;
  1980. $day = 7*$week + $t + 1;
  1981. $cdate = mktime (3,0,0,$thismonth,$day,$thisyear);
  1982. while ($cdate <= $realend+$ONE_DAY) {
  1983. if ( ! is_exception ( $cdate, $ex_days ) )
  1984. $ret[$n++] = $cdate;
  1985. $thismonth+=$freq;
  1986. //dow1 is the weekday that the 1st of the month falls on
  1987. $dow1time = mktime ( 3, 0, 0, $thismonth, 1, $thisyear );
  1988. $dow1 = date ( 'w', $dow1time );
  1989. $t = $dow - $dow1;
  1990. if ($t < 0) $t += 7;
  1991. $day = 7*$week + $t + 1;
  1992. $cdate = mktime (3,0,0,$thismonth,$day,$thisyear);
  1993. }
  1994. } else if ($rpt_type == 'monthlyByDayR') {
  1995. // by weekday of month reversed (i.e., last Monday of month)
  1996. $dow = date('w', $date);
  1997. $thisday = substr($dateYmd, 6, 2);
  1998. $thismonth = substr($dateYmd, 4, 2);
  1999. $thisyear = substr($dateYmd, 0, 4);
  2000. // get number of days in this month
  2001. $daysthismonth = $thisyear % 4 == 0 ? $ldays_per_month[$thismonth] :
  2002. $days_per_month[$thismonth];
  2003. // how many weekdays like this one remain in the month?
  2004. // 0=last one, 1=one more after this one, etc.
  2005. $whichWeek = floor ( ( $daysthismonth - $thisday ) / 7 );
  2006. // find first repeat date
  2007. $thismonth += $freq;
  2008. if ( $thismonth > 12 ) {
  2009. $thisyear++;
  2010. $thismonth -= 12;
  2011. }
  2012. // get weekday for last day of month
  2013. $dowLast += date('w',mktime (3,0,0,$thismonth + 1, -1,$thisyear));
  2014. if ( $dowLast >= $dow ) {
  2015. // last weekday is in last week of this month
  2016. $day = $daysthismonth - ( $dowLast - $dow ) -
  2017. ( 7 * $whichWeek );
  2018. } else {
  2019. // last weekday is NOT in last week of this month
  2020. $day = $daysthismonth - ( $dowLast - $dow ) -
  2021. ( 7 * ( $whichWeek + 1 ) );
  2022. }
  2023. $cdate = mktime (3,0,0,$thismonth,$day,$thisyear);
  2024. while ($cdate <= $realend+$ONE_DAY) {
  2025. if ( ! is_exception ( $cdate, $ex_days ) )
  2026. $ret[$n++] = $cdate;
  2027. $thismonth += $freq;
  2028. if ( $thismonth > 12 ) {
  2029. $thisyear++;
  2030. $thismonth -= 12;
  2031. }
  2032. // get weekday for last day of month
  2033. $dowLast += date('w',mktime (3,0,0,$thismonth + 1, -1,$thisyear));
  2034. if ( $dowLast >= $dow ) {
  2035. // last weekday is in last week of this month
  2036. $day = $daysthismonth - ( $dowLast - $dow ) -
  2037. ( 7 * $whichWeek );
  2038. } else {
  2039. // last weekday is NOT in last week of this month
  2040. $day = $daysthismonth - ( $dowLast - $dow ) -
  2041. ( 7 * ( $whichWeek + 1 ) );
  2042. }
  2043. $cdate = mktime (3,0,0,$thismonth,$day,$thisyear);
  2044. }
  2045. } else if ($rpt_type == 'monthlyByDate') {
  2046. $thismonth = substr($dateYmd, 4, 2);
  2047. $thisyear = substr($dateYmd, 0, 4);
  2048. $thisday = substr($dateYmd, 6, 2);
  2049. $hour = date('H',$date);
  2050. $minute = date('i',$date);
  2051. $thismonth += $freq;
  2052. $cdate = mktime (3,0,0,$thismonth,$thisday,$thisyear);
  2053. while ($cdate <= $realend+$ONE_DAY) {
  2054. if ( ! is_exception ( $cdate, $ex_days ) )
  2055. $ret[$n++] = $cdate;
  2056. $thismonth += $freq;
  2057. $cdate = mktime (3,0,0,$thismonth,$thisday,$thisyear);
  2058. }
  2059. } else if ($rpt_type == 'yearly') {
  2060. $thismonth = substr($dateYmd, 4, 2);
  2061. $thisyear = substr($dateYmd, 0, 4);
  2062. $thisday = substr($dateYmd, 6, 2);
  2063. $hour = date('H',$date);
  2064. $minute = date('i',$date);
  2065. $thisyear += $freq;
  2066. $cdate = mktime (3,0,0,$thismonth,$thisday,$thisyear);
  2067. while ($cdate <= $realend+$ONE_DAY) {
  2068. if ( ! is_exception ( $cdate, $ex_days ) )
  2069. $ret[$n++] = $cdate;
  2070. $thisyear += $freq;
  2071. $cdate = mktime (3,0,0,$thismonth,$thisday,$thisyear);
  2072. }
  2073. }
  2074. }
  2075. return $ret;
  2076. }
  2077. /**
  2078. * Gets all the repeating events for the specified date.
  2079. *
  2080. * <b>Note:</b>
  2081. * The global variable <var>$repeated_events</var> needs to be
  2082. * set by calling {@link read_repeated_events()} first.
  2083. *
  2084. * @param string $user Username
  2085. * @param string $date Date to get events for in YYYYMMDD format
  2086. * @param bool $get_unapproved Include unapproved events in results?
  2087. *
  2088. * @return mixed The query result resource on queries (which can then be
  2089. * passed to {@link dbi_fetch_row()} to obtain the results), or
  2090. * true/false on insert or delete queries.
  2091. *
  2092. * @global array Array of repeating events retreived using {@link read_repeated_events()}
  2093. */
  2094. function get_repeating_entries ( $user, $dateYmd, $get_unapproved=true ) {
  2095. global $repeated_events;
  2096. $n = 0;
  2097. $ret = array ();
  2098. //echo count($repeated_events)."<br />\n";
  2099. for ( $i = 0; $i < count ( $repeated_events ); $i++ ) {
  2100. if ( $repeated_events[$i]['cal_status'] == 'A' || $get_unapproved ) {
  2101. if ( repeated_event_matches_date ( $repeated_events[$i], $dateYmd ) ) {
  2102. // make sure this is not an exception date...
  2103. $unixtime = date_to_epoch ( $dateYmd );
  2104. if ( ! is_exception ( $unixtime, $repeated_events[$i]['cal_exceptions'] ) )
  2105. $ret[$n++] = $repeated_events[$i];
  2106. }
  2107. }
  2108. }
  2109. return $ret;
  2110. }
  2111. /**
  2112. * Determines whether the event passed in will fall on the date passed.
  2113. *
  2114. * @param array $event The event as an array
  2115. * @param string $dateYmd Date to check in YYYYMMDD format
  2116. *
  2117. * @return bool Does <var>$event</var> occur on <var>$dateYmd</var>?
  2118. */
  2119. function repeated_event_matches_date($event,$dateYmd) {
  2120. global $days_per_month, $ldays_per_month, $ONE_DAY;
  2121. // only repeat after the beginning, and if there is an end
  2122. // before the end
  2123. $date = date_to_epoch ( $dateYmd );
  2124. $thisyear = substr($dateYmd, 0, 4);
  2125. $start = date_to_epoch ( $event['cal_date'] );
  2126. $end = date_to_epoch ( $event['cal_end'] );
  2127. $freq = $event['cal_frequency'];
  2128. $thismonth = substr($dateYmd, 4, 2);
  2129. if ($event['cal_end'] && $dateYmd > date("Ymd",$end) )
  2130. return false;
  2131. if ( $dateYmd <= date("Ymd",$start) )
  2132. return false;
  2133. $id = $event['cal_id'];
  2134. if ($event['cal_type'] == 'daily') {
  2135. if ( (floor(($date - $start)/$ONE_DAY)%$freq) )
  2136. return false;
  2137. return true;
  2138. } else if ($event['cal_type'] == 'weekly') {
  2139. $dow = date("w", $date);
  2140. $dow1 = date("w", $start);
  2141. $isDay = substr($event['cal_days'], $dow, 1);
  2142. $wstart = $start - ($dow1 * $ONE_DAY);
  2143. if (floor(($date - $wstart)/604800)%$freq)
  2144. return false;
  2145. return (strcmp($isDay,"y") == 0);
  2146. } else if ($event['cal_type'] == 'monthlyByDay') {
  2147. $dowS = date("w", $start);
  2148. $dow = date("w", $date);
  2149. // do this comparison first in hopes of best performance
  2150. if ( $dowS != $dow )
  2151. return false;
  2152. $mthS = date("m", $start);
  2153. $yrS = date("Y", $start);
  2154. $dayS = floor(date("d", $start));
  2155. $dowS1 = ( date ( "w", $start - ( $ONE_DAY * ( $dayS - 1 ) ) ) + 35 ) % 7;
  2156. $days_in_first_weekS = ( 7 - $dowS1 ) % 7;
  2157. $whichWeekS = floor ( ( $dayS - $days_in_first_weekS ) / 7 );
  2158. if ( $dowS >= $dowS1 && $days_in_first_weekS )
  2159. $whichWeekS++;
  2160. //echo "dayS=$dayS;dowS=$dowS;dowS1=$dowS1;wWS=$whichWeekS<br />\n";
  2161. $mth = date("m", $date);
  2162. $yr = date("Y", $date);
  2163. $day = date("d", $date);
  2164. $dow1 = ( date ( "w", $date - ( $ONE_DAY * ( $day - 1 ) ) ) + 35 ) % 7;
  2165. $days_in_first_week = ( 7 - $dow1 ) % 7;
  2166. $whichWeek = floor ( ( $day - $days_in_first_week ) / 7 );
  2167. if ( $dow >= $dow1 && $days_in_first_week )
  2168. $whichWeek++;
  2169. //echo "day=$day;dow=$dow;dow1=$dow1;wW=$whichWeek<br />\n";
  2170. if ((($yr - $yrS)*12 + $mth - $mthS) % $freq)
  2171. return false;
  2172. return ( $whichWeek == $whichWeekS );
  2173. } else if ($event['cal_type'] == 'monthlyByDayR') {
  2174. $dowS = date("w", $start);
  2175. $dow = date("w", $date);
  2176. // do this comparison first in hopes of best performance
  2177. if ( $dowS != $dow )
  2178. return false;
  2179. $dayS = ceil(date("d", $start));
  2180. $mthS = ceil(date("m", $start));
  2181. $yrS = date("Y", $start);
  2182. $daysthismonthS = $mthS % 4 == 0 ? $ldays_per_month[$mthS] :
  2183. $days_per_month[$mthS];
  2184. $whichWeekS = floor ( ( $daysthismonthS - $dayS ) / 7 );
  2185. $day = ceil(date("d", $date));
  2186. $mth = ceil(date("m", $date));
  2187. $yr = date("Y", $date);
  2188. $daysthismonth = $mth % 4 == 0 ? $ldays_per_month[$mth] :
  2189. $days_per_month[$mth];
  2190. $whichWeek = floor ( ( $daysthismonth - $day ) / 7 );
  2191. if ((($yr - $yrS)*12 + $mth - $mthS) % $freq)
  2192. return false;
  2193. return ( $whichWeekS == $whichWeek );
  2194. } else if ($event['cal_type'] == 'monthlyByDate') {
  2195. $mthS = date("m", $start);
  2196. $yrS = date("Y", $start);
  2197. $mth = date("m", $date);
  2198. $yr = date("Y", $date);
  2199. if ((($yr - $yrS)*12 + $mth - $mthS) % $freq)
  2200. return false;
  2201. return (date("d", $date) == date("d", $start));
  2202. }
  2203. else if ($event['cal_type'] == 'yearly') {
  2204. $yrS = date("Y", $start);
  2205. $yr = date("Y", $date);
  2206. if (($yr - $yrS)%$freq)
  2207. return false;
  2208. return (date("dm", $date) == date("dm", $start));
  2209. } else {
  2210. // unknown repeat type
  2211. return false;
  2212. }
  2213. return false;
  2214. }
  2215. /**
  2216. * Converts a date to a timestamp.
  2217. *
  2218. * @param string $d Date in YYYYMMDD format
  2219. *
  2220. * @return int Timestamp representing 3:00 (or 4:00 if during Daylight Saving
  2221. * Time) in the morning on that day
  2222. */
  2223. function date_to_epoch ( $d ) {
  2224. if ( $d == 0 )
  2225. return 0;
  2226. $T = mktime ( 3, 0, 0, substr ( $d, 4, 2 ), substr ( $d, 6, 2 ), substr ( $d, 0, 4 ) );
  2227. $lt = localtime($T);
  2228. if ($lt[8]) {
  2229. return mktime ( 4, 0, 0, substr ( $d, 4, 2 ), substr ( $d, 6, 2 ), substr ( $d, 0, 4 ) );
  2230. } else {
  2231. return $T;
  2232. }
  2233. }
  2234. /**
  2235. * Checks if a date is an exception for an event.
  2236. *
  2237. * @param string $date Date in YYYYMMDD format
  2238. * @param array $exdays Array of dates in YYYYMMDD format
  2239. *
  2240. * @ignore
  2241. */
  2242. function is_exception ( $date, $ex_days ) {
  2243. $size = count ( $ex_days );
  2244. $count = 0;
  2245. $date = date ( "Ymd", $date );
  2246. //echo "Exception $date check.. count is $size <br />\n";
  2247. while ( $count < $size ) {
  2248. //echo "Exception date: $ex_days[$count] <br />\n";
  2249. if ( $date == $ex_days[$count++] )
  2250. return true;
  2251. }
  2252. return false;
  2253. }
  2254. /**
  2255. * Gets the Sunday of the week that the specified date is in.
  2256. *
  2257. * If the date specified is a Sunday, then that date is returned.
  2258. *
  2259. * @param int $year Year
  2260. * @param int $month Month (1-12)
  2261. * @param int $day Day of the month
  2262. *
  2263. * @return int The date (in UNIX timestamp format)
  2264. *
  2265. * @see get_monday_before
  2266. */
  2267. function get_sunday_before ( $year, $month, $day ) {
  2268. $weekday = date ( "w", mktime ( 3, 0, 0, $month, $day, $year ) );
  2269. $newdate = mktime ( 3, 0, 0, $month, $day - $weekday, $year );
  2270. return $newdate;
  2271. }
  2272. /**
  2273. * Gets the Monday of the week that the specified date is in.
  2274. *
  2275. * If the date specified is a Monday, then that date is returned.
  2276. *
  2277. * @param int $year Year
  2278. * @param int $month Month (1-12)
  2279. * @param int $day Day of the month
  2280. *
  2281. * @return int The date (in UNIX timestamp format)
  2282. *
  2283. * @see get_sunday_before
  2284. */
  2285. function get_monday_before ( $year, $month, $day ) {
  2286. $weekday = date ( "w", mktime ( 3, 0, 0, $month, $day, $year ) );
  2287. if ( $weekday == 0 )
  2288. return mktime ( 3, 0, 0, $month, $day - 6, $year );
  2289. if ( $weekday == 1 )
  2290. return mktime ( 3, 0, 0, $month, $day, $year );
  2291. return mktime ( 3, 0, 0, $month, $day - ( $weekday - 1 ), $year );
  2292. }
  2293. /**
  2294. * Returns the week number for specified date.
  2295. *
  2296. * Depends on week numbering settings.
  2297. *
  2298. * @param int $date Date in UNIX timestamp format
  2299. *
  2300. * @return string The week number of the specified date
  2301. */
  2302. function week_number ( $date ) {
  2303. $tmp = getdate($date);
  2304. $iso = gregorianToISO($tmp['mday'], $tmp['mon'], $tmp['year']);
  2305. $parts = explode('-',$iso);
  2306. $week_number = intval($parts[1]);
  2307. return sprintf("%02d",$week_number);
  2308. }
  2309. /**
  2310. * Generates the HTML for an add/edit/delete icon.
  2311. *
  2312. * This function is not yet used. Some of the places that will call it have to
  2313. * be updated to also get the event owner so we know if the current user has
  2314. * access to edit and delete.
  2315. *
  2316. * @param int $id Event ID
  2317. * @param bool $can_edit Can this user edit this event?
  2318. * @param bool $can_delete Can this user delete this event?
  2319. *
  2320. * @return HTML for add/edit/delete icon.
  2321. *
  2322. * @ignore
  2323. */
  2324. function icon_text ( $id, $can_edit, $can_delete ) {
  2325. global $readonly, $is_admin;
  2326. $ret = "<a title=\"" .
  2327. translate("View this entry") . "\" href=\"view_entry.php?id=$id\"><img src=\"view.gif\" alt=\"" .
  2328. translate("View this entry") . "\" style=\"border-width:0px; width:10px; height:10px;\" /></a>";
  2329. if ( $can_edit && $readonly == "N" )
  2330. $ret .= "<a title=\"" .
  2331. translate("Edit entry") . "\" href=\"edit_entry.php?id=$id\"><img src=\"edit.gif\" alt=\"" .
  2332. translate("Edit entry") . "\" style=\"border-width:0px; width:10px; height:10px;\" /></a>";
  2333. if ( $can_delete && ( $readonly == "N" || $is_admin ) )
  2334. $ret .= "<a title=\"" .
  2335. translate("Delete entry") . "\" href=\"del_entry.php?id=$id\" onclick=\"return confirm('" .
  2336. translate("Are you sure you want to delete this entry?") . "\\n\\n" .
  2337. translate("This will delete this entry for all users.") . "');\"><img src=\"delete.gif\" alt=\"" .
  2338. translate("Delete entry") . "\" style=\"border-width:0px; width:10px; height:10px;\" /></a>";
  2339. return $ret;
  2340. }
  2341. /**
  2342. * Prints all the calendar entries for the specified user for the specified date.
  2343. *
  2344. * If we are displaying data from someone other than
  2345. * the logged in user, then check the access permission of the entry.
  2346. *
  2347. * @param string $date Date in YYYYMMDD format
  2348. * @param string $user Username
  2349. * @param bool $ssi Is this being called from week_ssi.php?
  2350. */
  2351. function print_date_entries ( $date, $user, $ssi ) {
  2352. global $events, $readonly, $is_admin, $login,
  2353. $public_access, $public_access_can_add, $cat_id;
  2354. $cnt = 0;
  2355. $get_unapproved = ( $GLOBALS["DISPLAY_UNAPPROVED"] == "Y" );
  2356. // public access events always must be approved before being displayed
  2357. if ( $user == "__public__" )
  2358. $get_unapproved = false;
  2359. $year = substr ( $date, 0, 4 );
  2360. $month = substr ( $date, 4, 2 );
  2361. $day = substr ( $date, 6, 2 );
  2362. $dateu = mktime ( 3, 0, 0, $month, $day, $year );
  2363. //Debug
  2364. logs($log_file,"print_date_entries : ".$login." group :".$GLOBALS['type_param']." \n");
  2365. //Debug
  2366. if($GLOBALS['type_param'] == 'group'){
  2367. $role_user=user_project_role($login,$GLOBALS['group_param']);
  2368. }
  2369. //Debug
  2370. logs($log_file,"print_date_entries : ".$login." group :".$GLOBALS['group_param']." \n");
  2371. //Debug
  2372. $can_add=false;
  2373. if($GLOBALS['type_param'] == 'group' && $role_user >=2 ){
  2374. $can_add = true;
  2375. //debug
  2376. logs($log_file,"edit_entry_handler.php : can_modify \n");
  2377. //debug
  2378. }else{
  2379. if($GLOBALS['type_param'] == 'user'){
  2380. $can_add = true;
  2381. }
  2382. }
  2383. if ($GLOBALS['type_param']=='group'){
  2384. $info_type = "type_param=group&group_param=".$GLOBALS['group_param'];
  2385. }else{
  2386. $info_type = "type_param=user";
  2387. }
  2388. if ( ! $ssi && $can_add ) {
  2389. print "<a title=\"" .
  2390. translate("New Entry") . "\" href=\"edit_entry.php?";
  2391. if ( strcmp ( $user, $GLOBALS["login"] ) ){
  2392. print "user=$user&amp;";
  2393. }
  2394. print $info_type;
  2395. if ( ! empty ( $cat_id ) )
  2396. print "&cat_id=".$cat_id;
  2397. print "&date=$date\"><img src=\"new.gif\" alt=\"" .
  2398. translate("New Entry") . "\" class=\"new\" /></a>";
  2399. $cnt++;
  2400. }
  2401. if ( ! $ssi ) {
  2402. echo "<a class=\"dayofmonth\" href=\"day.php?".$info_type;
  2403. if ( strcmp ( $user, $GLOBALS["login"] ) )
  2404. echo "&user=$user&amp;";
  2405. if ( ! empty ( $cat_id ) )
  2406. echo "&cat_id=$cat_id&amp;";
  2407. echo "&date=$date\">$day</a>";
  2408. if ( $GLOBALS["DISPLAY_WEEKNUMBER"] == "Y" &&
  2409. date ( "w", $dateu ) == $GLOBALS["WEEK_START"] ) {
  2410. echo "&nbsp;<a title=\"" .
  2411. translate("Week") . "&nbsp;" . week_number ( $dateu ) . "\" href=\"week.php?date=".$date."&".$info_type;
  2412. if ( strcmp ( $user, $GLOBALS["login"] ) )
  2413. echo "&amp;user=$user";
  2414. if ( ! empty ( $cat_id ) )
  2415. echo "&amp;cat_id=$cat_id";
  2416. echo "\" class=\"weeknumber\">";
  2417. echo "(" .
  2418. translate("Week") . "&nbsp;" . week_number ( $dateu ) . ")</a>";
  2419. }
  2420. print "<br />\n";
  2421. $cnt++;
  2422. }
  2423. // get all the repeating events for this date and store in array $rep
  2424. $rep = get_repeating_entries ( $user, $date, $get_unapproved );
  2425. $cur_rep = 0;
  2426. // get all the non-repeating events for this date and store in $ev
  2427. $ev = get_entries ( $user, $date, $get_unapproved );
  2428. for ( $i = 0; $i < count ( $ev ); $i++ ) {
  2429. // print out any repeating events that are before this one...
  2430. while ( $cur_rep < count ( $rep ) &&
  2431. $rep[$cur_rep]['cal_time'] < $ev[$i]['cal_time'] ) {
  2432. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  2433. if ( ! empty ( $rep[$cur_rep]['cal_ext_for_id'] ) ) {
  2434. $viewid = $rep[$cur_rep]['cal_ext_for_id'];
  2435. $viewname = $rep[$cur_rep]['cal_name'] . " (" .
  2436. translate("cont.") . ")";
  2437. } else {
  2438. $viewid = $rep[$cur_rep]['cal_id'];
  2439. $viewname = $rep[$cur_rep]['cal_name'];
  2440. }
  2441. print_entry ( $viewid,
  2442. $date, $rep[$cur_rep]['cal_time'], $rep[$cur_rep]['cal_duration'],
  2443. $viewname, $rep[$cur_rep]['cal_description'],
  2444. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  2445. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_login'],
  2446. $rep[$cur_rep]['cal_category'] );
  2447. $cnt++;
  2448. }
  2449. $cur_rep++;
  2450. }
  2451. if ( $get_unapproved || $ev[$i]['cal_status'] == 'A' ) {
  2452. if ( ! empty ( $ev[$i]['cal_ext_for_id'] ) ) {
  2453. $viewid = $ev[$i]['cal_ext_for_id'];
  2454. $viewname = $ev[$i]['cal_name'] . " (" .
  2455. translate("cont.") . ")";
  2456. } else {
  2457. $viewid = $ev[$i]['cal_id'];
  2458. $viewname = $ev[$i]['cal_name'];
  2459. }
  2460. print_entry ( $viewid,
  2461. $date, $ev[$i]['cal_time'], $ev[$i]['cal_duration'],
  2462. $viewname, $ev[$i]['cal_description'],
  2463. $ev[$i]['cal_status'], $ev[$i]['cal_priority'],
  2464. $ev[$i]['cal_access'], $ev[$i]['cal_login'],
  2465. $ev[$i]['cal_category'] );
  2466. $cnt++;
  2467. }
  2468. }
  2469. // print out any remaining repeating events
  2470. while ( $cur_rep < count ( $rep ) ) {
  2471. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  2472. if ( ! empty ( $rep[$cur_rep]['cal_ext_for_id'] ) ) {
  2473. $viewid = $rep[$cur_rep]['cal_ext_for_id'];
  2474. $viewname = $rep[$cur_rep]['cal_name'] . " (" .
  2475. translate("cont.") . ")";
  2476. } else {
  2477. $viewid = $rep[$cur_rep]['cal_id'];
  2478. $viewname = $rep[$cur_rep]['cal_name'];
  2479. }
  2480. print_entry ( $viewid,
  2481. $date, $rep[$cur_rep]['cal_time'], $rep[$cur_rep]['cal_duration'],
  2482. $viewname, $rep[$cur_rep]['cal_description'],
  2483. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  2484. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_login'],
  2485. $rep[$cur_rep]['cal_category'] );
  2486. $cnt++;
  2487. }
  2488. $cur_rep++;
  2489. }
  2490. if ( $cnt == 0 )
  2491. echo "&nbsp;"; // so the table cell has at least something
  2492. }
  2493. /**
  2494. * Checks to see if two events overlap.
  2495. *
  2496. * @param string $time1 Time 1 in HHMMSS format
  2497. * @param int $duration1 Duration 1 in minutes
  2498. * @param string $time2 Time 2 in HHMMSS format
  2499. * @param int $duration2 Duration 2 in minutes
  2500. *
  2501. * @return bool True if the two times overlap, false if they do not
  2502. */
  2503. function times_overlap ( $time1, $duration1, $time2, $duration2 ) {
  2504. //echo "times_overlap ( $time1, $duration1, $time2, $duration2 )<br />\n";
  2505. $hour1 = (int) ( $time1 / 10000 );
  2506. $min1 = ( $time1 / 100 ) % 100;
  2507. $hour2 = (int) ( $time2 / 10000 );
  2508. $min2 = ( $time2 / 100 ) % 100;
  2509. // convert to minutes since midnight
  2510. // remove 1 minute from duration so 9AM-10AM will not conflict with 10AM-11AM
  2511. if ( $duration1 > 0 )
  2512. $duration1 -= 1;
  2513. if ( $duration2 > 0 )
  2514. $duration2 -= 1;
  2515. $tmins1start = $hour1 * 60 + $min1;
  2516. $tmins1end = $tmins1start + $duration1;
  2517. $tmins2start = $hour2 * 60 + $min2;
  2518. $tmins2end = $tmins2start + $duration2;
  2519. //echo "tmins1start=$tmins1start, tmins1end=$tmins1end, tmins2start=$tmins2start, tmins2end=$tmins2end<br />\n";
  2520. if ( ( $tmins1start >= $tmins2end ) || ( $tmins2start >= $tmins1end ) )
  2521. return false;
  2522. return true;
  2523. }
  2524. /**
  2525. * Checks for conflicts.
  2526. *
  2527. * Find overlaps between an array of dates and the other dates in the database.
  2528. *
  2529. * Limits on number of appointments: if enabled in System Settings
  2530. * (<var>$limit_appts</var> global variable), too many appointments can also
  2531. * generate a scheduling conflict.
  2532. *
  2533. * @todo Update this to handle exceptions to repeating events
  2534. *
  2535. * @param array $dates Array of dates in YYYYMMDD format that is
  2536. * checked for overlaps.
  2537. * @param int $duration Event duration in minutes
  2538. * @param int $hour Hour of event (0-23)
  2539. * @param int $minute Minute of the event (0-59)
  2540. * @param array $participants Array of users whose calendars are to be checked
  2541. * @param string $login The current user name
  2542. * @param int $id Current event id (this keeps overlaps from
  2543. * wrongly checking an event against itself)
  2544. *
  2545. * @return Empty string for no conflicts or return the HTML of the
  2546. * conflicts when one or more are found.
  2547. */
  2548. function check_for_conflicts ( $dates, $duration, $hour, $minute,
  2549. $participants, $login, $id ) {
  2550. global $single_user_login, $single_user;
  2551. global $repeated_events, $limit_appts, $limit_appts_number;
  2552. if (!count($dates)) return false;
  2553. $evtcnt = array ();
  2554. $sql = "SELECT distinct webcal_entry_user.cal_login, webcal_entry.cal_time," .
  2555. "webcal_entry.cal_duration, webcal_entry.cal_name, " .
  2556. "webcal_entry.cal_id, webcal_entry.cal_ext_for_id, " .
  2557. "webcal_entry.cal_access, " .
  2558. "webcal_entry_user.cal_status, webcal_entry.cal_date " .
  2559. "FROM webcal_entry, webcal_entry_user " .
  2560. "WHERE webcal_entry.cal_id = webcal_entry_user.cal_id " .
  2561. "AND (";
  2562. for ($x = 0; $x < count($dates); $x++) {
  2563. if ($x != 0) $sql .= " OR ";
  2564. $sql.="webcal_entry.cal_date = " . date ( "Ymd", $dates[$x] );
  2565. }
  2566. $sql .= ") AND webcal_entry.cal_time >= 0 " .
  2567. "AND webcal_entry_user.cal_status IN ('A','W') AND ( ";
  2568. if ( $single_user == "Y" ) {
  2569. $participants[0] = $single_user_login;
  2570. } else if ( strlen ( $participants[0] ) == 0 ) {
  2571. // likely called from a form with 1 user
  2572. $participants[0] = $login;
  2573. }
  2574. for ( $i = 0; $i < count ( $participants ); $i++ ) {
  2575. if ( $i > 0 )
  2576. $sql .= " OR ";
  2577. $sql .= " webcal_entry_user.cal_login = '" . $participants[$i] . "'";
  2578. }
  2579. $sql .= " )";
  2580. // make sure we don't get something past the end date of the
  2581. // event we are saving.
  2582. //echo "SQL: $sql<br />\n";
  2583. $conflicts = "";
  2584. $res = dbi_query ( $sql );
  2585. $found = array();
  2586. $count = 0;
  2587. if ( $res ) {
  2588. $time1 = sprintf ( "%d%02d00", $hour, $minute );
  2589. $duration1 = sprintf ( "%d", $duration );
  2590. while ( $row = dbi_fetch_row ( $res ) ) {
  2591. //Add to an array to see if it has been found already for the next part.
  2592. $found[$count++] = $row[4];
  2593. // see if either event overlaps one another
  2594. if ( $row[4] != $id && ( empty ( $row[5] ) || $row[5] != $id ) ) {
  2595. $time2 = $row[1];
  2596. $duration2 = $row[2];
  2597. $cntkey = $row[0] . "-" . $row[8];
  2598. if ( empty ( $evtcnt[$cntkey] ) )
  2599. $evtcnt[$cntkey] = 0;
  2600. else
  2601. $evtcnt[$cntkey]++;
  2602. $over_limit = 0;
  2603. if ( $limit_appts == "Y" && $limit_appts_number > 0
  2604. && $evtcnt[$cntkey] >= $limit_appts_number ) {
  2605. $over_limit = 1;
  2606. }
  2607. if ( $over_limit ||
  2608. times_overlap ( $time1, $duration1, $time2, $duration2 ) ) {
  2609. $conflicts .= "<li>";
  2610. if ( $single_user != "Y" )
  2611. $conflicts .= "$row[0]: ";
  2612. if ( $row[6] == 'R' && $row[0] != $login )
  2613. $conflicts .= "(" . translate("Private") . ")";
  2614. else {
  2615. $conflicts .= "<a href=\"view_entry.php?id=$row[4]";
  2616. if ( $row[0] != $login )
  2617. $conflicts .= "&amp;user=$row[0]";
  2618. $conflicts .= "\">$row[3]</a>";
  2619. }
  2620. if ( $duration2 == ( 24 * 60 ) ) {
  2621. $conflicts .= " (" . translate("All day event") . ")";
  2622. } else {
  2623. $conflicts .= " (" . display_time ( $time2 );
  2624. if ( $duration2 > 0 )
  2625. $conflicts .= "-" .
  2626. display_time ( add_duration ( $time2, $duration2 ) );
  2627. $conflicts .= ")";
  2628. }
  2629. $conflicts .= " on " . date_to_str( $row[8] );
  2630. if ( $over_limit ) {
  2631. $tmp = translate ( "exceeds limit of XXX events per day" );
  2632. $tmp = str_replace ( "XXX", $limit_appts_number, $tmp );
  2633. $conflicts .= " (" . $tmp . ")";
  2634. }
  2635. $conflicts .= "</li>\n";
  2636. }
  2637. }
  2638. }
  2639. dbi_free_result ( $res );
  2640. } else {
  2641. echo translate("Database error") . ": " . dbi_error (); exit;
  2642. }
  2643. //echo "<br />\nhello";
  2644. for ($q=0;$q<count($participants);$q++) {
  2645. $time1 = sprintf ( "%d%02d00", $hour, $minute );
  2646. $duration1 = sprintf ( "%d", $duration );
  2647. //This date filter is not necessary for functional reasons, but it eliminates some of the
  2648. //events that couldn't possibly match. This could be made much more complex to put more
  2649. //of the searching work onto the database server, or it could be dropped all together to put
  2650. //the searching work onto the client.
  2651. $date_filter = "AND (webcal_entry.cal_date <= " . date("Ymd",$dates[count($dates)-1]);
  2652. $date_filter .= " AND (webcal_entry_repeats.cal_end IS NULL OR webcal_entry_repeats.cal_end >= " . date("Ymd",$dates[0]) . "))";
  2653. //Read repeated events for the participants only once for a participant for
  2654. //for performance reasons.
  2655. $repeated_events=query_events($participants[$q],true,$date_filter);
  2656. //for ($dd=0; $dd<count($repeated_events); $dd++) {
  2657. // echo $repeated_events[$dd]['cal_id'] . "<br />";
  2658. //}
  2659. for ($i=0; $i < count($dates); $i++) {
  2660. $dateYmd = date ( "Ymd", $dates[$i] );
  2661. $list = get_repeating_entries($participants[$q],$dateYmd);
  2662. $thisyear = substr($dateYmd, 0, 4);
  2663. $thismonth = substr($dateYmd, 4, 2);
  2664. for ($j=0; $j < count($list);$j++) {
  2665. //okay we've narrowed it down to a day, now I just gotta check the time...
  2666. //I hope this is right...
  2667. $row = $list[$j];
  2668. if ( $row['cal_id'] != $id && ( empty ( $row['cal_ext_for_id'] ) ||
  2669. $row['cal_ext_for_id'] != $id ) ) {
  2670. $time2 = $row['cal_time'];
  2671. $duration2 = $row['cal_duration'];
  2672. if ( times_overlap ( $time1, $duration1, $time2, $duration2 ) ) {
  2673. $conflicts .= "<li>";
  2674. if ( $single_user != "Y" )
  2675. $conflicts .= $row['cal_login'] . ": ";
  2676. if ( $row['cal_access'] == 'R' && $row['cal_login'] != $login )
  2677. $conflicts .= "(" . translate("Private") . ")";
  2678. else {
  2679. $conflicts .= "<a href=\"view_entry.php?id=" . $row['cal_id'];
  2680. if ( ! empty ( $user ) && $user != $login )
  2681. $conflicts .= "&amp;user=$user";
  2682. $conflicts .= "\">" . $row['cal_name'] . "</a>";
  2683. }
  2684. $conflicts .= " (" . display_time ( $time2 );
  2685. if ( $duration2 > 0 )
  2686. $conflicts .= "-" .
  2687. display_time ( add_duration ( $time2, $duration2 ) );
  2688. $conflicts .= ")";
  2689. $conflicts .= " on " . date("l, F j, Y", $dates[$i]);
  2690. $conflicts .= "</li>\n";
  2691. }
  2692. }
  2693. }
  2694. }
  2695. }
  2696. return $conflicts;
  2697. }
  2698. /**
  2699. * Converts a time format HHMMSS (like 130000 for 1PM) into number of minutes past midnight.
  2700. *
  2701. * @param string $time Input time in HHMMSS format
  2702. *
  2703. * @return int The number of minutes since midnight
  2704. */
  2705. function time_to_minutes ( $time ) {
  2706. $h = (int) ( $time / 10000 );
  2707. $m = (int) ( $time / 100 ) % 100;
  2708. $num = $h * 60 + $m;
  2709. return $num;
  2710. }
  2711. /**
  2712. * Calculates which row/slot this time represents.
  2713. *
  2714. * This is used in day and week views where hours of the time are separeted
  2715. * into different cells in a table.
  2716. *
  2717. * <b>Note:</b> the global variable <var>$TIME_SLOTS</var> is used to determine
  2718. * how many time slots there are and how many minutes each is. This variable
  2719. * is defined user preferences (or defaulted to admin system settings).
  2720. *
  2721. * @param string $time Input time in HHMMSS format
  2722. * @param bool $round_down Should we change 1100 to 1059?
  2723. * (This will make sure a 10AM-100AM appointment just
  2724. * shows up in the 10AM slow and not in the 11AM slot
  2725. * also.)
  2726. *
  2727. * @return int The time slot index
  2728. */
  2729. function calc_time_slot ( $time, $round_down = false ) {
  2730. global $TIME_SLOTS, $TZ_OFFSET;
  2731. $interval = ( 24 * 60 ) / $TIME_SLOTS;
  2732. $mins_since_midnight = time_to_minutes ( $time );
  2733. $ret = (int) ( $mins_since_midnight / $interval );
  2734. if ( $round_down ) {
  2735. if ( $ret * $interval == $mins_since_midnight )
  2736. $ret--;
  2737. }
  2738. //echo "$mins_since_midnight / $interval = $ret <br />\n";
  2739. if ( $ret > $TIME_SLOTS )
  2740. $ret = $TIME_SLOTS;
  2741. //echo "<br />\ncalc_time_slot($time) = $ret <br />\nTIME_SLOTS = $TIME_SLOTS<br />\n";
  2742. return $ret;
  2743. }
  2744. /**
  2745. * Generates the HTML for an icon to add a new event.
  2746. *
  2747. * @param string $date Date for new event in YYYYMMDD format
  2748. * @param int $hour Hour of day (0-23)
  2749. * @param int $minute Minute of the hour (0-59)
  2750. * @param string $user Participant to initially select for new event
  2751. *
  2752. * @return string The HTML for the add event icon
  2753. */
  2754. function html_for_add_icon ( $date=0,$hour="", $minute="", $user="" ) {
  2755. //Debug
  2756. logs($log_file,"####### functions.php #######\n");
  2757. logs($log_file,"------- html_for_add_icon -------\n");
  2758. //Debug
  2759. global $TZ_OFFSET;
  2760. global $login, $readonly, $cat_id;
  2761. $u_url = '';
  2762. if(isset($GLOBALS['type_param']) && $GLOBALS['type_param']=='group'){
  2763. $u_url = "type_param=group&amp;group_param=".$GLOBALS['group_param']."&amp;";
  2764. }else{
  2765. if ( ! empty ( $user ) && $user != $login )
  2766. $u_url = "user=$user&amp;";
  2767. $u_url .= "type_param=user&";
  2768. }
  2769. //Debug
  2770. logs($log_file,"u_url : ".$u_url."\n");
  2771. //Debug
  2772. if ( $readonly == 'Y' )
  2773. return '';
  2774. if ( $minute < 0 ) {
  2775. $minute = abs($minute);
  2776. $hour = $hour -1;
  2777. }
  2778. if ( isset ( $hour ) && $hour != NULL )
  2779. $hour += $TZ_OFFSET;
  2780. return "<a title=\"" .
  2781. translate("New Entry") . "\" href=\"edit_entry.php?" . $u_url .
  2782. "date=$date" . ( isset ( $hour ) && $hour != NULL && $hour >= 0 ? "&amp;hour=$hour" : "" ) .
  2783. ( $minute > 0 ? "&amp;minute=$minute" : "" ) .
  2784. ( empty ( $user ) ? "" : "&amp;defusers=$user" ) .
  2785. ( empty ( $cat_id ) ? "" : "&amp;cat_id=$cat_id" ) .
  2786. "\"><img src=\"new.gif\" class=\"new\" alt=\"" .
  2787. translate("New Entry") . "\" /></a>\n";
  2788. }
  2789. /**
  2790. * Generates the HTML for an event to be viewed in the week-at-glance (week.php).
  2791. *
  2792. * The HTML will be stored in an array (global variable $hour_arr)
  2793. * indexed on the event's starting hour.
  2794. *
  2795. * @param int $id Event id
  2796. * @param string $date Date of event in YYYYMMDD format
  2797. * @param string $time Time of event in HHMM format
  2798. * @param string $name Brief description of event
  2799. * @param string $description Full description of event
  2800. * @param string $status Status of event ('A', 'W')
  2801. * @param int $pri Priority of event
  2802. * @param string $access Access to event by others ('P', 'R')
  2803. * @param int $duration Duration of event in minutes
  2804. * @param string $event_owner User who created event
  2805. * @param int $event_category Category id for event
  2806. */
  2807. function html_for_event_week_at_a_glance ( $id, $date, $time,
  2808. $name, $description, $status, $pri, $access, $duration, $event_owner,
  2809. $event_category=-1 ) {
  2810. global $first_slot, $last_slot, $hour_arr, $rowspan_arr, $rowspan,
  2811. $eventinfo, $login, $user;
  2812. static $key = 0;
  2813. global $DISPLAY_ICONS, $PHP_SELF, $TIME_SLOTS;
  2814. global $layers;
  2815. $popupid = "eventinfo-day-$id-$key";
  2816. $key++;
  2817. // Figure out which time slot it goes in.
  2818. if ( $time >= 0 && $duration != ( 24 * 60 ) ) {
  2819. $ind = calc_time_slot ( $time );
  2820. if ( $ind < $first_slot )
  2821. $first_slot = $ind;
  2822. if ( $ind > $last_slot )
  2823. $last_slot = $ind;
  2824. } else
  2825. $ind = 9999;
  2826. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  2827. $class = "layerentry";
  2828. } else {
  2829. $class = "entry";
  2830. if ( $status == "W" ) $class = "unapprovedentry";
  2831. }
  2832. // if we are looking at a view, then always use "entry"
  2833. if ( strstr ( $PHP_SELF, "view_m.php" ) ||
  2834. strstr ( $PHP_SELF, "view_w.php" ) ||
  2835. strstr ( $PHP_SELF, "view_v.php" ) ||
  2836. strstr ( $PHP_SELF, "view_t.php" ) )
  2837. $class = "entry";
  2838. // avoid php warning for undefined array index
  2839. if ( empty ( $hour_arr[$ind] ) )
  2840. $hour_arr[$ind] = "";
  2841. $catIcon = "icons/cat-" . $event_category . ".gif";
  2842. if ( $event_category > 0 && file_exists ( $catIcon ) ) {
  2843. $hour_arr[$ind] .= "<img src=\"$catIcon\" alt=\"$catIcon\" />";
  2844. }
  2845. if($GLOBALS['type_param']=='group'){
  2846. $info_type="&type_param=group&group_param=".$GLOBALS['group_param'];
  2847. }else{
  2848. $info_type="&type_param=user";
  2849. }
  2850. $hour_arr[$ind] .= "<a title=\"" .
  2851. translate("View this entry") . "\" class=\"$class\" href=\"view_entry.php?id=$id&amp;date=$date".$info_type;
  2852. if ( strlen ( $GLOBALS["user"] ) > 0 )
  2853. $hour_arr[$ind] .= "&amp;user=" . $GLOBALS["user"];
  2854. $hour_arr[$ind] .= "\" onmouseover=\"window.status='" .
  2855. translate("View this entry") . "'; show(event, '$popupid'); return true;\" onmouseout=\"hide('$popupid'); return true;\">";
  2856. if ( $pri == 3 )
  2857. $hour_arr[$ind] .= "<strong>";
  2858. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  2859. if ($layers) foreach ($layers as $layer) {
  2860. if ( $layer['cal_layeruser'] == $event_owner ) {
  2861. $in_span = true;
  2862. $hour_arr[$ind] .= "<span style=\"color:" . $layer['cal_color'] . ";\">";
  2863. }
  2864. }
  2865. }
  2866. if ( $duration == ( 24 * 60 ) ) {
  2867. $timestr = translate("All day event");
  2868. } else if ( $time >= 0 ) {
  2869. $hour_arr[$ind] .= display_time ( $time ) . "&raquo;&nbsp;";
  2870. $timestr = display_time ( $time );
  2871. if ( $duration > 0 ) {
  2872. // calc end time
  2873. $h = (int) ( $time / 10000 );
  2874. $m = ( $time / 100 ) % 100;
  2875. $m += $duration;
  2876. $d = $duration;
  2877. while ( $m >= 60 ) {
  2878. $h++;
  2879. $m -= 60;
  2880. }
  2881. $end_time = sprintf ( "%02d%02d00", $h, $m );
  2882. $timestr .= "-" . display_time ( $end_time );
  2883. } else {
  2884. $end_time = 0;
  2885. }
  2886. if ( empty ( $rowspan_arr[$ind] ) )
  2887. $rowspan_arr[$ind] = 0; // avoid warning below
  2888. // which slot is end time in? take one off so we don't
  2889. // show 11:00-12:00 as taking up both 11 and 12 slots.
  2890. $endind = calc_time_slot ( $end_time, true );
  2891. if ( $endind == $ind )
  2892. $rowspan = 0;
  2893. else
  2894. $rowspan = $endind - $ind + 1;
  2895. if ( $rowspan > $rowspan_arr[$ind] && $rowspan > 1 )
  2896. $rowspan_arr[$ind] = $rowspan;
  2897. } else {
  2898. $timestr = "";
  2899. }
  2900. // avoid php warning of undefined index when using .= below
  2901. if ( empty ( $hour_arr[$ind] ) )
  2902. $hour_arr[$ind] = "";
  2903. if ( $login != $user && $access == 'R' && strlen ( $user ) ) {
  2904. $hour_arr[$ind] .= "(" . translate("Private") . ")";
  2905. } else if ( $login != $event_owner && $access == 'R' &&
  2906. strlen ( $event_owner ) ) {
  2907. $hour_arr[$ind] .= "(" . translate("Private") . ")";
  2908. } else if ( $login != $event_owner && strlen ( $event_owner ) ) {
  2909. $hour_arr[$ind] .= htmlspecialchars ( $name );
  2910. if ( ! empty ( $in_span ) )
  2911. $hour_arr[$ind] .= "</span>"; //end color span
  2912. } else {
  2913. $hour_arr[$ind] .= htmlspecialchars ( $name );
  2914. }
  2915. if ( $pri == 3 ) $hour_arr[$ind] .= "</strong>"; //end font-weight span
  2916. $hour_arr[$ind] .= "</a>";
  2917. //if ( $DISPLAY_ICONS == "Y" ) {
  2918. // $hour_arr[$ind] .= icon_text ( $id, true, true );
  2919. //}
  2920. $hour_arr[$ind] .= "<br />\n";
  2921. if ( $login != $user && $access == 'R' && strlen ( $user ) ) {
  2922. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  2923. translate("This event is confidential"), "" );
  2924. } else if ( $login != $event_owner && $access == 'R' &&
  2925. strlen ( $event_owner ) ) {
  2926. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  2927. translate("This event is confidential"), "" );
  2928. } else {
  2929. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  2930. $description, $timestr, site_extras_for_popup ( $id ) );
  2931. }
  2932. }
  2933. /**
  2934. * Generates the HTML for an event to be viewed in the day-at-glance (day.php).
  2935. *
  2936. * The HTML will be stored in an array (global variable $hour_arr)
  2937. * indexed on the event's starting hour.
  2938. *
  2939. * @param int $id Event id
  2940. * @param string $date Date of event in YYYYMMDD format
  2941. * @param string $time Time of event in HHMM format
  2942. * @param string $name Brief description of event
  2943. * @param string $description Full description of event
  2944. * @param string $status Status of event ('A', 'W')
  2945. * @param int $pri Priority of event
  2946. * @param string $access Access to event by others ('P', 'R')
  2947. * @param int $duration Duration of event in minutes
  2948. * @param string $event_owner User who created event
  2949. * @param int $event_category Category id for event
  2950. */
  2951. function html_for_event_day_at_a_glance ( $id, $date, $time,
  2952. $name, $description, $status, $pri, $access, $duration, $event_owner,
  2953. $event_category=-1 ) {
  2954. //debug
  2955. logs($log_file,"####### functions.php ######\n");
  2956. logs($log_file,"------- html_for_event_day_at_a_glance -------\n");
  2957. logs($log_file,"type : ".$GLOBALS['type_param']."\n");
  2958. //debug
  2959. global $first_slot, $last_slot, $hour_arr, $rowspan_arr, $rowspan,
  2960. $eventinfo, $login, $user;
  2961. static $key = 0;
  2962. global $layers, $PHP_SELF, $TIME_SLOTS, $TZ_OFFSET;
  2963. $popupid = "eventinfo-day-$id-$key";
  2964. $key++;
  2965. if ( $login != $user && $access == 'R' && strlen ( $user ) )
  2966. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  2967. translate("This event is confidential"), "" );
  2968. else if ( $login != $event_owner && $access == 'R' &&
  2969. strlen ( $event_owner ) )
  2970. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  2971. translate("This event is confidential"), "" );
  2972. else
  2973. $eventinfo .= build_event_popup ( $popupid, $event_owner, $description,
  2974. "", site_extras_for_popup ( $id ) );
  2975. // calculate slot length in minutes
  2976. $interval = ( 60 * 24 ) / $TIME_SLOTS;
  2977. // If TZ_OFFSET make this event before the start of the day or
  2978. // after the end of the day, adjust the time slot accordingly.
  2979. if ( $time >= 0 && $duration != ( 24 * 60 ) ) {
  2980. if ( $time + ( $TZ_OFFSET * 10000 ) > 240000 )
  2981. $time -= 240000;
  2982. else if ( $time + ( $TZ_OFFSET * 10000 ) < 0 )
  2983. $time += 240000;
  2984. $ind = calc_time_slot ( $time );
  2985. if ( $ind < $first_slot )
  2986. $first_slot = $ind;
  2987. if ( $ind > $last_slot )
  2988. $last_slot = $ind;
  2989. } else
  2990. $ind = 9999;
  2991. //echo "time = $time <br />\nind = $ind <br />\nfirst_slot = $first_slot<br />\n";
  2992. if ( empty ( $hour_arr[$ind] ) )
  2993. $hour_arr[$ind] = "";
  2994. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  2995. $class = "layerentry";
  2996. } else {
  2997. $class = "entry";
  2998. if ( $status == "W" )
  2999. $class = "unapprovedentry";
  3000. }
  3001. // if we are looking at a view, then always use "entry"
  3002. if ( strstr ( $PHP_SELF, "view_m.php" ) ||
  3003. strstr ( $PHP_SELF, "view_w.php" ) ||
  3004. strstr ( $PHP_SELF, "view_v.php" ) ||
  3005. strstr ( $PHP_SELF, "view_t.php" ) )
  3006. $class = "entry";
  3007. $catIcon = "icons/cat-" . $event_category . ".gif";
  3008. if ( $event_category > 0 && file_exists ( $catIcon ) ) {
  3009. $hour_arr[$ind] .= "<img src=\"$catIcon\" alt=\"$catIcon\" />";
  3010. }
  3011. $hour_arr[$ind] .= "<a title=\"" .
  3012. translate("View this entry") . "\" class=\"$class\" href=\"view_entry.php?id=$id&amp;date=$date"."&type_param=".($GLOBALS['type_param']=='group'?"group&group_param=".$GLOBALS['group_param']:"user");
  3013. if ( strlen ( $GLOBALS["user"] ) > 0 )
  3014. $hour_arr[$ind] .= "&amp;user=" . $GLOBALS["user"];
  3015. $hour_arr[$ind] .= "\" onmouseover=\"window.status='" .
  3016. translate("View this entry") . "'; show(event, '$popupid'); return true;\" onmouseout=\"hide('$popupid'); return true;\">";
  3017. if ( $pri == 3 ) $hour_arr[$ind] .= "<strong>";
  3018. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  3019. if ($layers) foreach ($layers as $layer) {
  3020. if ( $layer['cal_layeruser'] == $event_owner) {
  3021. $in_span = true;
  3022. $hour_arr[$ind] .= "<span style=\"color:" . $layer['cal_color'] . ";\">";
  3023. }
  3024. }
  3025. }
  3026. if ( $duration == ( 24 * 60 ) ) {
  3027. $hour_arr[$ind] .= "[" . translate("All day event") . "] ";
  3028. } else if ( $time >= 0 ) {
  3029. $hour_arr[$ind] .= "[" . display_time ( $time );
  3030. if ( $duration > 0 ) {
  3031. // calc end time
  3032. $h = (int) ( $time / 10000 );
  3033. $m = ( $time / 100 ) % 100;
  3034. $m += $duration;
  3035. $d = $duration;
  3036. while ( $m >= 60 ) {
  3037. $h++;
  3038. $m -= 60;
  3039. }
  3040. $end_time = sprintf ( "%02d%02d00", $h, $m );
  3041. $hour_arr[$ind] .= "-" . display_time ( $end_time );
  3042. // which slot is end time in? take one off so we don't
  3043. // show 11:00-12:00 as taking up both 11 and 12 slots.
  3044. $endind = calc_time_slot ( $end_time, true );
  3045. if ( $endind == $ind )
  3046. $rowspan = 0;
  3047. else
  3048. $rowspan = $endind - $ind + 1;
  3049. if ( ! isset ( $rowspan_arr[$ind] ) )
  3050. $rowspan_arr[$ind] = 0;
  3051. if ( $rowspan > $rowspan_arr[$ind] && $rowspan > 1 )
  3052. $rowspan_arr[$ind] = $rowspan;
  3053. }
  3054. $hour_arr[$ind] .= "] ";
  3055. }
  3056. if ( $login != $user && $access == 'R' && strlen ( $user ) )
  3057. $hour_arr[$ind] .= "(" . translate("Private") . ")";
  3058. else
  3059. if ( $login != $event_owner && $access == 'R' && strlen ( $event_owner ) )
  3060. $hour_arr[$ind] .= "(" . translate("Private") . ")";
  3061. else
  3062. if ( $login != $event_owner && strlen ( $event_owner ) )
  3063. {
  3064. $hour_arr[$ind] .= htmlspecialchars ( $name );
  3065. if ( ! empty ( $in_span ) )
  3066. $hour_arr[$ind] .= "</span>"; //end color span
  3067. }
  3068. else
  3069. $hour_arr[$ind] .= htmlspecialchars ( $name );
  3070. if ( $pri == 3 ) $hour_arr[$ind] .= "</strong>"; //end font-weight span
  3071. $hour_arr[$ind] .= "</a>";
  3072. if ( $GLOBALS["DISPLAY_DESC_PRINT_DAY"] == "Y" ) {
  3073. $hour_arr[$ind] .= "\n<dl class=\"desc\">\n";
  3074. $hour_arr[$ind] .= "<dt>" . translate("Description") . ":</dt>\n<dd>";
  3075. if ( ! empty ( $GLOBALS['allow_html_description'] ) &&
  3076. $GLOBALS['allow_html_description'] == 'Y' ) {
  3077. $str = str_replace ( "&", "&amp;", $description );
  3078. $str = str_replace ( "&amp;amp;", "&amp;", $str );
  3079. // If there is no html found, then go ahead and replace
  3080. // the line breaks ("\n") with the html break.
  3081. if ( strstr ( $str, "<" ) && strstr ( $str, ">" ) ) {
  3082. // found some html...
  3083. $hour_arr[$ind] .= $str;
  3084. } else {
  3085. // no html, replace line breaks
  3086. $hour_arr[$ind] .= nl2br ( $str );
  3087. }
  3088. } else {
  3089. // html not allowed in description, escape everything
  3090. $hour_arr[$ind] .= nl2br ( htmlspecialchars ( $description ) );
  3091. }
  3092. $hour_arr[$ind] .= "</dd>\n</dl>\n";
  3093. }
  3094. $hour_arr[$ind] .= "<br />\n";
  3095. //debug
  3096. logs($log_file,"------- html_for_event_day_at_a_glance -------\n");
  3097. //debug
  3098. }
  3099. /**
  3100. * Prints all the calendar entries for the specified user for the specified date in day-at-a-glance format.
  3101. *
  3102. * If we are displaying data from someone other than
  3103. * the logged in user, then check the access permission of the entry.
  3104. *
  3105. * @param string $date Date in YYYYMMDD format
  3106. * @param string $user Username of calendar
  3107. */
  3108. function print_day_at_a_glance ( $date, $user, $can_add=0 ) {
  3109. //debug
  3110. logs($log_file,"####### functions.php ######\n");
  3111. logs($log_file,"------- print_day_at_a_glance -------\n");
  3112. logs($log_file,"type : ".$GLOBALS['type_param']."\n");
  3113. //debug
  3114. global $first_slot, $last_slot, $hour_arr, $rowspan_arr, $rowspan;
  3115. global $TABLEBG, $CELLBG, $TODAYCELLBG, $THFG, $THBG, $TIME_SLOTS, $TZ_OFFSET;
  3116. global $WORK_DAY_START_HOUR, $WORK_DAY_END_HOUR;
  3117. global $repeated_events;
  3118. $get_unapproved = ( $GLOBALS["DISPLAY_UNAPPROVED"] == "Y" );
  3119. if ( $user == "__public__" )
  3120. $get_unapproved = false;
  3121. if ( empty ( $TIME_SLOTS ) ) {
  3122. echo "Error: TIME_SLOTS undefined!<br />\n";
  3123. return;
  3124. }
  3125. // $interval is number of minutes per slot
  3126. $interval = ( 24 * 60 ) / $TIME_SLOTS;
  3127. $rowspan_arr = array ();
  3128. for ( $i = 0; $i < $TIME_SLOTS; $i++ ) {
  3129. $rowspan_arr[$i] = 0;
  3130. }
  3131. // get all the repeating events for this date and store in array $rep
  3132. $rep = get_repeating_entries ( $user, $date );
  3133. $cur_rep = 0;
  3134. // Get static non-repeating events
  3135. $ev = get_entries ( $user, $date, $get_unapproved );
  3136. $hour_arr = array ();
  3137. $interval = ( 24 * 60 ) / $TIME_SLOTS;
  3138. $first_slot = (int) ( ( ( $WORK_DAY_START_HOUR - $TZ_OFFSET ) * 60 ) / $interval );
  3139. $last_slot = (int) ( ( ( $WORK_DAY_END_HOUR - $TZ_OFFSET ) * 60 ) / $interval);
  3140. //echo "first_slot = $first_slot<br />\nlast_slot = $last_slot<br />\ninterval = $interval<br />\nTIME_SLOTS = $TIME_SLOTS<br />\n";
  3141. $rowspan_arr = array ();
  3142. $all_day = 0;
  3143. for ( $i = 0; $i < count ( $ev ); $i++ ) {
  3144. // print out any repeating events that are before this one...
  3145. while ( $cur_rep < count ( $rep ) &&
  3146. $rep[$cur_rep]['cal_time'] < $ev[$i]['cal_time'] ) {
  3147. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  3148. if ( ! empty ( $rep[$cur_rep]['cal_ext_for_id'] ) ) {
  3149. $viewid = $rep[$cur_rep]['cal_ext_for_id'];
  3150. $viewname = $rep[$cur_rep]['cal_name'] . " (" .
  3151. translate("cont.") . ")";
  3152. } else {
  3153. $viewid = $rep[$cur_rep]['cal_id'];
  3154. $viewname = $rep[$cur_rep]['cal_name'];
  3155. }
  3156. if ( $rep[$cur_rep]['cal_duration'] == ( 24 * 60 ) )
  3157. $all_day = 1;
  3158. html_for_event_day_at_a_glance ( $viewid,
  3159. $date, $rep[$cur_rep]['cal_time'],
  3160. $viewname, $rep[$cur_rep]['cal_description'],
  3161. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  3162. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_duration'],
  3163. $rep[$cur_rep]['cal_login'], $rep[$cur_rep]['cal_category'] );
  3164. }
  3165. $cur_rep++;
  3166. }
  3167. if ( $get_unapproved || $ev[$i]['cal_status'] == 'A' ) {
  3168. if ( ! empty ( $ev[$i]['cal_ext_for_id'] ) ) {
  3169. $viewid = $ev[$i]['cal_ext_for_id'];
  3170. $viewname = $ev[$i]['cal_name'] . " (" .
  3171. translate("cont.") . ")";
  3172. } else {
  3173. $viewid = $ev[$i]['cal_id'];
  3174. $viewname = $ev[$i]['cal_name'];
  3175. }
  3176. if ( $ev[$i]['cal_duration'] == ( 24 * 60 ) )
  3177. $all_day = 1;
  3178. html_for_event_day_at_a_glance ( $viewid,
  3179. $date, $ev[$i]['cal_time'],
  3180. $viewname, $ev[$i]['cal_description'],
  3181. $ev[$i]['cal_status'], $ev[$i]['cal_priority'],
  3182. $ev[$i]['cal_access'], $ev[$i]['cal_duration'],
  3183. $ev[$i]['cal_login'], $ev[$i]['cal_category'] );
  3184. }
  3185. }
  3186. // print out any remaining repeating events
  3187. while ( $cur_rep < count ( $rep ) ) {
  3188. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  3189. if ( ! empty ( $rep[$cur_rep]['cal_ext_for_id'] ) ) {
  3190. $viewid = $rep[$cur_rep]['cal_ext_for_id'];
  3191. $viewname = $rep[$cur_rep]['cal_name'] . " (" .
  3192. translate("cont.") . ")";
  3193. } else {
  3194. $viewid = $rep[$cur_rep]['cal_id'];
  3195. $viewname = $rep[$cur_rep]['cal_name'];
  3196. }
  3197. if ( $rep[$cur_rep]['cal_duration'] == ( 24 * 60 ) )
  3198. $all_day = 1;
  3199. html_for_event_day_at_a_glance ( $viewid,
  3200. $date, $rep[$cur_rep]['cal_time'],
  3201. $viewname, $rep[$cur_rep]['cal_description'],
  3202. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  3203. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_duration'],
  3204. $rep[$cur_rep]['cal_login'], $rep[$cur_rep]['cal_category'] );
  3205. }
  3206. $cur_rep++;
  3207. }
  3208. // squish events that use the same cell into the same cell.
  3209. // For example, an event from 8:00-9:15 and another from 9:30-9:45 both
  3210. // want to show up in the 8:00-9:59 cell.
  3211. $rowspan = 0;
  3212. $last_row = -1;
  3213. //echo "First SLot: $first_slot; Last Slot: $last_slot<br />\n";
  3214. $i = 0;
  3215. if ( $first_slot < 0 )
  3216. $i = $first_slot;
  3217. for ( ; $i < $TIME_SLOTS; $i++ ) {
  3218. if ( $rowspan > 1 ) {
  3219. if ( ! empty ( $hour_arr[$i] ) ) {
  3220. $diff_start_time = $i - $last_row;
  3221. if ( $rowspan_arr[$i] > 1 ) {
  3222. if ( $rowspan_arr[$i] + ( $diff_start_time ) > $rowspan_arr[$last_row] ) {
  3223. $rowspan_arr[$last_row] = ( $rowspan_arr[$i] + ( $diff_start_time ) );
  3224. }
  3225. $rowspan += ( $rowspan_arr[$i] - 1 );
  3226. } else {
  3227. $rowspan_arr[$last_row] += $rowspan_arr[$i];
  3228. }
  3229. // this will move entries apart that appear in one field,
  3230. // yet start on different hours
  3231. for ( $u = $diff_start_time ; $u > 0 ; $u-- ) {
  3232. $hour_arr[$last_row] .= "<br />\n";
  3233. }
  3234. $hour_arr[$last_row] .= $hour_arr[$i];
  3235. $hour_arr[$i] = "";
  3236. $rowspan_arr[$i] = 0;
  3237. }
  3238. $rowspan--;
  3239. } else if ( ! empty ( $rowspan_arr[$i] ) && $rowspan_arr[$i] > 1 ) {
  3240. $rowspan = $rowspan_arr[$i];
  3241. $last_row = $i;
  3242. }
  3243. }
  3244. if ( ! empty ( $hour_arr[9999] ) ) {
  3245. echo "<tr><th class=\"empty\">&nbsp;</th>\n" .
  3246. "<td class=\"hasevents\">$hour_arr[9999]</td></tr>\n";
  3247. }
  3248. $rowspan = 0;
  3249. //echo "first_slot = $first_slot<br />\nlast_slot = $last_slot<br />\ninterval = $interval<br />\n";
  3250. for ( $i = $first_slot; $i <= $last_slot; $i++ ) {
  3251. $time_h = (int) ( ( $i * $interval ) / 60 );
  3252. $time_m = ( $i * $interval ) % 60;
  3253. $time = display_time ( ( $time_h * 100 + $time_m ) * 100 );
  3254. echo "<tr>\n<th class=\"row\">" . $time . "</th>\n";
  3255. if ( $rowspan > 1 ) {
  3256. // this might mean there's an overlap, or it could mean one event
  3257. // ends at 11:15 and another starts at 11:30.
  3258. if ( ! empty ( $hour_arr[$i] ) ) {
  3259. echo "<td class=\"hasevents\">";
  3260. if ( $can_add )
  3261. echo html_for_add_icon ( $date, $time_h, $time_m, $user );
  3262. echo "$hour_arr[$i]</td>\n";
  3263. }
  3264. $rowspan--;
  3265. } else {
  3266. if ( empty ( $hour_arr[$i] ) ) {
  3267. echo "<td>";
  3268. if ( $can_add ) {
  3269. echo html_for_add_icon ( $date, $time_h, $time_m, $user ) . "</td>";
  3270. } else {
  3271. echo "&nbsp;</td>";
  3272. }
  3273. echo "</tr>\n";
  3274. } else {
  3275. if ( empty ( $rowspan_arr[$i] ) )
  3276. $rowspan = '';
  3277. else
  3278. $rowspan = $rowspan_arr[$i];
  3279. if ( $rowspan > 1 ) {
  3280. echo "<td rowspan=\"$rowspan\" class=\"hasevents\">";
  3281. if ( $can_add )
  3282. echo html_for_add_icon ( $date, $time_h, $time_m, $user );
  3283. echo "$hour_arr[$i]</td></tr>\n";
  3284. } else {
  3285. echo "<td class=\"hasevents\">";
  3286. if ( $can_add )
  3287. echo html_for_add_icon ( $date, $time_h, $time_m, $user );
  3288. echo "$hour_arr[$i]</td></tr>\n";
  3289. }
  3290. }
  3291. }
  3292. }
  3293. }
  3294. /**
  3295. * Checks for any unnaproved events.
  3296. *
  3297. * If any are found, display a link to the unapproved events (where they can be
  3298. * approved).
  3299. *
  3300. * If the user is an admin user, also count up any public events.
  3301. * If the user is a nonuser admin, count up events on the nonuser calendar.
  3302. *
  3303. * @param string $user Current user login
  3304. */
  3305. function display_unapproved_events ( $user , $info_type = "type_param=user") {
  3306. global $public_access, $is_admin, $nonuser_enabled, $login;
  3307. // Don't do this for public access login, admin user must approve public
  3308. // events
  3309. if ( $user == "__public__" )
  3310. return;
  3311. $sql = "SELECT COUNT(eu1.cal_id) " .
  3312. "FROM webcal_entry_user eu1, webcal_entry e " .
  3313. "WHERE eu1.cal_id = e.cal_id " .
  3314. "AND eu1.cal_status = 'W' " .
  3315. "AND (eu1.cal_group_status NOT LIKE ('%,A:".$user.",%') ".
  3316. "OR eu1.cal_group_status is null) ".
  3317. "AND (eu1.cal_group_status NOT LIKE ('%,R:".$user.",%') ".
  3318. "OR eu1.cal_group_status is null) ".
  3319. "AND ( eu1.cal_login = '".$user."'";
  3320. if ( $public_access == "Y" && $is_admin ) {
  3321. $sql .= " OR eu1.cal_login = '__public__'";
  3322. }
  3323. if ( $nonuser_enabled == 'Y' ) {
  3324. $admincals = get_nonuser_cals ( $login );
  3325. for ( $i = 0; $i < count ( $admincals ); $i++ ) {
  3326. $sql .= " OR eu1.cal_login = '" . $admincals[$i]['cal_login'] . "'";
  3327. }
  3328. }
  3329. $sql .= " OR eu1.cal_login in ".
  3330. "( SELECT eu2.cal_login
  3331. FROM webcal_entry e, webcal_entry_user eu2, "."webcal_group_user gu,webcal_group g
  3332. WHERE e.cal_id = eu2.cal_id ".
  3333. "AND eu2.cal_login = g.cal_name ".
  3334. "AND g.cal_group_id = gu.cal_group_id ".
  3335. "AND gu.cal_login = '".$user."' ".
  3336. "AND ((eu2.cal_group_status NOT LIKE ('%,A:".$user.",%') ".
  3337. "AND eu2.cal_group_status NOT LIKE ('%,R:".$user.",%')) ".
  3338. "OR eu2.cal_group_status is null)))";
  3339. //print "SQL: $sql<br />\n";
  3340. $res = dbi_query ( $sql );
  3341. if ( $res ) {
  3342. if ( $row = dbi_fetch_row ( $res ) ) {
  3343. if ( $row[0] > 0 ) {
  3344. $str = translate ("You have XXX unapproved events");
  3345. $str = str_replace ( "XXX", $row[0], $str );
  3346. echo "<a class=\"nav\" href=\"list_unapproved.php?";
  3347. if ( $user != $login ){
  3348. echo "user=".$user."&";
  3349. }
  3350. echo $info_type;
  3351. echo "\">" . $str . "</a><br />\n";
  3352. }
  3353. }
  3354. dbi_free_result ( $res );
  3355. }
  3356. }
  3357. /**
  3358. * Looks for URLs in the given text, and makes them into links.
  3359. *
  3360. * @param string $text Input text
  3361. *
  3362. * @return string The text altered to have HTML links for any web links
  3363. * (http or https)
  3364. */
  3365. function activate_urls ( $text ) {
  3366. $str = eregi_replace ( "(http://[^[:space:]$]+)",
  3367. "<a href=\"\\1\">\\1</a>", $text );
  3368. $str = eregi_replace ( "(https://[^[:space:]$]+)",
  3369. "<a href=\"\\1\">\\1</a>", $str );
  3370. return $str;
  3371. }
  3372. /**
  3373. * Displays a time in either 12 or 24 hour format.
  3374. *
  3375. * The global variable $TZ_OFFSET is used to adjust the time. Note that this
  3376. * is somewhat of a kludge for timezone support. If an event is set for 11PM
  3377. * server time and the user is 2 hours ahead, it will show up as 1AM, but the
  3378. * date will not be adjusted to the next day.
  3379. *
  3380. * @param string $time Input time in HHMMSS format
  3381. * @param bool $ignore_offset If true, then do not use the timezone offset
  3382. *
  3383. * @return string The time in the user's timezone and preferred format
  3384. *
  3385. * @global int The user's timezone offset from the server
  3386. */
  3387. function display_time ( $time, $ignore_offset=0 ) {
  3388. global $TZ_OFFSET;
  3389. $hour = (int) ( $time / 10000 );
  3390. if ( ! $ignore_offset )
  3391. $hour += $TZ_OFFSET;
  3392. $min = abs( ( $time / 100 ) % 100 );
  3393. //Prevent goofy times like 8:00 9:30 9:00 10:30 10:00
  3394. if ( $time < 0 && $min > 0 ) $hour = $hour - 1;
  3395. while ( $hour < 0 )
  3396. $hour += 24;
  3397. while ( $hour > 23 )
  3398. $hour -= 24;
  3399. if ( $GLOBALS["TIME_FORMAT"] == "12" ) {
  3400. $ampm = ( $hour >= 12 ) ? translate("pm") : translate("am");
  3401. $hour %= 12;
  3402. if ( $hour == 0 )
  3403. $hour = 12;
  3404. $ret = sprintf ( "%d:%02d%s", $hour, $min, $ampm );
  3405. } else {
  3406. $ret = sprintf ( "%d:%02d", $hour, $min );
  3407. }
  3408. return $ret;
  3409. }
  3410. /**
  3411. * Returns the full name of the specified month.
  3412. *
  3413. * Use {@link month_short_name()} to get the abbreviated name of the month.
  3414. *
  3415. * @param int $m Number of the month (0-11)
  3416. *
  3417. * @return string The full name of the specified month
  3418. *
  3419. * @see month_short_name
  3420. */
  3421. function month_name ( $m ) {
  3422. switch ( $m ) {
  3423. case 0: return translate("January");
  3424. case 1: return translate("February");
  3425. case 2: return translate("March");
  3426. case 3: return translate("April");
  3427. case 4: return translate("May_"); // needs to be different than "May"
  3428. case 5: return translate("June");
  3429. case 6: return translate("July");
  3430. case 7: return translate("August");
  3431. case 8: return translate("September");
  3432. case 9: return translate("October");
  3433. case 10: return translate("November");
  3434. case 11: return translate("December");
  3435. }
  3436. return "unknown-month($m)";
  3437. }
  3438. /**
  3439. * Returns the abbreviated name of the specified month (such as "Jan").
  3440. *
  3441. * Use {@link month_name()} to get the full name of the month.
  3442. *
  3443. * @param int $m Number of the month (0-11)
  3444. *
  3445. * @return string The abbreviated name of the specified month (example: "Jan")
  3446. *
  3447. * @see month_name
  3448. */
  3449. function month_short_name ( $m ) {
  3450. switch ( $m ) {
  3451. case 0: return translate("Jan");
  3452. case 1: return translate("Feb");
  3453. case 2: return translate("Mar");
  3454. case 3: return translate("Apr");
  3455. case 4: return translate("May");
  3456. case 5: return translate("Jun");
  3457. case 6: return translate("Jul");
  3458. case 7: return translate("Aug");
  3459. case 8: return translate("Sep");
  3460. case 9: return translate("Oct");
  3461. case 10: return translate("Nov");
  3462. case 11: return translate("Dec");
  3463. }
  3464. return "unknown-month($m)";
  3465. }
  3466. /**
  3467. * Returns the full weekday name.
  3468. *
  3469. * Use {@link weekday_short_name()} to get the abbreviated weekday name.
  3470. *
  3471. * @param int $w Number of the day in the week (0=Sunday,...,6=Saturday)
  3472. *
  3473. * @return string The full weekday name ("Sunday")
  3474. *
  3475. * @see weekday_short_name
  3476. */
  3477. function weekday_name ( $w ) {
  3478. switch ( $w ) {
  3479. case 0: return translate("Sunday");
  3480. case 1: return translate("Monday");
  3481. case 2: return translate("Tuesday");
  3482. case 3: return translate("Wednesday");
  3483. case 4: return translate("Thursday");
  3484. case 5: return translate("Friday");
  3485. case 6: return translate("Saturday");
  3486. }
  3487. return "unknown-weekday($w)";
  3488. }
  3489. /**
  3490. * Returns the abbreviated weekday name.
  3491. *
  3492. * Use {@link weekday_name()} to get the full weekday name.
  3493. *
  3494. * @param int $w Number of the day in the week (0=Sunday,...,6=Saturday)
  3495. *
  3496. * @return string The abbreviated weekday name ("Sun")
  3497. */
  3498. function weekday_short_name ( $w ) {
  3499. switch ( $w ) {
  3500. case 0: return translate("Sun");
  3501. case 1: return translate("Mon");
  3502. case 2: return translate("Tue");
  3503. case 3: return translate("Wed");
  3504. case 4: return translate("Thu");
  3505. case 5: return translate("Fri");
  3506. case 6: return translate("Sat");
  3507. }
  3508. return "unknown-weekday($w)";
  3509. }
  3510. /**
  3511. * Converts a date in YYYYMMDD format into "Friday, December 31, 1999",
  3512. * "Friday, 12-31-1999" or whatever format the user prefers.
  3513. *
  3514. * @param string $indate Date in YYYYMMDD format
  3515. * @param string $format Format to use for date (default is "__month__
  3516. * __dd__, __yyyy__")
  3517. * @param bool $show_weekday Should the day of week also be included?
  3518. * @param bool $short_months Should the abbreviated month names be used
  3519. * instead of the full month names?
  3520. * @param int $server_time ???
  3521. *
  3522. * @return string Date in the specified format
  3523. *
  3524. * @global string Preferred date format
  3525. * @global int User's timezone offset from the server
  3526. */
  3527. function date_to_str ( $indate, $format="", $show_weekday=true, $short_months=false, $server_time="" ) {
  3528. global $DATE_FORMAT, $TZ_OFFSET;
  3529. if ( strlen ( $indate ) == 0 ) {
  3530. $indate = date ( "Ymd" );
  3531. }
  3532. $newdate = $indate;
  3533. if ( $server_time != "" && $server_time >= 0 ) {
  3534. $y = substr ( $indate, 0, 4 );
  3535. $m = substr ( $indate, 4, 2 );
  3536. $d = substr ( $indate, 6, 2 );
  3537. if ( $server_time + $TZ_OFFSET * 10000 > 240000 ) {
  3538. $newdate = date ( "Ymd", mktime ( 3, 0, 0, $m, $d + 1, $y ) );
  3539. } else if ( $server_time + $TZ_OFFSET * 10000 < 0 ) {
  3540. $newdate = date ( "Ymd", mktime ( 3, 0, 0, $m, $d - 1, $y ) );
  3541. }
  3542. }
  3543. // if they have not set a preference yet...
  3544. if ( $DATE_FORMAT == "" )
  3545. $DATE_FORMAT = "__month__ __dd__, __yyyy__";
  3546. if ( empty ( $format ) )
  3547. $format = $DATE_FORMAT;
  3548. $y = (int) ( $newdate / 10000 );
  3549. $m = (int) ( $newdate / 100 ) % 100;
  3550. $d = $newdate % 100;
  3551. $date = mktime ( 3, 0, 0, $m, $d, $y );
  3552. $wday = strftime ( "%w", $date );
  3553. if ( $short_months ) {
  3554. $weekday = weekday_short_name ( $wday );
  3555. $month = month_short_name ( $m - 1 );
  3556. } else {
  3557. $weekday = weekday_name ( $wday );
  3558. $month = month_name ( $m - 1 );
  3559. }
  3560. $yyyy = $y;
  3561. $yy = sprintf ( "%02d", $y %= 100 );
  3562. $ret = $format;
  3563. $ret = str_replace ( "__yyyy__", $yyyy, $ret );
  3564. $ret = str_replace ( "__yy__", $yy, $ret );
  3565. $ret = str_replace ( "__month__", $month, $ret );
  3566. $ret = str_replace ( "__mon__", $month, $ret );
  3567. $ret = str_replace ( "__dd__", $d, $ret );
  3568. $ret = str_replace ( "__mm__", $m, $ret );
  3569. if ( $show_weekday )
  3570. return "$weekday, $ret";
  3571. else
  3572. return $ret;
  3573. }
  3574. /**
  3575. * Converts a hexadecimal digit to an integer.
  3576. *
  3577. * @param string $val Hexadecimal digit
  3578. *
  3579. * @return int Equivalent integer in base-10
  3580. *
  3581. * @ignore
  3582. */
  3583. function hextoint ( $val ) {
  3584. if ( empty ( $val ) )
  3585. return 0;
  3586. switch ( strtoupper ( $val ) ) {
  3587. case "0": return 0;
  3588. case "1": return 1;
  3589. case "2": return 2;
  3590. case "3": return 3;
  3591. case "4": return 4;
  3592. case "5": return 5;
  3593. case "6": return 6;
  3594. case "7": return 7;
  3595. case "8": return 8;
  3596. case "9": return 9;
  3597. case "A": return 10;
  3598. case "B": return 11;
  3599. case "C": return 12;
  3600. case "D": return 13;
  3601. case "E": return 14;
  3602. case "F": return 15;
  3603. }
  3604. return 0;
  3605. }
  3606. /**
  3607. * Extracts a user's name from a session id.
  3608. *
  3609. * This prevents users from begin able to edit their cookies.txt file and set
  3610. * the username in plain text.
  3611. *
  3612. * @param string $instr A hex-encoded string. "Hello" would be "678ea786a5".
  3613. *
  3614. * @return string The decoded string
  3615. *
  3616. * @global array Array of offsets
  3617. *
  3618. * @see encode_string
  3619. */
  3620. function decode_string ( $instr ) {
  3621. global $offsets;
  3622. //echo "<br />\nDECODE<br />\n";
  3623. $orig = "";
  3624. for ( $i = 0; $i < strlen ( $instr ); $i += 2 ) {
  3625. //echo "<br />\n";
  3626. $ch1 = substr ( $instr, $i, 1 );
  3627. $ch2 = substr ( $instr, $i + 1, 1 );
  3628. $val = hextoint ( $ch1 ) * 16 + hextoint ( $ch2 );
  3629. //echo "decoding \"" . $ch1 . $ch2 . "\" = $val<br />\n";
  3630. $j = ( $i / 2 ) % count ( $offsets );
  3631. //echo "Using offsets $j = " . $offsets[$j] . "<br />\n";
  3632. $newval = $val - $offsets[$j] + 256;
  3633. $newval %= 256;
  3634. //echo " neval \"$newval\"<br />\n";
  3635. $dec_ch = chr ( $newval );
  3636. //echo " which is \"$dec_ch\"<br />\n";
  3637. $orig .= $dec_ch;
  3638. }
  3639. //echo "Decode string: '$orig' <br/>\n";
  3640. return $orig;
  3641. }
  3642. /**
  3643. * Takes an input string and encode it into a slightly encoded hexval that we
  3644. * can use as a session cookie.
  3645. *
  3646. * @param string $instr Text to encode
  3647. *
  3648. * @return string The encoded text
  3649. *
  3650. * @global array Array of offsets
  3651. *
  3652. * @see decode_string
  3653. */
  3654. function encode_string ( $instr ) {
  3655. global $offsets;
  3656. //echo "<br />\nENCODE<br />\n";
  3657. $ret = "";
  3658. for ( $i = 0; $i < strlen ( $instr ); $i++ ) {
  3659. //echo "<br />\n";
  3660. $ch1 = substr ( $instr, $i, 1 );
  3661. $val = ord ( $ch1 );
  3662. //echo "val = $val for \"$ch1\"<br />\n";
  3663. $j = $i % count ( $offsets );
  3664. //echo "Using offsets $j = $offsets[$j]<br />\n";
  3665. $newval = $val + $offsets[$j];
  3666. $newval %= 256;
  3667. //echo "newval = $newval for \"$ch1\"<br />\n";
  3668. $ret .= bin2hex ( chr ( $newval ) );
  3669. }
  3670. return $ret;
  3671. }
  3672. /**
  3673. * An implementatin of array_splice() for PHP3.
  3674. *
  3675. * @param array $input Array to be spliced into
  3676. * @param int $offset Where to begin the splice
  3677. * @param int $length How long the splice should be
  3678. * @param array $replacement What to splice in
  3679. *
  3680. * @ignore
  3681. */
  3682. function my_array_splice(&$input,$offset,$length,$replacement) {
  3683. if ( floor(phpversion()) < 4 ) {
  3684. // if offset is negative, then it starts at the end of array
  3685. if ( $offset < 0 )
  3686. $offset = count($input) + $offset;
  3687. for ($i=0;$i<$offset;$i++) {
  3688. $new_array[] = $input[$i];
  3689. }
  3690. // if we have a replacement, insert it
  3691. for ($i=0;$i<count($replacement);$i++) {
  3692. $new_array[] = $replacement[$i];
  3693. }
  3694. // now tack on the rest of the original array
  3695. for ($i=$offset+$length;$i<count($input);$i++) {
  3696. $new_array[] = $input[$i];
  3697. }
  3698. $input = $new_array;
  3699. } else {
  3700. array_splice($input,$offset,$length,$replacement);
  3701. }
  3702. }
  3703. /**
  3704. * Loads current user's category info and stuff it into category global
  3705. * variable.
  3706. *
  3707. * @param string $ex_global Don't include global categories ('' or '1')
  3708. */
  3709. function load_user_categories ($ex_global = '') {
  3710. global $login, $user, $is_assistant;
  3711. global $categories, $category_owners;
  3712. global $categories_enabled, $is_admin;
  3713. $cat_owner = ( ( ! empty ( $user ) && strlen ( $user ) ) && ( $is_assistant ||
  3714. $is_admin ) ) ? $user : $login;
  3715. $categories = array ();
  3716. $category_owners = array ();
  3717. if ( $categories_enabled == "Y" ) {
  3718. $sql = "SELECT cat_id, cat_name, cat_owner FROM webcal_categories WHERE ";
  3719. $sql .= ($ex_global == '') ? " (cat_owner = '$cat_owner') OR (cat_owner IS NULL) ORDER BY cat_owner, cat_name" : " cat_owner = '$cat_owner' ORDER BY cat_name";
  3720. $res = dbi_query ( $sql );
  3721. if ( $res ) {
  3722. while ( $row = dbi_fetch_row ( $res ) ) {
  3723. $cat_id = $row[0];
  3724. $categories[$cat_id] = $row[1];
  3725. $category_owners[$cat_id] = $row[2];
  3726. }
  3727. dbi_free_result ( $res );
  3728. }
  3729. } else {
  3730. //echo "Categories disabled.";
  3731. }
  3732. }
  3733. /**
  3734. * Prints dropdown HTML for categories.
  3735. *
  3736. * @param string $form The page to submit data to (without .php)
  3737. * @param string $date Date in YYYYMMDD format
  3738. * @param int $cat_id Category id that should be pre-selected
  3739. */
  3740. function print_category_menu ( $form, $date = '', $cat_id = '' ) {
  3741. global $categories, $category_owners, $user, $login;
  3742. echo "<form action=\"{$form}.php\" method=\"get\" name=\"SelectCategory\" class=\"categories\">\n";
  3743. if ( ! empty($date) ) echo "<input type=\"hidden\" name=\"date\" value=\"$date\" />\n";
  3744. if ( ! empty ( $user ) && $user != $login )
  3745. echo "<input type=\"hidden\" name=\"user\" value=\"$user\" />\n";
  3746. echo translate ("Category") . ": <select name=\"cat_id\" onchange=\"document.SelectCategory.submit()\">\n";
  3747. echo "<option value=\"\"";
  3748. if ( $cat_id == '' ) echo " selected=\"selected\"";
  3749. echo ">" . translate("All") . "</option>\n";
  3750. $cat_owner = ( ! empty ( $user ) && strlen ( $user ) ) ? $user : $login;
  3751. if ( is_array ( $categories ) ) {
  3752. foreach ( $categories as $K => $V ){
  3753. if ( $cat_owner ||
  3754. empty ( $category_owners[$K] ) ) {
  3755. echo "<option value=\"$K\"";
  3756. if ( $cat_id == $K ) echo " selected=\"selected\"";
  3757. echo ">$V</option>\n";
  3758. }
  3759. }
  3760. }
  3761. echo "</select>\n";
  3762. echo "</form>\n";
  3763. echo "<span id=\"cat\">" . translate ("Category") . ": ";
  3764. echo ( strlen ( $cat_id ) ? $categories[$cat_id] : translate ('All') ) . "</span>\n";
  3765. }
  3766. /**
  3767. * Converts HTML entities in 8bit.
  3768. *
  3769. * <b>Note:</b> Only supported for PHP4 (not PHP3).
  3770. *
  3771. * @param string $html HTML text
  3772. *
  3773. * @return string The converted text
  3774. */
  3775. function html_to_8bits ( $html ) {
  3776. if ( floor(phpversion()) < 4 ) {
  3777. return $html;
  3778. } else {
  3779. return strtr ( $html, array_flip (
  3780. get_html_translation_table (HTML_ENTITIES) ) );
  3781. }
  3782. }
  3783. // ***********************************************************************
  3784. // Functions for getting information about boss and their assistant.
  3785. // ***********************************************************************
  3786. /**
  3787. * Gets a list of an assistant's boss from the webcal_asst table.
  3788. *
  3789. * @param string $assistant Login of assistant
  3790. *
  3791. * @return array Array of bosses, where each boss is an array with the following
  3792. * fields:
  3793. * - <var>cal_login</var>
  3794. * - <var>cal_fullname</var>
  3795. */
  3796. function user_get_boss_list ( $assistant ) {
  3797. global $bosstemp_fullname;
  3798. $res = dbi_query (
  3799. "SELECT cal_boss " .
  3800. "FROM webcal_asst " .
  3801. "WHERE cal_assistant = '$assistant'" );
  3802. $count = 0;
  3803. $ret = array ();
  3804. if ( $res ) {
  3805. while ( $row = dbi_fetch_row ( $res ) ) {
  3806. user_load_variables ( $row[0], "bosstemp_" );
  3807. $ret[$count++] = array (
  3808. "cal_login" => $row[0],
  3809. "cal_fullname" => $bosstemp_fullname
  3810. );
  3811. }
  3812. dbi_free_result ( $res );
  3813. }
  3814. return $ret;
  3815. }
  3816. /**
  3817. * Is this user an assistant of this boss?
  3818. *
  3819. * @param string $assistant Login of potential assistant
  3820. * @param string $boss Login of potential boss
  3821. *
  3822. * @return bool True or false
  3823. */
  3824. function user_is_assistant ( $assistant, $boss ) {
  3825. $ret = false;
  3826. if ( empty ( $boss ) )
  3827. return false;
  3828. $res = dbi_query ( "SELECT * FROM webcal_asst " .
  3829. "WHERE cal_assistant = '$assistant' AND cal_boss = '$boss'" );
  3830. if ( $res ) {
  3831. if ( dbi_fetch_row ( $res ) )
  3832. $ret = true;
  3833. dbi_free_result ( $res );
  3834. }
  3835. return $ret;
  3836. }
  3837. /**
  3838. * Is this user an assistant?
  3839. *
  3840. * @param string $assistant Login for user
  3841. *
  3842. * @return bool true if the user is an assistant to one or more bosses
  3843. */
  3844. function user_has_boss ( $assistant ) {
  3845. $ret = false;
  3846. $res = dbi_query ( "SELECT * FROM webcal_asst " .
  3847. "WHERE cal_assistant = '$assistant'" );
  3848. if ( $res ) {
  3849. if ( dbi_fetch_row ( $res ) )
  3850. $ret = true;
  3851. dbi_free_result ( $res );
  3852. }
  3853. return $ret;
  3854. }
  3855. /**
  3856. * Checks the boss user preferences to see if the boss wants to be notified via
  3857. * email on changes to their calendar.
  3858. *
  3859. * @param string $assistant Assistant login
  3860. * @param string $boss Boss login
  3861. *
  3862. * @return bool True if the boss wants email notifications
  3863. */
  3864. function boss_must_be_notified ( $assistant, $boss ) {
  3865. if (user_is_assistant ( $assistant, $boss ) )
  3866. return ( get_pref_setting ( $boss, "EMAIL_ASSISTANT_EVENTS" )=="Y" ? true : false );
  3867. return true;
  3868. }
  3869. /**
  3870. * Checks the boss user preferences to see if the boss must approve events
  3871. * added to their calendar.
  3872. *
  3873. * @param string $assistant Assistant login
  3874. * @param string $boss Boss login
  3875. *
  3876. * @return bool True if the boss must approve new events
  3877. */
  3878. function boss_must_approve_event ( $assistant, $boss ) {
  3879. if (user_is_assistant ( $assistant, $boss ) )
  3880. return ( get_pref_setting ( $boss, "APPROVE_ASSISTANT_EVENT" )=="Y" ? true : false );
  3881. return true;
  3882. }
  3883. /**
  3884. * Fakes an email for testing purposes.
  3885. *
  3886. * @param string $mailto Email address to send mail to
  3887. * @param string $subj Subject of email
  3888. * @param string $text Email body
  3889. * @param string $hdrs Other email headers
  3890. *
  3891. * @ignore
  3892. */
  3893. function fake_mail ( $mailto, $subj, $text, $hdrs ) {
  3894. echo "To: $mailto <br />\n" .
  3895. "Subject: $subj <br />\n" .
  3896. nl2br ( $hdrs ) . "<br />\n" .
  3897. nl2br ( $text );
  3898. }
  3899. /**
  3900. * Prints all the entries in a time bar format for the specified user for the
  3901. * specified date.
  3902. *
  3903. * If we are displaying data from someone other than the logged in user, then
  3904. * check the access permission of the entry.
  3905. *
  3906. * @param string $date Date in YYYYMMDD format
  3907. * @param string $user Username
  3908. * @param bool $ssi Should we not include links to add new events?
  3909. */
  3910. function print_date_entries_timebar ( $date, $user, $ssi ) {
  3911. global $events, $readonly, $is_admin,
  3912. $public_access, $public_access_can_add;
  3913. $cnt = 0;
  3914. $get_unapproved = ( $GLOBALS["DISPLAY_UNAPPROVED"] == "Y" );
  3915. // public access events always must be approved before being displayed
  3916. if ( $GLOBALS["login"] == "__public__" )
  3917. $get_unapproved = false;
  3918. $year = substr ( $date, 0, 4 );
  3919. $month = substr ( $date, 4, 2 );
  3920. $day = substr ( $date, 6, 2 );
  3921. $dateu = mktime ( 3, 0, 0, $month, $day, $year );
  3922. $can_add = ( $readonly == "N" || $is_admin );
  3923. if ( $public_access == "Y" && $public_access_can_add != "Y" &&
  3924. $GLOBALS["login"] == "__public__" )
  3925. $can_add = false;
  3926. // get all the repeating events for this date and store in array $rep
  3927. $rep = get_repeating_entries ( $user, $date ) ;
  3928. $cur_rep = 0;
  3929. // get all the non-repeating events for this date and store in $ev
  3930. $ev = get_entries ( $user, $date, $get_unapproved );
  3931. for ( $i = 0; $i < count ( $ev ); $i++ ) {
  3932. // print out any repeating events that are before this one...
  3933. while ( $cur_rep < count ( $rep ) &&
  3934. $rep[$cur_rep]['cal_time'] < $ev[$i]['cal_time'] ) {
  3935. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  3936. print_entry_timebar ( $rep[$cur_rep]['cal_id'],
  3937. $date, $rep[$cur_rep]['cal_time'], $rep[$cur_rep]['cal_duration'],
  3938. $rep[$cur_rep]['cal_name'], $rep[$cur_rep]['cal_description'],
  3939. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  3940. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_login'],
  3941. $rep[$cur_rep]['cal_category'] );
  3942. $cnt++;
  3943. }
  3944. $cur_rep++;
  3945. }
  3946. if ( $get_unapproved || $ev[$i]['cal_status'] == 'A' ) {
  3947. print_entry_timebar ( $ev[$i]['cal_id'],
  3948. $date, $ev[$i]['cal_time'], $ev[$i]['cal_duration'],
  3949. $ev[$i]['cal_name'], $ev[$i]['cal_description'],
  3950. $ev[$i]['cal_status'], $ev[$i]['cal_priority'],
  3951. $ev[$i]['cal_access'], $ev[$i]['cal_login'],
  3952. $ev[$i]['cal_category'] );
  3953. $cnt++;
  3954. }
  3955. }
  3956. // print out any remaining repeating events
  3957. while ( $cur_rep < count ( $rep ) ) {
  3958. if ( $get_unapproved || $rep[$cur_rep]['cal_status'] == 'A' ) {
  3959. print_entry_timebar ( $rep[$cur_rep]['cal_id'],
  3960. $date, $rep[$cur_rep]['cal_time'], $rep[$cur_rep]['cal_duration'],
  3961. $rep[$cur_rep]['cal_name'], $rep[$cur_rep]['cal_description'],
  3962. $rep[$cur_rep]['cal_status'], $rep[$cur_rep]['cal_priority'],
  3963. $rep[$cur_rep]['cal_access'], $rep[$cur_rep]['cal_login'],
  3964. $rep[$cur_rep]['cal_category'] );
  3965. $cnt++;
  3966. }
  3967. $cur_rep++;
  3968. }
  3969. if ( $cnt == 0 )
  3970. echo "&nbsp;"; // so the table cell has at least something
  3971. }
  3972. /**
  3973. * Prints the HTML for an events with a timebar.
  3974. *
  3975. * @param int $id Event id
  3976. * @param string $date Date of event in YYYYMMDD format
  3977. * @param string $time Time of event in HHMM format
  3978. * @param int $duration Duration of event in minutes
  3979. * @param string $name Brief description of event
  3980. * @param string $description Full description of event
  3981. * @param string $status Status of event ('A', 'W')
  3982. * @param int $pri Priority of event
  3983. * @param string $access Access to event by others ('P', 'R')
  3984. * @param string $event_owner User who created event
  3985. * @param int $event_category Category id for event
  3986. *
  3987. * @staticvar int Used to ensure all event popups have a unique id
  3988. */
  3989. function print_entry_timebar ( $id, $date, $time, $duration,
  3990. $name, $description, $status,
  3991. $pri, $access, $event_owner, $event_category=-1 ) {
  3992. global $eventinfo, $login, $user, $PHP_SELF, $prefarray;
  3993. static $key = 0;
  3994. $insidespan = false;
  3995. global $layers;
  3996. // compute time offsets in % of total table width
  3997. $day_start=$prefarray["WORK_DAY_START_HOUR"] * 60;
  3998. if ( $day_start == 0 ) $day_start = 9*60;
  3999. $day_end=$prefarray["WORK_DAY_END_HOUR"] * 60;
  4000. if ( $day_end == 0 ) $day_end = 19*60;
  4001. if ( $day_end <= $day_start ) $day_end = $day_start + 60; //avoid exceptions
  4002. if ($time >= 0) {
  4003. $bar_units= 100/(($day_end - $day_start)/60) ; // Percentage each hour occupies
  4004. $ev_start = round((floor(($time/10000) - ($day_start/60)) + (($time/100)%100)/60) * $bar_units);
  4005. }else{
  4006. $ev_start= 0;
  4007. }
  4008. if ($ev_start < 0) $ev_start = 0;
  4009. if ($duration > 0) {
  4010. $ev_duration = round(100 * $duration / ($day_end - $day_start)) ;
  4011. if ($ev_start + $ev_duration > 100 ) {
  4012. $ev_duration = 100 - $ev_start;
  4013. }
  4014. } else {
  4015. if ($time >= 0) {
  4016. $ev_duration = 1;
  4017. } else {
  4018. $ev_duration=100-$ev_start;
  4019. }
  4020. }
  4021. $ev_padding = 100 - $ev_start - $ev_duration;
  4022. // choose where to position the text (pos=0->before,pos=1->on,pos=2->after)
  4023. if ($ev_duration > 20) { $pos = 1; }
  4024. elseif ($ev_padding > 20) { $pos = 2; }
  4025. else { $pos = 0; }
  4026. echo "\n<!-- ENTRY BAR -->\n<table class=\"entrycont\" cellpadding=\"0\" cellspacing=\"0\">\n";
  4027. echo "<tr>\n";
  4028. echo ($ev_start > 0 ? "<td style=\"text-align:right; width:$ev_start%;\">" : "" );
  4029. if ( $pos > 0 ) {
  4030. echo ($ev_start > 0 ? "&nbsp;</td>\n": "" ) ;
  4031. echo "<td style=\"width:$ev_duration%;\">\n<table class=\"entrybar\">\n<tr>\n<td class=\"entry\">";
  4032. if ( $pos > 1 ) {
  4033. echo ($ev_padding > 0 ? "&nbsp;</td>\n": "" ) . "</tr>\n</table></td>\n";
  4034. echo ($ev_padding > 0 ? "<td style=\"text-align:left; width:$ev_padding%;\">" : "");
  4035. }
  4036. };
  4037. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  4038. $class = "layerentry";
  4039. } else {
  4040. $class = "entry";
  4041. if ( $status == "W" ) $class = "unapprovedentry";
  4042. }
  4043. // if we are looking at a view, then always use "entry"
  4044. if ( strstr ( $PHP_SELF, "view_m.php" ) ||
  4045. strstr ( $PHP_SELF, "view_w.php" ) ||
  4046. strstr ( $PHP_SELF, "view_v.php" ) ||
  4047. strstr ( $PHP_SELF, "view_t.php" ) )
  4048. $class = "entry";
  4049. if ( $pri == 3 ) echo "<strong>";
  4050. $popupid = "eventinfo-$id-$key";
  4051. $key++;
  4052. echo "<a class=\"$class\" href=\"view_entry.php?id=$id&amp;date=$date";
  4053. if ( strlen ( $user ) > 0 )
  4054. echo "&amp;user=" . $user;
  4055. echo "\" onmouseover=\"window.status='" .
  4056. translate("View this entry") . "'; show(event, '$popupid'); return true;\" onmouseout=\"hide('$popupid'); return true;\">";
  4057. if ( $login != $event_owner && strlen ( $event_owner ) ) {
  4058. if ($layers) foreach ($layers as $layer) {
  4059. if($layer['cal_layeruser'] == $event_owner) {
  4060. $insidespan = true;
  4061. echo("<span style=\"color:" . $layer['cal_color'] . ";\">");
  4062. }
  4063. }
  4064. }
  4065. echo "[$event_owner]&nbsp;";
  4066. $timestr = "";
  4067. if ( $duration == ( 24 * 60 ) ) {
  4068. $timestr = translate("All day event");
  4069. } else if ( $time >= 0 ) {
  4070. $timestr = display_time ( $time );
  4071. if ( $duration > 0 ) {
  4072. // calc end time
  4073. $h = (int) ( $time / 10000 );
  4074. $m = ( $time / 100 ) % 100;
  4075. $m += $duration;
  4076. $d = $duration;
  4077. while ( $m >= 60 ) {
  4078. $h++;
  4079. $m -= 60;
  4080. }
  4081. $end_time = sprintf ( "%02d%02d00", $h, $m );
  4082. $timestr .= " - " . display_time ( $end_time );
  4083. }
  4084. }
  4085. if ( $login != $user && $access == 'R' && strlen ( $user ) )
  4086. echo "(" . translate("Private") . ")";
  4087. else
  4088. if ( $login != $event_owner && $access == 'R' && strlen ( $event_owner ) )
  4089. echo "(" . translate("Private") . ")";
  4090. else
  4091. if ( $login != $event_owner && strlen ( $event_owner ) )
  4092. {
  4093. echo htmlspecialchars ( $name );
  4094. if ( $insidespan ) { echo ("</span>"); } //end color span
  4095. }
  4096. else
  4097. echo htmlspecialchars ( $name );
  4098. echo "</a>";
  4099. if ( $pri == 3 ) echo "</strong>"; //end font-weight span
  4100. echo "</td>\n";
  4101. if ( $pos < 2 ) {
  4102. if ( $pos < 1 ) {
  4103. echo "<td style=\"width:$ev_duration%;\"><table class=\"entrybar\">\n<tr>\n<td class=\"entry\">&nbsp;</td>\n";
  4104. }
  4105. echo "</tr>\n</table></td>\n";
  4106. echo ($ev_padding > 0 ? "<td style=\"text-align:left; width:$ev_padding%;\">&nbsp;</td>\n" : "" );
  4107. }
  4108. echo "</tr>\n</table>\n";
  4109. if ( $login != $user && $access == 'R' && strlen ( $user ) )
  4110. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  4111. translate("This event is confidential"), "" );
  4112. else
  4113. if ( $login != $event_owner && $access == 'R' && strlen ( $event_owner ) )
  4114. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  4115. translate("This event is confidential"), "" );
  4116. else
  4117. $eventinfo .= build_event_popup ( $popupid, $event_owner,
  4118. $description, $timestr, site_extras_for_popup ( $id ) );
  4119. }
  4120. /**
  4121. * Prints the header for the timebar.
  4122. *
  4123. * @param int $start_hour Start hour
  4124. * @param int $end_hour End hour
  4125. */
  4126. function print_header_timebar($start_hour, $end_hour) {
  4127. // sh+1 ... eh-1
  4128. // +------+----....----+------+
  4129. // | | | |
  4130. // print hours
  4131. if ( ($end_hour - $start_hour) == 0 )
  4132. $offset = 0;
  4133. else
  4134. $offset = round(100/($end_hour - $start_hour));
  4135. echo "\n<!-- TIMEBAR -->\n<table class=\"timebar\">\n<tr><td style=\"width:$offset%;\">&nbsp;</td>\n";
  4136. for ($i = $start_hour+1; $i < $end_hour; $i++) {
  4137. // $prev_offset = $offset;
  4138. // $offset = round(100/($end_hour - $start_hour)*($i - $start_hour + .5));
  4139. $offset = round(100/($end_hour - $start_hour));
  4140. $width = $offset;
  4141. echo "<td style=\"width:$width%;text-align:left;\">$i</td>\n";
  4142. }
  4143. // $width = 100 - $offset;
  4144. // echo "<td style=\"width:$width%;\">&nbsp;</td>\n";
  4145. echo "</tr>\n</table>\n<!-- /TIMEBAR -->\n";
  4146. // print yardstick
  4147. echo "\n<!-- YARDSTICK -->\n<table class=\"yardstick\">\n<tr>\n";
  4148. $width = round(100/($end_hour - $start_hour));
  4149. for ($i = $start_hour; $i < $end_hour; $i++) {
  4150. echo "<td style=\"width:$width%;\">&nbsp;</td>\n";
  4151. }
  4152. echo "</tr>\n</table>\n<!-- /YARDSTICK -->\n";
  4153. }
  4154. /**
  4155. * Gets a list of nonuser calendars and return info in an array.
  4156. *
  4157. * @param string $user Login of admin of the nonuser calendars
  4158. *
  4159. * @return array Array of nonuser cals, where each is an array with the
  4160. * following fields:
  4161. * - <var>cal_login</var>
  4162. * - <var>cal_lastname</var>
  4163. * - <var>cal_firstname</var>
  4164. * - <var>cal_admin</var>
  4165. * - <var>cal_fullname</var>
  4166. */
  4167. function get_nonuser_cals ($user = '') {
  4168. $count = 0;
  4169. $ret = array ();
  4170. $sql = "SELECT cal_login, cal_lastname, cal_firstname, " .
  4171. "cal_admin FROM webcal_nonuser_cals ";
  4172. if ($user != '') $sql .= "WHERE cal_admin = '$user' ";
  4173. $sql .= "ORDER BY cal_lastname, cal_firstname, cal_login";
  4174. $res = dbi_query ( $sql );
  4175. if ( $res ) {
  4176. while ( $row = dbi_fetch_row ( $res ) ) {
  4177. if ( strlen ( $row[1] ) || strlen ( $row[2] ) )
  4178. $fullname = "$row[2] $row[1]";
  4179. else
  4180. $fullname = $row[0];
  4181. $ret[$count++] = array (
  4182. "cal_login" => $row[0],
  4183. "cal_lastname" => $row[1],
  4184. "cal_firstname" => $row[2],
  4185. "cal_admin" => $row[3],
  4186. "cal_fullname" => $fullname
  4187. );
  4188. }
  4189. dbi_free_result ( $res );
  4190. }
  4191. return $ret;
  4192. }
  4193. /**
  4194. * Loads nonuser variables (login, firstname, etc.).
  4195. *
  4196. * The following variables will be set:
  4197. * - <var>login</var>
  4198. * - <var>firstname</var>
  4199. * - <var>lastname</var>
  4200. * - <var>fullname</var>
  4201. * - <var>admin</var>
  4202. * - <var>email</var>
  4203. *
  4204. * @param string $login Login name of nonuser calendar
  4205. * @param string $prefix Prefix to use for variables that will be set.
  4206. * For example, if prefix is "temp", then the login will
  4207. * be stored in the <var>$templogin</var> global variable.
  4208. */
  4209. function nonuser_load_variables ( $login, $prefix ) {
  4210. global $error,$nuloadtmp_email;
  4211. $ret = false;
  4212. $res = dbi_query ( "SELECT cal_login, cal_lastname, cal_firstname, " .
  4213. "cal_admin FROM webcal_nonuser_cals WHERE cal_login = '$login'" );
  4214. if ( $res ) {
  4215. while ( $row = dbi_fetch_row ( $res ) ) {
  4216. if ( strlen ( $row[1] ) || strlen ( $row[2] ) )
  4217. $fullname = "$row[2] $row[1]";
  4218. else
  4219. $fullname = $row[0];
  4220. // We need the email address for the admin
  4221. user_load_variables ( $row[3], 'nuloadtmp_' );
  4222. $GLOBALS[$prefix . "login"] = $row[0];
  4223. $GLOBALS[$prefix . "firstname"] = $row[2];
  4224. $GLOBALS[$prefix . "lastname"] = $row[1];
  4225. $GLOBALS[$prefix . "fullname"] = $fullname;
  4226. $GLOBALS[$prefix . "admin"] = $row[3];
  4227. $GLOBALS[$prefix . "email"] = $nuloadtmp_email;
  4228. $ret = true;
  4229. }
  4230. dbi_free_result ( $res );
  4231. }
  4232. return $ret;
  4233. }
  4234. /**
  4235. * Checks the webcal_nonuser_cals table to determine if the user is the
  4236. * administrator for the nonuser calendar.
  4237. *
  4238. * @param string $login Login of user that is the potential administrator
  4239. * @param string $nonuser Login name for nonuser calendar
  4240. *
  4241. * @return bool True if the user is the administrator for the nonuser calendar
  4242. */
  4243. function user_is_nonuser_admin ( $login, $nonuser ) {
  4244. $ret = false;
  4245. $res = dbi_query ( "SELECT * FROM webcal_nonuser_cals " .
  4246. "WHERE cal_login = '$nonuser' AND cal_admin = '$login'" );
  4247. if ( $res ) {
  4248. if ( dbi_fetch_row ( $res ) )
  4249. $ret = true;
  4250. dbi_free_result ( $res );
  4251. }
  4252. return $ret;
  4253. }
  4254. /**
  4255. * Loads nonuser preferences from the webcal_user_pref table if on a nonuser
  4256. * admin page.
  4257. *
  4258. * @param string $nonuser Login name for nonuser calendar
  4259. */
  4260. function load_nonuser_preferences ($nonuser) {
  4261. global $prefarray;
  4262. $res = dbi_query (
  4263. "SELECT cal_setting, cal_value FROM webcal_user_pref " .
  4264. "WHERE cal_login = '$nonuser'" );
  4265. if ( $res ) {
  4266. while ( $row = dbi_fetch_row ( $res ) ) {
  4267. $setting = $row[0];
  4268. $value = $row[1];
  4269. $sys_setting = "sys_" . $setting;
  4270. // save system defaults
  4271. // ** don't override ones set by load_user_prefs
  4272. if ( ! empty ( $GLOBALS[$setting] ) && empty ( $GLOBALS["sys_" . $setting] ))
  4273. $GLOBALS["sys_" . $setting] = $GLOBALS[$setting];
  4274. $GLOBALS[$setting] = $value;
  4275. $prefarray[$setting] = $value;
  4276. }
  4277. dbi_free_result ( $res );
  4278. }
  4279. }
  4280. /**
  4281. * Determines what the day is after the <var>$TZ_OFFSET</var> and sets it globally.
  4282. *
  4283. * The following global variables will be set:
  4284. * - <var>$thisyear</var>
  4285. * - <var>$thismonth</var>
  4286. * - <var>$thisday</var>
  4287. * - <var>$thisdate</var>
  4288. * - <var>$today</var>
  4289. *
  4290. * @param string $date The date in YYYYMMDD format
  4291. */
  4292. function set_today($date) {
  4293. global $thisyear, $thisday, $thismonth, $thisdate, $today;
  4294. global $TZ_OFFSET, $month, $day, $year, $thisday;
  4295. // Adjust for TimeZone
  4296. $today = time() + ($TZ_OFFSET * 60 * 60);
  4297. if ( ! empty ( $date ) && ! empty ( $date ) ) {
  4298. $thisyear = substr ( $date, 0, 4 );
  4299. $thismonth = substr ( $date, 4, 2 );
  4300. $thisday = substr ( $date, 6, 2 );
  4301. } else {
  4302. if ( empty ( $month ) || $month == 0 )
  4303. $thismonth = date("m", $today);
  4304. else
  4305. $thismonth = $month;
  4306. if ( empty ( $year ) || $year == 0 )
  4307. $thisyear = date("Y", $today);
  4308. else
  4309. $thisyear = $year;
  4310. if ( empty ( $day ) || $day == 0 )
  4311. $thisday = date("d", $today);
  4312. else
  4313. $thisday = $day;
  4314. }
  4315. $thisdate = sprintf ( "%04d%02d%02d", $thisyear, $thismonth, $thisday );
  4316. }
  4317. /**
  4318. * Converts from Gregorian Year-Month-Day to ISO YearNumber-WeekNumber-WeekDay.
  4319. *
  4320. * @internal JGH borrowed gregorianToISO from PEAR Date_Calc Class and added
  4321. * $GLOBALS["WEEK_START"] (change noted)
  4322. *
  4323. * @param int $day Day of month
  4324. * @param int $month Number of month
  4325. * @param int $year Year
  4326. *
  4327. * @return string Date in ISO YearNumber-WeekNumber-WeekDay format
  4328. *
  4329. * @ignore
  4330. */
  4331. function gregorianToISO($day,$month,$year) {
  4332. $mnth = array (0,31,59,90,120,151,181,212,243,273,304,334);
  4333. $y_isleap = isLeapYear($year);
  4334. $y_1_isleap = isLeapYear($year - 1);
  4335. $day_of_year_number = $day + $mnth[$month - 1];
  4336. if ($y_isleap && $month > 2) {
  4337. $day_of_year_number++;
  4338. }
  4339. // find Jan 1 weekday (monday = 1, sunday = 7)
  4340. $yy = ($year - 1) % 100;
  4341. $c = ($year - 1) - $yy;
  4342. $g = $yy + intval($yy/4);
  4343. $jan1_weekday = 1 + intval((((($c / 100) % 4) * 5) + $g) % 7);
  4344. // JGH added next if/else to compensate for week begins on Sunday
  4345. if (! $GLOBALS["WEEK_START"] && $jan1_weekday < 7) {
  4346. $jan1_weekday++;
  4347. } elseif (! $GLOBALS["WEEK_START"] && $jan1_weekday == 7) {
  4348. $jan1_weekday=1;
  4349. }
  4350. // weekday for year-month-day
  4351. $h = $day_of_year_number + ($jan1_weekday - 1);
  4352. $weekday = 1 + intval(($h - 1) % 7);
  4353. // find if Y M D falls in YearNumber Y-1, WeekNumber 52 or
  4354. if ($day_of_year_number <= (8 - $jan1_weekday) && $jan1_weekday > 4){
  4355. $yearnumber = $year - 1;
  4356. if ($jan1_weekday == 5 || ($jan1_weekday == 6 && $y_1_isleap)) {
  4357. $weeknumber = 53;
  4358. } else {
  4359. $weeknumber = 52;
  4360. }
  4361. } else {
  4362. $yearnumber = $year;
  4363. }
  4364. // find if Y M D falls in YearNumber Y+1, WeekNumber 1
  4365. if ($yearnumber == $year) {
  4366. if ($y_isleap) {
  4367. $i = 366;
  4368. } else {
  4369. $i = 365;
  4370. }
  4371. if (($i - $day_of_year_number) < (4 - $weekday)) {
  4372. $yearnumber++;
  4373. $weeknumber = 1;
  4374. }
  4375. }
  4376. // find if Y M D falls in YearNumber Y, WeekNumber 1 through 53
  4377. if ($yearnumber == $year) {
  4378. $j = $day_of_year_number + (7 - $weekday) + ($jan1_weekday - 1);
  4379. $weeknumber = intval($j / 7);
  4380. if ($jan1_weekday > 4) {
  4381. $weeknumber--;
  4382. }
  4383. }
  4384. // put it all together
  4385. if ($weeknumber < 10)
  4386. $weeknumber = '0'.$weeknumber;
  4387. return "{$yearnumber}-{$weeknumber}-{$weekday}";
  4388. }
  4389. /**
  4390. * Is this a leap year?
  4391. *
  4392. * @internal JGH Borrowed isLeapYear from PEAR Date_Calc Class
  4393. *
  4394. * @param int $year Year
  4395. *
  4396. * @return bool True for a leap year, else false
  4397. *
  4398. * @ignore
  4399. */
  4400. function isLeapYear($year='') {
  4401. if (empty($year)) $year = strftime("%Y",time());
  4402. if (strlen($year) != 4) return false;
  4403. if (preg_match('/\D/',$year)) return false;
  4404. return (($year % 4 == 0 && $year % 100 != 0) || $year % 400 == 0);
  4405. }
  4406. /**
  4407. * Replaces unsafe characters with HTML encoded equivalents.
  4408. *
  4409. * @param string $value Input text
  4410. *
  4411. * @return string The cleaned text
  4412. */
  4413. function clean_html($value){
  4414. $value = htmlspecialchars($value, ENT_QUOTES);
  4415. $value = strtr($value, array(
  4416. '(' => '&#40;',
  4417. ')' => '&#41;'
  4418. ));
  4419. return $value;
  4420. }
  4421. /**
  4422. * Removes non-word characters from the specified text.
  4423. *
  4424. * @param string $data Input text
  4425. *
  4426. * @return string The converted text
  4427. */
  4428. function clean_word($data) {
  4429. return preg_replace("/\W/", '', $data);
  4430. }
  4431. /**
  4432. * Removes non-digits from the specified text.
  4433. *
  4434. * @param string $data Input text
  4435. *
  4436. * @return string The converted text
  4437. */
  4438. function clean_int($data) {
  4439. return preg_replace("/\D/", '', $data);
  4440. }
  4441. /**
  4442. * Removes whitespace from the specified text.
  4443. *
  4444. * @param string $data Input text
  4445. *
  4446. * @return string The converted text
  4447. */
  4448. function clean_whitespace($data) {
  4449. return preg_replace("/\s/", '', $data);
  4450. }
  4451. /**
  4452. * Converts language names to their abbreviation.
  4453. *
  4454. * @param string $name Name of the language (such as "French")
  4455. *
  4456. * @return string The abbreviation ("fr" for "French")
  4457. */
  4458. function languageToAbbrev ( $name ) {
  4459. global $browser_languages;
  4460. foreach ( $browser_languages as $abbrev => $langname ) {
  4461. if ( $langname == $name )
  4462. return $abbrev;
  4463. }
  4464. return false;
  4465. }
  4466. /**
  4467. * Creates the CSS for using gradient.php, if the appropriate GD functions are
  4468. * available.
  4469. *
  4470. * A one-pixel wide image will be used for the background image.
  4471. *
  4472. * <b>Note:</b> The gd library module needs to be available to use gradient
  4473. * images. If it is not available, a single background color will be used
  4474. * instead.
  4475. *
  4476. * @param string $color Base color
  4477. * @param int $height Height of gradient image
  4478. * @param int $percent How many percent lighter the top color should be
  4479. * than the base color at the bottom of the image
  4480. *
  4481. * @return string The style sheet text to use
  4482. */
  4483. function background_css ( $color, $height = '', $percent = '' ) {
  4484. $ret = '';
  4485. if ( ( function_exists ( 'imagepng' ) || function_exists ( 'imagegif' ) )
  4486. && ( empty ( $GLOBALS['enable_gradients'] ) ||
  4487. $GLOBALS['enable_gradients'] == 'Y' ) ) {
  4488. $ret = "background: $color url(\"gradient.php?base=" . substr ( $color, 1 );
  4489. if ( $height != '' ) {
  4490. $ret .= "&height=$height";
  4491. }
  4492. if ( $percent != '' ) {
  4493. $ret .= "&percent=$percent";
  4494. }
  4495. $ret .= "\") repeat-x;\n";
  4496. } else {
  4497. $ret = "background-color: $color;\n";
  4498. }
  4499. return $ret;
  4500. }
  4501. /**
  4502. * Draws a daily outlook style availability grid showing events that are
  4503. * approved and awaiting approval.
  4504. *
  4505. * @param string $date Date to show the grid for
  4506. * @param array $participants Which users should be included in the grid
  4507. * @param string $popup Not used
  4508. */
  4509. function daily_matrix ( $date, $participants, $popup = '' ) {
  4510. global $CELLBG, $TODAYCELLBG, $THFG, $THBG, $TABLEBG;
  4511. global $user_fullname, $repeated_events, $events;
  4512. global $WORK_DAY_START_HOUR, $WORK_DAY_END_HOUR, $TZ_OFFSET,$ignore_offset;
  4513. $increment = 15;
  4514. $interval = 4;
  4515. $participant_pct = '20%'; //use percentage
  4516. $first_hour = $WORK_DAY_START_HOUR;
  4517. $last_hour = $WORK_DAY_END_HOUR;
  4518. $hours = $last_hour - $first_hour;
  4519. $cols = (($hours * $interval) + 1);
  4520. $total_pct = '80%';
  4521. $cell_pct = 80 /($hours * $interval);
  4522. $master = array();
  4523. // Build a master array containing all events for $participants
  4524. for ( $i = 0; $i < count ( $participants ); $i++ ) {
  4525. /* Pre-Load the repeated events for quckier access */
  4526. $repeated_events = read_repeated_events ( $participants[$i], "", $date );
  4527. /* Pre-load the non-repeating events for quicker access */
  4528. $events = read_events ( $participants[$i], $date, $date );
  4529. // get all the repeating events for this date and store in array $rep
  4530. $rep = get_repeating_entries ( $participants[$i], $date );
  4531. // get all the non-repeating events for this date and store in $ev
  4532. $ev = get_entries ( $participants[$i], $date );
  4533. // combine into a single array for easy processing
  4534. $ALL = array_merge ( $rep, $ev );
  4535. foreach ( $ALL as $E ) {
  4536. if ($E['cal_time'] == 0) {
  4537. $E['cal_time'] = $first_hour."0000";
  4538. $E['cal_duration'] = 60 * ( $last_hour - $first_hour );
  4539. } else {
  4540. $E['cal_time'] = sprintf ( "%06d", $E['cal_time']);
  4541. }
  4542. $hour = substr($E['cal_time'], 0, 2 );
  4543. $mins = substr($E['cal_time'], 2, 2 );
  4544. // Timezone Offset
  4545. if ( ! $ignore_offset ) $hour += $TZ_OFFSET;
  4546. while ( $hour < 0 ) $hour += 24;
  4547. while ( $hour > 23 ) $hour -= 24;
  4548. // Make sure hour is 2 digits
  4549. $hour = sprintf ( "%02d",$hour);
  4550. // convert cal_time to slot
  4551. if ($mins < 15) {
  4552. $slot = $hour.'';
  4553. } elseif ($mins >= 15 && $mins < 30) {
  4554. $slot = $hour.'.25';
  4555. } elseif ($mins >= 30 && $mins < 45) {
  4556. $slot = $hour.'.5';
  4557. } elseif ($mins >= 45) {
  4558. $slot = $hour.'.75';
  4559. }
  4560. // convert cal_duration to bars
  4561. $bars = $E['cal_duration'] / $increment;
  4562. // never replace 'A' with 'W'
  4563. for ($q = 0; $bars > $q; $q++) {
  4564. $slot = sprintf ("%02.2f",$slot);
  4565. if (strlen($slot) == 4) $slot = '0'.$slot; // add leading zeros
  4566. $slot = $slot.''; // convert to a string
  4567. if ( empty ( $master['_all_'][$slot] ) ||
  4568. $master['_all_'][$slot]['stat'] != 'A') {
  4569. $master['_all_'][$slot]['stat'] = $E['cal_status'];
  4570. }
  4571. if ( empty ( $master[$participants[$i]][$slot] ) ||
  4572. $master[$participants[$i]][$slot]['stat'] != 'A' ) {
  4573. $master[$participants[$i]][$slot]['stat'] = $E['cal_status'];
  4574. $master[$participants[$i]][$slot]['ID'] = $E['cal_id'];
  4575. }
  4576. $slot = $slot + '0.25';
  4577. }
  4578. }
  4579. }
  4580. ?>
  4581. <br />
  4582. <table align="center" class="matrixd" style="width:<?php echo $total_pct;?>;" cellspacing="0" cellpadding="0">
  4583. <tr><td class="matrix" colspan="<?php echo $cols;?>"></td></tr>
  4584. <tr><th style="width:<?php echo $participant_pct;?>;">
  4585. <?php etranslate("Participants");?></th>
  4586. <?php
  4587. $str = '';
  4588. $MouseOut = "onmouseout=\"window.status=''; this.style.backgroundColor='".$THBG."';\"";
  4589. $CC = 1;
  4590. for($i=$first_hour;$i<$last_hour;$i++) {
  4591. $hour = $i;
  4592. if ( $GLOBALS["TIME_FORMAT"] == "12" ) {
  4593. $hour %= 12;
  4594. if ( $hour == 0 ) $hour = 12;
  4595. }
  4596. for($j=0;$j<$interval;$j++) {
  4597. $str .= ' <td id="C'.$CC.'" class="dailymatrix" ';
  4598. $MouseDown = 'onmousedown="schedule_event('.$i.','.sprintf ("%02d",($increment * $j)).');"';
  4599. switch($j) {
  4600. case 1:
  4601. if($interval == 4) { $k = ($hour<=9?'0':substr($hour,0,1)); }
  4602. $str .= 'style="width:'.$cell_pct.'%; text-align:right;" '.$MouseDown." onmouseover=\"window.status='Schedule a ".$hour.':'.($increment * $j<=9?'0':'').($increment * $j)." appointment.'; this.style.backgroundColor='#CCFFCC'; return true;\" ".$MouseOut." title=\"Schedule an appointment for ".$hour.':'.($increment * $j<=9?'0':'').($increment * $j).".\">";
  4603. $str .= $k."</td>\n";
  4604. break;
  4605. case 2:
  4606. if($interval == 4) { $k = ($hour<=9?substr($hour,0,1):substr($hour,1,2)); }
  4607. $str .= 'style="width:'.$cell_pct.'%; text-align:left;" '.$MouseDown." onmouseover=\"window.status='Schedule a ".$hour.':'.($increment * $j)." appointment.'; this.style.backgroundColor='#CCFFCC'; return true;\" ".$MouseOut." title=\"Schedule an appointment for ".$hour.':'.($increment * $j<=9?'0':'').($increment * $j).".\">";
  4608. $str .= $k."</td>\n";
  4609. break;
  4610. default:
  4611. $str .= 'style="width:'.$cell_pct.'%;" '.$MouseDown." onmouseover=\"window.status='Schedule a ".$hour.':'.($increment * $j<=9?'0':'').($increment * $j)." appointment.'; this.style.backgroundColor='#CCFFCC'; return true;\" ".$MouseOut." title=\"Schedule an appointment for ".$hour.':'.($increment * $j<=9?'0':'').($increment * $j).".\">";
  4612. $str .= "&nbsp;&nbsp;</td>\n";
  4613. break;
  4614. }
  4615. $CC++;
  4616. }
  4617. }
  4618. echo $str .
  4619. "</tr>\n<tr><td class=\"matrix\" colspan=\"$cols\"></td></tr>\n";
  4620. // Add user _all_ to beginning of $participants array
  4621. array_unshift($participants, '_all_');
  4622. // Javascript for cells
  4623. $MouseOver = "onmouseover=\"this.style.backgroundColor='#CCFFCC';\"";
  4624. $MouseOut = "onmouseout=\"this.style.backgroundColor='".$CELLBG."';\"";
  4625. // Display each participant
  4626. for ( $i = 0; $i < count ( $participants ); $i++ ) {
  4627. if ($participants[$i] != '_all_') {
  4628. // Load full name of user
  4629. user_load_variables ( $participants[$i], "user_" );
  4630. // exchange space for &nbsp; to keep from breaking
  4631. $user_nospace = preg_replace ( '/\s/', '&nbsp;', $user_fullname );
  4632. } else {
  4633. $user_nospace = translate("All Attendees");
  4634. $user_nospace = preg_replace ( '/\s/', '&nbsp;', $user_nospace );
  4635. }
  4636. echo "<tr>\n<th class=\"row\" style=\"width:{$participant_pct};\">".$user_nospace."</th>\n";
  4637. $col = 1;
  4638. $viewMsg = translate ( "View this entry" );
  4639. // check each timebar
  4640. for ( $j = $first_hour; $j < $last_hour; $j++ ) {
  4641. for ( $k = 0; $k < $interval; $k++ ) {
  4642. $border = ($k == '0') ? ' border-left: 1px solid #000000;' : "";
  4643. $MouseDown = 'onmousedown="schedule_event('.$j.','.sprintf ("%02d",($increment * $k)).');"';
  4644. $RC = $CELLBG;
  4645. //$space = '';
  4646. $space = "&nbsp;";
  4647. $r = sprintf ("%02d",$j) . '.' . sprintf ("%02d", (25 * $k)).'';
  4648. if ( empty ( $master[$participants[$i]][$r] ) ) {
  4649. // ignore this..
  4650. } else if ( empty ( $master[$participants[$i]][$r]['ID'] ) ) {
  4651. // This is the first line for 'all' users. No event here.
  4652. $space = "<span class=\"matrix\"><img src=\"pix.gif\" alt=\"\" style=\"height: 8px\" /></span>";
  4653. } else if ($master[$participants[$i]][$r]['stat'] == "A") {
  4654. $space = "<a class=\"matrix\" href=\"view_entry.php?id={$master[$participants[$i]][$r]['ID']}\"><img src=\"pix.gif\" title=\"$viewMsg\" alt=\"$viewMsg\" /></a>";
  4655. } else if ($master[$participants[$i]][$r]['stat'] == "W") {
  4656. $space = "<a class=\"matrix\" href=\"view_entry.php?id={$master[$participants[$i]][$r]['ID']}\"><img src=\"pixb.gif\" title=\"$viewMsg\" alt=\"$viewMsg\" /></a>";
  4657. }
  4658. echo "<td class=\"matrixappts\" style=\"width:{$cell_pct}%;$border\" ";
  4659. if ($space == "&nbsp;") echo "$MouseDown $MouseOver $MouseOut";
  4660. echo ">$space</td>\n";
  4661. $col++;
  4662. }
  4663. }
  4664. echo "</tr><tr>\n<td class=\"matrix\" colspan=\"$cols\">" .
  4665. "<img src=\"pix.gif\" alt=\"-\" /></td></tr>\n";
  4666. } // End foreach participant
  4667. echo "</table><br />\n";
  4668. $busy = translate ("Busy");
  4669. $tentative = translate ("Tentative");
  4670. echo "<table align=\"center\"><tr><td class=\"matrixlegend\" >\n";
  4671. echo "<img src=\"pix.gif\" title=\"$busy\" alt=\"$busy\" /> $busy &nbsp; &nbsp; &nbsp;\n";
  4672. echo "<img src=\"pixb.gif\" title=\"$tentative\" alt=\"$tentative\" /> $tentative\n";
  4673. echo "</td></tr></table>\n";
  4674. }
  4675. /**
  4676. * Return the time in HHMMSS format of input time + duration
  4677. *
  4678. *
  4679. * <b>Note:</b> The gd library module needs to be available to use gradient
  4680. * images. If it is not available, a single background color will be used
  4681. * instead.
  4682. *
  4683. * @param string $time format "235900"
  4684. * @param int $duration number of minutes
  4685. *
  4686. * @return string The time in HHMMSS format
  4687. */
  4688. function add_duration ( $time, $duration ) {
  4689. $hour = (int) ( $time / 10000 );
  4690. $min = ( $time / 100 ) % 100;
  4691. $minutes = $hour * 60 + $min + $duration;
  4692. $h = $minutes / 60;
  4693. $m = $minutes % 60;
  4694. $ret = sprintf ( "%d%02d00", $h, $m );
  4695. //echo "add_duration ( $time, $duration ) = $ret <br />\n";
  4696. return $ret;
  4697. }
  4698. /**
  4699. * Return true if the user ($Login) can add an event in the calendar
  4700. *
  4701. *@param String Login
  4702. *@param String type
  4703. *@param int group
  4704. *
  4705. */
  4706. function Can_Add ($Login, $type, $group){
  4707. logs($log_file,"####### functions.php #######\n------- Can_Add -------\n");
  4708. $can_add = false;
  4709. if($type == 'user'){
  4710. $can_add = true;
  4711. }else{
  4712. if(user_project_role($Login,$group) >= 2){
  4713. $can_add = true;
  4714. }
  4715. }
  4716. return $can_add;
  4717. }
  4718. /**
  4719. * Return true if the user ($Login) can add an event in the calendar
  4720. *
  4721. *@param Int id event id
  4722. *@param String Login
  4723. *@param int project_id
  4724. *
  4725. */
  4726. function Can_Modify ($id, $Login){
  4727. logs($log_file,"####### functions.php #######\n------- Can_Modify -------\n");
  4728. //Debug
  4729. //Debug
  4730. logs($log_file,"id : ".$id." login : ".$Login."\n");
  4731. //Debug
  4732. $can_modify = false;
  4733. //Get the creator of the event
  4734. $res_cal_entry = dbi_query("SELECT cal_create_by
  4735. FROM webcal_entry
  4736. WHERE cal_id = ".$id);
  4737. $row_creator = pg_fetch_array($res_cal_entry);
  4738. $creator = $row_creator[0];
  4739. //Debug
  4740. logs($log_file,"creator".$creator."\n");
  4741. //Debug
  4742. //IF Login is the creator of the event, He can modify it
  4743. if($Login == $creator){
  4744. //Debug
  4745. logs($log_file,"login is creator \n");
  4746. //Debug
  4747. $can_modify = true;
  4748. //Else test if it's a project and if Login can modify the calendar of the project
  4749. }else{
  4750. $res_project = dbi_query("SELECT cal_name
  4751. FROM webcal_group
  4752. WHERE cal_name = '".$creator."'");
  4753. //Debug
  4754. logs($log_file,"test id is a project \n");
  4755. //Debug
  4756. //If it's a project
  4757. if(pg_num_rows($res_project) > 0){
  4758. //Debug
  4759. logs($log_file,"id is a project SQL : SELECT group_id
  4760. FROM groups
  4761. WHERE unix_group_name = '".$creator."'\n");
  4762. //Debug
  4763. //Get the Gforge id of the project
  4764. $res_id_project = dbi_query("SELECT group_id
  4765. FROM groups
  4766. WHERE unix_group_name = '".$creator."'");
  4767. $row_project_id = pg_fetch_array($res_id_project);
  4768. $project_id = $row_project_id[0];
  4769. //Debug
  4770. logs($log_file,"project id : ".$project_id." \n");
  4771. //Debug
  4772. //Test if Login can modify the calendar of the project
  4773. if(user_project_role($Login,$project_id) >=2){
  4774. $can_modify = true;
  4775. }
  4776. }
  4777. }
  4778. //Debug
  4779. logs($log_file,"------- Can_Modify -------\n####### functions.php #######\n");
  4780. //Debug
  4781. return $can_modify;
  4782. }
  4783. /**
  4784. * Return true if the user ($Login) can add an event in the calendar
  4785. *
  4786. *@param String Login
  4787. *@param String type
  4788. *@param int group
  4789. *
  4790. */
  4791. function Can_View ($Login, $type, $group){
  4792. //Debug
  4793. logs($log_file,"####### functions.php #######\n------- Can_View -------\n");
  4794. //Debug
  4795. $can_view = false;
  4796. if($type == 'user'){
  4797. $can_view = true;
  4798. }else{
  4799. if(user_project_role($Login,$group) >= 1){
  4800. $can_view = true;
  4801. }
  4802. }
  4803. return $can_view;
  4804. }
  4805. ?>