Fix a bug affecting newer boost
[shibboleth/cpp-xmltooling.git] / xmltooling / io / HTTPResponse.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  * HTTPResponse.cpp
23  * 
24  * Interface to HTTP responses.
25  */
26
27 #include "internal.h"
28 #include "HTTPResponse.h"
29
30 #include <boost/algorithm/string/predicate.hpp>
31 #include <boost/bind.hpp>
32
33 using namespace xmltooling;
34 using namespace boost;
35 using namespace std;
36
37 GenericResponse::GenericResponse()
38 {
39 }
40
41 GenericResponse::~GenericResponse()
42 {
43 }
44
45 vector<string> HTTPResponse::m_allowedSchemes;
46
47 vector<string>& HTTPResponse::getAllowedSchemes()
48 {
49     return m_allowedSchemes;
50 }
51
52 void HTTPResponse::sanitizeURL(const char* url)
53 {
54     // predicate for checking scheme below
55     static bool (*fn)(const string&, const string&, const std::locale&) = iequals;
56
57     const char* ch;
58     for (ch=url; *ch; ++ch) {
59         if (iscntrl((unsigned char)(*ch)))  // convert to unsigned to allow full range from 00-FF
60             throw IOException("URL contained a control character.");
61     }
62
63     ch = strchr(url, ':');
64     if (!ch)
65         throw IOException("URL is malformed.");
66     string s(url, ch - url);
67     std::locale loc;
68     vector<string>::const_iterator i =
69         find_if(m_allowedSchemes.begin(), m_allowedSchemes.end(), boost::bind(fn, boost::cref(s), _1, boost::cref(loc)));
70     if (i != m_allowedSchemes.end())
71         return;
72
73     throw IOException("URL contains invalid scheme ($1).", params(1, s.c_str()));
74 }
75
76 HTTPResponse::HTTPResponse()
77 {
78 }
79
80 HTTPResponse::~HTTPResponse()
81 {
82 }
83
84 void HTTPResponse::setContentType(const char* type)
85 {
86     setResponseHeader("Content-Type", type);
87 }
88
89 void HTTPResponse::setCookie(const char* name, const char* value)
90 {
91     string cookie(name);
92     cookie = cookie + '=' + value;
93     setResponseHeader("Set-Cookie", cookie.c_str());
94 }
95
96 void HTTPResponse::setResponseHeader(const char* name, const char* value)
97 {
98     for (const char* ch=name; *ch; ++ch) {
99         if (iscntrl(*ch))
100             throw IOException("Response header name contained a control character.");
101     }
102
103     for (const char* ch=value; *ch; ++ch) {
104         if (iscntrl(*ch))
105             throw IOException("Value for response header ($1) contained a control character.", params(1,name));
106     }
107 }
108
109 long HTTPResponse::sendRedirect(const char* url)
110 {
111     sanitizeURL(url);
112     return XMLTOOLING_HTTP_STATUS_MOVED;
113 }
114
115 long HTTPResponse::sendError(istream& inputStream)
116 {
117     return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_ERROR);
118 }
119
120 long HTTPResponse::sendResponse(istream& inputStream)
121 {
122     return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_OK);
123 }