Esempio n. 1
0
bool changenth(std::string &str, int n, const char *with, bool insert = false, bool nonzero = false)
{
    std::string::size_type s, e;
    if(!findnth(str,n,s,e))
        return false;

    if(nonzero && str.substr(s,e-s) == "0")
        return true;                                        // not an error
    if(!insert)
        str.replace(s,e-s, with);
    else
        str.insert(s, with);

    return true;
}
Esempio n. 2
0
DumpReturn PlayerDumpReader::LoadDump(const std::string& file, uint32 account, std::string name, uint32 guid, bool onlyBoundedItems)
{
    uint32 charcount = AccountMgr::GetCharactersCount(account);
    if (charcount >= 10)
        return DUMP_TOO_MANY_CHARS;

    FILE* fin = fopen(file.c_str(), "r");
    if (!fin)
        return DUMP_FILE_OPEN_ERROR;

    char newguid[20], chraccount[20], newpetid[20], currpetid[20], lastpetid[20];

    // midgar
    std::list<std::string> queryQueue;

    // make sure the same guid doesn't already exist and is safe to use
    bool incHighest = true;
    if (guid != 0 && guid < sObjectMgr->_hiCharGuid)
    {
        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_GUID);
        stmt->setUInt32(0, guid);
        PreparedQueryResult result = CharacterDatabase.Query(stmt);

        if (result)
            guid = sObjectMgr->_hiCharGuid; // use first free if exists
        else
            incHighest = false;
    }
    else
        guid = sObjectMgr->_hiCharGuid;

    // normalize the name if specified and check if it exists
    if (!normalizePlayerName(name))
        name = "";

    if (ObjectMgr::CheckPlayerName(name, true) == CHAR_NAME_SUCCESS)
    {
        PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
        stmt->setString(0, name);
        PreparedQueryResult result = CharacterDatabase.Query(stmt);

        if (result)
            name = "";                                      // use the one from the dump
    }
    else
        name = "";

    // name encoded or empty

    snprintf(newguid, 20, "%u", guid);
    snprintf(chraccount, 20, "%u", account);
    snprintf(newpetid, 20, "%u", sObjectMgr->GeneratePetNumber());
    snprintf(lastpetid, 20, "%s", "");

    std::map<uint32, uint32> items;
    std::map<uint32, uint32> mails;
    char buf[32000] = "";

    typedef std::map<uint32, uint32> PetIds;// old->new petid relation
    typedef PetIds::value_type PetIdsPair;
    PetIds petids;

    SQLTransaction trans = CharacterDatabase.BeginTransaction();
    std::stringstream stringstr;

    while (!feof(fin))
    {
        if (!fgets(buf, 32000, fin))
        {
            if (feof(fin))
                break;
            ROLLBACK(DUMP_FILE_BROKEN);
        }

        std::string line; line.assign(buf);

        // skip empty strings
        size_t nw_pos = line.find_first_not_of(" \t\n\r\7");
        if (nw_pos == std::string::npos)
            continue;

        // skip logfile-side dump start notice, the important notes and dump end notices
        if ((line.substr(nw_pos, 16) == "== START DUMP ==") ||
            (line.substr(nw_pos, 15) == "IMPORTANT NOTE:") ||
            (line.substr(nw_pos, 14) == "== END DUMP =="))
            continue;

        // add required_ check
        /*
            if (line.substr(nw_pos, 41) == "UPDATE character_db_version SET required_")
            {
                if (!CharacterDatabase.Execute(line.c_str()))
                    ROLLBACK(DUMP_FILE_BROKEN);

                continue;
            }
        */

        // determine table name and load type
        std::string tn = gettablename(line);
        if (tn.empty())
        {
            sLog->outError(LOG_FILTER_GENERAL, "LoadPlayerDump: Can't extract table name from line: '%s'!", line.c_str());
            ROLLBACK(DUMP_FILE_BROKEN);
        }

        DumpTableType type = DumpTableType(0);
        uint8 i;
        for (i = 0; i < DUMP_TABLE_COUNT; ++i)
        {
            if (tn == dumpTables[i].name)
            {
                type = dumpTables[i].type;
                break;
            }
        }

        if (i == DUMP_TABLE_COUNT)
        {
            sLog->outError(LOG_FILTER_GENERAL, "LoadPlayerDump: Unknown table: '%s'!", tn.c_str());
            ROLLBACK(DUMP_FILE_BROKEN);
        }

        bool allowedAppend = true;

        // change the data to server values
        switch (type)
        {
            case DTT_CHARACTER:
            {
                if (!changenth(line, 1, newguid)) // characters.guid update
                    ROLLBACK(DUMP_FILE_BROKEN);

                if (!changenth(line, 2, chraccount))// characters.account update
                    ROLLBACK(DUMP_FILE_BROKEN);

                if (name == "")
                {
                    // check if the original name already exists
                    name = getnth(line, 3);

                    PreparedStatement* stmt = CharacterDatabase.GetPreparedStatement(CHAR_SEL_CHECK_NAME);
                    stmt->setString(0, name);
                    PreparedQueryResult result = CharacterDatabase.Query(stmt);

                    if (result)
                        if (!changenth(line, 41, "1"))       // characters.at_login set to "rename on login"
                            ROLLBACK(DUMP_FILE_BROKEN);
                }
                else if (!changenth(line, 3, name.c_str())) // characters.name
                    ROLLBACK(DUMP_FILE_BROKEN);

                const char null[5] = "NULL";
                if (!changenth(line, 69, null))// characters.deleteInfos_Account
                    ROLLBACK(DUMP_FILE_BROKEN);
                if (!changenth(line, 70, null))// characters.deleteInfos_Name
                    ROLLBACK(DUMP_FILE_BROKEN);
                if (!changenth(line, 71, null))// characters.deleteDate
                    ROLLBACK(DUMP_FILE_BROKEN);
                break;
            }
            case DTT_CHAR_TABLE:
            {
                if (!changenth(line, 1, newguid)) // character_*.guid update
                    ROLLBACK(DUMP_FILE_BROKEN);
                break;
            }
            case DTT_EQSET_TABLE:
            {
                if (!changenth(line, 1, newguid))
                    ROLLBACK(DUMP_FILE_BROKEN); // character_equipmentsets.guid

                char newSetGuid[24];
                snprintf(newSetGuid, 24, UI64FMTD, sObjectMgr->GenerateEquipmentSetGuid());
                if (!changenth(line, 2, newSetGuid))
                    ROLLBACK(DUMP_FILE_BROKEN);// character_equipmentsets.setguid
                break;
            }
            case DTT_INVENTORY:
            {
                if (!changenth(line, 1, newguid)) // character_inventory.guid update
                    ROLLBACK(DUMP_FILE_BROKEN);

                if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid, true))
                    ROLLBACK(DUMP_FILE_BROKEN);// character_inventory.bag update
                if (!changeGuid(line, 4, items, sObjectMgr->_hiItemGuid))
                    ROLLBACK(DUMP_FILE_BROKEN);// character_inventory.item update
                break;
            }
            case DTT_MAIL: // mail
            {
                if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
                    ROLLBACK(DUMP_FILE_BROKEN); // mail.id update
                if (!changenth(line, 6, newguid))// mail.receiver update
                    ROLLBACK(DUMP_FILE_BROKEN);
                break;
            }
            case DTT_MAIL_ITEM: // mail_items
            {
                if (!changeGuid(line, 1, mails, sObjectMgr->_mailId))
                    ROLLBACK(DUMP_FILE_BROKEN); // mail_items.id
                if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid))
                    ROLLBACK(DUMP_FILE_BROKEN);// mail_items.item_guid
                if (!changenth(line, 3, newguid))// mail_items.receiver
                    ROLLBACK(DUMP_FILE_BROKEN);
                break;
            }
            case DTT_ITEM:
            {
                // item, owner, data field:item, owner guid
                if (!changeGuid(line, 1, items, sObjectMgr->_hiItemGuid))
                    ROLLBACK(DUMP_FILE_BROKEN);// item_instance.guid update
                if (!changenth(line, 3, newguid))// item_instance.owner_guid update
                    ROLLBACK(DUMP_FILE_BROKEN);

                std::string oldReforgeId = getnth(line, 11).c_str();
                if (oldReforgeId == "''")
                    if (!changenth(line, 11, "0"))
                        ROLLBACK(DUMP_FILE_BROKEN);

                std::string oldTransmogrificationId = getnth(line, 12).c_str();
                if (oldTransmogrificationId == "''")
                    if (!changenth(line, 12, "0"))
                        ROLLBACK(DUMP_FILE_BROKEN);

                if (onlyBoundedItems)
                {
                    std::string::size_type s, e;
                    if (!findnth(line, 9, s, e))
                        ROLLBACK(DUMP_FILE_BROKEN);

                    uint32 flags = atoi(line.substr(s, e - s).c_str());
                    if (!(flags & 1))
                        allowedAppend = false;
                }

                break;
            }
            case DTT_ITEM_GIFT:
            {
                if (!changenth(line, 1, newguid)) // character_gifts.guid update
                    ROLLBACK(DUMP_FILE_BROKEN);
                if (!changeGuid(line, 2, items, sObjectMgr->_hiItemGuid))
                    ROLLBACK(DUMP_FILE_BROKEN);// character_gifts.item_guid update
                break;
            }
            case DTT_PET:
            {
                //store a map of old pet id to new inserted pet id for use by type 5 tables
                snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());
                if (*lastpetid == '\0')
                    snprintf(lastpetid, 20, "%s", currpetid);
                if (strcmp(lastpetid, currpetid) != 0)
                {
                    snprintf(newpetid, 20, "%d", sObjectMgr->GeneratePetNumber());
                    snprintf(lastpetid, 20, "%s", currpetid);
                }

                std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));

                if (petids_iter == petids.end())
                {
                    petids.insert(PetIdsPair(atoi(currpetid), atoi(newpetid)));
                }

                if (!changenth(line, 1, newpetid)) // character_pet.id update
                    ROLLBACK(DUMP_FILE_BROKEN);
                if (!changenth(line, 3, newguid))// character_pet.owner update
                    ROLLBACK(DUMP_FILE_BROKEN);

                break;
            }
            case DTT_PET_TABLE: // pet_aura, pet_spell, pet_spell_cooldown
            {
                snprintf(currpetid, 20, "%s", getnth(line, 1).c_str());

                // lookup currpetid and match to new inserted pet id
                std::map<uint32, uint32> :: const_iterator petids_iter = petids.find(atoi(currpetid));
                if (petids_iter == petids.end())// couldn't find new inserted id
                {
                    allowedAppend = false;
                    break;
                }

                snprintf(newpetid, 20, "%d", petids_iter->second);

                if (!changenth(line, 1, newpetid))
                    ROLLBACK(DUMP_FILE_BROKEN);

                break;
            }
            default:
                //sLog->outError("Unknown dump table type: %u", type);
                ROLLBACK(DUMP_FILE_BROKEN);
                break;
        }

        if (allowedAppend)
        {
            fixNULLfields(line);

            trans->Append(line.c_str());
            queryQueue.push_back(line);
        }
    }

    CharacterDatabase.CommitTransaction(trans);
    //CharacterDatabase.DirectCommitTransaction(trans);

    sObjectMgr->_hiItemGuid += items.size();
    sObjectMgr->_mailId += mails.size();

    if (incHighest)
        ++sObjectMgr->_hiCharGuid;

    fclose(fin);

    //result = CharacterDatabase.PQuery("SELECT 1 FROM characters WHERE name = '%s'", name.c_str());

    //if(!result)
        //return DUMP_FILE_BROKEN;

    ///////////////////////////////////////////

    return DUMP_SUCCESS;
}