📄 mfccddb.cpp
字号:
bContinue = FALSE;
//Parse each line
CString sField;
CString sValue;
if (strcmp(pszCurLine, "Database entries by category:") == 0)
{
//Skip over the heading line
pszCurLine = pszNextLine;
//Handle the database entries
BOOL bMoreEntries = (pszCurLine != NULL);
while (bMoreEntries)
{
//Get the next line before we parse the current one
pszNextLine = GetNextLine(pszCurLine);
if (pszNextLine == NULL)
bMoreEntries = FALSE;
//Parse the category info
if (pszCurLine[0] = ' ')
{
if (SplitSemiColonLine(pszCurLine, sField, sValue))
{
status.m_Categories.Add(sField);
int nValue = _ttoi(sValue);
status.m_CategoryEntries.Add(nValue);
}
}
else
bMoreEntries = FALSE;
pszCurLine = pszNextLine;
}
}
else if (strcmp(pszCurLine, "Pending File transmissions:") == 0)
{
//Skip over the heading line
pszCurLine = pszNextLine;
//Handle the database entries
BOOL bMoreSites = (pszCurLine != NULL);
while (bMoreSites)
{
//Get the next line before we parse the current one
pszNextLine = GetNextLine(pszCurLine);
if (pszNextLine == NULL)
bMoreSites = FALSE;
//Parse the pending sites info
if (pszCurLine[0] = ' ')
{
if (SplitSemiColonLine(pszCurLine, sField, sValue))
{
status.m_PendingSites.Add(sField);
int nValue = _ttoi(sValue);
status.m_PendingEntries.Add(nValue);
}
}
else
bMoreSites = FALSE;
pszCurLine = pszNextLine;
}
}
//Parse out the other types of field
if (pszCurLine)
{
if (SplitSemiColonLine(pszCurLine, sField, sValue))
{
if (sField == _T("current proto"))
status.m_nCurrentProtocol = _ttoi(sValue);
else if (sField == _T("max proto"))
status.m_nMaxProtocol = _ttoi(sValue);
else if (sField == _T("gets"))
{
if (sValue == _T("yes"))
status.m_bGetsAllowed = TRUE;
else if (sValue == _T("no"))
status.m_bGetsAllowed = FALSE;
else
{
bContinue = FALSE;
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid gets response to the stat command\n"));
}
}
else if (sField == _T("updates"))
{
if (sValue == _T("yes"))
status.m_bUpdatesAllowed = TRUE;
else if (sValue == _T("no"))
status.m_bUpdatesAllowed = FALSE;
else
{
bContinue = FALSE;
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid updates response to the stat command\n"));
}
}
else if (sField == _T("posting"))
{
if (sValue == _T("yes"))
status.m_bPostingAllowed = TRUE;
else if (sValue == _T("no"))
status.m_bPostingAllowed = FALSE;
else
{
bContinue = FALSE;
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid posting response to the stat command\n"));
}
}
else if (sField == _T("quotes"))
{
if (sValue == _T("yes"))
status.m_bQuotes = TRUE;
else if (sValue == _T("no"))
status.m_bQuotes = FALSE;
else
{
bContinue = FALSE;
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid quotes response to the stat command\n"));
}
}
else if (sField == _T("current users"))
status.m_nCurrentUsers = _ttoi(sValue);
else if (sField == _T("max users"))
status.m_nMaxUsers = _ttoi(sValue);
else if (sField == _T("strip ext"))
{
if (sValue == _T("yes"))
status.m_bStripExtended = TRUE;
else if (sValue == _T("no"))
status.m_bStripExtended = FALSE;
else
{
bContinue = FALSE;
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid strip extended response to the stat command\n"));
}
}
else if (sField == _T("Database entries"))
status.m_nDatabaseEntries = _ttoi(sValue);
//Move to the next line
pszCurLine = pszNextLine;
}
else
bContinue = FALSE;
}
}
//Everything went ok ??
if (bContinue)
{
bSuccess = TRUE;
m_sLastCommandResponse.Empty();
}
}
return bSuccess;
}
BOOL CCDDB::Query(const CCDDBSite& server, DWORD dwDiscID, const CArray<CCDDBTrackPosition, CCDDBTrackPosition&>& tracks,
CArray<CCDDBQueryResult, CCDDBQueryResult&>& results)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
BOOL bSuccess = FALSE;
//Create the socket
CHTTPSocket socket;
if (!socket.Create())
{
m_dwLastError = 0;
TRACE(_T("Failed to create client socket for query command, GetLastError:%d, %s\n"), GetLastError(), GetErrorMessage());
return FALSE;
}
//Connect to the host on the specified port
if (!socket.Connect(server.m_sSite, server.m_nPort))
{
m_dwLastError = 0;
TRACE(_T("Could not connect to the CDDB HTTP server %s, GetLastError:%d, %s\n"), server.m_sSite, GetLastError(), GetErrorMessage());
return FALSE;
}
else
{
//Form the specialized HTTP request to retrieve the query data
CString sDiscID;
sDiscID.Format(_T("%08x"), dwDiscID);
int nTracks = tracks.GetSize() - 1; //Number of tracks is 1 less than the size
//of the array as it also contains the lead
//out position
CString sTracks;
sTracks.Format(_T("%d"), nTracks);
CString sOffsets;
for (int i=0; i<nTracks; i++)
{
//Form the frame number
CString sFrame;
sFrame.Format(_T("%d"), tracks[i].m_nMinute*60*75 + tracks[i].m_nSecond*75 + tracks[i].m_nFrame);
//Accumulate the frame number into the string
sOffsets += sFrame;
//Add a space between each offset
if (i<(nTracks-1))
sOffsets += _T("+");
}
//Compute the playing length in seconds by using the lead out position
int nCDlength = tracks[nTracks].m_nMinute*60 + tracks[nTracks].m_nSecond - tracks[0].m_nMinute - tracks[0].m_nSecond;
CString sLength;
sLength.Format(_T("%d"), nCDlength);
//Form the full request string
CString sRequest;
sRequest.Format(_T("GET %s?cmd=cddb+query+%s+%s+%s+%s&%s HTTP/1.0\r\n\r\n"), server.m_sAddress, sDiscID, sTracks, sOffsets, sLength, GetHelloCommand());
//Send the request through the socket
LPCSTR pszRequest = T2A((LPTSTR) (LPCTSTR) sRequest);
int nCmdLength = strlen(pszRequest);
if (!socket.Send(pszRequest, nCmdLength))
{
m_dwLastError = 0;
TRACE(_T("An unexpected error occurred while sending the HTTP query request, GetLastError:%d, %s\n"), GetLastError(), GetErrorMessage());
return FALSE;
}
//Read the response back through the socket
LPSTR pszOverFlowBuffer = NULL;
if (ReadResponse(socket, NULL, 0, "\r\n.\r\n", &pszOverFlowBuffer, 4096, READ_RESPONSE_QUERY))
{
ASSERT(pszOverFlowBuffer);
//Extract the HTTP body from the response;
LPSTR pszBody = FindHTTPBody(pszOverFlowBuffer);
//Parse out the query info from the body
bSuccess = ParseQueryBody(pszBody, sDiscID, results);
}
else
{
//Reponse could not be retrieved
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server did not respond correctly to the query command\n"));
}
//Don't forget to delete the allocated buffer
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return bSuccess;
}
}
BOOL CCDDB::ParseQueryBody(LPSTR pszBody, const CString& sDiscID, CArray<CCDDBQueryResult, CCDDBQueryResult&>& results)
{
//setup return value
BOOL bSuccess = FALSE;
//Hive away the last reponse until everything is ok
m_sLastCommandResponse = pszBody;
//From the HTTP body get the CDDB response code
int nResponseCode = GetCDDBReponseCode(pszBody);
//Remove any entries which are in the query array
results.RemoveAll();
//If the response is in the expected range (21x) then parse the query data line by line
if (nResponseCode >= 210 && nResponseCode <= 219)
{
//Get the query data and then iterate through all the lines
LPSTR pszLine = SkipToNextLine(pszBody);
while (pszLine)
{
//Get the next line before we parse the current line
LPSTR pszNextLine = GetNextLine(pszLine);
//If we can parse the current line then add it
//to the query array
CCDDBQueryResult result;
if (result.Parse(pszLine))
{
results.Add(result);
bSuccess = TRUE;
}
//Move on to the next line
pszLine = pszNextLine;
}
//Everything is successful, empty out the last command reponse string
m_sLastCommandResponse.Empty();
}
else if (nResponseCode == 200 && strlen(pszBody) > 5)
{
//found an exact match, If we can parse the
//current line then add it to the query array
CCDDBQueryResult result;
if (result.Parse(pszBody+4))
{
results.Add(result);
bSuccess = TRUE;
}
//Everything is successful, empty out the last command reponse string
m_sLastCommandResponse.Empty();
}
else if (nResponseCode == 202)
{
//Deliberately do nothing other than a trace
TRACE(_T("CDDB server does not contain the specifed album with DISCID:%s in its database\n"), sDiscID);
}
else
{
//An unexpected response was retrieved
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server failed to return a valid query response code\n"));
}
return bSuccess;
}
BOOL CCDDB::Read(const CCDDBSite& server, DWORD dwDiscID, const CString& sCategory, CCDDBRecord& record)
{
//For correct operation of the T2A macro, see MFC Tech Note 59
USES_CONVERSION;
BOOL bSuccess = FALSE;
//Create the socket
CHTTPSocket socket;
if (!socket.Create())
{
m_dwLastError = 0;
TRACE(_T("Failed to create client socket for read command, GetLastError:%d, %s\n"), GetLastError(), GetErrorMessage());
return FALSE;
}
//Connect to the host on the specified port
if (!socket.Connect(server.m_sSite, server.m_nPort))
{
m_dwLastError = 0;
TRACE(_T("Could not connect to the CDDB HTTP server %s, GetLastError:%d, %s\n"), server.m_sSite, GetLastError(), GetErrorMessage());
return FALSE;
}
else
{
//Form the full request string
CString sDiscID;
sDiscID.Format(_T("%08x"), dwDiscID);
CString sRequest;
sRequest.Format(_T("GET %s?cmd=cddb+read+%s+%s&%s HTTP/1.0\r\n\r\n"), server.m_sAddress, sCategory, sDiscID, GetHelloCommand());
//Send the request through the socket
LPCSTR pszRequest = T2A((LPTSTR) (LPCTSTR) sRequest);
int nCmdLength = strlen(pszRequest);
if (!socket.Send(pszRequest, nCmdLength))
{
m_dwLastError = 0;
TRACE(_T("An unexpected error occurred while sending the HTTP stat request, GetLastError:%d, %s\n"), GetLastError(), GetErrorMessage());
return FALSE;
}
//Read the response back through the socket
LPSTR pszOverFlowBuffer = NULL;
if (ReadResponse(socket, NULL, 0, "\r\n.\r\n", &pszOverFlowBuffer))
{
ASSERT(pszOverFlowBuffer);
//Hive away the last reponse until everything is ok
m_sLastCommandResponse = pszOverFlowBuffer;
//Extract the HTTP body from the response;
LPSTR pszBody = FindHTTPBody(pszOverFlowBuffer);
//Parse the CDDB record
bSuccess = ParseRecordBody(pszBody, record);
if (record.m_dwDiscID != dwDiscID)
{
TRACE(_T("Returned DiscID from CDDB read (%x) is different than the computed value (%x), using the computed value\n"), record.m_dwDiscID, dwDiscID);
record.m_dwDiscID = dwDiscID;
}
}
else
{
//Reponse could not be Retrieved
m_dwLastError = 0;
SetLastError(WSAEPROTONOSUPPORT);
TRACE(_T("CDDB server did not respond correctly to the stat command\n"));
}
//Don't forget to delete the allocated buffer
if (pszOverFlowBuffer)
delete [] pszOverFlowBuffer;
return bSuccess;
}
}
void CCDDB::ReplaceSubString(CString& sText, const CString& sFind, const CString& sReplacement)
{
int nFindLength = sFind.GetLength();
int nFind = sText.Find(sFind);
while (nFind != -1)
{
CString sTemp = sText.Left(nFind);
sTemp += sReplacement;
sTemp += sText.Right(sText.GetLength() - nFind - nFindLength);
sText = sTemp;
//Look for any more strings to replace prior to looping around
nFind = sText.Find(sFind);
}
}
BOOL CCDDB::ParseKeywordLine(LPCSTR pszLine, CString& sKeyword, CString& sValue)
{
//Validate out parameters
ASSERT(pszLine);
//Duplicate the string into a local variable
int nLength = strlen(pszLine);
LPSTR pszData = new char[nLength + 1];
strcpy(pszData, pszLine);
//Do the actual parsing
BOOL bSuccess = FALSE;
char* pszToken = strstr(pszData, "=");
if (pszData)
{
pszToken[0] = '\0';
sKeyword = pszData;
sValue = pszToken+1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -