* Adds an item of text, returns a stub object which points to the item.
* You must call setLocation() on the stub object before storing it to the
* database
- * Returns the key for getItem()
+ *
+ * @return String: the key for getItem()
*/
public function addItem( $text );
/**
* Get item by key, or false if the key is not present
+ *
+ * @return String or false
*/
public function getItem( $key );
/**
* Get default text. This is called from Revision::getRevisionText()
+ *
+ * @return String
*/
function getText();
}
var $mOldId, $mHash, $mRef;
/**
- * @param string $hash The content hash of the text
- * @param integer $oldid The old_id for the CGZ object
+ * @param $hash Strng: the content hash of the text
+ * @param $oldid Integer: the old_id for the CGZ object
*/
function HistoryBlobStub( $hash = '', $oldid = 0 ) {
$this->mHash = $hash;
var $mCurId;
/**
- * @param integer $curid The cur_id pointed to
+ * @param $curid Integer: the cur_id pointed to
*/
function HistoryBlobCurStub( $curid = 0 ) {
$this->mCurId = $curid;
* The maximum number of text items before the object becomes sad
*/
var $mMaxCount = 100;
+
+ /** Constants from xdiff.h */
+ const XDL_BDOP_INS = 1;
+ const XDL_BDOP_CPY = 2;
+ const XDL_BDOP_INSB = 3;
function __construct() {
- if ( !function_exists( 'xdiff_string_bdiff' ) ){
- throw new MWException( "Need xdiff 1.5+ support to read or write DiffHistoryBlob\n" );
- }
if ( !function_exists( 'gzdeflate' ) ) {
throw new MWException( "Need zlib support to read or write DiffHistoryBlob\n" );
}
}
function compress() {
+ if ( !function_exists( 'xdiff_string_rabdiff' ) ){
+ throw new MWException( "Need xdiff 1.5+ support to write DiffHistoryBlob\n" );
+ }
if ( isset( $this->mDiffs ) ) {
// Already compressed
return;
# Need to do a null concatenation with warnings off, due to bugs in the current version of xdiff
# "String is not zero-terminated"
wfSuppressWarnings();
- $diff = xdiff_string_bdiff( $t1, $t2 ) . '';
+ $diff = xdiff_string_rabdiff( $t1, $t2 ) . '';
wfRestoreWarnings();
return $diff;
}
function patch( $base, $diff ) {
- wfSuppressWarnings();
- $text = xdiff_string_bpatch( $base, $diff ) . '';
- wfRestoreWarnings();
- return $text;
+ if ( function_exists( 'xdiff_string_bpatch' ) ) {
+ wfSuppressWarnings();
+ $text = xdiff_string_bpatch( $base, $diff ) . '';
+ wfRestoreWarnings();
+ return $text;
+ }
+
+ # Pure PHP implementation
+
+ $header = unpack( 'Vofp/Vcsize', substr( $diff, 0, 8 ) );
+
+ # Check the checksum if mhash is available
+ if ( extension_loaded( 'mhash' ) ) {
+ $ofp = mhash( MHASH_ADLER32, $base );
+ if ( $ofp !== substr( $diff, 0, 4 ) ) {
+ wfDebug( __METHOD__. ": incorrect base checksum\n" );
+ return false;
+ }
+ }
+ if ( $header['csize'] != strlen( $base ) ) {
+ wfDebug( __METHOD__. ": incorrect base length\n" );
+ return false;
+ }
+
+ $p = 8;
+ $out = '';
+ while ( $p < strlen( $diff ) ) {
+ $x = unpack( 'Cop', substr( $diff, $p, 1 ) );
+ $op = $x['op'];
+ ++$p;
+ switch ( $op ) {
+ case self::XDL_BDOP_INS:
+ $x = unpack( 'Csize', substr( $diff, $p, 1 ) );
+ $p++;
+ $out .= substr( $diff, $p, $x['size'] );
+ $p += $x['size'];
+ break;
+ case self::XDL_BDOP_INSB:
+ $x = unpack( 'Vcsize', substr( $diff, $p, 4 ) );
+ $p += 4;
+ $out .= substr( $diff, $p, $x['csize'] );
+ $p += $x['csize'];
+ break;
+ case self::XDL_BDOP_CPY:
+ $x = unpack( 'Voff/Vcsize', substr( $diff, $p, 8 ) );
+ $p += 8;
+ $out .= substr( $base, $x['off'], $x['csize'] );
+ break;
+ default:
+ wfDebug( __METHOD__.": invalid op\n" );
+ return false;
+ }
+ }
+ return $out;
}
function uncompress() {
if ( isset( $info['default'] ) ) {
$this->mDefaultKey = $info['default'];
}
- $map = explode( ',', $info['map'] );
- $cur = 0;
- $this->mDiffMap = array();
- foreach ( $map as $i ) {
- $cur += $i;
- $this->mDiffMap[] = $cur;
- }
$this->mDiffs = $info['diffs'];
+ if ( isset( $info['base'] ) ) {
+ // Old format
+ $this->mDiffMap = range( 0, count( $this->mDiffs ) - 1 );
+ array_unshift( $this->mDiffs,
+ pack( 'VVCV', 0, 0, self::XDL_BDOP_INSB, strlen( $info['base'] ) ) .
+ $info['base'] );
+ } else {
+ // New format
+ $map = explode( ',', $info['map'] );
+ $cur = 0;
+ $this->mDiffMap = array();
+ foreach ( $map as $i ) {
+ $cur += $i;
+ $this->mDiffMap[] = $cur;
+ }
+ }
$this->uncompress();
}