SSPCPP-616 - clean up concatenated string literals
[shibboleth/cpp-opensaml.git] / saml / saml2 / binding / impl / SAML2Redirect.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * @file saml/saml2/binding/SAML2Redirect.h
23  * 
24  * SAML 2.0 HTTP Redirect compression functionality.
25  */
26
27 #include "internal.h"
28 #include "saml2/binding/SAML2Redirect.h"
29
30 #include <zlib.h>
31 #include <xmltooling/logging.h>
32 #include <xmltooling/util/NDC.h>
33
34 using namespace xmltooling::logging;
35 using namespace std;
36
37 namespace {
38     extern "C" {
39         voidpf saml_zalloc(void* opaque, uInt items, uInt size)
40         {
41             return malloc(items*size);
42         }
43         
44         void saml_zfree(void* opaque, voidpf addr)
45         {
46             free(addr);
47         }
48     };
49 };
50
51 char* opensaml::saml2p::deflate(char* in, unsigned int in_len, unsigned int* out_len)
52 {
53 #ifdef _DEBUG
54     xmltooling::NDC ndc("deflate");
55 #endif
56     Category& log = Category::getInstance(SAML_LOGCAT ".MessageDecoder.SAML2Redirect.zlib");
57
58     z_stream z;
59     memset(&z, 0, sizeof(z_stream));
60     
61     z.zalloc = saml_zalloc;
62     z.zfree = saml_zfree;
63     z.opaque = nullptr;
64     z.next_in = (Bytef*)in;
65     z.avail_in = in_len;
66     *out_len = 0;
67
68     int ret = deflateInit2(&z, 9, Z_DEFLATED, -15, 9, Z_DEFAULT_STRATEGY);
69     if (ret != Z_OK) {
70         log.error("zlib deflateInit2 failed with error code (%d)", ret);
71         return nullptr;
72     }
73   
74     int dlen = in_len + (in_len >> 8) + 12;  /* orig_size * 1.001 + 12 */
75     char* out = new char[dlen];
76     z.next_out = (Bytef*)out;
77     z.avail_out = dlen;
78   
79     ret = deflate(&z, Z_FINISH);
80     if (ret != Z_STREAM_END) {
81     deflateEnd(&z);
82         log.error("zlib deflateInit2 failed with error code (%d)", ret);
83         delete[] out;
84     }
85   
86     *out_len = z.total_out;
87     deflateEnd(&z);
88     return out;
89 }
90
91 unsigned int opensaml::saml2p::inflate(char* in, unsigned int in_len, ostream& out)
92 {
93 #ifdef _DEBUG
94     xmltooling::NDC ndc("inflate");
95 #endif
96     Category& log = Category::getInstance(SAML_LOGCAT ".MessageDecoder.SAML2Redirect.zlib");
97
98     z_stream z;
99     memset(&z, 0, sizeof(z_stream));
100     
101     z.zalloc = saml_zalloc;
102     z.zfree = saml_zfree;
103     z.opaque = nullptr;
104     z.next_in = (Bytef*)in;
105     z.avail_in = in_len;
106   
107     int dlen = in_len << 3;  /* guess inflated size: orig_size * 8 */
108     Byte* buf = new Byte[dlen];
109     memset(buf, 0, dlen);
110     z.next_out = buf;
111     z.avail_out = dlen;
112   
113     int ret = inflateInit2(&z, -15);
114     if (ret != Z_OK) {
115         log.error("zlib inflateInit2 failed with error code (%d)", ret);
116         delete[] buf;
117         return 0;
118     }
119   
120     size_t diff;
121     int iter = 30;
122     while (--iter) {  /* Make sure we can never be caught in infinite loop */
123         ret = inflate(&z, Z_SYNC_FLUSH);
124         switch (ret) {
125             case Z_STREAM_END:
126                 diff = z.next_out - buf;
127                 z.next_out = buf;
128                 while (diff--)
129                     out << *(z.next_out++);
130                 goto done;
131                 
132             case Z_OK:  /* avail_out should be 0 now. Time to dump the buffer. */
133                 diff = z.next_out - buf;
134                 z.next_out = buf;
135                 while (diff--)
136                     out << *(z.next_out++);
137                 memset(buf, 0, dlen);
138                 z.next_out = buf;
139                 z.avail_out = dlen;
140                 break;
141               
142             default:
143                 delete[] buf;
144                 inflateEnd(&z);
145                 log.error("zlib inflate failed with error code (%d)", ret);
146                 return 0;
147         }
148     }
149 done:
150     delete[] buf;
151     int out_len = z.total_out;
152     inflateEnd(&z);
153     return out_len;
154 }