[ Index ]
 

Code source de Serendipity 1.2

Accédez au Source d'autres logiciels libres

title

Body

[fermer]

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

   1  <?php # $Id: functions_trackbacks.inc.php 1747 2007-07-03 08:19:07Z 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_TRACKBACKS')) {
  10      return;
  11  }
  12  @define('S9Y_FRAMEWORK_TRACKBACKS', true);
  13  
  14  /**
  15   * Check a HTTP response if it is a valid XML trackback response
  16   *
  17   * @access public
  18   * @param   string  HTTP Response string
  19   * @return  mixed   Boolean or error message
  20   */
  21  function serendipity_trackback_is_success($resp) {
  22      if (preg_match('@<error>(\d+)</error>@', $resp, $matches)) {
  23          if ((int) $matches[1] === 0) {
  24              return true;
  25          } else {
  26              if (preg_match('@<message>([^<]+)</message>@', $resp, $matches)) {
  27                  return $matches[1];
  28              }
  29              else {
  30                  return 'unknown error';
  31              }
  32          }
  33      }
  34      return true;
  35  }
  36  
  37  /**
  38   * Perform a HTTP query for autodiscovering a pingback URL
  39   *
  40   * @access public
  41   * @param   string  (deprecated) The URL to try autodiscovery
  42   * @param   string  The response of the original URL
  43   * @return
  44   */
  45  function serendipity_pingback_autodiscover($loc, $body) {
  46  global $serendipity;
  47      if (!empty($_SERVER['X-PINGBACK'])) {
  48          $pingback = $_SERVER['X-PINGBACK'];
  49      } elseif (preg_match('@<link rel="pingback" href="([^"]+)" ?/?>@i', $body, $matches)) {
  50          $pingback = $matches[1];
  51      } else {
  52          return;
  53      }
  54  
  55      // xml-rpc hack
  56      $query = "
  57  <?xml version=\"1.0\"?>
  58  <methodCall>
  59    <methodName>pingback.ping</methodName>
  60    <params>
  61      <param>
  62        <name>sourceURI</name>
  63        <value><string>{$serendipity['baseURL']}</string></value>
  64      </param>
  65      <param>
  66        <name>targetURI</name>
  67        <value><string>$loc</string></value>
  68      </param>
  69    </params>
  70  </methodCall>";
  71          _serendipity_send($pingback, $query);
  72          return;
  73  }
  74  
  75  /**
  76   * Send a track/pingback ping
  77   *
  78   * @access public
  79   * @param   string  The URL to send a trackback to
  80   * @param   string  The XML data with the trackback contents
  81   * @return  string  Reponse
  82   */
  83  function _serendipity_send($loc, $data) {
  84      global $serendipity;
  85  
  86      $target = parse_url($loc);
  87      if ($target['query'] != '') {
  88          $target['query'] = '?' . str_replace('&amp;', '&', $target['query']);
  89      }
  90  
  91      if (!is_numeric($target['port'])) {
  92         $target['port'] = 80;
  93      }
  94  
  95      $uri = $target['scheme'] . '://' . $target['host'] . ':' . $target['port'] . $target['path'] . $target['query'];
  96      require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
  97      $options = array('allowRedirects' => true, 'maxRedirects' => 5, 'method' => 'POST');
  98      serendipity_plugin_api::hook_event('backend_http_request', $options, 'trackback_send');
  99      serendipity_request_start();
 100  
 101      $req = &new HTTP_Request($uri, $options);
 102      $req->addRawPostData($data, true);
 103      $res = $req->sendRequest();
 104  
 105      if (PEAR::isError($res)) {
 106          serendipity_request_end();
 107          return false;
 108      }
 109  
 110      $fContent = $req->getResponseBody();
 111      serendipity_request_end();
 112      return $fContent;
 113  }
 114  
 115  /**
 116   * Autodiscover a trackback location URL
 117   *
 118   * @access public
 119   * @param   string  The HTML of the source URL
 120   * @param   string  The source URL
 121   * @param   string  The URL of our blog
 122   * @param   string  The author of our entry
 123   * @param   string  The title of our entry
 124   * @param   string  The text of our entry
 125   * @param   string  A comparsion URL
 126  
 127   * @return string   Response
 128   */
 129  function serendipity_trackback_autodiscover($res, $loc, $url, $author, $title, $text, $loc2 = '') {
 130      if (!preg_match('@trackback:ping(\s*rdf:resource)?\s*=\s*["\'](https?:[^"\']+)["\']@i', $res, $matches)) {
 131          $matches = array();
 132          serendipity_plugin_api::hook_event('backend_trackback_check', $matches, $loc);
 133  
 134          // Plugins may say that a URI is valid, in situations where a blog has no valid RDF metadata
 135          if (empty($matches[2])) {
 136              echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, TRACKBACK_NOT_FOUND) . '</div>';
 137              return false;
 138          }
 139      }
 140  
 141      $trackURI = trim($matches[2]);
 142  
 143      if (preg_match('@dc:identifier\s*=\s*["\'](https?:[^\'"]+)["\']@i', $res, $test)) {
 144          if ($loc != $test[1] && $loc2 != $test[1]) {
 145              echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, TRACKBACK_URI_MISMATCH) . '</div>';
 146              return false;
 147          }
 148      }
 149  
 150      $data = 'url='        . rawurlencode($url)
 151            . '&title='     . rawurlencode($title)
 152            . '&blog_name=' . rawurlencode($author)
 153            . '&excerpt='   . rawurlencode(strip_tags($text));
 154  
 155      printf(TRACKBACK_SENDING, htmlspecialchars($trackURI));
 156      flush();
 157  
 158      $response = serendipity_trackback_is_success(_serendipity_send($trackURI, $data));
 159  
 160      if ($response === true) {
 161          echo '<div>&#8226; ' . TRACKBACK_SENT .'</div>';
 162      } else {
 163          echo '<div>&#8226; ' . sprintf(TRACKBACK_FAILED, $response) . '</div>';
 164      }
 165  
 166      return $response;
 167  }
 168  
 169  /**
 170   * Open a URL and autodetect contained ping/trackback locations
 171   *
 172   * @access public
 173   * @param   string  The URL to autodetect/try
 174   * @param   string  The URL to our blog
 175   * @param   string  The author of our entry
 176   * @param   string  The title of our entry
 177   * @param   string  The body of our entry
 178   * @return null
 179   */
 180  function serendipity_reference_autodiscover($loc, $url, $author, $title, $text) {
 181  global $serendipity;
 182      $timeout   = 30;
 183  
 184      $u = parse_url($loc);
 185  
 186      if ($u['scheme'] != 'http' && $u['scheme'] != 'https') {
 187          return;
 188      } elseif ($u['scheme'] == 'https' && !extension_loaded('openssl')) {
 189          return; // Trackbacks to HTTPS URLs can only be performed with openssl activated
 190      }
 191  
 192      echo '<div>&#8226; '. sprintf(TRACKBACK_CHECKING, $loc) .'</div>';
 193      flush();
 194  
 195      if (empty($u['port'])) {
 196          $u['port'] = 80;
 197          $port      = '';
 198      } else {
 199          $port      = ':' . $u['port'];
 200      }
 201  
 202      if (!empty($u['query'])) {
 203          $u['path'] .= '?' . $u['query'];
 204      }
 205  
 206      $parsed_loc = $u['scheme'] . '://' . $u['host'] . $port . $u['path'];
 207  
 208      if (preg_match('@\.(jpe?g|aiff?|gif|png|pdf|doc|rtf|wave?|mp2|mp4|mpe?g3|mpe?g4|divx|xvid|bz2|mpe?g|avi|mp3|xl?|ppt|pps|xslt?|xsd|zip|tar|t?gz|swf|rm|ram?|exe|mov|qt|midi?|qcp|emf|wmf|snd|pmg|w?bmp|gcd|mms|ogg|ogm|rv|wmv|wma|jad|3g?|jar)$@i', $u['path'])) {
 209          echo '<div>&#8226; ' . TRACKBACK_NO_DATA . '</div>';
 210          return;
 211      }
 212  
 213      require_once S9Y_PEAR_PATH . 'HTTP/Request.php';
 214      $options = array('allowRedirects' => true, 'maxRedirects' => 5, 'method' => 'GET');
 215      serendipity_plugin_api::hook_event('backend_http_request', $options, 'trackback_detect');
 216      serendipity_request_start();
 217      $req = &new HTTP_Request($parsed_loc, $options);
 218      $res = $req->sendRequest();
 219  
 220      if (PEAR::isError($res)) {
 221          echo '<div>&#8226; ' . sprintf(TRACKBACK_COULD_NOT_CONNECT, $u['host'], $u['port']) .'</div>';
 222          serendipity_request_end();
 223          return;
 224      }
 225  
 226      $fContent = $req->getResponseBody();
 227      serendipity_request_end();
 228  
 229      if (strlen($fContent) != 0) {
 230          serendipity_trackback_autodiscover($fContent, $parsed_loc, $url, $author, $title, $text, $loc);
 231          serendipity_pingback_autodiscover($loc, $fContent);
 232      } else {
 233          echo '<div>&#8226; ' . TRACKBACK_NO_DATA . '</div>';
 234      }
 235      echo '<hr noshade="noshade" />';
 236  }
 237  
 238  /**
 239   * Receive a trackback
 240   *
 241   * @access public
 242   * @param   int     The ID of our entry
 243   * @param   string  The title of the foreign blog
 244   * @param   string  The URL of the foreign blog
 245   * @param   string  The name of the foreign blog
 246   * @param   string  The excerpt text of the foreign blog
 247   * @return true
 248   */
 249  function add_trackback ($id, $title, $url, $name, $excerpt) {
 250      global $serendipity;
 251  
 252      // We can't accept a trackback if we don't get any URL
 253      // This is a protocol rule.
 254      if (empty($url)) {
 255          return 0;
 256      }
 257  
 258      // If title is not provided, the value for url will be set as the title
 259      // This is a protocol rule.
 260      if (empty($title)) {
 261          $title = $url;
 262      }
 263  
 264      $comment = array(
 265          'title'   => $title,
 266          'url'     => $url,
 267          'name'    => $name,
 268          'comment' => $excerpt
 269      );
 270  
 271      $is_utf8 = strtolower(LANG_CHARSET) == 'utf-8';
 272  
 273      if ($GLOBALS['tb_logging']) {
 274          $fp = fopen('trackback2.log', 'a');
 275          fwrite($fp, '[' . date('d.m.Y H:i') . '] TRACKBACK TRANSCODING CHECK' . "\n");
 276      }
 277  
 278      foreach($comment AS $idx => $field) {
 279          if (is_utf8($field)) {
 280              // Trackback is in UTF-8. Check if our blog also is UTF-8.
 281              if (!$is_utf8) {
 282                  if ($GLOBALS['tb_logging']) {
 283                      fwrite($fp, '[' . date('d.m.Y H:i') . '] Transcoding ' . $idx . ' from UTF-8 to ISO' . "\n");
 284                  }
 285                  $comment[$idx] = utf8_decode($field);
 286              }
 287          } else {
 288              // Trackback is in some native format. We assume ISO-8859-1. Check if our blog is also ISO.
 289              if ($is_utf8) {
 290                  if ($GLOBALS['tb_logging']) {
 291                      fwrite($fp, '[' . date('d.m.Y H:i') . '] Transcoding ' . $idx . ' from ISO to UTF-8' . "\n");
 292                  }
 293                  $comment[$idx] = utf8_encode($field);
 294              }
 295          }
 296      }
 297  
 298      if ($GLOBALS['tb_logging']) {
 299          fwrite($fp, '[' . date('d.m.Y H:i') . '] TRACKBACK DATA: ' . print_r($comment, true) . '...' . "\n");
 300          fwrite($fp, '[' . date('d.m.Y H:i') . '] TRACKBACK STORING...' . "\n");
 301          fclose($fp);
 302      }
 303  
 304      serendipity_saveComment($id, $comment, 'TRACKBACK');
 305  
 306      return 1;
 307  }
 308  
 309  /**
 310   * Receive a pingback
 311   *
 312   * @access public
 313   * @param   int     The entryid to receive a pingback for
 314   * @param   string  The foreign postdata to add
 315   * @return boolean
 316   */
 317  function add_pingback ($id, $postdata) {
 318      global $serendipity;
 319  
 320      if(preg_match('@<methodcall>\s*<methodName>\s*pingback.ping\s*</methodName>\s*<params>\s*<param>\s*<value>\s*<string>([^<]*)</string>\s*</value>\s*</param>\s*<param>\s*<value>\s*<string>([^<]*)</string>\s*</value>\s*</param>\s*</params>\s*</methodCall>@i', $postdata, $matches)) {
 321          $remote             = $matches[1];
 322          $local              = $matches[2];
 323          $comment['title']   = '';
 324          $comment['url']     = $remote;
 325          $comment['comment'] = '';
 326          $comment['name']    = '';
 327  
 328          serendipity_saveComment($id, $comment, 'PINGBACK');
 329          return 1;
 330      }
 331      return 0;
 332  }
 333  
 334  /**
 335   * Create an excerpt for a trackback to send
 336   *
 337   * @access public
 338   * @param   string  Input text
 339   * @return  string  Output text
 340   */
 341  function serendipity_trackback_excerpt($text) {
 342      return serendipity_mb('substr', strip_tags($text), 0, 255);
 343  }
 344  
 345  /**
 346   * Report success of a trackback
 347   *
 348   * @access public
 349   */
 350  function report_trackback_success () {
 351  print '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
 352  print <<<SUCCESS
 353  <response>
 354      <error>0</error>
 355  </response>
 356  SUCCESS;
 357  }
 358  
 359  /**
 360   * Report failure of a trackback
 361   *
 362   * @access public
 363   */
 364  function report_trackback_failure () {
 365  print '<?xml version="1.0" encoding="iso-8859-1"?>' . "\n";
 366  print <<<FAILURE
 367  <response>
 368      <error>1</error>
 369      <message>Danger Will Robinson, trackback failed.</message>
 370  </response>
 371  FAILURE;
 372  }
 373  
 374  /**
 375   * Return success of a pingback
 376   *
 377   * @access public
 378   */
 379  function report_pingback_success () {
 380  print '<?xml version="1.0"?>' . "\n";
 381  print <<<SUCCESS
 382  <methodResponse>
 383     <params>
 384        <param>
 385           <value><string>success</string></value>
 386           </param>
 387        </params>
 388     </methodResponse>
 389  SUCCESS;
 390  }
 391  
 392  /**
 393   * Return failure of a pingback
 394   *
 395   * @access public
 396   */
 397  function report_pingback_failure () {
 398  print '<?xml version="1.0"?>' . "\n";
 399  print <<<FAILURE
 400  <methodResponse>
 401      <fault>
 402      <value><i4>0</i4></value>
 403      </fault>
 404  </methodResponse>
 405  FAILURE;
 406  }
 407  
 408  /**
 409   * Search through link body, and automagically send a trackback ping.
 410   *
 411   * This is the trackback starter function that searches your text and sees if any
 412   * trackback URLs are in there
 413   *
 414   * @access public
 415   * @param   int     The ID of our entry
 416   * @param   string  The author of our entry
 417   * @param   string  The title of our entry
 418   * @param   string  The text of our entry
 419   * @param   boolean Dry-Run, without performing trackbacks?
 420   * @return
 421   */
 422  function serendipity_handle_references($id, $author, $title, $text, $dry_run = false) {
 423      global $serendipity;
 424      static $old_references = array();
 425      static $saved_references = array();
 426      static $debug = false;
 427  
 428      if ($dry_run) {
 429          // Store the current list of references. We might need to restore them for later user.
 430          $old_references = serendipity_db_query("SELECT * FROM {$serendipity['dbPrefix']}references WHERE (type = '' OR type IS NULL) AND entry_id = " . (int)$id, false, 'assoc');
 431          
 432          if ($debug && is_string($old_references)) {
 433              echo $old_references . "<br />\n";
 434          }
 435  
 436          if (is_array($old_references) && count($old_references) > 0) {
 437              $current_references = array();
 438              foreach($old_references AS $idx => $old_reference) {
 439                  // We need the current reference ID to restore it later.
 440                  $saved_references[$old_reference['link'] . $old_reference['name']] = $current_references[$old_reference['link'] . $old_reference['name']] = $old_reference;
 441              }
 442          }
 443          if ($debug) echo "Got references in dry run: <pre>" . print_r($current_references, true) . "</pre><br />\n";
 444      } else {
 445          // A dry-run was called previously and restorable references are found. Restore them now.
 446          $del = serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}references WHERE (type = '' OR type IS NULL) AND entry_id = " . (int)$id);
 447          if ($debug && is_string($del)) {
 448              echo $del . "<br />\n";
 449          }
 450  
 451          if ($debug) echo "Deleted references.<br />\n";
 452  
 453          if (is_array($old_references) && count($old_references) > 0) {
 454              $current_references = array();
 455              foreach($old_references AS $idx => $old_reference) {
 456                  // We need the current reference ID to restore it later.
 457                  $current_references[$old_reference['link'] . $old_reference['name']] = $old_reference;
 458                  $q = serendipity_db_insert('references', $old_reference, 'show');
 459                  $cr = serendipity_db_query($q);
 460                  if ($debug && is_string($cr)) {
 461                      echo $cr . "<br />\n";
 462                  }
 463              }
 464          }
 465  
 466          if ($debug) echo "Got references in final run: <pre>" . print_r($current_references, true) . "</pre><br />\n";
 467      }
 468  
 469      if (!preg_match_all('@<a[^>]+?href\s*=\s*["\']?([^\'" >]+?)[ \'"][^>]*>(.+?)</a>@i', $text, $matches)) {
 470          $matches = array(0 => array(), 1 => array());
 471      } else {
 472          // remove full matches
 473          array_shift($matches);
 474      }
 475  
 476      // Make trackback URL
 477      $url = serendipity_archiveURL($id, $title, 'baseURL');
 478  
 479      // Add URL references
 480      $locations = $matches[0];
 481      $names     = $matches[1];
 482  
 483      $checked_locations = array();
 484      serendipity_plugin_api::hook_event('backend_trackbacks', $locations);
 485      for ($i = 0, $j = count($locations); $i < $j; ++$i) {
 486          if ($debug) echo "Checking {$locations[$i]}...<br />\n";
 487          if ($locations[$i][0] == '/') {
 488              $locations[$i] = 'http' . (!empty($_SERVER['HTTPS']) && strtolower($_SERVER['HTTPS']) != 'off' ? 's' : '') . '://' . $_SERVER['HTTP_HOST'] . $locations[$i];
 489          }
 490  
 491          if (isset($checked_locations[$locations[$i]])) {
 492              if ($debug) echo "Already checked.<br />\n";
 493              continue;
 494          }
 495  
 496          if (preg_match_all('@<img[^>]+?alt=["\']?([^\'">]+?)[\'"][^>]+?>@i', $names[$i], $img_alt)) {
 497              if (is_array($img_alt) && is_array($img_alt[0])) {
 498                  foreach($img_alt[0] as $alt_idx => $alt_img) {
 499                      // Replace all <img>s within a link with their respective ALT tag, so that references
 500                      // can be stored with a title.
 501                      $names[$i] = str_replace($alt_img, $img_alt[1][$alt_idx], $names[$i]);
 502                  }
 503              }
 504          }
 505  
 506          $query = "SELECT COUNT(id) FROM {$serendipity['dbPrefix']}references
 507                                    WHERE entry_id = ". (int)$id ."
 508                                      AND link = '" . serendipity_db_escape_string($locations[$i]) . "'
 509                                      AND (type = '' OR type IS NULL)";
 510  
 511          $row = serendipity_db_query($query, true, 'num');
 512          if ($debug && is_string($row)) {
 513              echo $row . "<br />\n";
 514          }
 515  
 516          if ($row[0] > 0 && isset($saved_references[$locations[$i] . $names[$i]])) {
 517              if ($debug) echo "Found references for $id, skipping rest<br />\n";
 518              continue;
 519          }
 520  
 521          if (!isset($serendipity['noautodiscovery']) || !$serendipity['noautodiscovery']) {
 522              if (!$dry_run) {
 523                  if ($debug) echo "Enabling autodiscovery.<br />\n";
 524                  serendipity_reference_autodiscover($locations[$i], $url, $author, $title, serendipity_trackback_excerpt($text));
 525              } elseif ($debug) {
 526                  echo "Skipping autodiscovery<br />\n";
 527              }
 528              $checked_locations[$locations[$i]] = true; // Store trackbacked link so that no further trackbacks will be sent to the same link
 529          } elseif ($debug) {
 530              echo "Skipping full autodiscovery<br />\n";
 531          }
 532      }
 533      $del = serendipity_db_query("DELETE FROM {$serendipity['dbPrefix']}references WHERE entry_id=" . (int)$id . " AND (type = '' OR type IS NULL)");
 534      if ($debug && is_string($del)) {
 535          echo $del . "<br />\n";
 536      }
 537  
 538      if ($debug) echo "Deleted references again.<br />\n";
 539  
 540      if (!is_array($old_references)) {
 541          $old_references = array();
 542      }
 543  
 544      $duplicate_check = array();
 545      for ($i = 0; $i < $j; ++$i) {
 546          $i_link     = serendipity_db_escape_string(strip_tags($names[$i]));
 547          $i_location = serendipity_db_escape_string($locations[$i]);
 548          
 549          // No link with same description AND same text should be inserted.
 550          if (isset($duplicate_check[$i_location . $i_link])) {
 551              continue;
 552          }
 553  
 554          if (isset($current_references[$locations[$i] . $names[$i]])) {
 555              $query = "INSERT INTO {$serendipity['dbPrefix']}references (id, entry_id, name, link) VALUES(";
 556              $query .= (int)$current_references[$locations[$i] . $names[$i]]['id'] . ", " . (int)$id . ", '" . $i_link . "', '" . $i_location . "')";
 557              $ins = serendipity_db_query($query);
 558              if ($debug && is_string($ins)) {
 559                  echo $ins . "<br />\n";
 560              }
 561              $duplicate_check[$locations[$i] . $names[$i]] = true;
 562          } else {
 563              $query = "INSERT INTO {$serendipity['dbPrefix']}references (entry_id, name, link) VALUES(";
 564              $query .= (int)$id . ", '" . $i_link . "', '" . $i_location . "')";
 565              $ins = serendipity_db_query($query);
 566              if ($debug && is_string($ins)) {
 567                  echo $ins . "<br />\n";
 568              }
 569  
 570              $old_references[] = array(
 571                  'id'       => serendipity_db_insert_id('references', 'id'),
 572                  'name'     => $i_link,
 573                  'link'     => $i_location,
 574                  'entry_id' => (int)$id
 575              );
 576              $duplicate_check[$i_location . $i_link] = true;
 577          }
 578          
 579          if ($debug) {
 580              echo "Current lookup for {$locations[$i]}{$names[$i]} is <pre>" . print_r($current_references[$locations[$i] . $names[$i]], true) . "</pre><br />\n";
 581              echo $query . "<br />\n";
 582          }
 583      }
 584      
 585      if ($debug) {
 586          echo "Old/Saved locations: <pre>" . print_r($old_references, true) . "</pre><br />\n";
 587      }
 588  
 589      // Add citations
 590      preg_match_all('@<cite[^>]*>([^<]+)</cite>@i', $text, $matches);
 591  
 592      foreach ($matches[1] as $citation) {
 593          $query = "INSERT INTO {$serendipity['dbPrefix']}references (entry_id, name) VALUES(";
 594          $query .= (int)$id . ", '" . serendipity_db_escape_string($citation) . "')";
 595  
 596          $cite = serendipity_db_query($query);
 597          if ($debug && is_string($cite)) {
 598              echo $cite . "<br />\n";
 599          }
 600      }
 601  }
 602  
 603  /**
 604   * Check if a string is in UTF-8 format.
 605   *
 606   * @access public
 607   * @param   string  The string to check
 608   * @return  bool
 609   */
 610  function is_utf8($string) {
 611     // From http://w3.org/International/questions/qa-forms-utf-8.html
 612     return preg_match('%^(?:'
 613           . '[\x09\x0A\x0D\x20-\x7E]'             # ASCII
 614           . '|[\xC2-\xDF][\x80-\xBF]'             # non-overlong 2-byte
 615           . '|\xE0[\xA0-\xBF][\x80-\xBF]'         # excluding overlongs
 616           . '|[\xE1-\xEC\xEE\xEF][\x80-\xBF]{2}'  # straight 3-byte
 617           . '|\xED[\x80-\x9F][\x80-\xBF]'         # excluding surrogates
 618           . '|\xF0[\x90-\xBF][\x80-\xBF]{2}'      # planes 1-3
 619           . '|[\xF1-\xF3][\x80-\xBF]{3}'          # planes 4-15
 620           . '|\xF4[\x80-\x8F][\x80-\xBF]{2}'      # plane 16
 621           . ')*$%xs', $string);
 622  }


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