[ Index ]
 

Code source de Horde 3.1.3

Accédez au Source d'autres logiciels libresSoutenez Angelica Josefina !

title

Body

[fermer]

/lib/ -> Horde.php (source)

   1  <?php
   2  
   3  include_once 'Log.php';
   4  include_once  'Horde/Util.php';
   5  
   6  /**
   7   * The Horde:: class provides the functionality shared by all Horde
   8   * applications.
   9   *
  10   * $Horde: framework/Horde/Horde.php,v 1.489.2.54 2006/07/31 08:49:47 jan Exp $
  11   *
  12   * Copyright 1999-2006 Chuck Hagenbuch <chuck@horde.org>
  13   * Copyright 1999-2006 Jon Parise <jon@horde.org>
  14   *
  15   * See the enclosed file COPYING for license information (LGPL). If you
  16   * did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
  17   *
  18   * @author  Chuck Hagenbuch <chuck@horde.org>
  19   * @author  Jon Parise <jon@horde.org>
  20   * @since   Horde 1.3
  21   * @package Horde_Framework
  22   */
  23  class Horde {
  24  
  25      /**
  26       * Logs a message to the global Horde log backend.
  27       *
  28       * @param mixed $message     Either a string or a PEAR_Error object.
  29       * @param string $file       What file was the log function called from
  30       *                           (e.g. __FILE__)?
  31       * @param integer $line      What line was the log function called from
  32       *                           (e.g. __LINE__)?
  33       * @param integer $priority  The priority of the message. One of:
  34       * <pre>
  35       * PEAR_LOG_EMERG
  36       * PEAR_LOG_ALERT
  37       * PEAR_LOG_CRIT
  38       * PEAR_LOG_ERR
  39       * PEAR_LOG_WARNING
  40       * PEAR_LOG_NOTICE
  41       * PEAR_LOG_INFO
  42       * PEAR_LOG_DEBUG
  43       * </pre>
  44       */
  45      function logMessage($message, $file, $line, $priority = PEAR_LOG_INFO)
  46      {
  47          global $conf;
  48  
  49          if (!$conf['log']['enabled']) {
  50              return;
  51          }
  52  
  53          if ($priority > $conf['log']['priority']) {
  54              return;
  55          }
  56  
  57          $logger = &Horde::getLogger();
  58          if (!is_a($logger, 'Log')) {
  59              Horde::fatal(PEAR::raiseError('An error has occurred. Furthermore, Horde encountered an error attempting to log this error. Please check your Horde logging configuration in horde/config/conf.php.'), __FILE__, __LINE__, false);
  60          }
  61  
  62          if (is_a($message, 'PEAR_Error')) {
  63              $userinfo = $message->getUserInfo();
  64              $message = $message->getMessage();
  65              if (!empty($userinfo)) {
  66                  if (is_array($userinfo)) {
  67                      $userinfo = @implode(', ', $userinfo);
  68                  }
  69                  $message .= ': ' . $userinfo;
  70              }
  71          } elseif (is_callable(array($message, 'getMessage'))) {
  72              $message = $message->getMessage();
  73          }
  74  
  75          $app = isset($GLOBALS['registry']) ? $GLOBALS['registry']->getApp() : 'horde';
  76          $message = '[' . $app . '] ' . $message . ' [on line ' . $line . ' of "' . $file . '"]';
  77  
  78          /* Make sure to log in the system's locale. */
  79          $locale = setlocale(LC_TIME, 0);
  80          setlocale(LC_TIME, 'C');
  81  
  82          $logger->log($message, $priority);
  83  
  84          /* Restore original locale. */
  85          setlocale(LC_TIME, $locale);
  86  
  87          return true;
  88      }
  89  
  90      /**
  91       */
  92      function &getLogger()
  93      {
  94          global $conf;
  95  
  96          if (empty($conf['log']['enabled'])) {
  97              return false;
  98          }
  99  
 100          static $logcheck;
 101          if (!isset($logcheck)) {
 102              // Try to make sure that we can log messages somehow.
 103              if (empty($conf['log']) ||
 104                  empty($conf['log']['type']) ||
 105                  empty($conf['log']['name']) ||
 106                  empty($conf['log']['ident']) ||
 107                  !isset($conf['log']['params'])) {
 108                  Horde::fatal(PEAR::raiseError('Horde is not correctly configured to log error messages. You must configure at least a text file log in horde/config/conf.php.'), __FILE__, __LINE__, false);
 109              }
 110              $logcheck = true;
 111          }
 112  
 113          return $logger = &Log::singleton($conf['log']['type'], $conf['log']['name'],
 114                                           $conf['log']['ident'], $conf['log']['params']);
 115      }
 116  
 117      /**
 118       * Destroys any existing session on login and make sure to use a new
 119       * session ID, to avoid session fixation issues. Should be called before
 120       * checking a login.
 121       */
 122      function getCleanSession()
 123      {
 124          // Make sure to force a completely new session ID and clear
 125          // all session data.
 126          if (version_compare(phpversion(), '4.3.3') !== -1) {
 127              session_regenerate_id();
 128              session_unset();
 129          } else {
 130              @session_destroy();
 131              if (Util::extensionExists('posix')) {
 132                  $new_session_id = md5(microtime() . posix_getpid());
 133              } else {
 134                  $new_session_id = md5(uniqid(mt_rand(), true));
 135              }
 136              session_id($new_session_id);
 137  
 138              // Restart the session, including setting up the session
 139              // handler.
 140              Horde::setupSessionHandler();
 141              @session_start();
 142          }
 143  
 144          /* Reset cookie timeouts, if necessary. */
 145          if (!empty($GLOBALS['conf']['session']['timeout'])) {
 146              $app = $GLOBALS['registry']->getApp();
 147              if (Secret::clearKey($app)) {
 148                  Secret::setKey($app);
 149              }
 150              Secret::setKey('auth');
 151          }
 152      }
 153  
 154      /**
 155       * Aborts with a fatal error, displaying debug information to the user.
 156       *
 157       * @param mixed $error   A PEAR_Error object with debug information or an
 158       *                       error message.
 159       * @param integer $file  The file in which the error occured.
 160       * @param integer $line  The line on which the error occured.
 161       * @param boolean $log   Log this message via Horde::logMessage()?
 162       */
 163      function fatal($error, $file, $line, $log = true)
 164      {
 165          @include_once  'Horde/Auth.php';
 166          @include_once  'Horde/CLI.php';
 167  
 168          $admin = class_exists('Auth') && Auth::isAdmin();
 169          $cli = class_exists('Horde_CLI') && Horde_CLI::runningFromCLI();
 170  
 171          $errortext = '<h1>' . _("A fatal error has occurred") . '</h1>';
 172          if (is_a($error, 'PEAR_Error')) {
 173              $info = array_merge(array('file' => 'conf.php', 'variable' => '$conf'),
 174                                  array($error->getUserInfo()));
 175  
 176              switch ($error->getCode()) {
 177              case HORDE_ERROR_DRIVER_CONFIG_MISSING:
 178                  $message = sprintf(_("No configuration information specified for %s."), $info['name']) . '<br />' .
 179                      sprintf(_("The file %s should contain some %s settings."),
 180                              $GLOBALS['registry']->get('fileroot') . '/config/' . $info['file'],
 181                              sprintf("%s['%s']['params']", $info['variable'], $info['driver']));
 182                  break;
 183  
 184              case HORDE_ERROR_DRIVER_CONFIG:
 185                  $message = sprintf(_("Required \"%s\" not specified in %s configuration."), $info['field'], $info['name']) . '<br />' .
 186                      sprintf(_("The file %s should contain a %s setting."),
 187                              $GLOBALS['registry']->get('fileroot') . '/config/' . $info['file'],
 188                              sprintf("%s['%s']['params']['%s']", $info['variable'], $info['driver'], $info['field']));
 189                  break;
 190  
 191              default:
 192                  $message = $error->getMessage();
 193                  break;
 194              }
 195  
 196              $errortext .= '<h3>' . htmlspecialchars($message) . '</h3>';
 197          } elseif (is_object($error) && method_exists($error, 'getMessage')) {
 198              $errortext .= '<h3>' . htmlspecialchars($error->getMessage()) . '</h3>';
 199          } elseif (is_string($error)) {
 200              $errortext .= '<h3>' . htmlspecialchars($error) . '</h3>';
 201          }
 202  
 203          if ($admin) {
 204              $errortext .= '<p><code>' . sprintf(_("[line %s of %s]"), $line, $file) . '</code></p>';
 205              if (is_object($error)) {
 206                  $errortext .= '<h3>' . _("Details (also in Horde's logfile):") . '</h3>';
 207                  $errortext .= '<p><pre>' . htmlspecialchars(Util::bufferOutput('var_dump', $error)) . '</pre></p>';
 208              }
 209          } elseif ($log) {
 210              $errortext .= '<h3>' . _("Details have been logged for the administrator.") . '</h3>';
 211          }
 212  
 213          // Log the error via Horde::logMessage() if requested.
 214          if ($log) {
 215              Horde::logMessage($error, $file, $line, PEAR_LOG_EMERG);
 216          }
 217  
 218          if ($cli) {
 219              echo strip_tags(str_replace(array('<br />', '<p>', '</p>', '<h1>', '</h1>', '<h3>', '</h3>'), "\n", $errortext));
 220          } else {
 221              echo <<< HTML
 222  <html>
 223  <head><title>Horde :: Fatal Error</title></head>
 224  <body style="background:#fff; color:#000">$errortext</body>
 225  </html>
 226  HTML;
 227          }
 228          exit;
 229      }
 230  
 231      /**
 232       * Adds the javascript code to the output (if output has already started)
 233       * or to the list of script files to include via includeScriptFiles().
 234       *
 235       * @param string $file     The full javascript file name.
 236       * @param string $app      The application name. Defaults to the current
 237       *                         application.
 238       * @param boolean $direct  Include the file directly without passing it
 239       *                         through javascript.php?
 240       */
 241      function addScriptFile($file, $app = null, $direct = false)
 242      {
 243          global $registry;
 244          static $included = array();
 245  
 246          if (empty($app)) {
 247              $app = $registry->getApp();
 248          }
 249  
 250          // Skip any js files that have since been deprecated.
 251          $ignored_files = array('horde' => array('tooltip.js' => 1));
 252          if (!empty($ignored_files[$app][$file])) {
 253              return;
 254          }
 255  
 256          // Don't include scripts multiple times.
 257          if (!empty($included[$app][$file])) {
 258              return;
 259          }
 260          $included[$app][$file] = true;
 261  
 262          // Explicitly check for a non-PHP version of the script.
 263          if (!$direct && file_exists($file{0} == '/' ? $registry->get('fileroot', $app) . $file : $registry->get('jsfs', $app) . '/' . $file)) {
 264              $direct = true;
 265          }
 266  
 267          // If headers have already been sent, we need to output a
 268          // <script> tag directly.
 269          if (ob_get_length() || headers_sent()) {
 270              if ($direct) {
 271                  $url = Horde::url($file{0} == '/' ? $registry->get('webroot', $app) . $file : $registry->get('jsuri', $app) . '/' . $file);
 272              } else {
 273                  $url = Horde::url($registry->get('webroot', 'horde') . '/services/javascript.php');
 274                  $url = Util::addParameter($url, array('file' => $file,
 275                                                        'app'  => $app));
 276              }
 277              echo '<script type="text/javascript" src="' . $url . '"></script>' . "\n";
 278          } else {
 279              global $_horde_script_files;
 280              $_horde_script_files[$app][] = array($file, $direct);
 281          }
 282      }
 283  
 284      /**
 285       * Includes javascript files that were needed before any headers were sent.
 286       */
 287      function includeScriptFiles()
 288      {
 289          global $_horde_script_files, $registry;
 290  
 291          /* If there is no javascript available, there's no point in including
 292           * the rest of the files. */
 293          if (!$GLOBALS['browser']->hasFeature('javascript')) {
 294              return;
 295          }
 296  
 297          /* Add general UI js library. */
 298          Horde::addScriptFile('horde.js', 'horde', true);
 299          if ($GLOBALS['browser']->hasQuirk('windowed_controls')) {
 300              /* Fixes for IE that can't easily be done without browser
 301               * detection. */
 302              Horde::addScriptFile('horde.ie.js', 'horde', true);
 303          }
 304  
 305          if (!empty($_horde_script_files)) {
 306              $base_url = Horde::url($registry->get('webroot', 'horde') . '/services/javascript.php');
 307              foreach ($_horde_script_files as $app => $files) {
 308                  foreach ($files as $file) {
 309                      if (!empty($file[1])) {
 310                          $url = $file[0]{0} == '/' ? $registry->get('webroot', $app) . $file[0] : $registry->get('jsuri', $app) . '/' . $file[0];
 311                          echo '<script type="text/javascript" src="' . Horde::url($url) . "\"></script>\n";
 312                      } else {
 313                          $url = Util::addParameter($base_url, array('file' => $file[0],
 314                                                                     'app'  => $app));
 315                          echo '<script type="text/javascript" src="' . $url . "\"></script>\n";
 316                      }
 317                  }
 318              }
 319          }
 320      }
 321  
 322      /**
 323       * Includes javascript files that were needed before any headers were sent.
 324       */
 325      function inlineScriptFiles()
 326      {
 327          global $_horde_script_files, $registry;
 328  
 329          if (!empty($_horde_script_files)) {
 330              $jsWrapper = $registry->get('fileroot', 'horde') . '/services/javascript.php';
 331              foreach ($_horde_script_files as $app => $files) {
 332                  foreach ($files as $file) {
 333                      if (!empty($file[1])) {
 334                          @readfile($file[0]{0} == '/' ? $registry->get('fileroot', $app) . $file[0] : $registry->get('jsfs', $app) . '/' . $file[0]);
 335                      } else {
 336                          $file = $file[0];
 337                          require $jsWrapper;
 338                      }
 339                  }
 340              }
 341          }
 342      }
 343  
 344      /**
 345       * Checks if link should be shown and return the nescessary code.
 346       *
 347       * @param string  $type      Type of link to display
 348       * @param string  $app       The name of the current Horde application.
 349       * @param boolean $override  Override Horde settings?
 350       * @param boolean $referrer  Include the current page as the referrer (url=)?
 351       *
 352       * @return string  The HTML to create the link.
 353       */
 354      function getServiceLink($type, $app, $override = false, $referrer = true)
 355      {
 356          if (!Horde::showService($type) && !$override) {
 357              return false;
 358          }
 359  
 360          switch ($type) {
 361          case 'help':
 362              if ($GLOBALS['browser']->hasFeature('javascript')) {
 363                  Horde::addScriptFile('popup.js', 'horde', true);
 364              }
 365              $url = Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/help/', true);
 366              return Util::addParameter($url, 'module', $app);
 367  
 368          case 'problem':
 369              return Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/problem.php?return_url=' . urlencode(Horde::selfUrl(true, true, true)));
 370  
 371          case 'logout':
 372              return Horde::url(Auth::addLogoutParameters($GLOBALS['registry']->get('webroot', 'horde') . '/login.php', AUTH_REASON_LOGOUT));
 373  
 374          case 'login':
 375              return Auth::getLoginScreen('', $referrer ? Horde::selfUrl(true) : null);
 376  
 377          case 'options':
 378              global $conf;
 379              if (($conf['prefs']['driver'] != '') && ($conf['prefs']['driver'] != 'none')) {
 380                  return Horde::url($GLOBALS['registry']->get('webroot', 'horde') . '/services/prefs.php?app=' . $app);
 381              }
 382              break;
 383          }
 384  
 385          return false;
 386      }
 387  
 388      /**
 389       * @param string $type  The type of link.
 390       *
 391       * @return boolean  True if the link is to be shown.
 392       */
 393      function showService($type)
 394      {
 395          global $conf;
 396  
 397          if (empty($conf['menu']['links'][$type])) {
 398              return false;
 399          }
 400  
 401          switch ($conf['menu']['links'][$type]) {
 402          case 'all':
 403              return true;
 404  
 405          case 'never':
 406              return false;
 407  
 408          case 'authenticated':
 409              return (bool)Auth::getAuth();
 410  
 411          default:
 412              return false;
 413          }
 414      }
 415  
 416      /**
 417       * Returns the driver parameters for the specified backend.
 418       *
 419       * @param mixed $backend  The backend system (e.g. 'prefs', 'categories',
 420       *                        'contacts') being used.
 421       *                        The used configuration array will be
 422       *                        $conf[$backend]. If an array gets passed, it will
 423       *                        be $conf[$key1][$key2].
 424       * @param string $type    The type of driver.
 425       *
 426       * @return array  The connection parameters.
 427       */
 428      function getDriverConfig($backend, $type = 'sql')
 429      {
 430          global $conf;
 431  
 432          $c = null;
 433          if (is_array($backend)) {
 434              require_once  'Horde/Array.php';
 435              $c = Horde_Array::getElement($conf, $backend);
 436          } elseif (isset($conf[$backend])) {
 437              $c = $conf[$backend];
 438          }
 439          if (!is_null($c) && isset($c['params'])) {
 440              if (isset($conf[$type])) {
 441                  return array_merge($conf[$type], $c['params']);
 442              } else {
 443                  return $c['params'];
 444              }
 445          }
 446  
 447          return isset($conf[$type]) ? $conf[$type] : array();
 448      }
 449  
 450  
 451      /**
 452       * Returns the VFS driver parameters for the specified backend.
 453       *
 454       * @param string $name  The VFS system name (e.g. 'images', 'documents')
 455       *                      being used.
 456       *
 457       * @return array  A hash with the VFS parameters; the VFS driver in 'type'
 458       *                and the connection parameters in 'params'.
 459       */
 460      function getVFSConfig($name)
 461      {
 462          global $conf;
 463  
 464          if (!isset($conf[$name]['type'])) {
 465              return PEAR::raiseError(_("You must configure a VFS backend."));
 466          }
 467  
 468          if ($conf[$name]['type'] == 'horde') {
 469              $vfs = $conf['vfs'];
 470          } else {
 471              $vfs = $conf[$name];
 472          }
 473  
 474          if ($vfs['type'] == 'sql') {
 475              $vfs['params'] = Horde::getDriverConfig($name, 'sql');
 476          }
 477  
 478          return $vfs;
 479      }
 480  
 481      /**
 482       * Checks if all necessary parameters for a driver configuration
 483       * are set and throws a fatal error with a detailed explaination
 484       * how to fix this, if something is missing.
 485       *
 486       * @param array $params     The configuration array with all parameters.
 487       * @param string $driver    The key name (in the configuration array) of
 488       *                          the driver.
 489       * @param array $fields     An array with mandatory parameter names for
 490       *                          this driver.
 491       * @param string $name      The clear text name of the driver. If not
 492       *                          specified, the application name will be used.
 493       * @param string $file      The configuration file that should contain
 494       *                          these settings.
 495       * @param string $variable  The name of the configuration variable.
 496       */
 497      function assertDriverConfig($params, $driver, $fields, $name = null,
 498                                  $file = 'conf.php', $variable = '$conf')
 499      {
 500          global $registry;
 501  
 502          // Don't generate a fatal error if we fail during or before
 503          // Registry instantiation.
 504          if (is_null($name)) {
 505              $name = isset($registry) ? $registry->getApp() : '[unknown]';
 506          }
 507          $fileroot = isset($registry) ? $registry->get('fileroot') : '';
 508  
 509          if (!is_array($params) || !count($params)) {
 510              Horde::fatal(PEAR::raiseError(
 511                  sprintf(_("No configuration information specified for %s."), $name) . "\n\n" .
 512                  sprintf(_("The file %s should contain some %s settings."),
 513                      $fileroot . '/config/' . $file,
 514                      sprintf("%s['%s']['params']", $variable, $driver))),
 515                  __FILE__, __LINE__);
 516          }
 517  
 518          foreach ($fields as $field) {
 519              if (!isset($params[$field])) {
 520                  Horde::fatal(PEAR::raiseError(
 521                      sprintf(_("Required \"%s\" not specified in %s configuration."), $field, $name) . "\n\n" .
 522                      sprintf(_("The file %s should contain a %s setting."),
 523                          $fileroot . '/config/' . $file,
 524                          sprintf("%s['%s']['params']['%s']", $variable, $driver, $field))),
 525                      __FILE__, __LINE__);
 526              }
 527          }
 528      }
 529  
 530      /**
 531       * Returns a session-id-ified version of $uri.
 532       * If a full URL is requested, all parameter separators get converted to
 533       * "&", otherwise to "&amp;".
 534       *
 535       * @param string $uri              The URI to be modified.
 536       * @param boolean $full            Generate a full (http://server/path/)
 537       *                                 URL.
 538       * @param integer $append_session  0 = only if needed, 1 = always, -1 =
 539       *                                 never.
 540       *
 541       * @return string  The URL with the session id appended (if needed).
 542       */
 543      function url($uri, $full = false, $append_session = 0, $force_ssl = false)
 544      {
 545          if ($force_ssl) {
 546              $full = true;
 547          }
 548  
 549          if ($full) {
 550              global $conf, $registry, $browser;
 551  
 552              /* Store connection parameters in local variables. */
 553              $server_name = $conf['server']['name'];
 554              $server_port = $conf['server']['port'];
 555  
 556              $protocol = 'http';
 557              if ($conf['use_ssl'] == 1) {
 558                  $protocol = 'https';
 559              } elseif ($conf['use_ssl'] == 2 &&
 560                        $browser->usingSSLConnection()) {
 561                  $protocol = 'https';
 562              } elseif ($conf['use_ssl'] == 3) {
 563                  $server_port = '';
 564                  if ($force_ssl) {
 565                      $protocol = 'https';
 566                  }
 567              }
 568  
 569              /* If using non-standard ports, add the port to the URL. */
 570              if (!empty($server_port) &&
 571                  ((($protocol == 'http') && ($server_port != 80)) ||
 572                   (($protocol == 'https') && ($server_port != 443)))) {
 573                  $server_name .= ':' . $server_port;
 574              }
 575  
 576              /* Store the webroot in a local variable. */
 577              $webroot = $registry->get('webroot');
 578  
 579              $url = $protocol . '://' . $server_name;
 580              if (substr($uri, 0, 1) != '/') {
 581                  if (substr($webroot, -1) == '/') {
 582                      $url .= $webroot . $uri;
 583                  } else {
 584                      $url .= $webroot . '/' . $uri;
 585                  }
 586              } else {
 587                  $url .= $uri;
 588              }
 589          } else {
 590              $url = $uri;
 591          }
 592  
 593          if (empty($GLOBALS['conf']['session']['use_only_cookies']) &&
 594              (($append_session == 1) ||
 595               (($append_session == 0) &&
 596                !isset($_COOKIE[session_name()])))) {
 597              $url = Util::addParameter($url, session_name(), session_id());
 598          }
 599  
 600          if ($full) {
 601              /* We need to run the replace twice, because we only catch every
 602               * second match. */
 603              return preg_replace(array('/(=?.*?)&amp;(.*?=)/',
 604                                        '/(=?.*?)&amp;(.*?=)/'),
 605                                  '$1&$2', $url);
 606          } elseif (preg_match('/=.*&amp;.*=/', $url)) {
 607              return $url;
 608          } else {
 609              return htmlentities($url);
 610          }
 611      }
 612  
 613      /**
 614       * Returns a session-id-ified version of $uri, using the current
 615       * application's webroot setting.
 616       *
 617       * @param string $uri              The URI to be modified.
 618       * @param boolean $full            Generate a full (http://server/path/)
 619       *                                 URL.
 620       * @param integer $append_session  0 = only if needed, 1 = always, -1 =
 621       *                                 never.
 622       *
 623       * @return string  The url with the session id appended.
 624       */
 625      function applicationUrl($uri, $full = false, $append_session = 0)
 626      {
 627          if ($full) {
 628              return Horde::url($uri, $full, $append_session);
 629          }
 630  
 631          if (substr($uri, 0, 1) != '/') {
 632              $webroot = $GLOBALS['registry']->get('webroot');
 633              if (substr($webroot, -1) != '/') {
 634                  $webroot .= '/';
 635              }
 636              $uri = $webroot . $uri;
 637          }
 638  
 639          return Horde::url($uri, $full, $append_session);
 640      }
 641  
 642      /**
 643       * Returns an external link passed through the dereferrer to strip session
 644       * IDs from the referrer.
 645       *
 646       * @param string $url   The external URL to link to.
 647       * @param boolean $tag  If true, a complete <a> tag is returned, only the
 648       *                      url otherwise.
 649       *
 650       * @return string  The correct link to the dereferrer script.
 651       */
 652      function externalUrl($url, $tag = false)
 653      {
 654          if (isset($_COOKIE[session_name()])) {
 655              $ext = $url;
 656          } else {
 657              $ext = Horde::url($GLOBALS['registry']->get('webroot', 'horde') .
 658                                '/services/go.php', true, -1);
 659  
 660              /* We must make sure there are no &amp's in the URL. */
 661              $url = preg_replace(array('/(=?.*?)&amp;(.*?=)/', '/(=?.*?)&amp;(.*?=)/'), '$1&$2', $url);
 662              $ext = Util::addParameter($ext, 'url', $url);
 663          }
 664          if ($tag) {
 665              $ext = Horde::link($ext, $url, '', '_blank');
 666          }
 667          return $ext;
 668      }
 669  
 670      /**
 671       * Returns a URL to be used for downloading, that takes into account any
 672       * special browser quirks (i.e. IE's broken filename handling).
 673       *
 674       * @param string $filename  The filename of the download data.
 675       * @param array $params     Any additional parameters needed.
 676       * @param string $url       The URL to alter. If none passed in, will use
 677       *                          the file 'view.php' located in the current
 678       *                          module's base directory.
 679       *
 680       * @return string  The download URL.
 681       */
 682      function downloadUrl($filename, $params = array(), $url = null)
 683      {
 684          global $browser;
 685  
 686          $horde_url = false;
 687  
 688          if (is_null($url)) {
 689              global $registry;
 690              $url = Util::addParameter(Horde::url($registry->get('webroot', 'horde') . '/services/download/'), 'module', $registry->getApp());
 691              $horde_url = true;
 692          }
 693  
 694          /* Add parameters. */
 695          if (!is_null($params)) {
 696              $url = Util::addParameter($url, $params);
 697          }
 698  
 699          /* If we are using the default Horde download link, add the
 700           * filename to the end of the URL. Although not necessary for
 701           * many browsers, this should allow every browser to download
 702           * correctly. */
 703          if ($horde_url) {
 704              $url = Util::addParameter($url, 'fn', '/' . rawurlencode($filename));
 705          } elseif ($browser->hasQuirk('break_disposition_filename')) {
 706              /* Some browsers will only obtain the filename correctly
 707               * if the extension is the last argument in the query
 708               * string and rest of the filename appears in the
 709               * PATH_INFO element. */
 710              $filename = rawurlencode($filename);
 711  
 712              /* Get the webserver ID. */
 713              $server = Horde::webServerID();
 714  
 715              /* Get the name and extension of the file.  Apache 2 does
 716               * NOT support PATH_INFO information being passed to the
 717               * PHP module by default, so disable that
 718               * functionality. */
 719              if (($server != 'apache2')) {
 720                  if (($pos = strrpos($filename, '.'))) {
 721                      $name = '/' . preg_replace('/\./', '%2E', substr($filename, 0, $pos));
 722                      $ext = substr($filename, $pos);
 723                  } else {
 724                      $name = '/' . $filename;
 725                      $ext = '';
 726                  }
 727  
 728                  /* Enter the PATH_INFO information. */
 729                  if (($pos = strpos($url, '?'))) {
 730                      $url = substr($url, 0, $pos) . $name . substr($url, $pos);
 731                  } else {
 732                      $url .= $name;
 733                  }
 734              }
 735  
 736              /* Append the extension, if it exists. */
 737              if (($server == 'apache2') || !empty($ext)) {
 738                  $url = Util::addParameter($url, 'fn_ext', '/' . $filename);
 739              }
 740          }
 741  
 742          return $url;
 743      }
 744  
 745      /**
 746       * Returns an anchor tag with the relevant parameters
 747       *
 748       * @param string $url        The full URL to be linked to.
 749       * @param string $title      The link title/description.
 750       * @param string $class      The CSS class of the link.
 751       * @param string $target     The window target to point to.
 752       * @param string $onclick    JavaScript action for the 'onclick' event.
 753       * @param string $title2     The link title (tooltip) (deprecated - just
 754       *                           use $title).
 755       * @param string $accesskey  The access key to use.
 756       * @param array $attributes  Any other name/value pairs to add to the <a>
 757       *                           tag.
 758       * @param boolean $escape    Whether to escape special characters in the
 759       *                           title attribute.
 760       *
 761       * @return string  The full <a href> tag.
 762       */
 763      function link($url, $title = '', $class = '', $target = '', $onclick = '',
 764                    $title2 = '', $accesskey = '', $attributes = array(),
 765                    $escape = true)
 766      {
 767          static $charset;
 768          if (!isset($charset)) {
 769              $charset = NLS::getCharset();
 770          }
 771  
 772          if (!empty($title2)) {
 773              $title = $title2;
 774          }
 775  
 776          $ret = "<a href=\"$url\"";
 777          if (!empty($onclick)) {
 778              $ret .= " onclick=\"$onclick\"";
 779          }
 780          if (!empty($class)) {
 781              $ret .= " class=\"$class\"";
 782          }
 783          if (!empty($target)) {
 784              $ret .= " target=\"$target\"";
 785          }
 786          if (!empty($title)) {
 787              if ($escape) {
 788                  $title = nl2br(@htmlspecialchars(@htmlspecialchars($title, ENT_QUOTES, $charset), ENT_QUOTES, $charset));
 789              }
 790              $ret .= ' title="' . $title . '"';
 791          }
 792          if (!empty($accesskey)) {
 793              $ret .= ' accesskey="' . htmlspecialchars($accesskey) . '"';
 794          }
 795  
 796          foreach ($attributes as $name => $value) {
 797              $ret .= ' ' . htmlspecialchars($name) . '="' . htmlspecialchars($value) . '"';
 798          }
 799  
 800          return "$ret>";
 801      }
 802  
 803      /**
 804       * Uses DOM Tooltips to display the 'title' attribute for
 805       * Horde::link() calls.
 806       *
 807       * @param string $url        The full URL to be linked to
 808       * @param string $status     The JavaScript mouse-over string
 809       * @param string $class      The CSS class of the link
 810       * @param string $target     The window target to point to.
 811       * @param string $onclick    JavaScript action for the 'onclick' event.
 812       * @param string $title      The link title (tooltip).
 813       * @param string $accesskey  The access key to use.
 814       * @param array  $attributes Any other name/value pairs to add to the <a>
 815       *                           tag.
 816       *
 817       * @return string  The full <a href> tag.
 818       */
 819      function linkTooltip($url, $status = '', $class = '', $target = '',
 820                           $onclick = '', $title = '', $accesskey = '',
 821                           $attributes = array())
 822      {
 823          static $charset;
 824          if (!isset($charset)) {
 825              $charset = NLS::getCharset();
 826          }
 827  
 828          if (!empty($title)) {
 829              $title = '&lt;pre&gt;' . preg_replace(array('/\n/', '/((?<!<br)\s{1,}(?<!\/>))/em', '/<br \/><br \/>/', '/<br \/>/'), array('', 'str_repeat("&nbsp;", strlen("$1"))', '&lt;br /&gt; &lt;br /&gt;', '&lt;br /&gt;'), nl2br(@htmlspecialchars(@htmlspecialchars($title, ENT_QUOTES, $charset), ENT_QUOTES, $charset))) . '&lt;/pre&gt;';
 830          }
 831          return Horde::link($url, $title, $class, $target, $onclick, null, $accesskey, $attributes, false);
 832      }
 833  
 834      /**
 835       * Returns an anchor sequence with the relevant parameters for a widget
 836       * with accesskey and text.
 837       *
 838       * @access public
 839       *
 840       * @param string  $url      The full URL to be linked to.
 841       * @param string  $title    The link title/description.
 842       * @param string  $class    The CSS class of the link
 843       * @param string  $target   The window target to point to.
 844       * @param string  $onclick  JavaScript action for the 'onclick' event.
 845       * @param string  $title2   The link title (tooltip) (deprecated - just use
 846       *                          $title).
 847       * @param boolean $nocheck  Don't check if the access key already has been
 848       *                          used. Defaults to false (= check).
 849       *
 850       * @return string  The full <a href>Title</a> sequence.
 851       */
 852      function widget($url, $title = '', $class = 'widget', $target = '',
 853                      $onclick = '', $title2 = '', $nocheck = false)
 854      {
 855          if (!empty($title2)) {
 856              $title = $title2;
 857          }
 858  
 859          $ak = Horde::getAccessKey($title, $nocheck);
 860  
 861          return Horde::link($url, '', $class, $target, $onclick, '', $ak) . Horde::highlightAccessKey($title, $ak) . '</a>';
 862      }
 863  
 864      /**
 865       * Returns a session-id-ified version of $SCRIPT_NAME resp. $PHP_SELF.
 866       *
 867       * @param boolean $script_params Include script parameters like QUERY_STRING and PATH_INFO?
 868       * @param boolean $nocache       Include a nocache parameter in the URL?
 869       * @param boolean $full          Return a full URL?
 870       *
 871       * @return string  The requested URI.
 872       */
 873      function selfUrl($script_params = false, $nocache = true, $full = false,
 874                       $force_ssl = false)
 875      {
 876          if (substr(php_sapi_name(), 0, 3) == 'cgi') {
 877              // When using CGI PHP, SCRIPT_NAME may contain the path to
 878              // the PHP binary instead of the script being run; use
 879              // PHP_SELF instead.
 880              $url = $_SERVER['PHP_SELF'];
 881          } else {
 882              $url = isset($_SERVER['SCRIPT_NAME']) ?
 883                  $_SERVER['SCRIPT_NAME'] :
 884                  $_SERVER['PHP_SELF'];
 885          }
 886  
 887          if ($script_params) {
 888              if (!empty($_SERVER['PATH_INFO'])) {
 889                  $url .= $_SERVER['PATH_INFO'];
 890              }
 891              if (!empty($_SERVER['QUERY_STRING'])) {
 892                  $url .= '?' . $_SERVER['QUERY_STRING'];
 893              }
 894          }
 895  
 896          $url = Horde::url($url, $full, 0, $force_ssl);
 897  
 898          if ($nocache) {
 899              return Util::nocacheUrl($url);
 900          } else {
 901              return $url;
 902          }
 903      }
 904  
 905      /**
 906       * Constructs a correctly-pathed link to an image.
 907       *
 908       * @param string $src   The image file.
 909       * @param string $alt   Text describing the image.
 910       * @param mixed  $attr  Any additional attributes for the image tag. Can be
 911       *                      a pre-built string or an array of key/value pairs
 912       *                      that will be assembled and html-encoded.
 913       * @param string $dir   The root graphics directory.
 914       *
 915       * @return string  The full image tag.
 916       */
 917      function img($src, $alt = '', $attr = '', $dir = null)
 918      {
 919          static $charset;
 920          if (!isset($charset)) {
 921              $charset = NLS::getCharset();
 922          }
 923  
 924          /* If browser does not support images, simply return the ALT text. */
 925          if (!$GLOBALS['browser']->hasFeature('images')) {
 926              return @htmlspecialchars($alt, ENT_COMPAT, $charset);
 927          }
 928  
 929          /* If no directory has been specified, get it from the registry. */
 930          if ($dir === null) {
 931              global $registry;
 932              $dir = $registry->getImageDir();
 933          }
 934  
 935          /* If a directory has been provided, prepend it to the image source. */
 936          if (!empty($dir)) {
 937              $src = $dir . '/' . $src;
 938          }
 939  
 940          /* Build all of the tag attributes. */
 941          $attributes = array('src' => $src,
 942                              'alt' => $alt);
 943          if (is_array($attr)) {
 944              $attributes = array_merge($attributes, $attr);
 945          }
 946          if (empty($attributes['title'])) {
 947              $attributes['title'] = '';
 948          }
 949  
 950          $img = '<img';
 951          foreach ($attributes as $attribute => $value) {
 952              $img .= ' ' . $attribute . '="' . ($attribute == 'src' ? $value : @htmlspecialchars($value, ENT_COMPAT, $charset)) . '"';
 953          }
 954  
 955          /* If the user supplied a pre-built string of attributes, add that. */
 956          if (is_string($attr) && !empty($attr)) {
 957              $img .= ' ' . $attr;
 958          }
 959  
 960          /* Return the closed image tag. */
 961          return $img . ' />';
 962      }
 963  
 964      /**
 965       * Determines the location of the system temporary directory. If a specific
 966       * setting cannot be found, it defaults to /tmp.
 967       *
 968       * @return string  A directory name that can be used for temp files.
 969       *                 Returns false if one could not be found.
 970       */
 971      function getTempDir()
 972      {
 973          global $conf;
 974  
 975          /* If one has been specifically set, then use that */
 976          if (!empty($conf['tmpdir'])) {
 977              $tmp = $conf['tmpdir'];
 978          }
 979  
 980          /* Next, try Util::getTempDir(). */
 981          if (empty($tmp)) {
 982              $tmp = Util::getTempDir();
 983          }
 984  
 985          /* If it is still empty, we have failed, so return false;
 986           * otherwise return the directory determined. */
 987          return empty($tmp) ? false : $tmp;
 988      }
 989  
 990      /**
 991       * Creates a temporary filename for the lifetime of the script, and
 992       * (optionally) registers it to be deleted at request shutdown.
 993       *
 994       * @param string $prefix   Prefix to make the temporary name more
 995       *                         recognizable.
 996       * @param boolean $delete  Delete the file at the end of the request?
 997       * @param string $dir      Directory to create the temporary file in.
 998       * @param boolean $secure  If deleting file, should we securely delete the
 999       *                         file?
1000       *
1001       * @return string   Returns the full path-name to the temporary file or
1002       *                  false if a temporary file could not be created.
1003       */
1004      function getTempFile($prefix = 'Horde', $delete = true, $dir = '',
1005                           $secure = false)
1006      {
1007          if (empty($dir) || !is_dir($dir)) {
1008              $dir = Horde::getTempDir();
1009          }
1010  
1011          return Util::getTempFile($prefix, $delete, $dir, $secure);
1012      }
1013  
1014      /**
1015       * Starts output compression, if requested.
1016       */
1017      function compressOutput()
1018      {
1019          static $started;
1020  
1021          if (isset($started)) {
1022              return;
1023          }
1024  
1025          /* Compress output if requested and possible. */
1026          if ($GLOBALS['conf']['compress_pages'] &&
1027              !$GLOBALS['browser']->hasQuirk('buggy_compression') &&
1028              !(bool)ini_get('zlib.output_compression') &&
1029              !(bool)ini_get('zend_accelerator.compress_all') &&
1030              ini_get('output_handler') != 'ob_gzhandler') {
1031              if (ob_get_level()) {
1032                  ob_end_clean();
1033              }
1034              ob_start('ob_gzhandler');
1035          }
1036  
1037          $started = true;
1038      }
1039  
1040      /**
1041       * Determines if output compression can be used.
1042       *
1043       * @return boolean  True if output compression can be used, false if not.
1044       */
1045      function allowOutputCompression()
1046      {
1047          require_once  'Horde/Browser.php';
1048          $browser = &Browser::singleton();
1049  
1050          /* Turn off compression for buggy browsers. */
1051          if ($browser->hasQuirk('buggy_compression')) {
1052              return false;
1053          }
1054  
1055          return (ini_get('zlib.output_compression') == '' &&
1056                  ini_get('zend_accelerator.compress_all') == '' &&
1057                  ini_get('output_handler') != 'ob_gzhandler');
1058      }
1059  
1060      /**
1061       * Returns the Web server being used.
1062       * PHP string list built from the PHP 'configure' script.
1063       *
1064       * @return string  A web server identification string.
1065       * <pre>
1066       * 'aolserver' = AOL Server
1067       * 'apache1'   = Apache 1.x
1068       * 'apache2'   = Apache 2.x
1069       * 'caudium'   = Caudium
1070       * 'cgi'       = Unknown server - PHP built as CGI program
1071       * 'cli'       = Command Line Interface build
1072       * 'embed'     = Embedded PHP
1073       * 'isapi'     = Zeus ISAPI
1074       * 'milter'    = Milter
1075       * 'nsapi'     = NSAPI
1076       * 'phttpd'    = PHTTPD
1077       * 'pi3web'    = Pi3Web
1078       * 'roxen'     = Roxen/Pike
1079       * 'servlet'   = Servlet
1080       * 'thttpd'    = thttpd
1081       * 'tux'       = Tux
1082       * 'webjames'  = Webjames
1083       * </pre>
1084       */
1085      function webServerID()
1086      {
1087          $server = php_sapi_name();
1088  
1089          if ($server == 'apache') {
1090              return 'apache1';
1091          } elseif (($server == 'apache2filter') ||
1092                    ($server == 'apache2handler')) {
1093              return 'apache2';
1094          } else {
1095              return $server;
1096          }
1097      }
1098  
1099      /**
1100       * Returns the <link> tags for the CSS stylesheets.
1101       *
1102       * @param string|array $app  The Horde application(s).
1103       * @param mixed $theme       The theme to use; specify an empty value to
1104       *                           retrieve the theme from user preferences, and
1105       *                           false for no theme.
1106       * @param boolean $inherit   Inherit Horde-wide CSS?
1107       *
1108       * @return string  <link> tags for CSS stylesheets.
1109       */
1110      function stylesheetLink($apps = null, $theme = '', $inherit = true)
1111      {
1112          if ($theme === '' && isset($GLOBALS['prefs'])) {
1113              $theme = $GLOBALS['prefs']->getValue('theme');
1114          }
1115  
1116          $rtl = isset($GLOBALS['nls']['rtl'][$GLOBALS['language']]);
1117          $css = array();
1118  
1119          $themes_fs = $GLOBALS['registry']->get('themesfs', 'horde');
1120          if ($inherit) {
1121              $themes_uri = Horde::url($GLOBALS['registry']->get('themesuri', 'horde'), false, -1);
1122              $css[] = $themes_uri . '/screen.css';
1123              if (!empty($theme) &&
1124                  file_exists($themes_fs . '/' . $theme . '/screen.css')) {
1125                  $css[] = $themes_uri . '/' . $theme . '/screen.css';
1126              }
1127  
1128              if ($rtl) {
1129                  $css[] = $themes_uri . '/rtl.css';
1130                  if (!empty($theme) &&
1131                      file_exists($themes_fs . '/' . $theme . '/rtl.css')) {
1132                      $css[] = $themes_uri . '/' . $theme . '/rtl.css';
1133                  }
1134              }
1135          }
1136  
1137          if (!empty($apps)) {
1138              if (!is_array($apps)) {
1139                  $apps = array($apps);
1140              }
1141  
1142              foreach ($apps as $app) {
1143                  if ($inherit && $app == 'horde') {
1144                      continue;
1145                  }
1146  
1147                  $themes_fs = $GLOBALS['registry']->get('themesfs', $app);
1148                  $themes_uri = Horde::url($GLOBALS['registry']->get('themesuri', $app), false, -1);
1149                  if (file_exists($themes_fs . '/screen.css')) {
1150                      $css[] = $themes_uri . '/screen.css';
1151                  }
1152                  if (!empty($theme) &&
1153                      file_exists($themes_fs . '/' . $theme . '/screen.css')) {
1154                      $css[] = $themes_uri . '/' . $theme . '/screen.css';
1155                  }
1156  
1157                  if ($rtl) {
1158                      if (file_exists($themes_fs . '/rtl.css')) {
1159                          $css[] = $themes_uri . '/rtl.css';
1160                      }
1161                      if (!empty($theme) &&
1162                          file_exists($themes_fs . '/' . $theme . '/rtl.css')) {
1163                          $css[] = $themes_uri . '/' . $theme . '/rtl.css';
1164                      }
1165                  }
1166              }
1167          }
1168  
1169          $html = '';
1170          foreach ($css as $css_link) {
1171              $html .= '<link href="' . $css_link . '" rel="stylesheet" type="text/css" />' . "\n";
1172          }
1173  
1174          /* Load IE PNG transparency code if needed. */
1175          if ($GLOBALS['browser']->hasQuirk('png_transparency') &&
1176              $GLOBALS['prefs']->getValue('alpha_filter')) {
1177              $url = Horde::url($GLOBALS['registry']->get('jsuri', 'horde') . '/alphaImageLoader.php', true, -1);
1178              $html .= '<style type="text/css"> img { behavior: url("' . $url . '"); } </style>';
1179          }
1180  
1181          /* Load browser specific stylesheets if needed. */
1182          if ($GLOBALS['browser']->isBrowser('msie') && $GLOBALS['browser']->getMajor() < 7) {
1183              $html .= '<link href="' . $GLOBALS['registry']->get('themesuri', 'horde') . '/ie6_or_less.css" rel="stylesheet" type="text/css" />' . "\n";
1184              if ($GLOBALS['browser']->getPlatform() == 'mac') {
1185                  $html .= '<link href="' . $GLOBALS['registry']->get('themesuri', 'horde') . '/ie5mac.css" rel="stylesheet" type="text/css" />' . "\n";
1186              }
1187          }
1188          if ($GLOBALS['browser']->isBrowser('opera')) {
1189              $html .= '<link href="' . $GLOBALS['registry']->get('themesuri', 'horde') . '/opera.css" rel="stylesheet" type="text/css" />' . "\n";
1190          }
1191          if ($GLOBALS['browser']->isBrowser('mozilla') &&
1192              $GLOBALS['browser']->getMajor() >= 5 &&
1193              preg_match('/rv:(.*)\)/', $GLOBALS['browser']->getAgentString(), $revision) &&
1194              $revision[1] <= 1.4) {
1195              $html .= '<link href="' . $GLOBALS['registry']->get('themesuri', 'horde') . '/moz14.css" rel="stylesheet" type="text/css" />' . "\n";
1196          }
1197          if (strpos(strtolower($GLOBALS['browser']->getAgentString()), 'safari') !== false) {
1198              $html .= '<link href="' . $GLOBALS['registry']->get('themesuri', 'horde') . '/safari.css" rel="stylesheet" type="text/css" />' . "\n";
1199          }
1200  
1201          return $html;
1202      }
1203  
1204      /**
1205       * Sets a custom session handler up, if there is one.
1206       */
1207      function setupSessionHandler()
1208      {
1209          global $conf;
1210  
1211          ini_set('url_rewriter.tags', 0);
1212          if (!empty($conf['session']['use_only_cookies'])) {
1213              ini_set('session.use_only_cookies', 1);
1214              if (!empty($conf['cookie']['domain']) &&
1215                  strpos($conf['server']['name'], '.') === false) {
1216                  Horde::logMessage('Session cookies will not work without a FQDN and with a non-empty cookie domain.', __FILE__, __LINE__, PEAR_LOG_WARNING);
1217              }
1218          }
1219          session_set_cookie_params($conf['session']['timeout'],
1220                                    $conf['cookie']['path'], $conf['cookie']['domain'], $conf['use_ssl'] == 1 ? 1 : 0);
1221          session_cache_limiter($conf['session']['cache_limiter']);
1222          session_name(urlencode($conf['session']['name']));
1223  
1224          $type = !empty($conf['sessionhandler']['type']) ? $conf['sessionhandler']['type'] : 'none';
1225  
1226          if ($type == 'external') {
1227              $calls = $conf['sessionhandler']['params'];
1228              session_set_save_handler($calls['open'],
1229                                       $calls['close'],
1230                                       $calls['read'],
1231                                       $calls['write'],
1232                                       $calls['destroy'],
1233                                       $calls['gc']);
1234          } elseif ($type != 'none') {
1235              global $_session_handler;
1236              require_once  'Horde/SessionHandler.php';
1237              $_session_handler = &SessionHandler::singleton($conf['sessionhandler']['type']);
1238              if (!empty($_session_handler) &&
1239                  !is_a($_session_handler, 'PEAR_Error')) {
1240                  ini_set('session.save_handler', 'user');
1241                  session_set_save_handler(array(&$_session_handler, 'open'),
1242                                           array(&$_session_handler, 'close'),
1243                                           array(&$_session_handler, 'read'),
1244                                           array(&$_session_handler, 'write'),
1245                                           array(&$_session_handler, 'destroy'),
1246                                           array(&$_session_handler, 'gc'));
1247              } else {
1248                  Horde::fatal(PEAR::raiseError('Horde is unable to correctly start the custom session handler.'), __FILE__, __LINE__, false);
1249              }
1250          }
1251      }
1252  
1253      /**
1254       * Returns an un-used access key from the label given.
1255       *
1256       * @param string $label     The label to choose an access key from.
1257       * @param boolean $nocheck  Don't check if the access key already has been
1258       *                          used?
1259       *
1260       * @return string  A single lower case character access key or empty
1261       *                 string if none can be found
1262       */
1263      function getAccessKey($label, $nocheck = false, $shutdown = false)
1264      {
1265          /* The access keys already used in this page */
1266          static $_used = array();
1267  
1268          /* The labels already used in this page */
1269          static $_labels = array();
1270  
1271          /* Shutdown call for translators? */
1272          if ($shutdown) {
1273              if (!count($_labels)) {
1274                  return;
1275              }
1276              $script = basename($_SERVER['PHP_SELF']);
1277              $labels = array_keys($_labels);
1278              sort($labels);
1279              $used = array_keys($_used);
1280              sort($used);
1281              $remaining = str_replace($used, array(), 'abcdefghijklmnopqrstuvwxyz');
1282              Horde::logMessage('Access key information for ' . $script, __FILE__, __LINE__);
1283              Horde::logMessage('Used labels: ' . implode(',', $labels), __FILE__, __LINE__);
1284              Horde::logMessage('Used keys: ' . implode('', $used), __FILE__, __LINE__);
1285              Horde::logMessage('Free keys: ' . $remaining, __FILE__, __LINE__);
1286              return;
1287          }
1288  
1289          /* Use access keys at all? */
1290          static $notsupported;
1291          if (!isset($notsupported)) {
1292              $notsupported = !$GLOBALS['browser']->hasFeature('accesskey') ||
1293                  !$GLOBALS['prefs']->getValue('widget_accesskey');
1294          }
1295  
1296          if ($notsupported || !preg_match('/_([A-Za-z])/', $label, $match)) {
1297              return '';
1298          }
1299          $key = $match[1];
1300  
1301          /* Has this key already been used? */
1302          if (isset($_used[strtolower($key)]) &&
1303              !($nocheck && isset($_labels[$label]))) {
1304              return '';
1305          }
1306  
1307          /* Save key and label. */
1308          $_used[strtolower($key)] = true;
1309          $_labels[$label] = true;
1310  
1311          return $key;
1312      }
1313  
1314      /**
1315       * Strips an access key from a label.
1316       * For multibyte charset strings the access key gets removed completely,
1317       * otherwise only the underscore gets removed.
1318       *
1319       * @param string $label  The label containing an access key.
1320       *
1321       * @return string  The label with the access key being stripped.
1322       */
1323      function stripAccessKey($label)
1324      {
1325          include_once HORDE_BASE . '/config/nls.php';
1326          $multibyte = isset($GLOBALS['nls']['multibyte'][NLS::getCharset(true)]);
1327  
1328          return preg_replace('/_([A-Za-z])/',
1329                              $multibyte && preg_match('/[\x80-\xff]/', $label) ? '' : '\1',
1330                              $label);
1331      }
1332  
1333      /**
1334       * Highlights an access key in a label.
1335       *
1336       * @param string $label      The label to to highlight the access key in.
1337       * @param string $accessKey  The access key to highlight.
1338       *
1339       * @return string  The HTML version of the label with the access key
1340       *                 highlighted.
1341       */
1342      function highlightAccessKey($label, $accessKey)
1343      {
1344          $stripped_label = Horde::stripAccesskey($label);
1345  
1346          if (empty($accessKey)) {
1347              return $stripped_label;
1348          }
1349  
1350          if (isset($GLOBALS['nls']['multibyte'][NLS::getCharset(true)])) {
1351              return $stripped_label . '(' . '<span class="accessKey">' .
1352                  strtoupper($accessKey) . '</span>' . ')';
1353          } else {
1354              return str_replace('_' . $accessKey, '<span class="accessKey">' . $accessKey . '</span>', $label);
1355          }
1356      }
1357  
1358      /**
1359       * Returns the appropriate "accesskey" and "title" attributes for an HTML
1360       * tag and the given label.
1361       *
1362       * @param string $label     The title of an HTML element
1363       * @param boolean $nocheck  Don't check if the access key already has been
1364       *                          used?
1365       *
1366       * @return string  The title, and if appropriate, the accesskey attributes
1367       *                 for the element.
1368       */
1369      function getAccessKeyAndTitle($label, $nocheck = false)
1370      {
1371          $ak = Horde::getAccessKey($label, $nocheck);
1372          $attributes = 'title="' . Horde::stripAccessKey($label);
1373          if (!empty($ak)) {
1374              $attributes .= sprintf(_(" (Accesskey %s)"), $ak);
1375              $attributes .= '" accesskey="' . $ak;
1376          }
1377          $attributes .= '"';
1378          return $attributes;
1379      }
1380  
1381      /**
1382       * Returns a label element including an access key for usage in conjuction
1383       * with a form field. User preferences regarding access keys are respected.
1384       *
1385       * @param string $for    The form field's id attribute.
1386       * @param string $label  The label text.
1387       * @param string $ak     The access key to use. If null a new access key
1388       *                       will be generated.
1389       *
1390       * @return string  The html code for the label element.
1391       */
1392      function label($for, $label, $ak = null)
1393      {
1394          global $prefs;
1395  
1396          if (is_null($ak)) {
1397              $ak = Horde::getAccesskey($label, 1);
1398          }
1399          $label = Horde::highlightAccessKey($label, $ak);
1400  
1401          return sprintf('<label for="%s"%s>%s</label>',
1402                         $for,
1403                         !empty($ak) ? ' accesskey="' . $ak . '"' : '',
1404                         $label);
1405      }
1406  
1407      /**
1408       * Redirects to the main Horde login page on authentication failure.
1409       */
1410      function authenticationFailureRedirect()
1411      {
1412          require_once  'Horde/CLI.php';
1413          if (Horde_CLI::runningFromCLI()) {
1414              $cli = &Horde_CLI::singleton();
1415              $cli->fatal(_("You are not authenticated."));
1416          }
1417  
1418          $url = $GLOBALS['registry']->get('webroot', 'horde') . '/login.php';
1419          $url = Util::addParameter($url, array('url' => Horde::selfUrl(true), 'nosidebar' => 1), null, false);
1420          $url = Auth::addLogoutParameters($url);
1421          header('Location: ' . Horde::url($url, true));
1422          exit;
1423      }
1424  
1425      /**
1426       * Provides a standardised function to call a Horde hook, checking whether
1427       * a hook config file exists and whether the function itself exists. If
1428       * these two conditions are not satisfied it will return the specified
1429       * value (by default a PEAR error).
1430       *
1431       * @param string $hook  The function to call.
1432       * @param array  $args  An array of any arguments to pass to the hook
1433       *                      function.
1434       * @param string $app   If specified look for hooks in the config directory
1435       *                      of this app.
1436       * @param mixed $error  What to return if $app/config/hooks.php or $hook
1437       *                      does not exist. If this is the string 'PEAR_Error'
1438       *                      a PEAR error object is returned instead, detailing
1439       *                      the failure.
1440       *
1441       * @return mixed  Either the results of the hook or PEAR error on failure.
1442       */
1443      function callHook($hook, $args = array(), $app = 'horde', $error = 'PEAR_Error')
1444      {
1445          global $registry;
1446          static $hooks_loaded;
1447  
1448          if (!isset($hooks_loaded)) {
1449              if (file_exists($registry->get('fileroot', $app) . '/config/hooks.php')) {
1450                  require_once $registry->get('fileroot', $app) . '/config/hooks.php';
1451                  $hooks_loaded = true;
1452              } else {
1453                  $hooks_loaded = false;
1454              }
1455          }
1456          if ($hooks_loaded && function_exists($hook)) {
1457              return call_user_func_array($hook, $args);
1458          }
1459  
1460          if (is_string($error) && strcmp($error, 'PEAR_Error') == 0) {
1461              $error = PEAR::raiseError(sprintf('Hook %s in application %s not called.', $hook, $app));
1462              Horde::logMessage($error, __FILE__, __LINE__, PEAR_LOG_DEBUG);
1463          }
1464  
1465          return $error;
1466      }
1467  
1468      /**
1469       * Returns the specified permission for the current user.
1470       *
1471       * @since Horde 3.1
1472       *
1473       * @param string $permission  A permission, currently only 'max_blocks'.
1474       *
1475       * @return mixed  The value of the specified permission.
1476       */
1477      function hasPermission($permission)
1478      {
1479          global $perms;
1480  
1481          if (!$perms->exists('horde:' . $permission)) {
1482              return true;
1483          }
1484  
1485          $allowed = $perms->getPermissions('horde:' . $permission);
1486          if (is_array($allowed)) {
1487              switch ($permission) {
1488              case 'max_blocks':
1489                  $allowed = array_reduce($allowed, create_function('$a, $b', 'return max($a, $b);'), 0);
1490                  break;
1491              }
1492          }
1493  
1494          return $allowed;
1495      }
1496  
1497  }


Généré le : Sun Feb 25 18:01:28 2007 par Balluche grâce à PHPXref 0.7