📄 isession.cpp
字号:
/************************************************************************************
Copyright (c) 2000 Aaron O'Neil
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1) Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2) Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3) Redistributions in binary form must reproduce the above copyright notice on
program startup. Additional credits for program modification are acceptable
but original copyright and credits must be visible at startup.
4) You may charge a reasonable copying fee for any distribution of Mud Master.
You may charge any fee you choose for support of Mud Master. You may not
charge a fee for Mud Master itself.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
**************************************************************************************/
#include "StdAfx.h"
#include "Extern.h"
#include "ISession.h"
#include "MudWindow.h"
CISession::CISession() : CInternetSession("MM",1,INTERNET_OPEN_TYPE_PRECONFIG,NULL,NULL,
INTERNET_FLAG_ASYNC)
{
m_dwStatus = 0;
m_dwError = ERROR_SUCCESS;
m_pHttpFile = NULL;
m_pHttpServer = NULL;
m_nRetries = 0;
}
CISession::~CISession()
{
Stop();
}
void CISession::Stop()
{
try
{
if (m_pHttpFile)
{
m_pHttpFile->Close();
delete m_pHttpFile;
m_pHttpFile = NULL;
}
}
catch(CInternetException *pEx)
{
pEx->Delete();
PrintMessage("Exception closing m_pHttpFile.");
return;
}
try
{
if (m_pHttpServer)
{
m_pHttpServer->Close();
delete m_pHttpServer;
m_pHttpServer = NULL;
}
}
catch(CInternetException *pEx)
{
pEx->Delete();
PrintMessage("Exception closing m_pHttpServer.");
return;
}
}
BOOL CISession::DoIt()
{
try
{
if (!EnableStatusCallback())
return(FALSE);
if (!AfxParseURL("http://www.mud-master.com/Version.txt",
m_dwServiceType, m_strServerName, m_strObject, m_nPort))
return(FALSE);
m_pHttpServer = GetHttpConnection(m_strServerName,m_nPort);
if (!m_pHttpServer)
return(FALSE);
m_pHttpFile = m_pHttpServer->OpenRequest(CHttpConnection::HTTP_VERB_GET,
m_strObject,NULL,1,NULL,NULL,
INTERNET_FLAG_EXISTING_CONNECT|INTERNET_FLAG_NO_AUTO_REDIRECT);
if (!m_pHttpFile)
return(FALSE);
if (!m_pHttpFile->AddRequestHeaders("Accept: text/*\r\n"))
return(FALSE);
m_pHttpFile->SetReadBufferSize(30000);
}
catch(CInternetException *pEx)
{
pEx->Delete();
PrintMessage("Exception starting version checking.");
Stop();
return(FALSE);
}
// This ALWAYS fails. If it fails with error code 0x3e5 it seems to
// still work if I ignore it. I forget what that error was, IO already
// in progress, or something like that. All the examples I can find on
// using WinInet use synchronous mode, so I'm just guessing how it's
// supposed to work.
try
{
m_pHttpFile->SendRequest();
}
catch(CInternetException *pEx)
{
if (pEx->m_dwError != 0x3e5)
{
pEx->Delete();
PrintMessage("Exception sending document request.");
return(FALSE);
}
pEx->Delete();
}
return(TRUE);
}
void CISession::OnStatusCallback(DWORD dwContext, DWORD dwInternetStatus,
LPVOID lpvStatusInformation, DWORD dwStatusInformationLength)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState());
m_dwStatus = dwInternetStatus;
CString strTemp;
switch(dwInternetStatus)
{
case INTERNET_STATUS_RESOLVING_NAME :
strTemp = "Resolving Name";
break;
case INTERNET_STATUS_NAME_RESOLVED :
strTemp = "Name Resolved";
break;
case INTERNET_STATUS_CONNECTING_TO_SERVER :
strTemp = "Connecting to Server";
break;
case INTERNET_STATUS_CONNECTED_TO_SERVER :
strTemp = "Connected to Server";
break;
case INTERNET_STATUS_SENDING_REQUEST :
strTemp = "Sending Request";
break;
case INTERNET_STATUS_REQUEST_SENT :
strTemp = "Request Sent";
break;
case INTERNET_STATUS_RECEIVING_RESPONSE :
strTemp = "Receiving Response";
break;
case INTERNET_STATUS_RESPONSE_RECEIVED :
strTemp = "Response Received";
break;
case INTERNET_STATUS_CLOSING_CONNECTION :
strTemp = "Closing Connection";
break;
case INTERNET_STATUS_CONNECTION_CLOSED :
strTemp = "Connection Closed";
break;
case INTERNET_STATUS_HANDLE_CREATED :
strTemp = "Handle Created";
break;
case INTERNET_STATUS_HANDLE_CLOSING :
strTemp = "Handle Closing";
break;
case INTERNET_STATUS_REQUEST_COMPLETE :
if (_config.bDisplayVersionStuff)
{
strTemp.Format("Request Complete, Final Status: %d%s, Pointer: %x",
dwStatusInformationLength,
(dwStatusInformationLength==ERROR_INTERNET_EXTENDED_ERROR ? "(extended error)" : ""),
lpvStatusInformation);
PrintMessage(strTemp);
}
if (lpvStatusInformation)
{
INTERNET_ASYNC_RESULT *pResult = (INTERNET_ASYNC_RESULT *)lpvStatusInformation;
if (_config.bDisplayVersionStuff)
{
strTemp.Format("Async Result, dwResult: %d, dwError: %d",
pResult->dwResult,pResult->dwError);
PrintMessage(strTemp);
}
m_dwError = pResult->dwError;
if (m_dwError == ERROR_SUCCESS)
{
if (_config.bDisplayVersionStuff)
PrintMessage("Successful.");
}
else
{
PrintMessage("Failed, cannot fetch version.");
Stop();
return;
}
}
if (m_pHttpFile)
{
try
{
DWORD dwStatus;
if (m_pHttpFile->QueryInfoStatusCode(dwStatus))
{
if (_config.bDisplayVersionStuff)
{
strTemp.Format("Http status code: %d",dwStatus);
PrintMessage(strTemp);
}
if (dwStatus < 200 || dwStatus > 299)
{
if (_config.bDisplayVersionStuff)
PrintMessage("Bad http status code, cannot fetch version.");
Stop();
return;
}
// From experimenting it seems to work like this. The CHttpFile object
// doesn't have a way to tell if you have all the data yet or not in
// async mode. If you try to read from it, it will throw an exception.
// You get that same IO error that I trapped above. If I just delete
// the exception and return, I'll get another INTERNET_STATUS_REQUEST_COMPLETE
// and can try to do it again. Eventually, the whole file is here and
// the reads stop throwing exceptions.
if (m_nRetries > 29)
{
Stop();
return;
}
try
{
ProcessVersionFile();
}
catch(CInternetException *pEx)
{
m_nRetries++;
pEx->Delete();
return;
}
Stop();
}
}
catch(CInternetException *pEx)
{
pEx->Delete();
PrintMessage("Exception in m_pHttpFile->QueryInfoStatusCode(dwStatus).");
Stop();
return;
}
}
return;
default :
strTemp.Format("%d",dwInternetStatus);
break;
}
if (_config.bDisplayVersionStuff)
PrintMessage(strTemp);
}
void CISession::SplitVersion(CString &strData, CString &strVersion, UINT &nWeight)
{
int nIndex;
nIndex = strData.Find(',');
if (nIndex == -1)
{
strVersion = strData;
nWeight = 0;
return;
}
strVersion = strData.Left(nIndex);
nWeight = atoi(strData.Right(strData.GetLength()-nIndex-1));
}
UINT CISession::WeightVersion(int nVerMajor, int nVerMinor, int nVerBuild, int nVerBeta)
{
UINT nResult;
nResult = nVerBeta;
nResult += nVerBuild * 100;
nResult += nVerMinor * 10000;
nResult += nVerMajor * 1000000;
return(nResult);
}
// Lines in this file have a key, followed by a colon, followed by the data.
// V:1 Version of this file.
// r:URL Address of release version. These need to be before the R and B.
// b:URL Address of beta version.
// R:2.6.0 Most current released version.
// B:2.6.0 (Beta 30) Most current beta version.
// M:text Message to users. Each line must have a M: in front of it. The whole
// message is concatenated. All M: appear as the same message.
// * is used as an end of file marker. Anything after the * is ignored.
void CISession::ProcessVersionFile()
{
CString strSep;
CString strBetaAddress;
CString strReleaseAddress;
CString strVersion;
CString strLine;
CString strData;
CString strMessage;
UINT nVersion;
UINT nCurVersion;
if (!m_pHttpFile)
return;
nCurVersion = WeightVersion(_config.nVersionMajor,_config.nVersionMinor,
_config.nVersionBuild,_config.nVersionBeta);
strSep = "\n======================================================================\n";
while(m_pHttpFile->ReadString(strLine))
{
if (strLine.IsEmpty())
continue;
if (strLine == '*')
break;
if (strLine.GetLength() < 3 || strLine.GetAt(1) != ':')
continue;
strData = strLine.Right(strLine.GetLength()-2);
switch(strLine.GetAt(0))
{
case 'V' : // Not doing anything with this yet.
break;
case 'r' : // Address of release version.
strReleaseAddress = strData;
break;
case 'b' : // Address of beta version.
strBetaAddress = strData;
break;
case 'R' :
SplitVersion(strData,strVersion,nVersion);
if (nVersion > nCurVersion)
{
CommandPrintOn();
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
_terminal.SetColor(F_LIGHTCYAN);
_terminal.Print("There is a new Release version available for download - ");
_terminal.Print(strVersion);
_terminal.Print("\n\nYou can download it at:\n");
_terminal.Print(strReleaseAddress);
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
CommandPrintOff();
}
break;
case 'B' :
SplitVersion(strData,strVersion,nVersion);
if (nVersion > nCurVersion)
{
CommandPrintOn();
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
_terminal.SetColor(F_LIGHTCYAN);
_terminal.Print("There is a new Beta version available for download - ");
_terminal.Print(strVersion);
_terminal.Print("\n\nYou can download it at:\n");
_terminal.Print(strBetaAddress);
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
CommandPrintOff();
}
else
if (nVersion < nCurVersion)
{
CommandPrintOn();
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
_terminal.SetColor(F_LIGHTCYAN);
_terminal.Print("Congratulations! Your version is newer than the one available for download!");
_terminal.SetColor(F_WHITE);
_terminal.Print(strSep);
CommandPrintOff();
}
break;
case 'M' :
if (!strMessage.IsEmpty())
strMessage += "\n";
strMessage += strData;
break;
}
}
if (!strMessage.IsEmpty())
{
CommandPrintOn();
_terminal.SetColor(F_WHITE);
_terminal.Print("\n=== Mud Master Message ===\n");
_terminal.SetColor(F_LIGHTCYAN);
_terminal.Print(strMessage);
_terminal.SetColor(F_WHITE);
_terminal.Print("\n==========================\n");
CommandPrintOff();
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -