From 3e914018def1d59501a65857eb923f60f72afb79 Mon Sep 17 00:00:00 2001 From: Dries Buytaert <dries@buytaert.net> Date: Sat, 19 Feb 2011 13:24:32 +0000 Subject: [PATCH] - Patch #880278 by RoboPhred: cleanup _locale_import_read_po(). --- includes/bootstrap.inc | 25 +++- includes/locale.inc | 193 ++++++++++++++++++++------- includes/session.inc | 4 +- modules/simpletest/tests/common.test | 4 +- 4 files changed, 167 insertions(+), 59 deletions(-) diff --git a/includes/bootstrap.inc b/includes/bootstrap.inc index 0739332a4a01..a8ef38a5beeb 100644 --- a/includes/bootstrap.inc +++ b/includes/bootstrap.inc @@ -1136,6 +1136,7 @@ function drupal_serve_page_from_cache(stdClass $cache) { $etag = '"' . $cache->created . '-' . intval($return_compressed) . '"'; header('Etag: ' . $etag); + drupal_set_configured_timezone(); // See if the client has provided the required HTTP headers. $if_modified_since = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) : FALSE; $if_none_match = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : FALSE; @@ -1943,9 +1944,26 @@ function drupal_get_user_timezone() { return $user->timezone; } else { - // Ignore PHP strict notice if time zone has not yet been set in the php.ini - // configuration. - return variable_get('date_default_timezone', @date_default_timezone_get()); + // Note that is no site-wide timezone is set, and date.timezone is not set + // in php.ini, then calling date functions will cause a system call and + // PHP will issue an E_STRICT or E_WARNING error depending on PHP version. + // @todo: consider always setting the date_default_timezone variable from + // the installer. + return variable_get('date_default_timezone'); + } +} + +/** + * Set the timezone for a request when configured. + */ +function drupal_set_configured_timezone() { + $configured_timezone = drupal_get_user_timezone(); + $system_timezone = ini_get('date.timezone'); + // There is no point setting the timezone if it is configured the same + // as date.timezone in php.ini. Also date_default_timezone_set() validates + // the timezone, which relies on a system call to get the timezone database. + if ($configured_timezone != $system_timezone) { + date_default_timezone_set($configured_timezone); } } @@ -2046,7 +2064,6 @@ function _drupal_bootstrap_page_cache() { // Restore the metadata cached with the page. $_GET['q'] = $cache->data['path']; drupal_set_title($cache->data['title'], PASS_THROUGH); - date_default_timezone_set(drupal_get_user_timezone()); // If the skipping of the bootstrap hooks is not enforced, call // hook_boot. if (variable_get('page_cache_invoke_hooks', TRUE)) { diff --git a/includes/locale.inc b/includes/locale.inc index d6db7c17c6a0..9a1224842fbf 100644 --- a/includes/locale.inc +++ b/includes/locale.inc @@ -586,159 +586,250 @@ function _locale_import_po($file, $langcode, $mode, $group = NULL) { */ function _locale_import_read_po($op, $file, $mode = NULL, $lang = NULL, $group = 'default') { - $fd = fopen($file->uri, "rb"); // File will get closed by PHP on return + // The file will get closed by PHP on returning from this function. + $fd = fopen($file->uri, 'rb'); if (!$fd) { _locale_import_message('The translation import failed, because the file %filename could not be read.', $file); return FALSE; } - $context = "COMMENT"; // Parser context: COMMENT, MSGID, MSGID_PLURAL, MSGSTR and MSGSTR_ARR - $current = array(); // Current entry being read - $plural = 0; // Current plural form - $lineno = 0; // Current line + /* + * The parser context. Can be: + * - 'COMMENT' (#) + * - 'MSGID' (msgid) + * - 'MSGID_PLURAL' (msgid_plural) + * - 'MSGCTXT' (msgctxt) + * - 'MSGSTR' (msgstr or msgstr[]) + * - 'MSGSTR_ARR' (msgstr_arg) + */ + $context = 'COMMENT'; + + // Current entry being read. + $current = array(); + + // Current plurality for 'msgstr[]'. + $plural = 0; + + // Current line. + $lineno = 0; while (!feof($fd)) { - $line = fgets($fd, 10*1024); // A line should not be this long + // A line should not be longer than 10 * 1024. + $line = fgets($fd, 10 * 1024); + if ($lineno == 0) { // The first line might come with a UTF-8 BOM, which should be removed. $line = str_replace("\xEF\xBB\xBF", '', $line); } + $lineno++; + + // Trim away the linefeed. $line = trim(strtr($line, array("\\\n" => ""))); - if (!strncmp("#", $line, 1)) { // A comment - if ($context == "COMMENT") { // Already in comment context: add - $current["#"][] = substr($line, 1); + if (!strncmp('#', $line, 1)) { + // Lines starting with '#' are comments. + + if ($context == 'COMMENT') { + // Already in comment token, insert the comment. + $current['#'][] = substr($line, 1); } - elseif (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one + elseif (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) { + // We are currently in string token, close it out. _locale_import_one_string($op, $current, $mode, $lang, $file, $group); - $current = array(); - $current["#"][] = substr($line, 1); - $context = "COMMENT"; + + // Start a new entry for the comment. + $current = array(); + $current['#'][] = substr($line, 1); + + $context = 'COMMENT'; } - else { // Parse error + else { + // A comment following any other token is a syntax error. _locale_import_message('The translation file %filename contains an error: "msgstr" was expected but not found on line %line.', $file, $lineno); return FALSE; } } - elseif (!strncmp("msgid_plural", $line, 12)) { - if ($context != "MSGID") { // Must be plural form for current entry + elseif (!strncmp('msgid_plural', $line, 12)) { + // A plural form for the current message. + + if ($context != 'MSGID') { + // A plural form cannot be added to anything else but the id directly. _locale_import_message('The translation file %filename contains an error: "msgid_plural" was expected but not found on line %line.', $file, $lineno); return FALSE; } + + // Remove 'msgid_plural' and trim away whitespace. $line = trim(substr($line, 12)); + // At this point, $line should now contain only the plural form. + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The plural form must be wrapped in quotes. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $current["msgid"] = $current["msgid"] . "\0" . $quoted; - $context = "MSGID_PLURAL"; + + // Append the plural form to the current entry. + $current['msgid'] .= "\0" . $quoted; + + $context = 'MSGID_PLURAL'; } - elseif (!strncmp("msgid", $line, 5)) { - if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one + elseif (!strncmp('msgid', $line, 5)) { + // Starting a new message. + + if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) { + // We are currently in a message string, close it out. _locale_import_one_string($op, $current, $mode, $lang, $file, $group); + + // Start a new context for the id. $current = array(); } - elseif ($context == "MSGID") { // Already in this context? Parse error + elseif ($context == 'MSGID') { + // We are currently already in the context, meaning we passed an id with no data. _locale_import_message('The translation file %filename contains an error: "msgid" is unexpected on line %line.', $file, $lineno); return FALSE; } + + // Remove 'msgid' and trim away whitespace. $line = trim(substr($line, 5)); + // At this point, $line should now contain only the message id. + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The message id must be wrapped in quotes. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $current["msgid"] = $quoted; - $context = "MSGID"; + + $current['msgid'] = $quoted; + $context = 'MSGID'; } - elseif (!strncmp("msgctxt", $line, 7)) { - if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { // End current entry, start a new one + elseif (!strncmp('msgctxt', $line, 7)) { + // Starting a new context. + + if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) { + // We are currently in a message, start a new one. _locale_import_one_string($op, $current, $mode, $lang, $file, $group); $current = array(); } - elseif (!empty($current["msgctxt"])) { // Already in this context? Parse error + elseif (!empty($current['msgctxt'])) { + // A context cannot apply to another context. _locale_import_message('The translation file %filename contains an error: "msgctxt" is unexpected on line %line.', $file, $lineno); return FALSE; } + + // Remove 'msgctxt' and trim away whitespaces. $line = trim(substr($line, 7)); + // At this point, $line should now contain the context. + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The context string must be quoted. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $current["msgctxt"] = $quoted; - $context = "MSGCTXT"; + + $current['msgctxt'] = $quoted; + + $context = 'MSGCTXT'; } - elseif (!strncmp("msgstr[", $line, 7)) { - if (($context != "MSGID") && ($context != "MSGCTXT") && ($context != "MSGID_PLURAL") && ($context != "MSGSTR_ARR")) { // Must come after msgid, msgxtxt, msgid_plural, or msgstr[] + elseif (!strncmp('msgstr[', $line, 7)) { + // A message string for a specific plurality. + + if (($context != 'MSGID') && ($context != 'MSGCTXT') && ($context != 'MSGID_PLURAL') && ($context != 'MSGSTR_ARR')) { + // Message strings must come after msgid, msgxtxt, msgid_plural, or other msgstr[] entries. _locale_import_message('The translation file %filename contains an error: "msgstr[]" is unexpected on line %line.', $file, $lineno); return FALSE; } - if (strpos($line, "]") === FALSE) { + + // Ensure the plurality is terminated. + if (strpos($line, ']') === FALSE) { _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $frombracket = strstr($line, "["); - $plural = substr($frombracket, 1, strpos($frombracket, "]") - 1); + + // Extract the plurality. + $frombracket = strstr($line, '['); + $plural = substr($frombracket, 1, strpos($frombracket, ']') - 1); + + // Skip to the next whitespace and trim away any further whitespace, bringing $line to the message data. $line = trim(strstr($line, " ")); + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The string must be quoted. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $current["msgstr"][$plural] = $quoted; - $context = "MSGSTR_ARR"; + + $current['msgstr'][$plural] = $quoted; + + $context = 'MSGSTR_ARR'; } elseif (!strncmp("msgstr", $line, 6)) { - if (($context != "MSGID") && ($context != "MSGCTXT")) { // Should come just after a msgid or msgctxt block + // A string for the an id or context. + + if (($context != 'MSGID') && ($context != 'MSGCTXT')) { + // Strings are only valid within an id or context scope. _locale_import_message('The translation file %filename contains an error: "msgstr" is unexpected on line %line.', $file, $lineno); return FALSE; } + + // Remove 'msgstr' and trim away away whitespaces. $line = trim(substr($line, 6)); + // At this point, $line should now contain the message. + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The string must be quoted. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - $current["msgstr"] = $quoted; - $context = "MSGSTR"; + + $current['msgstr'] = $quoted; + + $context = 'MSGSTR'; } - elseif ($line != "") { + elseif ($line != '') { + // Anything that is not a token may be a continuation of a previous token. + $quoted = _locale_import_parse_quoted($line); if ($quoted === FALSE) { + // The string must be quoted. _locale_import_message('The translation file %filename contains a syntax error on line %line.', $file, $lineno); return FALSE; } - if (($context == "MSGID") || ($context == "MSGID_PLURAL")) { - $current["msgid"] .= $quoted; + + // Append the string to the current context. + if (($context == 'MSGID') || ($context == 'MSGID_PLURAL')) { + $current['msgid'] .= $quoted; } - elseif ($context == "MSGCTXT") { - $current["msgctxt"] .= $quoted; + elseif ($context == 'MSGCTXT') { + $current['msgctxt'] .= $quoted; } - elseif ($context == "MSGSTR") { - $current["msgstr"] .= $quoted; + elseif ($context == 'MSGSTR') { + $current['msgstr'] .= $quoted; } - elseif ($context == "MSGSTR_ARR") { - $current["msgstr"][$plural] .= $quoted; + elseif ($context == 'MSGSTR_ARR') { + $current['msgstr'][$plural] .= $quoted; } else { + // No valid context to append to. _locale_import_message('The translation file %filename contains an error: there is an unexpected string on line %line.', $file, $lineno); return FALSE; } } } - // End of PO file, flush last entry. - if (($context == "MSGSTR") || ($context == "MSGSTR_ARR")) { + // End of PO file, closed out the last entry. + if (($context == 'MSGSTR') || ($context == 'MSGSTR_ARR')) { _locale_import_one_string($op, $current, $mode, $lang, $file, $group); } - elseif ($context != "COMMENT") { + elseif ($context != 'COMMENT') { _locale_import_message('The translation file %filename ended unexpectedly at line %line.', $file, $lineno); return FALSE; } - } /** diff --git a/includes/session.inc b/includes/session.inc index 23af6bd64193..478079b4f57c 100644 --- a/includes/session.inc +++ b/includes/session.inc @@ -259,7 +259,7 @@ function drupal_session_initialize() { // a user becomes authenticated. session_id(drupal_hash_base64(uniqid(mt_rand(), TRUE))); } - date_default_timezone_set(drupal_get_user_timezone()); + drupal_set_configured_timezone(); } /** @@ -387,7 +387,7 @@ function drupal_session_regenerate() { drupal_session_start(); $user = $account; } - date_default_timezone_set(drupal_get_user_timezone()); + drupal_set_configured_timezone(); } /** diff --git a/modules/simpletest/tests/common.test b/modules/simpletest/tests/common.test index f48497559a77..52a8a7fe2ee8 100644 --- a/modules/simpletest/tests/common.test +++ b/modules/simpletest/tests/common.test @@ -2226,7 +2226,7 @@ class FormatDateUnitTest extends DrupalWebTestCase { $real_language = $language->language; $language->language = $user->language; // Simulate a Drupal bootstrap with the logged-in user. - date_default_timezone_set(drupal_get_user_timezone()); + drupal_set_configured_timezone(); $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'America/Los_Angeles', 'en'), 'Sunday, 25-Mar-07 17:00:00 PDT', t('Test a different language.')); $this->assertIdentical(format_date($timestamp, 'custom', 'l, d-M-y H:i:s T', 'Europe/London'), 'Monday, 26-Mar-07 01:00:00 BST', t('Test a different time zone.')); @@ -2240,7 +2240,7 @@ class FormatDateUnitTest extends DrupalWebTestCase { $user = $real_user; $language->language = $real_language; // Restore default time zone. - date_default_timezone_set(drupal_get_user_timezone()); + drupal_set_configured_timezone(); drupal_save_session(TRUE); } } -- GitLab