common.inc 27.8 KB
Newer Older
Dries's avatar
 
Dries committed
1 2 3
<?php
// $Id$

Dries's avatar
 
Dries committed
4
/**
Dries's avatar
 
Dries committed
5 6 7 8 9
  @name drupal_title

  Functions to get and set the title of the current page.
  @{
**/
Dries's avatar
 
Dries committed
10 11 12 13
function drupal_set_title($title = NULL) {
  static $stored_title;

  if (isset($title)) {
Dries's avatar
 
Dries committed
14
    $stored_title = ucfirst($title);
Dries's avatar
 
Dries committed
15 16 17 18 19 20 21 22 23 24 25 26 27
  }
  return $stored_title;
}

function drupal_get_title() {
  $title = drupal_set_title();

  if (!isset($title)) {
    $title = menu_get_active_title();
  }

  return $title;
}
28
// @}
Dries's avatar
 
Dries committed
29 30

/**
Dries's avatar
 
Dries committed
31 32 33 34 35 36 37 38
  @name drupal_breadcrumb

  Functions to get and set the breadcrumb trail of the current page.

  @param   $breadcrumb   array of links, starting with "home" and proceeding
    up to but not including the current page.
  @{
**/
Dries's avatar
 
Dries committed
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
function drupal_set_breadcrumb($breadcrumb = NULL) {
  static $stored_breadcrumb;

  if (isset($breadcrumb)) {
    $stored_breadcrumb = $breadcrumb;
  }
  return $stored_breadcrumb;
}

function drupal_get_breadcrumb() {
  $breadcrumb = drupal_set_breadcrumb();

  if (!isset($breadcrumb)) {
    $breadcrumb = menu_get_active_breadcrumb();
    array_pop($breadcrumb);
  }

  return $breadcrumb;
}
58
// @}
Dries's avatar
 
Dries committed
59

Dries's avatar
 
Dries committed
60
/**
Dries's avatar
 
Dries committed
61 62
  Build the alias/path array
**/
Dries's avatar
 
Dries committed
63
function drupal_get_path_map($action = "") {
Dries's avatar
 
Dries committed
64 65

  static $cache;
Dries's avatar
 
Dries committed
66 67
  static $map;

Dries's avatar
 
Dries committed
68 69
  if ($action == "rebuild") {
    $map = NULL;
Dries's avatar
 
Dries committed
70
    $cache = 0;
Dries's avatar
 
Dries committed
71 72
  }

Dries's avatar
 
Dries committed
73
  if (!$cache) {
Dries's avatar
 
Dries committed
74
    $result = db_query("SELECT * FROM {url_alias}");
Dries's avatar
 
Dries committed
75
    while ($data = db_fetch_object($result)) {
Dries's avatar
 
Dries committed
76
      $map[$data->dst] = $data->src;
Dries's avatar
 
Dries committed
77
    }
Dries's avatar
 
Dries committed
78 79

    $cache = 1;
Dries's avatar
 
Dries committed
80 81 82 83 84
  }

  return $map;
}

Dries's avatar
 
Dries committed
85 86 87 88
function drupal_rebuild_path_map() {
  drupal_get_path_map("rebuild");
}

Dries's avatar
 
Dries committed
89 90 91
function error_handler($errno, $message, $filename, $line, $variables) {
  $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");
  $entry = $types[$errno] .": $message in $filename on line $line.";
Dries's avatar
 
Dries committed
92 93

  if ($errno & E_ALL ^ E_NOTICE) {
Dries's avatar
 
Dries committed
94
    watchdog("error", $types[$errno] .": $message in $filename on line $line.");
95
    print "<pre>$entry</pre>";
Dries's avatar
 
Dries committed
96 97 98
  }
}

Dries's avatar
 
Dries committed
99
function watchdog($type, $message, $link = NULL) {
Dries's avatar
 
Dries committed
100
  global $user;
Dries's avatar
 
Dries committed
101
  db_query("INSERT INTO {watchdog} (uid, type, message, link, location, hostname, timestamp) VALUES (%d, '%s', '%s', '%s', '%s', '%s', %d)", $user->uid, $type, $message, $link, request_uri(), getenv("REMOTE_ADDR"), time());
Dries's avatar
 
Dries committed
102 103 104 105
}

function throttle($type, $rate) {
  if (!user_access("access administration pages")) {
Dries's avatar
 
Dries committed
106
    if ($throttle = db_fetch_object(db_query("SELECT * FROM {watchdog} WHERE type = '$type' AND hostname = '". getenv("REMOTE_ADDR") ."' AND ". time() ." - timestamp < $rate"))) {
Dries's avatar
 
Dries committed
107 108 109 110 111 112 113 114 115
      watchdog("warning", "throttle: '". getenv("REMOTE_ADDR") ."' exceeded submission rate - $throttle->type");
      die(message_throttle());
    }
    else {
      watchdog($type, "throttle");
    }
  }
}

Dries's avatar
 
Dries committed
116 117 118 119
function _fix_gpc_magic_array(&$items) {
  foreach ($items as $k => $i) {
    if (is_array($i)) _fix_gpc_magic_array($items[$k]);
    else $items[$k] = stripslashes($i);
Dries's avatar
 
Dries committed
120 121 122
  }
}

Dries's avatar
 
Dries committed
123 124 125 126 127 128 129 130 131 132 133 134
function fix_gpc_magic() {
  static $fixed = false;
  if ($fixed) return;
  if (ini_get("magic_quotes_gpc") == 0) return;

  _fix_gpc_magic_array($_GET);
  _fix_gpc_magic_array($_POST);
  _fix_gpc_magic_array($_COOKIE);

  $fixed = true;
}

