/* the jpg handler just responds with HTTP OK */ int jpg_handler(struct soap *soap) { char *buf; size_t len; soap_http_body(soap, &buf, &len); soap_response(soap, SOAP_OK); soap_end_send(soap); return SOAP_OK; }
/* the image handler responds with HTTP OK and a text/html body */ int image_handler(struct soap *soap) { char *buf; size_t len; soap_http_body(soap, &buf, &len); soap_response(soap, SOAP_HTML); soap_send(soap, "<html>Image received</html>"); soap_end_send(soap); return SOAP_OK; }
/* the text handler copies the message back */ int text_handler(struct soap *soap) { char *buf; size_t len; soap_http_body(soap, &buf, &len); /* use current soap->http_content from HTTP header as return HTTP type */ soap_response(soap, SOAP_FILE); soap_send_raw(soap, buf, len); soap_end_send(soap); return SOAP_OK; }
int main(int argc, char **argv) { char *buf; size_t len; struct soap soap; soap_init(&soap); /* chunking conserves memory and is generally faster: */ soap_set_omode(&soap, SOAP_IO_CHUNK); if (argc < 2) { /* CGI server */ struct http_post_handlers handlers[] = { { "image/jpg", jpg_handler }, { "image/*", image_handler }, { "image/*;*", image_handler }, { "text/*", text_handler }, { "text/*;*", text_handler }, { NULL } }; soap_register_plugin_arg(&soap, http_post, handlers); /* register plugin (server only) */ soap_serve(&soap); exit(0); } /* client */ if (soap_post_connect(&soap, argv[1], NULL, "text/html") || soap_send(&soap, "<html>") || soap_send(&soap, argc == 2 ? "Hello" : argv[2]) || soap_send(&soap, "</html>") || soap_end_send(&soap)) { soap_print_fault(&soap, stderr); exit(1); } /* after sending, receive body (note: POST handlers should not be set) */ if (soap_begin_recv(&soap) || soap_http_body(&soap, &buf, &len) || soap_end_recv(&soap)) { soap_print_fault(&soap, stderr); exit(1); } printf("Received %lu bytes of type %s:\n", (unsigned long)len, soap.http_content?soap.http_content:""); soap_end(&soap); soap_done(&soap); return 0; }
int32 LoginRESTService::HandlePost(soap* soapClient) { boost::asio::ip::address_v4 address(soapClient->ip); std::string ip_address = address.to_string(); TC_LOG_DEBUG("server.rest", "[%s:%d] Handling POST request path=\"%s\"", ip_address.c_str(), soapClient->port, soapClient->path); static std::string const expectedPath = "/bnetserver/login/"; if (strstr(soapClient->path, expectedPath.c_str()) != &soapClient->path[0]) return 404; char *buf; size_t len; soap_http_body(soapClient, &buf, &len); Battlenet::JSON::Login::LoginForm loginForm; Battlenet::JSON::Login::LoginResult loginResult; if (!JSON::Deserialize(buf, &loginForm)) { if (soap_register_plugin_arg(soapClient, &ResponseCodePlugin::Init, nullptr) != SOAP_OK) return 500; ResponseCodePlugin* responseCode = reinterpret_cast<ResponseCodePlugin*>(soap_lookup_plugin(soapClient, ResponseCodePlugin::PluginId)); ASSERT(responseCode); responseCode->ErrorCode = 400; loginResult.set_authentication_state(Battlenet::JSON::Login::LOGIN); loginResult.set_error_code("UNABLE_TO_DECODE"); loginResult.set_error_message("There was an internal error while connecting to Battle.net. Please try again later."); return SendResponse(soapClient, loginResult); } std::string login; std::string password; for (int32 i = 0; i < loginForm.inputs_size(); ++i) { if (loginForm.inputs(i).input_id() == "account_name") login = loginForm.inputs(i).value(); else if (loginForm.inputs(i).input_id() == "password") password = loginForm.inputs(i).value(); } Utf8ToUpperOnlyLatin(login); Utf8ToUpperOnlyLatin(password); PreparedStatement* stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_ACCOUNT_INFO); stmt->setString(0, login); if (PreparedQueryResult result = LoginDatabase.Query(stmt)) { std::string pass_hash = result->Fetch()[13].GetString(); std::unique_ptr<Battlenet::Session::AccountInfo> accountInfo = Trinity::make_unique<Battlenet::Session::AccountInfo>(); accountInfo->LoadResult(result); if (CalculateShaPassHash(login, std::move(password)) == pass_hash) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_CHARACTER_COUNTS_BY_BNET_ID); stmt->setUInt32(0, accountInfo->Id); if (PreparedQueryResult characterCountsResult = LoginDatabase.Query(stmt)) { do { Field* fields = characterCountsResult->Fetch(); accountInfo->GameAccounts[fields[0].GetUInt32()] .CharacterCounts[Battlenet::RealmHandle{ fields[3].GetUInt8(), fields[4].GetUInt8(), fields[2].GetUInt32() }.GetAddress()] = fields[1].GetUInt8(); } while (characterCountsResult->NextRow()); } stmt = LoginDatabase.GetPreparedStatement(LOGIN_SEL_BNET_LAST_PLAYER_CHARACTERS); stmt->setUInt32(0, accountInfo->Id); if (PreparedQueryResult lastPlayerCharactersResult = LoginDatabase.Query(stmt)) { Field* fields = lastPlayerCharactersResult->Fetch(); Battlenet::RealmHandle realmId{ fields[1].GetUInt8(), fields[2].GetUInt8(), fields[3].GetUInt32() }; Battlenet::Session::LastPlayedCharacterInfo& lastPlayedCharacter = accountInfo->GameAccounts[fields[0].GetUInt32()] .LastPlayedCharacters[realmId.GetSubRegionAddress()]; lastPlayedCharacter.RealmId = realmId; lastPlayedCharacter.CharacterName = fields[4].GetString(); lastPlayedCharacter.CharacterGUID = fields[5].GetUInt64(); lastPlayedCharacter.LastPlayedTime = fields[6].GetUInt32(); } BigNumber ticket; ticket.SetRand(20 * 8); loginResult.set_login_ticket("TC-" + ByteArrayToHexStr(ticket.AsByteArray(20).get(), 20)); AddLoginTicket(loginResult.login_ticket(), std::move(accountInfo)); } else if (!accountInfo->IsBanned) { uint32 maxWrongPassword = uint32(sConfigMgr->GetIntDefault("WrongPass.MaxCount", 0)); if (sConfigMgr->GetBoolDefault("WrongPass.Logging", false)) TC_LOG_DEBUG("server.rest", "[%s, Account %s, Id %u] Attempted to connect with wrong password!", ip_address.c_str(), login.c_str(), accountInfo->Id); if (maxWrongPassword) { SQLTransaction trans = LoginDatabase.BeginTransaction(); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_FAILED_LOGINS); stmt->setUInt32(0, accountInfo->Id); trans->Append(stmt); ++accountInfo->FailedLogins; TC_LOG_DEBUG("server.rest", "MaxWrongPass : %u, failed_login : %u", maxWrongPassword, accountInfo->Id); if (accountInfo->FailedLogins >= maxWrongPassword) { BanMode banType = BanMode(sConfigMgr->GetIntDefault("WrongPass.BanType", uint16(BanMode::BAN_IP))); int32 banTime = sConfigMgr->GetIntDefault("WrongPass.BanTime", 600); if (banType == BanMode::BAN_ACCOUNT) { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_BNET_ACCOUNT_AUTO_BANNED); stmt->setUInt32(0, accountInfo->Id); } else { stmt = LoginDatabase.GetPreparedStatement(LOGIN_INS_IP_AUTO_BANNED); stmt->setString(0, ip_address); } stmt->setUInt32(1, banTime); trans->Append(stmt); stmt = LoginDatabase.GetPreparedStatement(LOGIN_UPD_BNET_RESET_FAILED_LOGINS); stmt->setUInt32(0, accountInfo->Id); trans->Append(stmt); } LoginDatabase.CommitTransaction(trans); } } } loginResult.set_authentication_state(Battlenet::JSON::Login::DONE); return SendResponse(soapClient, loginResult); }