Currently, aurweb displays all dates and times in UTC time. This patch adds a capability for each logged in user to set their preferred timezone. Implements: FS#48729 Signed-off-by: Mark Weiman <mark.weiman@markzz.com> --- conf/config.proto | 1 + schema/aur-schema.sql | 1 + upgrading/4.5.0.txt | 5 +++ web/html/account.php | 3 ++ web/html/register.php | 4 ++- web/html/voters.php | 2 +- web/lib/acctfuncs.inc.php | 16 ++++++--- web/lib/aur.inc.php | 4 +++ web/lib/pkgreqfuncs.inc.php | 2 +- web/lib/timezone.inc.php | 69 ++++++++++++++++++++++++++++++++++++ web/template/account_edit_form.php | 15 ++++++++ web/template/flag_comment.php | 2 +- web/template/pkg_comments.php | 6 ++-- web/template/pkg_details.php | 6 ++-- web/template/pkgbase_details.php | 6 ++-- web/template/pkgreq_results.php | 2 +- web/template/stats/updates_table.php | 2 +- web/template/tu_details.php | 4 +-- web/template/tu_list.php | 4 +-- 19 files changed, 130 insertions(+), 24 deletions(-) create mode 100644 upgrading/4.5.0.txt create mode 100644 web/lib/timezone.inc.php diff --git a/conf/config.proto b/conf/config.proto index 96fad80..b6a414d 100644 --- a/conf/config.proto +++ b/conf/config.proto @@ -11,6 +11,7 @@ username_min_len = 3 username_max_len = 16 passwd_min_len = 4 default_lang = en +deafult_timezone = UTC sql_debug = 0 max_sessions_per_user = 8 login_timeout = 7200 diff --git a/schema/aur-schema.sql b/schema/aur-schema.sql index 30209bd..95a4373 100644 --- a/schema/aur-schema.sql +++ b/schema/aur-schema.sql @@ -32,6 +32,7 @@ CREATE TABLE Users ( ResetKey CHAR(32) NOT NULL DEFAULT '', RealName VARCHAR(64) NOT NULL DEFAULT '', LangPreference VARCHAR(6) NOT NULL DEFAULT 'en', + Timezone VARCHAR(50) NOT NULL DEFAULT 'UTC', Homepage TEXT NULL DEFAULT NULL, IRCNick VARCHAR(32) NOT NULL DEFAULT '', PGPKey VARCHAR(40) NULL DEFAULT NULL, diff --git a/upgrading/4.5.0.txt b/upgrading/4.5.0.txt new file mode 100644 index 0000000..a9c0220 --- /dev/null +++ b/upgrading/4.5.0.txt @@ -0,0 +1,5 @@ +1. Add Timezone column to Users + +--- +ALTER TABLE Users ADD COLUMN Timezone VARCHAR(50) NOT NULL DEFAULT 'UTC'; +--- \ No newline at end of file diff --git a/web/html/account.php b/web/html/account.php index 2892f04..91e5703 100644 --- a/web/html/account.php +++ b/web/html/account.php @@ -34,6 +34,7 @@ if ($action == "UpdateAccount") { in_request("U"), in_request("T"), in_request("S"), in_request("E"), in_request("H"), in_request("P"), in_request("C"), in_request("R"), in_request("L"), + in_request("TZ"), in_request("HP"), in_request("I"), in_request("K"), in_request("PK"), in_request("J"), in_request("CN"), in_request("UN"), in_request("ON"), in_request("ID"), @@ -89,6 +90,7 @@ if (isset($_COOKIE["AURSID"])) { "", $row["RealName"], $row["LangPreference"], + $row["Timezone"], $row["Homepage"], $row["IRCNick"], $row["PGPKey"], @@ -141,6 +143,7 @@ if (isset($_COOKIE["AURSID"])) { in_request("C"), in_request("R"), in_request("L"), + in_request("TZ"), in_request("HP"), in_request("I"), in_request("K"), diff --git a/web/html/register.php b/web/html/register.php index 6c6d52e..72092a7 100644 --- a/web/html/register.php +++ b/web/html/register.php @@ -31,6 +31,7 @@ if (in_request("Action") == "NewAccount") { '', in_request("R"), in_request("L"), + in_request("TZ"), in_request("HP"), in_request("I"), in_request("K"), @@ -53,6 +54,7 @@ if (in_request("Action") == "NewAccount") { '', in_request("R"), in_request("L"), + in_request("TZ"), in_request("HP"), in_request("I"), in_request("K"), @@ -64,7 +66,7 @@ if (in_request("Action") == "NewAccount") { } } else { print '<p>' . __("Use this form to create an account.") . '</p>'; - display_account_form("NewAccount", "", "", "", "", "", "", "", "", $LANG); + display_account_form("NewAccount", "", "", "", "", "", "", "", "", $LANG, "UTC"); } echo '</div>'; diff --git a/web/html/voters.php b/web/html/voters.php index 8833be1..4180933 100644 --- a/web/html/voters.php +++ b/web/html/voters.php @@ -20,7 +20,7 @@ if (has_credential(CRED_PKGBASE_LIST_VOTERS)): <li> <a href="<?= get_user_uri($row['Username']); ?>"><?= htmlspecialchars($row['Username']) ?></a> <?php if ($row["VoteTS"] > 0): ?> - (<?= gmdate("Y-m-d H:i", intval($row["VoteTS"])) ?>) + (<?= gmdate("Y-m-d H:i", tz_timestamp(intval($row["VoteTS"]))) ?>) <?php endif; ?> </li> <?php endwhile; ?> diff --git a/web/lib/acctfuncs.inc.php b/web/lib/acctfuncs.inc.php index 172b962..46dbce7 100644 --- a/web/lib/acctfuncs.inc.php +++ b/web/lib/acctfuncs.inc.php @@ -1,5 +1,4 @@ <?php - /** * Determine if an HTTP request variable is set * @@ -52,6 +51,7 @@ function html_format_pgp_fingerprint($fingerprint) { * @param string $C The confirmed password value of the displayed user * @param string $R The real name of the displayed user * @param string $L The language preference of the displayed user + * @param string $TZ The timezone preference of the displayed user * @param string $HP The homepage of the displayed user * @param string $I The IRC nickname of the displayed user * @param string $K The PGP key fingerprint of the displayed user @@ -66,7 +66,7 @@ function html_format_pgp_fingerprint($fingerprint) { * @return void */ function display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R="", - $L="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="") { + $L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="") { global $SUPPORTED_LANGS; include("account_edit_form.php"); @@ -88,6 +88,7 @@ function display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R="" * @param string $C The confirmed password for the user * @param string $R The real name of the user * @param string $L The language preference of the user + * @param string $TZ The timezone preference of the user * @param string $HP The homepage of the displayed user * @param string $I The IRC nickname of the user * @param string $K The PGP fingerprint of the user @@ -102,7 +103,7 @@ function display_account_form($A,$U="",$T="",$S="",$E="",$H="",$P="",$C="",$R="" * @return array Boolean indicating success and message to be printed */ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="", - $R="",$L="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="") { + $R="",$L="",$TZ="",$HP="",$I="",$K="",$PK="",$J="",$CN="",$UN="",$ON="",$UID=0,$N="") { global $SUPPORTED_LANGS; $error = ''; @@ -278,13 +279,14 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="" $salt = $dbh->quote($salt); $R = $dbh->quote($R); $L = $dbh->quote($L); + $TZ = $dbh->quote($TZ); $HP = $dbh->quote($HP); $I = $dbh->quote($I); $K = $dbh->quote(str_replace(" ", "", $K)); $q = "INSERT INTO Users (AccountTypeID, Suspended, "; $q.= "InactivityTS, Username, Email, Passwd, Salt, "; - $q.= "RealName, LangPreference, Homepage, IRCNick, PGPKey) "; - $q.= "VALUES (1, 0, 0, $U, $E, $P, $salt, $R, $L, "; + $q.= "RealName, LangPreference, Timezone, Homepage, IRCNick, PGPKey) "; + $q.= "VALUES (1, 0, 0, $U, $E, $P, $salt, $R, $L, $TZ "; $q.= "$HP, $I, $K)"; $result = $dbh->exec($q); if (!$result) { @@ -347,6 +349,7 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="" } $q.= ", RealName = " . $dbh->quote($R); $q.= ", LangPreference = " . $dbh->quote($L); + $q.= ", Timezone = " . $dbh->quote($TZ); $q.= ", Homepage = " . $dbh->quote($HP); $q.= ", IRCNick = " . $dbh->quote($I); $q.= ", PGPKey = " . $dbh->quote(str_replace(" ", "", $K)); @@ -359,6 +362,9 @@ function process_account_form($TYPE,$A,$U="",$T="",$S="",$E="",$H="",$P="",$C="" $ssh_key_result = account_set_ssh_keys($UID, $ssh_keys, $ssh_fingerprints); + error_log($result ? "t" : "f"); + error_log($ssh_key_result ? "t" : "f"); + error_log($q); if ($result === false || $ssh_key_result === false) { $message = __("No changes were made to the account, %s%s%s.", "<strong>", htmlspecialchars($U,ENT_QUOTES), "</strong>"); diff --git a/web/lib/aur.inc.php b/web/lib/aur.inc.php index 9015ae8..38dcdd0 100644 --- a/web/lib/aur.inc.php +++ b/web/lib/aur.inc.php @@ -18,6 +18,9 @@ include_once("cachefuncs.inc.php"); include_once("confparser.inc.php"); include_once("credentials.inc.php"); +include_once('timezone.inc.php'); +set_tz(); + /** * Check if a visitor is logged in * @@ -356,6 +359,7 @@ function uid_from_sid($sid="") { function html_header($title="", $details=array()) { global $LANG; global $SUPPORTED_LANGS; + global $TZ; include('header.php'); return; diff --git a/web/lib/pkgreqfuncs.inc.php b/web/lib/pkgreqfuncs.inc.php index 8ceac8d..e7512c1 100644 --- a/web/lib/pkgreqfuncs.inc.php +++ b/web/lib/pkgreqfuncs.inc.php @@ -172,7 +172,7 @@ function pkgreq_file($ids, $type, $merge_into, $comments) { * maintainer will not be included in the Cc list of the * request notification email. */ - $out_of_date_time = gmdate("Y-m-d", intval($details["OutOfDateTS"])); + $out_of_date_time = gmdate("Y-m-d", tz_timestamp(intval($details["OutOfDateTS"]))); pkgreq_close($request_id, "accepted", "The package base has been flagged out-of-date " . "since " . $out_of_date_time . ".", true); diff --git a/web/lib/timezone.inc.php b/web/lib/timezone.inc.php new file mode 100644 index 0000000..e69e35c --- /dev/null +++ b/web/lib/timezone.inc.php @@ -0,0 +1,69 @@ +<?php +set_include_path(get_include_path() . PATH_SEPARATOR . '../lib'); + +/** + * Generate an associative of the PHP timezones and display text. + * + * @return array PHP Timezone => Displayed Description + */ +function generate_timezone_list() { + $php_timezones = DateTimeZone::listIdentifiers(DateTimeZone::ALL); + + $offsets = array(); + foreach ($php_timezones as $timezone) { + $tz = new DateTimeZone($timezone); + $offset = $tz->getOffset(new DateTime()); + $offsets[$timezone] = "(UTC" . ($offset < 0 ? "-" : "+") . gmdate("H:i", abs($offset)) . + ") " . $timezone; + } + + asort($offsets); + return $offsets; +} + +/** + * Set the $TZ global variable. + * + * @global string $TZ Timezone set for session. + * + * @return null + */ +function set_tz() { + global $TZ; + + $timezones = generate_timezone_list(); + + if (isset($_COOKIE['AURSID'])) { + $dbh = DB::connect(); + $q = "SELECT Timezone FROM Users, Sessions "; + $q.= "WHERE Users.ID = Sessions.UsersID "; + $q.= "AND Sessions.SessionID = "; + $q.= $dbh->quote($_COOKIE['AURSID']); + $result = $dbh->query($q); + + if ($result) { + $row = $result->fetchAll(); + $TZ = $row[0][0]; + } else { + $TZ = config_get("options", "default_timezone"); + } + + if (!array_key_exists($TZ, $timezones)) { + error_log("Am I Here?"); + $TZ = config_get("options", "default_timezone"); + } + } +} + +/** + * Add the selected timezone's offset to a timestamp. + * + * @param $timestamp int Timestamp to be manipulated + * + * @return int Manipulated timestamp + */ +function tz_timestamp($timestamp) { + global $TZ; + $offset = isset($TZ) ? timezone_offset_get(new DateTimeZone($TZ), new DateTime()) : 0; + return $timestamp + $offset; +} \ No newline at end of file diff --git a/web/template/account_edit_form.php b/web/template/account_edit_form.php index 19821a0..17c9d14 100644 --- a/web/template/account_edit_form.php +++ b/web/template/account_edit_form.php @@ -129,6 +129,21 @@ ?> </select> </p> + <p> + <label for="id_timezone"><?= __("Timezone") ?></label> + <select name="TZ" id="id_timezone"> +<?php + $timezones = generate_timezone_list(); + while (list($key, $val) = each($timezones)) { + if ($TZ == $key) { + print "<option value=\"".$key."\" selected=\"selected\"> ".$val."</option>\n"; + } else { + print "<option value=\"".$key."\"> ".$val."</option>\n"; + } + } +?> + </select> + </p> </fieldset> <fieldset> diff --git a/web/template/flag_comment.php b/web/template/flag_comment.php index 36af43e..a0e91b8 100644 --- a/web/template/flag_comment.php +++ b/web/template/flag_comment.php @@ -5,7 +5,7 @@ <?= __('%s%s%s flagged %s%s%s out-of-date on %s%s%s for the following reason:', '<strong>', html_format_username($message['Username']), '</strong>', '<strong>', htmlspecialchars($pkgbase_name), '</strong>', - '<strong>', gmdate('Y-m-d', $message['OutOfDateTS']), '</strong>'); ?> + '<strong>', gmdate('Y-m-d', tz_timestamp($message['OutOfDateTS'])), '</strong>'); ?> <?php else: ?> <?= __('%s%s%s is not flagged out-of-date.', '<strong>', htmlspecialchars($pkgbase_name), '</strong>'); ?> diff --git a/web/template/pkg_comments.php b/web/template/pkg_comments.php index a28e41b..dcd6901 100644 --- a/web/template/pkg_comments.php +++ b/web/template/pkg_comments.php @@ -17,7 +17,7 @@ if (!isset($count)) { <?php while (list($indx, $row) = each($comments)): ?> <?php - $date_fmtd = gmdate('Y-m-d H:i', $row['CommentTS']); + $date_fmtd = gmdate('Y-m-d H:i', tz_timestamp($row['CommentTS'])); if ($row['UserName']) { $user_fmtd = html_format_username($row['UserName']); $heading = __('%s commented on %s', $user_fmtd, $date_fmtd); @@ -30,7 +30,7 @@ if (!isset($count)) { $is_pinned = $row['PinnedTS']; if ($uid && $is_deleted) { - $date_fmtd = gmdate('Y-m-d H:i', $row['DelTS']); + $date_fmtd = gmdate('Y-m-d H:i', tz_timestamp($row['DelTS'])); $heading .= ' <span class="edited">('; if ($row['DelUserName']) { $user_fmtd = html_format_username($row['DelUserName']); @@ -40,7 +40,7 @@ if (!isset($count)) { } $heading .= ')</span>'; } elseif ($uid && $is_edited) { - $date_fmtd = gmdate('Y-m-d H:i', $row['EditedTS']); + $date_fmtd = gmdate('Y-m-d H:i', tz_timestamp($row['EditedTS'])); $heading .= ' <span class="edited">('; if ($row['EditUserName']) { $user_fmtd = html_format_username($row['EditUserName']); diff --git a/web/template/pkg_details.php b/web/template/pkg_details.php index b9c66d4..8cca437 100644 --- a/web/template/pkg_details.php +++ b/web/template/pkg_details.php @@ -34,9 +34,9 @@ $msg = __('unknown'); $license = empty($row['License']) ? $msg : $row['License']; # Print the timestamps for last updates -$updated_time = ($row["ModifiedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", intval($row["ModifiedTS"])); -$submitted_time = ($row["SubmittedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", intval($row["SubmittedTS"])); -$out_of_date_time = ($row["OutOfDateTS"] == 0) ? $msg : gmdate("Y-m-d", intval($row["OutOfDateTS"])); +$updated_time = ($row["ModifiedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", tz_timestamp(intval($row["ModifiedTS"]))); +$submitted_time = ($row["SubmittedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", tz_timestamp(intval($row["SubmittedTS"]))); +$out_of_date_time = ($row["OutOfDateTS"] == 0) ? $msg : gmdate("Y-m-d", tz_timestamp(intval($row["OutOfDateTS"]))); $lics = pkg_licenses($row["ID"]); $grps = pkg_groups($row["ID"]); diff --git a/web/template/pkgbase_details.php b/web/template/pkgbase_details.php index 1012c4e..819ad68 100644 --- a/web/template/pkgbase_details.php +++ b/web/template/pkgbase_details.php @@ -31,9 +31,9 @@ $popularity = $row['Popularity']; $msg = __('unknown'); # Print the timestamps for last updates -$updated_time = ($row["ModifiedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", intval($row["ModifiedTS"])); -$submitted_time = ($row["SubmittedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", intval($row["SubmittedTS"])); -$out_of_date_time = ($row["OutOfDateTS"] == 0) ? $msg : gmdate("Y-m-d", intval($row["OutOfDateTS"])); +$updated_time = ($row["ModifiedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", tz_timestamp(intval($row["ModifiedTS"]))); +$submitted_time = ($row["SubmittedTS"] == 0) ? $msg : gmdate("Y-m-d H:i", tz_timestamp(intval($row["SubmittedTS"]))); +$out_of_date_time = ($row["OutOfDateTS"] == 0) ? $msg : gmdate("Y-m-d", tz_timestamp(intval($row["OutOfDateTS"]))); $pkgs = pkgbase_get_pkgnames($base_id); diff --git a/web/template/pkgreq_results.php b/web/template/pkgreq_results.php index b27963b..38f9f23 100644 --- a/web/template/pkgreq_results.php +++ b/web/template/pkgreq_results.php @@ -67,7 +67,7 @@ <td> <a href="<?= get_uri('/account/') . htmlspecialchars($row['User'], ENT_QUOTES) ?>" title="<?= __('View account information for %s', htmlspecialchars($row['User'])) ?>"><?= htmlspecialchars($row['User']) ?></a> </td> - <td<?php if ($due): ?> class="flagged"<?php endif; ?>><?= gmdate("Y-m-d H:i", intval($row['RequestTS'])) ?></td> + <td<?php if ($due): ?> class="flagged"<?php endif; ?>><?= gmdate("Y-m-d H:i", tz_timestamp(intval($row['RequestTS']))) ?></td> <?php if ($row['Open']): ?> <td> <?php if ($row['BaseID']): ?> diff --git a/web/template/stats/updates_table.php b/web/template/stats/updates_table.php index 580583b..2addf0a 100644 --- a/web/template/stats/updates_table.php +++ b/web/template/stats/updates_table.php @@ -10,7 +10,7 @@ <a href="<?= get_pkg_uri($row["Name"]); ?>" title="<?= htmlspecialchars($row["Name"]) . ' ' . htmlspecialchars($row["Version"]); ?>"><?= htmlspecialchars($row["Name"]) . ' ' . htmlspecialchars($row["Version"]); ?></a> </td> <td class="pkg-date"> - <span><?= gmdate("Y-m-d H:i", intval($row["ModifiedTS"])); ?></span> + <span><?= gmdate("Y-m-d H:i", tz_timestamp(intval($row["ModifiedTS"]))); ?></span> </td> </tr> <?php endforeach; ?> diff --git a/web/template/tu_details.php b/web/template/tu_details.php index 38f6c0d..b0f77cd 100644 --- a/web/template/tu_details.php +++ b/web/template/tu_details.php @@ -39,10 +39,10 @@ if ($yes > $active_tus / 2) { <?php endif; ?> </strong> <br /> - <?= __("Submitted: %s by %s", gmdate("Y-m-d H:i", $row['Submitted']), html_format_username(username_from_id($row['SubmitterID']))) ?> + <?= __("Submitted: %s by %s", gmdate("Y-m-d H:i", tz_timestamp($row['Submitted'])), html_format_username(username_from_id($row['SubmitterID']))) ?> <br /> <?= __("End") ?>: - <strong><?= gmdate("Y-m-d H:i", $row['End']) ?></strong> + <strong><?= gmdate("Y-m-d H:i", tz_timestamp($row['End'])) ?></strong> <?php if ($isrunning == 0): ?> <br /> <?= __("Result") ?>: diff --git a/web/template/tu_list.php b/web/template/tu_list.php index b3e1073..707169b 100644 --- a/web/template/tu_list.php +++ b/web/template/tu_list.php @@ -38,8 +38,8 @@ <td><?php $row["Agenda"] = htmlspecialchars(substr($row["Agenda"], 0, $prev_Len)); ?> <a href="<?= get_uri('/tu/'); ?>?id=<?= $row['ID'] ?>"><?= $row["Agenda"] ?></a> </td> - <td><?= gmdate("Y-m-d", $row["Submitted"]) ?></td> - <td><?= gmdate("Y-m-d", $row["End"]) ?></td> + <td><?= gmdate("Y-m-d", tz_timestamp($row["Submitted"])) ?></td> + <td><?= gmdate("Y-m-d", tz_timestamp($row["End"])) ?></td> <td> <?php if (!empty($row['User'])): ?> <a href="<?= get_uri('/packages/'); ?>?K=<?= $row['User'] ?>&SeB=m"><?= $row['User'] ?></a> -- 2.10.2