Dries's avatar
 
Dries committed
135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
function array2object($node) {

  if (is_array($node)) {
    foreach ($node as $key => $value) {
      $object->$key = $value;
    }
  }
  else {
    $object = $node;
  }

  return $object;
}

function object2array($node) {

  if (is_object($node)) {
    foreach ($node as $key => $value) {
      $array[$key] = $value;
    }
  }
  else {
    $array = $node;
  }

  return $array;
}

Dries's avatar
 
Dries committed
163
function message_access() {
Dries's avatar
 
Dries committed
164
  return t("You are not authorized to access this page.");
Dries's avatar
 
Dries committed
165 166 167 168 169 170 171 172 173 174
}

function message_na() {
  return t("n/a");
}

function message_throttle() {
  return t("You exceeded the maximum submission rate.  Please wait a few minutes and try again.");
}

Dries's avatar
 
Dries committed
175 176
function locale_init() {
  global $languages, $user;
Dries's avatar
 
Dries committed
177 178 179 180 181 182
  if ($user->uid && $languages[$user->language]) {
    return $user->language;
  }
  else {
    return key($languages);
  }
Dries's avatar
 
Dries committed
183 184
}

Dries's avatar
 
Dries committed
185
function t($string, $args = 0) {
Dries's avatar
 
Dries committed
186
  global $languages;
187

Dries's avatar
 
Dries committed
188 189 190 191 192 193 194
  /*
  ** About the usage of t().  We try to keep strings whole as much as
  ** possible and are unafraid of HTML markup within translation strings
  ** if necessary.  The suggested syntax for a link embedded within a
  ** translation string is for example:
  **
  ** $msg = t("You must login below or <a href=\"%url\">create a new
Dries's avatar
 
Dries committed
195 196
  **           account</a> before viewing the next page.", array("%url"
  **           => url("user/register")));
Dries's avatar
 
Dries committed
197 198
  */

199
  $string = ($languages && module_exist("locale") ? locale($string) : $string);
200

Dries's avatar
 
Dries committed
201 202
  if (!$args) {
    return $string;
Kjartan's avatar
Kjartan committed
203 204
  }
  else {
Dries's avatar
 
Dries committed
205 206
    return strtr($string, $args);
  }
Dries's avatar
 
Dries committed
207 208
}

Dries's avatar
 
Dries committed
209
function drupal_specialchars($input, $quotes = ENT_NOQUOTES) {
Dries's avatar
 
Dries committed
210 211 212 213 214 215 216 217 218

  /*
  ** Note that we'd like to go 'htmlspecialchars($input, $quotes, "utf-8")'
  ** like the PHP manual tells us to, but we can't because there's a bug in
  ** PHP <4.3 that makes it mess up multibyte charsets if we specify the
  ** charset.  Change this later once we make PHP 4.3 a requirement.
  */

  return htmlspecialchars($input, $quotes);
Dries's avatar
 
Dries committed
219 220
}

221 222 223 224 225 226
/**
 * Verify the syntax of the given e-mail address.  Empty e-mail addresses
 * are allowed.  See RFC 2822 for details.
 *
 * @param $mail  a email address
 */
Dries's avatar
 
Dries committed
227
function valid_email_address($mail) {
228 229 230 231 232 233 234 235 236 237 238 239 240
  $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}';

  if (preg_match("/^$user@($domain|(\[($ipv4|$ipv6)\]))$/", $mail)) {
    return 1;
  }
  else {
    return 0;
  }
}

Dries's avatar
 
Dries committed
241 242 243 244 245 246 247
/**
 * Verify the syntax of the given URL.
 *
 * @param $url  an URL
 */
function valid_url($url) {

Dries's avatar
 
Dries committed
248
  if (preg_match("/^[a-zA-z0-9\/:_\-_\.,]+$/", $url)) {
Dries's avatar
 
Dries committed
249 250 251 252 253 254 255
    return 1;
  }
  else {
    return 0;
  }
}

Kjartan's avatar
Kjartan committed
256 257 258
/**
 * Format a single result entry of a search query:
 *
259 260 261
 * @param $item  a single search result as returned by <i>module</i>_search of
 *   type array("count" => ..., "link" => ..., "title" => ..., "user" => ...,
 *              "date" => ..., "keywords" => ...)
Kjartan's avatar
Kjartan committed
262 263
 * @param $type  module type of this item
 */
Dries's avatar
 
Dries committed
264
function search_item($item, $type) {
Dries's avatar
 
Dries committed
265 266 267 268 269 270 271 272 273 274

  /*
  ** Modules may implement the "search_item" hook in order to overwrite
  ** the default function to display search results.
  */

  if (module_hook($type, "search_item")) {
    $output = module_invoke($type, "search_item", $item);
  }
  else {
Dries's avatar
 
Dries committed
275
    $output .= " <b><u><a href=\"". $item["link"] ."\">". $item["title"] ."</a></u></b><br />";
Dries's avatar
 
Dries committed
276
    $output .= " <small>" . t($type) . ($item["user"] ? " - ". $item["user"] : "") ."". ($item["date"] ? " - ". format_date($item["date"], "small") : "") ."</small>";
Dries's avatar
 
Dries committed
277 278
    $output .= "<br /><br />";
  }
Dries's avatar
 
Dries committed
279 280 281 282

  return $output;
}

