
08-06-2009
|
|
|
|
Asynchronous Pluggable Protocol and http traffic analyzer
Hi,
I am trying to capture and modify HTML page from Internet Explorer 8 add-on.
I found some sample code (written by Igor Tandetnik) that implements
IInternetProtocol interface on which I based my BHO. This BHO unfortunately
works only partially.
The majority of my code can be found within the implementation of
IInternetProtocol::Read method. My goal was to capture HTML, analyze it,
probably modify it and finally send it back to IE. It means I have to read
the whole HTML page in buffer and after analysis pass it back to IE.
When user navigates on some page, everything works fine. Problem occurs when
user refreshes current page with F5. Then I receive only a small chunk of
HTML. I suspect that problem lies somewhere within my "Read" method
implementation. Here's a description how it works:
a) browser calls my component
b) I receive only a chunk of total HTML which I store to my buffer and
immediately pass "empty" response back to browser to fool him that he's
receiving something (I don't know if this is the best method, but I don'
have any better idea):
*pcbRead = 0;
retResult = S_OK;
c) process is repeated multiple times as described in b) depending on the
size of HTML
d) finally I analyze whole buffer, possibly modify it and send it back to IE
Does anyone has suggestion how to do it better, or has maybe some completely
different approach which would work with F5 also?
Does anybody know how and when InternetProtocolImpl::Read method is called
by IE?
Follows my implementation of Read method:
// IInternetProtocol::Read impl
STDMETHODIMP CInternetProtocolImpl::Read(void *pv, ULONG cb, ULONG *pcbRead)
{
if (m_spInternetProtocol==NULL)
return E_UNEXPECTED;
if ( isHtmlTextMimeType() ) {
HRESULT retResult = S_OK;
HRESULT hr = S_OK;
try {
m_criticalSection.lock();
if (!m_allDataReceived) {
ULONG retCount = 0;
int cbLocal = cb;
// check allocated buffer size
if (cbLocal > m_buffer.size() - m_readPos)
m_buffer.resize(m_readPos + cbLocal, '\0');
hr = m_spInternetProtocol->Read(&m_buffer[m_readPos],
cbLocal, &retCount);
if (hr==S_FALSE)
m_allDataReceived = true;
if (retCount!=0) {
// fix offset (use actually read bytes)
m_readPos += retCount;
}
}
if ( !m_htmlContentUpdated && m_allDataReceived ) {
analyzeHtmlContent(m_buffer);
m_htmlContentUpdated = true;
}
if ( m_htmlContentUpdated && (m_buffer.size()>0) ) {
// all data are sent
if (m_sendPos >= m_readPos) {
m_allDataReceived = false;
m_htmlContentUpdated = false;
m_readPos = 0;
m_sendPos = 0;
m_buffer.clear();
*pcbRead = 0;
retResult = S_FALSE;
} else {
int nrOfBytesForSending = cb;
if ( nrOfBytesForSending > (m_readPos-m_sendPos) )
nrOfBytesForSending = (m_readPos-m_sendPos);
memset(pv, '\0', cb);
memcpy( pv, &m_buffer[m_sendPos], nrOfBytesForSending );
m_sendPos+=nrOfBytesForSending ;
*pcbRead = nrOfBytesForSending ;
retResult = S_OK;
}
} else {
*pcbRead = 0;
retResult = S_OK;
}
m_criticalSection.unlock();
} catch(...) {
m_criticalSection.unlock();
}
return retResult;
} else {
return m_spInternetProtocol->Read(pv, cb, pcbRead);
}
}
|