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

Dries's avatar
 
Dries committed
4
/**
5
 * @name drupal_title
Dries's avatar
 
Dries committed
6
 * Functions to get and set the title of the current page.
7
 * @{
Dries's avatar
 
Dries committed
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 */
function drupal_set_title($title = NULL) {
  static $stored_title;

  if (isset($title)) {
    $stored_title = $title;
  }
  return $stored_title;
}

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

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

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

/**
30
 * @name drupal_breadcrumb
Dries's avatar
 
Dries committed
31 32 33
 * Functions to get and set the breadcrumb trail of the current page. The
 * breadcrumb trail is represented as an array of links, starting with
 * "home" and proceeding up to but not including the current page.
34
 * @{
Dries's avatar
 
Dries committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
 */
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;
}
55
// @}
Dries's avatar
 
Dries committed
56

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

  static $cache;
Dries's avatar
 
Dries committed
63 64
  static $map;

Dries's avatar
 
Dries committed
65 66
  if ($action == "rebuild") {
    $map = NULL;
Dries's avatar
 
Dries committed
67
    $cache = 0;
Dries's avatar
 
Dries committed
68 69
  }

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

    $cache = 1;
Dries's avatar
 
Dries committed
77 78 79 80 81
  }

  return $map;
}

Dries's avatar
 
Dries committed
82 83 84 85
function drupal_rebuild_path_map() {
  drupal_get_path_map("rebuild");
}

Dries's avatar
 
Dries committed
86 87 88
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
89 90

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

Dries's avatar
 
Dries committed
96
function watchdog($type, $message, $link = NULL) {
Dries's avatar
 
Dries committed
97
  global $user;
Dries's avatar
 
Dries committed
98
  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
99 100 101 102
}

function throttle($type, $rate) {
  if (!user_access("access administration pages")) {
Dries's avatar
 
Dries committed
103
    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
104 105 106 107 108 109 110 111 112
      watchdog("warning", "throttle: '". getenv("REMOTE_ADDR") ."' exceeded submission rate - $throttle->type");
      die(message_throttle());
    }
    else {
      watchdog($type, "throttle");
    }
  }
}

Dries's avatar
 
Dries committed
113 114 115 116
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
117 118 119
  }
}

Dries's avatar
 
Dries committed
120 121 122 123 124 125 126 127 128 129 130 131
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
132 133 134 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
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
160
function message_access() {
Dries's avatar
 
Dries committed
161
  return t("You are not authorized to access this page.");
Dries's avatar
 
Dries committed
162 163 164 165 166 167 168 169 170 171
}

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
172 173
function locale_init() {
  global $languages, $user;
Dries's avatar
 
Dries committed
174 175 176 177 178 179
  if ($user->uid && $languages[$user->language]) {
    return $user->language;
  }
  else {
    return key($languages);
  }
Dries's avatar
 
Dries committed
180 181
}

Dries's avatar
 
