Incorporating boostisms
[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     vector<string>::const_iterator i =
68         find_if(m_allowedSchemes.begin(), m_allowedSchemes.end(), boost::bind(fn, boost::cref(s), _1, boost::cref(std::locale())));
69     if (i != m_allowedSchemes.end())
70         return;
71
72     throw IOException("URL contains invalid scheme ($1).", params(1, s.c_str()));
73 }
74
75 HTTPResponse::HTTPResponse()
76 {
77 }
78
79 HTTPResponse::~HTTPResponse()
80 {
81 }
82
83 void HTTPResponse::setContentType(const char* type)
84 {
85     setResponseHeader("Content-Type", type);
86 }
87
88 void HTTPResponse::setCookie(const char* name, const char* value)
89 {
90     string cookie(name);
91     cookie = cookie + '=' + value;
92     setResponseHeader("Set-Cookie", cookie.c_str());
93 }
94
95 void HTTPResponse::setResponseHeader(const char* name, const char* value)
96 {
97     for (const char* ch=name; *ch; ++ch) {
98         if (iscntrl(*ch))
99             throw IOException("Response header name contained a control character.");
100     }
101
102     for (const char* ch=value; *ch; ++ch) {
103         if (iscntrl(*ch))
104             throw IOException("Value for response header ($1) contained a control character.", params(1,name));
105     }
106 }
107
108 long HTTPResponse::sendRedirect(const char* url)
109 {
110     sanitizeURL(url);
111     return XMLTOOLING_HTTP_STATUS_MOVED;
112 }
113
114 long HTTPResponse::sendError(istream& inputStream)
115 {
116     return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_ERROR);
117 }
118
119 long HTTPResponse::sendResponse(istream& inputStream)
120 {
121     return sendResponse(inputStream, XMLTOOLING_HTTP_STATUS_OK);
122 }