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
?>