Kjartan's avatar
Kjartan committed
283 284 285 286
/**
 * Render a generic search form.
 *
 * "Generic" means "universal usable" - that is, usable not only from
Dries's avatar
 
Dries committed
287
 * 'site.com/search', but also as a simple seach box (without
Dries's avatar
 
Dries committed
288 289
 * "Restrict search to", help text, etc) from theme's header etc.
 * This means: provide options to only conditionally render certain
Kjartan's avatar
Kjartan committed
290 291
 * parts of this form.
 *
Dries's avatar
 
Dries committed
292
 * @param $action  Form action. Defaults to 'site.com/search'.
Dries's avatar
 
Dries committed
293
 * @param $keys   string containing keywords for the search.
Dries's avatar
 
Dries committed
294
 * @param $options != 0: Render additional form fields/text
Kjartan's avatar
Kjartan committed
295 296
 *                 ("Restrict search to", help text, etc).
 */
Dries's avatar
 
Dries committed
297
function search_form($action = NULL, $keys = NULL, $options = NULL) {
Dries's avatar
 
Dries committed
298 299

  if (!$action) {
Dries's avatar
 
Dries committed
300
    $action = url("search");
Dries's avatar
 
Dries committed
301 302
  }

Dries's avatar
 
Dries committed
303 304
  $output .= " <br /><input type=\"text\" class=\"form-text\" size=\"50\" value=\"". check_form($keys) ."\" name=\"keys\" />";
  $output .= " <input type=\"submit\" class=\"form-submit\" value=\"". t("Search") ."\" />\n";
Dries's avatar
 
Dries committed
305 306 307 308 309 310 311

  if ($options != 0) {
    $output .= "<br />";
    $output .= t("Restrict search to") .": ";

    foreach (module_list() as $name) {
      if (module_hook($name, "search")) {
Kjartan's avatar
Kjartan committed
312
        $output .= " <input type=\"checkbox\" name=\"edit[type][$name]\" ". ($edit["type"][$name] ? " checked=\"checked\"" : "") ." /> ". t($name);
Dries's avatar
 
Dries committed
313 314 315 316
      }
    }
  }

Kjartan's avatar
Kjartan committed
317 318
  $form .= "<br />";

Dries's avatar
 
Dries committed
319 320 321 322
  return form($output, "post", $action);
}

/*
Kjartan's avatar
Kjartan committed
323 324
 * Collect the search results:
 */
Dries's avatar
 
Dries committed
325
function search_data($keys = NULL) {
Dries's avatar
 
Dries committed
326 327

  $edit = $_POST["edit"];
Dries's avatar
 
Dries committed
328

Dries's avatar
 
Dries committed
329
  if (isset($keys)) {
Dries's avatar
 
Dries committed
330
    foreach (module_list() as $name) {
Dries's avatar
 
Dries committed
331
      if (module_hook($name, "search") && (!$edit["type"] || $edit["type"][$name]) && ($result = module_invoke($name, "search", $keys))) {
Kjartan's avatar
Kjartan committed
332
        if ($name == "node" || $name == "comment") {
Dries's avatar
 
Dries committed
333
          $output .= "<p><b>". t("Matching ". $name ."s ranked in order of relevance") .":</b></p>";
Kjartan's avatar
Kjartan committed
334 335
        }
        else {
Dries's avatar
 
Dries committed
336
          $output .= "<p><b>". t("Matching ". $name ."s") .":</b></p>";
Kjartan's avatar
Kjartan committed
337
        }
Dries's avatar
 
Dries committed
338 339 340 341 342 343 344 345 346 347
        foreach ($result as $entry) {
          $output .= search_item($entry, $name);
        }
      }
    }
  }

  return $output;
}

Kjartan's avatar
Kjartan committed
348 349 350
/**
 * Display the search form and the resulting data.
 *
Dries's avatar
 
Dries committed
351
 * @param $type    If set, search only nodes of this type.
Kjartan's avatar
Kjartan committed
352
 *                 Otherwise, search all types.
Dries's avatar
 
Dries committed
353
 * @param $action  Form action. Defaults to 'site.com/search'.
354
 * @param $keys    Query string. Defaults to global $keys.
Dries's avatar
 
Dries committed
355
 * @param $options != 0: Render additional form fields/text
Kjartan's avatar
Kjartan committed
356 357
 *                 ("Restrict search to", help text, etc).
 */
Dries's avatar
 
Dries committed
358
function search_type($type, $action = NULL, $keys = NULL, $options = NULL) {
Dries's avatar
 
Dries committed
359

Dries's avatar
 
Dries committed
360
  $_POST["edit"]["type"][$type] = "on";
Dries's avatar
 
Dries committed
361

Dries's avatar
 
Dries committed
362
  return search_form($action, $keys, $options) . "<br />". search_data($keys);
Dries's avatar
 
Dries committed
363 364
}

Dries's avatar
 
Dries committed
365

Dries's avatar
 
Dries committed
366 367
function drupal_goto($url) {

Dries's avatar
 
Dries committed
368 369 370
  /*
  ** Translate &amp; to simply &
  */
Dries's avatar
 
Dries committed
371

Dries's avatar
 
Dries committed
372
  $url = str_replace("&amp;", "&", $url);
Dries's avatar
 
Dries committed
373

Dries's avatar
 
Dries committed
374 375 376 377 378
  /*
  ** It is advised to use "drupal_goto()" instead of PHP's "header()" as
  ** "drupal_goto()" will append the user's session ID to the URI when PHP
  ** is compiled with "--enable-trans-sid".
  */
Dries's avatar
 
Dries committed
379
  if (!ini_get("session.use_trans_sid") || !session_id() || strstr($url, session_id())) {
Dries's avatar
 
Dries committed
380 381 382
    header("Location: $url");
  }
  else {
Dries's avatar
 
Dries committed
383 384 385 386 387 388 389 390
    $sid = session_name() . "=" . session_id();

    if (strstr($url, "?") && !strstr($url, $sid)) {
      header("Location: $url&". $sid);
    }
    else {
      header("Location: $url?". $sid);
    }
Dries's avatar
 
Dries committed
391 392 393 394
  }

  /*
  ** The "Location" header sends a REDIRECT status code to the http
Dries's avatar
 
Dries committed
395
  ** daemon.  In some cases this can go wrong, so we make sure none
Dries's avatar
 
Dries committed
396 397 398 399 400 401
  ** of the code /below/ gets executed when we redirect.
  */

  exit();
}

