Go Back   EQEmulator Home > EQEmulator Forums > Development > Development::Tools

Development::Tools 3rd Party Tools for EQEMu (DB management tools, front ends, etc...)

Reply
 
Thread Tools Display Modes
  #1  
Old 05-07-2008, 06:31 PM
cybernine186
Sarnak
 
Join Date: Feb 2008
Posts: 87
Default CRC32 Checksum How to in Player Profile

I have developed a tool for viewing/editing the player profile in the character_ table. The viewing and editing works for int values only (Which almost every value seems to be a numeric value) but I am having trouble trying to figure out how the CRC32 check works. So far from my research the CRC32's value runs off the sizeof value. I am using PHP and it has build in capabilities for CRC32 and sizeof. Can anyone help me or point me in the right direction of being able to recreate the checksum in the player profile in the database or is the checksum totally worthless to the EQ client?
Reply With Quote
  #2  
Old 05-07-2008, 08:46 PM
Theeper
Discordant
 
Join Date: May 2004
Posts: 290
Default

Take a look at crc32.cpp. You'll need the data from "int32 CRC32Table[256]" at the top. Also the function "SetEQChecksum()" is passed a reference to the profile and it creates the checksum and then copies it into the profile.

I don't know if the checksum is actually used by the server, but it is set.

I wrote a C++ app a while back to display the profile using the profile struct from the server code. I started to make it write the profile back to the DB but was unsure of what type of problems it could create. I got lazy and never finished it.

I do know that some events cause the server to save the profile like a change in coin, zoning and inventory changes. Spells don't seem to cause the server to save the profile.

You'll need to unpack() the data with PHP unless you're just doing a string replace on the binary data. AndMetal wrote a nice PHP script to unpack the profile here.
Reply With Quote
  #3  
Old 05-07-2008, 10:56 PM
cybernine186
Sarnak
 
Join Date: Feb 2008
Posts: 87
Default

I am using substr_replace in php to just replace the data that is changed instead of repacking the entire blob. Just seems to make more since to me that way. So far everything in the editor works perfectly, all char info, money, features, colors, languages, skills, etc. Just mostly the basics no LDON stuff yet. But that still doesn't tell me what the CRC32 checksum uses for the actual checksum. It has to be part or all of the info in the profile but what. I ant a C++ expert so any help is appreciated.
Reply With Quote
  #4  
Old 05-08-2008, 12:29 AM
AndMetal
Developer
 
Join Date: Mar 2007
Location: Ohio
Posts: 648
Default

I'll give you a hint: don't worry about the checksum.

I tried messing with it a little bit, until I discovered there wasn't any real reason to. This is what I came up with:

From my PHP-based utility:
Code:
   73 /*
   74 SetEQChecksum taken from crc32.cpp source code, translated to PHP
   75 
   76 Original source:
   77 void CRC32::SetEQChecksum(uchar* in_data, int32 in_length)
   78 {
   79 	unsigned long data;
   80     unsigned long check = 0xffffffff;
   81 
   82 	assert(in_length >= 4 && in_data);
   83 
   84     for(int32 i=4; i<in_length; i++)
   85     {
   86         data = in_data[i];
   87         data = data ^ (check);
   88         data = data & 0x000000ff;
   89         check = check >> 8;
   90         data = CRC32Table[data];
   91         check = check ^ data;
   92     }
   93 
   94     memcpy(in_data, (char*)&check, 4);
   95 }
   96 */
   97 function SetEQChecksum($in_data) {
   98 	$in_length = strlen($in_data);
   99 	$check = 0xffffffff;
  100 	for ($i=4; $i<in_length; $i++) {
  101 		$data = $in_data[$i];
  102 		$data = $data XOR ($check);
  103 		$data = $data & 0x000000ff;
  104 		$check = $check >> 8;
  105 		$data = $CRC32Table[$data];
  106 		$check = $check XOR $data;
  107 	};
  108 	return $check;
  109 };
Plus the CRC32Table:
Code:
  380 $CRC32Table = array(
  381 	0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
  382 	0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
  383 	0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
  384 	0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
  385 	0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
  386 	0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
  387 	0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
  388 	0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
  389 	0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
  390 	0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
  391 	0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
  392 	0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
  393 	0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
  394 	0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
  395 	0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
  396 	0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
  397 
  398 	0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
  399 	0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
  400 	0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
  401 	0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
  402 	0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
  403 	0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
  404 	0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
  405 	0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
  406 	0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
  407 	0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
  408 	0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
  409 	0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
  410 	0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
  411 	0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
  412 	0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
  413 	0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
  414 
  415 	0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
  416 	0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
  417 	0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
  418 	0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
  419 	0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
  420 	0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
  421 	0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
  422 	0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
  423 	0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
  424 	0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
  425 	0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
  426 	0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
  427 	0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
  428 	0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
  429 	0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
  430 	0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
  431 
  432 	0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
  433 	0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
  434 	0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
  435 	0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
  436 	0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
  437 	0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
  438 	0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
  439 	0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
  440 	0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
  441 	0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
  442 	0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
  443 	0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
  444 	0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
  445 	0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
  446 	0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
  447 	0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
  448 );
Unfortunately, it just ANDs the entire thing to all binary 1's. I didn't really try anything else after that, but I'm sure it's pretty straightforward to figure out, it will just take some debugging.

Btw, if you're looking for a somewhat basic way to just look at the profile blob, I put together a script to break it down:
PHP Code:
<html>

<head>

<?php

