foxpro crc32 routine nach php
james beckmann
- php
0 Carsten
he!
für einen shop ist es nötig, checksummen zu berechnen. diese werte kommen allerdings von foxpro,
die allerdings dem ergebnis von crc32() unter php garnicht ähnlich sind. also hat der foxpro
programmierer eine foxpro-routine für crc32 aus dem internet inkl. quelltext gefischt, welche
ich nun in php umgesetzt habe. leider bekommen wir auch hier völlig andere ergebnisse.
hier der haupteil in foxpro:
Init-Methode:
*------ inicialization This.CRCTbl -----------------------*
This.CRCTbl(001) = 0x00000000
...
This.CRCTbl(256) = 0x2d02ef8d
Methode: STRCRC32
lParameters tcStr
Local lnCrc32, ix, lnZ, lnByte
If Empty(tcStr)
Return 0 &&Space(8)
Else
lnCrc32 = 0xFFFFFFFF
For iX = 1 To Len(tcStr)
lnByte = Asc(SubStr(tcStr, iX, 1))
lnZ = BitXor(lnByte, BitAnd(lnCrc32, 0x000000FF))
lnCrc32 = BitXor(This.CRCTbl(lnZ + 1), BitRShift(lnCrc32, 8))
EndFor
lnCrc32 = BitNot(lnCrc32)
If lnCRC32 < 0
lnCRC32 = Int(lnCRC32 + 0x100000000)
EndIf
* Return This.DecToHex(lnCrc32)
Return (lnCrc32)
EndIf
hier in php:
function STRCRC32($tcStr)
{
$CRCTbl[001] = 0x00000000;
...
$CRCTbl[256] = 0x2d02ef8d;
$lnCrc32 = 0xFFFFFFFF;
For ($iX=0; $iX<strlen($tcStr); $iX++)
{
$lnByte = ord(SubStr($tcStr, $iX, 1));
$lnZ = $lnByte ^ ($lnCrc32 & 0x000000FF);
$lnCrc32 = $CRCTbl[$lnZ + 1] ^ ($lnCrc32 >> 8);
}
$lnCrc32 = ~$lnCrc32;
If ($lnCRC32 < 0) $lnCRC32 = Intval($lnCRC32 + 0x100000000);
Return $lnCrc32;
}
echo STRCRC32("A");
irgendetwas läuft da schief. vieleicht kennt sich ja jemand von euch damit aus.
gruss
j.b.
Hi James!
[...] If ($lnCRC32 < 0) $lnCRC32 = Intval($lnCRC32 + 0x100000000);
Das macht Probleme. PHP behandelt Integer als vorzeichenbehaftet und klippt bei der Konvertierung auf die Grenzen. Eventuell erfolgt auch eine Typkonvertierung in Float - da geht dann auch mehr.
Für ne Lösung kann der Rückgabewert kein Integer mehr sein:
if($lnCRC32 < 0) $lnCRC32 = 4294967296+ $lnCRC32;
sollte gehen, da 4294967296 gleich als Float angelegt wird.
Gruss,
Carsten
if($lnCRC32 < 0) $lnCRC32 = 4294967296+ $lnCRC32;
sollte gehen, da 4294967296 gleich als Float angelegt wird.
hi,
hmm. das ging leider auch nicht. dummerweise habe ich kein foxpro um mal
zeile für zeile zudebuggen. aber ich denke auch das es bei der typenkonvertierung
zu problemen kommt. mal schauen, irgendwo eine alte version gefunden. müßte doch
vb kompatibel sein ...
gruss
j.b.
Hallo james!
Ich hab sowas auch mal von Assembler nach C nach PHP 'portiert', und hatte dabei mit den Typen Probleme (Die Integer in PHP sind prinzipiell vorzeichenbehaftet). Nur habe ich den Code nicht hier und kann mich nicht genau erinnern - wenns bis Montag Zeit hat ...
Einen hab ich allerdings noch, statt:
$lnCrc32 = 0xFFFFFFFF; // <-- das ist ein Float, der bei der ersten bitoperation zerlegt wird!
mal so:
$lnCrc32 = -1;
probieren.
Ausserdem müsstest du in CRCTbl alle Zahlen grösser 0x7fffffff durch ihre vorzeichenbehaftete Darstellung ersetzen.
(also jeweils $JetzigerWert-4294967296, statt dem bisherigen Eintragen, wenn es denn negativ ist.)
Gruss,
Carsten
hi,
super dank ersteinmal. hat aber alles nichts geholfen.
leider konnte ich auch keine alte foxpro version auffinden.
evt. werde ich dann diese woche zum entwickler der software
hin und mit ihm das problem durchgehen. obwohl dieser recht
komplexe anwendungen schreibt, stehen wir beide trotzdem
jedesmal wie ochs vorm berg wenn es um bit-operationen und
verschiebungen geht. aus meiner assemblerzeit mitte der 80´er
ist leider einiges auf der strecke geblieben. ich weiß, so
schwer ist das eigentlich garnicht, aber wir haben keine
zeit das problem zulösen und überlegen eine eigene sache
zuentwicklen. mal sehen. die überlegen jetzt den datenabgleich
per email zubewerkstelligen. evt. fällt mir da dann sowieso eine
andere möglichkeit ein.
gruss,
j.b.
evt. finde ich mal den source der php crc32 routine ...
Hallo james!
Diese Zeile kann noch ärger machen:
$lnCrc32 = $CRCTbl[$lnZ + 1] ^ ($lnCrc32 >> 8);
wenn nämlich von links das Vorzeichen nachrückt (wie es für vorzeichenbehaftete Zahlen richtig wäre)
dann sollte
(($lnCrc32 >> 8)&0x00ffffff)
das korrigieren.
Gruss,
Carsten
hallo,
deinen letzten vorschlagt ebenfalls beherzt - mit dem erfolg das die zahlen
zumindet jetzt durchweg im ergebnis positiv sind und die anzahl der stellen
gleich ist. die routine sieht jetzt so aus:
...
$lnCrc32 = -1;
For ($iX=0; $iX<strlen($tcStr); $iX++)
{
$lnByte = ord(SubStr($tcStr, $iX, 1));
$lnZ = $lnByte ^ ($lnCrc32 & 0x000000FF);
$wert=$CRCTbl[$lnZ];
if ($wert>0x7fffffff) $wert=$wert-4294967296;
$lnCrc32 = $wert ^ (($lnCrc32 >> 8) & 0x00ffffff);
}
$lnCrc32 = ~$lnCrc32;
if($lnCRC32 < 0) $lnCRC32 = 4294967296 + $lnCRC32;
Return $lnCrc32;
...
dank für deine mühe,
j.b.