Dries committed
182
function t($string, $args = 0) {
Dries's avatar
 
Dries committed
183
  global $languages;
184

Dries's avatar
 
Dries committed
185 186 187 188 189 190 191
  /*
  ** 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
192 193
  **           account</a> before viewing the next page.", array("%url"
  **           => url("user/register")));
Dries's avatar
 
Dries committed
194 195
  */

196
  $string = ($languages && module_exist("locale") ? locale($string) : $string);
197

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

Dries's avatar
 
Dries committed
206
function drupal_specialchars($input, $quotes = ENT_NOQUOTES) {
Dries's avatar
 
Dries committed
207 208 209 210 211 212 213 214 215

  /*
  ** 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
216 217
}

218 219 220 221 222 223
/**
 * 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
224
function valid_email_address($mail) {
225 226 227 228 229 230 231 232 233 234 235 236 237
  $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
238 239 240 241 242 243 244
/**
 * Verify the syntax of the given URL.
 *
 * @param $url  an URL
 */
function valid_url($url) {

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

Kjartan's avatar
Kjartan committed
253 254 255
/**
 * Format a single result entry of a search query:
 *
256 257 258
 * @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
259 260
 * @param $type  module type of this item
 */
Dries's avatar
 
Dries committed
261
function search_item($item, $type) {
Dries's avatar
 
Dries committed
262 263 264 265 266 267 268 269 270 271

  /*
  ** 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
272
    $output .= " <b><u><a href=\"". $item["link"] ."\">". $item["title"] ."</a></u></b><br />";
Dries's avatar
 
Dries committed
273
    $output .= " <small>" . t($type) . ($item["user"] ? " - ". $item["user"] : "") ."". ($item["date"] ? " - ". format_date($item["date"], "small") : "") ."</small>";
Dries's avatar
 
Dries committed
274 275
    $output .= "<br /><br />";
  }
Dries's avatar
 
Dries committed
276 277 278 279

  return $output;
}

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

  if (!$action) {
Dries's avatar
 
Dries committed
297
    $action = url("search");
Dries's avatar
 
Dries committed
298 299
  }

Dries's avatar
 
Dries committed
300 301
  $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
302 303 304 305 306 307 308

  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
309
        $output .= " <input type=\"checkbox\" name=\"edit[type][$name]\" ". ($edit["type"][$name] ? " checked=\"checked\"" : "") ." /> ". t($name);
Dries's avatar
 
Dries committed
310 311 312 313
      }
    }
  }

Kjartan's avatar
Kjartan committed
314 315
  $form .= "<br />";

Dries's avatar
 
Dries committed
316 317 318 319
  return form($output, "post", $action);
}

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

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

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

  return $output;
}

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

Dries's avatar
 
Dries committed
357
  $_POST["edit"]["type"][$type] = "on";
Dries's avatar
 
Dries committed
358

Dries's avatar
 
Dries committed
359
  return search_form($action, $keys, $options) . "<br />". search_data($keys);
Dries's avatar
 
Dries committed
360 361
}

Dries's avatar
 
Dries committed
362

Dries's avatar
 
Dries committed
363 364
function drupal_goto($url) {

Dries's avatar
 
Dries committed
365 366 367
  /*
  ** Translate &amp; to simply &
  */
Dries's avatar
 
Dries committed
368

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

Dries's avatar
 
Dries committed
371 372 373 374 375
  /*
  ** 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
376
  if (!ini_get("session.use_trans_sid") || !session_id() || strstr($url, session_id())) {
Dries's avatar
 
Dries committed
377 378 379
    header("Location: $url");
  }
  else {
Dries's avatar
 
Dries committed
380 381 382 383 384 385 386 387
    $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
388 389 390 391
  }

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

  exit();
}

Dries's avatar
 
Dries committed
399
function valid_input_data($data) {
400

401
  if (is_array($data) || is_object($data)) {
402 403 404 405 406
    /*
    ** Form data can contain a number of nested arrays.
    */

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

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

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

425 426

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

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

  return 1;
436
}
Dries's avatar
 
Dries committed
437

Dries's avatar
 
Dries committed
438
function check_form($text) {
Dries's avatar
 
Dries committed
439
  return drupal_specialchars($text, ENT_QUOTES);
Dries's avatar
 
Dries committed
440 441 442
}

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

Dries's avatar
 
Dries committed
444 445 446 447 448 449 450 451 452 453 454 455 456
  $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
457 458 459 460 461
      $text = module_invoke($name, "filter", $text);
    }
  }

  return $text;
Dries's avatar
 
Dries committed
462 463
}

Dries's avatar
 
Dries committed
464 465
function rewrite_old_urls($text) {

Dries's avatar
 
Dries committed
466 467 468 469
  global $base_url;

  $end = substr($base_url, 12);

Dries's avatar
 
Dries committed
470 471 472
  /*
  ** 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
473 474
  ** (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
475 476 477
  ** and comment bodies.
  */

Dries's avatar
 
Dries committed
478
  if (variable_get("clean_url", "0") == "0") {
Dries's avatar
 
Dries committed
479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
    /*
    ** 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
495
    // rewrite 'node.php?id=<number>[&cid=<number>]' style URLs:
Dries's avatar
 
Dries committed
496
    $text = eregi_replace("$end/(node)\.php\?id=([[:digit:]]+)(&cid=)?([[:digit:]]*)", "$end/?q=\\1/view/\\2/\\4", $text);
Dries's avatar
 
Dries committed
497

Dries's avatar
 
Dries committed
498
    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
Dries's avatar
 
Dries committed
499 500 501
    $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
502 503
  }
  else {
Dries's avatar
 
Dries committed
504 505 506 507
    /*
    ** Relative URLs:
    */

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

    // rewrite 'module.php?mod=<name>{&<op>=<value>}' style URLs:
Dries's avatar
 
Dries committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527
    $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
528

Dries's avatar
 
Dries committed
529 530 531
  return $text;
}

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

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

  return $text;
Dries's avatar
 
Dries committed
547 548
}

549

550 551
function check_file($filename) {
  return is_uploaded_file($filename);
Dries's avatar
 
Dries committed
552 553
}

Dries's avatar
 
