PHP WDB Parsing Class

From Source Peek Wiki

Jump to: navigation, search

The parser doesn't account for the 8 or so null bytes at the end of the file.

Basic usage:

    $p = new parser;
    $p->filename = '/absolute/path';
    $p->setVars();

    if (!$data = $p->fetchData())
        return true; // file had no data

The source:

class parser {
    var $lang = 'en',
    $author,
    $ip,
    $debug = false,
    $timestamp,
    $filename,
    $dataType,
    $error = '',
    $tableID,
    $tableName,
    $dataHeader,
    $dataVersion,
    $langName;

    function getcsv($dataArray, $delimiter=',', $enclosure='"')
    {
        $string = "";
        $writeDelimiter = false;
        foreach($dataArray as $dataElement)
        {
            if ($writeDelimiter)
                $string .= $delimiter;
            $string .= $enclosure . $dataElement . $enclosure;
            $writeDelimiter = true;
        }
    
        return $string;
    }
    function setVars()
    {
        if (!is_readable($this->filename))
        {
            $this->error = 'not readable';
            return false;
        }
        if (!is_file($this->filename))
        {
            $this->error = 'cannot open';
            return false;
        }

        return true;
    }
    function fetchData()
    {

        if (!$fp = fopen($this->filename, "rb"))
        {
            $this->error = 'unable to open file';
            return false;
        }

        $header = fread($fp, 4);
        
        if (($this->dataHeader = $this->selectType($header)) !== false)
        {
            $this->dataType = 'wdb';
            if (!$this->selectTable($this->dataHeader) && !$this->debug)
            {
                @unlink($this->filename);
                $this->error = 'useless data';
                return false;
            }
            if ((!$fields = $this->selectFields($this->dataHeader)) && !$this->debug)
            {
                $this->error = 'unable to select fields';
                return false;
            }

            $hex = bin2hex(fread($fp, 4));
            $hex = substr($hex, 6, 2).substr($hex, 4, 2).substr($hex, 2, 2).substr($hex, 0, 2);
            $this->dataVersion = hexdec($hex);

            if (!($this->dataVersion >= 5195))
            {
                @unlink($this->filename);
                $this->error = 'old data';
                return false;
            }

            $this->langName = strrev(fread($fp, 4));
            $this->lang = substr($this->langName, 0, 2);
            if (trim($this->lang) == 'zh')
                $this->lang = strtolower(substr($this->langName, -2));

            $hdr = $this->dataVersion.$this->langName.fread($fp, 8);
            if(!(ord($hdr)&1) && 0x5a!=ord($hdr))
                $hdr .= fread($fp, 4);

            $e = 0;
            while (!feof($fp))
            {
                $hex = bin2hex(fread($fp, 4));
                $hex = substr($hex, 6, 2).substr($hex, 4, 2).substr($hex, 2, 2).substr($hex, 0, 2);
                $id = hexdec($hex);
                            
                $hex = bin2hex(fread($fp, 4));
                $hex = substr($hex, 6, 2).substr($hex, 4, 2).substr($hex, 2, 2).substr($hex, 0, 2);
                $length = hexdec($hex);

                $rest = @fread($fp, $length);

                $array[$e][0] = $id;
                $z = 2;
                $i = 0;

                while ($i < strlen($rest))
                {
                    if (empty($fields[$z]))
                        $fields[$z] = array('0');
                    $string = '';

                    if ($fields[$z][0] == 1 || $fields[$z][0] == 2)
                    {
                        for($s=$i; ord(substr($rest, $i, 1)); ++$i)
                            ;
                        $string = substr($rest, $s, $i-$s);
                        $array[$e][$z] = $string;
                        $i++;
                    }
                    else
                    {
                        $string = substr($rest, $i, 4);
                        $i += 4;
                        $hex = bin2hex($string);
                        $hex = substr($hex, 6, 2).substr($hex, 4, 2).substr($hex, 2, 2).substr($hex, 0, 2);
                        list(,$floatval) = unpack("f*", $string);
                        if (round($floatval,0) == $floatval || $fields[$z][0] == 3)
                        {
                            $array[$e][$z] = round($floatval,2);
                        }
                        else
                            $array[$e][$z] = $this->parse_unsigned_int(hexdec($hex));

                        $string = '';
                    }
                    $z++;
                }
                $e++;
            }
            fclose($fp);
            return $array;
        }
        fclose($fp);
        $this->error = 'unknown error';
        return false;
    }
    function selectType($header)
    {
        switch ($header)
        {
            case 'BOGW':
                return 'gameobjectcache';
            case 'BOMW':
                return 'creaturecache';
            case 'BDNW':
                return 'itemnamecache';
            case 'TSQW':
                return 'questcache';
            case 'BDIW':
                return 'itemcache';
            case 'XTIW':
                return 'itemtextcaxhe';
            case 'CPNW':
                return 'npccache';
            case 'XTPW':
                return 'pagetextcache';
        }
    }
    function selectTable($type)
    {
        switch ($type)
        {
            case "creaturecache":
            {
                $this->tableName = 'db_creatures';
                $this->tableID = 'creatureID';
                return true;
            }
            case "itemcache":
            {
                $this->tableName = 'db_items';
                $this->tableID = 'itemID';
                return true;
            }
            case "questcache":
            {
                $this->tableName = 'db_quests';
                $this->tableID = 'questID';
                return true;
            }
            case "gameobjectcache":
            {
                $this->tableName = 'db_objects';
                $this->tableID = 'objectID';
                return true;
            }
            case "pagetextcache":
            {
                $this->tableName = 'db_pages';
                $this->tableID = 'pageID';
                return true;
            }
        }
    }
    function selectFields($type)
    {
        // fist param: 1 for string, 2 for trash, 3 for float
        // second param: field name for strings
        switch ($type)
        {
            case 'itemcache':
                $ar = array();
                $ar[4] = array(1,'itemName');
                $ar[5] = array(2);
                $ar[6] = array(2);
                $ar[7] = array(2);
                $ar[48] = array(3);
                $ar[49] = array(3);
                $ar[51] = array(3);
                $ar[52] = array(3);
                $ar[54] = array(3);
                $ar[55] = array(3);
                $ar[57] = array(3);
                $ar[58] = array(3);
                $ar[60] = array(3);
                $ar[61] = array(3);
                $ar[104] = array(1,'itemDescription');
                return $ar;
                break;
            case 'questcache':
                $ar = array();
                $ar[41] = array(1,'questName');
                $ar[42] = array(1,'questDescription');
                $ar[43] = array(1,'questDetails');
                $ar[44] = array(1,'questSubdescription');
                $ar[61] = array(1,'objective1');
                $ar[62] = array(1,'objective2');
                $ar[63] = array(1,'objective3');
                $ar[64] = array(1,'objective4');
                return $ar;
                break;
            case 'npccache':
                $ar = array();
                $ar[3] = array(1,'speech1String');
                $ar[4] = array(2);
                $ar[6] = array(1,'speech2String');
                $ar[7] = array(2);
                $ar[14] = array(1,'speech3String');
                $ar[15] = array(2);
                $ar[24] = array(1,'speed4String');
                $ar[25] = array(2);
                return $ar;
                break;
            case 'itemnamecache':
                return array(
                        'item_id',
                        '',
                        'name:string',
                );
                break;
            case 'itemtextcaxhe':
                return array(
                        'item_id',
                        '',
                        'text:string',
                );
                break;
            case 'creaturecache':
                $ar = array();
                $ar[2] = array(1,'creatureName');
                $ar[3] = array(2);
                $ar[4] = array(2);
                $ar[5] = array(2);
                $ar[6] = array(1,'creatureDescription');
                return $ar;
                break;
            case 'gameobjectcache':
                $ar = array();
                $ar[4] = array(1,'objectName');
                $ar[5] = array(2);
                $ar[6] = array(2);
                $ar[7] = array(2);
                return $ar;
                break;
            case 'pagetextcache':
                return array(
                        'page_id',
                        '',
                        'text:string',
                );
                break;
        }
    }
    function parse_unsigned_int($string) {
        $x = (float)$string;
        if ($x > (float)2147483647)
            $x -= (float)"4294967296";
        else
            return $string;
        return (int)$x;
   }
}
Personal tools
Sponsors