예제 #1
0
BanManager::BanManager()
{
    Result result(db->Select("SELECT * FROM bans"));
    if (!result.IsValid())
        return;

    time_t now = time(0);
    for (unsigned int i=0; i<result.Count(); i++)
    {
        AccountID account = AccountID(result[i].GetUInt32("account"));
        time_t end = result[i].GetUInt32("end");

        if (now > end)  // Time served
        {
            db->Command("DELETE FROM bans WHERE account='%u'", account.Unbox());
            continue;
        }

        BanEntry* newentry = new BanEntry;
        newentry->account = account;
        newentry->end = end;
        newentry->start = result[i].GetUInt32("start");
        newentry->ipRange = result[i]["ip_range"];
        newentry->reason = result[i]["reason"];
        newentry->banIP = result[i].GetUInt32("ban_ip") != 0;
        
        // If account ban, add to list
        if (newentry->account.IsValid())
            banList_IDHash.Put(newentry->account,newentry);

        // If IP range ban, add to list
        if ( newentry->ipRange.Length() && newentry->banIP /*(!end || now < newentry->start + IP_RANGE_BAN_TIME)*/ )
            banList_IPRList.Push(newentry);
    }
}
예제 #2
0
파일: AccountID.cpp 프로젝트: E-LLP/rippled
std::string
toBase58 (AccountID const& v)
{
    return base58EncodeToken(
        TOKEN_ACCOUNT_ID,
            v.data(), v.size());
}
예제 #3
0
uint256 CanonicalTXSet::accountKey (AccountID const& account)
{
    uint256 ret = beast::zero;
    memcpy (
        ret.begin (),
        account.begin (),
        account.size ());
    ret ^= salt_;
    return ret;
}
예제 #4
0
파일: AccountID.cpp 프로젝트: E-LLP/rippled
boost::optional<AccountID>
parseHex (std::string const& s)
{
    if (s.size() != 40)
        return boost::none;
    AccountID id;
    if (! id.SetHex(s, true))
        return boost::none;
    return id;
}
예제 #5
0
파일: AccountID.cpp 프로젝트: E-LLP/rippled
/*
    Calculation of the Account ID

    The AccountID is a 160-bit identifier that uniquely
    distinguishes an account. The account may or may not
    exist in the ledger. Even for accounts that are not in
    the ledger, cryptographic operations may be performed
    which affect the ledger. For example, designating an
    account not in the ledger as a regular key for an
    account that is in the ledger.

    Why did we use half of SHA512 for most things but then
    SHA256 followed by RIPEMD160 for account IDs? Why didn't
    we do SHA512 half then RIPEMD160? Or even SHA512 then RIPEMD160?
    For that matter why RIPEMD160 at all why not just SHA512 and keep
    only 160 bits?

    Answer (David Schwartz):

        The short answer is that we kept Bitcoin's behavior.
        The longer answer was that:
            1) Using a single hash could leave ripple
               vulnerable to length extension attacks.
            2) Only RIPEMD160 is generally considered safe at 160 bits.

        Any of those schemes would have been acceptable. However,
        the one chosen avoids any need to defend the scheme chosen.
        (Against any criticism other than unnecessary complexity.)

        "The historical reason was that in the very early days,
        we wanted to give people as few ways to argue that we were
        less secure than Bitcoin. So where there was no good reason
        to change something, it was not changed."
*/
AccountID
calcAccountID (PublicKey const& pk)
{
    ripesha_hasher rsh;
    rsh(pk.data(), pk.size());
    auto const d = static_cast<
        ripesha_hasher::result_type>(rsh);
    AccountID id;
    static_assert(sizeof(d) == sizeof(id), "");
    std::memcpy(id.data(), d.data(), d.size());
    return id;
}
예제 #6
0
STPathSet::STPathSet (SerialIter& sit, SField const& name)
    : STBase(name)
{
    std::vector<STPathElement> path;
    for(;;)
    {
        int iType = sit.get8 ();

        if (iType == STPathElement::typeNone ||
            iType == STPathElement::typeBoundary)
        {
            if (path.empty ())
            {
                JLOG (debugLog().error())
                    << "Empty path in pathset";
                Throw<std::runtime_error> ("empty path");
            }

            push_back (path);
            path.clear ();

            if (iType == STPathElement::typeNone)
                return;
        }
        else if (iType & ~STPathElement::typeAll)
        {
            JLOG (debugLog().error())
                << "Bad path element " << iType << " in pathset";
            Throw<std::runtime_error> ("bad path element");
        }
        else
        {
            auto hasAccount = iType & STPathElement::typeAccount;
            auto hasCurrency = iType & STPathElement::typeCurrency;
            auto hasIssuer = iType & STPathElement::typeIssuer;

            AccountID account;
            Currency currency;
            AccountID issuer;

            if (hasAccount)
                account.copyFrom (sit.get160 ());

            if (hasCurrency)
                currency.copyFrom (sit.get160 ());

            if (hasIssuer)
                issuer.copyFrom (sit.get160 ());

            path.emplace_back (account, currency, issuer, hasCurrency);
        }
    }
}
예제 #7
0
// DEPRECATED
AccountID
calcAccountID (RippleAddress const& publicKey)
{
    auto const& pk =
        publicKey.getAccountPublic();
    ripesha_hasher rsh;
    rsh(pk.data(), pk.size());
    auto const d = static_cast<
        ripesha_hasher::result_type>(rsh);
    AccountID id;
    static_assert(sizeof(d) == sizeof(id), "");
    std::memcpy(id.data(), d.data(), d.size());
    return id;
}
예제 #8
0
파일: AccountID.cpp 프로젝트: E-LLP/rippled
boost::optional<AccountID>
deprecatedParseBitcoinAccountID (std::string const& s)
{
    auto const result =
        decodeBase58TokenBitcoin(
            s, TOKEN_ACCOUNT_ID);
    if (result.empty())
        return boost::none;
    AccountID id;
    if (result.size() != id.size())
        return boost::none;
    std::memcpy(id.data(),
        result.data(), result.size());
    return id;
}
예제 #9
0
bool CharCreationManager::IsLastNameAvailable(const char* lastname, AccountID requestingAcct)
{
    if(!lastname || strlen(lastname) < 1)
        return true; // blank last names are allowed.

    // Check to see if name already exists in character database.
    csString query;
    csString escape;
    db->Escape(escape, lastname);
    query.Format("SELECT account_id FROM characters WHERE lastname='%s'", escape.GetData());
    Result result(db->Select(query));
    if(result.IsValid())
    {
        if(result.Count() == 0)
            return true; // nobody owns it yet, it's available

        if(requestingAcct.IsValid())
        {
            for(unsigned int i = 0; i < result.Count(); i++)
            {
                if(AccountID(result[i].GetInt("account_id")) == requestingAcct)
                    return true; // another character on the same account; available
            }
        }
    }
    return false; // already in use by someone else
}
예제 #10
0
int CharCreationManager::IsReserved(const char* name, AccountID acctID)
{
    // Check to see if this name is reserved.  Does this check by comparing
    // the email address of the account with that stored in the migration table.
    csString query;
    csString escape;
    db->Escape(escape, name);
    query.Format("SELECT m.email FROM migration m WHERE m.username='******'", escape.GetData());
    Result result(db->Select(query));

    if(result.IsValid() && result.Count() == 1)
    {
        csString savedEmail(result[0][0]);

        query.Format("SELECT username FROM accounts WHERE id=%d\n", acctID.Unbox());

        Result result2(db->Select(query));
        if(result2.IsValid() && result2.Count() == 1)
        {
            csString email(result2[0][0]);
            if(savedEmail.CompareNoCase(email))
                return NAME_RESERVED_FOR_YOU;
            else
                return NAME_RESERVED;
        }
    }

    return NAME_AVAILABLE;
}
예제 #11
0
bool BanManager::RemoveBan(AccountID account)
{
    BanEntry* ban = GetBanByAccount(account);
    if (!ban)
        return false;  // Not banned

    db->Command("DELETE FROM bans WHERE account='%u'", account.Unbox());
    banList_IDHash.Delete(account,ban);
    banList_IPRList.Delete(ban);
    delete ban;
    return true;
}
예제 #12
0
파일: AccountID.cpp 프로젝트: E-LLP/rippled
bool
to_issuer (AccountID& issuer, std::string const& s)
{
    if (s.size () == (160 / 4))
    {
        issuer.SetHex (s);
        return true;
    }
    auto const account =
        parseBase58<AccountID>(s);
    if (! account)
        return false;
    issuer = *account;
    return true;
}
//新增加帐号
void CAccountDBAddHandler::AddAccount(unsigned uiSessionFd, const AccountID& stAccountID, int iWorldID, const std::string& strPasswd)
{
    static GameProtocolMsg stMsg;

    //生成消息头
    GenerateMsgHead(&stMsg, uiSessionFd, MSGID_ACCOUNTDB_ADDACCOUNT_REQUEST, GetAccountHash(stAccountID.straccount()));

    //AccountDB插入新帐号的请求
    AccountDB_AddAccount_Request* pstReq = stMsg.mutable_m_stmsgbody()->mutable_m_staccountdb_addaccount_request();
    pstReq->mutable_staccountid()->CopyFrom(stAccountID);
    pstReq->set_iworldid(iWorldID);

    //加密密码
    char szEncryptPasswd[256] = {0};
    int iEncryptBuffLen = sizeof(szEncryptPasswd);

    int iRet = CPasswordEncryptionUtility::DoPasswordEncryption(strPasswd.c_str(), strPasswd.size(), szEncryptPasswd, iEncryptBuffLen);
    if(iRet)
    {
        TRACESVR("Failed to encrypt account password, account: %s, password: %s\n", stAccountID.straccount().c_str(), strPasswd.c_str());
        return;
    }

    //设置密码为加密后的密码
    pstReq->set_strpassword(szEncryptPasswd, iEncryptBuffLen);

    //转发消息给AccountDBServer
    if(EncodeAndSendCode(SSProtocolEngine, NULL, &stMsg, GAME_SERVER_ACCOUNTDB) != 0)
    {
        TRACESVR("Failed to send add account request to Account DB server\n");
        return;
    }

    LOGDEBUG("Send add account request to Account DB server\n");

    return;
}
예제 #14
0
void CharCreationManager::HandleUploadMessage(MsgEntry* me, Client* client)
{
    Debug1(LOG_NEWCHAR, me->clientnum,"New Character is being created");

    psCharUploadMessage upload(me);

    if(!upload.valid)
    {
        Debug2(LOG_NET,me->clientnum,"Received unparsable psUploadMessage from client %u.",me->clientnum);
        return;
    }

    AccountID acctID = client->GetAccountID();
    if(!acctID.IsValid())
    {
        Error2("Player tried to upload a character to unknown account %s.", ShowID(acctID));

        psCharRejectedMessage reject(me->clientnum);

        psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET);
        psserver->RemovePlayer(me->clientnum,"Could not find your account.");
        return;
    }

    // Check to see if the player already has 4 accounts;
    csString query;
    query.Format("SELECT id FROM characters WHERE account_id=%d", acctID.Unbox());
    Result result(db->Select(query));
    if(result.IsValid() && result.Count() >= CHARACTERS_ALLOWED)
    {
        psserver->RemovePlayer(me->clientnum,"At your character limit.");
        return;
    }

    csString playerName =  upload.name;
    csString lastName =  upload.lastname;

    playerName = NormalizeCharacterName(playerName);
    lastName = NormalizeCharacterName(lastName);

    // Check banned names
    if(psserver->GetCharManager()->IsBanned(playerName))
    {
        csString error;
        error.Format("The name %s is banned", playerName.GetData());
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::RESERVED_NAME,
                                     (char*)error.GetData());
        reject.SendMessage();
        return;
    }

    if(psserver->GetCharManager()->IsBanned(lastName))
    {
        csString error;
        error.Format("The lastname %s is banned", lastName.GetData());
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::RESERVED_NAME,
                                     (char*)error.GetData());
        reject.SendMessage();
        return;
    }

    Debug3(LOG_NEWCHAR, me->clientnum,"Got player firstname (%s) and lastname (%s)\n",playerName.GetData(), lastName.GetData());

    ///////////////////////////////////////////////////////////////
    //  Check to see if the player name is valid
    ///////////////////////////////////////////////////////////////
    if(playerName.Length() == 0 || !FilterName(playerName))
    {
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::NON_LEGAL_NAME,
                                     "The name you specifed is not a legal player name.");

        psserver->GetEventManager()->SendMessage(reject.msg);
        return;
    }

    if(lastName.Length() != 0 && !FilterName(lastName))
    {
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::NON_LEGAL_NAME,
                                     "The name you specifed is not a legal lastname.");

        psserver->GetEventManager()->SendMessage(reject.msg);
        return;
    }

    Debug2(LOG_NEWCHAR, me->clientnum,"Checking player firstname '%s'..\n",playerName.GetData());
    ///////////////////////////////////////////////////////////////
    //  Check to see if the character name is unique in 'characters'.
    ///////////////////////////////////////////////////////////////
    if(!IsUnique(playerName))
    {
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::NON_UNIQUE_NAME,
                                     "The firstname you specifed is not unique.");

        psserver->GetEventManager()->SendMessage(reject.msg);
        return;
    }

    if(lastName.Length())
    {
        Debug2(LOG_NEWCHAR, me->clientnum,"Checking player lastname '%s'..\n",lastName.GetData());
        if(!IsLastNameAvailable(lastName, acctID))
        {
            psCharRejectedMessage reject(me->clientnum,
                                         psCharRejectedMessage::NON_UNIQUE_NAME,
                                         "The lastname you specifed is not unique.");

            psserver->GetEventManager()->SendMessage(reject.msg);
            return;
        }
    }
    ///////////////////////////////////////////////////////////////
    //  Check to see if the character name is on the reserve list.
    ///////////////////////////////////////////////////////////////
    int reservedName = IsReserved(playerName, acctID);
    if(reservedName == NAME_RESERVED)
    {
        csString error;
        error.Format("The name %s is reserved", playerName.GetData());
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::RESERVED_NAME,
                                     (char*)error.GetData());

        psserver->GetEventManager()->SendMessage(reject.msg);
        return;
    }


    csString error;
    if(!psserver->charCreationManager->Validate(upload, error))
    {
        error.Append(", your creation choices are invalid.");
        psCharRejectedMessage reject(me->clientnum,
                                     psCharRejectedMessage::INVALID_CREATION,
                                     (char*)error.GetData());

        reject.SendMessage();
        return;
    }

    ///////////////////////////////////////////////////////////////
    //  Create the psCharacter structure for the player.
    ///////////////////////////////////////////////////////////////
    psCharacter* chardata=new psCharacter();
    chardata->SetCharType(PSCHARACTER_TYPE_PLAYER);
    chardata->SetFullName(playerName,lastName);
    chardata->SetCreationInfo(upload.bio);

    psRaceInfo* raceinfo=psserver->GetCacheManager()->GetRaceInfoByNameGender(upload.race, (PSCHARACTER_GENDER)upload.gender);
    if(raceinfo==NULL)
    {
        Error3("Invalid race/gender combination on character creation:  Race='%d' Gender='%d'", upload.race, upload.gender);
        psCharRejectedMessage reject(me->clientnum);
        psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET);
        psserver->RemovePlayer(me->clientnum,"Player tried to create an invalid race/gender.");
        delete chardata;
        return;
    }
    chardata->SetRaceInfo(raceinfo);
    chardata->SetHitPoints(50.0);
    chardata->GetMaxHP().SetBase(0.0);
    chardata->GetMaxMana().SetBase(0.0);

    //range is unused here
    float x,y,z,yrot,range;
    const char* sectorname;
    InstanceID newinstance = DEFAULT_INSTANCE;

    //get the option entries for tutorial from the server options. Note it's tutorial:variousdata
    optionEntry* tutorialEntry = psserver->GetCacheManager()->getOptionSafe("tutorial","");
    sectorname = tutorialEntry->getOptionSafe("sectorname", "tutorial")->getValue();

    psSectorInfo* sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName(sectorname);

    if(!sectorinfo || PlayerHasFinishedTutorial(acctID, sectorinfo->uid))
    {
        raceinfo->GetStartingLocation(x,y,z,yrot,range,sectorname);
        sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName(sectorname);

        //As we aren't going in the tutorial disable the tutorial help messages disable them
        for(int i = 0; i < TutorialManager::TUTOREVENTTYPE_COUNT; i++)
            chardata->CompleteHelpEvent(i);
    }
    else
    {
        // Try tutorial level first.
        x = tutorialEntry->getOptionSafe("sectorx", "-225.37")->getValueAsDouble();
        y = tutorialEntry->getOptionSafe("sectory", "-21.32")->getValueAsDouble();
        z = tutorialEntry->getOptionSafe("sectorz", "26.79")->getValueAsDouble();
        yrot = tutorialEntry->getOptionSafe("sectoryrot", "-2.04")->getValueAsDouble();
    }

    bool sectorFound = true;

    if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name) == NULL)
    {
        Error2("Sector='%s' found but no map file was detected for it. Using NPCroom1", sectorname);
        sectorinfo = psserver->GetCacheManager()->GetSectorInfoByName("NPCroom1");
        if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name) == NULL)
        {
            Error1("NPCroom1 failed - Critical");
            sectorFound = false;
        }
        else if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name))
        {
            sectorFound = true;
        }
        else
        {
            sectorFound = false;
        }
    }
    else if(sectorinfo && EntityManager::GetSingleton().FindSector(sectorinfo->name))
    {
        sectorFound = true;
    }
    else
    {
        sectorFound = false;
    }


    if(!sectorFound)
    {
        Error2("Unresolvable starting sector='%s'", sectorname);
        psCharRejectedMessage reject(me->clientnum);
        psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET);
        psserver->RemovePlayer(me->clientnum,"No starting Sector.");
        delete chardata;
        return;
    }

    chardata->SetLocationInWorld(newinstance, sectorinfo, x, y, z, yrot);

    psTrait* trait;
