d221bf315c4060cc1be8a962e26e9db452a75ae8
[shibboleth/cpp-opensaml.git] / saml / saml2 / binding / impl / SAML2Redirect.cpp
1 /*
2  *  Copyright 2001-2006 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 /**
18  * @file saml/saml2/binding/SAML2Redirect.h
19  * 
20  * SAML 2.0 HTTP Redirect compression functionality
21  */
22
23 #include "internal.h"
24 #include "saml2/binding/SAML2Redirect.h"
25 #include "zlib/zlib.h"
26
27 #include <log4cpp/Category.hh>
28 #include <xmltooling/util/NDC.h>
29
30 using namespace log4cpp;
31 using namespace std;
32
33 namespace {
34     extern "C" {
35         voidpf saml_zalloc(void* opaque, uInt items, uInt size)
36         {
37             return malloc(items*size);
38         }
39         
40         void saml_zfree(void* opaque, voidpf addr)
41         {
42             free(addr);
43         }
44     };
45 };
46
47 unsigned int opensaml::saml2p::inflate(char* in, unsigned int in_len, ostream& out)
48 {
49 #ifdef _DEBUG
50     xmltooling::NDC ndc("inflate");
51 #endif
52     Category& log = Category::getInstance(SAML_LOGCAT".MessageDecoder.SAML2Redirect.zlib");
53
54     z_stream z;
55     memset(&z, 0, sizeof(z_stream));
56     
57     z.zalloc = saml_zalloc;
58     z.zfree = saml_zfree;
59     z.opaque = NULL;
60     z.next_in = (Bytef*)in;
61     z.avail_in = in_len;
62   
63     int dlen = in_len << 3;  /* guess inflated size: orig_size * 8 */
64     Byte* buf = new Byte[dlen];
65     memset(buf, 0, dlen);
66     z.next_out = buf;
67     z.avail_out = dlen;
68   
69     int ret = inflateInit2(&z, -15);
70     if (ret != Z_OK) {
71         log.error("zlib inflateInit failed with error code (%d)", ret);
72         delete[] buf;
73         return 0;
74     }
75   
76     int iter = 30;
77     while (--iter) {  /* Make sure we can never be caught in infinite loop */
78         ret = inflate(&z, Z_SYNC_FLUSH);
79         switch (ret) {
80             case Z_STREAM_END:
81                 ret = z.next_out - buf;
82                 z.next_out = buf;
83                 while (ret--)
84                     out << *(z.next_out++);
85                 goto done;
86                 
87             case Z_OK:  /* avail_out should be 0 now. Time to dump the buffer. */
88                 ret = z.next_out - buf;
89                 z.next_out = buf;
90                 while (ret--)
91                     out << *(z.next_out++);
92                 memset(buf, 0, dlen);
93                 z.next_out = buf;
94                 z.avail_out = dlen;
95                 break;
96               
97             default:
98                 delete[] buf;
99                 inflateEnd(&z);
100                 log.error("zlib inflate failed with error code (%d)", ret);
101                 return 0;
102         }
103     }
104 done:
105     delete[] buf;
106     int out_len = z.total_out;
107     inflateEnd(&z);
108     return out_len;
109 }