Dries committed
554 555 556
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
557
  $output .= "<channel>\n";
Dries's avatar
 
Dries committed
558 559 560 561
  $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
562
  foreach ($args as $key => $value) {
Dries's avatar
 
Dries committed
563
    $output .= " <$key>". drupal_specialchars(strip_tags($value)) ."</$key>\n";
Dries's avatar
 
Dries committed
564
  }
Dries's avatar
 
Dries committed
565 566 567 568 569 570
  $output .= $items;
  $output .= "</channel>\n";

  return $output;
}

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

Dries's avatar
 
Dries committed
574
  $output .= "<item>\n";
Dries's avatar
 
Dries committed
575 576 577
  $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
578
  foreach ($args as $key => $value) {
Dries's avatar
 
Dries committed
579
    $output .= "<$key>". drupal_specialchars(strip_tags($value)) ."</$key>";
Dries's avatar
 
Dries committed
580
  }
Dries's avatar
 
Dries committed
581 582 583 584 585
  $output .= "</item>\n";

  return $output;
}

Dries's avatar
 
Dries committed
586 587 588 589 590 591 592 593 594 595 596 597 598 599
/**
 * 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
600
function format_plural($count, $singular, $plural) {
Dries's avatar
 
Dries committed
601
  return t($count == 1 ? $singular : $plural, array("%count" => $count));
Dries's avatar
 
Dries committed
602 603 604
}

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

function format_interval($timestamp) {
Dries's avatar
 
Dries committed
618
  $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
619
  foreach ($units as $key=>$value) {
Dries's avatar
 
Dries committed
620 621 622 623 624 625
    $key = explode("|", $key);
    if ($timestamp >= $value) {
      $output .= ($output ? " " : "") . format_plural(floor($timestamp / $value), $key[0], $key[1]);
      $timestamp %= $value;
    }
  }
Dries's avatar
 
Dries committed
626
  return ($output) ? $output : t("0 sec");
Dries's avatar
 
Dries committed
627 628 629 630 631
}

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

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

  switch ($type) {
    case "small":
Dries's avatar
 
Dries committed
636
      $format = variable_get("date_format_short", "m/d/Y - H:i");
Dries's avatar
 
Dries committed
637 638
      break;
    case "large":
Dries's avatar
 
Dries committed
639
      $format = variable_get("date_format_long", "l, F j, Y - H:i");
Dries's avatar
 
Dries committed
640 641
      break;
    case "custom":
Dries's avatar
 
Dries committed
642
      // No change to format
Dries's avatar
 
Dries committed
643
      break;
Dries's avatar
 
Dries committed
644
    case "medium":
Dries's avatar
 
Dries committed
645
    default:
Dries's avatar
 
Dries committed
646 647 648 649 650 651 652 653 654 655 656 657 658
      $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
659 660 661 662 663 664 665
  }
  return $date;
}

function format_name($object) {

  if ($object->uid && $object->name) {
Dries's avatar
Dries committed
666 667 668 669 670 671 672 673 674 675 676 677
    /*
    ** 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
678
    if (arg(0) == "admin") {
Dries's avatar
Dries committed
679
      $output = l($name, "admin/user/edit/$object->uid", array("title" => t("Administer user profile.")));
Dries's avatar
 
Dries committed
680 681
    }
    else {
Dries's avatar
Dries committed
682
      $output = l($name, "user/view/$object->uid", array("title" => t("View user profile.")));
Dries's avatar
 
Dries committed
683
    }
Dries's avatar
 
Dries committed
684
  }
Dries's avatar
 
Dries committed
685 686 687 688 689 690 691 692 693 694
  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
695
  else {
Dries's avatar
 
Dries committed
696
    $output = t(variable_get("anonymous", "Anonymous"));
Dries's avatar
 
Dries committed
697 698
  }

Dries's avatar
 
Dries committed
699
  return $output;
Dries's avatar
 
Dries committed
700 701 702
}

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

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

function form_item($title, $value, $description = 0) {
Dries's avatar
 
Dries committed
711
  return theme("form_element", $title, $value, $description);
Dries's avatar
 
Dries committed
712
}
Dries's avatar
 
Dries committed
713

Dries's avatar
 
Dries committed
714 715 716
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
717

718
function form_radio($title, $name, $value = 1, $checked = 0, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
719
  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
720 721
}

722
function form_checkbox($title, $name, $value = 1, $checked = 0, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
723
  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
724 725
}

726
function form_textfield($title, $name, $value, $size, $maxlength, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
727
  $size = $size ? " size=\"$size\"" : "";
Dries's avatar
 
Dries committed
728
  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
729 730
}

731
function form_password($title, $name, $value, $size, $maxlength, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
732
  $size = $size ? " size=\"$size\"" : "";
Dries's avatar
 
Dries committed
733
  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
734 735
}

736
function form_textarea($title, $name, $value, $cols, $rows, $description = 0, $attributes = 0) {
Dries's avatar
 
Dries committed
737
  $cols = $cols ? " cols=\"$cols\"" : "";
Dries's avatar
 
Dries committed
738
  module_invoke_all("textarea", $name);  // eg. optionally plug in a WYSIWYG editor
Dries's avatar
 
Dries committed
739
  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
740 741
}

Dries's avatar
 
Dries committed
742
function form_select($title, $name, $value, $options, $description = 0, $extra = 0, $multiple = 0) {
Dries's avatar
 
Dries committed
743
  if (count($options) > 0) {
Kjartan's avatar
Kjartan committed
744
    foreach ($options as $key=>$choice) {
745
      $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
746
    }
Dries's avatar
 
Dries committed
747
    return theme("form_element", $title, "<select name=\"edit[$name]". ($multiple ? "[]" : "") ."\"". ($multiple ? " multiple " : "") . ($extra ? " $extra" : "") .">$select</select>", $description);
Dries's avatar
 
Dries committed
748 749 750
  }
}

Dries's avatar
 
Dries committed
751 752 753 754 755
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
756
    return theme("form_element", $title, $output, $description);
Dries's avatar
 
Dries committed
757 758 759
  }
}

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

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

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

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

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

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

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

Dries's avatar
 
Dries committed
790 791 792
  if ($map) {
    return array_search($path, $map);
  }
Dries's avatar
 
Dries committed
793 794 795
}

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

Dries's avatar
 
Dries committed
803
function url($url = NULL, $query = NULL) {
Dries's avatar
 
Dries committed
804
  global $base_url;
Dries's avatar
 
Dries committed
805

Dries's avatar
 
Dries committed
806 807 808 809 810 811 812 813 814 815 816
  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
817
  if ($alias = drupal_get_path_alias($url)) {
Dries's avatar
 
Dries committed
818 819 820
    $url = $alias;
  }

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

859 860 861 862 863 864 865
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
866
  }
867
}
Dries's avatar
 
Dries committed
868

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

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

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

function link_page() {
887
  global $custom_links;
Dries's avatar
 
Dries committed
888

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

function link_node($node, $main = 0) {
Dries's avatar
 
Dries committed
900
  return module_invoke_all("link", "node", $node, $main);
Dries's avatar
 
Dries committed
901 902
}

Dries's avatar
 
Dries committed
903
function drupal_page_footer() {
Dries's avatar
 
Dries committed
904
  if (variable_get("cache", 0)) {
Dries's avatar
 
Dries committed
905
    page_set_cache();
Dries's avatar
 
Dries committed
906
  }
Dries's avatar
 
Dries committed
907

Dries's avatar
 
Dries committed
908 909 910 911 912
  /*
  ** 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
913
  module_invoke_all("exit");
Dries's avatar
 
Dries committed
914 915 916
}

include_once "includes/theme.inc";
Dries's avatar
 
Dries committed
917
include_once "includes/pager.inc";
Dries's avatar
 
Dries committed
918
include_once "includes/menu.inc";
Dries's avatar
 
Dries committed
919
include_once "includes/xmlrpc.inc";
Dries's avatar
 
Dries committed
920
include_once "includes/tablesort.inc";
921

Dries's avatar
 
Dries committed
922 923 924
// set error handler:
set_error_handler("error_handler");

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

Dries's avatar
 
Dries committed
928 929
// initialize the _GET["q"] prior to loading the modules and invoking their 'init' hook:
if (!empty($_GET["q"])) {
Dries's avatar
 
Dries committed
930
  if ($path = drupal_get_normal_path(trim($_GET["q"], "/"))) {
Dries's avatar
 
Dries committed
931 932 933 934
    $_GET["q"] = $path;
  }
}
else {
Dries's avatar
 
Dries committed
935 936 937 938 939 940
  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
941 942
}

Dries's avatar
 
Dries committed
943 944 945
// initialize installed modules:
module_init();

Dries's avatar
 
Dries committed
946 947 948 949 950 951
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
952 953 954 955
// initialize localization system:
$locale = locale_init();

// initialize theme:
Dries's avatar
 
Dries committed
956
$theme = init_theme();
Dries's avatar
 
Dries committed
957

Dries's avatar
 
Dries committed
958
?>