当前位置: 首页>>代码示例>>C++>>正文


C++ NetworkMessage::SkipBytes方法代码示例

本文整理汇总了C++中NetworkMessage::SkipBytes方法的典型用法代码示例。如果您正苦于以下问题:C++ NetworkMessage::SkipBytes方法的具体用法?C++ NetworkMessage::SkipBytes怎么用?C++ NetworkMessage::SkipBytes使用的例子?那么, 这里精选的方法代码示例或许可以为您提供帮助。您也可以进一步了解该方法所在NetworkMessage的用法示例。


在下文中一共展示了NetworkMessage::SkipBytes方法的8个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的C++代码示例。

示例1: parseFirstPacket

bool ProtocolOld::parseFirstPacket(NetworkMessage& msg)
{
	if(g_game.getGameState() == GAME_STATE_SHUTDOWN)
	{
		getConnection()->closeConnection();
		return false;
	}

	/*uint16_t clientOS =*/ msg.GetU16();
	uint16_t version = msg.GetU16();
	msg.SkipBytes(12);

	if(version <= 760)
		disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");

	if(!RSA_decrypt(msg))
	{
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.GetU32();
	key[1] = msg.GetU32();
	key[2] = msg.GetU32();
	key[3] = msg.GetU32();
	enableXTEAEncryption();
	setXTEAKey(key);

	if(version <= 822)
		disableChecksum();

	disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
	return false;
}
开发者ID:CkyLua,项目名称:tfs,代码行数:35,代码来源:protocolold.cpp

示例2: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{
	if(
#ifndef _CONSOLE
		!GUI::getInstance()->m_connections ||
#endif
		g_game.getGameState() == GAME_STATE_SHUTDOWN)
	{
		getConnection()->closeConnection();
		return false;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos = */msg.GetU16();
	uint16_t version = msg.GetU16();
	msg.SkipBytes(12);

	if(version <= 760)
	{
		disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return false;
	}

	if(!RSA_decrypt(msg))
	{
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.GetU32();
	key[1] = msg.GetU32();
	key[2] = msg.GetU32();
	key[3] = msg.GetU32();
	enableXTEAEncryption();
	setXTEAKey(key);

	std::string accountName = msg.GetString();
	std::string password = msg.GetString();

	if(accountName.empty())
	{
		if(g_config.getBoolean(ConfigManager::ACCOUNT_MANAGER))
		{
			accountName = "1";
			password = "1";
		}
		else
		{
			disconnectClient(0x0A, "Invalid Account Name.");
			return false;
		}
	}

	if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX)
	{
		disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return false;
	}

	if(g_game.getGameState() == GAME_STATE_STARTUP)
	{
		disconnectClient(0x0A, "Gameworld is starting up. Please wait.");
		return false;
	}

	if(g_game.getGameState() == GAME_STATE_MAINTAIN)
	{
		disconnectClient(0x0A, "Gameworld is under maintenance. Please re-connect in a while.");
		return false;
	}

	if(g_bans.isIpDisabled(clientip))
	{
		disconnectClient(0x0A, "Too many connections attempts from this IP. Try again later.");
		return false;
	}

	if(IOBan::getInstance()->isIpBanished(clientip))
	{
		disconnectClient(0x0A, "Your IP is banished!");
		return false;
	}

	uint32_t serverip = serverIPs[0].first;
	for(uint32_t i = 0; i < serverIPs.size(); i++)
	{
		if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second))
		{
			serverip = serverIPs[i].first;
			break;
		}
	}

	Account account = IOLoginData::getInstance()->loadAccount(accountName);
	if(account.id == 0 || !passwordTest(password, account.password))
	{
		g_bans.addLoginAttempt(clientip, false);
		disconnectClient(0x0A, "Account name or password is not correct.");
//.........这里部分代码省略.........
开发者ID:armadaazteca,项目名称:tfs0.2.15,代码行数:101,代码来源:protocollogin.cpp

示例3: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{
	if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
		getConnection()->closeConnection();
		return false;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos = */
	msg.get<uint16_t>();
	uint16_t version = msg.get<uint16_t>();

	if (version >= 971) {
		msg.SkipBytes(17);
	}
	else {
		msg.SkipBytes(12);
	}

	/*
	* Skipped bytes:
	* 4 bytes: protocolVersion (only 971+)
	* 12 bytes: dat, spr, pic signatures (4 bytes each)
	* 1 byte: 0 (only 971+)
	*/

	if (version <= 760) {
		disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return false;
	}
	
	if (!RSA_decrypt(msg)) {
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.get<uint32_t>();
	key[1] = msg.get<uint32_t>();
	key[2] = msg.get<uint32_t>();
	key[3] = msg.get<uint32_t>();
	enableXTEAEncryption();
	setXTEAKey(key);

	std::string accountName = msg.GetString();
	std::string password = msg.GetString();

	if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
		if (version >= 1076)
			disconnectClient(0x0B, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		else
			disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return false;
	}

	if (g_game.getGameState() == GAME_STATE_STARTUP) {
		disconnectClient(0x0B, "Gameworld is starting up. Please wait.");
		return false;
	}

	if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
		disconnectClient(0x0B, "Gameworld is under maintenance. Please re-connect in a while.");
		return false;
	}

	BanInfo banInfo;
	if (IOBan::isIpBanned(clientip, banInfo)) {
		if (banInfo.reason.empty()) {
			banInfo.reason = "(none)";
		}

		std::ostringstream ss;
		ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
		disconnectClient(0x0B, ss.str().c_str());
		return false;
	}
	//IF THE PASSWORD FIELDS AND ACCOUNT FIELD ARE EMPTY THEN THE USER WAN'T TO USE CAST SYSTEM
	bool cast_login = false;
	if ((accountName.empty() && password.empty()) || (accountName.empty() && !password.empty()))
	{
		cast_login = true;
	}
	if (!cast_login && accountName.empty()) {
		disconnectClient(0x0B, "Invalid account name.");
		return false;
	}

	Account account;
	if (!cast_login && !IOLoginData::loginserverAuthentication(accountName, password, account)) {
		disconnectClient(0x0B, "Account name or password is not correct.");
		return false;
	}

	OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if (output) {
		//Update premium days
		g_game.updatePremium(account);

		//Add MOTD
//.........这里部分代码省略.........
开发者ID:osiann,项目名称:Source-10.76-TFS-1.0,代码行数:101,代码来源:protocollogin.cpp

示例4: onRecvFirstMessage

void ProtocolLogin::onRecvFirstMessage(NetworkMessage& msg)
{
	if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
		getConnection()->closeConnection();
		return;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos = */
	msg.get<uint16_t>();
	uint16_t version = msg.get<uint16_t>();

	if (version >= 971) {
		msg.SkipBytes(17);
	} else {
		msg.SkipBytes(12);
	}

	/*
	 * Skipped bytes:
	 * 4 bytes: protocolVersion (only 971+)
	 * 12 bytes: dat, spr, pic signatures (4 bytes each)
	 * 1 byte: 0 (only 971+)
	 */

#define dispatchDisconnectClient(err) g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::disconnectClient, this, err)))

	if (version <= 760) {
		dispatchDisconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return;
	}

	if (!RSA_decrypt(msg)) {
		getConnection()->closeConnection();
		return;
	}

	uint32_t key[4];
	key[0] = msg.get<uint32_t>();
	key[1] = msg.get<uint32_t>();
	key[2] = msg.get<uint32_t>();
	key[3] = msg.get<uint32_t>();
	enableXTEAEncryption();
	setXTEAKey(key);

	std::string accountName = msg.GetString();
	std::string password = msg.GetString();

	if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
		dispatchDisconnectClient("Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return;
	}

	if (g_game.getGameState() == GAME_STATE_STARTUP) {
		dispatchDisconnectClient("Gameworld is starting up. Please wait.");
		return;
	}

	if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
		dispatchDisconnectClient("Gameworld is under maintenance. Please re-connect in a while.");
		return;
	}

	BanInfo banInfo;
	if (IOBan::isIpBanned(clientip, banInfo)) {
		if (banInfo.reason.empty()) {
			banInfo.reason = "(none)";
		}

		std::ostringstream ss;
		ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
		dispatchDisconnectClient(ss.str());
		return;
	}

	if (accountName.empty()) {
		dispatchDisconnectClient("Invalid account name.");
		return;
	}

#undef dispatchDisconnectClient

	g_dispatcher.addTask(createTask(std::bind(&ProtocolLogin::getCharacterList, this, accountName, password)));
}
开发者ID:Ablankzin,项目名称:forgottenserver,代码行数:85,代码来源:protocollogin.cpp

示例5: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{	
	if(g_game.getGameState() == GAME_STATE_SHUTDOWN){
		getConnection()->closeConnection();
		return false;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos =*/ msg.GetU16();
	uint16_t version  = msg.GetU16();
	msg.SkipBytes(12);
	
	if(version <= 760){
		disconnectClient(0x0A, STRING_CLIENT_VERSION);
	}

	if(!RSA_decrypt(g_otservRSA, msg)){
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.GetU32();
	key[1] = msg.GetU32();
	key[2] = msg.GetU32();
	key[3] = msg.GetU32();
	enableXTEAEncryption();
	setXTEAKey(key);

	uint32_t accnumber = msg.GetU32();
	std::string password = msg.GetString();

	if(!accnumber){
		disconnectClient(0x0A, "You must enter your account number.");
		return false;
	}

	if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX){
		disconnectClient(0x0A, STRING_CLIENT_VERSION);
		return false;
	}

	if(g_game.getGameState() == GAME_STATE_STARTUP){
		disconnectClient(0x0A, "Gameworld is starting up. Please wait.");
		return false;
	}

	if(g_bans.isIpDisabled(clientip)){
		disconnectClient(0x0A, "Too many connections attempts from this IP. Try again later.");
		return false;
	}
	
	if(g_bans.isIpBanished(clientip)){
		disconnectClient(0x0A, "Your IP is banished!");
		return false;
	}

	uint32_t serverip = serverIPs[0].first;
	for(uint32_t i = 0; i < serverIPs.size(); i++){
		if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)){
			serverip = serverIPs[i].first;
			break;
		}
	}
	
	Account account = IOAccount::instance()->loadAccount(accnumber);
	if(!(accnumber != 0 && account.accnumber == accnumber &&
			passwordTest(password, account.password))){

		g_bans.addLoginAttempt(clientip, false);
		disconnectClient(0x0A, "Please enter a valid account number and password.");
		return false;
	}

	g_bans.addLoginAttempt(clientip, true);
		
	
	OutputMessage* output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	//Add MOTD
	std::stringstream motd;
	output->AddByte(0x14);
	motd << g_config.getNumber(ConfigManager::MOTD_NUM) << "\n";
	motd << g_config.getString(ConfigManager::MOTD);
	output->AddString(motd.str());
	//Add char list
	output->AddByte(0x64);
	output->AddByte((uint8_t)account.charList.size());
	std::list<std::string>::iterator it;
	for(it = account.charList.begin(); it != account.charList.end(); it++){
		output->AddString((*it));
		output->AddString(g_config.getString(ConfigManager::WORLD_NAME));
		output->AddU32(serverip);
		output->AddU16(g_config.getNumber(ConfigManager::PORT));
	}
	//Add premium days
	output->AddU16(account.premiumDays);//output->AddU16(0);
	
	OutputMessagePool::getInstance()->send(output);
	getConnection()->closeConnection();
//.........这里部分代码省略.........
开发者ID:cp1337,项目名称:devland,代码行数:101,代码来源:protocollogin.cpp

示例6: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{
	if(g_game.getGameState() == GAME_STATE_SHUTDOWN){
		getConnection()->closeConnection();
		return false;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos =*/ msg.GetU16();
	uint16_t version  = msg.GetU16();
	msg.SkipBytes(12);

	if(version <= 760){
		disconnectClient(0x0A, "This server requires client version " CLIENT_VERSION_STRING ".");
	}

	if(!RSA_decrypt(msg)){
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.GetU32();
	key[1] = msg.GetU32();
	key[2] = msg.GetU32();
	key[3] = msg.GetU32();
	enableXTEAEncryption();
	setXTEAKey(key);

	std::string accname = msg.GetString();
	std::string password = msg.GetString();

	if(!accname.length()){
		//Tibia sends this message if the account name length is < 5
		//We will send it only if account name is BLANK
		disconnectClient(0x0A, "Invalid Account Name.");
		return false;
	}

	if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX){
		disconnectClient(0x0A, "This server requires client version " CLIENT_VERSION_STRING ".");
		return false;
	}

	if(g_game.getGameState() == GAME_STATE_STARTUP){
		disconnectClient(0x0A, "Gameworld is starting up. Please wait.");
		return false;
	}

	if(g_bans.isIpDisabled(clientip)){
		disconnectClient(0x0A, "Too many connections attempts from this IP. Try again later.");
		return false;
	}

	if(g_bans.isIpBanished(clientip)){
		disconnectClient(0x0A, "Your IP is banished!");
		return false;
	}
	/*
	uint32_t serverip = serverIPs[0].first;
	for(uint32_t i = 0; i < serverIPs.size(); i++){
		if((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)){
			serverip = serverIPs[i].first;
			break;
		}
	}
	*/

	Account account = IOAccount::instance()->loadAccount(accname);
	if(!(asLowerCaseString(account.name) == asLowerCaseString(accname) &&
			passwordTest(password, account.password))){

		g_bans.addLoginAttempt(clientip, false);
		disconnectClient(0x0A, "Account name or password is not correct.");
		return false;
	}

	g_bans.addLoginAttempt(clientip, true);


	OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if(output){
		TRACK_MESSAGE(output);
		//Add MOTD
		std::stringstream motd;
		output->AddByte(0x14);
		motd << g_config.getNumber(ConfigManager::MOTD_NUM) << "\n";
		motd << g_config.getString(ConfigManager::MOTD);
		output->AddString(motd.str());
		//Add char list
		output->AddByte(0x64);
		output->AddByte((uint8_t)account.charList.size());
		std::list<AccountCharacter>::iterator it;
		for(it = account.charList.begin(); it != account.charList.end(); it++){
			const AccountCharacter& character = *it;
			output->AddString(character.name);
			output->AddString(character.world_name);
			output->AddU32(character.ip);
			output->AddU16(character.port);
//.........这里部分代码省略.........
开发者ID:HeavenIsLost,项目名称:server,代码行数:101,代码来源:protocollogin.cpp

示例7: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{
	if (g_game.getGameState() == GAME_STATE_SHUTDOWN) {
		getConnection()->closeConnection();
		return false;
	}

	uint32_t clientip = getConnection()->getIP();

	/*uint16_t clientos = */
	msg.GetU16();
	uint16_t version = msg.GetU16();
	msg.SkipBytes(12);

	/*
	 * Skipped bytes:
	 * 12 bytes: dat, spr, pic signatures (4 bytes each)
	*/

	#ifdef __PROTOCOL_77__
	if (!RSA_decrypt(msg)) {
		getConnection()->closeConnection();
		return false;
	}

	uint32_t key[4];
	key[0] = msg.GetU32();
	key[1] = msg.GetU32();
	key[2] = msg.GetU32();
	key[3] = msg.GetU32();
	enableXTEAEncryption();
	setXTEAKey(key);
	#endif

	uint32_t accountName = msg.GetU32();
	std::string password = msg.GetString();

	if (version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX) {
		disconnectClient(0x0A, "Only clients with protocol " CLIENT_VERSION_STR " allowed!");
		return false;
	}

	if (g_game.getGameState() == GAME_STATE_STARTUP) {
		disconnectClient(0x0A, "Gameworld is starting up. Please wait.");
		return false;
	}

	if (g_game.getGameState() == GAME_STATE_MAINTAIN) {
		disconnectClient(0x0A, "Gameworld is under maintenance. Please re-connect in a while.");
		return false;
	}

	BanInfo banInfo;
	if (IOBan::getInstance()->isIpBanned(clientip, banInfo)) {
		if (banInfo.reason.empty()) {
			banInfo.reason = "(none)";
		}

		std::ostringstream ss;
		ss << "Your IP has been banned until " << formatDateShort(banInfo.expiresAt) << " by " << banInfo.bannedBy << ".\n\nReason specified:\n" << banInfo.reason;
		disconnectClient(0x0A, ss.str().c_str());
		return false;
	}

	uint32_t serverip = serverIPs[0].first;
	for (uint32_t i = 0; i < serverIPs.size(); i++) {
		if ((serverIPs[i].first & serverIPs[i].second) == (clientip & serverIPs[i].second)) {
			serverip = serverIPs[i].first;
			break;
		}
	}

	if (!accountName) {
		disconnectClient(0x0A, "Invalid account id.");
		return false;
	}

	Account account;
	if (!IOLoginData::getInstance()->loginserverAuthentication(accountName, password, account)) {
		disconnectClient(0x0A, "Account id or password is not correct.");
		return false;
	}

	OutputMessage_ptr output = OutputMessagePool::getInstance()->getOutputMessage(this, false);
	if (output) {
		//Update premium days
		g_game.updatePremium(account);

		//Add MOTD
		output->AddByte(0x14);

		std::ostringstream ss;
		ss << g_game.getMotdNum() << "\n" << g_config.getString(ConfigManager::MOTD);
		output->AddString(ss.str());

		//Add char list
		output->AddByte(0x64);
		output->AddByte((uint8_t)account.charList.size());

		for (const std::string& characterName : account.charList) {
//.........这里部分代码省略.........
开发者ID:CkyLua,项目名称:forgottenserver-1,代码行数:101,代码来源:protocollogin.cpp

示例8: parseFirstPacket

bool ProtocolLogin::parseFirstPacket(NetworkMessage& msg)
{
	if(server.game().getGameState() == GAME_STATE_SHUTDOWN)
	{
		getConnection()->close();
		return false;
	}

	uint32_t clientIp = getConnection()->getIP();
	/*uint16_t operatingSystem = msg.GetU16();*/msg.SkipBytes(2);
	uint16_t version = msg.GetU16();

	msg.SkipBytes(12);
	if(!RSA_decrypt(msg))
	{
		getConnection()->close();
		return false;
	}

	uint32_t key[4] = {msg.GetU32(), msg.GetU32(), msg.GetU32(), msg.GetU32()};
	enableXTEAEncryption();
	setXTEAKey(key);

	std::string name = msg.GetString(), password = msg.GetString();
	if(name.empty())
	{
		if(!server.configManager().getBool(ConfigManager::ACCOUNT_MANAGER))
		{
			disconnectClient(0x0A, "Invalid account name.");
			return false;
		}

		name = "1";
		password = "1";
	}

	if(version < CLIENT_VERSION_MIN || version > CLIENT_VERSION_MAX)
	{
		disconnectClient(0x0A, CLIENT_VERSION_STRING);
		return false;
	}

	if(server.game().getGameState() < GAME_STATE_NORMAL)
	{
		disconnectClient(0x0A, "Server is just starting up, please wait.");
		return false;
	}

	if(server.game().getGameState() == GAME_STATE_MAINTAIN)
	{
		disconnectClient(0x0A, "Server is under maintenance, please re-connect in a while.");
		return false;
	}

	if(ConnectionManager::getInstance()->isDisabled(clientIp, protocolId))
	{
		disconnectClient(0x0A, "Too many connections attempts from your IP address, please try again later.");
		return false;
	}

	if(IOBan::getInstance()->isIpBanished(clientIp))
	{
		disconnectClient(0x0A, "Your IP is banished!");
		return false;
	}

	uint32_t id = 1;
	if(!IOLoginData::getInstance()->getAccountId(name, id))
	{
		ConnectionManager::getInstance()->addAttempt(clientIp, protocolId, false);
		disconnectClient(0x0A, "Invalid account name.");
		return false;
	}

	AccountP account = IOLoginData::getInstance()->loadAccount(id);
	if (account == nullptr) {
		disconnectClient(0x0A, "Invalid account name.");
		return false;
	}

	if(!encryptTest(password, account->getPassword()))
	{
		ConnectionManager::getInstance()->addAttempt(clientIp, protocolId, false);
		disconnectClient(0x0A, "Invalid password.");
		return false;
	}

	Ban ban;
	ban.value = account->getId();

	ban.type = BAN_ACCOUNT;
	if(IOBan::getInstance()->getData(ban) && !IOLoginData::getInstance()->hasFlag(account->getId(), PlayerFlag_CannotBeBanned))
	{
		bool deletion = ban.expires < 0;
		std::string name_ = "Automatic ";
		if(!ban.adminId)
			name_ += (deletion ? "deletion" : "banishment");
		else
			IOLoginData::getInstance()->getNameByGuid(ban.adminId, name_, true);

//.........这里部分代码省略.........
开发者ID:novasdream,项目名称:tyano-core,代码行数:101,代码来源:protocollogin.cpp


注:本文中的NetworkMessage::SkipBytes方法示例由纯净天空整理自Github/MSDocs等开源代码及文档管理平台,相关代码片段筛选自各路编程大神贡献的开源项目,源码版权归原作者所有,传播和使用请参考对应项目的License;未经允许,请勿转载。