r42995 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r42994‎ | r42995 | r42996 >
Date:13:36, 1 November 2008
Author:tstarling
Status:old (Comments)
Tags:
Comment:
Implemented xdiff_string_bpatch() in pure PHP, allowing DiffHistoryBlob objects to be decompressed without libxdiff. Negligible performance difference. This provides a stability guarantee -- if libxdiff disappears or changes, we can continue to read old blobs. It also means we don't have to package libxdiff for all app servers.
Modified paths:
  • /trunk/phase3/includes/HistoryBlob.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/HistoryBlob.php
@@ -319,11 +319,13 @@
320320 * The maximum number of text items before the object becomes sad
321321 */
322322 var $mMaxCount = 100;
 323+
 324+ /** Constants from xdiff.h */
 325+ const XDL_BDOP_INS = 1;
 326+ const XDL_BDOP_CPY = 2;
 327+ const XDL_BDOP_INSB = 3;
323328
324329 function __construct() {
325 - if ( !function_exists( 'xdiff_string_bdiff' ) ){
326 - throw new MWException( "Need xdiff 1.5+ support to read or write DiffHistoryBlob\n" );
327 - }
328330 if ( !function_exists( 'gzdeflate' ) ) {
329331 throw new MWException( "Need zlib support to read or write DiffHistoryBlob\n" );
330332 }
@@ -353,6 +355,9 @@
354356 }
355357
356358 function compress() {
 359+ if ( !function_exists( 'xdiff_string_bdiff' ) ){
 360+ throw new MWException( "Need xdiff 1.5+ support to write DiffHistoryBlob\n" );
 361+ }
357362 if ( isset( $this->mDiffs ) ) {
358363 // Already compressed
359364 return;
@@ -431,10 +436,60 @@
432437 }
433438
434439 function patch( $base, $diff ) {
435 - wfSuppressWarnings();
436 - $text = xdiff_string_bpatch( $base, $diff ) . '';
437 - wfRestoreWarnings();
438 - return $text;
 440+ if ( function_exists( 'xdiff_string_bpatch' ) ) {
 441+ wfSuppressWarnings();
 442+ $text = xdiff_string_bpatch( $base, $diff ) . '';
 443+ wfRestoreWarnings();
 444+ return $text;
 445+ }
 446+
 447+ # Pure PHP implementation
 448+
 449+ $header = unpack( 'Vofp/Vcsize', substr( $diff, 0, 8 ) );
 450+
 451+ # Check the checksum if mhash is available
 452+ if ( extension_loaded( 'mhash' ) ) {
 453+ $ofp = mhash( MHASH_ADLER32, $base );
 454+ if ( $ofp !== substr( $diff, 0, 4 ) ) {
 455+ wfDebug( __METHOD__. ": incorrect base checksum\n" );
 456+ return false;
 457+ }
 458+ }
 459+ if ( $header['csize'] != strlen( $base ) ) {
 460+ wfDebug( __METHOD__. ": incorrect base length {$header['csize']} -> {strlen($base)}\n" );
 461+ return false;
 462+ }
 463+
 464+ $p = 8;
 465+ $out = '';
 466+ while ( $p < strlen( $diff ) ) {
 467+ $x = unpack( 'Cop', substr( $diff, $p, 1 ) );
 468+ $op = $x['op'];
 469+ ++$p;
 470+ switch ( $op ) {
 471+ case self::XDL_BDOP_INS:
 472+ $x = unpack( 'Csize', substr( $diff, $p, 1 ) );
 473+ $p++;
 474+ $out .= substr( $diff, $p, $x['size'] );
 475+ $p += $x['size'];
 476+ break;
 477+ case self::XDL_BDOP_INSB:
 478+ $x = unpack( 'Vcsize', substr( $diff, $p, 4 ) );
 479+ $p += 4;
 480+ $out .= substr( $diff, $p, $x['csize'] );
 481+ $p += $x['csize'];
 482+ break;
 483+ case self::XDL_BDOP_CPY:
 484+ $x = unpack( 'Voff/Vcsize', substr( $diff, $p, 8 ) );
 485+ $p += 8;
 486+ $out .= substr( $base, $x['off'], $x['csize'] );
 487+ break;
 488+ default:
 489+ wfDebug( __METHOD__.": invalid op\n" );
 490+ return false;
 491+ }
 492+ }
 493+ return $out;
439494 }
440495
441496 function uncompress() {

Comments

#Comment by Brion VIBBER (talk | contribs)   01:01, 14 November 2008

Hoping this is all good per Tim :D

Status & tagging log