[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

/include/ -> functions_installer.inc.php (source)

   1  <?php # $Id: functions_installer.inc.php 1767 2007-07-12 09:36:32Z garvinhicking $
   2  # Copyright (c) 2003-2005, Jannis Hermanns (on behalf the Serendipity Developer Team)
   3  # All rights reserved.  See LICENSE file for licensing details
   4  
   5  if (IN_serendipity !== true) {
   6      die ("Don't hack!");
   7  }
   8  
   9  if (defined('S9Y_FRAMEWORK_INSTALLER')) {
  10      return;
  11  }
  12  @define('S9Y_FRAMEWORK_INSTALLER', true);
  13  
  14  /**
  15   * Convert a PHP Ini setting to a boolean flag
  16   *
  17   * @access public
  18   * @param   mixed       input variable
  19   * @return  boolean     output variable
  20   */
  21  function serendipity_ini_bool($var) {
  22      return ($var === 'on' || $var == '1');
  23  }
  24  
  25  /**
  26   * convert a size value from a PHP.ini to a bytesize
  27   *
  28   * @access public
  29   * @param   string  size value from PHP.ini
  30   * @return  string  bytesize
  31   */
  32  function serendipity_ini_bytesize($val) {
  33      if ( $val == '' )
  34          return 0;
  35  
  36      switch(substr($val, -1)) {
  37          case 'k':
  38          case 'K':
  39              return (int) $val * 1024;
  40              break;
  41          case 'm':
  42          case 'M':
  43              return (int) $val * 1048576;
  44              break;
  45          default:
  46              return $val;
  47     }
  48  }
  49  
  50  /**
  51   * Update the serendipity_config_local.inc.php file with core information
  52   *
  53   * @access public
  54   * @param   string  Database name
  55   * @param   string  Database prefix
  56   * @param   string  Database host
  57   * @param   string  Database user
  58   * @param   string  Datapase Passwort
  59   * @param   string  Database type
  60   * @param   string  Use persistent connections?
  61   * @param   array   An array of additional variables to be put into the config file
  62   * @return true
  63   */
  64  function serendipity_updateLocalConfig($dbName, $dbPrefix, $dbHost, $dbUser, $dbPass, $dbType, $dbPersistent, $privateVariables = null) {
  65      global $serendipity;
  66      umask(0000);
  67  
  68      $file = 'serendipity_config_local.inc.php';
  69      $path = $serendipity['serendipityPath'];
  70  
  71      $oldconfig = @file_get_contents($path . $file);
  72      $configfp  = fopen($path . $file, 'w');
  73  
  74      if (!is_resource($configfp)) {
  75          $errs[] = sprintf(FILE_WRITE_ERROR, $file);
  76          $errs[] = sprintf(DIRECTORY_RUN_CMD, 'chown -R www:www', $path) . ' (' . WWW_USER . ')';
  77          $errs[] = sprintf(DIRECTORY_RUN_CMD, 'chmod 770'       , $path);
  78          $errs[] = BROWSER_RELOAD;
  79  
  80          return $errs;
  81      }
  82  
  83      if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
  84          $dbName = $_POST['sqlitedbName'];
  85      }
  86  
  87      $file_start    = "<?php\n"
  88                     . "\t/*\n"
  89                     . "\t  Serendipity configuration file\n";
  90      $file_mark     = "\n\t// End of Serendipity configuration file"
  91                     . "\n\t// You can place your own special variables after here:\n";
  92      $file_end      = "\n?>\n";
  93      $file_personal = '';
  94  
  95      preg_match('@' . preg_quote($file_start) . '.*' . preg_quote($file_mark) . '(.+)' . preg_quote($file_end) . '@imsU', $oldconfig, $match);
  96      if (!empty($match[1])) {
  97          $file_personal = $match[1];
  98      }
  99  
 100      fwrite($configfp, $file_start);
 101  
 102      fwrite($configfp, "\t  Written on ". date('r') ."\n");
 103      fwrite($configfp, "\t*/\n\n");
 104  
 105      fwrite($configfp, "\t\$serendipity['versionInstalled']  = '{$serendipity['version']}';\n");
 106      fwrite($configfp, "\t\$serendipity['dbName']            = '" . addslashes($dbName) . "';\n");
 107      fwrite($configfp, "\t\$serendipity['dbPrefix']          = '" . addslashes($dbPrefix) . "';\n");
 108      fwrite($configfp, "\t\$serendipity['dbHost']            = '" . addslashes($dbHost) . "';\n");
 109      fwrite($configfp, "\t\$serendipity['dbUser']            = '" . addslashes($dbUser) . "';\n");
 110      fwrite($configfp, "\t\$serendipity['dbPass']            = '" . addslashes($dbPass) . "';\n");
 111      fwrite($configfp, "\t\$serendipity['dbType']            = '" . addslashes($dbType) . "';\n");
 112      fwrite($configfp, "\t\$serendipity['dbPersistent']      = ". (serendipity_db_bool($dbPersistent) ? 'true' : 'false') .";\n");
 113      if ($serendipity['dbNames']) {
 114          fwrite($configfp, "\t\$serendipity['dbCharset']         = '" . addslashes(SQL_CHARSET) . "';\n");
 115      }
 116  
 117      if (is_array($privateVariables) && count($privateVariables) > 0) {
 118          foreach($privateVariables AS $p_idx => $p_val) {
 119              fwrite($configfp, "\t\$serendipity['{$p_idx}']  = '" . addslashes($p_val) . "';\n");
 120          }
 121      }
 122  
 123      fwrite($configfp, $file_mark .  $file_personal . $file_end);
 124  
 125      fclose($configfp);
 126  
 127      @chmod($path . $file, 0700);
 128      return true;
 129  }
 130  
 131  /**
 132   * Setup the core database tables
 133   *
 134   * Creates the needed tables - beware, they will be empty and need to be stuffed with
 135   * default templates and such...
 136   *
 137   * @access public
 138   * @return null
 139   */
 140  function serendipity_installDatabase() {
 141    global $serendipity;
 142  
 143      $queries = serendipity_parse_sql_tables(S9Y_INCLUDE_PATH . 'sql/db.sql');
 144      $queries = str_replace('{PREFIX}', $serendipity['dbPrefix'], $queries);
 145  
 146      foreach ($queries as $query) {
 147          serendipity_db_schema_import($query);
 148      }
 149  
 150      if (file_exists(S9Y_INCLUDE_PATH . 'sql/preload.sql')) {
 151          $queries = serendipity_parse_sql_inserts(S9Y_INCLUDE_PATH . 'sql/preload.sql');
 152          $queries = str_replace('{PREFIX}', $serendipity['dbPrefix'], $queries);
 153          foreach ($queries as $query) {
 154              serendipity_db_schema_import($query);
 155          }
 156      }
 157  }
 158  
 159  /**
 160   * Check a default value of a config item from the configuration template files
 161   *
 162   * @access public
 163   * @param   string      Name of the config item to check
 164   * @param   string      The default value, if none is found
 165   * @param   boolean     If true, it's the personal config template, if false its the global config template
 166   * @param   string      Protected fields will not be echo'd in the HTML form
 167   * @return  string      The default value
 168   */
 169  function serendipity_query_default($optname, $default, $usertemplate = false, $type = 'string') {
 170      global $serendipity;
 171  
 172      /* I won't tell you the password, it's MD5 anyway, you can't do anything with it */
 173      if ($type == 'protected' && IS_installed === true) {
 174          return '';
 175      }
 176  
 177      switch ($optname) {
 178          case 'permalinkStructure':
 179              return $default;
 180  
 181          case 'dbType' :
 182              if (extension_loaded('mysqli')) {
 183                  $type = 'mysqli';
 184              }
 185              if (extension_loaded('PDO') &&
 186                  in_array('pgsql', PDO::getAvailableDrivers())) {
 187                  $type = 'pdo-postgres';
 188              }
 189              if (extension_loaded('pgsql')) {
 190                  $type = 'postgres';
 191              }
 192              if (extension_loaded('mysql')) {
 193                  $type = 'mysql';
 194              }
 195              return $type;
 196  
 197          case 'serendipityPath':
 198              if (empty($_SERVER['PHP_SELF'])) {
 199                  $test_path1 = $_SERVER['DOCUMENT_ROOT'] . rtrim(dirname($_SERVER['SCRIPT_FILENAME']), '/') . '/';
 200              } else {
 201                  $test_path1 = $_SERVER['DOCUMENT_ROOT'] . rtrim(dirname($_SERVER['PHP_SELF']), '/') . '/';
 202              }
 203              $test_path2 = serendipity_getRealDir(__FILE__);
 204              if (file_exists($test_path1 . 'serendipity_admin.php')) {
 205                  return $test_path1;
 206              } elseif (defined('S9Y_DATA_PATH')) {
 207                  // Shared installation!
 208                  return S9Y_DATA_PATH;
 209              } else {
 210                  return $test_path2;
 211              }
 212  
 213          case 'serendipityHTTPPath':
 214              return rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/';
 215  
 216          case 'baseURL':
 217              $ssl  = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on';
 218              $port = $_SERVER['SERVER_PORT'];
 219  
 220              return sprintf('http%s://%s%s%s',
 221  
 222                              $ssl ? 's' : '',
 223                              preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']),
 224                              (($ssl && $port != 443) || (!$ssl && $port != 80)) ? (':' . $port) : '',
 225                              rtrim(dirname($_SERVER['PHP_SELF']), '/') .'/'
 226                     );
 227  
 228          case 'convert':
 229              $path = array();
 230  
 231              $path[] = ini_get('safe_mode_exec_dir');
 232  
 233              if (isset($_SERVER['PATH'])) {
 234                  $path = array_merge($path, explode(PATH_SEPARATOR, $_SERVER['PATH']));
 235              }
 236  
 237              /* add some other possible locations to the path while we are at it,
 238               * as these are not always included in the apache path */
 239              $path[] = '/usr/X11R6/bin';
 240              $path[] = '/usr/bin';
 241              $path[] = '/usr/local/bin';
 242  
 243              foreach ($path as $dir) {
 244                  if (!empty($dir) && (function_exists('is_executable') && is_readable($dir) && @is_executable($dir . '/convert')) || @is_file($dir . '/convert')) {
 245                      return $dir . '/convert';
 246                  }
 247  
 248                  if (!empty($dir) && (function_exists('is_executable') && is_readable($dir . '/convert') && @is_executable($dir . '/convert.exe')) || @is_file($dir . '/convert.exe')) {
 249                      return $dir . '/convert.exe';
 250                  }
 251              }
 252              return $default;
 253  
 254          case 'rewrite':
 255              return serendipity_check_rewrite($default);
 256  
 257          default:
 258              if ($usertemplate) {
 259                  return serendipity_get_user_var($optname, $serendipity['authorid'], $default);
 260              }
 261  
 262              return $default;
 263      }
 264  }
 265  
 266  /**
 267   * Parse a configuration template file
 268   *
 269   * @access public
 270   * @param   string      Path to the s9y configuration template file
 271   * @param   array       An array of config areas/sections that shall be returned from the template
 272   * @param   array       Restrict the return of template variables to items containing a specific flag
 273   * @return  array        An array with configuration items, keys and values
 274   */
 275  function serendipity_parseTemplate($filename, $areas = null, $onlyFlags=null) {
 276      global $serendipity;
 277  
 278      $userlevel = $serendipity['serendipityUserlevel'];
 279  
 280      if ( !IS_installed ) {
 281          $userlevel = USERLEVEL_ADMIN;
 282      }
 283  
 284      $config = @include($filename);
 285  
 286      foreach ( $config as $n => $category ) {
 287          /* If $areas is an array, we filter out those categories, not within the array */
 288          if ( is_array($areas) && !in_array($n, $areas) ) {
 289              unset($config[$n]);
 290              continue;
 291          }
 292  
 293          foreach ( $category['items'] as $i => $item ) {
 294              $items = &$config[$n]['items'][$i];
 295  
 296              if (!isset($items['userlevel']) || !is_numeric($items['userlevel'])) {
 297                  $items['userlevel'] = USERLEVEL_ADMIN;
 298              }
 299  
 300              if (!isset($items['permission']) && $userlevel < $items['userlevel']) {
 301                  unset($config[$n]['items'][$i]);
 302                  continue;
 303              } elseif (!is_array($items['permission']) && !serendipity_checkPermission($items['permission'])) {
 304                  unset($config[$n]['items'][$i]);
 305                  continue;
 306              } elseif (is_array($items['permission'])) {
 307                  $one_found = false;
 308                  $all_found = true;
 309                  foreach($items['permission'] AS $check_permission) {
 310                      if (serendipity_checkPermission($check_permission)) {
 311                          $one_found = true;
 312                      } else {
 313                          $all_found = false;
 314                      }
 315                  }
 316  
 317                  if (!isset($items['perm_mode'])) {
 318                      $items['perm_mode'] = 'or';
 319                  }
 320  
 321                  if ($items['perm_mode'] == 'or' && !$one_found) {
 322                      unset($config[$n]['items'][$i]);
 323                      continue;
 324                  } elseif ($items['perm_mode'] == 'and' && !$one_found && !$all_found) {
 325                      unset($config[$n]['items'][$i]);
 326                      continue;
 327                  }
 328              }
 329  
 330              if (!isset($items['flags']) || !is_array($items['flags'])) {
 331                  $items['flags'] = array();
 332              }
 333  
 334              if ( is_array($onlyFlags) ) {
 335                  foreach ( $onlyFlags as $onlyFlag ) {
 336                      if ( !in_array($onlyFlag, $items['flags']) ) {
 337                          unset($config[$n]['items'][$i]);
 338                          continue;
 339                      }
 340                  }
 341              }
 342          }
 343  
 344          if (sizeof($config[$n]['items']) < 1) {
 345              unset($config[$n]);
 346          }
 347      }
 348  
 349      return $config;
 350  }
 351  
 352  /**
 353   * Replace some variables within config item values with the right values
 354   *
 355   * @access public
 356   * @param   string  Input string
 357   * @return  string  Output string
 358   */
 359  function serendipity_replaceEmbeddedConfigVars ($s) {
 360      return str_replace(
 361                    array(
 362                      '%clock%'
 363                    ),
 364  
 365                    array(
 366                      date('H:i')
 367                    ),
 368  
 369                    $s);
 370  }
 371  
 372  /**
 373   * Preprocess the configuration value and put it into a HTML output field (radio, password, text, select, ...)
 374   *
 375   * @access public
 376   * @param   string  The type of the configuration item
 377   * @param   string  The name of the configuration item
 378   * @param   string  The current value of the configuration item
 379   * @param   string  The default value of the configuration item
 380   * @return null
 381   */
 382  
 383  function serendipity_guessInput($type, $name, $value='', $default='') {
 384      global $serendipity;
 385  
 386      switch ($type) {
 387          case 'bool':
 388              $value = serendipity_get_bool($value);
 389              echo '<input class="input_radio" id="radio_cfg_' . $name . '_yes" type="radio" name="' . $name . '" value="true" ';
 390              echo (($value == true) ? 'checked="checked"' : ''). ' /><label for="radio_cfg_' . $name . '_yes"> ' . YES . '</label>&nbsp;';
 391              echo '<input class="input_radio" id="radio_cfg_' . $name . '_no" type="radio" name="' . $name . '" value="false" ';
 392              echo (($value == true) ? '' : 'checked="checked"'). ' /><label for="radio_cfg_' . $name . '_no"> ' . NO . '</label>';
 393              break;
 394  
 395          case 'protected':
 396              echo '<input class="input_textbox" type="password" size="30" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
 397              break;
 398  
 399          case 'multilist':
 400              echo '<select name="'. $name .'[]" multiple="multiple" size="5">';
 401              foreach ((array)$default as $k => $v) {
 402                  print_r($v);
 403                  $selected = false;
 404                  foreach((array)$value AS $vk => $vv) {
 405                      if ($vv['confkey'] == $v['confkey']) {
 406                          $selected = true;
 407                      }
 408                  }
 409  
 410                  printf('<option value="%s"%s>%s</option>'. "\n",
 411                        $v['confkey'],
 412                        ($selected ? ' selected="selected"' : ''),
 413                        $v['confvalue']);
 414              }
 415              echo '</select>';
 416              break;
 417  
 418          case 'list':
 419              echo '<select name="'. $name .'">';
 420  
 421              foreach ((array)$default as $k => $v) {
 422                  $selected = ($k == $value);
 423  
 424                  printf('<option value="%s"%s>%s</option>'. "\n",
 425                        $k,
 426                        ($selected ? ' selected="selected"' : ''),
 427                        $v);
 428              }
 429              echo '</select>';
 430              break;
 431  
 432          case 'file':
 433              echo '<input class="input_file" type="file" size="30" name="' . $name . '" />';
 434              break;
 435  
 436          case 'textarea':
 437              echo '<textarea rows="5" cols="40" name="' . $name . '">' . htmlspecialchars($value) . '</textarea>';
 438              break;
 439  
 440          default:
 441              echo '<input class="input_textbox" type="text" size="30" name="' . $name . '" value="' . htmlspecialchars($value) . '" />';
 442              break;
 443      }
 444  }
 445  
 446  /**
 447   * Parses the configuration array and displays the configuration screen
 448   *
 449   * @access public
 450   * @param   array       Configuration superarray
 451   * @param   array       The previous values submitted by the user
 452   * @param   boolean     If true, no HTML FORM container will be emitted
 453   * @param   boolean     If true, the configuration sections will all be folded
 454   * @param   boolean     If true, the user can turn config sections on and off
 455   * @param   boolean     If true, the user can NOT display possibly dangerous options
 456   * @return null
 457   */
 458  function serendipity_printConfigTemplate($config, $from = false, $noForm = false, $folded = true, $allowToggle = true, $showDangerous = false) {
 459      global $serendipity;
 460      if ( $allowToggle ) {
 461  ?>
 462  <script type="text/javascript" language="JavaScript">
 463  function showConfig(id) {
 464      if (document.getElementById) {
 465          el = document.getElementById(id);
 466          if (el.style.display == 'none') {
 467              document.getElementById('option' + id).src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
 468              el.style.display = '';
 469          } else {
 470              document.getElementById('option' + id).src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
 471              el.style.display = 'none';
 472          }
 473      }
 474  }
 475  
 476  var state='<?php echo ($folded === true ? '' : 'none'); ?>';
 477  function showConfigAll(count) {
 478      if (document.getElementById) {
 479          for (i = 1; i <= count; i++) {
 480              document.getElementById('el' + i).style.display = state;
 481              document.getElementById('optionel' + i).src = (state == '' ? '<?php echo serendipity_getTemplateFile('img/minus.png') ?>' : '<?php echo serendipity_getTemplateFile('img/plus.png') ?>');
 482          }
 483  
 484          if (state == '') {
 485              document.getElementById('optionall').src = '<?php echo serendipity_getTemplateFile('img/minus.png') ?>';
 486              state = 'none';
 487          } else {
 488              document.getElementById('optionall').src = '<?php echo serendipity_getTemplateFile('img/plus.png') ?>';
 489              state = '';
 490          }
 491      }
 492  }
 493  </script>
 494  
 495  <?php
 496      }
 497  
 498      if (!$noForm) {
 499  ?>
 500  <form action="?" method="POST">
 501      <div>
 502          <input type="hidden" name="serendipity[adminModule]" value="installer" />
 503          <input type="hidden" name="installAction" value="check" />
 504          <?php echo serendipity_setFormToken(); ?>
 505          <br />
 506  <?php   }
 507      if (sizeof($config) > 1 && $allowToggle) { ?>
 508          <div align="right">
 509              <a style="border:0; text-decoration: none" href="#" onClick="showConfigAll(<?php echo sizeof($config); ?>)" title="<?php echo TOGGLE_ALL; ?>"><img src="<?php echo serendipity_getTemplateFile('img/'. ($folded === true ? 'plus' : 'minus') .'.png') ?>" id="optionall" alt="+/-" border="0" />&nbsp;<?php echo TOGGLE_ALL; ?></a></a><br />
 510          </div>
 511  <?php
 512      }
 513      $el_count = 0;
 514      foreach ($config as $category) {
 515          $el_count++;
 516  ?>
 517          <table width="100%" cellspacing="2">
 518  <?php
 519          if (sizeof($config) > 1) {
 520  ?>
 521              <tr>
 522                  <th align="left" colspan="2" style="padding-left: 15px;">
 523  <?php if ($allowToggle) { ?>
 524                      <a style="border:0; text-decoration: none;" href="#" onClick="showConfig('el<?php echo $el_count; ?>'); return false" title="<?php echo TOGGLE_OPTION; ?>"><img src="<?php echo serendipity_getTemplateFile('img/'. ($folded === true ? 'plus' : 'minus') .'.png') ?>" id="optionel<?php echo $el_count; ?>" alt="+/-" border="0" />&nbsp;<?php echo $category['title']; ?></a>
 525  <?php } else { ?>
 526                      <?php echo $category['title']; ?>
 527  <?php } ?>
 528                  </th>
 529              </tr>
 530  <?php   } ?>
 531              <tr>
 532                  <td>
 533                      <table width="100%" cellspacing="0" cellpadding="3" id="el<?php echo $el_count; ?>">
 534                          <tr>
 535                              <td style="padding-left: 20px;" colspan="2">
 536                                  <?php echo $category['description'] ?>
 537                              </td>
 538                          </tr>
 539  
 540  <?php
 541          foreach ($category['items'] as $item) {
 542  
 543              $value = $from[$item['var']];
 544  
 545              /* Calculate value if we are not installed, how clever :) */
 546              if ($from == false) {
 547                  $value = serendipity_query_default($item['var'], $item['default']);
 548              }
 549  
 550              /* Check for installOnly flag */
 551              if (in_array('installOnly', $item['flags']) && IS_installed === true) {
 552                  continue;
 553              }
 554  
 555              if (in_array('hideValue', $item['flags'])) {
 556                  $value = '';
 557              }
 558              
 559              if (!$showDangerous && $item['view'] == 'dangerous') {
 560                  continue;
 561              }
 562  
 563              if (in_array('config', $item['flags']) && isset($from['authorid'])) {
 564                  $value = serendipity_get_user_config_var($item['var'], $from['authorid'], $item['default']);
 565              }
 566  
 567              if (in_array('parseDescription', $item['flags'])) {
 568                  $item['description'] = serendipity_replaceEmbeddedConfigVars($item['description']);
 569              }
 570  
 571              if (in_array('probeDefault', $item['flags'])) {
 572                  $item['default'] = serendipity_probeInstallation($item['var']);
 573              }
 574  
 575              if (in_array('ifEmpty', $item['flags']) && empty($value)) {
 576                  $value = serendipity_query_default($item['var'], $item['default']);
 577              }
 578  ?>
 579                          <tr>
 580                              <td style="border-bottom: 1px #000000 solid" align="left" valign="top" width="75%">
 581                                  <strong><?php echo $item['title']; ?></strong>
 582                                  <br />
 583                                  <span style="color: #5E7A94; font-size: 8pt;"><?php echo $item['description']; ?></span>
 584                              </td>
 585                              <td style="border-bottom: 1px #000000 solid; font-size: 8pt" align="left" valign="middle" width="25%">
 586                                  <span style="white-space: nowrap"><?php echo serendipity_guessInput($item['type'], $item['var'], $value, $item['default']); ?></span>
 587                              </td>
 588                          </tr>
 589  <?php
 590          }
 591  ?>
 592                      </table><br /><br />
 593                  </td>
 594              </tr>
 595          </table>
 596  <?php
 597      }
 598  
 599      if ($folded && $allowToggle) {
 600          echo '<script type="text/javascript" language="JavaScript">';
 601          for ($i = 1; $i <= $el_count; $i++) {
 602              echo 'document.getElementById("el' . $i . '").style.display = "none";' . "\n";
 603          }
 604          echo '</script>';
 605      }
 606  
 607      if (!$noForm) {
 608  ?>
 609          <input type="submit" value="<?php echo CHECK_N_SAVE; ?>" class="serendipityPrettyButton input_button" />
 610      </div>
 611  </form>
 612  <?php
 613      }
 614  }
 615  
 616  /**
 617   * Parse .sql files for use within Serendipity, query by query,
 618   * accepting only CREATE commands.
 619   *
 620   * @access public
 621   * @param   string  The filename of the SQL file
 622   * @return array    An array of queries to execute
 623   */
 624  function serendipity_parse_sql_tables($filename) {
 625      $in_table = 0;
 626      $queries = array();
 627  
 628      $fp = fopen($filename, 'r', 1);
 629      if ($fp) {
 630          while (!@feof($fp)) {
 631              $line = trim(fgets($fp, 4096));
 632              if ($in_table) {
 633                  $def .= $line;
 634                  if (preg_match('/^\)\s*(type\=\S+|\{UTF_8\})?\s*\;$/i', $line)) {
 635                      $in_table = 0;
 636                      array_push($queries, $def);
 637                  }
 638              } else {
 639                  if (preg_match('#^create table \{PREFIX\}\S+\s*\(#i', $line)) {
 640                      $in_table = 1;
 641                      $def = $line;
 642                  }
 643  
 644                  if (preg_match('#^create\s*(\{fulltext\}|unique|\{fulltext_mysql\})?\s*index#i', $line)) {
 645                      array_push($queries, $line);
 646                  }
 647              }
 648          }
 649          fclose($fp);
 650      }
 651  
 652      return $queries;
 653  }
 654  
 655  /**
 656   * Parse .sql files for use within Serendipity, query by query,
 657   * accepting only INSERT commands.
 658   *
 659   * @access public
 660   * @param   string  The filename of the SQL file
 661   * @return array    An array of queries to execute
 662   */
 663  function serendipity_parse_sql_inserts($filename) {
 664      $queries = array();
 665  
 666      $fp = fopen($filename, 'r', 1);
 667      if ($fp) {
 668          while (!@feof($fp)) {
 669              $line = trim(fgets($fp, 65536));
 670                  if (preg_match('#^insert\s*into.*;$#i', $line)) {
 671                      array_push($queries, $line);
 672                  }
 673              }
 674          }
 675          fclose($fp);
 676  
 677      return $queries;
 678  }
 679  
 680  /**
 681   * Check the serendipity Installation for problems, during installation
 682   *
 683   * @access public
 684   * @return boolean  Errors encountered?
 685   */
 686  function serendipity_checkInstallation() {
 687      global $serendipity, $umask;
 688  
 689      $errs = array();
 690  
 691      serendipity_initPermalinks();
 692  
 693      // Check dirs
 694      if (!is_dir($_POST['serendipityPath'])) {
 695          $errs[] = sprintf(DIRECTORY_NON_EXISTANT, $_POST['serendipityPath']);
 696      }
 697      /* This test has already been passed on the diagnosis page.  Besides
 698         it's a partially bogus test.
 699      elseif (!is_writable($_POST['serendipityPath']) ) {
 700          $errs[] = sprintf(DIRECTORY_WRITE_ERROR, $_POST['serendipityPath']);
 701      }*/
 702      elseif (!is_dir($_POST['serendipityPath'] . $_POST['uploadPath'] ) && @mkdir($_POST['serendipityPath'] . $_POST['uploadPath'], $umask) !== true) {
 703          $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . $_POST['uploadPath']);
 704      }
 705      elseif (!is_writable($_POST['serendipityPath'] . $_POST['uploadPath'])) {
 706          $errs[] = sprintf(DIRECTORY_WRITE_ERROR, $_POST['serendipityPath'] . $_POST['uploadPath']);
 707          $errs[] = sprintf(DIRECTORY_RUN_CMD    , 'chmod go+rws', $_POST['serendipityPath'] . $_POST['uploadPath']);
 708      }
 709  
 710      // Attempt to create the template compile directory, it might already be there, but we just want to be sure
 711      if (!is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @mkdir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
 712          $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
 713          $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'mkdir'      , $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
 714          $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
 715      } elseif (is_dir($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && !is_writeable($_POST['serendipityPath'] . PATH_SMARTY_COMPILE) && @chmod($_POST['serendipityPath'] . PATH_SMARTY_COMPILE, $umask) !== true) {
 716          $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_SMARTY_COMPILE);
 717      }
 718  
 719      // Attempt to create the archives directory
 720      if (!is_dir($_POST['serendipityPath'] . PATH_ARCHIVES) && @mkdir($_POST['serendipityPath'] . PATH_ARCHIVES, $umask) !== true) {
 721          $errs[] = sprintf(DIRECTORY_CREATE_ERROR, $_POST['serendipityPath'] . PATH_ARCHIVES);
 722          $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'mkdir'      , $_POST['serendipityPath'] . PATH_ARCHIVES);
 723          $errs[] = sprintf(DIRECTORY_RUN_CMD     , 'chmod go+rwx', $_POST['serendipityPath'] . PATH_ARCHIVES);
 724      }
 725  
 726      // Check imagick
 727      if ($_POST['magick'] == 'true' && function_exists('is_executable') && !@is_executable($_POST['convert'])) {
 728          $errs[] = sprintf(CANT_EXECUTE_BINARY, 'convert imagemagick');
 729      }
 730  
 731      if ($_POST['dbType'] == 'sqlite' || $_POST['dbType'] == 'sqlite3') {
 732          // We don't want that our SQLite db file can be guessed from other applications on a server
 733          // and have access to our's. So we randomize the SQLite dbname.
 734          $_POST['sqlitedbName'] = $_POST['dbName'] . '_' . md5(time());
 735      }
 736  
 737      if (empty($_POST['dbPrefix']) && empty($serendipity['dbPrefix'])) {
 738          $errs[] = sprintf(EMPTY_SETTING, INSTALL_DBPREFIX);
 739      }
 740  
 741      $serendipity['dbType'] = $_POST['dbType'];
 742      // Probe database
 743      // (do it after the dir stuff, as we need to be able to create the sqlite database)
 744      @include_once($_POST['serendipityPath'] . 'include/db/db.inc.php');
 745      // For shared installations, probe the file on include path
 746      include_once (S9Y_INCLUDE_PATH . 'include/db/db.inc.php');
 747  
 748      if (S9Y_DB_INCLUDED) {
 749          serendipity_db_probe($_POST, $errs);
 750      }
 751  
 752      return (count($errs) > 0 ? $errs : '');
 753  }
 754  
 755  /**
 756   * Create the files needed by Serendipity [htaccess/serendipity_config_local.inc.php]
 757   *
 758   * @access public
 759   * @param   string      Path to the serendipity directory
 760   * @return  true
 761   */
 762  function serendipity_installFiles($serendipity_core = '') {
 763      global $serendipity;
 764  
 765      // This variable is transmitted from serendipity_admin_installer. If an empty variable is used,
 766      // this means that serendipity_installFiles() was called from the auto-updater facility.
 767      if (empty($serendipity_core)) {
 768          $serendipity_core = $serendipity['serendipityPath'];
 769      }
 770  
 771      $htaccess = @file_get_contents($serendipity_core . '.htaccess');
 772  
 773      // Let this function be callable outside installation and let it use existing settings.
 774      $import = array('rewrite', 'serendipityHTTPPath', 'indexFile');
 775      foreach($import AS $key) {
 776          if (empty($_POST[$key]) && isset($serendipity[$key])) {
 777              $$key = $serendipity[$key];
 778          } else {
 779              $$key = $_POST[$key];
 780          }
 781      }
 782  
 783      if (php_sapi_name() == 'cgi' || php_sapi_name() == 'cgi-fcgi') {
 784          $htaccess_cgi = '_cgi';
 785      } else {
 786          $htaccess_cgi = '';
 787      }
 788  
 789      /* If this file exists, a previous install failed painfully. We must consider the safer alternative now */
 790      if (file_exists($serendipity_core . '.installer_detection_failsafe')) {
 791          $htaccess_cgi = '_cgi';
 792          @unlink($serendipity_core . '.htaccess');
 793      }
 794  
 795      /* Detect comptability with php_value directives */
 796      if ($htaccess_cgi == '') {
 797          $response = '';
 798          $serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
 799          $serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
 800  
 801          $old_htaccess = @file_get_contents($serendipity_core . '.htaccess');
 802          $fp = @fopen($serendipity_core . '.htaccess', 'w');
 803          if ($fp) {
 804              fwrite($fp, 'php_value register_globals off'. "\n" .'php_value session.use_trans_sid 0');
 805              fclose($fp);
 806              
 807              $safeFP = @fopen($serendipity_core . '.installer_detection_failsafe', 'w');
 808              fclose($safeFP);
 809              $sock = fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
 810              if ($sock) {
 811                  fputs($sock, "GET {$serendipityHTTPPath} HTTP/1.0\r\n");
 812                  fputs($sock, "Host: $serendipity_host\r\n");
 813                  fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
 814                  fputs($sock, "Connection: close\r\n\r\n");
 815  
 816                  while (!feof($sock) && strlen($response) < 4096) {
 817                      $response .= fgets($sock, 400);
 818                  }
 819                  fclose($sock);
 820              }
 821  
 822              # If we get HTTP 500 Internal Server Error, we have to use the .cgi template
 823              if (preg_match('@^HTTP/\d\.\d 500@', $response)) {
 824                  $htaccess_cgi = '_cgi';
 825              }
 826  
 827              if (!empty($old_htaccess)) {
 828                  $fp = @fopen($serendipity_core . '.htaccess', 'w');
 829                  fwrite($fp, $old_htaccess);
 830                  fclose($fp);
 831              } else {
 832                  @unlink($serendipity_core . '.htaccess');
 833              }
 834  
 835              @unlink($serendipity_core . '.installer_detection_failsafe');
 836          }
 837      }
 838  
 839  
 840      if ($rewrite == 'rewrite') {
 841          $template = 'htaccess' . $htaccess_cgi . '_rewrite.tpl';
 842      } elseif ($rewrite == 'errordocs') {
 843          $template = 'htaccess' . $htaccess_cgi . '_errordocs.tpl';
 844      } else {
 845          $template = 'htaccess' . $htaccess_cgi . '_normal.tpl';
 846      }
 847  
 848      if (!($a = file(S9Y_INCLUDE_PATH . 'include/tpl/' . $template, 1))) {
 849          $errs[] = ERROR_TEMPLATE_FILE;
 850      }
 851  
 852      // When we write this file we cannot rely on the constants defined
 853      // earlier, as they do not yet contain the updated contents from the
 854      // new config. Thus we re-define those. We do still use constants
 855      // for backwards/code compatibility.
 856  
 857      $PAT = serendipity_permalinkPatterns(true);
 858  
 859      $content = str_replace(
 860                   array(
 861                     '{PREFIX}',
 862                     '{indexFile}',
 863                     '{PAT_UNSUBSCRIBE}', '{PATH_UNSUBSCRIBE}',
 864                     '{PAT_ARCHIVES}', '{PATH_ARCHIVES}',
 865                     '{PAT_FEEDS}', '{PATH_FEEDS}',
 866                     '{PAT_FEED}',
 867                     '{PAT_ADMIN}', '{PATH_ADMIN}',
 868                     '{PAT_ARCHIVE}', '{PATH_ARCHIVE}',
 869                     '{PAT_PLUGIN}', '{PATH_PLUGIN}',
 870                     '{PAT_DELETE}', '{PATH_DELETE}',
 871                     '{PAT_APPROVE}', '{PATH_APPROVE}',
 872                     '{PAT_SEARCH}', '{PATH_SEARCH}',
 873                     '{PAT_COMMENTS}', '{PATH_COMMENTS}',
 874                     '{PAT_CSS}',
 875                     '{PAT_PERMALINK}',
 876                     '{PAT_PERMALINK_AUTHORS}',
 877                     '{PAT_PERMALINK_FEEDCATEGORIES}',
 878                     '{PAT_PERMALINK_CATEGORIES}',
 879                     '{PAT_PERMALINK_FEEDAUTHORS}'
 880                   ),
 881  
 882                   array(
 883                     $serendipityHTTPPath,
 884                     $indexFile,
 885                     trim($PAT['UNSUBSCRIBE'], '@/i'), $serendipity['permalinkUnsubscribePath'],
 886                     trim($PAT['ARCHIVES'], '@/i'),    $serendipity['permalinkArchivesPath'],
 887                     trim($PAT['FEEDS'], '@/i'),       $serendipity['permalinkFeedsPath'],
 888                     trim(PAT_FEED, '@/i'),
 889                     trim($PAT['ADMIN'], '@/i'),       $serendipity['permalinkAdminPath'],
 890                     trim($PAT['ARCHIVE'], '@/i'),     $serendipity['permalinkArchivePath'],
 891                     trim($PAT['PLUGIN'], '@/i'),      $serendipity['permalinkPluginPath'],
 892                     trim($PAT['DELETE'], '@/i'),      $serendipity['permalinkDeletePath'],
 893                     trim($PAT['APPROVE'], '@/i'),     $serendipity['permalinkApprovePath'],
 894                     trim($PAT['SEARCH'], '@/i'),      $serendipity['permalinkSearchPath'],
 895                     trim($PAT['COMMENTS'], '@/i'),    $serendipity['permalinkCommentsPath'],
 896                     trim(PAT_CSS, '@/i'),
 897                     trim($PAT['PERMALINK'], '@/i'),
 898                     trim($PAT['PERMALINK_AUTHORS'], '@/i'),
 899                     trim($PAT['PERMALINK_FEEDCATEGORIES'], '@/i'),
 900                     trim($PAT['PERMALINK_CATEGORIES'], '@/i'),
 901                     trim($PAT['PERMALINK_FEEDAUTHORS'], '@/i')
 902                   ),
 903  
 904                   implode('', $a)
 905                );
 906  
 907      $fp = @fopen($serendipity_core . '.htaccess', 'w');
 908      if (!$fp) {
 909          $errs[] = sprintf(FILE_WRITE_ERROR, $serendipity_core . '.htaccess') . ' ' . FILE_CREATE_YOURSELF;
 910          $errs[] = sprintf(COPY_CODE_BELOW , $serendipity_core . '.htaccess', 'serendipity', htmlspecialchars($content));
 911          return $errs;
 912      } else {
 913          // Check if an old htaccess file existed and try to preserve its contents. Otherwise completely wipe the file.
 914          if ($htaccess != '' && preg_match('@^(.*)#\s+BEGIN\s+s9y.*#\s+END\s+s9y(.*)$@isU', $htaccess, $match)) {
 915              // Code outside from s9y-code was found.
 916              fwrite($fp, $match[1] . $content . $match[2]);
 917          } else {
 918              fwrite($fp, $content);
 919          }
 920          fclose($fp);
 921          return true;
 922      }
 923  
 924  }
 925  
 926  /**
 927   * Check the flags of a configuration item for their belonging into a template
 928   *
 929   * @access public
 930   * @param   array       An item to check
 931   * @param   array       The area (configuration|local) where the config item might be displayed
 932   * @return  boolean
 933   */
 934  function serendipity_checkConfigItemFlags(&$item, $area) {
 935  
 936      if ( in_array('nosave', $item['flags']) ) {
 937          return false;
 938      }
 939  
 940      if ( in_array('local', $item['flags']) && $area == 'configuration' ) {
 941          return false;
 942      }
 943  
 944      if ( in_array('config', $item['flags']) && $area == 'local' ) {
 945          return false;
 946      }
 947  
 948      return true;
 949  }
 950  
 951  /**
 952   * When paths or other options are changed in the s9y configuration, update the core files
 953   *
 954   * @access public
 955   * @return boolean
 956   */
 957  function serendipity_updateConfiguration() {
 958      global $serendipity, $umask;
 959  
 960      // Save all basic config variables to the database
 961      $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
 962  
 963      if (isset($_POST['sqlitedbName']) && !empty($_POST['sqlitedbName'])) {
 964          $_POST['dbName'] = $_POST['sqlitedbName'];
 965      }
 966  
 967      // Password can be hidden in re-configuring, but we need to store old password
 968      if (empty($_POST['dbPass']) && !empty($serendipity['dbPass'])) {
 969          $_POST['dbPass'] = $serendipity['dbPass'];
 970      }
 971  
 972      foreach($config as $category) {
 973          foreach ( $category['items'] as $item ) {
 974  
 975              /* Don't save trash */
 976              if ( !serendipity_checkConfigItemFlags($item, 'configuration') ) {
 977                  continue;
 978              }
 979  
 980              if (!isset($item['userlevel'])) {
 981                  $item['userlevel'] = USERLEVEL_ADMIN;
 982              }
 983  
 984              // Check permission set. Changes to blogConfiguration or siteConfiguration items
 985              // always required authorid = 0, so that it be not specific to a userlogin
 986              if ( $serendipity['serendipityUserlevel'] >= $item['userlevel'] || IS_installed === false ) {
 987                  $authorid = 0;
 988              } elseif ($item['permission'] == 'blogConfiguration' && serendipity_checkPermission('blogConfiguration')) {
 989                  $authorid = 0;
 990              } elseif ($item['permission'] == 'siteConfiguration' && serendipity_checkPermission('siteConfiguration')) {
 991                  $authorid = 0;
 992              } else {
 993                  $authorid = $serendipity['authorid'];
 994              }
 995  
 996              if (is_array($_POST[$item['var']])) {
 997                  // Arrays not allowed. Use first index value.
 998                  list($a_key, $a_val) = each($_POST[$item['var']]);
 999                  $_POST[$item['var']] = $a_key;
1000  
1001                  // If it still is an array, munge it all together.
1002                  if (is_array($_POST[$item['var']])) {
1003                      $_POST[$item['var']] = @implode(',', $_POST[$item['var']]);
1004                  }
1005              }
1006  
1007              serendipity_set_config_var($item['var'], $_POST[$item['var']], $authorid);
1008          }
1009      }
1010  
1011      if (IS_installed === false || serendipity_checkPermission('siteConfiguration')) {
1012          return serendipity_updateLocalConfig($_POST['dbName'],
1013                                               $_POST['dbPrefix'],
1014                                               $_POST['dbHost'],
1015                                               $_POST['dbUser'],
1016                                               $_POST['dbPass'],
1017                                               $_POST['dbType'],
1018                                               $_POST['dbPersistent']);
1019      } else {
1020          return true;
1021      }
1022  }
1023  
1024  /**
1025   * Get the root directory of Serendipity
1026   *
1027   * @access public
1028   * @return  string      The root directory of Serendipity
1029   */
1030  function serendipity_httpCoreDir() {
1031      if (!empty($_SERVER['SCRIPT_FILENAME']) && substr(php_sapi_name(), 0, 3) != 'cgi') {
1032          return dirname($_SERVER['SCRIPT_FILENAME']) . '/';
1033      }
1034  
1035      return $_SERVER['DOCUMENT_ROOT'] . dirname($_SERVER['PHP_SELF']) . '/';
1036  }
1037  
1038  /**
1039   * Delete obsolete files from Serendipity
1040   *
1041   * @access public
1042   * @param   array       List of files to remove (backup is tried)
1043   * @return boolean
1044   */
1045  function serendipity_removeFiles($files = null) {
1046      global $serendipity, $errors;
1047  
1048      if (!is_array($files)) {
1049          return;
1050      }
1051  
1052      $backupdir = S9Y_INCLUDE_PATH . 'backup';
1053      if (!is_dir($backupdir)) {
1054          @mkdir($backupdir, 0777);
1055          if (!is_dir($backupdir)) {
1056              $errors[] = sprintf(DIRECTORY_CREATE_ERROR, $backupdir);
1057              return false;
1058          }
1059      }
1060  
1061      if (!is_writable($backupdir)) {
1062          $errors[] = sprintf(DIRECTORY_WRITE_ERROR, $backupdir);
1063          return false;
1064      }
1065  
1066      foreach($files AS $file) {
1067          $source   = S9Y_INCLUDE_PATH . $file;
1068          $sanefile = str_replace('/', '_', $file);
1069          $target   = $backupdir . '/' . $sanefile;
1070  
1071          if (!file_exists($source)) {
1072              continue;
1073          }
1074  
1075          if (file_exists($target)) {
1076              $target = $backupdir . '/' . time() . '.' . $sanefile; // Backupped file already exists. Append with timestamp as name.
1077          }
1078  
1079          if (!is_writable($source)) {
1080              $errors[] = sprintf(FILE_WRITE_ERROR, $source) . '<br />';
1081          } else {
1082              rename($source, $target);
1083          }
1084      }
1085  }
1086  
1087  /**
1088   * Get the real directory of this function file
1089   *
1090   * @access public
1091   * @param   string      A filename to strip extra paths from
1092   * @return  string      The real directory name
1093   */
1094  function serendipity_getRealDir($file) {
1095      $dir = str_replace( "\\", "/", dirname($file));
1096      $base = preg_replace('@/include$@', '', $dir) . '/';
1097      return $base;
1098  }
1099  
1100  /**
1101   * Try to detect if apache URL rewriting is available
1102   *
1103   * This function makes a dummy HTTP request and sees if it works
1104   *
1105   * @access public
1106   * @param   string      The default option when rewrite fails
1107   * @return  string      The best preference option for URL rewriting
1108   */
1109  function serendipity_check_rewrite($default) {
1110      global $serendipity;
1111  
1112      if (IS_installed == true) {
1113          return $default;
1114      }
1115  
1116      $serendipity_root = dirname($_SERVER['PHP_SELF']) . '/';
1117      $serendipity_core = serendipity_httpCoreDir();
1118      $old_htaccess     = @file_get_contents($serendipity_core . '.htaccess');
1119      $fp               = @fopen($serendipity_core . '.htaccess', 'w');
1120      $serendipity_host = preg_replace('@^([^:]+):?.*$@', '\1', $_SERVER['HTTP_HOST']);
1121  
1122      if (!$fp) {
1123          printf(HTACCESS_ERROR,
1124            '<b>chmod go+rwx ' . getcwd() . '/</b>'
1125          );
1126          return $default;
1127      } else {
1128          fwrite($fp, 'ErrorDocument 404 ' . addslashes($serendipity_root) . 'index.php');
1129          fclose($fp);
1130  
1131          // Do a request on a nonexistant file to see, if our htaccess allows ErrorDocument
1132          $sock = @fsockopen($serendipity_host, $_SERVER['SERVER_PORT'], $errorno, $errorstring, 10);
1133          $response = '';
1134  
1135          if ($sock) {
1136              fputs($sock, "GET {$_SERVER['PHP_SELF']}nonexistant HTTP/1.0\r\n");
1137              fputs($sock, "Host: $serendipity_host\r\n");
1138              fputs($sock, "User-Agent: Serendipity/{$serendipity['version']}\r\n");
1139              fputs($sock, "Connection: close\r\n\r\n");
1140  
1141              while (!feof($sock) && strlen($response) < 4096) {
1142                  $response .= fgets($sock, 400);
1143              }
1144              fclose($sock);
1145          }
1146  
1147          if (preg_match('@^HTTP/\d\.\d 200@', $response) && preg_match('@X\-Blog: Serendipity@', $response)) {
1148              $default = 'errordocs';
1149          } else {
1150              $default = 'none';
1151          }
1152  
1153          if (!empty($old_htaccess)) {
1154              $fp = @fopen($serendipity_core . '.htaccess', 'w');
1155              fwrite($fp, $old_htaccess);
1156              fclose($fp);
1157          } else {
1158              @unlink($serendipity_core . '.htaccess');
1159          }
1160  
1161          return $default;
1162      }
1163  }
1164  
1165  /**
1166   * Remove old configuration values that are no longer used by Serendipity
1167   *
1168   * @access public
1169   * @return null
1170   */
1171  function serendipity_removeObsoleteVars() {
1172  global $serendipity;
1173  
1174      $config = serendipity_parseTemplate(S9Y_CONFIG_TEMPLATE);
1175      foreach($config as $category) {
1176          foreach($category['items'] as $item) {
1177              /* Remove trash */
1178              if (!serendipity_checkConfigItemFlags($item, 'remove')) {
1179                  serendipity_remove_config_var($item['var'], 0);
1180              }
1181          }
1182      }
1183  }
1184  


Généré le : Sat Nov 24 09:00:37 2007 par Balluche grâce à PHPXref 0.7
  Clicky Web Analytics