[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

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

   1  <?php # $Id: functions.inc.php 1721 2007-06-11 14:32: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_FUNCTIONS')) {
  10      return;
  11  }
  12  @define('S9Y_FRAMEWORK_FUNCTIONS', true);
  13  
  14  $serendipity['imageList'] = array();
  15  if (!defined('S9Y_FRAMEWORK_DB')) {
  16      include (S9Y_INCLUDE_PATH . "include/db/db.inc.php");
  17  }
  18  if (!defined('S9Y_FRAMEWORK_COMPAT')) {
  19      include (S9Y_INCLUDE_PATH . "include/compat.inc.php");
  20  }
  21  if (!defined('S9Y_FRAMEWORK_CONFIG')) {
  22      include (S9Y_INCLUDE_PATH . "include/functions_config.inc.php");
  23  }
  24  if (!defined('S9Y_FRAMEWORK_PLUGIN_API')) {
  25      include (S9Y_INCLUDE_PATH . "include/plugin_api.inc.php");
  26  }
  27  if (!defined('S9Y_FRAMEWORK_IMAGES')) {
  28      include (S9Y_INCLUDE_PATH . "include/functions_images.inc.php");
  29  }
  30  if (!defined('S9Y_FRAMEWORK_INSTALLER')) {
  31      include (S9Y_INCLUDE_PATH . "include/functions_installer.inc.php");
  32  }
  33  if (!defined('S9Y_FRAMEWORK_ENTRIES')) {
  34      include (S9Y_INCLUDE_PATH . "include/functions_entries.inc.php");
  35  }
  36  if (!defined('S9Y_FRAMEWORK_COMMENTS')) {
  37      include (S9Y_INCLUDE_PATH . "include/functions_comments.inc.php");
  38  }
  39  if (!defined('S9Y_FRAMEWORK_PERMALINKS')) {
  40      include (S9Y_INCLUDE_PATH . "include/functions_permalinks.inc.php");
  41  }
  42  if (!defined('S9Y_FRAMEWORK_SMARTY')) {
  43      include (S9Y_INCLUDE_PATH . "include/functions_smarty.inc.php");
  44  }
  45  /**
  46   * Truncate a string to a specific length, multibyte aware. Appends '...' if successfully truncated
  47   *
  48   * @access public
  49   * @param   string  Input string
  50   * @param   int     Length the final string should have
  51   * @return  string  Truncated string
  52   */
  53  function serendipity_truncateString($s, $len) {
  54      if ( strlen($s) > ($len+3) ) {
  55          $s = serendipity_mb('substr', $s, 0, $len) . '...';
  56      }
  57      return $s;
  58  }
  59  
  60  /**
  61   * Optionally turn on GZip Compression, if configured
  62   *
  63   * @access public
  64   */
  65  function serendipity_gzCompression() {
  66      global $serendipity;
  67      if (isset($serendipity['useGzip']) && serendipity_db_bool($serendipity['useGzip']) && function_exists('ob_gzhandler') && extension_loaded('zlib') && serendipity_ini_bool(ini_get('zlib.output_compression')) == false && serendipity_ini_bool(ini_get('session.use_trans_sid')) == false) {
  68          ob_start("ob_gzhandler");
  69      }
  70  }
  71  
  72  /**
  73   * Returns a timestamp formatted according to the current Server timezone offset
  74   *
  75   * @access public
  76   * @param  int      The timestamp you want to convert into the current server timezone. Defaults to "now".
  77   * @param  boolean  A toggle to indicate, if the timezone offset should be ADDED or SUBSTRACTED from the timezone. Substracting is required to restore original time when posting an entry.
  78   * @return int      The final timestamp
  79   */
  80  function serendipity_serverOffsetHour($timestamp = null, $negative = false) {
  81      global $serendipity;
  82  
  83      if ($timestamp == null) {
  84          $timestamp = time();
  85      }
  86  
  87      if (empty($serendipity['serverOffsetHours']) || !is_numeric($serendipity['serverOffsetHours']) || $serendipity['serverOffsetHours'] == 0) {
  88          return $timestamp;
  89      } else {
  90          return $timestamp + (($negative ? -$serendipity['serverOffsetHours'] : $serendipity['serverOffsetHours']) * 60 * 60);
  91      }
  92  }
  93  
  94  /* Converts a date string (DD.MM.YYYY, YYYY-MM-DD, MM/DD/YYYY) into a unix timestamp
  95   *
  96   * @access public
  97   * @param  string  The input date
  98   * @return int     The output unix timestamp
  99   */
 100  function &serendipity_convertToTimestamp($in) {
 101      if (preg_match('@([0-9]+)([/\.-])([0-9]+)([/\.-])([0-9]+)@', $in, $m)) {
 102          if ($m[2] != $m[4]) {
 103              return $in;
 104          }
 105  
 106          switch($m[2]) {
 107              case '.':
 108                  return mktime(0, 0, 0, /* month */ $m[3], /* day */ $m[1], /* year */ $m[5]);
 109                  break;
 110  
 111              case '/':
 112                  return mktime(0, 0, 0, /* month */ $m[1], /* day */ $m[3], /* year */ $m[5]);
 113                  break;
 114  
 115              case '-':
 116                  return mktime(0, 0, 0, /* month */ $m[3], /* day */ $m[5], /* year */ $m[1]);
 117                  break;
 118          }
 119  
 120          return $in;
 121      }
 122  
 123      return $in;
 124  }
 125  
 126  /**
 127   * Format a timestamp
 128   *
 129   * This function can convert an input timestamp into specific PHP strftime() outputs, including applying necessary timezone calculations.
 130   *
 131   * @access public
 132   * @param   string      Output format for the timestamp
 133   * @param   int         Timestamp to use for displaying
 134   * @param   boolean     Indicates, if timezone calculations shall be used.
 135   * @param   boolean     Whether to use strftime or simply date
 136   * @return  string      The formatted timestamp
 137   */
 138  function serendipity_strftime($format, $timestamp = null, $useOffset = true, $useDate = false) {
 139      global $serendipity;
 140      static $is_win_utf = null;
 141  
 142      if ($is_win_utf === null) {
 143          // Windows does not have UTF-8 locales.
 144          $is_win_utf = (LANG_CHARSET == 'UTF-8' && strtoupper(substr(PHP_OS, 0, 3)) === 'WIN' ? true : false);
 145      }
 146  
 147      if ($useDate) {
 148          $out = date($format, $timestamp);
 149      } else {
 150          switch($serendipity['calendar']) {
 151              default:
 152              case 'gregorian':
 153                  if ($timestamp == null) {
 154                      $timestamp = serendipity_serverOffsetHour();
 155                  } elseif ($useOffset) {
 156                      $timestamp = serendipity_serverOffsetHour($timestamp);
 157                  }
 158                  $out = strftime($format, $timestamp);
 159                  break;
 160      
 161              case 'persian-utf8':
 162                  if ($timestamp == null) {
 163                      $timestamp = serendipity_serverOffsetHour();
 164                  } elseif ($useOffset) {
 165                      $timestamp = serendipity_serverOffsetHour($timestamp);
 166                  }
 167      
 168                  require_once  S9Y_INCLUDE_PATH . 'include/functions_calendars.inc.php';
 169                  $out = persian_strftime_utf($format, $timestamp);
 170                  break;
 171          }
 172      }
 173  
 174      if ($is_win_utf && (empty($serendipity['calendar']) || $serendipity['calendar'] == 'gregorian')) {
 175          $out = utf8_encode($out);
 176      }
 177  
 178      return $out;
 179  }
 180  
 181  /**
 182   * A wrapper function call for formatting Timestamps.
 183   *
 184   * Utilizes serendipity_strftime() and prepares the output timestamp with a few tweaks, and applies automatic uppercasing of the return.
 185   *
 186   * @see serendipity_strftime()
 187   * @param   string      Output format for the timestamp
 188   * @param   int         Timestamp to use for displaying
 189   * @param   boolean     Indicates, if timezone calculations shall be used.
 190   * @param   boolean     Whether to use strftime or simply date
 191   * @return  string      The formatted timestamp
 192   */
 193  function serendipity_formatTime($format, $time, $useOffset = true, $useDate = false) {
 194      static $cache;
 195      if (!isset($cache)) {
 196          $cache = array();
 197      }
 198  
 199      if (!isset($cache[$format])) {
 200          $cache[$format] = $format;
 201          if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
 202              $cache[$format] = str_replace('%e', '%d', $cache[$format]);
 203          }
 204      }
 205      
 206      return serendipity_mb('ucfirst', serendipity_strftime($cache[$format], (int)$time, $useOffset, $useDate));
 207  }
 208  
 209  /**
 210   * Fetches the list of available templates/themes/styles.
 211   *
 212   * @access public
 213   * @param   string  Directory to search for a template [recursive use]
 214   * @return  array   Sorted array of available template names
 215   */
 216  function serendipity_fetchTemplates($dir = '') {
 217      global $serendipity;
 218  
 219      $cdir = @opendir($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir);
 220      $rv   = array();
 221      if (!$cdir) {
 222          return $rv;
 223      }
 224      while (($file = readdir($cdir)) !== false) {
 225          if (is_dir($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file) && !ereg('^(\.|CVS)', $file) && !file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file . '/inactive.txt')) {
 226              if (file_exists($serendipity['serendipityPath'] . $serendipity['templatePath'] . $dir . $file . '/info.txt')) {
 227                  $key = strtolower($file);
 228                  if (isset($rv[$key])) {
 229                      $key = $dir . $key;
 230                  }
 231                  $rv[$key] = $dir . $file;
 232              } else {
 233                  $temp = serendipity_fetchTemplates($dir . $file . '/');
 234                  if (count($temp) > 0) {
 235                      $rv = array_merge($rv, $temp);
 236                  }
 237              }
 238          }
 239      }
 240      closedir($cdir);
 241      ksort($rv);
 242      return $rv;
 243  }
 244  
 245  /**
 246   * Get information about a specific theme/template/style
 247   *
 248   * @access public
 249   * @param   string  Directory name of a theme
 250   * @param   string  Absolute path to the templates [for use on CVS mounted directories]
 251   * @return  array   Associative array if template information
 252   */
 253  function serendipity_fetchTemplateInfo($theme, $abspath = null) {
 254      global $serendipity;
 255  
 256      if ($abspath === null) {
 257          $abspath = $serendipity['serendipityPath'] . $serendipity['templatePath'];
 258      }
 259  
 260      $lines = @file($abspath . $theme . '/info.txt');
 261      if ( !$lines ) {
 262          return array();
 263      }
 264  
 265      for($x=0; $x<count($lines); $x++) {
 266          $j = preg_split('/([^\:]+)\:/', $lines[$x], -1, PREG_SPLIT_DELIM_CAPTURE);
 267          if ($j[2]) {
 268              $currSec = $j[1];
 269              $data[strtolower($currSec)][] = trim($j[2]);
 270          } else {
 271              $data[strtolower($currSec)][] = trim($j[0]);
 272          }
 273      }
 274  
 275      foreach ($data as $k => $v) {
 276          $data[$k] = implode("\n", $v);
 277      }
 278  
 279      if ( $theme != 'default' && $theme != 'default-rtl'
 280        && @is_dir($serendipity['templatePath'] . $theme . '/admin')
 281        && @is_readable($serendipity['templatePath'] . $theme . '/admin/style.css') ) {
 282  
 283          $data['custom_admin_interface'] = YES;
 284      } else {
 285          $data['custom_admin_interface'] = NO;
 286      }
 287  
 288      return $data;
 289  }
 290  
 291  /**
 292   * Recursively walks an 1-dimensional array to map parent IDs and depths, depending on the nested array set.
 293   *
 294   * Used for sorting a list of comments, for example. The list of comment is iterated, and the nesting level is calculated, and the array will be sorted to represent the amount of nesting.
 295   *
 296   * @access public
 297   * @param   array   Input array to investigate [consecutively sliced for recursive calls]
 298   * @param   string  Array index name to indicate the ID value of an array index
 299   * @param   string  Array index name to indicate the PARENT ID value of an array index, matched against the $child_name value
 300   * @param   int     The parent id to check an element against for recursive nesting
 301   * @param   int     The current depth of the cycled array
 302   * @return  array   The sorted and shiny polished result array
 303   */
 304  function serendipity_walkRecursive($ary, $child_name = 'id', $parent_name = 'parent_id', $parentid = 0, $depth = 0) {
 305      global $serendipity;
 306      static $_resArray;
 307      static $_remain;
 308  
 309      if (!is_array($ary) || sizeof($ary) == 0) {
 310          return array();
 311      }
 312  
 313      if ($parentid === VIEWMODE_THREADED) {
 314          $parentid = 0;
 315      }
 316  
 317      if ($depth == 0) {
 318          $_resArray = array();
 319          $_remain   = $ary;
 320      }
 321  
 322      foreach($ary AS $key => $data) {
 323          if ($parentid === VIEWMODE_LINEAR || !isset($data[$parent_name]) || $data[$parent_name] == $parentid) {
 324              $data['depth'] = $depth;
 325              $_resArray[]   = $data;
 326              unset($_remain[$key]);
 327              if ($data[$child_name] && $parentid !== VIEWMODE_LINEAR ) {
 328                  serendipity_walkRecursive($ary, $child_name, $parent_name, $data[$child_name], ($depth+1));
 329              }
 330          }
 331      }
 332  
 333      /* We are inside a recusive child, and we need to break out */
 334      if ($depth !== 0) {
 335          return true;
 336      }
 337  
 338      if (count($_remain) > 0) {
 339          // Remaining items need to be appended
 340          foreach($_remain AS $key => $data) {
 341              $data['depth'] = 0;
 342              $_resArray[]   = $data;
 343          }
 344      }
 345  
 346      return $_resArray;
 347  }
 348  
 349  /**
 350   * Fetch the list of Serendipity Authors
 351   *
 352   * @access public
 353   * @param   int     Fetch only a specific User
 354   * @param   array   Can contain an array of group IDs you only want to fetch authors of.
 355   * @param   boolean If set to TRUE, the amount of entries per author will also be returned
 356   * @return  array   Result of the SQL query
 357   */
 358  function serendipity_fetchUsers($user = '', $group = null, $is_count = false) {
 359      global $serendipity;
 360  
 361      $where = '';
 362      if (!empty($user)) {
 363          $where = "WHERE a.authorid = '" . (int)$user ."'";
 364      }
 365  
 366      $query_select   = '';
 367      $query_join     = '';
 368      $query_group    = '';
 369      $query_distinct = '';
 370      if ($is_count) {
 371          $query_select = ", count(e.authorid) as artcount";
 372          $query_join   = "LEFT OUTER JOIN {$serendipity['dbPrefix']}entries AS e
 373                                        ON a.authorid = e.authorid";
 374      }
 375  
 376      if ($is_count || $group != null) {
 377          if ($serendipity['dbType'] == 'postgres' ||
 378              $serendipity['dbType'] == 'pdo-postgres') {
 379              // Why does PostgreSQL keep doing this to us? :-)
 380              $query_group    = 'GROUP BY a.authorid, a.realname, a.username, a.password, a.mail_comments, a.mail_trackbacks, a.email, a.userlevel, a.right_publish';
 381              $query_distinct = 'DISTINCT';
 382          } else {
 383              $query_group    = 'GROUP BY a.authorid';
 384              $query_distinct = '';
 385          }
 386      }
 387  
 388  
 389      if ($group === null) {
 390          $querystring = "SELECT $query_distinct
 391                                 a.authorid,
 392                                 a.realname,
 393                                 a.username,
 394                                 a.password,
 395                                 a.mail_comments,
 396                                 a.mail_trackbacks,
 397                                 a.email,
 398                                 a.userlevel,
 399                                 a.right_publish
 400                                 $query_select
 401                            FROM {$serendipity['dbPrefix']}authors AS a
 402                                 $query_join
 403                                 $where
 404                                 $query_group
 405                        ORDER BY a.realname ASC";
 406      } else {
 407          if (is_array($group)) {
 408              foreach($group AS $idx => $groupid) {
 409                  $group[$idx] = (int)$groupid;
 410              }
 411              $group_sql = implode(', ', $group);
 412          } else {
 413              $group_sql = (int)$group;
 414          }
 415  
 416          $querystring = "SELECT $query_distinct
 417                                 a.authorid,
 418                                 a.realname,
 419                                 a.username,
 420                                 a.password,
 421                                 a.mail_comments,
 422                                 a.mail_trackbacks,
 423                                 a.email,
 424                                 a.userlevel,
 425                                 a.right_publish
 426                                 $query_select
 427                            FROM {$serendipity['dbPrefix']}authors AS a
 428                 LEFT OUTER JOIN {$serendipity['dbPrefix']}authorgroups AS ag
 429                              ON a.authorid = ag.authorid
 430                 LEFT OUTER JOIN {$serendipity['dbPrefix']}groups AS g
 431                              ON ag.groupid  = g.id
 432                                 $query_join
 433                           WHERE g.id IN ($group_sql)
 434                                 $where
 435                                 $query_group
 436                        ORDER BY a.realname ASC";
 437      }
 438  
 439      return serendipity_db_query($querystring);
 440  }
 441  
 442  
 443  /**
 444   * Sends a Mail with Serendipity formatting
 445   *
 446   * @access public
 447   * @param   string  The recipient address of the mail
 448   * @param   string  The subject of the mail
 449   * @param   string  The body of the mail
 450   * @param   string  The sender mail address of the mail
 451   * @param   array   additional headers to pass to the E-Mail
 452   * @param   string  The name of the sender
 453   * @return  int     Return code of the PHP mail() function
 454   */
 455  function serendipity_sendMail($to, $subject, $message, $fromMail, $headers = NULL, $fromName = NULL) {
 456      global $serendipity;
 457  
 458      if (!is_null($headers) && !is_array($headers)) {
 459          trigger_error(__FUNCTION__ . ': $headers must be either an array or null', E_USER_ERROR);
 460      }
 461  
 462      if (is_null($fromName) || empty($fromName)) {
 463          $fromName = $serendipity['blogTitle'];
 464      }
 465  
 466      if (is_null($fromMail) || empty($fromMail)) {
 467          $fromMail = $to;
 468      }
 469  
 470      if (is_null($headers)) {
 471          $headers = array();
 472      }
 473  
 474      // Fix special characters
 475      $fromName = str_replace(array('"', "\r", "\n"), array("'", '', ''), $fromName);
 476      $fromMail = str_replace(array("\r","\n"), array('', ''), $fromMail);
 477  
 478      // Prefix all mail with weblog title
 479      $subject = '['. $serendipity['blogTitle'] . '] '.  $subject;
 480  
 481      // Append signature to every mail
 482      $message .= "\n" . sprintf(SIGNATURE, $serendipity['blogTitle']);
 483  
 484      $maildata = array(
 485          'to'       => &$to,
 486          'subject'  => &$subject,
 487          'fromName' => &$fromName,
 488          'fromMail' => &$fromMail,
 489          'blogMail' => $serendipity['blogMail'],
 490          'version'  => 'Serendipity/' . $serendipity['version'],
 491          'legacy'   => true,
 492          'headers'  => &$headers,
 493          'message'  => &$message
 494      );
 495  
 496      serendipity_plugin_api::hook_event('backend_sendmail', $maildata, LANG_CHARSET);
 497  
 498      // This routine can be overridden by a plugin.
 499      if ($maildata['legacy']) {
 500          // Check for mb_* function, and use it to encode headers etc. */
 501          if (function_exists('mb_encode_mimeheader')) {
 502              // mb_encode_mimeheader function insertes linebreaks after 74 chars.
 503              // Usually this is according to spec, but for us it caused more trouble than
 504              // it prevented.
 505              // Regards to Mark Kronsbein for finding this issue!
 506              $maildata['subject'] = str_replace(array("\n", "\r"), array('', ''), mb_encode_mimeheader($maildata['subject'], LANG_CHARSET));
 507              $maildata['fromName'] = str_replace(array("\n", "\r"), array('', ''), mb_encode_mimeheader($maildata['fromName'], LANG_CHARSET));
 508          }
 509  
 510  
 511          // Always add these headers
 512          if (!empty($maildata['blogMail'])) {
 513              $maildata['headers'][] = 'From: "'. $maildata['fromName'] .'" <'. $maildata['blogMail'] .'>';
 514          }
 515          $maildata['headers'][] = 'Reply-To: "'. $maildata['fromName'] .'" <'. $maildata['fromMail'] .'>';
 516          $maildata['headers'][] = 'X-Mailer: ' . $maildata['version'];
 517          $maildata['headers'][] = 'X-Engine: PHP/'. phpversion();
 518          $maildata['headers'][] = 'Message-ID: <'. md5(microtime() . uniqid(time())) .'@'. $_SERVER['HTTP_HOST'] .'>';
 519          $maildata['headers'][] = 'MIME-Version: 1.0';
 520          $maildata['headers'][] = 'Precedence: bulk';
 521          $maildata['headers'][] = 'Content-Type: text/plain; charset=' . LANG_CHARSET;
 522  
 523          if (LANG_CHARSET == 'UTF-8') {
 524              if (function_exists('imap_8bit')) {
 525                  $maildata['headers'][] = 'Content-Transfer-Encoding: quoted-printable';
 526                  $maildata['message']   = str_replace("=\r\n", "", imap_8bit($maildata['message']));
 527              } else {
 528                  $maildata['headers'][] = 'Content-Transfer-Encoding: base64';
 529                  $maildata['message']   = chunk_split(base64_encode($maildata['message']));
 530              }
 531          }
 532      }
 533  
 534      return mail($maildata['to'], $maildata['subject'], $maildata['message'], implode("\n", $maildata['headers']));
 535  }
 536  
 537  /**
 538   * Fetch all references (links) from a given entry ID
 539   *
 540   * @access public
 541   * @param   int     The entry ID
 542   * @return  array   The SQL result containing the references/links of an entry
 543   */
 544  function serendipity_fetchReferences($id) {
 545      global $serendipity;
 546  
 547      $query = "SELECT name,link FROM {$serendipity['dbPrefix']}references WHERE entry_id = '" . (int)$id . "' AND type = ''";
 548  
 549      return serendipity_db_query($query);
 550  }
 551  
 552  
 553  /**
 554   * Encode a string to UTF-8, if not already in UTF-8 format.
 555   *
 556   * @access public
 557   * @param   string  The input string
 558   * @return  string  The output string
 559   */
 560  function serendipity_utf8_encode($string) {
 561      if (strtolower(LANG_CHARSET) != 'utf-8') {
 562          if (function_exists('iconv')) {
 563              $new = iconv(LANG_CHARSET, 'UTF-8', $string);
 564              if ($new !== false) {
 565                  return $new;
 566              } else {
 567                  return utf8_encode($string);
 568              }
 569          } else if (function_exists('mb_convert_encoding')) {
 570              return mb_convert_encoding($string, 'UTF-8', LANG_CHARSET);
 571          } else {
 572              return utf8_encode($string);
 573          }
 574      } else {
 575          return $string;
 576      }
 577  }
 578  
 579  /**
 580   * Create a link that can be used within a RSS feed to indicate a permalink for an entry or comment
 581   *
 582   * @access public
 583   * @param   array       The input entry array
 584   * @param   boolean     Toggle whether the link will be for a COMMENT [true] or an ENTRY [false]
 585   * @return  string      A permalink for the given entry
 586   */
 587  function serendipity_rss_getguid($entry, $comments = false) {
 588      global $serendipity;
 589  
 590      $id = (isset($entry['entryid']) && $entry['entryid'] != '' ? $entry['entryid'] : $entry['id']);
 591  
 592      // When using %id%, we can make the GUID shorter and independent from the title.
 593      // If not using %id%, the entryid needs to be used for uniqueness.
 594      if (stristr($serendipity['permalinkStructure'], '%id%') !== FALSE) {
 595          $title = 'guid';
 596      } else {
 597          $title = $id;
 598      }
 599  
 600      $guid = serendipity_archiveURL(
 601          $id,
 602          $title,
 603          'baseURL',
 604          true,
 605          array('timestamp' => $entry['timestamp'])
 606      );
 607  
 608      if ($comments == true) {
 609          $guid .= '#c' . $entry['commentid'];
 610      }
 611  
 612      return $guid;
 613  }
 614  
 615  /**
 616   * Perform some replacement calls to make valid XHTML content
 617   *
 618   * jbalcorn: starter function to clean up xhtml for atom feed.  Add things to this as we find common
 619   * mistakes, unless someone finds a better way to do this.
 620   *      DONE:
 621   *          since someone encoded all the urls, we can now assume any amp followed by
 622   *              whitespace or a HTML tag (i.e. &<br /> )should be
 623   *              encoded and most not with a space are intentional
 624   *
 625   * @access public
 626   * @param   string  Input HTML code
 627   * @return  string  Cleaned HTML code
 628   */
 629  function xhtml_cleanup($html) {
 630      static $p = array(
 631          '/\&([\s\<])/',                 // ampersand followed by whitespace or tag
 632          '/\&$/',                        // ampersand at end of body
 633          '/<(br|hr|img)([^\/>]*)>/i',    // unclosed br tag - attributes included
 634          '/\&nbsp;/'                     // Protect whitespace
 635      );
 636  
 637      static $r = array(
 638          '&amp;\1',
 639          '&amp;',
 640          '<\1\2 />',
 641          '&#160;'
 642      );
 643  
 644      return preg_replace($p, $r, $html);
 645  }
 646  
 647  /**
 648   * Fetch user data for a specific Serendipity author
 649   *
 650   * @access public
 651   * @param   int     The requested author id
 652   * @return  array   The SQL result array
 653   */
 654  function serendipity_fetchAuthor($author) {
 655      global $serendipity;
 656  
 657      return serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}authors WHERE " . (is_numeric($author) ? "authorid={$author};" : "username='" . serendipity_db_escape_string($author) . "';"));
 658  }
 659  
 660  /**
 661   * Split a filename into basename and extension parts
 662   *
 663   * @access public
 664   * @param   string  Filename
 665   * @return  array   Return array containing the basename and file extension
 666   */
 667  function serendipity_parseFileName($file) {
 668      $x = explode('.', $file);
 669      $suf = array_pop($x);
 670      $f   = @implode('.', $x);
 671      return array($f, $suf);
 672  }
 673  
 674  /**
 675   * Track the referer to a specific Entry ID
 676   *
 677   * @access public
 678   * @param   int     Entry ID
 679   * @return  null
 680   */
 681  function serendipity_track_referrer($entry = 0) {
 682      global $serendipity;
 683  
 684      // Tracking disabled.
 685      if ($serendipity['trackReferrer'] === false) {
 686          return;
 687      }
 688  
 689      if (isset($_SERVER['HTTP_REFERER'])) {
 690          if (stristr($_SERVER['HTTP_REFERER'], $serendipity['baseURL']) !== false) {
 691              return;
 692          }
 693  
 694          if (!isset($serendipity['_blockReferer']) || !is_array($serendipity['_blockReferer'])) {
 695              // Only generate an array once per call
 696              $serendipity['_blockReferer'] = array();
 697              $serendipity['_blockReferer'] = @explode(';', $serendipity['blockReferer']);
 698          }
 699  
 700          $url_parts  = parse_url($_SERVER['HTTP_REFERER']);
 701          $host_parts = explode('.', $url_parts['host']);
 702          if (!$url_parts['host'] ||
 703              strstr($url_parts['host'], $_SERVER['SERVER_NAME'])) {
 704              return;
 705          }
 706  
 707          foreach($serendipity['_blockReferer'] AS $idx => $hostname) {
 708              if (@strstr($url_parts['host'], $hostname)) {
 709                  return;
 710              }
 711          }
 712  
 713          if (rand(0, 100) < 1) {
 714              serendipity_track_referrer_gc();
 715          }
 716  
 717          $ts       = serendipity_db_get_interval('ts');
 718          $interval = serendipity_db_get_interval('interval', 900);
 719  
 720          $suppressq = "SELECT count(1)
 721                        FROM $serendipity[dbPrefix]suppress
 722                        WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'
 723                        AND scheme = '" . serendipity_db_escape_string($url_parts['scheme']) . "'
 724                        AND port = '" . serendipity_db_escape_string($url_parts['port']) . "'
 725                        AND host = '" . serendipity_db_escape_string($url_parts['host']) . "'
 726                        AND path = '" . serendipity_db_escape_string($url_parts['path']) . "'
 727                        AND query = '" . serendipity_db_escape_string($url_parts['query']) . "'
 728                        AND last > $ts - $interval";
 729  
 730          $suppressp = "DELETE FROM $serendipity[dbPrefix]suppress
 731                        WHERE ip = '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "'
 732                        AND scheme = '" . serendipity_db_escape_string($url_parts['scheme']) . "'
 733                        AND host = '" . serendipity_db_escape_string($url_parts['host']) . "'
 734                        AND port = '" . serendipity_db_escape_string($url_parts['port']) . "'
 735                        AND query = '" . serendipity_db_escape_string($url_parts['query']) . "'
 736                        AND path = '" . serendipity_db_escape_string($url_parts['path']) . "'";
 737          $suppressu = "INSERT INTO $serendipity[dbPrefix]suppress
 738                        (ip, last, scheme, host, port, path, query)
 739                        VALUES (
 740                        '" . serendipity_db_escape_string($_SERVER['REMOTE_ADDR']) . "',
 741                        $ts,
 742                        '" . serendipity_db_escape_string($url_parts['scheme']) . "',
 743                        '" . serendipity_db_escape_string($url_parts['host']) . "',
 744                        '" . serendipity_db_escape_string($url_parts['port']) . "',
 745                        '" . serendipity_db_escape_string($url_parts['path']) . "',
 746                        '" . serendipity_db_escape_string($url_parts['query']) . "'
 747                        )";
 748  
 749          $count = serendipity_db_query($suppressq, true);
 750  
 751          if ($count[0] == 0) {
 752              serendipity_db_query($suppressu);
 753              return;
 754          }
 755  
 756          serendipity_db_query($suppressp);
 757          serendipity_db_query($suppressu);
 758  
 759          serendipity_track_url('referrers', $_SERVER['HTTP_REFERER'], $entry);
 760      }
 761  }
 762  
 763  /**
 764   * Garbage Collection for suppressed referrers
 765   *
 766   * "Bad" referrers, that only occured once to your entry are put within a
 767   * SUPPRESS database table. Entries contained there will be cleaned up eventually.
 768   *
 769   * @access public
 770   * @return null
 771   */
 772  function serendipity_track_referrer_gc() {
 773      global $serendipity;
 774  
 775      $ts       = serendipity_db_get_interval('ts');
 776      $interval = serendipity_db_get_interval('interval', 900);
 777      $gc = "DELETE FROM $serendipity[dbPrefix]suppress WHERE last <= $ts - $interval";
 778      serendipity_db_query($gc);
 779  }
 780  
 781  /**
 782   * Track a URL used in your Blog (Exit-Tracking)
 783   *
 784   * @access public
 785   * @param  string   Name of the DB table where to store the link (exits|referrers)
 786   * @param  string   The URL to track
 787   * @param  int      The Entry ID to relate the track to
 788   * @return null
 789   */
 790  function serendipity_track_url($list, $url, $entry_id = 0) {
 791      global $serendipity;
 792  
 793      $url_parts = parse_url($url);
 794  
 795      serendipity_db_query(
 796        @sprintf(
 797          "UPDATE %s%s
 798              SET count = count + 1
 799            WHERE scheme = '%s'
 800              AND host   = '%s'
 801              AND port   = '%s'
 802              AND path   = '%s'
 803              AND query  = '%s'
 804              AND day    = '%s'
 805              %s",
 806  
 807          $serendipity['dbPrefix'],
 808          $list,
 809          serendipity_db_escape_string($url_parts['scheme']),
 810          serendipity_db_escape_string($url_parts['host']),
 811          serendipity_db_escape_string($url_parts['port']),
 812          serendipity_db_escape_string($url_parts['path']),
 813          serendipity_db_escape_string($url_parts['query']),
 814          date('Y-m-d'),
 815          ($entry_id != 0) ? "AND entry_id = '". (int)$entry_id ."'" : ''
 816        )
 817      );
 818  
 819      if (serendipity_db_affected_rows() == 0) {
 820          serendipity_db_query(
 821            sprintf(
 822              "INSERT INTO %s%s
 823                      (entry_id, day, count, scheme, host, port, path, query)
 824               VALUES (%d, '%s', 1, '%s', '%s', '%s', '%s', '%s')",
 825  
 826              $serendipity['dbPrefix'],
 827              $list,
 828              (int)$entry_id,
 829              date('Y-m-d'),
 830              serendipity_db_escape_string($url_parts['scheme']),
 831              serendipity_db_escape_string($url_parts['host']),
 832              serendipity_db_escape_string($url_parts['port']),
 833              serendipity_db_escape_string($url_parts['path']),
 834              serendipity_db_escape_string($url_parts['query'])
 835            )
 836          );
 837      }
 838  }
 839  
 840  /**
 841   * Display the list of top referrers
 842   *
 843   * @access public
 844   * @see serendipity_displayTopUrlList()
 845   * @param  int      Number of referrers to show
 846   * @param  boolean  Whether to use HTML links for URLs
 847   * @param  int      Interval for which the top referrers are aggregated
 848   * @return string   List of Top referrers
 849   */
 850  function serendipity_displayTopReferrers($limit = 10, $use_links = true, $interval = 7) {
 851      serendipity_displayTopUrlList('referrers', $limit, $use_links, $interval);
 852  }
 853  
 854  /**
 855   * Display the list of top exits
 856   *
 857   * @access public
 858   * @see serendipity_displayTopUrlList()
 859   * @param  int      Number of exits to show
 860   * @param  boolean  Whether to use HTML links for URLs
 861   * @param  int      Interval for which the top exits are aggregated
 862   * @return string   List of Top exits
 863   */
 864  function serendipity_displayTopExits($limit = 10, $use_links = true, $interval = 7) {
 865      serendipity_displayTopUrlList('exits', $limit, $use_links, $interval);
 866  }
 867  
 868  /**
 869   * Display HTML output data of a Exit/Referrer list
 870   *
 871   * @access public
 872   * @see serendipity_displayTopExits()
 873   * @see serendipity_displayTopReferrers()
 874   * @param   string      Name of the DB table to show data from (exits|referrers)
 875   * @param  boolean  Whether to use HTML links for URLs
 876   * @param  int      Interval for which the top exits are aggregated
 877   * @return
 878   */
 879  function serendipity_displayTopUrlList($list, $limit, $use_links = true, $interval = 7) {
 880      global $serendipity;
 881  
 882      if ($limit){
 883          $limit = serendipity_db_limit_sql($limit);
 884      }
 885  
 886      /* HACK */
 887      if (preg_match('/^mysqli?/', $serendipity['dbType'])) {
 888          /* Nonportable SQL due to MySQL date functions,
 889           * but produces rolling 7 day totals, which is more
 890           * interesting
 891           */
 892          $query = "SELECT scheme, host, SUM(count) AS total
 893                    FROM {$serendipity['dbPrefix']}$list
 894                    WHERE day > date_sub(current_date, interval " . (int)$interval . " day)
 895                    GROUP BY host
 896                    ORDER BY total DESC, host
 897                    $limit";
 898      } else {
 899          /* Portable version of the same query */
 900          $query = "SELECT scheme, host, SUM(count) AS total
 901                    FROM {$serendipity['dbPrefix']}$list
 902                    GROUP BY scheme, host
 903                    ORDER BY total DESC, host
 904                    $limit";
 905      }
 906  
 907      $rows = serendipity_db_query($query);
 908      echo "<span class='serendipityReferer'>";
 909      if (is_array($rows)) {
 910          foreach ($rows as $row) {
 911              if ($use_links) {
 912                  printf(
 913                      '<a href="%1$s://%2$s" title="%2$s" >%2$s</a> (%3$s)<br />',
 914                      $row['scheme'],
 915                      $row['host'],
 916                      $row['total']
 917                  );
 918              } else {
 919                  printf(
 920                      '%1$s (%2$s)<br />',
 921                      $row['host'],
 922                      $row['total']
 923                  );
 924              }
 925          }
 926      }
 927      echo "</span>";
 928  }
 929  
 930  /**
 931   * Return either HTML or XHTML code for an '<a target...> attribute.
 932   *
 933   * @access public
 934   * @param   string  The target to use (_blank, _parent, ...)
 935   * @return  string  HTML string containig the valid markup for the target attribute.
 936   */
 937  function serendipity_xhtml_target($target) {
 938      global $serendipity;
 939  
 940      if ($serendipity['enablePopup'] != true)
 941          return "";
 942  
 943      return ' onclick="window.open(this.href, \'target' . time() . '\'); return false;" ';
 944  }
 945  
 946  /**
 947   * Parse a URI portion to return which RSS Feed version was requested
 948   *
 949   * @access public
 950   * @param  string  Name of the core URI part
 951   * @param  string  File extension name of the URI
 952   * @return string  RSS feed type/version
 953   */
 954  function serendipity_discover_rss($name, $ext) {
 955      static $default = '2.0';
 956  
 957      /* Detect type */
 958      if ($name == 'comments') {
 959          $type = 'comments';
 960      } elseif ($name == 'comments_and_trackbacks') {
 961          $type = 'comments_and_trackbacks';
 962      } elseif ($name == 'trackbacks') {
 963          $type = 'trackbacks';
 964      } else {
 965          $type = 'content';
 966      }
 967  
 968      /* Detect version */
 969      if ($name == 'atom' || $name == 'atom10' || $ext == 'atom') {
 970          $ver = 'atom1.0';
 971      } elseif ($name == 'atom03') {
 972          $ver = 'atom0.3';
 973      } elseif ($name == 'opml' || $ext == 'opml') {
 974          $ver = 'opml1.0';
 975      } elseif ($ext == 'rss') {
 976          $ver = '0.91';
 977      } elseif ($ext == 'rss1') {
 978          $ver = '1.0';
 979      } else {
 980          $ver = $default;
 981      }
 982  
 983      return array($ver, $type);
 984  }
 985  
 986  /**
 987   * Check whether an input string contains "evil" characters used for HTTP Response Splitting
 988   *
 989   * @access public
 990   * @param   string      String to check for evil characters
 991   * @return  boolean     Return true on success, false on failure
 992   */
 993  function serendipity_isResponseClean($d) {
 994      return (strpos($d, "\r") === false && strpos($d, "\n") === false);
 995  }
 996  
 997  /**
 998   * Create a new Category
 999   *
1000   * @access public
1001   * @param   string  The new category name
1002   * @param   string  The new category description
1003   * @param   int     The category owner
1004   * @param   string  An icon representing the category
1005   * @param   int     A possible parentid to a category
1006   * @return  int     The new category's ID
1007   */
1008  function serendipity_addCategory($name, $desc, $authorid, $icon, $parentid) {
1009      global $serendipity;
1010      $query = "INSERT INTO {$serendipity['dbPrefix']}category
1011                      (category_name, category_description, authorid, category_icon, parentid, category_left, category_right)
1012                    VALUES
1013                      ('". serendipity_db_escape_string($name) ."',
1014                       '". serendipity_db_escape_string($desc) ."',
1015                        ". (int)$authorid .",
1016                       '". serendipity_db_escape_string($icon) ."',
1017                        ". (int)$parentid .",
1018                         0,
1019                         0)";
1020  
1021      serendipity_db_query($query);
1022      $cid = serendipity_db_insert_id('category', 'categoryid');
1023      serendipity_plugin_api::hook_event('backend_category_addNew', $cid);
1024  
1025      $data = array(
1026          'categoryid'           => $cid,
1027          'category_name'        => $name,
1028          'category_description' => $desc
1029      );
1030  
1031      serendipity_insertPermalink($data, 'category');
1032      return $cid;
1033  }
1034  
1035  /**
1036   * Update an existing category
1037   *
1038   * @access public
1039   * @param   int     Category ID to update
1040   * @param   string  The new category name
1041   * @param   string  The new category description
1042   * @param   int     The new category owner
1043   * @param   string  The new category icon
1044   * @param   int     The new category parent ID
1045   * @param   int     The new category sort order
1046   * @param   int     The new category subcat hiding
1047   * @return null
1048   */
1049  function serendipity_updateCategory($cid, $name, $desc, $authorid, $icon, $parentid, $sort_order = 0, $hide_sub = 0) {
1050      global $serendipity;
1051  
1052      $query = "UPDATE {$serendipity['dbPrefix']}category
1053                      SET category_name = '". serendipity_db_escape_string($name) ."',
1054                          category_description = '". serendipity_db_escape_string($desc) ."',
1055                          authorid = ". (int)$authorid .",
1056                          category_icon = '". serendipity_db_escape_string($icon) ."',
1057                          parentid = ". (int)$parentid .",
1058                          sort_order = ". (int)$sort_order . ",
1059                          hide_sub = ". (int)$hide_sub . "
1060                      WHERE categoryid = ". (int)$cid ."
1061                          $admin_category";
1062      serendipity_db_query($query);
1063      serendipity_plugin_api::hook_event('backend_category_update', $cid);
1064  
1065      $data = array(
1066          'id'                   => $cid,
1067          'categoryid'           => $cid,
1068          'category_name'        => $name,
1069          'category_description' => $desc
1070      );
1071  
1072      serendipity_updatePermalink($data, 'category');
1073  }
1074  
1075  /**
1076   * Ends a session, so that while a file requests happens, Serendipity can work on in that session
1077   */
1078  function serendipity_request_start() {
1079      @session_write_close();
1080      return true;
1081  }
1082  
1083  /**
1084   * Continues a session after a file request
1085   */
1086  function serendipity_request_end() {
1087      @session_start();
1088      return true;
1089  }
1090  
1091  if (!function_exists('microtime_float')) {
1092      /**
1093       * Get current timestamp as microseconds
1094       *
1095       * @access public
1096       * @return float    the time
1097       */
1098      function microtime_float() {
1099          list($usec, $sec) = explode(" ", microtime());
1100          return ((float)$usec + (float)$sec);
1101      }
1102  }
1103  
1104  /**
1105   * Converts Array data to be used as a GET string
1106   *
1107   * @access public
1108   * @param   array   The input array
1109   * @param   string  An array prefix
1110   * @param   string  How to join the array
1111   * @return  string  The HTTP query string
1112   */
1113  function serendipity_build_query(&$array, $array_prefix = null, $comb_char = '&amp;') {
1114      $ret = array();
1115      if (!is_array($array)) {
1116          return '';
1117      }
1118  
1119      foreach ($array as $k => $v) {
1120          $newkey = urlencode($k);
1121          if ($array_prefix) {
1122              $newkey = $array_prefix . '[' . $newkey . ']';
1123          }
1124          if (is_array($v)) {
1125              $ret[] = serendipity_build_query($v, $newkey, $comb_char);
1126          } else {
1127              $ret[] = $newkey . '=' . urlencode($v);
1128          }
1129      }
1130  
1131      return implode($comb_char, $ret);
1132  }
1133  
1134  /* Picks a specified key from an array and returns it
1135   *
1136   * @access public
1137   * @param   array   The input array
1138   * @param   string  The key to search for
1139   * @param   string  The default value to return when not found
1140   * @return null
1141   */
1142  function &serendipity_pickKey(&$array, $key, $default) {
1143      if (!is_array($array)) {
1144          return $default;
1145      }
1146  
1147      foreach($array AS $child) {
1148          if (is_array($child) && isset($child[$key]) && !empty($child[$key])) {
1149              return $child[$key];
1150          }
1151      }
1152  
1153      return $default;
1154  }
1155  
1156  /* Retrieves the current timestamp but only deals with minutes to optimize Database caching
1157   * @access public
1158   * @return timestamp
1159   * @author Matthew Groeninger
1160   */
1161  function serendipity_db_time() {
1162      static $ts    = null;
1163      static $cache = 300; // Seconds to cache
1164  
1165      if ($ts === null) {
1166          $now = time();
1167          $ts = $now - ($now % $cache) + $cache;
1168      }
1169  
1170      return $ts;
1171  }
1172  
1173  define("serendipity_FUNCTIONS_LOADED", true);
1174  /* vim: set sts=4 ts=4 expandtab : */


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