1 // This may look like C code, but it's really -*- C++ -*-
2 /*
3  * Copyright (C) 2008 Emweb bv, Herent, Belgium.
4  *
5  * See the LICENSE file for terms of use.
6  */
7 #ifndef WENVIRONMENT_H_
8 #define WENVIRONMENT_H_
9 
10 #include <chrono>
11 #include <string>
12 #include <map>
13 #include <vector>
14 
15 #include <Wt/WDllDefs.h>
16 #include <Wt/Http/Request.h>
17 #include <Wt/WLocale.h>
18 #include <Wt/WSignal.h>
19 
20 namespace Wt {
21 
22 /*! \brief An enumeration type for specific user agent.
23  *
24  * \sa agent()
25  */
26 enum class UserAgent {
27   Unknown = 0,                //!< Unknown user agent
28   IEMobile = 1000,            //!< Internet Explorer Mobile, 5 or older
29   IE6 = 1001,                 //!< Internet Explorer 6
30   IE7 = 1002,                 //!< Internet Explorer 7
31   IE8 = 1003,                 //!< Internet Explorer 8
32   IE9 = 1004,                 //!< Internet Explorer 9
33   IE10 = 1005,                //!< Internet Explorer 10
34   IE11 = 1006,                //!< Internet Explorer 11
35   Edge = 1100,		      //!< Edge
36   Opera = 3000,               //!< Opera
37   Opera10 = 3010,             //!< Opera 10 or later
38   WebKit = 4000,              //!< WebKit
39   Safari = 4100,              //!< Safari 2 or older
40   Safari3 = 4103,             //!< Safari 3
41   Safari4 = 4104,             //!< Safari 4 or later
42   Chrome0 = 4200,             //!< Chrome 0
43   Chrome1 = 4201,             //!< Chrome 1
44   Chrome2 = 4202,             //!< Chrome 2
45   Chrome3 = 4203,             //!< Chrome 3
46   Chrome4 = 4204,             //!< Chrome 4
47   Chrome5 = 4205,             //!< Chrome 5 or later
48   Arora = 4300,               //!< Arora
49   MobileWebKit = 4400,        //!< Mobile WebKit
50   MobileWebKitiPhone = 4450,  //!< Mobile WebKit iPhone/iPad
51   MobileWebKitAndroid = 4500, //!< Mobile WebKit Android
52   Konqueror = 5000,           //!< Konqueror
53   Gecko = 6000,               //!< Gecko
54   Firefox = 6100,             //!< Firefox 2 or older
55   Firefox3_0 = 6101,          //!< Firefox 3.0
56   Firefox3_1 = 6102,          //!< Firefox 3.1
57   Firefox3_1b = 6103,         //!< Firefox 3.1b
58   Firefox3_5 = 6104,          //!< Firefox 3.5
59   Firefox3_6 = 6105,          //!< Firefox 3.6
60   Firefox4_0 = 6106,          //!< Firefox 4.0
61   Firefox5_0 = 6107,          //!< Firefox 5.0 or later
62   BotAgent = 10000            //!< Bot user agent
63 };
64 
65 /*! \brief Enumeration for HTML content type.
66  */
67 enum class HtmlContentType {
68   XHTML1, //!< XHTML1.x
69   HTML4,  //!< HTML4
70   HTML5   //!< HTML5
71 };
72 
73 class WSslInfo;
74 class WAbstractServer;
75 class Configuration;
76 class WServer;
77 class WebRequest;
78 class WebSession;
79 
80 /*! \class WEnvironment Wt/WEnvironment.h Wt/WEnvironment.h
81  *  \brief A class that captures information on the application environment.
82  *
83  * The environment provides information on the client, and gives access
84  * to startup arguments.
85  *
86  * Usage example:
87  * \if cpp
88  * \code
89  * const WEnvironment& env = WApplication::instance()->environment();
90  *
91  * // read an application startup argument
92  * // (passed as argument in the URL or POST'ed to the application).
93  * if (!env.getParameterValues("login").empty()) {
94  *   std::string login = env.getParameterValues("login")[0];
95  *   ...
96  * }
97  *
98  * // Check for JavaScript/AJAX availability before using AJAX-only
99  * // widgets
100  * std::unique_ptr<Wt::WTextArea> textEdit;
101  * if (!env.ajax())
102  *   textEdit = std::make_unique<Wt::WTextEdit>(); // provide an HTML text editor
103  * else
104  *   textEdit = std::make_unique<Wt::WTextArea>(); // fall-back to a plain old text area.
105  *
106  * \endcode
107  * \elseif java
108  * \code
109  * WEnvironment env = WApplication.instance().environment();
110  *
111  * // read an application startup argument
112  * // (passed as argument in the URL or POST'ed to the application).
113  * if (!env.getParameterValues("login").isEmpty()) {
114  * String login = env.getParameterValues("login").get(0);
115  * //...
116  * }
117  *
118  * // Check for JavaScript/AJAX availability before using JavaScript-only
119  * // widgets
120  *  WTextArea textEdit;
121  * if (!env.isAjax())
122  *   textEdit = new WTextEdit(); // provide an HTML text editor
123  * else
124  *   textEdit = new WTextArea(); // fall-back to a plain old text area.
125  * \endcode
126  * \endif
127  */
128 class WT_API WEnvironment
129 {
130 public:
131   /*! \brief Cookie map.
132    *
133    * A std::map which associates a cookie name with a cookie value.
134    *
135    * \sa cookies()
136    */
137   typedef std::map<std::string, std::string> CookieMap;
138 
139 #ifdef WT_TARGET_JAVA
140   /*! \brief %Wt's JavaScript scope.
141    */
javaScriptWtScope()142   static std::string javaScriptWtScope() { return WT_CLASS; }
143 #endif //WT_TARGET_JAVA
144 
145   /*! \brief Parameters passed to the application.
146    *
147    * Arguments passed to the application, either in the URL for a
148    * http GET, or in both the URL and data submitted in a http POST.
149    *
150    * \if cpp
151    * \note The parameter map will be updated when the page is refreshed
152    * (e.g. in non-Ajax sessions and when reload-is-new-session is false),
153    * so you will have to make a copy of values in the parameter map if you want
154    * to preserve them across different requests.
155    * \endif
156    *
157    * \sa getParameterValues()
158    */
getParameterMap()159   const Http::ParameterMap& getParameterMap() const { return parameters_; }
160 
161   /*! \brief Returns values for a query parameter.
162    *
163    * Returns an empty list if the parameter was not defined.
164    *
165    * One or more values may be associated with a single argument.
166    *
167    * For example a %Wt application <tt>foo.wt</tt> started as
168    * <tt>http://.../foo.wt?hello=Hello&hello=World</tt> will result in
169    * both values <tt>"Hello"</tt> and <tt>"World"</tt> to be
170    * associated with the argument <tt>"hello"</tt>.
171    *
172    * \if cpp
173    * \note The parameter map will be updated when the page is refreshed
174    * (e.g. in non-Ajax sessions and when reload-is-new-session is false),
175    * so you will have to make a copy of these values to preserve it across
176    * different requests.
177    * \endif
178    *
179    * \sa getParameterMap()
180    */
181   const Http::ParameterValues& getParameterValues(const std::string& name)
182     const;
183 
184   /*! \brief Returns a single value for a query parameter.
185    *
186    * Returns the first value for a parameter, or \c 0 if the parameter is
187    * not found.
188    *
189    * \if cpp
190    * \note The parameter map will be updated when the page is refreshed
191    * (e.g. in non-Ajax sessions and when reload-is-new-session is false),
192    * so you will have to make a copy of the returned string if you want to
193    * preserve this parameter across different requests.
194    * \endif
195    *
196    * \sa getParameterValues()
197    */
198   const std::string *getParameter(const std::string& name) const;
199 
200   /*! \brief Returns the cookies from the environment.
201    *
202    * This returns all cookies that were present in initial request for
203    * the application. Cookies set with WApplication::setCookie() are
204    * not taken into consideration.
205    *
206    * Cookies allow you to persist information across sessions, but
207    * note that not all clients may support cookies or may some clients
208    * may be configured to block cookies.
209    *
210    * \sa supportsCookies(), getCookie(), getCookieValue()
211    */
cookies()212   const CookieMap& cookies() const { return cookies_; }
213 
214   /*! \brief Returns a cookie value.
215    *
216    * Returns 0 if no value was set for the given cookie.
217    *
218    * \sa getCookie()
219    */
220   const std::string *getCookie(const std::string& cookieName) const;
221 
222   /*! \brief Returns a header value.
223    *
224    * Returns a header value, or an empty string if the header was
225    * present.
226    */
227   const std::string headerValue(const std::string& field) const;
228 
229   /*! \brief Returns whether the browser has enabled support for cookies.
230    *
231    * When the user disables cookies during the visit of the page, this
232    * value is not updated.
233    *
234    * \sa cookies(), getCookie()
235    */
supportsCookies()236   bool supportsCookies() const { return doesCookies_; }
237 
238   /*! \brief Returns whether the browser has enabled support for JavaScript.
239    *
240    * This is the same as ajax(): %Wt only considers using JavaScript
241    * when it has detected AJAX support.
242    *
243    * \sa ajax()
244    */
javaScript()245   bool javaScript() const { return doesAjax_; }
246 
247   /*! \brief Returns whether the browser has enabled support for AJAX.
248    *
249    * Without support for JavaScript/AJAX, %Wt will still be able to
250    * serve the application, but with one considerable limitation: only
251    * the WTimer::timeout(), WInteractWidget::clicked(),
252    * WApplication::internalPathChanged(), and WAbstractArea::clicked()
253    * signals (and any derived signals) will generate events.
254    *
255    * Every event will cause the complete page to be rerendered.
256    *
257    * \sa javaScript()
258    */
ajax()259   bool ajax() const { return doesAjax_; }
260 
261   /*! \brief Returns whether the browser has support for WebGL.
262    *
263    * Support for WebGL is required for client-side rendering of
264    * WGLWidget.
265    */
webGL()266   bool webGL() const { return webGLsupported_; }
267 
268   /*! \brief Returns the horizontal resolution of the client's screen.
269    *
270    * Returns -1 if screen width is not known.
271    *
272    * \sa screenHeight()
273    */
screenWidth()274   int screenWidth() const { return screenWidth_; }
275 
276   /*! \brief Returns the vertical resolution of the client's screen.
277    *
278    * Returns -1 if screen height is not known.
279    *
280    * \sa screenWidth()
281    */
screenHeight()282   int screenHeight() const { return screenHeight_; }
283 
284   /*! \brief Returns the browser-side DPI scaling factor
285    *
286    * Internet Explorer scales all graphics, fonts and other elements
287    * on high-density screens to make them readable. This is controlled
288    * by the DPI setting of the display. If all goes well, you do not
289    * have to worry about this scaling factor. Unfortunately, not
290    * all elements are scaled appropriately. The scaling factor is
291    * supposed to be used only internally in %Wt and is in this interface
292    * for informational purposes.
293    *
294    * \sa WVmlImage
295    */
dpiScale()296   double dpiScale() const { return dpiScale_; }
297 
298   /*! \brief Returns the preferred language indicated in the request
299    *         header.
300    *
301    * The language is parsed from the HTTP <tt>Accept-Language</tt>
302    * field, if present. If not, the locale is empty.
303    *
304    * If multiple languages are present, the one with the highest
305    * "q"uality is assumed, and if a tie is present, the first one
306    * is taken.
307    *
308    * \sa WApplication::setLocale()
309    */
locale()310   const WLocale& locale() const { return locale_; }
311 
312   /*! \brief Returns the time zone offset as reported by the client.
313    *
314    * This returns the time offset that the client has relative to
315    * UTC. A positive value thus means that the local time is ahead of
316    * UTC.
317    *
318    * This requires JavaScript support.
319    *
320    * \sa WLocalDateTime::timeZoneOffset()
321    */
timeZoneOffset()322   std::chrono::minutes timeZoneOffset() const { return timeZoneOffset_; }
323 
324   /*! \brief Returns the time zone name as reported by the client.
325    *
326    * \note This requires JavaScript support and is only supported by
327    * browsers that implement the JavaScript Internationalization API.
328    * No version of Internet Explorer supports this, but modern browsers
329    * do. If not supported, this will return the empty string.
330    */
timeZoneName()331   std::string timeZoneName() const { return timeZoneName_; }
332 
333   /*! \brief Returns the server host name that is used by the client.
334    *
335    * The hostname is the unresolved host name with optional port number,
336    * which the browser used to connect to the application.
337    *
338    * Examples:
339    *   - <tt>www.mydomain.com</tt>
340    *   - <tt>localhost:8080</tt>
341    *
342    * For HTTP 1.1 requests, this information is fetched from the HTTP
343    * <tt>Host</tt> header. If %Wt is configured behind a reverse
344    * proxy, then the last entry in the HTTP <tt>X-Forwarded-Host</tt>
345    * header field is used instead (to infer the name of the reverse
346    * proxy instead).
347    *
348    * For HTTP 1.0 requests, the HTTP <tt>Host</tt> header is not
349    * required. When not present, the server host name is inferred from
350    * the configured server name, which defaults to the DNS name.
351    */
hostName()352   const std::string& hostName() const { return host_; }
353 
354   /*! \brief Returns the URL scheme used for the current request
355    * (<tt>"http"</tt> or <tt>"https"</tt>).
356    */
urlScheme()357   const std::string& urlScheme() const { return urlScheme_; }
358 
359   /*! \brief Returns the user agent.
360    *
361    * The user agent, as reported in the HTTP <tt>User-Agent</tt> field.
362    *
363    * \sa agent()
364    */
userAgent()365   const std::string& userAgent() const { return userAgent_; }
366 
367   /*! \brief Returns the referer.
368    *
369    * The referer, as reported in the HTTP <tt>Referer</tt> field.
370    */
referer()371   const std::string& referer() const { return referer_; }
372 
373   /*! \brief Returns the accept header.
374    *
375    * The accept header, as reported in the HTTP <tt>Accept</tt> field.
376    */
accept()377   const std::string& accept() const { return accept_; }
378 
379   /*! \brief Returns if the user agent is a (known) indexing spider bot.
380    *
381    * Note: currently the list of know bots is quite small. This method
382    * is used internally to render the web application for optimal
383    * indexing by bots:
384    * - there is no detection for JavaScript, instead the application is
385    *   directly served assuming no JavaScript support.
386    * - session information is omitted from the Urls.
387    * - no sessions are created (they are immediately stopped after the request
388    *   has been handled).
389    * - auto-generated <tt>id</tt> and <tt>name</tt> attributes are omitted
390    *   from DOM nodes. In this way, the generated page is always exactly the
391    *   same.
392    */
agentIsSpiderBot()393   bool agentIsSpiderBot() const { return agent_ == UserAgent::BotAgent; }
394 
395   /*! \brief Returns the web server signature.
396    *
397    * The value of the CGI variable <tt>SERVER_SIGNATURE</tt>.
398    *
399    * Example: <tt>&lt;address&gt;Apache Server at localhost Port 80&lt;/address&gt;</tt>.
400    */
serverSignature()401   const std::string& serverSignature() const { return serverSignature_; }
402 
403   /*! \brief Returns the web server software.
404    *
405    * The value of the CGI variable <tt>SERVER_SOFTWARE</tt>.
406    *
407    * Example: <tt>"Apache"</tt>
408    */
serverSoftware()409   const std::string& serverSoftware() const { return serverSoftware_; }
410 
411   /*! \brief Returns the email address of the server admin.
412    *
413    * The value of the CGI variable <tt>SERVER_ADMIN</tt>.
414    *
415    * Example: <tt>"root@localhost"</tt>
416    */
serverAdmin()417   const std::string& serverAdmin() const { return serverAdmin_; }
418 
419   /*! \brief Returns the IP address of the client.
420    *
421    * The (most likely) IP address of the client that is connected to
422    * this session.
423    *
424    * This is taken to be the first public address that is given in the
425    * Client-IP header, or in the X-Forwarded-For header (in case the
426    * client is behind a proxy). If none of these headers is present,
427    * the remote socket IP address is used.
428    */
clientAddress()429   const std::string& clientAddress() const { return clientAddress_; }
430 
431   /*! \brief Returns the initial internal path.
432    *
433    * This is the internal path with which the application was started.
434    *
435    * For an application deployed at <tt>"/stuff/app.wt"</tt>, the following
436    * two URLs are considered equivalent, and indicate an internal path
437    * <tt>"/this/there"</tt>:
438    * \code
439    * http://www.mydomain.com/stuff/app.wt/this/there
440    * http://www.mydomain.com/stuff/app.wt/this/there
441    * \endcode
442    *
443    * \if cpp
444    * For the built-in httpd, when the application is deployed at a folder
445    * (ending with '/'), only an exact matching path is routed to
446    * the application (this can be changed since Wt 3.1.9, see
447    * \ref wthttpd), making clean URLs impossible. Then, also the
448    * following URL is supported (assuming deployment at <tt>"/stuff/"</tt>:
449    * \code
450    * http://www.mydomain.com/stuff/?_=/this/there
451    * \endcode
452    * \endif
453    *
454    * \sa WApplication::setInternalPath(), deploymentPath()
455    */
internalPath()456   const std::string& internalPath() const { return internalPath_; }
457 
458   /*! \brief Returns the deployment path.
459    *
460    * This is the path at which the application is deployed.
461    *
462    * \sa internalPath().
463    */
464   const std::string& deploymentPath() const;
465 
466   /*! \brief Returns the version of the %Wt library.
467    *
468    * Example: <tt>"1.99.2"</tt>
469    */
470   static std::string libraryVersion();
471 
472   /*! \brief Returns the version of the %Wt library, broken down.
473    *
474    * The version of the %Wt library, broken down in its three numbers,
475    *
476    * Example: <i>series</i> = 1, <i>major</i> = 99, \p minor = 2.
477    */
478   void libraryVersion(int& series, int& major, int& minor) const;
479 
480   /*! \brief Returns a raw CGI environment variable.
481    *
482    * Retrieves the value for the given CGI environment variable (like
483    * <tt>"SSL_CLIENT_S_DN_CN"</tt>), if it is defined, otherwise an
484    * empty string.
485    *
486    * \sa serverSignature(), serverSoftware(), serverAdmin(),
487    */
488   std::string getCgiValue(const std::string& varName) const;
489 
490   /*! \brief The type of the content provided to the browser.
491    *
492    * This is here for backwards compatibility, but the implementation now
493    * alwasy returns HTML5.
494    */
contentType()495   HtmlContentType contentType() const { return HtmlContentType::HTML5; }
496 
497   /*! \brief Returns the user agent type.
498    *
499    * This returns an interpretation of the userAgent(). It should be
500    * used only for user-agent specific work-arounds (as a last
501    * resort).
502    *
503    * \sa agentIsIE(), agentIsOpera(), agentIsGecko(), agentIsChrome(),
504    *     agentIsSafari(), agentIsWebKit()
505    */
agent()506   UserAgent agent() const { return agent_; }
507 
508   /*! \brief Returns whether the user agent is Microsoft Internet Explorer.
509    *
510    * \sa agent()
511    */
agentIsIE()512   bool agentIsIE() const {
513     return static_cast<unsigned int>(agent_) >=
514       static_cast<unsigned int>(UserAgent::IEMobile) &&
515       static_cast<unsigned int>(agent_) <
516 	static_cast<unsigned int>(UserAgent::Opera);
517   }
518 
519   /*! \brief Returns whether the user agent is an older version of IE
520    *
521    * Returns whether the agent is an IE version older than the given version.
522 
523    * \sa agentIsIE()
524    */
agentIsIElt(int version)525   bool agentIsIElt(int version) const {
526     if (agentIsIE())
527       return static_cast<unsigned int>(agent_) <
528 	static_cast<unsigned int>(UserAgent::IEMobile) + (version - 5);
529     else
530       return false;
531   }
532 
533   /*! \brief Returns whether the user agent is Internet Explorer Mobile.
534    *
535    * Returns also \c true when the agent is Internet Explorer 5 or older.
536    *
537    * \sa agent()
538    */
agentIsIEMobile()539   bool agentIsIEMobile() const {
540     return agent_ == UserAgent::IEMobile;
541   }
542 
543   /*! \brief Returns whether the user agent is Opera.
544    *
545    * \sa agent()
546    */
agentIsOpera()547   bool agentIsOpera() const {
548     return static_cast<unsigned int>(agent_) >=
549       static_cast<unsigned int>(UserAgent::Opera) &&
550       static_cast<unsigned int>(agent_) <
551 	static_cast<unsigned int>(UserAgent::Safari);
552   }
553 
554   /*! \brief Returns whether the user agent is WebKit-based.
555    *
556    * Webkit-based browsers include Safari, Chrome, Arora and Konquerer
557    * browsers.
558    *
559    * \sa agent()
560    */
agentIsWebKit()561   bool agentIsWebKit() const {
562     return static_cast<unsigned int>(agent_) >=
563       static_cast<unsigned int>(UserAgent::WebKit) &&
564       static_cast<unsigned int>(agent_) <
565 	static_cast<unsigned int>(UserAgent::Konqueror);
566   }
567 
568    /*! \brief Returns whether the user agent is Mobile WebKit-based.
569    *
570    * Mobile Webkit-based browsers include the Android Mobile WebKit
571    * and the iPhone Mobile WebKit browsers.
572    *
573    * \sa agent()
574    */
agentIsMobileWebKit()575   bool agentIsMobileWebKit() const {
576     return static_cast<unsigned int>(agent_) >=
577       static_cast<unsigned int>(UserAgent::MobileWebKit) &&
578       static_cast<unsigned int>(agent_) <
579 	static_cast<unsigned int>(UserAgent::Konqueror);
580   }
581 
582   /*! \brief Returns whether the user agent is Safari.
583    *
584    * \sa agent()
585    */
agentIsSafari()586   bool agentIsSafari() const {
587     return static_cast<unsigned int>(agent_) >=
588       static_cast<unsigned int>(UserAgent::Safari) &&
589       static_cast<unsigned int>(agent_) <
590 	static_cast<unsigned int>(UserAgent::Chrome0);
591   }
592 
593   /*! \brief Returns whether the user agent is Chrome.
594    *
595    * \sa agent()
596    */
agentIsChrome()597   bool agentIsChrome() const {
598     return static_cast<unsigned int>(agent_) >=
599       static_cast<unsigned int>(UserAgent::Chrome0) &&
600       static_cast<unsigned int>(agent_) <
601 	static_cast<unsigned int>(UserAgent::Konqueror);
602   }
603 
604   /*! \brief Returns whether the user agent is Gecko-based.
605    *
606    * Gecko-based browsers include Firefox.
607    *
608    * \sa agent()
609    */
agentIsGecko()610   bool agentIsGecko() const {
611     return static_cast<unsigned int>(agent_) >=
612       static_cast<unsigned int>(UserAgent::Gecko) &&
613       static_cast<unsigned int>(agent_) <
614 	static_cast<unsigned int>(UserAgent::BotAgent);
615   }
616 
617 #ifndef WT_TARGET_JAVA
618   /*! \brief Returns the server.
619    *
620    * This returns the server environment of this session.
621    */
622 #else
623   /*! \brief Returns the servlet.
624    *
625    * This returns the servlet environment of this session.
626    */
627 #endif // WT_TARGET_JAVA
628   WServer *server() const;
629 
630 #ifndef WT_TARGET_JAVA
631   /*! \brief Returns information on the SSL client certificate or \c nullptr
632    *  if no authentication took place.
633    *
634    * This function will return \c nullptr if no verification took place, %Wt
635    * was compiled without SSL support, or the web server was
636    * configured without client SSL certificates.
637    *
638    * This method may return a pointer to a WSslInfo object, while the
639    * authentication may have failed. This depends on the configuration
640    * of the web server. It is therefore important to always check the
641    * verification result with WSslInfo::clientVerificationResult().
642    *
643    * Remember that WEnvironment is 'const', thus the object returned
644    * by this function will represent the SSL information of the
645    * first request for this session. It will not be updated during
646    * the lifetime of the session.
647    *
648    * The object returned is owned by WEnvironment and will be deleted
649    * when WEnvironment is destroyed (= at the end of the session).
650    *
651    * \includedoc ssl_client_headers.dox
652    *
653    * \sa Wt::Http::Request::sslInfo()
654    */
sslInfo()655   WSslInfo *sslInfo() const {
656     return sslInfo_.get();
657   }
658 #endif
659 
660   /*! \brief Returns whether internal paths are implemented using URI fragments.
661    *
662    * This may be the case for older non-HTML5 browsers which do not support
663    * HTML5 History APIs.
664    */
internalPathUsingFragments()665   bool internalPathUsingFragments() const {
666     return internalPathUsingFragments_;
667   }
668 
669   /*! \brief Returns whether this agent supports CSS3 animations.
670    */
671   bool supportsCss3Animations() const;
672 
673   virtual Signal<WDialog *>& dialogExecuted() const;
674   virtual Signal<WPopupMenu *>& popupExecuted() const;
675 
676   /*! \brief Returns whether this is a mocked test environment.
677    */
678   virtual bool isTest() const;
679 
680 protected:
681   WebSession *session_;
682   bool        doesAjax_;
683   bool        doesCookies_;
684   bool        internalPathUsingFragments_;
685   UserAgent   agent_;
686   int         screenWidth_;
687   int         screenHeight_;
688   double      dpiScale_;
689   std::string queryString_;
690   bool        webGLsupported_;
691 
692   Http::ParameterMap parameters_;
693   CookieMap   cookies_;
694 
695   WLocale locale_;
696   std::chrono::minutes timeZoneOffset_;
697   std::string timeZoneName_;
698   std::string host_;
699   std::string userAgent_;
700   std::string urlScheme_;
701   std::string referer_;
702   std::string accept_;
703   std::string serverSignature_;
704   std::string serverSoftware_;
705   std::string serverAdmin_;
706   std::string clientAddress_;
707   std::string pathInfo_;
708   std::string internalPath_;
709   std::string publicDeploymentPath_;
710 
711 #ifndef WT_TARGET_JAVA
712   std::unique_ptr<WSslInfo> sslInfo_;
713 #endif
714 
715   WEnvironment();
716   virtual ~WEnvironment();
717 
718   void setUserAgent(const std::string& agent);
719   void setInternalPath(const std::string& path);
720 
721 private:
722   WEnvironment(WebSession *session);
723 
724   void init(const WebRequest& request);
725   void updateHostName(const WebRequest& request);
726   void updateUrlScheme(const WebRequest& request);
727   void enableAjax(const WebRequest& request);
728 
729   bool agentSupportsAjax() const;
730   static void parseCookies(const std::string& cookie,
731 			   std::map<std::string, std::string>& result);
732 
733   friend class WebController;
734   friend class WebRenderer;
735   friend class WebSession;
736   friend class WApplication;
737   friend class Http::Request;
738 };
739 
740 }
741 
742 #endif // WENVIRONMENT_H_
743