-
Notifications
You must be signed in to change notification settings - Fork 388
Expand file tree
/
Copy pathWApplication.h
More file actions
2507 lines (2329 loc) · 85.5 KB
/
WApplication.h
File metadata and controls
2507 lines (2329 loc) · 85.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// This may look like C code, but it's really -*- C++ -*-
/*
* Copyright (C) 2008 Emweb bv, Herent, Belgium.
*
* See the LICENSE file for terms of use.
*/
#ifndef WAPPLICATION_
#define WAPPLICATION_
#include <vector>
#include <string>
#include <set>
// even boost/poolfwd.hpp includes <windows.h> ...
namespace boost {
struct default_user_allocator_new_delete;
template <typename UserAllocator>
class pool;
}
#include <Wt/WObject.h>
#include <Wt/WCssStyleSheet.h>
#include <Wt/WEvent.h>
#include <Wt/WJavaScriptPreamble.h>
#include <Wt/WJavaScriptSlot.h>
#include <Wt/WLocale.h>
#include <Wt/WMessageResourceBundle.h>
#include <Wt/WSignal.h>
#include <Wt/WString.h>
namespace Wt {
#ifndef WT_TARGET_JAVA
/*
* Symbols used to check that included version matches library version
* against which you link.
*/
struct WtLibVersion { };
extern WT_API const WtLibVersion WT_INCLUDED_VERSION;
#endif
class WApplication;
class WCombinedLocalizedStrings;
class WContainerWidget;
class WEnvironment;
class WEvent;
class WLoadingIndicator;
class WLogEntry;
class WResource;
class WText;
class WebSession;
class RootContainer;
class UpdateLockImpl;
class SoundManager;
/*! \brief Typedef for a function that creates WApplication objects.
*
* \sa WRun()
*
* \relates WApplication
*/
typedef std::function<std::unique_ptr<WApplication> (const WEnvironment&)> ApplicationCreator;
#ifdef WT_TARGET_JAVA
/*! \brief An HTML Meta Header
*/
#endif // WT_TARGET_JAVA
class MetaHeader {
public:
/*! \brief Constructor
*
* Creates a meta header. The lang and user agents are optional, and should
* be an empty string if not used.
*/
MetaHeader(MetaHeaderType type, const std::string& name,
const WString& content, const std::string& lang,
const std::string& userAgent);
MetaHeaderType type;
std::string name, lang, userAgent;
WString content;
};
/*! \class WApplication Wt/WApplication.h Wt/WApplication.h
* \brief Represents an application instance for a single session.
*
* \if cpp
*
* Each user session of your application has a corresponding
* %WApplication instance. You need to create a new instance and return
* it as the result of the callback function passed to WRun(). The
* instance is the main entry point to session information, and holds
* a reference to the root() of the widget tree.
*
* \elseif java
*
* Each user session of your application has a corresponding
* %WApplication instance. You need to create a new instance and return
* it as the result of {javadoclink WtServlet#createApplication(WEnvironment)}.
* The instance is the main entry point to session information,
* and holds a reference to the root() of the widget tree.
*
* \endif
*
* The recipe for a %Wt web application, which allocates new
* WApplication instances for every user visiting the application is
* thus:
*
* \if cpp
* \code
* std::unique_ptr<WApplication> createApplication(const WEnvironment& env)
* {
* //
* // Optionally, check the environment and redirect to an error page.
* //
* bool valid = ...;
*
* std::unique_ptr<WApplication> app;
* if (!valid) {
* app = std::make_unique<WApplication>(env);
* app->redirect("error.html");
* app->quit();
* } else {
* // usually you will specialize your application class
* app = std::make_unique<WApplication>(env);
*
* //
* // Add widgets to app->root() and return the application object.
* //
* }
*
* return app;
* }
* \endcode
* \elseif java
* \code
* public class HelloServlet extends WtServlet {
* public HelloServlet() {
* super();
* }
*
* public WApplication createApplication(WEnvironment env) {
* // In practice, you will specialize WApplication and simply
* // return a new instance.
* WApplication app = new WApplication(env);
* app.getRoot().addWidget(new WText("Hello world."));
* return app;
* }
* }
* \endcode
* \endif
*
* \if cpp
*
* Throughout the session, the instance is available through
* WApplication::instance() (or through #wApp). The application may be
* exited either using the method quit(), or because of a timeout
* after the user has closed the window, but not because the user does
* not interact: keep-alive messages in the background will keep the
* session around as long as the user has the page opened. In either
* case, the application object is deleted, allowing for cleanup of
* the entire widget tree, and any other resources.
*
* \elseif java
*
* Throughout the session, the instance is available through the
* static method WApplication::instance(), which uses thread-specific
* storage to keep track of the current session. The application may
* be exited either using the method quit(), or because of a timeout
* after the user has closed the window, but not because the user does
* not interact: keep-alive messages in the background will keep the
* session around as long as the user has the page opened.
*
* \endif
*
* The %WApplication object provides access to session-wide settings, including:
*
* - circumstantial information through environment(), which gives
* details about the user, start-up arguments, and user agent
* capabilities.
* - the application title with setTitle().
* - inline and external style sheets using styleSheet() and
* useStyleSheet().
* - inline and external JavaScript using doJavaScript() and require().
* - the top-level widget in root(), representing the entire browser window,
* or multiple top-level widgets using bindWidget() when deployed in
* EntryPointType::WidgetSet mode to manage a number of widgets within a 3rd party page.
* - definition of cookies using setCookie() to persist information across
* sessions, which may be read using WEnvironment::getCookie() in a future
* session.
* - management of the internal path (that enables browser history and
* bookmarks) using setInternalPath() and related methods.
* - support for server-initiated updates with enableUpdates()
* \if cpp
* - localization information and message resources bundles using setLocale()
* and messageResourceBundle().
* \elseif java
* - localization information and message resources bundles, with
* setLocale() and setLocalizedStrings()
* \endif
*/
class WT_API WApplication : public WObject
{
public:
/*! \brief Typedef for a function that creates WApplication objects.
*
* \sa WRun()
*/
typedef Wt::ApplicationCreator ApplicationCreator;
/*! \brief Creates a new application instance.
*
* The \p environment provides information on the initial request,
* user agent, and deployment-related information.
*/
#if defined(DOXYGEN_ONLY) || defined(WT_TARGET_JAVA)
WApplication(const WEnvironment& environment);
#else
WApplication(const WEnvironment& environment,
WtLibVersion version = WT_INCLUDED_VERSION);
#endif
#ifndef WT_TARGET_JAVA
/*! \brief Destructor.
*
* The destructor deletes the root() container, and as a consequence
* the entire widget tree.
*/
~WApplication();
#endif // WT_TARGET_JAVA
/*! \brief Returns the current application instance.
*
* \if cpp
* This is the same as the global define #wApp. In a multi-threaded server,
* this method uses thread-specific storage to fetch the current session.
* \elseif java
* This method uses thread-specific storage to fetch the current session.
* \endif
*/
static WApplication *instance();
/*! \brief Returns the environment information.
*
* This method returns the environment object that was used when
* constructing the application. The environment provides
* information on the initial request, user agent, and
* deployment-related information.
*
* \sa url(), sessionId()
*/
const WEnvironment& environment() const;
/*! \brief Returns the root container.
*
* This is the top-level widget container of the application, and
* corresponds to entire browser window. The user interface of your
* application is represented by the content of this container.
*
* \if cpp
*
* The %root() widget is only defined when the application manages
* the entire window. When deployed as a \link Wt::EntryPointType::WidgetSet
* EntryPointType::WidgetSet\endlink application, there is no %root() container, and
* \c 0 is returned. Instead, use bindWidget() to bind one or more
* root widgets to existing HTML <div> (or other) elements on
* the page.
*
* \elseif java
*
* The root() widget is only defined when the application manages
* the entire window. When deployed as a \link Wt::EntryPointType::WidgetSet
* EntryPointType::WidgetSet\endlink application, there is no %root() container, and
* <code>null</code> is returned. Instead, use bindWidget() to bind
* one or more root widgets to existing HTML <div> (or other)
* elements on the page.
*
* \endif
*/
WContainerWidget *root() const { return widgetRoot_; }
/*! \brief Finds a widget by name.
*
* This finds a widget in the application's widget hierarchy. It
* does not only consider widgets in the root(), but also widgets
* that are placed outside this root, such as in dialogs, or other
* "roots" such as all the bound widgets in a widgetset application.
*
* \sa WWidget::setObjectName(), WWidget::find()
*/
WWidget *findWidget(const std::string& name);
/** @name Style sheets and CSS
*/
//!@{
/*! \brief Returns a reference to the inline style sheet.
*
* Widgets may allow configuration of their look and feel through
* style classes. These may be defined in this inline stylesheet, or
* in external style sheets.
*
* It is usually preferable to use external stylesheets (and
* consider more accessible). Still, the internal stylesheet has as
* benefit that style rules may be dynamically updated, and it is
* easier to manage logistically.
*
* \sa useStyleSheet()
* \sa WWidget::setStyleClass()
*/
WCssStyleSheet& styleSheet() { return styleSheet_; }
/*! \brief Adds an external style sheet.
*
* The \p link is a link to a stylesheet.
*
* The \p media indicates the CSS media to which this stylesheet
* applies. This may be a comma separated list of media. The default
* value is "all" indicating all media.
*
* This is an overloaded method for convenience, equivalent to:
* \code
* useStyleSheet(Wt::WCssStyleSheet(link, media))
* \endcode
*/
void useStyleSheet(const WLink& link, const std::string& media = "all");
/*! \brief Conditionally adds an external style sheet.
*
* This is an overloaded method for convenience, equivalent to:
* \code
* useStyleSheet(Wt::WLinkedCssStyleSheet(link, media), condition)
* \endcode
*/
void useStyleSheet(const WLink& link, const std::string& condition,
const std::string& media);
/*! \brief Adds an external stylesheet.
*
* Widgets may allow configuration of their look and feel through
* style classes. These may be defined in an inline stylesheet,
* or in external style sheets.
*
* External stylesheets are inserted after the internal style sheet,
* and can therefore override default styles set by widgets in the
* internal style sheet.
* External stylesheets must have valid link.
*
* If not empty, \p condition is a string that is used to apply the
* stylesheet to specific versions of IE. Only a limited subset of
* the IE conditional comments syntax is supported (since these are
* in fact interpreted server-side instead of client-side). Examples
* are:
*
* - "IE gte 6": only for IE version 6 or later.
* - "!IE gte 6": only for IE versions prior to IE6.
* - "IE lte 7": only for IE versions prior to IE7.
*
* \sa styleSheet(), useStyleSheet(const std::string&, const std::string&),
* removeStyleSheet(const WLink& link)
* \sa WWidget::setStyleClass()
*/
void useStyleSheet(const WLinkedCssStyleSheet& styleSheet,
const std::string& condition = "");
/*! \brief Removes an external stylesheet.
*
* \sa styleSheet(), useStyleSheet(const std::string&, const std::string&)
* \sa WWidget::setStyleClass()
*/
void removeStyleSheet(const WLink& link);
/*! \brief Sets the theme.
*
* The theme provides the look and feel of several built-in widgets,
* using CSS style rules. Rules for each theme are defined in the
* <tt>resources/themes/</tt><i>theme</i><tt>/</tt> folder.
*
* The default theme is "default" CSS theme.
*/
void setTheme(const std::shared_ptr<WTheme>& theme);
/*! \brief Returns the theme.
*/
std::shared_ptr<WTheme> theme() const { return theme_; }
/*! \brief Sets a CSS theme.
*
* This sets a WCssTheme as theme.
*
* The theme provides the look and feel of several built-in widgets,
* using CSS style rules. Rules for each CSS theme are defined in
* the <tt>resources/themes/</tt><i>name</i><tt>/</tt> folder.
*
* The default theme is "default". Setting an empty theme "" will
* result in a stub CSS theme that does not load any stylesheets.
*/
void setCssTheme(const std::string& name);
/*! \brief Sets the layout direction.
*
* The default direction is LayoutDirection::LeftToRight.
*
* This sets the language text direction, which by itself sets the
* default text alignment and reverse the column orders of <table>
* elements.
*
* In addition, %Wt will take this setting into account in
* WTextEdit, WTableView and WTreeView (so that columns are
* reverted), and swap the behaviour of WWidget::setFloatSide() and
* WWidget::setOffsets() for LayoutDirection::RightToLeft
* languages. Note that CSS settings themselves are not affected by
* this setting, and thus for example <tt>"float: right"</tt> will
* move a box to the right, irrespective of the layout direction.
*
* The library sets <tt>"Wt-ltr"</tt> or <tt>"Wt-rtl"</tt> as style
* classes for the document body. You may use this if to override
* certain style rules for a Right-to-Left document.
*
* The only valid values are LayoutDirection::LeftToRight or
* LayoutDirection::RightToLeft.
*
* For example:
* \code
* body .sidebar { float: right; }
* body.Wt-rtl .sidebar { float: left; }
* \endcode
*
* \note The layout direction can be set only at application startup
* and does not have the effect of rerendering the entire UI.
*/
void setLayoutDirection(LayoutDirection direction);
/*! \brief Returns the layout direction.
*
* \sa setLayoutDirection()
*/
LayoutDirection layoutDirection() const { return layoutDirection_; }
/*! \brief Sets a style class to the entire page <body>.
*
* \sa setHtmlClass()
*/
void setBodyClass(const std::string& styleClass);
/*! \brief Returns the style class set for the entire page <body>.
*
* \sa setBodyClass()
*/
std::string bodyClass() const { return bodyClass_; }
/*! \brief Sets a style class to the entire page <html>.
*
* \sa setBodyClass()
*/
void setHtmlClass(const std::string& styleClass);
/*! \brief Returns the style class set for the entire page <html>.
*
* \sa setHtmlClass()
*/
std::string htmlClass() const { return htmlClass_; }
//!@}
/*! \brief Sets the window title.
*
* Sets the browser window title to \p title.
*
* The default title is "".
*
* \sa title()
*/
void setTitle(const WString& title);
/*! \brief Returns the window title.
*
* \sa setTitle(const WString&)
*/
const WString& title() const { return title_; }
/*! \brief Returns the close message.
*
* \sa setConfirmCloseMessage()
*/
const WString& closeMessage() const { return closeMessage_; }
/*! \brief Returns the resource object that provides localized strings.
*
* \if cpp
* The default value is a WMessageResourceBundle instance, which
* uses XML files to resolve localized strings, but you can set a
* custom class using setLocalizedStrings().
* \elseif java
* This returns the object previously set using setLocalizedStrings().
* \endif
*
* WString::tr() is used to create localized strings, whose
* localized translation is looked up through this object, using a
* key.
*
* \if cpp
* \sa WString::tr(), messageResourceBundle()
* \elseif java
* \sa WString::tr()
* \endif
*/
std::shared_ptr<WLocalizedStrings> localizedStrings();
#ifdef WT_TARGET_JAVA
/*! \brief Accesses the built-in resource bundle.
*
* This is an internal function and should not be called directly.
*
* \sa localizedStrings()
*/
#endif // WT_TARGET_JAVA
WMessageResourceBundle& builtinLocalizedStrings();
/*! \brief Sets the resource object that provides localized strings.
*
* The \p translator resolves localized strings within the current
* application locale.
*
* \sa localizedStrings(), WString::tr(const char *key)
*/
void setLocalizedStrings(const std::shared_ptr<WLocalizedStrings>&
stringResolver);
#ifndef WT_TARGET_JAVA
/*! \brief Returns the message resource bundle.
*
* The message resource bundle defines the list of external XML
* files that are used to lookup localized strings.
*
* The default localizedStrings() is a WMessageResourceBundle
* object, and this method returns localizedStrings() downcasted to
* this type.
*
* \throws WException when localizedStrings() is not a WMessageResourceBundle
*
* \sa WString::tr(const char *key)
*/
WMessageResourceBundle& messageResourceBundle();
#endif // WT_TARGET_JAVA
/*! \brief Changes the locale.
*
* The locale is used by the localized strings resource to resolve
* localized strings.
*
* By passing an empty \p locale, the default locale is
* chosen.
*
* When the locale is changed, refresh() is called, which will
* resolve the strings of the current user-interface in the new
* locale.
*
* At construction, the locale is copied from the environment
* (WEnvironment::locale()), and this is the locale that was
* configured by the user in his browser preferences, and passed
* using an HTTP request header.
*
* \sa localizedStrings(), WString::tr()
*/
void setLocale(const WLocale& locale);
/*! \brief Returns the current locale.
*
* \sa setLocale(const WLocale&)
*/
const WLocale& locale() const { return locale_; }
/*! \brief Refreshes the application.
*
* This lets the application refresh its data, including strings
* from message resource bundles. This is done by propagating
* WWidget::refresh() through the widget hierarchy.
*
* This method is also called when the user hits the refresh (or
* reload) button, if this can be caught within the current session.
*
* \if cpp
*
* The reload button may only be caught when %Wt is configured so that
* reload should not spawn a new session. When URL rewriting is used for
* session tracking, this will cause an ugly session ID to be added to the
* URL. See \ref config_session for configuring the reload
* behavior ("<reload-is-new-session>").
*
* \elseif java
*
* The reload button may only be caught when cookies for session
* tracking are configured in the servlet container.
*
* \endif
*
* \sa WWidget::refresh()
*/
virtual void refresh();
/*! \brief Binds a top-level widget for a EntryPointType::WidgetSet deployment.
*
* This method binds a \p widget to an existing element with DOM id
* \p domId on the page. The element type should correspond with
* the widget type (e.g. it should be a <div> for a
* WContainerWidget, or a <table> for a WTable).
*
* \sa root()
* \sa Wt::EntryPointType::WidgetSet
*/
void bindWidget(std::unique_ptr<WWidget> widget, const std::string& domId);
/** @name URLs and internal paths
*/
//!@{
/*! \brief Returns a URL for the current session
*
* Returns the (relative) URL for this application session
* (including the session ID if necessary). The URL includes the
* full application path, and is expanded by the browser into a full
* URL.
*
* For example, for an application deployed at \code
* http://www.mydomain.com/stuff/app.wt \endcode this method might
* return <tt>"/stuff/app.wt?wtd=AbCdEf"</tt>. Additional query
* parameters can be appended in the form of
* <tt>"¶m1=value¶m2=value"</tt>.
*
* To obtain a URL that is suitable for bookmarking the current
* application state, to be used across sessions, use bookmarkUrl()
* instead.
*
* \sa redirect(), WEnvironment::hostName(), WEnvironment::urlScheme()
* \sa bookmarkUrl()
*/
std::string url(const std::string& internalPath = std::string()) const;
/*! \brief Makes an absolute URL.
*
* Returns an absolute URL for a given (relative url) by including
* the schema, hostname, and deployment path.
*
* If \p url is "", then the absolute base URL is returned. This is
* the absolute URL at which the application is deployed, up to the
* last '/'.
*
* The default implementation is not complete: it does not handle relative
* URL path segments with '..'. It just handles the cases that are necessary for
* %Wt.
*
* This is not used in the library, except when a public URL is
* needed, e.g. for inclusion in an email.
*
* You may want to reimplement this method when the application is
* hosted behind a reverse proxy or in general the public URL of the
* application cannot be guessed correctly by the application.
*/
virtual std::string makeAbsoluteUrl(const std::string& url) const;
/*! \brief "Resolves" a relative URL taking into account internal paths.
*
* This resolves the relative URL against the base path of the application,
* so that it will point to the correct path regardless of the current internal
* path, e.g. if the application is deployed at <tt>%http://example.com/one</tt>
* and we're at the internal path <tt>/two/</tt>, so that the full URL is
* <tt>%http://example.com/one/two/</tt>, the output of the input URL <tt>three</tt>
* will point to <tt>%http://example.com/three</tt>, and not
* <tt>%http://example.com/one/two/three</tt>.
*
* If the given url is the empty string, the result will point to the base path
* of the application.
*
* See the table below for more examples.
*
* <h3>When you would want to use resolveRelativeUrl:</h3>
*
* Using HTML5 History API or in a plain HTML session (without ugly
* internal paths), the internal path is present as a full part of
* the URL. This has a consequence that relative URLs, if not dealt
* with, would be resolved against the last 'folder' name of the
* internal path, rather than against the application deployment
* path (which is what you probably want).
*
* When using a widgetset mode deployment, or when configuring a
* baseURL property in the configuration, this method will make an
* absolute URL so that the property is fetched from the right
* server.
*
* Otherwise, this method will fixup a relative URL so that it
* resolves correctly against the base path of an application. This
* does not necessarily mean that the URL is resolved into an
* absolute URL. In fact, %Wt will simply prepend a sequence of "../"
* path elements to correct for the internal path. When passed an
* absolute URL (i.e. starting with '/'), the url is returned
* unchanged.
*
* For URLs passed to the %Wt API (and of which the library knows it
* represents a URL) this method is called internally by the
* library. But it may be useful for URLs which are set e.g. inside
* a WTemplate.
*
* <h3>Examples</h3>
*
* Note that whether the deployment path and entry point ends with a slash is significant.
* Below are some examples with the
* <span style="color:red;">deployment path</span> in <span style="color:red;">red</span>
* and the <span style="color:blue;">internal path</span> in <span style="color:blue;">blue</span>.
*
* <table>
* <tr><th>Current full path</th><th>url argument</th><th>Result points to</th></tr>
* <tr><td rowspan="4"><tt>%http://example.com</tt><tt style="color:red;">/foo/bar</tt><tt style="color:blue;">/internal/path</tt><br />Deployment path: <tt style="color:red;">/foo/bar</tt> (no slash at the end)<br />Internal path: <tt style="color:blue;">/internal/path</tt></td>
* <td><i>(empty string)</i></td><td><tt>%http://example.com/foo/bar</tt></tr>
* <tr><td><tt>.</tt></td><td><tt>%http://example.com/foo/</tt></td></tr>
* <tr><td><tt>./</tt></td><td><tt>%http://example.com/foo/</tt></td></tr>
* <tr><td><tt>../</tt></td><td><tt>%http://example.com/</tt></td></tr>
* <tr><td rowspan="4"><tt>%http://example.com</tt><tt style="color:red;">/foo/bar</tt><tt style="color:magenta;font-weight:bold;">/</tt><tt style="color:blue;">internal/path</tt><br />Deployment path: <tt style="color:red;">/foo/bar/</tt> (with slash at the end)<br />Internal path: <tt style="color:blue;">/internal/path</tt><br />Note that the slash between the deployment path and the internal path is shared</td>
* <td><i>(empty string)</i></td><td><tt>%http://example.com/foo/bar/</tt></tr>
* <tr><td><tt>.</tt></td><td><tt>%http://example.com/foo/bar/</tt></td></tr>
* <tr><td><tt>./</tt></td><td><tt>%http://example.com/foo/bar/</tt></td></tr>
* <tr><td><tt>../</tt></td><td><tt>%http://example.com/foo/</tt></td></tr>
* </table>
*/
std::string resolveRelativeUrl(const std::string& url) const;
/*! \brief Returns a bookmarkable URL for the current internal path.
*
* Is equivalent to <tt>bookmarkUrl(internalPath())</tt>, see
* bookmarkUrl(const std::string&) const.
*
* To obtain a URL that is refers to the current session of the
* application, use url() instead.
*
* \sa url(), bookmarkUrl(const std::string&) const
*/
std::string bookmarkUrl() const;
/*! \brief Returns a bookmarkable URL for a given internal path.
*
* Returns the (relative) URL for this application that includes the
* internal path \p internalPath, usable across sessions.
*
* The returned URL concatenates the internal path to the application
* base URL, and when no JavaScript is available and URL rewriting is used
* for session-tracking, a session Id is appended to reuse an existing
* session if available.
*
* \if cpp
* See also \ref config_session for configuring the session-tracking
* method.
*
* For the built-in httpd, when the application is deployed at a folder
* (ending with '/'), only an exact matching path is routed to
* the application (this can be changed since Wt 3.1.9, see
* \ref wthttpd ), making clean URLs impossible. Returned URLs then
* include a <tt>"?_="</tt> encoding for the internal path.
* \endif
*
* You can use bookmarkUrl() as the destination for a WAnchor, and
* listen to a click event is attached to a slot that switches to
* the internal path \p internalPath (see
* WAnchor::setRefInternalPath()). In this way, an anchor can be
* used to switch between internal paths within an application
* regardless of the situation (browser with or without Ajax
* support, or a web spider bot), but still generates suitable URLs
* across sessions, which can be used for bookmarking, opening in a
* new window/tab, or indexing.
*
* To obtain a URL that refers to the current session of the
* application, use url() instead.
*
* \sa url(), bookmarkUrl()
*
* \if cpp
* \note the \p internalPath should be CharEncoding::UTF8 encoded (we may fix the API
* to use WString in the future).
* \endif
*/
std::string bookmarkUrl(const std::string& internalPath) const;
/*! \brief Changes the internal path.
*
* A %Wt application may manage multiple virtual paths. The virtual
* path is appended to the application URL. Depending on the
* situation, the path is directly appended to the application URL
* or it is appended using a name anchor (#).
*
* For example, for an application deployed at:
* \code
* http://www.mydomain.com/stuff/app.wt
* \endcode
* for which an \p internalPath <tt>"/project/z3cbc/details/"</tt> is
* set, the two forms for the application URL are:
* <ul>
* <li> in an AJAX session (HTML5):
* \code
* http://www.mydomain.com/stuff/app.wt/project/z3cbc/details/
* \endcode
* </li><li> in an AJAX session (HTML4):
* \code
* http://www.mydomain.com/stuff/app.wt#/project/z3cbc/details/
* \endcode
* </li><li>
* in a plain HTML session:
* \code
* http://www.mydomain.com/stuff/app.wt/project/z3cbc/details/
* \endcode
* </li></ul>
*
* Note, since %Wt 3.1.9, the actual form of the URL no longer
* affects relative URL resolution, since now %Wt includes an HTML
* <tt>meta base</tt> tag which points to the deployment path,
* regardless of the current internal path. This does break
* deployments behind a reverse proxy which changes paths.
*
* \if cpp
* For the built-in httpd, when the application is deployed
* at a folder (ending with '/'), only an exact matching path is
* routed to the application (this can be changed since Wt 3.1.9,
* see \ref wthttpd ), making clean URLs impossible. Returned
* URLs then include a <tt>"?_="</tt> encoding for the internal
* path:
*
* \code
* http://www.mydomain.com/stuff/?_=/project/z3cbc/details/
* \endcode
* \endif
*
* When the internal path is changed, an entry is added to the
* browser history. When the user navigates back and forward through
* this history (using the browser back/forward buttons), an
* internalPathChanged() event is emitted. You should listen to this
* signal to switch the application to the corresponding state. When
* \p emitChange is \c true, this signal is also emitted by setting
* the path (but only if the path is actually changed).
*
* A url that includes the internal path may be obtained using
* bookmarkUrl().
*
* The \p internalPath must start with a '/'. In this way, you
* can still use normal anchors in your HTML. Internal path changes
* initiated in the browser to paths that do not start with a '/'
* are ignored.
*
* The \p emitChange parameter determines whether calling this
* method causes the internalPathChanged() signal to be emitted.
*
* \sa bookmarkUrl(), internalPath(), internalPathChanged()
*
* \if cpp
* \note the \p path should be CharEncoding::UTF8 encoded (we may fix the API
* to use WString in the future).
* \endif
*/
void setInternalPath(const std::string& path, bool emitChange = false);
/*! \brief Sets whether an internal path is valid by default.
*
* This configures how you treat (invalid) internal paths. If an
* internal path is treated valid by default then you need to call
* setInternalPath(false) for an invalid path. If on the other hand
* you treat an internal path as invalid by default, then you need
* to call setInternalPath(true) for a valid path.
*
* A user which opens an invalid internal path will receive a HTTP
* 404-Not Found response code (if sent an HTML response).
*
* The default value is \c true.
*/
void setInternalPathDefaultValid(bool valid);
/*! \brief Returns whether an internal path is valid by default.
*
* \sa setInternalPathDefaultValid()
*/
bool internalPathDefaultValid() const { return internalPathDefaultValid_; }
/*! \brief Sets whether the current internal path is valid.
*
* You can use this function in response to an internal path change
* event (or at application startup) to indicate whether the new (or
* initial) internal path is valid. This has only an effect on plain
* HTML sessions, or on the first response in an application
* deployed with progressive bootstrap settings, as this generates
* then a 404 Not-Found response.
*
* \sa internalPathChanged(), setInternalPathDefaultValid()
*/
void setInternalPathValid(bool valid);
/*! \brief Returns whether the current internal path is valid.
*
* \sa setInternalPathValid()
*/
bool internalPathValid() const { return internalPathValid_; }
/*! \brief Returns the current internal path.
*
* When the application is just created, this is equal to
* WEnvironment::internalPath().
*
* \sa setInternalPath(), internalPathNextPart(), internalPathMatches()
*
* \if cpp
* \note the \p returned path is CharEncoding::UTF8 (we may fix the API
* to use WString in the future).
* \endif
*/
std::string internalPath() const;
/*! \brief Returns a part of the current internal path.
*
* This is a convenience method which returns the next \p folder
* in the internal path, after the given \p path.
*
* For example, when the current internal path is
* <tt>"/project/z3cbc/details"</tt>, this method returns
* <tt>"details"</tt> when called with <tt>"/project/z3cbc/"</tt> as
* \p path argument.
*
* The \p path must start with a '/', and internalPathMatches()
* should evaluate to \c true for the given \p path. If not,
* an empty string is returned and an error message is logged.
*
* \sa internalPath(), internalPathChanged()
*
* \if cpp
* \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API
* to use WString in the future).
* \endif
*/
std::string internalPathNextPart(const std::string& path) const;
std::string internalSubPath(const std::string& path) const;
/*! \brief Checks if the internal path matches a given path.
*
* Returns whether the current internalPath() starts with
* \p path (or is equal to \p path). You will typically use
* this method within a slot conneted to the internalPathChanged()
* signal, to check that an internal path change affects the
* widget. It may also be useful before changing \p path using
* setInternalPath() if you do not intend to remove sub paths when
* the current internal path already matches \p path.
*
* The \p path must start with a '/'.
*
* \sa setInternalPath(), internalPath()
*
* \if cpp
* \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API
* to use WString in the future).
* \endif
*/
bool internalPathMatches(const std::string& path) const;
/*! \brief %Signal which indicates that the user changes the internal path.
*
* This signal indicates a change to the internal path, which is
* usually triggered by the user using the browser back/forward
* buttons.
*
* The argument contains the new internal path.
*
* \sa setInternalPath()
*
* \if cpp
* \note the \p internal path is CharEncoding::UTF8 encoded (we may fix the API
* to use WString in the future).
* \endif
*/
Signal<std::string>& internalPathChanged();
/*! \brief %Signal which indicates that an invalid internal path is navigated.
*/
Signal<std::string>& internalPathInvalid() { return internalPathInvalid_; }
/*! \brief Redirects the application to another location.
*
* The client will be redirected to a new location identified by \p
* url. Use this in conjunction with quit() if you want the
* application to be terminated as well.
*
* Calling %redirect() does not imply %quit() since it may be useful
* to switch between a non-secure and secure (SSL) transport
* connection.
*/
void redirect(const std::string& url);
//!@}
/*! \brief Returns the URL at which the resources are deployed.
*
* Returns resolveRelativeUrl(relativeResourcesUrl())
*/
static std::string resourcesUrl();
/*! \brief Returns the URL at which the resources are deployed.
*
* \if cpp
* This returns the value of the 'resources' property set in the