Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

CHttpFile and Accept-Encoding: gzip, deflate

254 views
Skip to first unread message

Jacob L. Anawalt

unread,
Mar 30, 2005, 6:15:23 PM3/30/05
to
I am looking (hoping) for some methods within the CInternetSession,
CHttpConnection and CHttpFile MFC objects that will allow me to
transparently use data that the server has sent with "Content-Encoding:
gzip".

Are there methods already existing to get these classes to do this
behind the scenes as it does with "Transfer-Encoding: chunked"? (I
realize that Content-Encoding and Transfer-Encoding are not the same.)

If there aren't built-in methods for these classes, then it seems the
following steps are necessary. I don't want to re-invent the wheel, so
if anyone knows of example code for this please point me in that direction.

I can use the CHttpFile::AddRequestHeaders method to add
"Accept-Encoding: gzip, deflate\r\n", but the data is returned to my
program compressed because CHttpFile doesn't decompress it. To
decompress the returned data, I expect I need to link in a function that
implements the deflate method, give it access to the CString's memory
buffer and have it stick the deflated data somewhere else so that I can
then do my processing.

I see that IE can decompress gzip encoded content, so I would expect
some DLL or class on MS Windows to have the zlib deflate methods. All I
can find references to are WFC for Java. If there are API/VC/MFC methods
already to deflate a gzip stream, I would prefer to use those. If there
aren't, I guess I'll need to have my own copy of zlib1.dll.

Any examples or pointers for where to look are appreciated.

--
Jacob Anawalt

Jacob L. Anawalt

unread,
Apr 5, 2005, 2:33:16 PM4/5/05
to
Jacob L. Anawalt wrote:
> I am looking (hoping) for some methods within the CInternetSession,
> CHttpConnection and CHttpFile MFC objects that will allow me to
> transparently use data that the server has sent with "Content-Encoding:
> gzip".
>

I haven't found any such methods and am surprised that the Internet
Client SDK doesn't expose them since IE clearly sends "Accept-Encoding:
gzip, deflate" and handles "Content-Encoding: gzip" responses. I am just
as surprised that there are no code examples to do this floating around.

I have moved forward and attempted to create gzip enabled methods by
overriding CHttpFile (and thus CHttpConnection and CHttpInternetSession)
and linking to zlib1.lib.

I have put all of these overrides into one definition and one
implementation file. It compiles into an object file, but when I link it
into my program the compiler says:

AfxInetGzip.obj : error LNK2001: unresolved external symbol "protected:
static char const * const * const CHttpConnection::szHtmlVerbs"
(?szHtmlVerbs@CHttpConnection@@1QBQBDB)

The LNK2001 help page suggests that I should move the const
initialization into a header file and only include that header in the
implementation files that need it. Since CHttpConnection::szHtmlVerbs is
defined in INET.H, all I think I can do about this is juggle where I
include afxinet.h, which I have done as liberally as I can think.

Here is the class definition of CHttpConnectionGzip. Hopefully it comes
across correctly.

class CHttpConnectionGzip : public CHttpConnection
{
public:
CHttpConnectionGzip(CInternetSessionGzip* pSession, HINTERNET hConnected,
LPCTSTR pstrServer, DWORD dwContext);
CHttpConnectionGzip(CInternetSessionGzip* pSession, LPCTSTR pstrServer,
INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER,
LPCTSTR pstrUserName = NULL, LPCTSTR pstrPassword = NULL,
DWORD dwContext = 1);
CHttpConnectionGzip(CInternetSessionGzip* pSession, LPCTSTR pstrServer,
DWORD dwFlags, INTERNET_PORT nPort = INTERNET_INVALID_PORT_NUMBER,
LPCTSTR pstrUserName = NULL, LPCTSTR pstrPassword = NULL,
DWORD dwContext = 1);

CHttpFileGzip* OpenRequestGzip(LPCTSTR pstrVerb, LPCTSTR pstrObjectName,
LPCTSTR pstrReferer = NULL,DWORD dwContext = 1,
LPCTSTR* ppstrAcceptTypes = NULL, LPCTSTR pstrVersion = NULL,
DWORD dwFlags = INTERNET_FLAG_EXISTING_CONNECT);

CHttpFileGzip* OpenRequestGzip(int nVerb, LPCTSTR pstrObjectName,
LPCTSTR pstrReferer = NULL, DWORD dwContext = 1,
LPCTSTR* ppstrAcceptTypes = NULL, LPCTSTR pstrVersion = NULL,
DWORD dwFlags = INTERNET_FLAG_EXISTING_CONNECT);

// implementation
~CHttpConnectionGzip();

public:

friend class CInternetSessionGzip; // just to access szHtmlVerbs
//DECLARE_DYNAMIC(CHttpConnectionGzip)

};


If I include the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC macros, then the
expansion of the IMPLEMENT_DYNAMIC macros also give link errors.

I imagine that I'm making some glaringly obvious mistake and would
appreciate having it pointed out.

--
Jacob

Jacob L. Anawalt

unread,
Apr 5, 2005, 3:54:52 PM4/5/05
to
Jacob L. Anawalt wrote:
> I have put all of these overrides into one definition and one
> implementation file. It compiles into an object file, but when I link it
> into my program the compiler says:
>
> AfxInetGzip.obj : error LNK2001: unresolved external symbol "protected:
> static char const * const * const CHttpConnection::szHtmlVerbs"
> (?szHtmlVerbs@CHttpConnection@@1QBQBDB)
>

That was a silly mistake. szHtmlVerbs is only defined in INET.CPP. I was
using it in CHttpConnectionGzip::OpenRequestGzip. I didn't call the
parent to handle this because I wanted my OpenRequestGzip to be called
and not just the parent's OpenRequest. I've defined szHtmlVerbs in my
implementation file and it works (until INET.CPP changes szHttpVerbs.)
Any suggestions for a better way to handle this are welcome.


Now for the DECLARE_DYNAMIC and IMPLEMENT_DYNAMIC issues. I believe I
can live without these for my needs, but it irks me that I'm doing
something wrong so that these don't work:

AfxInetGzip.obj : error LNK2001: unresolved external symbol

"__declspec(dllimport) public: static struct CRuntimeClass const
CHttpFile::classCHttpFile"
(__imp_?classCHttpFile@CHttpFile@@2UCRuntimeClass@@B)

AfxInetGzip.obj : error LNK2001: unresolved external symbol

"__declspec(dllimport) public: static struct CRuntimeClass const
CInternetSession::classCInternetSession"
(__imp_?classCInternetSession@CInternetSession@@2UCRuntimeClass@@B)

AfxInetGzip.obj : error LNK2001: unresolved external symbol

"__declspec(dllimport) public: static struct CRuntimeClass const
CHttpConnection::classCHttpConnection"
(__imp_?classCHttpConnection@CHttpConnection@@2UCRuntimeClass@@B)

I've compared my code to many many other examples of
overriding/extending MFC classes and am puzzled on this one. Here are my
declare (pulled from their respective class declarations) and my
implement statements from my implementation file:

DECLARE_DYNAMIC(CInternetSessionGzip)
DECLARE_DYNAMIC(CHttpConnectionGzip)
DECLARE_DYNAMIC(CHttpFileGzip)

IMPLEMENT_DYNAMIC(CHttpFileGzip, CHttpFile)
IMPLEMENT_DYNAMIC(CInternetSessionGzip, CInternetSession)
IMPLEMENT_DYNAMIC(CHttpConnectionGzip, CHttpConnection)

I'm probably not doing the right thing with AFX_DATA.

--
Jacob

0 new messages