Dries's avatar
 
Dries committed
402
function valid_input_data($data) {
403

404
  if (is_array($data) || is_object($data)) {
405 406 407 408 409
    /*
    ** Form data can contain a number of nested arrays.
    */

    foreach ($data as $key => $value) {
Dries's avatar
 
Dries committed
410 411 412
      if (!valid_input_data($value)) {
        return 0;
      }
413 414 415 416 417 418 419
    }
  }
  else {
    /*
    ** Detect evil input data.
    */

Dries's avatar
Dries committed
420
    // check strings:
Dries's avatar
Dries committed
421
    $match  = preg_match("/\Wjavascript\s*:/i", $data);
Dries's avatar
Dries committed
422 423 424
    $match += preg_match("/\Wexpression\s*\(/i", $data);
    $match += preg_match("/\Walert\s*\(/i", $data);

425
    // check attributes:
Dries's avatar
Dries committed
426
    $match += preg_match("/\W(dynsrc|datasrc|data|lowsrc|on[a-z]+)\s*=[^>]+?>/i", $data);
Dries's avatar
 
Dries committed
427

428 429

    // check tags:
Dries's avatar
 
Dries committed
430
    $match += preg_match("/<\s*(applet|script|object|style|embed|form|blink|meta|html|frame|iframe|layer|ilayer|head|frameset|xml)/i", $data);
431 432 433

    if ($match) {
      watchdog("warning", "terminated request because of suspicious input data: ". drupal_specialchars($data));
Dries's avatar
 
Dries committed
434
      return 0;
435 436
    }
  }
Dries's avatar
 
Dries committed
437 438

  return 1;
439
}
Dries's avatar
 
Dries committed
440

Dries's avatar
 
Dries committed
441
function check_form($text) {
Dries's avatar
 
Dries committed
442
  return drupal_specialchars($text, ENT_QUOTES);
Dries's avatar
 
Dries committed
443 444 445
}

function filter($text) {
Dries's avatar
 
Dries committed
446

Dries's avatar
 
Dries committed
447 448 449 450 451 452 453 454 455 456 457 458 459
  $modules = module_list();

  /*
  ** Make sure the HTML filters that are part of the node module
  ** are run first.
  */

  if (in_array("node", $modules)) {
    $text = module_invoke("node", "filter", $text);
  }

  foreach ($modules as $name) {
    if (module_hook($name, "filter") && $name != "node") {
Dries's avatar
 
Dries committed
460 461 462 463 464
      $text = module_invoke($name, "filter", $text);
    }
  }

  return $text;
Dries's avatar
 
Dries committed
465 466
}

Dries's avatar
 
Dries committed
467 468
function rewrite_old_urls($text) {

Dries's avatar
 
Dries committed
469 470 471 472
  global $base_url;

  $end = substr($base_url, 12);

Dries's avatar
 
Dries committed
473 474 475
  /*
  ** This is a *temporary* filter to rewrite old-style URLs to new-style
  ** URLs (clean URLs).  Currently, URLs are being rewritten dynamically
Dries's avatar
 
Dries committed
476 477
  ** (ie. "on output"), however when these rewrite rules have been tested
  ** enough, we will use them to permanently rewrite the links in node
Dries's avatar
 
Dries committed
478 479 480
  ** and comment bodies.
  */

Dries's avatar
 
Dries committed
481
  if (variable_get("clean_url", "0") == "0") {
Dries's avatar
 
Dries committed
482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497
    /*
    ** Relative URLs:
    */

    // rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
    $text = eregi_replace("\"(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "\"?q=\\1/view/\\2/\\4", $text);

    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2/\\4/\\6" , $text);
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2/\\4", $text);
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"?q=\\2", $text);

    /*
    ** Absolute URLs:
    */

Dries's avatar
 
Dries committed
498
    // rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
Dries's avatar
 
Dries committed
499
    $text = eregi_replace("$end/(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "$end/?q=\\1/view/\\2/\\4", $text);
Dries's avatar
 
Dries committed
500

Dries's avatar
 
Dries committed
501
    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
Dries's avatar
 
Dries committed
502 503 504
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/?q=\\2/\\4/\\6" , $text);
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/?q=\\2/\\4", $text);
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"$end/?q=\\2", $text);
Dries's avatar
 
Dries committed
505 506
  }
  else {
Dries's avatar
 
Dries committed
507 508 509 510
    /*
    ** Relative URLs:
    */

Dries's avatar
 
Dries committed
511
    // rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
Dries's avatar
 
Dries committed
512
    $text = eregi_replace("\"(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "\"\\1/view/\\2/\\4", $text);
Dries's avatar
 
Dries committed
513 514

    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
Dries's avatar
 
Dries committed
515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2/\\4/\\6", $text);
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2/\\4", $text);
    $text = ereg_replace("\"module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "\"\\2", $text);

    /*
    ** Absolute URLs:
    */

    // rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
    $text = eregi_replace("$end/(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "$end/\\1/view/\\2/\\4", $text);

    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2/\\4/\\6", $text);
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2/\\4", $text);
    $text = ereg_replace("$end/module\.php\?(&?[[:alpha:]]+=([[:alnum:]]+))", "$end/\\2", $text);
}
Dries's avatar
 
Dries committed
531

Dries's avatar
 
Dries committed
532 533 534
  return $text;
}

