1 /*****************************************************************
2 |
3 |   Platinum - HTTP Helper
4 |
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
8 |
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
13 |
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
21 |
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25 | GNU General Public License for more details.
26 |
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
32 |
33 ****************************************************************/
34 
35 /** @file
36  HTTP utilities
37  */
38 
39 #ifndef _PLT_HTTP_H_
40 #define _PLT_HTTP_H_
41 
42 /*----------------------------------------------------------------------
43 |   includes
44 +---------------------------------------------------------------------*/
45 #include "Neptune.h"
46 #include "PltVersion.h"
47 
48 /*----------------------------------------------------------------------
49 |   constants
50 +---------------------------------------------------------------------*/
51 #if !defined(PLT_HTTP_DEFAULT_USER_AGENT)
52 #define PLT_HTTP_DEFAULT_USER_AGENT "UPnP/1.0 DLNADOC/1.50 Platinum/" PLT_PLATINUM_SDK_VERSION_STRING
53 #endif
54 
55 #if !defined(PLT_HTTP_DEFAULT_SERVER)
56 #define PLT_HTTP_DEFAULT_SERVER "UPnP/1.0 DLNADOC/1.50 Platinum/" PLT_PLATINUM_SDK_VERSION_STRING
57 #endif
58 
59 /*----------------------------------------------------------------------
60 |   types
61 +---------------------------------------------------------------------*/
62 typedef enum {
63     PLT_DEVICE_UNKNOWN,
64     PLT_DEVICE_XBOX_360,
65     PLT_DEVICE_XBOX_ONE,
66     PLT_DEVICE_PS3,
67     PLT_DEVICE_WMP,
68     PLT_DEVICE_SONOS,
69     PLT_DEVICE_MAC,
70     PLT_DEVICE_WINDOWS,
71     PLT_DEVICE_VLC
72 } PLT_DeviceSignature;
73 
74 /*----------------------------------------------------------------------
75 |   PLT_HttpHelper
76 +---------------------------------------------------------------------*/
77 /**
78  The PLT_HttpHelper class is a set of utility functions for manipulating
79  HTTP headers, entities and messages.
80  */
81 class PLT_HttpHelper {
82 public:
83     static bool         IsConnectionKeepAlive(NPT_HttpMessage& message);
84     static bool         IsBodyStreamSeekable(NPT_HttpMessage& message);
85 
86     static NPT_Result   GetContentType(const NPT_HttpMessage& message, NPT_String& type);
87     static NPT_Result   GetContentLength(const NPT_HttpMessage& message, NPT_LargeSize& len);
88 
89     static NPT_Result   GetHost(const NPT_HttpRequest& request, NPT_String& value);
90     static void         SetHost(NPT_HttpRequest& request, const char* host);
91     static PLT_DeviceSignature GetDeviceSignature(const NPT_HttpRequest& request);
92 
93     static NPT_Result   SetBody(NPT_HttpMessage& message, NPT_String& text, NPT_HttpEntity** entity = NULL);
94     static NPT_Result   SetBody(NPT_HttpMessage& message, const char* text, NPT_HttpEntity** entity = NULL);
95     static NPT_Result   SetBody(NPT_HttpMessage& message, const void* body, NPT_LargeSize len, NPT_HttpEntity** entity = NULL);
96     static NPT_Result   SetBody(NPT_HttpMessage& message, NPT_InputStreamReference stream, NPT_HttpEntity** entity = NULL);
97     static NPT_Result   GetBody(const NPT_HttpMessage& message, NPT_String& body);
98     static NPT_Result   ParseBody(const NPT_HttpMessage& message, NPT_XmlElementNode*& xml);
99 
100     static void         SetBasicAuthorization(NPT_HttpRequest& request, const char* username, const char* password);
101 };
102 
103 /*----------------------------------------------------------------------
104 |   PLT_HttpRequestContext
105 +---------------------------------------------------------------------*/
106 /**
107  The PLT_HttpRequestContext class holds information about the request sent, the
108  local & remote ip addresses and ports associated with a connection. It is used
109  mostly when processing a HTTP response.
110  */
111 class PLT_HttpRequestContext : public NPT_HttpRequestContext {
112 public:
113     // constructors and destructor
PLT_HttpRequestContext(const NPT_HttpRequest & request)114     PLT_HttpRequestContext(const NPT_HttpRequest& request) :
115         m_Request(request) {}
PLT_HttpRequestContext(const NPT_HttpRequest & request,const NPT_HttpRequestContext & context)116     PLT_HttpRequestContext(const NPT_HttpRequest& request, const NPT_HttpRequestContext& context) :
117         NPT_HttpRequestContext(&context.GetLocalAddress(), &context.GetRemoteAddress()),
118         m_Request(request) {}
~PLT_HttpRequestContext()119     virtual ~PLT_HttpRequestContext() {}
120 
GetRequest()121     const NPT_HttpRequest& GetRequest() const { return m_Request; }
GetDeviceSignature()122     PLT_DeviceSignature GetDeviceSignature() { return PLT_HttpHelper::GetDeviceSignature(m_Request); }
123 
124 private:
125     const NPT_HttpRequest& m_Request;
126 };
127 
128 /*----------------------------------------------------------------------
129 |   NPT_HttpHeaderPrinter
130 +---------------------------------------------------------------------*/
131 class NPT_HttpHeaderPrinter
132 {
133 public:
134     // methods
NPT_HttpHeaderPrinter(NPT_OutputStreamReference & stream)135     NPT_HttpHeaderPrinter(NPT_OutputStreamReference& stream) :
136     m_Stream(stream) {}
operator()137     NPT_Result operator()(NPT_HttpHeader*& header) const {
138         m_Stream->WriteString(header->GetName());
139         m_Stream->Write(": ", 2);
140         m_Stream->WriteString(header->GetValue());
141         m_Stream->Write("\r\n", 2, NULL);
142         return NPT_SUCCESS;
143     }
144 
145 private:
146     // members
147     NPT_OutputStreamReference& m_Stream;
148 };
149 
150 /*----------------------------------------------------------------------
151 |   macros
152 +---------------------------------------------------------------------*/
153 #if defined(NPT_CONFIG_ENABLE_LOGGING)
154 #define PLT_LOG_HTTP_REQUEST_L(_logger, _level, _prefix, _request) \
155 do { \
156     if (!_request) break; \
157     NPT_LOG_GET_LOGGER((_logger))                                       \
158     if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
159         NPT_StringOutputStreamReference stream(new NPT_StringOutputStream); \
160         NPT_OutputStreamReference output = stream; \
161         _request->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output)); \
162         NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"%s\n%s %s %s\n%s", (const char*)_prefix, (const char*)_request->GetMethod(), (const char*)_request->GetUrl().ToRequestString(true), (const char*)_request->GetProtocol(), (const char*)stream->GetString())); \
163     } \
164 } while (0)
165 
166 #define PLT_LOG_HTTP_RESPONSE_L(_logger, _level, _prefix, _response) \
167 do { \
168     if (!_response) break; \
169     NPT_LOG_GET_LOGGER((_logger))                                       \
170     if ((_logger).logger && (_level) >= (_logger).logger->GetLevel()) { \
171         NPT_StringOutputStreamReference stream(new NPT_StringOutputStream); \
172         NPT_OutputStreamReference output = stream; \
173         _response->GetHeaders().GetHeaders().Apply(NPT_HttpHeaderPrinter(output)); \
174         NPT_LOG_X((_logger),(_level),((_level),__FILE__,__LINE__,(NPT_LocalFunctionName),"%s\n%s %d %s\n%s", (const char*)_prefix, (const char*)_response->GetProtocol(), _response->GetStatusCode(), (const char*)_response->GetReasonPhrase(), (const char*)stream->GetString())); \
175     } \
176 } while (0)
177 
178 #define PLT_LOG_HTTP_REQUEST(_level,_prefix,_request) PLT_LOG_HTTP_REQUEST_L(_NPT_LocalLogger,(_level),(_prefix),(_request))
179 
180 #define PLT_LOG_HTTP_RESPONSE(_level,_prefix,_response) PLT_LOG_HTTP_RESPONSE_L(_NPT_LocalLogger,(_level),(_prefix),(_response))
181 
182 #else /* NPT_CONFIG_ENABLE_LOGGING */
183 #define PLT_LOG_HTTP_REQUEST_L(_logger, _level, _prefix, _request)
184 #define PLT_LOG_HTTP_RESPONSE_L(_logger, _level, _prefix, _response)
185 #define PLT_LOG_HTTP_REQUEST(_level,_prefix,_request)
186 #define PLT_LOG_HTTP_RESPONSE(_level,_prefix,_response)
187 #endif /* NPT_CONFIG_ENABLE_LOGGING */
188 
189 /*----------------------------------------------------------------------
190 |   PLT_HttpRequestHandler
191 +---------------------------------------------------------------------*/
192 /**
193  The PLT_HttpRequestHandler class delegates the handling of the response of a
194  received HTTP request by a HTTP Server.
195  */
196 class PLT_HttpRequestHandler : public NPT_HttpRequestHandler
197 {
198 public:
PLT_HttpRequestHandler(NPT_HttpRequestHandler * delegate)199     PLT_HttpRequestHandler(NPT_HttpRequestHandler* delegate) :
200         m_Delegate(delegate) {}
~PLT_HttpRequestHandler()201     virtual ~PLT_HttpRequestHandler() {}
202 
203     // NPT_HttpRequestHandler methods
SetupResponse(NPT_HttpRequest & request,const NPT_HttpRequestContext & context,NPT_HttpResponse & response)204     NPT_Result SetupResponse(NPT_HttpRequest&              request,
205                              const NPT_HttpRequestContext& context,
206                              NPT_HttpResponse&             response) {
207         return m_Delegate->SetupResponse(request, context, response);
208     }
209 
210 private:
211     NPT_HttpRequestHandler* m_Delegate;
212 };
213 
214 #endif /* _PLT_HTTP_H_ */
215