00001
00010 #ifdef _ZLIB_SUPPORT_
00011
00012 #include "Encoding_Deflate.h"
00013 #include "../CallBack.h"
00014 #include "../IoFunctions.h"
00015 #include <stdio.h>
00016 #include <stdlib.h>
00017 #include <string.h>
00018 #include <assert.h>
00019
00020
00021 #ifdef __WIN32__RELEASE__
00022 #pragma comment(lib, "zdll.lib")
00023 #include "../../Includes/Zlib/include/zlib.h"
00024 #include "../../Includes/Zlib/include/zconf.h"
00025 #else
00026 #include <zlib.h>
00027 #include <zconf.h>
00028 #endif
00029
00030 #define CHUNK 16384
00031
00033
00037
00038
00039 __inline static int get_byte(z_stream *strm)
00040 {
00041 if (strm->avail_in==0) {
00042 return EOF;
00043 }
00044 strm->avail_in--;
00045 return *(strm->next_in)++;
00046 }
00047
00048
00050
00059
00060 static char *gunzip(char *in, int inSize, int *total, int what)
00061 {
00062 int ret;
00063 unsigned have;
00064 z_stream strm;
00065 unsigned char out[CHUNK];
00066
00067 unsigned long lpBufferSize;
00068 PHTTPIOMapping HTTPIoMapping = NULL;
00069
00070
00071
00072 if ( (!inSize) || (!in) ) {
00073 return(NULL);
00074 }
00075
00076
00077 strm.zalloc = Z_NULL;
00078 strm.zfree = Z_NULL;
00079 strm.opaque = Z_NULL;
00080 strm.avail_in = strm.avail_out = 0;
00081 strm.next_in = strm.next_out = 0;
00082
00083 strm.avail_in = inSize;
00084 strm.next_in=(Bytef*)in;
00085
00086 if (what == GZIP_DATA )
00087 {
00088 unsigned int len;
00089 int c;
00090 ret = inflateInit2(&strm,-MAX_WBITS);
00091 if (ret != Z_OK) return(NULL);
00092
00093 memset(out,0,sizeof(out));
00094
00095 if (strm.next_in[0] != 0x1f ||
00096 strm.next_in[1] != 0x8b) {
00097 #ifdef _DBG_
00098 printf("gunzip(): INVALID Magic gzip header\n");
00099 #endif
00100 inflateEnd(&strm);
00101 return (NULL);;
00102 }
00103 strm.avail_in -= 2;
00104 strm.next_in += 2;
00105
00106 int method= get_byte(&strm);
00107 int flags = get_byte(&strm);
00108
00109
00110 #define ASCII_FLAG 0x01
00111 #define HEAD_CRC 0x02
00112 #define EXTRA_FIELD 0x04
00113 #define ORIG_NAME 0x08
00114 #define COMMENT 0x10
00115 #define RESERVED 0xE0
00116
00117 if (method != Z_DEFLATED || (flags & RESERVED) != 0)
00118 {
00119 #ifdef _DBG_
00120 printf("gunzip(): Method or flags error: %i - %i\n",method,flags);
00121 #endif
00122 inflateEnd(&strm);
00123 return NULL;
00124 }
00125
00126 strm.avail_in-=6;
00127 strm.next_in+=6;
00128
00129 if ((flags & EXTRA_FIELD) != 0) {
00130 len = (uInt)get_byte(&strm);
00131 len += ((uInt)get_byte(&strm))<<8;
00132
00133 while (len-- != 0 && get_byte(&strm) != EOF) ;
00134 }
00135
00136 if ((flags & ORIG_NAME) != 0) {
00137 while ((c = get_byte(&strm)) != 0 && c != EOF) ;
00138 }
00139 if ((flags & COMMENT) != 0) {
00140 while ((c = get_byte(&strm)) != 0 && c != EOF) ;
00141 }
00142 if ((flags & HEAD_CRC) != 0) {
00143 for (len = 0; len < 2; len++) (void)get_byte(&strm);
00144 }
00145 } else if (what == DEFLATE_DATA )
00146 {
00147 ret = inflateInit(&strm);
00148 if (ret != Z_OK) return(NULL);
00149 } else return (NULL);
00150
00151 *total=0;
00152
00153
00154 do {
00155 strm.avail_out = sizeof(out);
00156 strm.next_out = out;
00157 ret = inflate(&strm, Z_NO_FLUSH);
00158 assert(ret != Z_STREAM_ERROR);
00159 switch (ret) {
00160 case Z_NEED_DICT:
00161 ret = Z_DATA_ERROR;
00162 case Z_DATA_ERROR:
00163 case Z_MEM_ERROR:
00164 (void)inflateEnd(&strm);
00165
00166
00167
00168 if (HTTPIoMapping)
00169 {
00170 #ifdef __WIN32__RELEASE__
00171 CloseHandle(HTTPIoMapping->hTmpFilename);
00172 DeleteFile(HTTPIoMapping->BufferedFileName);
00173 #else
00174 close(HTTPIoMapping->hTmpFilename);
00175 rmdir(HTTPIoMapping->BufferedFileName);
00176 #endif
00177 HTTPIoMapping->assigned=0;
00178 }
00179 return(NULL);
00180 }
00181 have = CHUNK - strm.avail_out;
00182 if (have>0) {
00183
00184
00185
00186
00187
00188 if (!HTTPIoMapping){
00189 HTTPIoMapping = GetFileMapping(0,NULL);
00190 if (!HTTPIoMapping) return(NULL);
00191 }
00192 if (HTTPIoMapping) {
00193 #ifdef __WIN32__RELEASE__
00194 WriteFile(HTTPIoMapping->hTmpFilename,out,have,&lpBufferSize,NULL);
00195 #else
00196
00197 write(HTTPIoMapping->hTmpFilename,out,have);
00198 #endif
00199 HTTPIoMapping->MemoryLenght+=have;
00200 }
00201
00202
00203 *total+=have;
00204
00205
00206 }
00207 } while (strm.avail_out == 0);
00208
00209 (void)inflateEnd(&strm);
00210 #ifdef __WIN32__RELEASE__
00211 WriteFile(HTTPIoMapping->hTmpFilename,"\x00",1,&lpBufferSize,NULL);
00212 HTTPIoMapping->hMapping = CreateFileMapping (HTTPIoMapping->hTmpFilename,
00213 NULL,
00214 PAGE_READWRITE,
00215 0,
00216 HTTPIoMapping->MemoryLenght+1,
00217 NULL);
00218 HTTPIoMapping->BufferedPtr = (char*) MapViewOfFile (HTTPIoMapping->hMapping , FILE_MAP_ALL_ACCESS, 0,0,0);
00219
00220 #else
00221 write(HTTPIoMapping->hTmpFilename,"\x00",1);
00222 HTTPIoMapping->BufferedPtr = (char*) mmap (0, *total +1, PROT_READ | PROT_WRITE, MAP_SHARED, HTTPIoMapping->hTmpFilename, 0);
00223 #endif
00224 return(HTTPIoMapping->BufferedPtr);
00225
00226
00227 }
00228
00230
00238
00239 int CBDeflate(int cbType,HTTPHANDLE HTTPHandle,PHTTP_DATA *prequest,PHTTP_DATA *presponse)
00240 {
00241
00242 PHTTP_DATA response = *presponse;
00243 PHTTP_DATA request = *prequest;
00244
00245
00246
00247 if (cbType == CBTYPE_CLIENT_REQUEST)
00248 {
00249 if (request)
00250 {
00251 AddHeader(request,"Accept-Encoding: gzip, deflate\r\n");
00252 }
00253 return (CBRET_STATUS_NEXT_CB_CONTINUE);
00254 } else if (cbType == CBTYPE_CLIENT_RESPONSE)
00255 {
00256 int total= 0;
00257 int type = NORMAL_DATA;
00258
00259 if ( (!response) || (!response->HeaderSize) || (!response->Header) ) {
00260 return (CBRET_STATUS_NEXT_CB_CONTINUE);
00261 }
00262
00263 char *encoding=GetHeaderValue(response->Header,"Content-Encoding: ",0);
00264 if (!encoding)
00265 return(CBRET_STATUS_NEXT_CB_CONTINUE);
00266
00267 char *p = strstr(encoding,"deflate");
00268 if (p)
00269 type= DEFLATE_DATA;
00270 else {
00271 p = strstr(encoding,"gzip");
00272 if (p) type= GZIP_DATA;
00273
00274 }
00275
00276 if (type != NORMAL_DATA)
00277 {
00278 char *decoded = (char *) gunzip(response->Data, response->DataSize, &total, type);
00279 if (decoded) {
00280 #ifdef _DBG_
00281 printf("CBDeflate(): uncompressed %i bytes to %i. Data: %s\n",response->DataSize,total,p);
00282 #endif
00283 printf("Liberando memoria..\n");
00284 response->Data = DeleteFileMapping(response->Data);
00285 if (response->Data)
00286 {
00287 printf("[Encoding_Deflate CB: Unable to delete mapping against response->Data. Memory leak here\n");
00288 free(response->Data);
00289
00290 }
00291 response->Data=decoded;
00292 response->DataSize=total;
00293 RemoveHeader(response,"Content-Encoding:");
00294 RemoveHeader(response,"Content-Length:");
00295 char tmp[256];
00296 sprintf(tmp,"Content-Length: %i\r\n",total);
00297 AddHeader(response,tmp);
00298 } else {
00299 #ifdef _DBG_
00300 printf("CBDeflate(): Error decoding buffer with %s\n",p);
00301 #endif
00302 }
00303 }
00304 free(encoding);
00305 }
00306 return (CBRET_STATUS_NEXT_CB_CONTINUE);
00307
00308 }
00309 #endif
00310