Dries's avatar
 
Dries committed
535
function check_output($text) {
Dries's avatar
 
Dries committed
536
  if (isset($text)) {
Dries's avatar
 
Dries committed
537 538 539 540
    // filter content on output:
    $text = filter($text);

    // get the line breaks right:
Dries's avatar
 
Dries committed
541
    if (strip_tags($text, "<a><i><b><u><tt><code><cite><strong><img>") == $text) {
Dries's avatar
 
Dries committed
542 543 544 545 546 547 548 549
      $text = nl2br($text);
    }
  }
  else {
    $text = message_na();
  }

  return $text;
Dries's avatar
 
Dries committed
550 551
}

552

553 554
function check_file($filename) {
  return is_uploaded_file($filename);
Dries's avatar
 
Dries committed
555 556
}

Dries's avatar
 
Dries committed
557 558 559
function format_rss_channel($title, $link, $description, $items, $language = "en", $args = array()) {
  // arbitrary elements may be added using the $args associative array

Dries's avatar
 
Dries committed
560
  $output .= "<channel>\n";
Dries's avatar
 
Dries committed
561 562 563 564
  $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n";
  $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n";
  $output .= " <description>". drupal_specialchars($description) ."</description>\n";
  $output .= " <language>". drupal_specialchars(strip_tags($language)) ."</language>\n";
Dries's avatar
 
Dries committed
565
  foreach ($args as $key => $value) {
Dries's avatar
 
Dries committed
566
    $output .= " <$key>". drupal_specialchars(strip_tags($value)) ."</$key>\n";
Dries's avatar
 
Dries committed
567
  }
Dries's avatar
 
Dries committed
568 569 570 571 572 573
  $output .= $items;
  $output .= "</channel>\n";

  return $output;
}

Dries's avatar
 
Dries committed
574 575 576
function format_rss_item($title, $link, $description, $args = array()) {
  // arbitrary elements may be added using the $args associative array

Dries's avatar
 
Dries committed
577
  $output .= "<item>\n";
Dries's avatar
 
Dries committed
578 579 580
  $output .= " <title>". drupal_specialchars(strip_tags($title)) ."</title>\n";
  $output .= " <link>". drupal_specialchars(strip_tags($link)) ."</link>\n";
  $output .= " <description>". drupal_specialchars(check_output($description)) ."</description>\n";
Dries's avatar
 
Dries committed
581
  foreach ($args as $key => $value) {
Dries's avatar
 
Dries committed
582
    $output .= "<$key>". drupal_specialchars(strip_tags($value)) ."</$key>";
Dries's avatar
 
Dries committed
583
  }
Dries's avatar
 
Dries committed
584 585 586 587 588
  $output .= "</item>\n";

  return $output;
}

Dries's avatar
 
Dries committed
589 590 591 592 593 594 595 596 597 598 599 600 601 602
/**
 * Formats a string with a count of items so that the string is pluralized
 * correctly.
 * format_plural calls t() by itself, make sure not to pass already localized
 * strings to it.
 *
 * @param $count    The item count to display.
 * @param $singular The string for the singular case. Please make sure it's clear
 *                  this is singular, to ease translation. ("1 new comment" instead of
 *                  "1 new").
 * @param $plural   The string for the plrual case. Please make sure it's clear
 *                  this is plural, to ease translation. Use %count in places of the
 *                  item count, as in "%count new comments".
 */
Dries's avatar
 
Dries committed
603
function format_plural($count, $singular, $plural) {
Dries's avatar
 
Dries committed
604
  return t($count == 1 ? $singular : $plural, array("%count" => $count));
Dries's avatar
 
Dries committed
605 606 607
}

function format_size($size) {
Dries's avatar
 
Dries committed
608
  $suffix = t("bytes");
Dries's avatar
 
Dries committed
609 610
  if ($size > 1024) {
    $size = round($size / 1024, 2);
Dries's avatar
 
Dries committed
611
    $suffix = t("KB");
Dries's avatar
 
Dries committed
612 613 614
  }
  if ($size > 1024) {
    $size = round($size / 1024, 2);
Dries's avatar
 
Dries committed
615
    $suffix = t("MB");
Dries's avatar
 
Dries committed
616
  }
Dries's avatar
 
Dries committed
617
  return t("%size %suffix", array("%size" => $size, "%suffix" => $suffix));
Dries's avatar
 
Dries committed
618 619 620
}

function format_interval($timestamp) {
Dries's avatar
 
Dries committed
621
  $units = array("1 year|%count years" => 31536000, "1 week|%count weeks" => 604800, "1 day|%count days" => 86400, "1 hour|%count hours" => 3600, "1 min|%count min" => 60, "1 sec|%count sec" => 1);
Kjartan's avatar
Kjartan committed
622
  foreach ($units as $key=>$value) {
Dries's avatar
 
Dries committed
623 624 625 626 627 628
    $key = explode("|", $key);
    if ($timestamp >= $value) {
      $output .= ($output ? " " : "") . format_plural(floor($timestamp / $value), $key[0], $key[1]);
      $timestamp %= $value;
    }
  }
Dries's avatar
 
Dries committed
629
  return ($output) ? $output : t("0 sec");
Dries's avatar
 
Dries committed
630 631 632 633 634
}