//    CPrintf(CON_DEBUG, "Trait: %d\n", upload.selectedFace );
    trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedFace);
    if(trait)
        chardata->SetTraitForLocation(trait->location, trait);

    trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedHairStyle);
    if(trait)
        chardata->SetTraitForLocation(trait->location, trait);

    trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedBeardStyle);
    if(trait)
        chardata->SetTraitForLocation(trait->location, trait);

    trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedHairColour);
    if(trait)
        chardata->SetTraitForLocation(trait->location, trait);

    trait = psserver->GetCacheManager()->GetTraitByID(upload.selectedSkinColour);
    if(trait)
        chardata->SetTraitForLocation(trait->location, trait);

    gemActor* actor = new gemActor(gemSupervisor, cacheManager, entityManager, chardata,
                                   raceinfo->mesh_name,
                                   newinstance,
                                   EntityManager::GetSingleton().FindSector(sectorinfo->name),
                                   csVector3(x,y,z),yrot,
                                   client->GetClientNum());

    actor->SetupCharData();

    if(!upload.verify)
    {
        if(!psServer::CharacterLoader.NewCharacterData(acctID,chardata))
        {
            Error1("Character could not be created.");
            psCharRejectedMessage reject(me->clientnum);
            psserver->GetEventManager()->Broadcast(reject.msg, NetBase::BC_FINALPACKET);
            psserver->RemovePlayer(me->clientnum,"Your character could not be created in the database.");
            delete chardata;
            return;
        }
    }

    // Check to see if a path name was set. If so we will use that to generate
    // the character starting stats and skills.
    if(upload.path != "None")
    {
        // Progression Event name is PATH_PathName
        csString name("PATH_");
        name.Append(upload.path);
        ProgressionScript* script = psserver->GetProgressionManager()->FindScript(name.GetData());
        if(script)
        {
            // The script uses the race base character points to calculate starting stats.
            MathEnvironment env;
            env.Define("CharPoints", raceinfo->initialCP);
            env.Define("Actor", actor);
            script->Run(&env);
        }
    }
    else
    {
        //int cpUsage = psserver->charCreationManager->CalculateCPChoice( upload.choices ) +
        //              psserver->charCreationManager->CalculateCPLife(upload.lifeEvents );
        for(size_t ci = 0; ci < upload.choices.GetSize(); ci++)
        {
            CharCreationManager::CreationChoice* choice = psserver->charCreationManager->FindChoice(upload.choices[ci]);
            if(choice)
            {
                csString name(psserver->charCreationManager->FindChoice(upload.choices[ci])->name.GetData());
                Debug3(LOG_NEWCHAR, me->clientnum,"Choice: %s Creation Script: %s", name.GetData(), choice->eventScript.GetData());

                MathEnvironment env;
                env.Define("Actor", actor);
                if(choice->choiceArea == FATHER_JOB || choice->choiceArea == MOTHER_JOB)
                {
                    int modifier = (choice->choiceArea == FATHER_JOB) ? upload.fatherMod : upload.motherMod;
                    if(modifier > 3 || modifier < 1)
                        modifier = 1;

                    env.Define("ParentStatus", modifier);
                }
                ProgressionScript* script = psserver->GetProgressionManager()->FindScript(choice->eventScript);
                if(script)
                    script->Run(&env);
            }
            else
            {
                Debug2(LOG_NEWCHAR, me->clientnum,"Character Choice %d not found\n", upload.choices[ci]);
            }
        }
        for(size_t li = 0; li < upload.lifeEvents.GetSize(); li++)
        {
            MathEnvironment env;
            env.Define("Actor", actor);
            LifeEventChoiceServer* lifeEvent = psserver->charCreationManager->FindLifeEvent(upload.lifeEvents[li]);
            if(!lifeEvent)
            {
                Error2("No LifeEvent Script found: %d", upload.lifeEvents[li]);
                continue;
            }

            csString scriptName(lifeEvent->eventScript.GetData());
            Debug2(LOG_NEWCHAR, me->clientnum, "LifeEvent Script: %s", scriptName.GetDataSafe());

            ProgressionScript* script = psserver->GetProgressionManager()->FindScript(scriptName);
            if(script)
                script->Run(&env);
        }
    }

    if(!upload.verify)
    {

        if(reservedName == NAME_RESERVED_FOR_YOU)
        {
            AssignScript(chardata);
        }
        // This function recalculates the Max HP, Mana and Stamina of the new character
        chardata->RecalculateStats();

        // Make sure the new player have HP, Mana and Samina that was calculated
        chardata->SetHitPoints(chardata->GetMaxHP().Base());
        chardata->SetMana(chardata->GetMaxMana().Base());
        chardata->SetStamina(chardata->GetMaxPStamina().Base(),true);
        chardata->SetStamina(chardata->GetMaxMStamina().Base(),false);


        psServer::CharacterLoader.SaveCharacterData(chardata, actor);
        Debug1(LOG_NEWCHAR,me->clientnum,"Player Creation Complete");

        // Remove cached objects to make sure that the client gets a fresh character
        // list from the database if it logs out and in within 2 minutes.
        iCachedObject* obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("list",client->GetAccountID().Unbox()));
        if(obj)
        {
            obj->ProcessCacheTimeout();
            obj->DeleteSelf();
        }
        obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("auth",client->GetAccountID().Unbox()));
        if(obj)
        {
            obj->ProcessCacheTimeout();
            obj->DeleteSelf();
        }

        // Here everything is ok
        client->SetPID(chardata->GetPID());
        client->SetName(playerName);

        psCharApprovedMessage app(me->clientnum);
        if(app.valid)
            psserver->GetEventManager()->SendMessage(app.msg);
        else
            Bug2("Could not create valid psCharApprovedMessage for client %u.\n",me->clientnum);
    }
    else
    {
        psCharVerificationMesg mesg(me->clientnum);
        size_t z;
        //unfortunately count goes out of valid area so we need to check on charisma

        for(z = 0; z < psserver->GetCacheManager()->GetSkillAmount(); z++)
        {
            unsigned int rank = chardata->Skills().GetSkillRank((PSSKILL) z).Base();

            psSkillInfo* info = psserver->GetCacheManager()->GetSkillByID(z);
            csString name("Not found");
            if(info)
                name.Replace(info->name);

            if(rank > 0)
            {
                if(z >= PSSKILL_AGI && z <= PSSKILL_WILL)
                {
                    mesg.AddStat(rank, name);
                }
                else
                {
                    mesg.AddSkill(rank, name);
                }
            }
        }
        mesg.Construct();
        mesg.SendMessage();
    }

    delete actor;

    if(!upload.verify)
    {
        // Remove char data from the cache
        iCachedObject* obj = psserver->GetCacheManager()->RemoveFromCache(psserver->GetCacheManager()->MakeCacheName("char", chardata->GetPID().Unbox()));
        if(obj)
        {
            obj->ProcessCacheTimeout();
            obj->DeleteSelf();
        }
    }
}
예제 #15
0
bool CharCreationManager::PlayerHasFinishedTutorial(AccountID acctID, uint32 tutorialsecid)
{
    // if there are characters associated with this account that are outside the tutorial assume the tutorial was passed...
    Result result(db->Select("SELECT id FROM characters WHERE account_id = %u AND loc_sector_id != %u", acctID.Unbox(), tutorialsecid));
    if(result.IsValid() && result.Count())
    {
        return true;
    }
    return false;
}
//拉取返回帐号详细信息
int CFetchAccountHandler::FetchAccountInfo(const AccountID& stAccountID, const std::string& strPassword, AccountDB_FetchAccount_Response& rstResp)
{
    //设置连接的DB
    const ONEACCOUNTDBINFO* pstDBConfig = (CAccountDBApp::m_stAccountDBConfigManager).GetOneAccountDBInfoByIndex(m_iThreadIdx);
    if(!pstDBConfig)
    {
        TRACE_THREAD(m_iThreadIdx, "Failed to get account db config, index %d\n", m_iThreadIdx);
        return -1;
    }

    int iRet = m_pDatabase->SetMysqlDBInfo(pstDBConfig->szDBHost, pstDBConfig->szUserName, pstDBConfig->szUserPasswd, pstDBConfig->szDBName);
    if(iRet)
    {
        TRACE_THREAD(m_iThreadIdx, "Failed to set mysql db info, ret %d\n", iRet);
        return iRet;
    }

    char* pszQueryString = m_szQueryString[m_iThreadIdx];
    int iLength = SAFE_SPRINTF(pszQueryString, sizeof(m_szQueryString[m_iThreadIdx])-1, "select * from %s where accountID='%s' and accountType=%d", 
                 MYSQL_ACCOUNTINFO_TABLE, stAccountID.straccount().c_str(), stAccountID.iaccounttype());

    iRet = m_pDatabase->ExecuteRealQuery(pszQueryString, iLength, true);
    if(iRet)
    {
        TRACE_THREAD(m_iThreadIdx, "Failed to execute sql query, ret %d\n", iRet);
        return iRet;
    }

     //分析结果
    int iRowNum = m_pDatabase->GetNumberRows();
    if(iRowNum != 1)
    {
        TRACE_THREAD(m_iThreadIdx, "Wrong result, invalid rows %d, account %s\n", iRowNum, stAccountID.straccount().c_str());
        return T_ACCOUNTDB_INVALID_RECORD;
    }

    MYSQL_ROW pstResult = NULL;
    unsigned long* pLengths = NULL;
    unsigned int uFields = 0;

    iRet = m_pDatabase->FetchOneRow(pstResult, pLengths, uFields);
    if(iRet)
    {
        TRACE_THREAD(m_iThreadIdx, "Failed to fetch rows, account %s, ret %d\n", stAccountID.straccount().c_str(), iRet);
        return iRet;
    }

    //判断uFields是否相符
    if(uFields != MYSQL_ACCOUNTINFO_FIELDS)
    {
        TRACE_THREAD(m_iThreadIdx, "Wrong result, real fields %u, needed %u\n", uFields, MYSQL_ACCOUNTINFO_FIELDS);
        return T_ACCOUNTDB_INVALID_RECORD;
    }

    //字段3是password
    std::string strDBPassword(pstResult[3], pLengths[3]);

    //检查密码是否一致
    if(strDBPassword.compare(strPassword) != 0)
    {
        return T_ACCOUNTDB_INVALID_RECORD;
    }

    //从结果中解析需要的字段
    rstResp.mutable_staccountid()->CopyFrom(stAccountID);

    //字段0是accountID, 字段1是accountType, 跳过

    //字段2是uin
    rstResp.set_uin(strtoul(pstResult[2],NULL,10));

    //字段4是lastWorldID
    rstResp.set_iworldid(atoi(pstResult[4]));

    //字段5是activeState
    rstResp.set_bisbinded(atoi(pstResult[5]));

    return T_SERVER_SUCESS;
}
예제 #17
0
std::pair<bool, Json::Value>
ripplePathFind (RippleLineCache::pointer const& cache,
  AccountID const& raSrc, AccountID const& raDst,
    STAmount const& saDstAmount, Json::Value const& jvSrcCurrencies,
        boost::optional<Json::Value> const& contextPaths, int const& level)
{
    FindPaths fp(
        cache,
        raSrc,
        raDst,
        saDstAmount,
        level,
        4); // max paths

    Json::Value jvArray(Json::arrayValue);

    for (unsigned int i = 0; i != jvSrcCurrencies.size(); ++i)
    {
        Json::Value jvSource = jvSrcCurrencies[i];

        Currency uSrcCurrencyID;
        AccountID uSrcIssuerID;

        if (!jvSource.isObject())
            return std::make_pair(false, rpcError(rpcINVALID_PARAMS));

        // Parse mandatory currency.
        if (!jvSource.isMember(jss::currency)
            || !to_currency(
            uSrcCurrencyID, jvSource[jss::currency].asString()))
        {
            WriteLog(lsINFO, RPCHandler) << "Bad currency.";

            return std::make_pair(false, rpcError(rpcSRC_CUR_MALFORMED));
        }

        if (uSrcCurrencyID.isNonZero())
            uSrcIssuerID = raSrc;

        // Parse optional issuer.
        if (jvSource.isMember(jss::issuer) &&
            ((!jvSource[jss::issuer].isString() ||
            !to_issuer(uSrcIssuerID, jvSource[jss::issuer].asString())) ||
            (uSrcIssuerID.isZero() != uSrcCurrencyID.isZero()) ||
            (noAccount() == uSrcIssuerID)))
        {
            WriteLog(lsINFO, RPCHandler) << "Bad issuer.";
            return std::make_pair(false, rpcError(rpcSRC_ISR_MALFORMED));
        }

        STPathSet spsComputed;
        if (contextPaths)
        {
            Json::Value pathSet = Json::objectValue;
            pathSet[jss::Paths] = contextPaths.get();
            STParsedJSONObject paths("pathSet", pathSet);
            if (! paths.object)
                return std::make_pair(false, paths.error);
            else
            {
                spsComputed = paths.object->getFieldPathSet(sfPaths);
                WriteLog(lsTRACE, RPCHandler) << "ripple_path_find: Paths: " <<
                    spsComputed.getJson(0);
            }
        }

        STPath fullLiquidityPath;
        auto valid = fp.findPathsForIssue(
            { uSrcCurrencyID, uSrcIssuerID },
            spsComputed,
            fullLiquidityPath);
        if (!valid)
        {
            WriteLog(lsWARNING, RPCHandler)
                << "ripple_path_find: No paths found.";
        }
        else
        {
            auto& issuer =
                isXRP(uSrcIssuerID) ?
                isXRP(uSrcCurrencyID) ? // Default to source account.
                xrpAccount() :
                (raSrc)
                : uSrcIssuerID;            // Use specifed issuer.

            STAmount saMaxAmount({ uSrcCurrencyID, issuer }, 1);
            saMaxAmount.negate();

            boost::optional<PaymentSandbox> sandbox;
            sandbox.emplace(&*cache->getLedger(), tapNONE);
            assert(sandbox->open());

            auto rc = path::RippleCalc::rippleCalculate(
                *sandbox,
                saMaxAmount,            // --> Amount to send is unlimited
                //     to get an estimate.
                saDstAmount,            // --> Amount to deliver.
                raDst,                  // --> Account to deliver to.
                raSrc,                  // --> Account sending from.
                spsComputed);           // --> Path set.

            WriteLog(lsWARNING, RPCHandler)
                << "ripple_path_find:"
                << " saMaxAmount=" << saMaxAmount
                << " saDstAmount=" << saDstAmount
                << " saMaxAmountAct=" << rc.actualAmountIn
                << " saDstAmountAct=" << rc.actualAmountOut;

            if (fullLiquidityPath.size() > 0 &&
                (rc.result() == terNO_LINE || rc.result() == tecPATH_PARTIAL))
            {
                WriteLog(lsDEBUG, PathRequest)
                    << "Trying with an extra path element";

                spsComputed.push_back(fullLiquidityPath);
                sandbox.emplace(&*cache->getLedger(), tapNONE);
                assert(sandbox->open());
                rc = path::RippleCalc::rippleCalculate(
                    *sandbox,
                    saMaxAmount,            // --> Amount to send is unlimited
                    //     to get an estimate.
                    saDstAmount,            // --> Amount to deliver.
                    raDst,                  // --> Account to deliver to.
                    raSrc,                  // --> Account sending from.
                    spsComputed);           // --> Path set.
                WriteLog(lsDEBUG, PathRequest)
                    << "Extra path element gives "
                    << transHuman(rc.result());
            }

            if (rc.result() == tesSUCCESS)
            {
                Json::Value jvEntry(Json::objectValue);

                STPathSet   spsCanonical;

                // Reuse the expanded as it would need to be calcuated
                // anyway to produce the canonical.  (At least unless we
                // make a direct canonical.)

                jvEntry[jss::source_amount] = rc.actualAmountIn.getJson(0);
                jvEntry[jss::paths_canonical] = Json::arrayValue;
                jvEntry[jss::paths_computed] = spsComputed.getJson(0);

                jvArray.append(jvEntry);
            }
            else
            {
                std::string strToken;
                std::string strHuman;

                transResultInfo(rc.result(), strToken, strHuman);

                WriteLog(lsDEBUG, RPCHandler)
                    << "ripple_path_find: "
                    << strToken << " "
                    << strHuman << " "
                    << spsComputed.getJson(0);
            }
        }
    }

    return std::make_pair(true, jvArray);
}
예제 #18
0
int PathRequest::parseJson (Json::Value const& jvParams)
{
    if (! jvParams.isMember(jss::source_account))
    {
        jvStatus = rpcError(rpcSRC_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (! jvParams.isMember(jss::destination_account))
    {
        jvStatus = rpcError(rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (! jvParams.isMember(jss::destination_amount))
    {
        jvStatus = rpcError(rpcDST_AMT_MISSING);
        return PFR_PJ_INVALID;
    }

    raSrcAccount = parseBase58<AccountID>(
        jvParams[jss::source_account].asString());
    if (! raSrcAccount)
    {
        jvStatus = rpcError (rpcSRC_ACT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    raDstAccount = parseBase58<AccountID>(
        jvParams[jss::destination_account].asString());
    if (! raDstAccount)
    {
        jvStatus = rpcError (rpcDST_ACT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    if (! amountFromJsonNoThrow (
        saDstAmount, jvParams[jss::destination_amount]))
    {
        jvStatus = rpcError (rpcDST_AMT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    convert_all_ = saDstAmount == STAmount(saDstAmount.issue(), 1u, 0, true);

    if ((saDstAmount.getCurrency ().isZero () &&
            saDstAmount.getIssuer ().isNonZero ()) ||
        (saDstAmount.getCurrency () == badCurrency ()) ||
        (! convert_all_ && saDstAmount <= zero))
    {
        jvStatus = rpcError (rpcDST_AMT_MALFORMED);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember(jss::send_max))
    {
        // Send_max requires destination amount to be -1.
        if (! convert_all_)
        {
            jvStatus = rpcError(rpcDST_AMT_MALFORMED);
            return PFR_PJ_INVALID;
        }

        saSendMax.emplace();
        if (! amountFromJsonNoThrow(
            *saSendMax, jvParams[jss::send_max]) ||
            (saSendMax->getCurrency().isZero() &&
                saSendMax->getIssuer().isNonZero()) ||
            (saSendMax->getCurrency() == badCurrency()) ||
            (*saSendMax <= zero &&
                *saSendMax != STAmount(saSendMax->issue(), 1u, 0, true)))
        {
            jvStatus = rpcError(rpcSENDMAX_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }

    if (jvParams.isMember (jss::source_currencies))
    {
        Json::Value const& jvSrcCurrencies = jvParams[jss::source_currencies];
        if (! jvSrcCurrencies.isArray() || jvSrcCurrencies.size() == 0 ||
            jvSrcCurrencies.size() > RPC::Tuning::max_src_cur)
        {
            jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
            return PFR_PJ_INVALID;
        }

        sciSourceCurrencies.clear ();

        for (auto const& c : jvSrcCurrencies)
        {
            // Mandatory currency
            Currency srcCurrencyID;
            if (! c.isObject() ||
                ! c.isMember(jss::currency) ||
                ! to_currency(srcCurrencyID, c[jss::currency].asString()))
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            // Optional issuer
            AccountID srcIssuerID;
            if (c.isMember (jss::issuer) &&
                (! c[jss::issuer].isString() ||
                    ! to_issuer(srcIssuerID, c[jss::issuer].asString())))
            {
                jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (srcCurrencyID.isZero())
            {
                if (srcIssuerID.isNonZero())
                {
                    jvStatus = rpcError(rpcSRC_CUR_MALFORMED);
                    return PFR_PJ_INVALID;
                }
            }
            else if (srcIssuerID.isZero())
            {
                srcIssuerID = *raSrcAccount;
            }

            if (saSendMax)
            {
                // If the currencies don't match, ignore the source currency.
                if (srcCurrencyID == saSendMax->getCurrency())
                {
                    // If neither is the source and they are not equal, then the
                    // source issuer is illegal.
                    if (srcIssuerID != *raSrcAccount &&
                        saSendMax->getIssuer() != *raSrcAccount &&
                            srcIssuerID != saSendMax->getIssuer())
                    {
                        jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
                        return PFR_PJ_INVALID;
                    }

                    // If both are the source, use the source.
                    // Otherwise, use the one that's not the source.
                    if (srcIssuerID != *raSrcAccount)
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, srcIssuerID});
                    }
                    else if (saSendMax->getIssuer() != *raSrcAccount)
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, saSendMax->getIssuer()});
                    }
                    else
                    {
                        sciSourceCurrencies.insert(
                            {srcCurrencyID, *raSrcAccount});
                    }
                }
            }
            else
            {
                sciSourceCurrencies.insert({srcCurrencyID, srcIssuerID});
            }
        }
    }

    if (jvParams.isMember ("id"))
        jvId = jvParams["id"];

    return PFR_PJ_NOCHANGE;
}
예제 #19
0
int PathRequest::parseJson (Json::Value const& jvParams, bool complete)
{
    int ret = PFR_PJ_NOCHANGE;

    if (jvParams.isMember (jss::source_account))
    {
        raSrcAccount = parseBase58<AccountID>(
            jvParams[jss::source_account].asString());
        if (! raSrcAccount)
        {
            jvStatus = rpcError (rpcSRC_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcSRC_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::destination_account))
    {
        raDstAccount = parseBase58<AccountID>(
            jvParams[jss::destination_account].asString());
        if (! raDstAccount)
        {
            jvStatus = rpcError (rpcDST_ACT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::destination_amount))
    {
        if (! amountFromJsonNoThrow (
                saDstAmount, jvParams[jss::destination_amount]) ||
            (saDstAmount.getCurrency ().isZero () &&
             saDstAmount.getIssuer ().isNonZero ()) ||
            (saDstAmount.getCurrency () == badCurrency ()) ||
            saDstAmount <= zero)
        {
            jvStatus = rpcError (rpcDST_AMT_MALFORMED);
            return PFR_PJ_INVALID;
        }
    }
    else if (complete)
    {
        jvStatus = rpcError (rpcDST_ACT_MISSING);
        return PFR_PJ_INVALID;
    }

    if (jvParams.isMember (jss::source_currencies))
    {
        Json::Value const& jvSrcCur = jvParams[jss::source_currencies];

        if (!jvSrcCur.isArray ())
        {
            jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
            return PFR_PJ_INVALID;
        }

        sciSourceCurrencies.clear ();

        for (unsigned i = 0; i < jvSrcCur.size (); ++i)
        {
            Json::Value const& jvCur = jvSrcCur[i];
            Currency uCur;
            AccountID uIss;

            if (!jvCur.isObject() || !jvCur.isMember (jss::currency) ||
                !to_currency (uCur, jvCur[jss::currency].asString ()))
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (jvCur.isMember (jss::issuer) &&
                !to_issuer (uIss, jvCur[jss::issuer].asString ()))
            {
                jvStatus = rpcError (rpcSRC_ISR_MALFORMED);
            }

            if (uCur.isZero () && uIss.isNonZero ())
            {
                jvStatus = rpcError (rpcSRC_CUR_MALFORMED);
                return PFR_PJ_INVALID;
            }

            if (uCur.isNonZero() && uIss.isZero())
            {
                uIss = *raSrcAccount;
            }

            sciSourceCurrencies.insert ({uCur, uIss});
        }
    }

    if (jvParams.isMember ("id"))
        jvId = jvParams["id"];

    return ret;
}