--- C:\Users\Edward\Webs\drupal\includes\common.inc 2008-01-15 23:26:00.086000000 -0500 +++ C:\Users\Edward\Webs\drupal\includes\common.inc.formatted 2008-01-16 17:40:02.089957100 -0500 @@ -1,6 +1,7 @@ 'alternate', - 'type' => 'application/rss+xml', - 'title' => $title, - 'href' => $url)); + 'type' => 'application/rss+xml', + 'title' => $title, + 'href' => $url)); } return $stored_feed_links; } @@ -200,22 +201,23 @@ * nested items. * @param $parent * Should not be passed, only used in recursive calls. + * * @return * An urlencoded string which can be appended to/as the URL query string. */ function drupal_query_string_encode($query, $exclude = array(), $parent = '') { $params = array(); - + foreach ($query as $key => $value) { $key = drupal_urlencode($key); if ($parent) { $key = $parent .'['. $key .']'; } - + if (in_array($key, $exclude)) { continue; } - + if (is_array($value)) { $params[] = drupal_query_string_encode($value, $exclude, $key); } @@ -223,7 +225,7 @@ $params[] = $key .'='. drupal_urlencode($value); } } - + return implode('&', $params); } @@ -294,30 +296,30 @@ * @see drupal_get_destination() */ function drupal_goto($path = '', $query = NULL, $fragment = NULL, $http_response_code = 302) { - + if (isset($_REQUEST['destination'])) { extract(parse_url(urldecode($_REQUEST['destination']))); } else if (isset($_REQUEST['edit']['destination'])) { extract(parse_url(urldecode($_REQUEST['edit']['destination']))); } - + $url = url($path, array('query' => $query, 'fragment' => $fragment, 'absolute' => TRUE)); // Remove newlines from the URL to avoid header injection attacks. $url = str_replace(array("\n", "\r"), '', $url); - + // Allow modules to react to the end of the page request before redirecting. // We do not want this while running update.php. if (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') { module_invoke_all('exit', $url); } - + // Even though session_write_close() is registered as a shutdown function, we // need all session data written to the database before redirecting. session_write_close(); - + header('Location: '. $url, TRUE, $http_response_code); - + // The "Location" header sends a redirect status code to the HTTP daemon. In // some cases this can be wrong, so we make sure none of the code below the // drupal_goto() call gets executed upon redirection. @@ -332,7 +334,7 @@ drupal_set_header('HTTP/1.1 503 Service unavailable'); drupal_set_title(t('Site off-line')); print theme('maintenance_page', filter_xss_admin(variable_get('site_offline_message', - t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))))); + t('@site is currently under maintenance. We should be back shortly. Thank you for your patience.', array('@site' => variable_get('site_name', 'Drupal')))))); } /** @@ -340,14 +342,14 @@ */ function drupal_not_found() { drupal_set_header('HTTP/1.1 404 Not Found'); - + watchdog('page not found', check_plain($_GET['q']), NULL, WATCHDOG_WARNING); - + // Keep old path for reference. if (!isset($_REQUEST['destination'])) { $_REQUEST['destination'] = $_GET['q']; } - + $path = drupal_get_normal_path(variable_get('site_404', '')); if ($path && $path != $_GET['q']) { // Set the active item in case there are tabs to display, or other @@ -355,12 +357,12 @@ menu_set_active_item($path); $return = menu_execute_active_handler($path); } - + if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) { drupal_set_title(t('Page not found')); $return = t('The requested page could not be found.'); } - + // To conserve CPU and bandwidth, omit the blocks. print theme('page', $return, FALSE); } @@ -371,12 +373,12 @@ function drupal_access_denied() { drupal_set_header('HTTP/1.1 403 Forbidden'); watchdog('access denied', check_plain($_GET['q']), NULL, WATCHDOG_WARNING); - + // Keep old path for reference. if (!isset($_REQUEST['destination'])) { $_REQUEST['destination'] = $_GET['q']; } - + $path = drupal_get_normal_path(variable_get('site_403', '')); if ($path && $path != $_GET['q']) { // Set the active item in case there are tabs to display or other @@ -384,7 +386,7 @@ menu_set_active_item($path); $return = menu_execute_active_handler($path); } - + if (empty($return) || $return == MENU_NOT_FOUND || $return == MENU_ACCESS_DENIED) { drupal_set_title(t('Access denied')); $return = t('You are not authorized to access this page.'); @@ -409,6 +411,7 @@ * @param $retry * An integer representing how many times to retry the request in case of a * redirect. + * * @return * An object containing the HTTP request headers, response code, headers, * data and redirect status. @@ -422,7 +425,7 @@ // some parsing has failed. if (!$self_test && variable_get('drupal_http_request_fails', FALSE)) { $self_test = TRUE; - $works = module_invoke('system', 'check_http_request'); + $works = module_invoke('system', 'check_http_request'); $self_test = FALSE; if (!$works) { // Do not bother with further operations if we already know that we @@ -431,27 +434,29 @@ return $result; } } - + // Parse the URL and make sure we can handle the schema. $uri = parse_url($url); - + switch ($uri['scheme']) { case 'http': $port = isset($uri['port']) ? $uri['port'] : 80; $host = $uri['host'] . ($port != 80 ? ':'. $port : ''); - $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); + $fp = @fsockopen($uri['host'], $port, $errno, $errstr, 15); break; + case 'https': // Note: Only works for PHP 4.3 compiled with OpenSSL. $port = isset($uri['port']) ? $uri['port'] : 443; $host = $uri['host'] . ($port != 443 ? ':'. $port : ''); - $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); + $fp = @fsockopen('ssl://'. $uri['host'], $port, $errno, $errstr, 20); break; + default: $result->error = 'invalid schema '. $uri['scheme']; return $result; } - + // Make sure the socket opened properly. if (!$fp) { // When a network error occurs, we use a negative number so it does not @@ -460,13 +465,13 @@ $result->error = trim($errstr); return $result; } - + // Construct the path to act on. $path = isset($uri['path']) ? $uri['path'] : '/'; if (isset($uri['query'])) { $path .= '?'. $uri['query']; } - + // Create HTTP request. $defaults = array( // RFC 2616: "non-standard ports MUST, default ports MAY be included". @@ -474,18 +479,18 @@ // host that do not take into account the port number. 'Host' => "Host: $host", 'User-Agent' => 'User-Agent: Drupal (+http://drupal.org/)', - 'Content-Length' => 'Content-Length: '. strlen($data) + 'Content-Length' => 'Content-Length: '. strlen($data), ); - + // If the server url has a user then attempt to use basic authentication if (isset($uri['user'])) { $defaults['Authorization'] = 'Authorization: Basic '. base64_encode($uri['user'] . (!empty($uri['pass']) ? ":". $uri['pass'] : '')); } - + foreach ($headers as $header => $value) { $defaults[$header] = $header .': '. $value; } - + $request = $method .' '. $path ." HTTP/1.0\r\n"; $request .= implode("\r\n", $defaults); $request .= "\r\n\r\n"; @@ -493,23 +498,23 @@ $request .= $data ."\r\n"; } $result->request = $request; - + fwrite($fp, $request); - + // Fetch response. $response = ''; while (!feof($fp) && $chunk = fread($fp, 1024)) { $response .= $chunk; } fclose($fp); - + // Parse response. list($split, $result->data) = explode("\r\n\r\n", $response, 2); $split = preg_split("/\r\n|\n|\r/", $split); - + list($protocol, $code, $text) = explode(' ', trim(array_shift($split)), 3); $result->headers = array(); - + // Parse headers. while ($line = trim(array_shift($split))) { list($header, $value) = explode(':', $line, 2); @@ -522,43 +527,50 @@ $result->headers[$header] = trim($value); } } - + $responses = array( 100 => 'Continue', 101 => 'Switching Protocols', 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 307 => 'Temporary Redirect', 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', - 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported' + 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', ); // RFC 2616 states that all unknown HTTP codes must be treated the same as the // base code in their class. if (!isset($responses[$code])) { $code = floor($code / 100) * 100; } - + switch ($code) { - case 200: // OK - case 304: // Not modified + case 200: + // OK + case 304: + // Not modified break; - case 301: // Moved permanently - case 302: // Moved temporarily - case 307: // Moved temporarily + + case 301: + // Moved permanently + case 302: + // Moved temporarily + case 307: + // Moved temporarily $location = $result->headers['Location']; - + if ($retry) { $result = drupal_http_request($result->headers['Location'], $headers, $method, $data, --$retry); $result->redirect_code = $result->code; } $result->redirect_url = $location; - break; + default: $result->error = $text; } - + $result->code = $code; return $result; } + /** * @} End of "HTTP handling". */ @@ -576,18 +588,18 @@ if (error_reporting() == 0) { return; } - + if ($errno & (E_ALL)) { $types = array(1 => 'error', 2 => 'warning', 4 => 'parse error', 8 => 'notice', 16 => 'core error', 32 => 'core warning', 64 => 'compile error', 128 => 'compile warning', 256 => 'user error', 512 => 'user warning', 1024 => 'user notice', 2048 => 'strict warning', 4096 => 'recoverable fatal error'); - + // For database errors, we want the line number/file name of the place that // the query was originally called, not _db_query(). if (isset($context[DB_ERROR])) { $backtrace = array_reverse(debug_backtrace()); - + // List of functions where SQL queries can originate. $query_functions = array('db_query', 'pager_query', 'db_query_range', 'db_query_temporary', 'update_sql'); - + // Determine where query function was called, and adjust line/file // accordingly. foreach ($backtrace as $index => $function) { @@ -598,14 +610,14 @@ } } } - + $entry = $types[$errno] .': '. $message .' in '. $filename .' on line '. $line .'.'; - + // Force display of error messages in update.php. if (variable_get('error_level', 1) == 1 || strstr($_SERVER['SCRIPT_NAME'], 'update.php')) { drupal_set_message($entry, 'error'); } - + watchdog('php', '%message in %file on line %line.', array('%error' => $types[$errno], '%message' => $message, '%file' => $filename, '%line' => $line), WATCHDOG_ERROR); } } @@ -747,15 +759,16 @@ * @param $langcode * Optional language code to translate to a language other than what is used * to display the page. + * * @return * The translated string. */ function t($string, $args = array(), $langcode = NULL) { global $language; static $custom_strings; - + $langcode = isset($langcode) ? $langcode : $language->language; - + // First, check for an array of customized strings. If present, use the array // *instead of* database lookups. This is a high performance way to provide a // handful of string replacements. See settings.php for examples. @@ -782,13 +795,13 @@ // Escaped only. $args[$key] = check_plain($value); break; - + case '%': default: // Escaped and placeholder. $args[$key] = theme('placeholder', $value); break; - + case '!': // Pass-through. } @@ -810,15 +823,16 @@ * * @param $mail * A string containing an e-mail address. + * * @return * TRUE if the address is in a valid format. */ function valid_email_address($mail) { - $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+'; + $user = '[a-zA-Z0-9_\-\.\+\^!#\$%&*+\/\=\?\`\|\{\}~\']+'; $domain = '(?:(?:[a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.?)+'; - $ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}'; - $ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}'; - + $ipv4 = '[0-9]{1,3}(\.[0-9]{1,3}){3}'; + $ipv6 = '[0-9a-fA-F]{1,4}(\:[0-9a-fA-F]{1,4}){7}'; + return preg_match("/^$user@($domain|(\[($ipv4|$ipv6)\]))$/", $mail); } @@ -832,6 +846,7 @@ * The URL to verify. * @param $absolute * Whether the URL is absolute (beginning with a scheme such as "http:"). + * * @return * TRUE if the URL is in a valid format. */ @@ -865,6 +880,7 @@ * The name of the event. * @param $number * The maximum number of the specified event per hour (per visitor). + * * @return * True if the user did not exceed the hourly threshold. False otherwise. */ @@ -898,11 +914,11 @@ function format_rss_channel($title, $link, $description, $items, $langcode = NULL, $args = array()) { global $language; $langcode = $langcode ? $langcode : $language->language; - + $output = "\n"; $output .= ' '. check_plain($title) ."\n"; $output .= ' '. check_url($link) ."\n"; - + // The RSS 2.0 "spec" doesn't indicate HTML can be used in the description. // We strip all HTML tags, but need to prevent double encoding from properly // escaped source data (such as & becoming &amp;). @@ -911,7 +927,7 @@ $output .= format_xml_elements($args); $output .= $items; $output .= "\n"; - + return $output; } @@ -927,7 +943,7 @@ $output .= ' '. check_plain($description) ."\n"; $output .= format_xml_elements($args); $output .= "\n"; - + return $output; } @@ -954,7 +970,7 @@ if (isset($value['attributes']) && is_array($value['attributes'])) { $output .= drupal_attributes($value['attributes']); } - + if ($value['value'] != '') { $output .= '>'. (is_array($value['value']) ? format_xml_elements($value['value']) : check_plain($value['value'])) .'\n"; } @@ -1013,6 +1029,7 @@ * @param $langcode * Optional language code to translate to a language other than * what is used to display the page. + * * @return * A translated string. */ @@ -1021,7 +1038,7 @@ if ($count == 1) { return t($singular, $args, $langcode); } - + // Get the plural index through the gettext formula. $index = (function_exists('locale_get_plural')) ? locale_get_plural($count, $langcode) : -1; // Backwards compatibility. @@ -1032,8 +1049,10 @@ switch ($index) { case "0": return t($singular, $args, $langcode); + case "1": return t($plural, $args, $langcode); + default: unset($args['@count']); $args['@count['. $index .']'] = $count; @@ -1048,6 +1067,7 @@ * @param $size * A size expressed as a number of bytes with optional SI size and unit * suffix (e.g. 2, 3K, 5MB, 10G). + * * @return * An integer representation of the size. */ @@ -1055,8 +1075,10 @@ $suffixes = array( '' => 1, 'k' => 1024, - 'm' => 1048576, // 1024 * 1024 - 'g' => 1073741824, // 1024 * 1024 * 1024 + // 1024 * 1024 + 'm' => 1048576, + // 1024 * 1024 * 1024 + 'g' => 1073741824, ); if (preg_match('/([0-9]+)\s*(k|m|g)?(b?(ytes?)?)/i', $size, $match)) { return $match[1] * $suffixes[drupal_strtolower($match[2])]; @@ -1071,6 +1093,7 @@ * @param $langcode * Optional language code to translate to a language other than what is used * to display the page. + * * @return * A translated string representation of the size. */ @@ -1099,6 +1122,7 @@ * @param $langcode * Optional language code to translate to a language other than * what is used to display the page. + * * @return * A translated string representation of the interval. */ @@ -1112,7 +1136,7 @@ $timestamp %= $value; $granularity--; } - + if ($granularity == 0) { break; } @@ -1141,6 +1165,7 @@ * @param $langcode * Optional language code to translate to a language other than what is used * to display the page. + * * @return * A translated date string in the requested format. */ @@ -1154,24 +1179,27 @@ $timezone = variable_get('date_default_timezone', 0); } } - + $timestamp += $timezone; - + switch ($type) { case 'small': $format = variable_get('date_format_short', 'm/d/Y - H:i'); break; + case 'large': $format = variable_get('date_format_long', 'l, F j, Y - H:i'); break; + case 'custom': // No change to format. break; + case 'medium': default: $format = variable_get('date_format_medium', 'D, m/d/Y - H:i'); } - + $max = strlen($format); $date = ''; for ($i = 0; $i < $max; $i++) { @@ -1204,7 +1232,7 @@ $date .= $c; } } - + return $date; } @@ -1244,6 +1272,7 @@ * 'prefix' * Only used internally, to modify the path when a language dependent URL * requires so. + * * @return * A string containing a URL to the given path. * @@ -1257,7 +1286,7 @@ 'query' => '', 'absolute' => FALSE, 'alias' => FALSE, - 'prefix' => '' + 'prefix' => '', ); if (!isset($options['external'])) { // Return an external link if $path contains an allowed absolute URL. @@ -1266,7 +1295,7 @@ $colonpos = strpos($path, ':'); $options['external'] = ($colonpos !== FALSE && !preg_match('![/?#]!', substr($path, 0, $colonpos)) && filter_xss_bad_protocol($path, FALSE) == check_plain($path)); } - + // May need language dependent rewriting if language.inc is present. if (function_exists('language_url_rewrite')) { language_url_rewrite($path, $options); @@ -1277,7 +1306,7 @@ if (is_array($options['query'])) { $options['query'] = drupal_query_string_encode($options['query']); } - + if ($options['external']) { // Split off the fragment. if (strpos($path, '#') !== FALSE) { @@ -1293,32 +1322,32 @@ // Reassemble. return $path . $options['fragment']; } - + global $base_url; static $script; static $clean_url; - + if (!isset($script)) { // On some web servers, such as IIS, we can't omit "index.php". So, we // generate "index.php?q=foo" instead of "?q=foo" on anything that is not // Apache. $script = (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') === FALSE) ? 'index.php' : ''; } - + // Cache the clean_url variable to improve performance. if (!isset($clean_url)) { $clean_url = (bool)variable_get('clean_url', '0'); } - + if (!isset($options['base_url'])) { // The base_url might be rewritten from the language rewrite in domain mode. $options['base_url'] = $base_url; } $base = $options['absolute'] ? $options['base_url'] .'/' : base_path(); - + // Preserve the original path before aliasing. $original_path = $path; - + // The special path '' links to the default front page. if (!empty($path) && $path != '') { if (!$options['alias']) { @@ -1334,7 +1363,7 @@ // Will be empty if there is no language prefix. $path = trim($options['prefix'], '/'); } - + if ($clean_url) { // With Clean URLs. if ($options['query']) { @@ -1367,6 +1396,7 @@ * * @param $attributes * An associative array of HTML attributes. + * * @return * An HTML string ready for insertion in a tag. */ @@ -1420,16 +1450,17 @@ * escaped HTML. * 'alias' (default FALSE) * Whether the given path is an alias already. + * * @return * an HTML string containing a link to the given path. */ function l($text, $path, $options = array()) { // Merge in defaults. $options += array( - 'attributes' => array(), - 'html' => FALSE, - ); - + 'attributes' => array(), + 'html' => FALSE, + ); + // Append active class. if ($path == $_GET['q'] || ($path == '' && drupal_is_front_page())) { if (isset($options['attributes']['class'])) { @@ -1439,13 +1470,13 @@ $options['attributes']['class'] = 'active'; } } - + // Remove all HTML and PHP tags from a tooltip. For best performance, we act only // if a quick strpos() pre-check gave a suspicion (because strip_tags() is expensive). if (isset($options['attributes']['title']) && strpos($options['attributes']['title'], '<') !== FALSE) { $options['attributes']['title'] = strip_tags($options['attributes']['title']); } - + return ''. ($options['html'] ? $text : check_plain($text)) .''; } @@ -1459,7 +1490,7 @@ if (variable_get('cache', CACHE_DISABLED) != CACHE_DISABLED) { page_set_cache(); } - + module_invoke_all('exit'); } @@ -1509,16 +1540,17 @@ * * @param $code * The code to evaluate. + * * @return * A string containing the printed output of the code, followed by the returned * output of the code. */ function drupal_eval($code) { global $theme_path, $theme_info, $conf; - + // Store current theme path. $old_theme_path = $theme_path; - + // Restore theme_path to the theme, as long as drupal_eval() executes, // so code evaluted will not see the caller module as the current theme. // If theme info is not initialized get the path from theme_default. @@ -1528,15 +1560,15 @@ else { $theme_path = dirname($theme_info->filename); } - + ob_start(); print eval('?>'. $code); $output = ob_get_contents(); ob_end_clean(); - + // Recover original theme path. $theme_path = $old_theme_path; - + return $output; } @@ -1633,13 +1665,14 @@ * * Typical candidates for caching are for example styles for nodes across * the site, or used in the theme. + * * @return * An array of CSS files. */ function drupal_add_css($path = NULL, $type = 'module', $media = 'all', $preprocess = TRUE) { static $css = array(); global $language; - + // Create an array of CSS files for each media type first, since each type needs to be served // to the browser differently. if (isset($path)) { @@ -1647,7 +1680,7 @@ if (!isset($css[$media])) { $css[$media] = array('module' => array(), 'theme' => array()); } - + // If a theme is adding the current stylesheet, check for any existing CSS files // with the same name. If they exist, remove them and allow the theme's own CSS // file to replace it. @@ -1656,7 +1689,7 @@ // Match by style sheet name. if (basename($path) == basename($old_path)) { unset($css[$media]['module'][$old_path]); - + // If the current language is RTL and the CSS file had an RTL variant, // pull out the original. The theme must provide its own RTL style. if (defined('LANGUAGE_RTL') && $language->direction == LANGUAGE_RTL) { @@ -1672,7 +1705,7 @@ } } $css[$media][$type][$path] = $preprocess; - + // If the current language is RTL, add the CSS file with RTL overrides. if (defined('LANGUAGE_RTL') && $language->direction == LANGUAGE_RTL) { $rtl_path = str_replace('.css', '-rtl.css', $path); @@ -1681,7 +1714,7 @@ } } } - + return $css; } @@ -1695,6 +1728,7 @@ * @param $css * (optional) An array of CSS files. If no array is provided, the default * stylesheets array is used instead. + * * @return * A string of XHTML CSS tags. */ @@ -1705,17 +1739,17 @@ } $no_module_preprocess = ''; $no_theme_preprocess = ''; - + $preprocess_css = (variable_get('preprocess_css', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')); $directory = file_directory_path(); $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC); - + // A dummy query-string is added to filenames, to gain control over // browser-caching. The string changes on every update or full cache // flush, forcing browsers to load a new copy of the files, as the // URL changed. $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1); - + foreach ($css as $media => $types) { // If CSS preprocessing is off, we still need to output the styles. // Additionally, go through any remaining styles if CSS preprocessing is on and output the non-cached ones. @@ -1738,14 +1772,14 @@ } } } - + if ($is_writable && $preprocess_css) { $filename = md5(serialize($types) . $query_string) .'.css'; $preprocess_file = drupal_build_css_cache($types, $filename); $output .= ''."\n"; } } - + return $no_module_preprocess . $output . $no_theme_preprocess; } @@ -1757,16 +1791,17 @@ * compress into one file. * @param $filename * The name of the aggregate CSS file. + * * @return * The name of the CSS file. */ function drupal_build_css_cache($types, $filename) { $data = ''; - + // Create the css/ within the files folder. $csspath = file_create_path('css'); file_check_directory($csspath, FILE_CREATE_DIRECTORY); - + if (!file_exists($csspath .'/'. $filename)) { // Build aggregate CSS file. foreach ($types as $type) { @@ -1781,14 +1816,14 @@ } } } - + // Per the W3C specification at http://www.w3.org/TR/REC-CSS2/cascade.html#at-import, // @import rules must proceed any other style, so we move those to the top. $regexp = '/@import[^;]+;/i'; preg_match_all($regexp, $data, $matches); $data = preg_replace($regexp, '', $data); $data = implode('', $matches[0]) . $data; - + // Create the CSS file. file_save_data($data, $csspath .'/'. $filename, FILE_EXISTS_REPLACE); } @@ -1806,7 +1841,7 @@ if (isset($base)) { $_base = $base; } - + // Prefix with base and remove '../' segments where possible. $path = $_base . $matches[1]; $last = ''; @@ -1832,6 +1867,7 @@ * Name of the stylesheet to be processed. * @param $optimize * Defines if CSS contents should be compressed or not. + * * @return * Contents of the stylesheet including the imported stylesheets. */ @@ -1841,22 +1877,22 @@ if (isset($optimize)) { $_optimize = $optimize; } - + $contents = ''; if (file_exists($file)) { // Load the local CSS stylesheet. $contents = file_get_contents($file); - + // Change to the current stylesheet's directory. $cwd = getcwd(); chdir(dirname($file)); - + // Replaces @import commands with the actual stylesheet content. // This happens recursively but omits external files. $contents = preg_replace_callback('/@import\s*(?:url\()?[\'"]?(?![a-z]+:)([^\'"\()]+)[\'"]?\)?;/', '_drupal_load_stylesheet', $contents); // Remove multiple charset declarations for standards compliance (and fixing Safari problems). $contents = preg_replace('/^@charset\s+[\'"](\S*)\b[\'"];/i', '', $contents); - + if ($_optimize) { // Perform some safe CSS optimizations. $contents = preg_replace('< @@ -1865,11 +1901,11 @@ [\n\r] # Remove line breaks. >x', '\1', $contents); } - + // Change back directory. chdir($cwd); } - + return $contents; } @@ -1945,6 +1981,7 @@ * @param $preprocess * (optional) Should this JS file be aggregated if this * feature has been turned on under the performance section? + * * @return * If the first parameter is NULL, the JavaScript array that has been built so * far for $scope is returned. If the first three parameters are NULL, @@ -1952,9 +1989,9 @@ */ function drupal_add_js($data = NULL, $type = 'module', $scope = 'header', $defer = FALSE, $cache = TRUE, $preprocess = TRUE) { static $javascript = array(); - + if (isset($data)) { - + // Add jquery.js and drupal.js, as well as the basePath setting, the // first time a Javascript file is added. if (empty($javascript)) { @@ -1971,30 +2008,32 @@ 'inline' => array(), ); } - + if (isset($scope) && !isset($javascript[$scope])) { $javascript[$scope] = array('core' => array(), 'module' => array(), 'theme' => array(), 'setting' => array(), 'inline' => array()); } - + if (isset($type) && isset($scope) && !isset($javascript[$scope][$type])) { $javascript[$scope][$type] = array(); } - + switch ($type) { case 'setting': $javascript[$scope][$type][] = $data; break; + case 'inline': $javascript[$scope][$type][] = array('code' => $data, 'defer' => $defer); break; + default: // If cache is FALSE, don't preprocess the JS file. $javascript[$scope][$type][$data] = array('cache' => $cache, 'defer' => $defer, 'preprocess' => (!$cache ? FALSE : $preprocess)); } } - + if (isset($scope)) { - + if (isset($javascript[$scope])) { return $javascript[$scope]; } @@ -2021,6 +2060,7 @@ * @parameter $javascript * (optional) An array with all JavaScript code. Defaults to the default * JavaScript array for the given scope. + * * @return * All JavaScript code segments and includes for the scope as HTML tags. */ @@ -2028,23 +2068,23 @@ if ((!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update') && function_exists('locale_update_js_files')) { locale_update_js_files(); } - + if (!isset($javascript)) { $javascript = drupal_add_js(NULL, NULL, $scope); } - + if (empty($javascript)) { return ''; } - - $output = ''; - $preprocessed = ''; + + $output = ''; + $preprocessed = ''; $no_preprocess = array('core' => '', 'module' => '', 'theme' => ''); - $files = array(); + $files = array(); $preprocess_js = (variable_get('preprocess_js', FALSE) && (!defined('MAINTENANCE_MODE') || MAINTENANCE_MODE != 'update')); - $directory = file_directory_path(); - $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC); - + $directory = file_directory_path(); + $is_writable = is_dir($directory) && is_writable($directory) && (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC); + // A dummy query-string is added to filenames, to gain control over // browser-caching. The string changes on every update or full cache // flush, forcing browsers to load a new copy of the files, as the @@ -2052,20 +2092,22 @@ // get time() as query-string instead, to enforce reload on every // page request. $query_string = '?'. substr(variable_get('css_js_query_string', '0'), 0, 1); - + foreach ($javascript as $type => $data) { - + if (!$data) continue; - + switch ($type) { case 'setting': $output .= '\n"; break; + case 'inline': foreach ($data as $info) { $output .= '\n"; } break; + default: // If JS preprocessing is off, we still need to output the scripts. // Additionally, go through any remaining scripts if JS preprocessing is on and output the non-cached ones. @@ -2079,18 +2121,18 @@ } } } - + // Aggregate any remaining JS files that haven't already been output. if ($is_writable && $preprocess_js && count($files) > 0) { $filename = md5(serialize($files) . $query_string) .'.js'; $preprocess_file = drupal_build_js_cache($files, $filename); $preprocessed .= ''."\n"; } - + // Keep the order of JS files consistent as some are preprocessed and others are not. // Make sure any inline or JS setting variables appear last after libraries have loaded. $output = $preprocessed . implode('', $no_preprocess) . $output; - + return $output; } @@ -2207,7 +2249,7 @@ drupal_add_js('misc/tabledrag.js', 'core'); $js_added = TRUE; } - + // If a subgroup or source isn't set, assume it is the same as the group. $target = isset($subgroup) ? $subgroup : $group; $source = isset($source) ? $source : $target; @@ -2229,16 +2271,17 @@ * An array of JS files to aggregate and compress into one file. * @param $filename * The name of the aggregate JS file. + * * @return * The name of the JS file. */ function drupal_build_js_cache($files, $filename) { $contents = ''; - + // Create the js/ within the files folder. $jspath = file_create_path('js'); file_check_directory($jspath, FILE_CREATE_DIRECTORY); - + if (!file_exists($jspath .'/'. $filename)) { // Build aggregate JS file. foreach ($files as $path => $info) { @@ -2247,11 +2290,11 @@ $contents .= file_get_contents($path) .';'; } } - + // Create the JS file. file_save_data($contents, $jspath .'/'. $filename, FILE_EXISTS_REPLACE); } - + return $jspath .'/'. $filename; } @@ -2271,20 +2314,24 @@ function drupal_to_js($var) { switch (gettype($var)) { case 'boolean': - return $var ? 'true' : 'false'; // Lowercase necessary! + // Lowercase necessary! + return $var ? 'true' : 'false'; + case 'integer': case 'double': return $var; + case 'resource': case 'string': return '"'. str_replace(array("\r", "\n", "<", ">", "&"), - array('\r', '\n', '\x3c', '\x3e', '\x26'), - addslashes($var)) .'"'; + array('\r', '\n', '\x3c', '\x3e', '\x26'), + addslashes($var)) .'"'; + case 'array': // Arrays in JSON can't be associative. If the array is empty or if it // has sequential whole number keys starting with 0, it's not associative // so we can go ahead and convert it as an array. - if (empty ($var) || array_keys($var) === range(0, sizeof($var) - 1)) { + if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) { $output = array(); foreach ($var as $v) { $output[] = drupal_to_js($v); @@ -2298,6 +2345,7 @@ $output[] = drupal_to_js(strval($k)) .': '. drupal_to_js($v); } return '{ '. implode(', ', $output) .' }'; + default: return 'null'; } @@ -2315,7 +2363,7 @@ function drupal_json($var = NULL) { // We are returning JavaScript, so tell the browser. drupal_set_header('Content-Type: text/javascript; charset=utf-8'); - + if (isset($var)) { echo drupal_to_js($var); } @@ -2343,8 +2391,8 @@ function drupal_urlencode($text) { if (variable_get('clean_url', '0')) { return str_replace(array('%2F', '%26', '%23', '//'), - array('/', '%2526', '%2523', '/%252F'), - rawurlencode($text)); + array('/', '%2526', '%2523', '/%252F'), + rawurlencode($text)); } else { return str_replace('%2F', '/', rawurlencode($text)); @@ -2385,6 +2433,7 @@ * An additional value to base the token on. * @param $skip_anonymous * Set to true to skip token validation for anonymous users. + * * @return * True for a valid token, false for an invalid token. When $skip_anonymous * is true, the return value will always be true for anonymous users. @@ -2407,6 +2456,7 @@ * For multiple requests (system.multicall): * An array of call arrays. Each call array follows the pattern of the single * request: method name followed by the arguments to the method. + * * @return * For one request: * Either the return value of the method on success, or FALSE. @@ -2424,7 +2474,7 @@ function _drupal_bootstrap_full() { static $called; - + if ($called) { return; } @@ -2471,7 +2521,7 @@ */ function page_set_cache() { global $user, $base_root; - + if (!$user->uid && $_SERVER['REQUEST_METHOD'] == 'GET' && count(drupal_get_messages(NULL, FALSE)) == 0) { // This will fail in some cases, see page_get_cache() for the explanation. if ($data = ob_get_contents()) { @@ -2498,6 +2548,7 @@ /** * Executes a cron run when called + * * @return * Returns TRUE if ran successfully */ @@ -2506,16 +2557,16 @@ if (!ini_get('safe_mode')) { set_time_limit(240); } - + // Fetch the cron semaphore $semaphore = variable_get('cron_semaphore', FALSE); - + if ($semaphore) { if (time() - $semaphore > 3600) { // Either cron has been running for more than an hour or the semaphore // was not reset due to a database error. watchdog('cron', 'Cron has been running for more than an hour and is most likely stuck.', array(), WATCHDOG_ERROR); - + // Release cron semaphore variable_del('cron_semaphore'); } @@ -2527,20 +2578,20 @@ else { // Register shutdown callback register_shutdown_function('drupal_cron_cleanup'); - + // Lock cron semaphore variable_set('cron_semaphore', time()); - + // Iterate through the modules calling their cron handlers (if any): module_invoke_all('cron'); - + // Record cron time variable_set('cron_last', time()); watchdog('cron', 'Cron run completed.', array(), WATCHDOG_NOTICE); - + // Release cron semaphore variable_del('cron_semaphore'); - + // Return TRUE so other functions can check if it did run successfully return TRUE; } @@ -2553,7 +2604,7 @@ // See if the semaphore is still locked. if (variable_get('cron_semaphore', FALSE)) { watchdog('cron', 'Cron run exceeded the time limit and was aborted.', array(), WATCHDOG_WARNING); - + // Release cron semaphore variable_del('cron_semaphore'); } @@ -2589,7 +2640,7 @@ function drupal_system_listing($mask, $directory, $key = 'name', $min_depth = 1) { global $profile; $config = conf_path(); - + // When this function is called during Drupal's initial installation process, // the name of the profile that's about to be installed is stored in the global // $profile variable. At all other times, the standard Drupal systems variable @@ -2600,10 +2651,10 @@ } $searchdir = array($directory); $files = array(); - + // Always search sites/all/* as well as the global directories $searchdir[] = 'sites/all/'. $directory; - + // The 'profiles' directory contains pristine collections of modules and // themes as organized by a distribution. It is pristine in the same way // that /modules is pristine for core; users should avoid changing anything @@ -2611,20 +2662,19 @@ if (file_exists("profiles/$profile/$directory")) { $searchdir[] = "profiles/$profile/$directory"; } - + if (file_exists("$config/$directory")) { $searchdir[] = "$config/$directory"; } - + // Get current list of items foreach ($searchdir as $dir) { $files = array_merge($files, file_scan_directory($dir, $mask, array('.', '..', 'CVS'), 0, TRUE, $key, $min_depth)); } - + return $files; } - /** * This dispatch function hands off structured Drupal arrays to type-specific * *_alter implementations. It ensures a consistent interface for all altering @@ -2652,28 +2702,27 @@ $by_ref_parameters = $data['__drupal_alter_by_ref']; unset($data['__drupal_alter_by_ref']); } - + // Hang onto a reference to the data array so that it isn't blown away later. // Also, merge in any parameters that need to be passed by reference. $args = array(&$data); if (isset($by_ref_parameters)) { $args = array_merge($args, $by_ref_parameters); } - + // Now, use func_get_args() to pull in any additional parameters passed into // the drupal_alter() call. $additional_args = func_get_args(); array_shift($additional_args); array_shift($additional_args); $args = array_merge($args, $additional_args); - + foreach (module_implements($type .'_alter') as $module) { $function = $module .'_'. $type .'_alter'; call_user_func_array($function, $args); } } - /** * Renders HTML given a structured array tree. * @@ -2683,6 +2732,7 @@ * * @param $elements * The structured array describing the data to be rendered. + * * @return * The rendered HTML. */ @@ -2690,7 +2740,7 @@ if (!isset($elements) || (isset($elements['#access']) && !$elements['#access'])) { return NULL; } - + // If the default values for this element haven't been loaded yet, populate // them. if (!isset($elements['#defaults_loaded']) || !$elements['#defaults_loaded']) { @@ -2698,7 +2748,7 @@ $elements += $info; } } - + // Make any final changes to the element before it is rendered. This means // that the $element or the children can be altered or corrected before the // element is rendered into the final text. @@ -2709,7 +2759,7 @@ } } } - + $content = ''; // Either the elements did not go through form_builder or one of the children // has a #weight. @@ -2722,7 +2772,7 @@ /* Render all the children that use a theme function */ if (isset($elements['#theme']) && empty($elements['#theme_used'])) { $elements['#theme_used'] = TRUE; - + $previous = array(); foreach (array('#value', '#type', '#prefix', '#suffix') as $key) { $previous[$key] = isset($elements[$key]) ? $elements[$key] : NULL; @@ -2735,10 +2785,10 @@ $elements['#value'] = ''; } $elements['#type'] = 'markup'; - + unset($elements['#prefix'], $elements['#suffix']); $content = theme($elements['#theme'], $elements); - + foreach (array('#value', '#type', '#prefix', '#suffix') as $key) { $elements[$key] = isset($previous[$key]) ? $previous[$key] : NULL; } @@ -2753,13 +2803,13 @@ if (isset($content) && $content !== '') { $elements['#children'] = $content; } - + // Until now, we rendered the children, here we render the element itself if (!isset($elements['#printed'])) { $content = theme(!empty($elements['#type']) ? $elements['#type'] : 'markup', $elements); $elements['#printed'] = TRUE; } - + if (isset($content) && $content !== '') { // Filter the outputted content and make any last changes before the // content is sent to the browser. The changes are made on $content @@ -2786,7 +2836,7 @@ if ($a_weight == $b_weight) { return 0; } - return ($a_weight < $b_weight) ? -1 : 1; + return ($a_weight < $b_weight) ? - 1 : 1; } /** @@ -2825,7 +2875,7 @@ // theme.inc 'placeholder' => array( 'arguments' => array('text' => NULL) - ), + ), 'page' => array( 'arguments' => array('content' => NULL, 'show_blocks' => TRUE, 'show_messages' => TRUE), 'template' => 'page', @@ -2895,7 +2945,7 @@ ), 'more_link' => array( 'arguments' => array('url' => NULL, 'title' => NULL) - ), + ), 'closure' => array( 'arguments' => array('main' => 0), ), @@ -3035,7 +3085,7 @@ */ function drupal_get_schema($table = NULL, $rebuild = FALSE) { static $schema = array(); - + if (empty($schema) || $rebuild) { // Try to load the schema from cache. if (!$rebuild && $cached = cache_get('schema')) { @@ -3046,19 +3096,19 @@ $schema = array(); // Load the .install files to get hook_schema. module_load_all_includes('install'); - + // Invoke hook_schema for all modules. foreach (module_implements('schema') as $module) { $current = module_invoke($module, 'schema'); _drupal_initialize_schema($module, $current); $schema = array_merge($schema, $current); } - + drupal_alter('schema', $schema); cache_set('schema', $schema); } } - + if (!isset($table)) { return $schema; } @@ -3079,6 +3129,7 @@ * * @param $module * The module for which the tables will be created. + * * @return * An array of arrays with the following key/value pairs: * success: a boolean indicating whether the query succeeded @@ -3087,7 +3138,7 @@ function drupal_install_schema($module) { $schema = drupal_get_schema_unprocessed($module); _drupal_initialize_schema($module, $schema); - + $ret = array(); foreach ($schema as $name => $table) { db_create_table($ret, $name, $table); @@ -3104,6 +3155,7 @@ * * @param $module * The module for which the tables will be removed. + * * @return * An array of arrays with the following key/value pairs: * success: a boolean indicating whether the query succeeded @@ -3112,7 +3164,7 @@ function drupal_uninstall_schema($module) { $schema = drupal_get_schema_unprocessed($module); _drupal_initialize_schema($module, $schema); - + $ret = array(); foreach ($schema as $table) { db_drop_table($ret, $table['name']); @@ -3148,7 +3200,7 @@ // Load the .install file to get hook_schema. module_load_include('install', $module); $schema = module_invoke($module, 'schema'); - + if (!is_null($table) && isset($schema[$table])) { return $schema[$table]; } @@ -3219,6 +3271,7 @@ * If this is an update, specify the primary keys' field names. It is the * caller's responsibility to know if a record for this object already * exists in the database. If there is only 1 key, you may pass a simple string. + * * @return * Failure to write a record will return FALSE. Otherwise SAVED_NEW or * SAVED_UPDATED is returned depending on the operation performed. The @@ -3231,7 +3284,7 @@ if (is_string($update)) { $update = array($update); } - + // Convert to an object if needed. if (is_array($object)) { $object = (object) $object; @@ -3240,14 +3293,14 @@ else { $array = FALSE; } - + $schema = drupal_get_schema($table); if (empty($schema)) { return FALSE; } - + $fields = $defs = $values = $serials = array(); - + // Go through our schema, build SQL, and when inserting, fill in defaults for // fields that are not set. foreach ($schema['fields'] as $field => $info) { @@ -3255,24 +3308,24 @@ if ($info['type'] == 'serial' && count($update)) { continue; } - + // For inserts, populate defaults from Schema if not already provided if (!isset($object->$field) && !count($update) && isset($info['default'])) { $object->$field = $info['default']; } - + // Track serial fields so we can helpfully populate them after the query. if ($info['type'] == 'serial') { $serials[] = $field; // Ignore values for serials when inserting data. Unsupported. unset($object->$field); } - + // Build arrays for the fields, placeholders, and values in our query. if (isset($object->$field)) { $fields[] = $field; $placeholders[] = db_type_placeholder($info['type']); - + if (empty($info['serialize'])) { $values[] = $object->$field; } @@ -3281,7 +3334,7 @@ } } } - + // Build the SQL. $query = ''; if (!count($update)) { @@ -3296,16 +3349,16 @@ } $query .= $field .' = '. $placeholders[$id]; } - - foreach ($update as $key){ + + foreach ($update as $key) { $conditions[] = "$key = ". db_type_placeholder($schema['fields'][$key]['type']); $values[] = $object->$key; } - + $query = "UPDATE {". $table ."} SET $query WHERE ". implode(' AND ', $conditions); $return = SAVED_UPDATED; } - + // Execute the SQL. if (db_query($query, $values)) { if ($serials) { @@ -3314,15 +3367,15 @@ $object->$field = db_last_insert_id($table, $field); } } - + // If we began with an array, convert back so we don't surprise the caller. if ($array) { $object = (array) $object; } - + return $return; } - + return FALSE; } @@ -3386,16 +3439,17 @@ * * @param $filename * The file we are parsing. Accepts file with relative or absolute path. + * * @return * The info array. */ function drupal_parse_info_file($filename) { $info = array(); - + if (!file_exists($filename)) { return $info; } - + $data = file_get_contents($filename); if (preg_match_all(' @^\s* # Start at the beginning of a line, ignoring leading whitespace @@ -3417,12 +3471,12 @@ $$var = isset($match[++$i]) ? $match[$i] : ''; } $value = stripslashes(substr($value1, 1, -1)) . stripslashes(substr($value2, 1, -1)) . $value3; - + // Parse array syntax - $keys = preg_split('/\]?\[/', rtrim($key, ']')); - $last = array_pop($keys); + $keys = preg_split('/\]?\[/', rtrim($key, ']')); + $last = array_pop($keys); $parent = &$info; - + // Create nested arrays foreach ($keys as $key) { if ($key == '') { @@ -3433,12 +3487,12 @@ } $parent = &$parent[$key]; } - + // Handle PHP constants if (defined($value)) { $value = constant($value); } - + // Insert actual value if ($last == '') { $last = count($parent); @@ -3446,11 +3500,12 @@ $parent[$last] = $value; } } - + return $info; } /** + * * @return * Array of the possible severity levels for log messages. * @@ -3458,18 +3513,17 @@ */ function watchdog_severity_levels() { return array( - WATCHDOG_EMERG => t('emergency'), - WATCHDOG_ALERT => t('alert'), + WATCHDOG_EMERG => t('emergency'), + WATCHDOG_ALERT => t('alert'), WATCHDOG_CRITICAL => t('critical'), - WATCHDOG_ERROR => t('error'), - WATCHDOG_WARNING => t('warning'), - WATCHDOG_NOTICE => t('notice'), - WATCHDOG_INFO => t('info'), - WATCHDOG_DEBUG => t('debug'), + WATCHDOG_ERROR => t('error'), + WATCHDOG_WARNING => t('warning'), + WATCHDOG_NOTICE => t('notice'), + WATCHDOG_INFO => t('info'), + WATCHDOG_DEBUG => t('debug'), ); } - /** * Explode a string of given tags into an array. */ @@ -3479,7 +3533,7 @@ $regexp = '%(?:^|,\ *)("(?>[^"]*)(?>""[^"]* )*"|(?: [^",]*))%x'; preg_match_all($regexp, $tags, $matches); $typed_tags = array_unique($matches[1]); - + $tags = array(); foreach ($typed_tags as $tag) { // If a user has escaped a term (to demonstrate that it is a group, @@ -3490,7 +3544,7 @@ $tags[] = $tag; } } - + return $tags; } @@ -3504,7 +3558,7 @@ if (strpos($tag, ',') !== FALSE || strpos($tag, '"') !== FALSE) { $tag = '"'. str_replace('"', '""', $tag) .'"'; } - + $encoded_tags[] = $tag; } return implode(', ', $encoded_tags); @@ -3519,7 +3573,7 @@ function drupal_flush_all_caches() { // Change query-strings on css/js files to enforce reload for all users. _drupal_flush_css_js(); - + drupal_clear_css_cache(); drupal_clear_js_cache(); drupal_rebuild_theme_registry(); @@ -3545,10 +3599,11 @@ */ function _drupal_flush_css_js() { $string_history = variable_get('css_js_query_string', '00000000000000000000'); - $new_character = $string_history[0]; - $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; + $new_character = $string_history[0]; + $characters = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'; while (strpos($string_history, $new_character) !== FALSE) { $new_character = $characters[mt_rand(0, strlen($characters) - 1)]; } variable_set('css_js_query_string', $new_character . substr($string_history, 0, 19)); } +