function format_date($timestamp, $type = "medium", $format = "") {
  global $user;

Kjartan's avatar
Kjartan committed
635
  $timestamp += ($user->timezone) ? $user->timezone - date("Z") : 0;
Dries's avatar
 
Dries committed
636 637 638

  switch ($type) {
    case "small":
Dries's avatar
 
Dries committed
639
      $format = variable_get("date_format_short", "m/d/Y - H:i");
Dries's avatar
 
Dries committed
640 641
      break;
    case "large":
Dries's avatar
 
Dries committed
642
      $format = variable_get("date_format_long", "l, F j, Y - H:i");
Dries's avatar
 
Dries committed
643 644
      break;
    case "custom":
Dries's avatar
 
Dries committed
645
      // No change to format
Dries's avatar
 
Dries committed
646
      break;
Dries's avatar
 
Dries committed
647
    case "medium":
Dries's avatar
 
Dries committed
648
    default:
Dries's avatar
 
Dries committed
649 650 651 652 653 654 655 656 657 658 659 660 661
      $format = variable_get("date_format_medium", "D, m/d/Y - H:i");
  }

  for ($i = strlen($format); $i >= 0; $c = $format[--$i]) {
    if (strstr("DFlMSw", $c)) {
      $date = t(date($c, $timestamp)) . $date;
    }
    else if (strstr("AaBdgGhHiIjLmnOrstTUWYyZz", $c)) {
      $date = date($c, $timestamp) . $date;
    }
    else {
      $date = $c.$date;
    }
Dries's avatar
 
Dries committed
662 663 664 665 666 667 668
  }
  return $date;
}

function format_name($object) {

  if ($object->uid && $object->name) {
Dries's avatar
Dries committed
669 670 671 672 673 674 675 676 677 678 679 680
    /*
    ** Shorten the name when it is too long or it will break many
    ** tables.
    */

    if (strlen($object->name) > 20) {
      $name = substr($object->name, 0, 15) ."...";
    }
    else {
      $name = $object->name;
    }

Dries's avatar
 
Dries committed
681
    if (arg(0) == "admin") {
Dries's avatar
Dries committed
682
      $output = l($name, "admin/user/edit/$object->uid", array("title" => t("Administer user profile.")));
Dries's avatar
 
Dries committed
683 684
    }
    else {
Dries's avatar
Dries committed
685
      $output = l($name, "user/view/$object->uid", array("title" => t("View user profile.")));
Dries's avatar
 
Dries committed
686
    }
Dries's avatar
 
Dries committed
687
  }
Dries's avatar
 
Dries committed
688 689 690 691 692 693 694 695 696 697
  else if ($object->name) {
    /*
    ** Sometimes modules display content composed by people who are
    ** not registers members of the site (i.e. mailing list or news
    ** aggregator modules).  This clause enables modules to display
    ** the true author of the content.
    */

    $output = $object->name;
  }
Dries's avatar
 
Dries committed
698
  else {
Dries's avatar
 
Dries committed
699
    $output = t(variable_get("anonymous", "Anonymous"));
Dries's avatar
 
Dries committed
700 701
  }

Dries's avatar
 
Dries committed
702
  return $output;
Dries's avatar
 
Dries committed
703 704 705
}

function form($form, $method = "post", $action = 0, $options = 0) {
Dries's avatar
 
Dries committed
706 707

  if (!$action) {
708
    $action = request_uri();
Dries's avatar
 
Dries committed
709
  }
710
  return "<form action=\"$action\" method=\"$method\"". drupal_attributes($options) .">\n$form\n</form>\n";
Dries's avatar
 
Dries committed
711 712 713
}

function form_item($title, $value, $description = 0) {
Dries's avatar
 
Dries committed
714
  return theme("form_element", $title, $value, $description);
Dries's avatar
 
Dries committed
715
}
Dries's avatar
 
Dries committed
716

Dries's avatar
 
Dries committed
717 718 719
function form_group($legend, $group, $description = 0) {
  return "<fieldset>" . ($legend ? "<legend>$legend</legend>" : "") . $group . ($description ? "<div class=\"description\">$description</div>" : "") . "</fieldset>\n";
}
Dries's avatar
 
Dries committed
720