// Database Info
$db_user "eqemu";            // Username
$db_pass "password";    // Password
$db_host "localhost";        // Hostname/IP Address
$db_name "peq";            // Database Name
$db mysql_connect($db_host,$db_user,$db_pass) or die(mysql_error());
mysql_select_db($db_name);
// include "../includes/constants.php";

// Default settings for output
$field "profile";
$line_size 16;
$limit 20;        // Max lines to display per page. 0 to show all
$offset 0;        // Usually won't change from 0, but can be used to set an offset starting point (in rows)

// Set values to defaults if not passed in $_GET
if (!isset($_GET[field]) || ($_GET[field] == "")) $_GET[field] = $field;
if (!isset(
$_GET[line_size]) || ($_GET[line_size] == "")) $_GET[line_size] = $line_size;
if (!isset(
$_GET[limit]) || ($_GET[limit] == "")) $_GET[limit] = $limit;
if (!isset(
$_GET[offset]) || ($_GET[offset] == "")) $_GET[offset] = $offset;

?>

<title></title>

<style type="text/css">
td 
{
    text-align: center;
    /* width: 5px; */
}
</style>

</head>

<body>

<form name="NoID" method="GET" action="">Enter ID: <input type="text" name="id" size="2" value="<?php echo $_GET['id']?>"><button type="submit">Go</button>&nbsp;<button type="reset">Reset</button><br>
<input type="radio" name="field" value="profile"<?php if ($_GET[field] == "profile") echo " checked"?>>Profile</input> <input type="radio" name="field" value="extprofile"<?php if ($_GET[field] == "extprofile") echo " checked"?>>Extended Profile</input><br>
Characters per line: <input type="text" name="line_size" size="2" value="<?php echo $_GET[line_size]?>"><br>
Lines per page: <input type="text" name="limit" size="3" value="<?php echo $_GET[limit]?>"><br>
Start: <input type="text" name="offset" size="3" value="<?php echo $_GET[offset]?>"><br>
</form>

<?php

if ($_GET['id']) {

    
flush(); ob_flush();

    
$query "SELECT " $_GET[field] . " FROM character_ WHERE id='" $_GET['id'] . "' ";
    
$result mysql_query($query,$db);
    
$db_row mysql_fetch_array($result);
    
$total_chars strlen($db_row[$_GET[field]]);
    
$total_chars_len strlen($total_chars);

?>

<table border="1">
<form method="GET" action="">
<caption align="top" style="text-align:left">
<a href="?id=<?php echo $_GET['id']?>&line_size=<?php echo $_GET[line_size]?>&limit=<?php echo $_GET[limit]?>&offset=<?php if ($_GET[offset] - ($_GET[line_size] * $_GET[limit]) >= 0) {echo $_GET[offset] - ($_GET[line_size] * $_GET[limit]);};?>">&lt;&lt;Prev</a>
<a href="?id=<?php echo $_GET['id']?>&line_size=<?php echo $_GET[line_size]?>&limit=<?php echo $_GET[limit]?>&offset=<?php echo $_GET[offset] + ($_GET[line_size] * $_GET[limit]);?>">Next&gt;&gt;</a>
</caption>
</form>
<tr><td align="center">Row</td><td colspan="<?php echo $_GET[line_size]?>">Val</td><td colspan="<?php echo $_GET[line_size]?>">Char</td></tr>
<?php

    
if ($_GET[limit] == 0$_GET[limit] = ($total_chars $_GET[line_size]) - 1;
    for (
$row $_GET[offset]; $row <= ((($_GET[line_size] * $_GET[limit]) + $_GET[offset]) - 1) && $row <= $total_chars$row += $_GET[line_size]) {

?>
<tr><td align="right"><?php echo str_pad($row,$total_chars_len,0,STR_PAD_LEFT)?></td><?php
        
//Output for HEX
        
for ($char $row$char <= ($row + ($_GET[line_size] - 1)); $char++) {
?>
<td title="<?php echo str_pad($char,$total_chars_len,0,STR_PAD_LEFT)?>"><?php echo strtoupper(str_pad(dechex(ord($db_row[$_GET[field]][$char])),2,0,STR_PAD_LEFT))?></td><?php
        
};
        
        
// Output for Characters
        
for ($char $row$char <= ($row + ($_GET[line_size] - 1)); $char++) {
?>
<td title="<?php echo str_pad($char,$total_chars_len,0,STR_PAD_LEFT)?>"><?php
            $char_dec_val 
ord($db_row[$_GET[field]][$char]);
            echo 
"";
            if ((
$char_dec_val >= 33) && ($char_dec_val <= 126)) {echo $db_row[$_GET[field]][$char];}
            elseif (
$char_dec_val == 32) {echo "&nbsp;";};
?></td><?php
        
};
?>
</tr>
<?php
        flush
(); ob_flush();
    };
?>
</table>

<?php
};
?>

</body>

</html>
I'll eventually include it with the other stuff, but that's for another day.

Anyways, hope this points you in the right direction.
__________________
GM-Impossible of 'A work in progress'
A non-legit PEQ DB server
How to create your own non-legit server

My Contributions to the Wiki
Reply With Quote
Reply

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump

   

All times are GMT -4. The time now is 05:58 AM.


 

Everquest is a registered trademark of Daybreak Game Company LLC.
EQEmulator is not associated or affiliated in any way with Daybreak Game Company LLC.
Except where otherwise noted, this site is licensed under a Creative Commons License.
       
Powered by vBulletin®, Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Template by Bluepearl Design and vBulletin Templates - Ver3.3