721
function form_radio($title, $name, $value = 1, $checked = 0, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
722
  return theme("form_element", 0, "<input type=\"radio\" class=\"form-radio\" name=\"edit[$name]\" value=\"". $value ."\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) ." /> $title", $description);
Dries's avatar
 
Dries committed
723 724
}

725
function form_checkbox($title, $name, $value = 1, $checked = 0, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
726
  return form_hidden($name, 0) . theme("form_element", 0, "<input type=\"checkbox\" class=\"form-checkbox\" name=\"edit[$name]\" value=\"". $value ."\"". ($checked ? " checked=\"checked\"" : "") . drupal_attributes($attributes) ." /> $title", $description);
Dries's avatar
 
Dries committed
727 728
}

729
function form_textfield($title, $name, $value, $size, $maxlength, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
730
  $size = $size ? " size=\"$size\"" : "";
Dries's avatar
 
Dries committed
731
  return theme("form_element", $title, "<input type=\"text\" maxlength=\"$maxlength\" class=\"form-text\" name=\"edit[$name]\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description);
Dries's avatar
 
Dries committed
732 733
}

734
function form_password($title, $name, $value, $size, $maxlength, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
735
  $size = $size ? " size=\"$size\"" : "";
Dries's avatar
 
Dries committed
736
  return theme("form_element", $title, "<input type=\"password\" class=\"form-password\" maxlength=\"$maxlength\" name=\"edit[$name]\"$size value=\"". check_form($value) ."\"". drupal_attributes($attributes) ." />", $description);
Dries's avatar
 
Dries committed
737 738
}

739
function form_textarea($title, $name, $value, $cols, $rows, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
740
  $cols = $cols ? " cols=\"$cols\"" : "";
Dries's avatar
 
Dries committed
741
  module_invoke_all("textarea", $name);  // eg. optionally plug in a WYSIWYG editor
Dries's avatar
 
Dries committed
742
  return theme("form_element", $title, "<textarea wrap=\"virtual\"$cols rows=\"$rows\" name=\"edit[$name]\" id=\"edit[$name]\"". drupal_attributes($attributes) .">". check_form($value) ."</textarea>", $description);
Dries's avatar
 
Dries committed
743 744
}

Dries's avatar
 
Dries committed
745
function form_select($title, $name, $value, $options, $description = 0, $extra = 0, $multiple = 0) {
Dries's avatar
 
Dries committed
746
  if (count($options) > 0) {
Kjartan's avatar
Kjartan committed
747
    foreach ($options as $key=>$choice) {
748
      $select .= "<option value=\"$key\"". (is_array($value) ? (in_array($key, $value) ? " selected=\"selected\"" : "") : ($value == $key ? " selected=\"selected\"" : "")) .">". check_form($choice) ."</option>";
Dries's avatar
 
Dries committed
749
    }
Dries's avatar
 
Dries committed
750
    return theme("form_element", $title, "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple " : "") . ($extra ? " $extra" : "") .">$select</select>", $description);
Dries's avatar
 
Dries committed
751 752 753
  }
}

Dries's avatar
 
Dries committed
754 755 756 757 758
function form_radios($title, $name, $value, $options, $description = 0) {
  if (count($options) > 0) {
    foreach ($options as $key=>$choice) {
      $output .= form_radio($choice, $name, $key, ($key == $value));
    }
Dries's avatar
 
Dries committed
759
    return theme("form_element", $title, $output, $description);
Dries's avatar
 
Dries committed
760 761 762
  }
}

763
function form_file($title, $name, $size, $description = 0) {
Dries's avatar
 
Dries committed
764
  return theme("form_element", $title, "<input type=\"file\" class=\"form-file\" name=\"edit[$name]\" size=\"$size\" />\n", $description);
Dries's avatar
 
Dries committed
765 766 767 768 769 770
}

function form_hidden($name, $value) {
  return "<input type=\"hidden\" name=\"edit[$name]\" value=\"". check_form($value) ."\" />\n";
}

771
function form_submit($value, $name = "op", $attributes = 0) {
Dries's avatar
 
Dries committed
772
  return "<input type=\"submit\" class=\"form-submit\" name=\"$name\" value=\"". check_form($value) ."\" />\n";
Dries's avatar
 
Dries committed
773 774
}

Dries's avatar
 
Dries committed
775
function form_weight($title = NULL, $name = "weight", $value = 0, $delta = 10, $description = 0, $extra = 0) {
Dries's avatar
 
Dries committed
776
  for ($n = (-1 * $delta); $n <= $delta; $n++) {
Dries's avatar
 
Dries committed
777 778 779 780 781 782
    $weights[$n] = $n;
  }

  return form_select($title, $name, $value, $weights, $description, $extra);
}

Dries's avatar
 
Dries committed
783 784 785 786
function form_allowed_tags_text() {
  return variable_get("allowed_html", "") ? (t("Allowed HTML tags") .": ". htmlspecialchars(variable_get("allowed_html", ""))) : "";
}

Dries's avatar
 
Dries committed
787 788 789
/**
 * Given an old url, return the alias.
 */
Dries's avatar
 
Dries committed
790 791
function drupal_get_path_alias($path) {
  $map = drupal_get_path_map();
Dries's avatar
 
Dries committed
792

Dries's avatar
 
Dries committed
793 794 795
  if ($map) {
    return array_search($path, $map);
  }
Dries's avatar
 
Dries committed
796 797 798
}

/**
Dries's avatar
 
Dries committed
799
 * Given an alias, return the default url.
Dries's avatar
 
Dries committed
800
 */
Dries's avatar
 
Dries committed
801 802
function drupal_get_normal_path($path) {
  $map = drupal_get_path_map();
Dries's avatar
 
Dries committed
803 804 805
  return $map[$path];
}

Dries's avatar
 
Dries committed
806
function url($url = NULL, $query = NULL) {
Dries's avatar
 
Dries committed
807
  global $base_url;
Dries's avatar
 
Dries committed
808

Dries's avatar
 
Dries committed
809 810 811 812 813 814 815 816 817 818 819
  static $script;

  if (empty($script)) {
    /*
    ** On some webservers such as IIS we can't omit "index.php".  As such 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" : "";
  }

Dries's avatar
 
Dries committed
820
  if ($alias = drupal_get_path_alias($url)) {
Dries's avatar
 
Dries committed
821 822 823
    $url = $alias;
  }

Dries's avatar
 
Dries committed
824
  if (variable_get("clean_url", "0") == "0") {
Dries's avatar
 
Dries committed
825 826
    if (isset($url)) {
      if (isset($query)) {
Dries's avatar
 
Dries committed
827
        return "$base_url/$script?q=$url&amp;$query";
Dries's avatar
 
Dries committed
828 829
      }
      else {
Dries's avatar
 
Dries committed
830
        return "$base_url/$script?q=$url";
Dries's avatar
 
Dries committed
831
      }
Dries's avatar
 
Dries committed
832 833
    }
    else {
Dries's avatar
 
Dries committed
834
      if (isset($query)) {
Dries's avatar
 
Dries committed
835
        return "$base_url/$script?$query";
Dries's avatar
 
Dries committed
836 837
      }
      else {
Dries's avatar
 
Dries committed
838
        return "$base_url/";
Dries's avatar
 
Dries committed
839
      }
Dries's avatar
 
Dries committed
840 841 842
    }
  }
  else {
Dries's avatar
 
Dries committed
843 844
    if (isset($url)) {
      if (isset($query)) {
Dries's avatar
 
Dries committed
845
        return "$base_url/$url?$query";
Dries's avatar
 
Dries committed
846 847
      }
      else {
Dries's avatar
 
Dries committed
848
        return "$base_url/$url";
Dries's avatar
 
Dries committed
849
      }
Dries's avatar
 
Dries committed
850
    }
Dries's avatar
 
Dries committed
851
    else {
Dries's avatar
 
Dries committed
852
      if (isset($query)) {
Dries's avatar
 
Dries committed
853
        return "$base_url/$script?$query";
Dries's avatar
 
Dries committed
854 855
      }
      else {
Dries's avatar
 
Dries committed
856
        return "$base_url/";
Dries's avatar
 
Dries committed
857
      }
Dries's avatar
 
Dries committed
858
    }
Dries's avatar
 
Dries committed
859
  }
Dries's avatar
 
Dries committed
860 861
}

862 863 864 865 866 867 868
function drupal_attributes($attributes = 0) {
  if (is_array($attributes)) {
    $t = array();
    foreach ($attributes as $key => $value) {
      $t[] = "$key=\"$value\"";
    }
    return " ". implode($t, " ");
Dries's avatar
 
Dries committed
869
  }
870
}
Dries's avatar
 
Dries committed
871

872 873
function l($text, $url, $attributes = array(), $query = NULL) {
  return "<a href=\"". url($url, $query) ."\"". drupal_attributes($attributes) .">$text</a>";
Dries's avatar
 
Dries committed
874 875
}

Dries's avatar
 
Dries committed
876
function field_get($string, $name) {
877
  ereg(",?$name=([^,]+)", ", $string", $regs);
Dries's avatar
 
Dries committed
878 879 880 881 882
  return $regs[1];
}

function field_set($string, $name, $value) {
  $rval = ereg_replace(",$name=[^,]+", "", ",$string");
Dries's avatar
 
Dries committed
883
  if (isset($value)) {
Kjartan's avatar
Kjartan committed
884 885
    $rval .= ($rval == "," ? "" : ",") ."$name=$value";
  }
Dries's avatar
 
Dries committed
886 887 888 889
  return substr($rval, 1);
}

function link_page() {
890
  global $custom_links;
Dries's avatar
 
Dries committed
891

892
  if (is_array($custom_links)) {
893 894 895
    return $custom_links;
  }
  else {
Dries's avatar
 
Dries committed
896
    $links = module_invoke_all("link", "page");
897
    array_unshift($links, l(t("home"), "", array("title" => t("Return to the main page."))));
898
    return $links;
Dries's avatar
 
Dries committed
899
  }
Dries's avatar
 
Dries committed
900
}
Dries's avatar
 
Dries committed
901 902

function link_node($node, $main = 0) {
Dries's avatar
 
Dries committed
903
  return module_invoke_all("link", "node", $node, $main);
Dries's avatar
 
Dries committed
904 905
}

Dries's avatar
 
Dries committed
906
function drupal_page_footer() {
Dries's avatar
 
Dries committed
907
  if (variable_get("cache", 0)) {
Dries's avatar
 
Dries committed
908
    page_set_cache();
Dries's avatar
 
Dries committed
909
  }
Dries's avatar
 
Dries committed
910

Dries's avatar
 
Dries committed
911 912 913 914 915
  /*
  ** A hook for modules where modules may take action at the end of a
  ** request good uses include setting a cache, page logging, etc.
  */

Dries's avatar
 
Dries committed
916
  module_invoke_all("exit");
Dries's avatar
 
Dries committed
917 918 919
}

include_once "includes/theme.inc";
Dries's avatar
 
Dries committed
920
include_once "includes/pager.inc";
Dries's avatar
 
Dries committed
921
include_once "includes/menu.inc";
Dries's avatar
 
Dries committed
922
include_once "includes/xmlrpc.inc";
Dries's avatar
 
Dries committed
923
include_once "includes/tablesort.inc";
924

Dries's avatar
 
Dries committed
925 926 927
// set error handler:
set_error_handler("error_handler");

Dries's avatar
 
Dries committed
928
// spit out the correct charset http header
Dries's avatar
 
Dries committed
929
header("Content-Type: text/html; charset=utf-8");
Dries's avatar
 
Dries committed
930

Dries's avatar
 
Dries committed
931 932
// initialize the _GET["q"] prior to loading the modules and invoking their 'init' hook:
if (!empty($_GET["q"])) {
Dries's avatar
 
Dries committed
933
  if ($path = drupal_get_normal_path(trim($_GET["q"], "/"))) {
Dries's avatar
 
Dries committed
934 935 936 937
    $_GET["q"] = $path;
  }
}
else {
Dries's avatar
 
Dries committed
938 939 940 941 942 943
  if ($path = drupal_get_normal_path(variable_get("site_frontpage", "node"))) {
    $_GET["q"] = $path;
  }
  else {
    $_GET["q"] = variable_get("site_frontpage", "node");
  }
Dries's avatar
 
Dries committed
944 945
}

Dries's avatar
 
Dries committed
946 947 948
// initialize installed modules:
module_init();

Dries's avatar
 
Dries committed
949 950 951 952 953 954
if (!user_access("bypass input data check")) {
  if (!valid_input_data($_REQUEST)) {
    die("terminated request because of suspicious input data");
  }
}

Dries's avatar
 
Dries committed
955 956 957 958
// initialize localization system:
$locale = locale_init();

// initialize theme:
Dries's avatar
 
Dries committed
959
$theme = init_theme();
Dries's avatar
 
Dries committed
960

Dries's avatar
 
Dries committed
961
?>