http://wiki.overbyte.eu/wiki/api.php?action=feedcontributions&user=Fpiette&feedformat=atomOverbyte - User contributions [en]2024-03-29T08:20:27ZUser contributionsMediaWiki 1.34.0http://wiki.overbyte.eu/wiki/index.php?title=ICS_V8.58&diff=3460ICS V8.582018-12-01T08:33:34Z<p>Fpiette: </p>
<hr />
<div>'''Major changes in ICS V8.58 include:'''<br />
<br />
# Support for OpenSSL 1.1.1 with TLSv1.3, new cryptographic algorithms and ciphers. OpenSSL 1.1.0 and 1.0.2 also supported.<br />
# A new client TSslHttpRest component with Json support for all compilers and integrating cookie, SSL/TLS, content decoding, content compression and logging. There are many THttpCli improvements.<br />
# A new TRestOAuth component for OAuth2 authentication including an integrated local web server.<br />
# JOSE (Json Object Signing and Encryption) components supporting JWT, JWS and JWK.<br />
# Simplified client SSL/TLS security and protocol settings. Support for SSL ALPN extension.<br />
# A new TSslX509Certs component allowing ICS servers to automatically order, download and install SSL/TLS certificates from various suppliers, including free certificates from Let's Encrypt, and commercial certificates for DigiCert, Comodo, Thawte and GeoTrust from CertCentre AG. It also acts as a private CA to issue local certificates.<br />
<br />
== OpenSSL 1.1.1 Support ==<br />
<br />
OpenSSL 1.1.1 is the latest long term support version and adds support<br />
for TLSv1.3 RFC8446 and various new cryptographic private key and hash<br />
digest types. This version will be supported until 2023. OpenSSL 1.1.0<br />
and 1.0.2 also supported by ICS, but 1.1.0 support ceases in September<br />
2019, and 1.0.2 in December 2019. More details of OpenSSL 1.1.1 are at:<br />
https://www.openssl.org/blog/blog/2018/09/11/release111/<br />
<br />
== New HTTPS REST Component ==<br />
<br />
TSslHttpRest descends from THttpCli, and publishes all it's properties<br />
and events with additional methods and properties for making REST<br />
(REpresentional State Transfer) client requests. It also integrates<br />
several other existing components for extra HTTP functionality,<br />
including SSL configuration and certificate validation with a root<br />
bundle, SSL session caching, content compression, content code page<br />
decoding, persistent cookies, Json handling, logging and client SSL<br />
certificate.<br />
<br />
The component uses TRestParams which define a collection of REST<br />
parameters and allows them to be saved as URL encoded or Json. An ICS<br />
version of Super Object Toolkit for Json is included supported by<br />
Delphi 7 and later. Using TSslHttpRest in new applications for HTTP<br />
and HTTPS requires only a few lines of code and no event handlers to<br />
make requests instead of much more code, SSL contexts, extra<br />
components and many event handlers when using THttpCli.<br />
<br />
There is a new sample project OverbyteIcsHttpRestTst to demonstrate<br />
the HTTPS REST and OAuth Components.<br />
<br />
== HTTP Client Improvements ==<br />
<br />
The THttpCli component adds various new properties and events.<br />
ExtraHeaders simplifies adding extra headers to a request (previously<br />
done in the onBeforeHeaderSend event). THttpAuthType adds<br />
httpAuthBearer and httpAuthToken, and AuthBearerToken for OAuth.<br />
Connected is now available as a property. ResponseNoException property<br />
suppresses error exceptions for sync requests, ie most 400 and 500<br />
status codes (eases debugging). ReasonPhrase for abort may return SSL<br />
handshake error. Added OnSelectDns event to allow application to change<br />
DnsResult to one of the several offered, round robin or IPV4/IPV6.<br />
<br />
== New OAuth Component ==<br />
<br />
TRestOAuth is for handling 0Auth authorization to web apps, by several<br />
means. Beware OAuth is really a concept with differing implementations,<br />
so use may not always be straight forward. OAuth1 and 1A were<br />
originally developed for Twitter and use cryptography, OAuth2 is a<br />
simpler and easier to implement version now widely used by most cloud<br />
services without any cryptography (other than SSL).<br />
<br />
The concept of OAuth is that applications should not know any login<br />
details. The login need to be entered through a browser, which then<br />
redirects to a fixed URL which includes an Authorization Code that is<br />
subsequently exchanged for an Access Token that can used by the REST<br />
client. Access Tokens have a limited life and usually expire within<br />
three to 24 hours. To avoid user interaction, the token exchange process<br />
sometimes offers a Refresh Token with the same expiry, but which can be<br />
used to get another Access Token, and this is automatically handled by<br />
TRestOAuth, while it still runs.<br />
<br />
== New Simple Web Server ==<br />
<br />
TSimpleWebSrv is a simple web server primarily designed for accepting<br />
HTTP requests from REST servers which don't expect real pages to be<br />
sent but just application generated responses. It is used by TRestOAuth<br />
to respond to the browser login and by TSslHttpRest for .well-known file<br />
responses generated by from a challenge database.<br />
<br />
== New JOSE functions - Json Object Signing and Encryption ==<br />
<br />
JOSE is used for JWS (Json Web Signing), JWT (Json Web Tokens), JWK<br />
(Json Web Key) and JWE (Json Web Encryption). Variously used by OAuth1,<br />
ACME and other protocols. Creates hash digests using SHA, SHA2, SHA3 and<br />
shake, Keyed-Hash Message Authentication Codes (HMAC) with shared secret<br />
keys, Asymmetric Key-Hash Message Authentication Code (Async MAC) using<br />
private/public keys. Creates Json Web Keys with RSA or EC public or HMAC<br />
keys, and Json Web Signatures to protect headers and payloads.<br />
<br />
There is a new sample project OverbyteIcsJoseTst to demonstrate various<br />
JOSE functions.<br />
<br />
== SSL/TLS security ==<br />
<br />
SslContext has a new property SslCliSecurity which if set to other than<br />
sslCliSecIgnore sets the protocols, security and ciphers to standardised<br />
settings, may be changed without reinitialising the context. This means<br />
client applications can avoid messing with several SSL settings and offer<br />
the user a 'simple' list of security settings. Several are very useful for<br />
testing SSL applications. sslCliSecHigh is recommended.<br />
<br />
sslCliSecIgnore - ignore, use old settings<br />
sslCliSecNone - all protocols and ciphers, any key lengths<br />
sslCliSecSsl3Only - SSLv3 only, all ciphers, any key lengths, MD5<br />
sslCliSecTls1Only - TLSv1 only, all ciphers, RSA/DH keys=>2048<br />
sslCliSecTls11Only - TLSv1.1 only, all ciphers, RSA/DH keys=>2048<br />
sslCliSecTls12Only - TLSv1.2 only, all ciphers, RSA/DH keys=>2048<br />
sslCliSecTls13Only - TLSv1.3 only, all ciphers, RSA/DH keys=>2048<br />
sslCliSecTls1 - TLSv1 or later, all ciphers, RSA/DH keys=>1024<br />
sslCliSecTls11 - TLSv1.1 or later, all ciphers, RSA/DH keys=>1024<br />
sslCliSecTls12 - TLSv1.2 or later, all ciphers, RSA/DH keys=>2048<br />
sslCliSecBack - TLSv1 or later, backward ciphers, RSA/DH keys=>1024, ECC=>160, no MD5, SHA1<br />
sslCliSecInter - TLSv1.1 or later, intermediate ciphers, RSA/DH keys=>2048, ECC=>224, no RC4, no SHA1 certs<br />
sslCliSecHigh - TLSv1.2 or later, high ciphers, RSA/DH keys=>2048, ECC=>224, no RC4, no SHA1 certs<br />
sslCliSecHigh128 - TLSv1.2 or later, high ciphers, RSA/DH keys=>3072, ECC=>256, FS forced<br />
sslCliSecHigh192 - TLSv1.2 or later, high ciphers, RSA/DH keys=>7680, ECC=>384, FS forced<br />
sslCliSecDefault - currently equal to sslCliSecTls11 but will change soon to sslCliSecHigh when TLSv1.1 is deprecated.<br />
<br />
Note there is also SslSrvSecurity as part of IcsHosts which sets<br />
similar security levels for servers.<br />
<br />
SSL Application Layer Protocol Negotiation (ALPN) is an extension which<br />
is sent with the initial SSL hello. For clients, SslAlpnProtocols sets<br />
SslContext with a list of protocols the application supports (ie<br />
http/1.1, h2), and SslGetAlpnProtocol after connection returns whatever<br />
the server selected (if any). For servers, there is a OnSslAlpnSelect<br />
event that has the list of protocols from the client, from which one<br />
may be selected (ie H2 to support HTTP/2).<br />
<br />
== Automatic SSL/TLS certificates ==<br />
<br />
The TSslX509Certs component will automatically download SSL/TLS X509<br />
certificates from various suppliers, including free certificates from<br />
Let's Encrypt, and commercial certificates for Digicert, Comodo, Thawte<br />
and GeoTrust from CertCentre AG and Servertastic (not done yet). It<br />
also acts as a private CA to issue local certificates.<br />
<br />
The component automates the process from creating a new private key and<br />
certificate request, placing the order, arranging for domain validated<br />
certificates to be checked by various challenge methods, collecting the<br />
certificate and intermediate, creating PEM and PKC12 bundle files with<br />
the private key, then copying the files to the web server ready for<br />
automatic installation. Ordering wildcard and multiple SAN<br />
certificates is fully supported.<br />
<br />
The component includes a database of certificate orders and pending<br />
challenges, allowing certificates to be re-ordered and the supplier<br />
periodically checked to see if a challenge has been successful when<br />
the X509 certificate can be automatically downloaded and installed.<br />
Events are generated upon completion or failure, allowing the<br />
application to inform the user (by email) of certificate ordering<br />
progress.<br />
<br />
The component supports automated file challenge for Domain Validated<br />
certificates, using an external HTTP server such as IIS or HTTP server<br />
component such as TSslHttpServer or TSslHttpAppSrv to which files may<br />
be copied using UNC shares, or a built-in local HTTP server so the<br />
component is self contained. In all cases, the web server must be<br />
accessible from the public internet for the domain (or domains) for<br />
which a certificate is being ordered. The application can also use<br />
an FTP server to copy files to an external HTTP server. DNS challenge<br />
currently require the application to update the DNS server, the demo<br />
application waits a few minutes for the user to manually update the DNS<br />
server which allows wild card certificates to be ordered. A pending<br />
feature is TLS-ALPN SSL SNI challenges for Let's Encrypt using HTTPS.<br />
<br />
The component supports the ACME V1 and V2 protocols as implemented by<br />
Let's Encrypt to download free domain validated certificates, beware<br />
V1 bears little resemblance to any of the Acme Internet Draft<br />
specifications, V2 is much closer to draft 10 but only implemented<br />
sufficiently for Let's Encrypt, V2 is designed to also handle<br />
commercial certificates which are more complicated to process. Acme<br />
V1 has been superseded by V2, and was only supported because V2 did<br />
not go public until March 2018.<br />
<br />
You don't need to register with Let's Encrypt, but it only supplies<br />
domain validated certificates so the domains for which you order<br />
certificates must already be registered and have DNS pointing to a<br />
live HTTP server to satisfy the domain challenge.<br />
<br />
Commercial suppliers of certificates have their own APIs, usually using<br />
HTTP REST, currently the component supports CertCentre AG at<br />
https://www.certcenter.de/, https://www.certcenter.co.uk/ or<br />
https://www.certcenter.com/ from where you can buy certificates issued<br />
by Comondo, DigiCert (including GeoTrust, Symantec and Thawte) and<br />
GlobalSign, and free certificates from AlwaysOnSSL (by resellers only),<br />
see https://alwaysonssl.com/issue.php. You need to register with<br />
CertCentre AG and open a reseller account to pay for any certificates<br />
bought, although for testing most can be cancelled within 30 days<br />
without charge. CertCentre AG uses OAuth2 authentication which is<br />
complex to set-up, but then mostly invisible. Domain validated<br />
certificates can be purchased and downloaded automatically using file<br />
or DNS challenges, other types of certificates can be ordered and will<br />
automatically downloaded when the order is completed after hours or days.<br />
<br />
The TSslWSocketServer, TSslHttpServer, TSslHttpAppSrv, TIcsProxy and<br />
TIcsHttpProxy components can assign a TSslX509Certs component to support<br />
automatic certificate ordering of domain validated certificates with<br />
very little extra code.<br />
<br />
There is a new sample project OverbyteIcsX509CertsTst to demonstrate<br />
the TSslX509Certs component, which may be used as a standalone<br />
application to order X509 certificates from Let's Encrypt and<br />
CertCentre AG, and monitor the certificate orders database, and to<br />
issue own CA certificates.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TWSocket.State&diff=3109TWSocket.State2011-07-09T06:45:23Z<p>Fpiette: Added navigation</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[TWSocket]] -> [[TWSocket.State | State]]<br />
<br />
== Definition ==<br />
<br />
'''property''' State: '''TSocketState''';<br />
<br />
== Descripton ==<br />
<br />
'''State''' defines the current state of the socket, mainly used for log or display purposes.. The following values are available:<br />
<br />
* wsInvalidState<br />
* wsOpened<br />
* wsBound<br />
* wsConnecting<br />
* wsSocksConnected<br />
* wsConnected<br />
* wsAccepting<br />
* wsListening<br />
* wsClosed<br />
<br />
== Best practices ==<br />
The State property is intended for display or logging purpose only. To manage your application flow/state, use the events instead. The most usefull events are [[TWSocket.OnSessionConnected | OnSessionConnected]], [[TWSocket.OnSessionAvailable | OnSessionAvailable]], [[TWSocket.OnSessionClosed | OnSessionClosed]] and [[TWSocket.OnDataAvailable | OnDataAvailable]].</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TWSocket.State&diff=3108TWSocket.State2011-07-09T06:44:29Z<p>Fpiette: Added best practices</p>
<hr />
<div>== Definition ==<br />
<br />
'''property''' State: '''TSocketState''';<br />
<br />
== Descripton ==<br />
<br />
'''State''' defines the current state of the socket, mainly used for log or display purposes.. The following values are available:<br />
<br />
* wsInvalidState<br />
* wsOpened<br />
* wsBound<br />
* wsConnecting<br />
* wsSocksConnected<br />
* wsConnected<br />
* wsAccepting<br />
* wsListening<br />
* wsClosed<br />
<br />
== Best practices ==<br />
The State property is intended for display or logging purpose only. To manage your application flow/state, use the events instead. The most usefull events are [[TWSocket.OnSessionConnected | OnSessionConnected]], [[TWSocket.OnSessionAvailable | OnSessionAvailable]], [[TWSocket.OnSessionClosed | OnSessionClosed]] and [[TWSocket.OnDataAvailable | OnDataAvailable]].</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TWSocket.OnDataAvailable&diff=3107TWSocket.OnDataAvailable2011-07-09T06:42:08Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[TWSocket]] -> [[TWSocket.OnDataAvailable | OnDataAvailable]]<br />
<br />
== Definition ==<br />
<br />
'''event''' OnDataAvailable '''Sender:TObject; ErrCode:Integer''';<br />
<br />
== Description ==<br />
<br />
'''OnDataAvailable''' is triggered every time a packet has been received on the interface the corresponding socket is attached (bound) to. In this event you should fetch the received data via [[TWSocket.Receive|Receive]], otherwise the event will occur forever. As long as there is still data in the receive buffer of the socket the event will be raised again. <br />
<br />
e.g.<br />
* There were 512 bytes in the buffer<br />
* you only feteched 256 bytes of them at the first time<br />
* the OnDataAvailable will occur a second time, since 256 bytes are left<br />
* if you fetch the other 256 bytes OnDataAvailable stays quiet until the next packet is received<br />
<br />
If your program is in the eventhandler now it won't fire again until all the code in the handler has been run, so it may be wise to put long running processing (e.g. database queries) into a worker thread you create in the eventhandler or pass the data to a buffer which is on the other end processed by a thread (so the buffer contents is the thread's workload).<br />
<br />
== Example ==<br />
<br />
With following definition:<br />
'''const''' EndOfLine = #13#10;<br />
<br />
and on the MyForm<br />
...<br />
WSocket :TWSocket;<br />
...<br />
Terminal :TMemo;<br />
...<br />
<br />
append the received line to the Memo by using '''[[TWSocket.ReceiveStr | ReceiveStr]]''':<br />
'''procedure''' TFormMyForm.WSocket1'''DataAvailable'''(Sender: TObject; ErrCode: Word);<br />
var Line :string;<br />
begin<br />
if ErrCode <> 0 then Exit;<br />
<br />
with Sender as TWSocket do begin<br />
Line := '''ReceiveStr''';<br />
Line := LeftStr(Line,Length(Line)-Length(EndOfLine)); // remove EndOfLine<br />
Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line);<br />
end;<br />
end;<br />
<br />
... or by using '''[[TWSocket.Receive | Receive]]''':<br />
'''procedure''' TFormMyForm.WSocket1'''DataAvailable'''(Sender: TObject; ErrCode: Word);<br />
'''var ''' Count :integer;<br />
Buffer :array [0..255] of char;<br />
Line :string;<br />
'''begin'''<br />
if ErrCode <> 0 then Exit;<br />
<br />
with Sender as TWSocket do<br />
Count := '''Receive'''(@Buffer, Sizeof(Buffer)-1);<br />
<br />
if Count <= 0 then Exit;<br />
<br />
// Assume the Buffer was long enough and the whole line ist in the Buffer.<br />
Buffer[Count-Length(EndOfLine)] := #0; // "delete" LineEnd<br />
// zero terminiated String<br />
Line := Buffer; // copy to string<br />
if Length(Line) = 0 then Exit;<br />
Terminal.Lines.Add('Line: '+ IntToStr(Length(Line)) +' '+Line);<br />
'''end;'''<br />
<br />
If 'Hello World!' was received, you will see:<br />
Line: 12 Hello World!<br />
<br />
== Best practices ==<br />
* do not call Application.Processmessages or any other form of a message pump (such as TWSocket's message pump or GetMessage or any modal form) within the event, otherwise you can run into severe reetrancy problems.<br />
<br />
== How to ==</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TWSocket.OnChangeState&diff=3106TWSocket.OnChangeState2011-07-09T06:42:01Z<p>Fpiette: Added description</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[TWSocket]] -> [[TWSocket.OnChangeState | OnChangeState]]<br />
<br />
== Definition ==<br />
<br />
'''event''' OnChangeState '''Sender:TObject; OldState, NewState : TSocketState''';<br />
<br />
== Description ==<br />
<br />
'''OnChangeState''' is triggered each time TWSocket internal state changes. This event is intended for display or logging purpose only. <br />
<br />
== Best practices ==<br />
<br />
Don't use it to manage your application state/flow. Instead, use [[TWSocket.OnSessionConnected | OnSessionConnected]], [[TWSocket.OnSessionAvailable | OnSessionAvailable]], [[TWSocket.OnSessionClosed | OnSessionClosed]] and [[TWSocket.OnDataAvailable | OnDataAvailable]].</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2320TutWebAppServer2009-05-22T14:34:22Z<p>Fpiette: /* Source code */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[THttpAppSrv | THttpAppSrv]] -> '''Tutorial'''<br />
<br />
== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
<br />
== Source code ==<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to4.zip Lesson 1 to 4]<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to6.zip Lesson 1 to 6]<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
== Lessons ==<br />
[[TutWebAppServer Lesson 1 - Hello World|Lesson 1 - Hello World]]<br><br />
[[TutWebAppServer Lesson 2 - Hello Today|Lesson 2 - Hello Today]]<br><br />
[[TutWebAppServer Lesson 3 - Simple data entry and processing|Lesson 3 - Simple data entry and processing]]<br><br />
[[TutWebAppServer Lesson 4 - Building tables|Lesson 4 - Building tables]]<br><br />
[[TutWebAppServer Lesson 5 - Relocation|Lesson 5 - Relocation]]<br><br />
[[TutWebAppServer Lesson 6 - Simple login and session data|Lesson 6 - Simple login and session data]]<br><br />
[[TutWebAppServer Lesson 7 - Dynamic images|Lesson 7 - Dynamic images]]<br><br />
[[TutWebAppServer Lesson 8 - Asynchronous answer|Lesson 8 - Asynchronous answer]]<br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2319TutWebAppServer2009-05-22T14:32:15Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[THttpAppSrv | THttpAppSrv]] -> '''Tutorial'''<br />
<br />
== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
<br />
== Source code ==<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to4.zip Lesson 1 to 4]<br />
<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
== Lessons ==<br />
[[TutWebAppServer Lesson 1 - Hello World|Lesson 1 - Hello World]]<br><br />
[[TutWebAppServer Lesson 2 - Hello Today|Lesson 2 - Hello Today]]<br><br />
[[TutWebAppServer Lesson 3 - Simple data entry and processing|Lesson 3 - Simple data entry and processing]]<br><br />
[[TutWebAppServer Lesson 4 - Building tables|Lesson 4 - Building tables]]<br><br />
[[TutWebAppServer Lesson 5 - Relocation|Lesson 5 - Relocation]]<br><br />
[[TutWebAppServer Lesson 6 - Simple login and session data|Lesson 6 - Simple login and session data]]<br><br />
[[TutWebAppServer Lesson 7 - Dynamic images|Lesson 7 - Dynamic images]]<br><br />
[[TutWebAppServer Lesson 8 - Asynchronous answer|Lesson 8 - Asynchronous answer]]<br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2318TutWebAppServer2009-05-22T14:31:31Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[THttpAppSrv | THttpAppSrv]] -> Tutorial<br />
<br />
== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
<br />
== Source code ==<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to4.zip Lesson 1 to 4]<br />
<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
== Lessons ==<br />
[[TutWebAppServer Lesson 1 - Hello World|Lesson 1 - Hello World]]<br><br />
[[TutWebAppServer Lesson 2 - Hello Today|Lesson 2 - Hello Today]]<br><br />
[[TutWebAppServer Lesson 3 - Simple data entry and processing|Lesson 3 - Simple data entry and processing]]<br><br />
[[TutWebAppServer Lesson 4 - Building tables|Lesson 4 - Building tables]]<br><br />
[[TutWebAppServer Lesson 5 - Relocation|Lesson 5 - Relocation]]<br><br />
[[TutWebAppServer Lesson 6 - Simple login and session data|Lesson 6 - Simple login and session data]]<br><br />
[[TutWebAppServer Lesson 7 - Dynamic images|Lesson 7 - Dynamic images]]<br><br />
[[TutWebAppServer Lesson 8 - Asynchronous answer|Lesson 8 - Asynchronous answer]]<br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2317THttpAppSrv2009-05-22T14:20:35Z<p>Fpiette: /* Overview */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[THttpAppSrv | THttpAppSrv]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> [[THttpServer]] -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages. See the [[TutWebAppServer | Tutorial]] for a step by step explanation of the component use.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="150" valign="top" | [[THttpAppSrv.Start | Start]] |||| Start listening for clients.<br />
|- <br />
| valign="top" | [[THttpAppSrv.Stop | Stop]] |||| Stop listening for clients.<br />
|- <br />
| valign="top" | [[THttpAppSrv.SaveSessionsToFile | SaveSessionsToFile]] |||| Save all current sessions to a file.<br />
|- <br />
| valign="top" | [[THttpAppSrv.LoadSessionsFromFile | LoadSessionsFromFile]] |||| Load sessions saved in a file. Existing sessions are deleted.<br />
|- <br />
| valign="top" | [[THttpAppSrv.ClearSessions | ClearSessions]] |||| Delete all sessions.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddGetHandler | AddGetHandler]] |||| Add a handler class for a given URL for HTTP GET method.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddPostHandler | AddPostHandler]] |||| Add a handler class for a given URL for HTTP POST method.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddGetAllowedPath | AddGetAllowedPath]] |||| Add a path that the component is allowed to server static pages or files.<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| valign="top" width="150" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnDeleteSession | OnDeleteSession]] |||| Triggered when a session is deleted.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|-<br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. <br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. <br />
|- <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarted]] |||| Triggered when server has started listening.<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening.<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TutWebAppServer | Build a HTTP webserver application]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2316THttpAppSrv2009-05-22T14:19:06Z<p>Fpiette: Added methods</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[THttpAppSrv | THttpAppSrv]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> [[THttpServer]] -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="150" valign="top" | [[THttpAppSrv.Start | Start]] |||| Start listening for clients.<br />
|- <br />
| valign="top" | [[THttpAppSrv.Stop | Stop]] |||| Stop listening for clients.<br />
|- <br />
| valign="top" | [[THttpAppSrv.SaveSessionsToFile | SaveSessionsToFile]] |||| Save all current sessions to a file.<br />
|- <br />
| valign="top" | [[THttpAppSrv.LoadSessionsFromFile | LoadSessionsFromFile]] |||| Load sessions saved in a file. Existing sessions are deleted.<br />
|- <br />
| valign="top" | [[THttpAppSrv.ClearSessions | ClearSessions]] |||| Delete all sessions.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddGetHandler | AddGetHandler]] |||| Add a handler class for a given URL for HTTP GET method.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddPostHandler | AddPostHandler]] |||| Add a handler class for a given URL for HTTP POST method.<br />
|- <br />
| valign="top" | [[THttpAppSrv.AddGetAllowedPath | AddGetAllowedPath]] |||| Add a path that the component is allowed to server static pages or files.<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| valign="top" width="150" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnDeleteSession | OnDeleteSession]] |||| Triggered when a session is deleted.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|-<br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. <br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. <br />
|- <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarted]] |||| Triggered when server has started listening.<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening.<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TutWebAppServer | Build a HTTP webserver application]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=ICS_Components_Reference&diff=2315ICS Components Reference2009-05-22T14:08:46Z<p>Fpiette: Added THttpAppSrv component</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]]<br />
<br />
== Sockets components ==<br />
These components implement the basic TCP/IP sockets.<br />
<br />
{|<br />
| width="130" | [[image:Twsocket.gif]] [[TWSocket | TWSocket]] |||| Basic Socket for TCP and UDP, client and server<br />
|-<br />
| [[image:Twsocketserver.gif]] [[TWSocketServer | TWSocketServer]] |||| Basic TCP Server Socket<br />
|}<br />
<br />
== Protocol components ==<br />
These components implement some of the protocols used by TCP/IP applications, over the Internet.<br />
All are implementing RFCs as described on the [http://www.ietf.org IETF website].<br />
<br />
{|<br />
| width="130" | [[image:Tfingercli.gif]] [[TFingerCli | TFingerCli]] |||| Finger Client<br />
|-<br />
| [[image:Tftpcli.gif]] [[TFtpClient | TFtpClient]] |||| FTP Client<br />
|-<br />
| [[image:Tftpserver.gif]] [[TFtpServer | TFtpServer]] |||| FTP Server<br />
|-<br />
| [[image:Thttpcli.gif]] [[THttpCli | THttpCli]] |||| HTTP Client<br />
|-<br />
| [[image:Thttpserver.gif]] [[THttpServer | THttpServer]] |||| HTTP Server<br />
|-<br />
| [[image:THttpAppSrv.gif]] [[THttpAppSrv | THttpAppSrv]] |||| HTTP Application Server<br />
|-<br />
| [[image:Tnntpcli.gif]] [[TNntpCli | TNntpCli]] |||| NNTP Client (News)<br />
|-<br />
| [[image:Thtmlnntpcli.gif]] [[THtmlNntpCli | THtmlNntpCli]] |||| HTML NNTP Client<br />
|-<br />
| [[image:Tping.gif]] [[TPing | TPing]] |||| Ping client<br />
|-<br />
| [[image:Ttncnx.gif]] [[TTnCnx | TTnCnx]] |||| Telnet Connection<br />
|-<br />
| [[image:Tsmtpcli.gif]] [[TSmtpCli | TSmtpCli]] |||| SMTP Client<br />
|-<br />
| [[image:Tsyncsmtpcli.gif]] [[TSyncSmtpCli | TSyncSmtpCli]] |||| Synchronous SMTP Client<br />
|-<br />
| [[image:Thtmlsmtpcli.gif]] [[THtmlSmtpCli | THtmlSmtpCli]] |||| HTML Smtp Client<br />
|-<br />
| [[image:Tpop3cli.gif]] [[TPop3Cli | TPop3Cli]] |||| POP3 Client<br />
|-<br />
| [[image:Tsyncpop3cli.gif]] [[TSyncPop3cli | TSyncPop3cli]] |||| Synchronous POP3 Client<br />
|-<br />
| [[image:Tdnsquery.gif]] [[TDnsQuery | TDnsQuery]] |||| DNS Query Client<br />
|}<br />
<br />
== Helper Components ==<br />
<br />
{|<br />
| width="130" | [[image:Tmimedecode.gif]] [[TMimeDecode | TMimeDecode]] |||| Mime Decoder<br />
|-<br />
| [[image:Ttnemulvt.gif]] [[TTnEmulVT | TTnEmulVT]] |||| Telnet VT Terminal Emulator<br />
|-<br />
| [[image:Ttnscript.gif]] [[TTnScript | TTnScript]] |||| Telnet Script<br />
|-<br />
| [[image:Temulvt.gif]] [[TEmulVt | TEmulVT]] |||| VT Terminal Emulator<br />
|-<br />
| [[image:Tmbxhandler.gif]] [[TMbxHandler | TMbxHandler]] |||| Mail Box Handler (Obsolete, don't use it anymore)<br />
|-<br />
| [[image:Twait.gif]] [[TWait | TWait]] |||| Wait socket (Obsolete, don't use it anymore)<br />
|}<br />
<br />
== Cryptography ==<br />
{|<br />
| width="130" | [[SHA1 | SHA1]] |||| Secure Hash Algoritm 1 implementation<br />
|-<br />
| [[MD4 | MD4]] |||| Message Digest 4 Hash algorithm implementation<br />
|-<br />
| [[MD5 | MD5]] |||| Message Digest 5 Hash algorithm implementation<br />
|-<br />
| [[DES | DES]] |||| Data Encryption Standard encryption algorithm implementation<br />
|}<br />
<br />
== List of demo programs ==<br />
[[Demo applications installed with the ICS-package]]<br />
<br />
== Templates ==<br />
<br />
[[Template | Edit new component]]<br />
<br />
[[TemplateProp | Edit new property]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=File:THttpAppSrv.gif&diff=2314File:THttpAppSrv.gif2009-05-22T14:07:51Z<p>Fpiette: </p>
<hr />
<div></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpServer&diff=2313THttpServer2009-05-22T11:18:44Z<p>Fpiette: /* Overview */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] <br />
-> [[THttpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' HttpSrv.pas<br />
*'''inheritance''' THttpServer- TComponent<br />
<br />
THttpServer component is implementing the server side HTTP protocol. HTTP protocol is the standard protocol for browsing the World Wide Web. <br>If you want to write a web application, you should use [[THttpAppSrv]] which derive from THttpServer and add a lot of nice features to ease writing HTTP application server.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Start | Start]] |||| Starts the webserver so it lisen for incoming requests.<br />
|-<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarte]] |||| Triggered when server has started listening<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. You can either do nothing and let server handle all work, or you can build a document on the fly or refuse access.<br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request. You can either do nothing and let server handle all work, or you can build a document header on the fly or refuse access.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request. You have to tell if you accept data or not. If you accept, you'll get OnPostedData event with incomming data.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. When you've got all data, you have to build a reply to be sent to client.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate<br />
|}<br />
<br />
== How to ==<br />
<br />
<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2312THttpAppSrv2009-05-22T10:49:11Z<p>Fpiette: /* Overview */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[Template | Edit new component]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> [[THttpServer]] -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| valign="top" width="150" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnDeleteSession | OnDeleteSession]] |||| Triggered when a session is deleted.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|-<br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. <br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. <br />
|- <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarted]] |||| Triggered when server has started listening.<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening.<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TutWebAppServer | Build a HTTP webserver application]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2311THttpAppSrv2009-05-22T10:18:48Z<p>Fpiette: /* How to */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[Template | Edit new component]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> THttpServer -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| valign="top" width="150" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnDeleteSession | OnDeleteSession]] |||| Triggered when a session is deleted.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|-<br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. <br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. <br />
|- <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarted]] |||| Triggered when server has started listening.<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening.<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TutWebAppServer | Build a HTTP webserver application]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2310THttpAppSrv2009-05-22T10:13:20Z<p>Fpiette: /* Events */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[Template | Edit new component]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> THttpServer -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| valign="top" width="150" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected.<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnDeleteSession | OnDeleteSession]] |||| Triggered when a session is deleted.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|-<br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. <br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. <br />
|- <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarted]] |||| Triggered when server has started listening.<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening.<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TName.HowTo.Title | Title]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpServer&diff=2309THttpServer2009-05-22T09:47:51Z<p>Fpiette: /* Events */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] <br />
-> [[THttpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' HttpSrv.pas<br />
*'''inheritance''' THttpServer- TComponent<br />
<br />
THttpServer component is implementing the server side HTTP protocol. HTTP protocol is the standard protocol for browsing the World Wide Web.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Start | Start]] |||| Starts the webserver so it lisen for incoming requests.<br />
|-<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| width="90" valign="top" | [[THttpServer.OnServerStarted| OnServerStarte]] |||| Triggered when server has started listening<br />
|- <br />
| valign="top" | [[THttpServer.OnServerStopped | OnServerStopped]] |||| Triggered when server has stopped listening<br />
|- <br />
| valign="top" | [[THttpServer.OnClientConnect | OnClientConnect]] |||| Triggered when a client has connected<br />
|- <br />
| valign="top" | [[THttpServer.OnClientDisconnect | OnClientDisconnect]] |||| Triggered when a client is about to disconnect.<br />
|- <br />
| valign="top" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Triggered when a client sent GET request. You can either do nothing and let server handle all work, or you can build a document on the fly or refuse access.<br />
|- <br />
| valign="top" | [[THttpServer.OnHeadDocument | OnHeadDocument]] |||| Triggered when a client sent HEAD request. You can either do nothing and let server handle all work, or you can build a document header on the fly or refuse access.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostDocument | OnPostDocument]] |||| Triggered when a client sent POST request. You have to tell if you accept data or not. If you accept, you'll get OnPostedData event with incomming data.<br />
|- <br />
| valign="top" | [[THttpServer.OnPostedData | OnPostedData]] |||| Triggered when client post data and you accepted it from OnPostDocument event. When you've got all data, you have to build a reply to be sent to client.<br />
|- <br />
| valign="top" | [[THttpServer.OnHttpRequestDone | OnHttpRequestDone]] |||| A HTTP request has been handled on behalf of a client.<br />
|- <br />
| valign="top" | [[THttpServer.OnBeforeProcessRequest | OnBeforeProcessRequest]] |||| Triggered before processing any request.<br />
|- <br />
| valign="top" | [[THttpServer.OnFilterDirEntry | OnFilterDirEntry]] |||| Triggered to filter directory entries.<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetPassword | OnAuthGetPassword]] |||| Triggered to get the password for authentication<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthResult | OnAuthResult]] |||| TAuthResultEvent<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthGetType | OnAuthGetType]] |||| TAuthGetTypeEvent<br />
|- <br />
| valign="top" | [[THttpServer.OnAuthNtlmBeforeValidate | OnAuthNtlmBeforeValidat]] |||| TAuthNtlmBeforeValidate<br />
|}<br />
<br />
== How to ==<br />
<br />
<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2308THttpAppSrv2009-05-22T08:53:44Z<p>Fpiette: /* Runtime Properties */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[Template | Edit new component]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> THttpServer -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
'''Object inspector properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.SessionCount | SessionCount]] |||| Number of active sessions.<br />
|- <br />
| valign="top" | [[THttpServer.Sessions | Sessions]] |||| Array of active sessions. Index if from 0 to SessionCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.WSessions | WSessions]] |||| Reference to TWebSessions instance used to manage sessions.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TName.HowTo.Title | Title]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpServer&diff=2307THttpServer2009-05-22T08:48:54Z<p>Fpiette: /* Properties */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] <br />
-> [[THttpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' HttpSrv.pas<br />
*'''inheritance''' THttpServer- TComponent<br />
<br />
THttpServer component is implementing the server side HTTP protocol. HTTP protocol is the standard protocol for browsing the World Wide Web.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
'''Runtime properties'''<br><br />
{|<br />
| valign="top" width="150" | [[THttpServer.ClientCount | ClientCount]] |||| Number of currently connected clients.<br />
|- <br />
| valign="top" | [[THttpServer.Client | Client]] |||| Array of connected clients. Index is from 0 to ClientCount - 1.<br />
|- <br />
| valign="top" | [[THttpServer.ClientClass | ClientClass]] |||| Reference to the class the component has to instanciate for each client.<br />
|- <br />
| valign="top" | [[THttpServer.WSocketServer | WSocketServer]] |||| Reference to the underlaying TWSocketServer.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Start | Start]] |||| Starts the webserver so it lisen for incoming requests.<br />
|-<br />
|}<br />
<br />
== Events ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Processes requests for documents.<br />
|-<br />
|}<br />
<br />
== How to ==<br />
<br />
<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpAppSrv&diff=2306THttpAppSrv2009-05-22T08:41:31Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[Template | Edit new component]]<br />
<br />
== Overview ==<br />
{|<br />
| '''unit''' |||| OverbyteIcsHttpAppServer<br />
|-<br />
| '''inheritance''' |||| THttpAppSrv -> THttpServer -> TComponent<br />
|}<br />
<br />
THttpAppSrv is implementing the core of an HTTP application server. It is used to build powerful and large web applications with dynamic pages.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.SessionTimeout | SessionTimeout]] |||| Time in second for session expiration.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== Events ==<br />
<br />
{| <br />
| width="90" valign="top" | [[TName.Name | Name]] |||| Short description<br />
|- <br />
| valign="top" | [[TName.Name | Name]] |||| Short description<br />
|}<br />
<br />
== How to ==<br />
<br />
[[TName.HowTo.Title | Title]]<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=THttpServer&diff=2305THttpServer2009-05-22T08:39:50Z<p>Fpiette: /* Properties */</p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] <br />
-> [[THttpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' HttpSrv.pas<br />
*'''inheritance''' THttpServer- TComponent<br />
<br />
THttpServer component is implementing the server side HTTP protocol. HTTP protocol is the standard protocol for browsing the World Wide Web.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Addr | Addr]] |||| Binds the server to a specific IP-address and only receives request for that IP+Port.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestMethod | AuthDigestMethod]] |||| Select the method to be used for digest authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthDigestNonceLifeTimeMin | AuthDigestNonceLifeTimeMin]] |||| Life time for digest nonce.<br />
|- <br />
| valign="top" | [[THttpServer.AuthRealm | AuthRealm]] |||| Name space for authentication.<br />
|- <br />
| valign="top" | [[THttpServer.AuthTypes | AuthTypes]] |||| Allowed authentications methods.<br />
|- <br />
| valign="top" | [[THttpServer.DefaultDoc | DefaultDoc]] |||| Name of the default document.<br />
|- <br />
| valign="top" | [[THttpServer.DocDir | DocDir]] |||| Path name for the root directory where documents are stored.<br />
|- <br />
| valign="top" | [[THttpServer.IcsLogger | IcsLogger]] |||| Reference to the TIcsLgger component.<br />
|- <br />
| valign="top" | [[THttpServer.KeepAliveTimeSec | KeepAliveTimeSec]] |||| Keep alive time expressed in seconds.<br />
|- <br />
| valign="top" | [[THttpServer.LingerOnOff | LingerOnOff]] |||| How linger must be done. This affect the way sockets are closed.<br />
|- <br />
| valign="top" | [[THttpServer.LingerTimeout | LingerTimeout]] |||| How long should the socket linger when closing.<br />
|- <br />
| valign="top" | [[THttpServer.ListenBacklog | ListenBackog]] |||| How many connections can be queued by the OS before refusing new connections.<br />
|- <br />
| valign="top" | [[THttpServer.MaxClients | MaxClients]] |||| Maximum number of simultaneous client accepted. Use 0 if not limit desired.<br />
|- <br />
| valign="top" | [[THttpServer.MaxRequestsKeepAlive | MaxRequestsKeepAlive]] |||| MaxRequestsKeepAlive.<br />
|- <br />
| valign="top" | [[THttpServer.Name | Name]] |||| Component name.<br />
|- <br />
| valign="top" | [[THttpServer.Options | Options]] |||| Affect how the component is operating.<br />
|- <br />
| valign="top" | [[THttpServer.Port | Port]] |||| TCP port number the component has to listen to.<br />
|- <br />
| valign="top" | [[THttpServer.Tag | Tag]] |||| Tag.<br />
|- <br />
| valign="top" | [[THttpServer.TemplateDir | TemplateDir]] |||| Path where the component search for dynamic pages templates.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.Start | Start]] |||| Starts the webserver so it lisen for incoming requests.<br />
|-<br />
|}<br />
<br />
== Events ==<br />
<br />
{|<br />
| valign="top" width="150" | [[THttpServer.OnGetDocument | OnGetDocument]] |||| Processes requests for documents.<br />
|-<br />
|}<br />
<br />
== How to ==<br />
<br />
<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_6_-_Simple_login_and_session_data&diff=2304TutWebAppServer Lesson 6 - Simple login and session data2009-05-17T14:47:01Z<p>Fpiette: Fixed a few typos</p>
<hr />
<div>During this lesson, you will learn how to handle session data.<br />
<br />
As you probably know, HTTP is a stateless protocol. This means that each request is totally indepedent from each other as far as HTTP protocol is concerned. A web application is made of a lot of HTTP requests as the user interacts with the application. Because of the stateless nature of the HTTP protocol, your web application cannot rely on HTTP to have each page of the application know it is part of a single application used by a particular user at a given time. It is the application programmer's responsibility to make the application pages seen as a whole application, that is having a page content or behaviour affected by what the user has done previously with the application.<br />
<br />
The application programmer has the need to have a data structure, at server side, with values private to a given user for the duration of his activity with the application. Of course since we are building a server application, we can have many users connected at the same time. The developer need a different data instance for each user. We will refer to this kind of data as "session data" in the remaining lessons. <br />
<br />
Don't be scary, ICS HttpAppServer component and the user browser will help you achieve that goal.<br />
<br />
From the user perspective, a session begin when he starts working with the application and ends when he stop working with the application. Usually the user is presented a login screen at the start of his working session, and simply close his browser or select some "logout" link to end his session.<br />
<br />
Login screen is not mandatory. You may want to begin a session with any page from the application and create the session from there without ever asking the user to identify itself. Consider this as a kind of login where actually no usercode/password is checked but everything else is done.<br />
<br />
In this lesson we will create a simple login page, create a data structure to hold data for the user session, create a simple dynamic page protected by the login and showing data saved in the session. The later will be the page shown immediately after login. <br />
<br />
==== Steps ====<br />
<br />
<ol><br />
<li> Create a new template containing the login form. We do a dynamic page because frequently login is done from the main page which almost contain dynamic data. For simplicity here our page will only show the current time at server side. Enter the following code into the body part of the document:<br />
<tt><br />
: <form action="/DoSimpleLogin.html"<br />
:::: method="GET"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
:: Usercode <input type="TEXT" name="UserCode">&lt;br><br />
:: Password <input type="PASSWORD" name="Password">&lt;br><br />
:: <input type="SUBMIT" value="Login">&lt;br><br />
:: &lt;br><br />
:: &lt;br>Server time is <#ServerTime><br />
: </form><br />
</tt><br />
Save the HTML file in the templates folder under the name "SimpleLogin.html".</li><br />
<li> Create a new template containing the simple page accessible only after login and showing some session data. Here after is the HTML code you have to enter into the body part of the document:<br />
<tt><br />
: If you see this page, then you have a valid session.&lt;br><br />
: You logged at <#LoginTime>&lt;br><br />
: Your user code is <#UserCode>&lt;br><br />
: You already saw this page <#PageCount> times since you logged in.&lt;br><br />
</tt><br />
Save the HTML file in the templates folder under the name "SimpleMainPage.html".</li><br />
<li> Create a new Delphi unit "OverbyteIcsTutWebAppServerSimpleLogin.pas". You will write the classes TUrlHandlerSimpleLogin and TUrlHandlerDoSimpleLogin containing the code to handle the login process: one class for the login form and one class for the login form action. You will also write the class TUrlHandlerSimpleMainPage to handle the main page, that is the result page shown when login is OK.<br />
</li><br />
<li> Map the classes to the URLs. In TTutWebAppServerMainForm.FormShow, add the following lines after the similar already there: <br />
<tt><br />
: HttpAppSrv1.AddGetHandler('/SimpleLogin.Html', TUrlHandlerSimpleLogin);<br />
: HttpAppSrv1.AddGetHandler('/DoSimpleLogin.html', TUrlHandlerDoSimpleLogin);<br />
: HttpAppSrv1.AddGetHandler('/SimpleMainPage.html', TUrlHandlerSimpleMainPage);<br />
</tt><br />
</li><br />
<li> Create the supporting 3 classes. For now, we just build basic code which doesn't do an actual login. This is just to verify that everything is OK until now. The class declaration part of unit "OverbyteIcsTutWebAppServerSimpleLogin.pas" looks like:<br />
<tt><br />
: TUrlHandlerSimpleLogin = '''class'''(TUrlHandler)<br />
: '''public'''<br />
:: '''procedure''' Execute; '''override;'''<br />
: '''end;'''<br />
:<br><br />
: TUrlHandlerDoSimpleLogin = '''class'''(TUrlHandler)<br />
: '''public'''<br />
:: '''procedure''' Execute; '''override;'''<br />
: '''end;'''<br />
:<br><br />
: TUrlHandlerSimpleMainPage = '''class'''(TUrlHandler)<br />
: '''public'''<br />
:: '''procedure''' Execute; '''override;'''<br />
: '''end;'''<br />
</tt><br />
And the implementation looks like:<br />
<tt><br />
:'''procedure''' TUrlHandlerSimpleLogin.Execute;<br />
:'''begin'''<br />
:: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleLogin.html', nil,<br />
:::: ['ServerTime', DateTimeToStr(Now)]);<br />
:: Finish;<br />
:'''end;'''<br />
:<br><br />
:'''procedure''' TUrlHandlerDoSimpleLogin.Execute;<br />
:'''var'''<br />
:: Location : '''String;'''<br />
:'''begin'''<br />
:: Location := '/SimpleMainPage.html';<br />
:: AnswerString('302 moved', &rsquo;&rsquo;,<br />
:::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::: '<A HREF="' + Location + '">Click here</A>');<br />
:: Finish;<br />
:'''end;'''<br />
:<br><br />
:'''procedure''' TUrlHandlerSimpleMainPage.Execute;<br />
:'''begin'''<br />
:: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleMainPage.html', nil, []);<br />
:: Finish;<br />
:'''end;'''<br />
</tt><br />
Now you can hit F9 to compile and run the server. Point your browser to http://127.0.0.1:20080/SimpleLogin.html. You should see the login page displayed in the browser with the server time properly displayed. Enter any value in usercode and password fields (we don't check those values yet) and click the login button. You should see the SimpleMainPage displayed.</li><br />
<li>Since the login is not working yet, you can verify that you have an unrestricted access to SimpleMainPage.html: Restart your browser and enter http://127.0.0.1:20080/SimpleMainPage.html. You can see that page normally. This is the expected behaviour now. We will change this to protect the page by the login: the user will be forced to pass by the login process to successfuly access the page.<br />
</li><br />
<li> Now we will create a new class in a new Delphi unit. This class will be our session data. Do File / New / Other / Delphi Project / Delphi Files / Unit. Save it under the name OverbyteIcsTutWebAppServerSessionData.pas.</li><br />
<li>For now, we will use very simple session data: we will keep usercode and login time so that it is available during the whole session. Create a class like this:<br />
<tt><br />
: TAppSrvSessionData = '''class'''(TWebSessionData)<br />
: '''private'''<br />
:: FUserCode: '''String;'''<br />
:: FLoginTime: TDateTime;<br />
:: FLoggedOn: Boolean;<br />
: '''published'''<br />
:: '''property''' UserCode : '''String''' '''read''' FUserCode '''write''' FUserCode;<br />
:: '''property''' LoginTime : TDateTime '''read''' FLoginTime '''write''' FLoginTime;<br />
:: '''property''' LoggedOn : Boolean '''read''' FLoggedOn '''write''' FLoggedOn;<br />
: '''end;'''<br />
</tt><br />
Every data you want in your session data must be declared as published. This is fundamental to have persistance.<br />
</li><br />
<li>Register your session data class. Add this code at the end of the unit, just before the final "end.".<br />
<tt><br />
:'''initialization'''<br />
:: RegisterClass(TAppSrvSessionData);<br />
</tt></li><br />
<li> Add OverbyteIcsTutWebAppServerSessionData unit to OverbyteIcsTutWebAppServerSimpleLogin.pas uses clause.</li><br />
<li>Change TUrlHandlerSimpleLogin.Execute to create the session when the user request the login page. <br />
<tt><br />
:'''procedure''' TUrlHandlerSimpleLogin.Execute;<br />
:'''var'''<br />
:: MySessionData : TAppSrvSessionData;<br />
:: Headers : '''String;'''<br />
:'''begin'''<br />
:: '''if not''' ValidateSession '''then begin'''<br />
::: Inc(GSessionDataCount);<br />
::: MySessionData := TAppSrvSessionData.Create(nil);<br />
::: MySessionData.Name := 'MySessionData' + IntToStr(GSessionDataCount);<br />
::: Headers := NO_CACHE + CreateSession(&rsquo;&rsquo;, 0, MySessionData);<br />
:: '''end'''<br />
:: '''else begin'''<br />
::: MySessionData := WSession.SessionData as TAppSrvSessionData;<br />
::: Headers := NO_CACHE;<br />
:: '''end;'''<br />
:: MySessionData.LoggedOn := FALSE;<br />
:<br><br />
:: AnswerPage(&rsquo;&rsquo;, Headers, 'SimpleLogin.html', nil,<br />
:::: ['ServerTime', DateTimeToStr(Now)]);<br />
:: Finish;<br />
:'''end;'''<br />
</tt><br />
The code above check for a valid session. If a valid session exists, then it is reused, otherwise a new one is created with new session data. Note that the session must be given a unique name. That's why we used the global integer variable GSessionDataCount which is incremented when a new session is created. <br />
</li><br />
<li>Create a global variable like this:<br />
<tt><br />
:'''var'''<br />
:: GSessionDataCount : Integer;<br />
</tt><br />
</li><br />
<li> Modify the code in TUrlHandlerDoSimpleLogin to extract usercode and password, and verify them against the user database. Since we are in a simple tutorial, we won't use a database but simply hard code a test for usercode "root" and password "admin". You'll easily adapt the code to fetch password from any database and verify validity more realisticly. The code is like this:<br />
<tt><br />
:'''procedure''' TUrlHandlerDoSimpleLogin.Execute;<br />
:'''var'''<br />
:: UserCode : '''String;'''<br />
:: Password : '''String;'''<br />
:: Location : '''String;'''<br />
:: SessionData : TAppSrvSessionData;<br />
:'''begin'''<br />
:: '''if not''' ValidateSession '''then'''<br />
::: Location := '/SimpleLogin.html'<br />
:: '''else begin'''<br />
::: SessionData := WSession.SessionData '''as''' TAppSrvSessionData;<br />
::: ExtractURLEncodedValue(Params, 'Password', Password);<br />
::: ExtractURLEncodedValue(Params, 'UserCode', UserCode);<br />
:<br><br />
::: '''if not''' (SameText(UserCode, 'root') '''and''' SameText(Password, 'admin')) '''then begin'''<br />
:::: DeleteSession;<br />
:::: Location := '/SimpleLogin.html';<br />
::: '''end'''<br />
::: '''else begin'''<br />
:::: SessionData.LoginTime := Now;<br />
:::: SessionData.UserCode := UserCode;<br />
:::: SessionData.LoggedOn := TRUE;<br />
:::: Location := '/SimpleMainPage.html';<br />
::: '''end;'''<br />
:: '''end;'''<br />
:: AnswerString('302 moved', &rsquo;&rsquo;,<br />
:::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::: '<A HREF="' + Location + '">Click here</A>');<br />
:: Finish;<br />
:'''end;'''<br />
</tt><br />
In the above code, we do a serie of checks and then redirect to some page according to the check results. For simplicity we redirect to the SimpleLogin page if anything is wrong or missing and to SimpleMainPage if usercode and password are OK.<br><br />
We first check for a valid session. We have a valid session if the user already loaded the SimpleLogin page because we created the session there.<br><br />
Then we extract usercode and password from the request parameters (they are comming from the HTML form) and verify their values. If not OK, we redirect to SimpleLogin. If correct, we save UserCode and Password into session data and we set the LoggedOn flag in the session data.<br><br />
The idea behing this LoggedOn flag is that we can have a valid session because the user has seen the login page, but not authenticated the user since the user has not given his usercode and password. In this tutorial, we only create the session from the login page, but as we have seen above, the session could be created anywhere in the application. Probably at many places, we don't care about who is the user and at some place we need to authenticate the user before continuing. We have to make distinction between having a valid session and having an authenticated user. This is common is eCommerce website. We need to authenticate the user only to checkout his shopping cart. The process of shopping can be conduced without actually knowing who is the user. The shopping cart is just part of the session data.<br><br />
You can hit F9 to compile and run the server. Point you browser to http://127.0.0.1:20080/SimpleLogin.html, enter the usercode "john" and password "abc" and click login. You should get back to the SimpleLogin page since the usercode and password is invalid. Try with "root" and "admin". You should see SimpleMainPage.<br />
</li><br />
<li>Now that we have our login process operational, we will protect SimpleMainPage from anonymous access. That is we will force the user to be logged on before showing the actual page. To do that, we simply have to validate the session and check the LoggedOn flag. If not OK, we will redirect the user to the login page.<br><br />
Modify the code in TUrlHandlerSimpleMainPage.Execute so that it looks like:<br />
<tt><br />
:'''procedure''' TUrlHandlerSimpleMainPage.Execute;<br />
:'''var'''<br />
:: Location : '''String;'''<br />
:: SessionData : TAppSrvSessionData;<br />
:'''begin'''<br />
:: Location := &rsquo;&rsquo;;<br />
:: SessionData := nil;<br />
:: '''if not''' ValidateSession '''then'''<br />
::: Location := '/SimpleLogin.html'<br />
:: '''else begin'''<br />
::: SessionData := WSession.SessionData '''as''' TAppSrvSessionData;<br />
::: '''if not''' SessionData.LoggedOn '''then'''<br />
:::: Location := '/SimpleLogin.html';<br />
:: '''end;'''<br />
:<br><br />
:: '''if''' Location = &rsquo;&rsquo; '''then'''<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleMainPage.html', nil,<br />
::::: ['UserCode', SessionData.UserCode,<br />
::::: 'LoginTime', DateTimeToStr(SessionData.LoginTime)])<br />
:: '''else'''<br />
::: AnswerString('302 moved', &rsquo;&rsquo;,<br />
::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
::::: '<A HREF="' + Location + '">Click here</A>');<br />
:: '''Finish''';<br />
:end;<br />
</tt><br />
Hit F9 to compile and run the server. Point your browser to http://127.0.0.1:20080/SimpleMainPage.html. You should be redirected to SimpleLogin page since you have not yet logged on. Enter a "root" and "admin" as usercode and password. You should see the SimpleMainPage. Navigate somewhere else without closing your browser and then enter http://127.0.0.1:20080/SimpleMainPage.html. This time you should see the page immediately since you already logged in. If you close your browser or close the server program, you'll be again redirected to the login page. Our goal is reached: SimpleMainPage is protected by the login.<br />
</li><br />
<li>There is one more step in the lesson showing how to use session data from a webpage. For simplicity, we will simple count the number of times the user has seen the SimpleMainPage since he logged in.<br><br />
Create a new property MainPageCount in TAppSrvSessionData class:<br />
<tt><br />
: '''private'''<br />
:: FMainPageCount : Integer;<br />
: '''published'''<br />
:: '''property''' MainPageCount : Integer '''read''' FMainPageCount '''write''' FMainPageCount;<br />
</tt><br />
</li><br />
<li>Using the new MainPageCount property is easy. You have direct access to it and do whatever you like. Any change is persistent as long as the session exists. Change the code in TUrlHandlerSimpleMainPage.Execute so that it looks like:<br />
<tt><br />
: '''if''' Location = &rsquo;&rsquo; '''then begin'''<br />
:: SessionData.MainPageCount := SessionData.MainPageCount + 1;<br />
:: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleMainPage.html', nil,<br />
:::: ['UserCode', SessionData.UserCode,<br />
:::: 'LoginTime', DateTimeToStr(SessionData.LoginTime),<br />
:::: 'PageCount', SessionData.MainPageCount])<br />
: '''end'''<br />
</tt><br />
</li><br />
</ol><br />
<br><br><br><br />
==== Summary ====<br />
In this lesson you learned that session data is persistent data during the time the user intercat with your website. You learend how to create a class to define and store your session data. You learned how to create a session and use it to remember a user has been authenticated. You also used it to count the number of access for a given user.<br />
<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 7 - Dynamic images|Dynamic images]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 5 - Relocation|Relocation]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_6_-_Simple_login_and_session_data&diff=2302TutWebAppServer Lesson 6 - Simple login and session data2009-05-17T08:58:50Z<p>Fpiette: </p>
<hr />
<div>During this lesson, you will learn how to handle session data. As you probably know, HTTP is a stateless protocol. This means that each request is totally indepedent from each other as far as HTTP protocol is concerned. A web application is made of a lot of HTTP requests as the user interact with the application. Because of the stateless nature of the HTTP protocol, your web application cannot rely on HTTP to have each page of the application know it is part of a single application used by a particular user at a given time. It is the application programmer's responsibility to make the application pages seen as a whole application, that is having a page content or behaviour affected by what the user has done previously with the application.<br />
<br />
The application programmer has the need to have a data structure, at server side, with values private to a given user for the duration of his activity with the application. Of course since we are building a server application, we can have many users connected at the same time. The developper need a different data instance for each user. We will refer to this kind of data as "session data" in the remaining lessons. <br />
<br />
Don't be scary, ICS HttpAppServer component and the user browser will help you achieve that goal.<br />
<br />
From the user perspective, a session begin when he starts working with the application and ends when he stop working with the application. Usually the user is presented a login screen at the start of his working session, and simply close his browser or select some "logout" link to end his session.<br />
<br />
Login screen is not mandatory. You may want to begin a session with any page from the application and create the session from there without ever asking the user to identify itself. Consider this as a kind of login where actually no usercode/password is checked but everything else is done.<br />
<br />
In this lesson we will create a simple login page, create a data structure to hold data for the user session, create a simple dynamic page protected by the login and showing data saved in the session. The later will be the page shown immediately after login. <br />
<br />
==== Steps ====<br />
<br />
<ol><br />
<li> Create a new template containing the login form. We do a dynamic page because frequently login is done from the main page which almost contain dynamic data. For simplicity here our page will only show the current time at server side. Enter the following code into the body part of the document:<br />
<tt><br />
::: <form action="/DoSimpleLogin.html"<br />
:::::: method="GET"<br />
:::::: enctype="application/x-www-form-urlencoded"><br />
:::: Usercode <input type="TEXT" name="UserCode"><br><br />
:::: Password <input type="PASSWORD" name="Password"><br><br />
:::: <input type="SUBMIT" value="Login"><br><br />
:::: <br><br />
:::: <br>Server time is <#ServerTime><br />
::: </form><br />
</tt><br />
Save the HTML file in the templates folder under the name "SimpleLogin.html".</li><br />
<li> Create a new template containing the simple page accessible only after login and showing some session data. Here after is the HTML code you have to enter into the body part of the document:<br />
<tt><br />
::: If you see this page, then you have a valid session.<br><br />
::: You logged at <#LoginTime><br><br />
::: Your user code is <#UserCode><br><br />
::: You already saw this page <#PageCount> times since you logged in.<br><br />
</tt><br />
Save the HTML file in the templates folder under the name "SimpleMainPage.html".</li><br />
</li><br />
<li> Create a new Delphi unit "OverbyteIcsTutWebAppServerSimpleLogin.pas". You will write the classes TUrlHandlerSimpleLogin and TUrlHandlerDoSimpleLogin containing the code to handle the login process: one class for the login form and one class for the login form action. You will also have the class TUrlHandlerSimpleMainPage to handle the main page, that is the result page shown when login is OK.<br />
</li><br />
<li> Map the classes to the url. In TTutWebAppServerMainForm.FormShow, add the following lines after the similar already there: <br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleLogin.Html', TUrlHandlerSimpleLogin);<br />
::: HttpAppSrv1.AddGetHandler('/DoSimpleLogin.html', TUrlHandlerDoSimpleLogin);<br />
::: HttpAppSrv1.AddGetHandler('/SimpleMainPage.html', TUrlHandlerSimpleMainPage);<br />
</tt><br />
</li><br />
<li> Create the supporting 3 classes. For now, we just build basic code which doesn't do an actual login. This is just to verify that everything is OK until now. The class declaration part of unit "OverbyteIcsTutWebAppServerSimpleLogin.pas" looks like:<br />
<tt><br />
::: TUrlHandlerSimpleLogin = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br><br />
::: TUrlHandlerDoSimpleLogin = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br><br />
::: TUrlHandlerSimpleMainPage = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
</tt><br />
And the implementation looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerSimpleLogin.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleLogin.html', nil,<br />
:::::: ['ServerTime', DateTimeToStr(Now)]);<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerDoSimpleLogin.Execute;<br />
:::'''var'''<br />
:::: Location : '''String;'''<br />
:::'''begin'''<br />
:::: Location := '/SimpleMainPage.html';<br />
:::: AnswerString('302 moved', '',<br />
:::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::::: '<A HREF="' + Location + '">Click here</A>');<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerSimpleMainPage.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage('', NO_CACHE, 'SimpleMainPage.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
Now you can hit F9 to compile and run the server. Then point your browser to http://127.0.0.1:20080/SimpleLogin.html. You should see the login page displayed in the browser with the server time properly displayed. Enter any value in usercode and password fields (we don't check those values yet) and click the login button. You should see the SimpleMainPage displayed.</li><br />
<li>Since the login is not working yet, you can verify that you have an unrestricted access to SimpleMainPage.html: Restart your browser and enter http://127.0.0.1:20080/SimpleMainPage.html. You can see that page normally. This is the expected behaviour now. We will change this to protect the page by the login: the user will be forced to pass by the login process to successfuly access the page.<br />
</li><br />
<li> Now we will create a new class in a new Delphi unit. This class will be our session data. Do File / New / Other / Delphi Project / Delphi Files / Unit. Save it under the name OverbyteIcsTutWebAppServerSessionData.pas.</li><br />
<li>For now, we will use very simple session data: we will keep usercode and login time so that it is available during the whole session. Create a class like this:<br />
<tt><br />
::: TAppSrvSessionData = '''class'''(TWebSessionData)<br />
::: '''private'''<br />
:::: FUserCode: '''String;'''<br />
:::: FLoginTime: TDateTime;<br />
:::: FLoggedOn: Boolean;<br />
::: '''published'''<br />
:::: '''property''' UserCode : '''String''' '''read''' FUserCode '''write''' FUserCode;<br />
:::: '''property''' LoginTime : TDateTime '''read''' FLoginTime '''write''' FLoginTime;<br />
:::: '''property''' LoggedOn : Boolean '''read''' FLoggedOn '''write''' FLoggedOn;<br />
::: '''end;'''<br />
</tt><br />
Every data you want in your session data must be declared as published. This is fundamental to have persistance.<br />
</li><br />
<li>Register your session data class. Add this code at the end of the unit, just before the final "end.".<br />
<tt><br />
:::'''initialization'''<br />
:::: RegisterClass(TAppSrvSessionData);<br />
</tt></li><br />
<li> Add OverbyteIcsTutWebAppServerSessionData unit to OverbyteIcsTutWebAppServerSimpleLogin.paz uses clause.</li><br />
<li>Change TUrlHandlerSimpleLogin.Execute to create the session when the user request the login page. <br />
<tt><br />
:::'''procedure''' TUrlHandlerSimpleLogin.Execute;<br />
:::'''var'''<br />
:::: MySessionData : TAppSrvSessionData;<br />
:::: Headers : '''String;'''<br />
:::'''begin'''<br />
:::: '''if not''' ValidateSession '''then begin'''<br />
::::: Inc(GSessionDataCount);<br />
::::: MySessionData := TAppSrvSessionData.Create(nil);<br />
::::: MySessionData.Name := 'MySessionData' + IntToStr(GSessionDataCount);<br />
::::: Headers := NO_CACHE + CreateSession('', 0, MySessionData);<br />
:::: '''end'''<br />
:::: '''else begin'''<br />
::::: MySessionData := WSession.SessionData as TAppSrvSessionData;<br />
::::: Headers := NO_CACHE;<br />
:::: '''end;'''<br />
:::: MySessionData.LoggedOn := FALSE;<br />
:::<br><br />
:::: AnswerPage(&rsquo;&rsquo;, Headers, 'SimpleLogin.html', nil,<br />
:::::: ['ServerTime', DateTimeToStr(Now)]);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
The code above check for a valid session. If a valid session exists, then it is reused, otherwise a new one is created with new session data. Note that the session must be given a unique name. That's why we used the global integer variable GSessionDataCount which is incremented when a new session is created. <br />
</li><br />
<li>Create a global variable like this:<br />
<tt><br />
:::'''var'''<br />
:::: GSessionDataCount : Integer;<br />
</tt><br />
</li><br />
<li> Modify the code in TUrlHandlerDoSimpleLogin to extract usercode and password, and verify them against the user database. Since we are in a simple tutorial, we won't use a database but simply hard code a test for usercode "root" and password "admin". You'll easily adapt the code to fetch paswword from any database and verify validity more realisticly. The code is like this:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoSimpleLogin.Execute;<br />
:::'''var'''<br />
:::: UserCode : '''String;'''<br />
:::: Password : '''String;'''<br />
:::: Location : '''String;'''<br />
:::: SessionData : TAppSrvSessionData;<br />
:::'''begin'''<br />
:::: '''if not''' ValidateSession '''then begin'''<br />
::::: Location := '/SimpleLogin.html';<br />
:::: '''end'''<br />
:::: '''else begin'''<br />
::::: SessionData := WSession.SessionData '''as''' TAppSrvSessionData;<br />
::::: ExtractURLEncodedValue(Params, 'Password', Password);<br />
::::: ExtractURLEncodedValue(Params, 'UserCode', UserCode);<br />
:::<br><br />
::::: '''if not''' (SameText(UserCode, 'root') '''and''' SameText(Password, 'admin')) '''then begin'''<br />
:::::: DeleteSession;<br />
:::::: Location := '/SimpleLogin.html';<br />
::::: '''end'''<br />
::::: '''else begin'''<br />
:::::: SessionData.LoginTime := Now;<br />
:::::: SessionData.UserCode := UserCode;<br />
:::::: SessionData.LoggedOn := TRUE;<br />
:::::: Location := '/SimpleMainPage.html';<br />
::::: '''end;'''<br />
:::: '''end;'''<br />
:::: AnswerString('302 moved', &rsquo;&rsquo;,<br />
:::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::::: '<A HREF="' + Location + '">Click here</A>');<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
In the above code, we do a serie of checks and then redirect to some page according to the check results. For simplicity we redirect to the SimpleLogin page if anything is wrong or missing and to SimpleMainPage if usercode and password are OK.<br><br />
We first check for a valid session. We have a valid session if the user already loaded the SimpleLogin page because we create the session there.<br><br />
Then we extract usercode and password from the request parameters (they are comming from the HTML form) and verify their values. If not OK, we redirect to SimpleLogin. If correct, we save UserCode and Password into session data and we set the LoggedOn flag in the session data.<br><br />
The idea behing this LoggedOn flag is that we can have a valid session because the user has seen the login page, but not authenticated the user since the user has not given his usercode and password. In this tutorial, we only create the session from the login page, but as we have seen above, the session could be created anywhere in the application. Probably at many places, we don't care about who is the user and at some place we need to authenticate the user before continuing. We have to make distinction between having a valid session and having an authenticated user. This is common is eCommerce website. We need to authenticate the user only to checkout his shopping cart. The process of shopping can be conduced without actually knowing who is the user. The shopping cart is just part of the session data.<br><br />
You can hit F9 to compile and run the server. Point you browser to http://127.0.0.1:20080/SimpleLogin.html, enter the usercode "john" and password "abc" anc click login. You should get back to the SimpleLogin page since the usercode and password is invalid. Try with "root" and "admin". You should see SimpleMainPage.<br />
</li><br />
<li>Now that we have our login process operational, we will protect SimpleMainPage from anonymous access. That is we will force the user to be logged on before showing the actual page. To do that, we simply have to validate the session and check the LoggedOn flag. If not OK, we will redirect the user to the login page.<br><br />
Modify the code in TUrlHandlerSimpleMainPage.Execute so that it looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerSimpleMainPage.Execute;<br />
:::'''var'''<br />
:::: Location : '''String;'''<br />
:::: SessionData : TAppSrvSessionData;<br />
:::'''begin'''<br />
:::: Location := &rsquo;&rsquo;;<br />
:::: SessionData := nil;<br />
:::: '''if not''' ValidateSession '''then'''<br />
::::: Location := '/SimpleLogin.html'<br />
:::: '''else begin'''<br />
::::: SessionData := WSession.SessionData '''as''' TAppSrvSessionData;<br />
::::: '''if not''' SessionData.LoggedOn '''then'''<br />
:::::: Location := '/SimpleLogin.html';<br />
:::: '''end;'''<br />
:::<br><br />
:::: '''if''' Location = &rsquo;&rsquo; '''then'''<br />
::::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleMainPage.html', nil,<br />
::::::: ['UserCode', SessionData.UserCode,<br />
::::::: 'LoginTime', DateTimeToStr(SessionData.LoginTime)])<br />
:::: '''else'''<br />
::::: AnswerString('302 moved', '',<br />
::::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
::::::: '<A HREF="' + Location + '">Click here</A>');<br />
:::: '''Finish''';<br />
:::end;<br />
</tt><br />
Hit F9 to compile and run the server.Point you browser to http://127.0.0.1:20080/SimpleMainPage.html. You should be redirected to SimpleLogin page since you hve not yet logged on. Enter a "root" and "admin" as usercode and password. You should see the SimpleMainPage. Navigate somewhere else without closing your browser and then enter http://127.0.0.1:20080/SimpleMainPage.html. This time you should see the page immediately since you already logged in. If you close your browser or close the server program, you'll be again redirected to the login page. Our goal is reached: SimpleMainPage is protected by the login.<br />
</li><br />
<li>There is one more step in the lesson showing how to use session data from a webpage. For simplicity, we will simple count the number of times the user has seen the SimpleMainPage since he logged in.<br><br />
Create a new property MainPageCount in TAppSrvSessionData class:<br />
<tt><br />
::: '''private'''<br />
:::: FMainPageCount : Integer;<br />
::: '''published'''<br />
:::: '''property''' MainPageCount : Integer '''read''' FMainPageCount '''write''' FMainPageCount;<br />
</tt><br />
</li><br />
<li>Using the new MainPageCount property is easy. You have direct access to it and do whatever you like. Any change is persistent as long as the session exists. Change the code in TUrlHandlerSimpleMainPage.Execute so that it looks like:<br />
<tt><br />
:::: '''if''' Location = &rsquo;&rsquo; '''then begin'''<br />
::::: SessionData.MainPageCount := SessionData.MainPageCount + 1;<br />
::::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleMainPage.html', nil,<br />
::::::: ['UserCode', SessionData.UserCode,<br />
::::::: 'LoginTime', DateTimeToStr(SessionData.LoginTime),<br />
::::::: 'PageCount', SessionData.MainPageCount])<br />
:::: '''end'''<br />
</tt><br />
</li><br />
/ol><br />
<br><br><br><br />
==== Summary ====<br />
In this lesson you learned that session data is persistent data during the time the user intercat with your website. You learend how to create a class to define and store your session data. You learned how to create a session and use it to remember a user has been authenticated. You also used it to count the number of access for a given user.<br />
<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 7 - Dynamic images|Dynamic images]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 5 - Relocation|Relocation]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2301TutWebAppServer2009-05-04T18:41:24Z<p>Fpiette: Split of the page into one page per lesson</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
<br />
== Source code ==<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to4.zip Lesson 1 to 4]<br />
<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
== Lessons ==<br />
[[TutWebAppServer Lesson 1 - Hello World|Lesson 1 - Hello World]]<br><br />
[[TutWebAppServer Lesson 2 - Hello Today|Lesson 2 - Hello Today]]<br><br />
[[TutWebAppServer Lesson 3 - Simple data entry and processing|Lesson 3 - Simple data entry and processing]]<br><br />
[[TutWebAppServer Lesson 4 - Building tables|Lesson 4 - Building tables]]<br><br />
[[TutWebAppServer Lesson 5 - Relocation|Lesson 5 - Relocation]]<br><br />
[[TutWebAppServer Lesson 6 - Simple login and session data|Lesson 6 - Simple login and session data]]<br><br />
[[TutWebAppServer Lesson 7 - Dynamic images|Lesson 7 - Dynamic images]]<br><br />
[[TutWebAppServer Lesson 8 - Asynchronous answer|Lesson 8 - Asynchronous answer]]<br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_5_-_Relocation&diff=2300TutWebAppServer Lesson 5 - Relocation2009-05-04T18:33:42Z<p>Fpiette: </p>
<hr />
<div>In this lesson you will learn how to redirect the client to another URL. This is the relocation process. Under some conditions, you may determine that the requested page is not the correct one. Instead of telling the user where the page is, you may instruct his browser to go directly to that page. In the next lesson, we will see a good place for a relocation: when a user has not logged on yet and can't be grant access to a page. He is then relocated to the login page. For now, we will do something simpler to demonstrate how to do the relocation: we will provide an URL taking one parameter. If that parameter is even, then the user is redirected to a given page and if the parameter is odd, the user is redirected to another page. We will redirect to static pages but there is defenitely no difference relocating to a dynamic page. It's just a matter of the redirection URL.<br />
<br />
Let assume the URL is: <br />
* http://127.0.0.1:20080/RelocateMe?parameter=1<br />
* The even page is RelocateMeEven.html<br />
* The odd page is RelocateMeOdd.html<br />
<br />
== Steps ==<br />
<ol><br />
<li>Write the RelocateMeEven.html static page. Just enter this in the body:<br />
<tt><br />
Even !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeEven.html.<br />
</li><br />
<li>Write the RelocateMeOdd.html static page. Just enter this in the body:<br />
<tt><br />
Odd !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeOdd.html.<br />
</li><br />
<li> Create a new Delphi unit "OverbyteIcsTutWebAppServerRedirectionDemo.pas". Create a new class to handle the URL. The code looks like:<br />
<tt><br />
:::unit OverbyteIcsTutWebAppServerRedirectionDemo;<br />
::::<br><br />
:::interface<br />
::::<br><br />
:::'''uses'''<br />
:::: Windows, SysUtils, Classes, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::::<br><br />
:::'''type'''<br />
:::: TUrlHandlerRelocateMe = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
::::<br><br />
::::<br><br />
:::'''implementation'''<br />
::::<br><br />
:::'''procedure''' TUrlHandlerRelocateMe.Execute;<br />
:::'''var'''<br />
:::: Parameter : '''String;'''<br />
:::: Location : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'Parameter', Parameter);<br />
:::: '''if''' (StrToIntDef(Parameter, 0) and 1) = 0 '''then'''<br />
::::: Location := '/RelocateMeEven.html'<br />
:::: '''else'''<br />
::::: Location := '/RelocateMeOdd.html';<br />
:::: AnswerString('302 moved', &rsquo;&rsquo;, <br />
:::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::::: '&lt;h tml&gt;&lt;body&gt;&lt;a HREF="' + Location + '"&gt;Click here&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;');<br />
:::: Finish;<br />
:::'''end;'''<br />
::::<br><br />
:::'''end.'''<br />
</tt><br />
As you can see in the code, a relocation is done by sending anything to the client with status "302 moved" and a "location" header line with the new URL. Here we send a simple HTML document without even bothering with a HTML file. The HTML document is given by a string. Of course we could have used an HTML file. <br />
<br />
Why do we return a document ? Because it may happend that the URL is accessed using something that do not automatically follow relocation. The document provide a simple link the user will have to click in case his browser is configured to ignore relocation.<br />
</li><br />
<li> Now map the URL handler class to the actual URL. Add a single line in TTutWebAppServerMainForm.FormShow:<br />
<tt><br />
HttpAppSrv1.AddGetHandler('/RelocateMe', TUrlHandlerRelocateMe);<br />
</tt><br />
Don't forget to add the unit name to the uses clause so that the compiler understand the class name.<br />
</li><br />
<li> You can now point your browser to http://127.0.0.1:20080/RelocateMe?parameter=1 and test. You should get the "Odd" page since the parameter is odd. Enter http://127.0.0.1:20080/RelocateMe?parameter=2 and you should get the "Even" page.<br />
Please pay attention to the URL displayed in your browser: it is the Odd or Even page's URL. This is typical of a relocation: the browser shows the url of the destination page.<br />
</li><br />
</ol><br />
<br><br><br />
== Summary ==<br />
During this lesson, you learned how to instruct the client browser to display the page from another location. You know that this process is known as "relocation".<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 6 - Simple login and session data|Simple login and session data]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 4 - Building tables|Building tables]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_4_-_Building_tables&diff=2299TutWebAppServer Lesson 4 - Building tables2009-05-04T18:31:49Z<p>Fpiette: </p>
<hr />
<div>During this lesson, you will learn how to build a table with a variable number of rows containing dynamic data. In a typical application, a table is used to show the result of a database query (for example a list of items matching a given search criteria) or to build a list of items to fill a HTML combobox or anything else repetitive.<br />
<br />
In this lesson, to avoid database stuff we have not yet learned, we will do something simple and yet useful: We will create a password generator. The user will be presented a form where he can enter the number of passwords he wants. The program will generated those passwords and present them in a nice HTML table.<br />
<br />
Since we already learned how to handle HTML forms to enter data, I will quickly pass over those steps to come directly tho this lesson's objective: generate a table.<br />
<br />
== Steps ==<br />
<ol><br />
<li> Create the entry form to enter the number of passwords the user want to get. Save the form to c:\icstutorial\templates\GenerateTable.html. Create the code to handle the form and to get the value back. Save the code into a new unit named OverbyteIcsTutWebAppServerGenerateTable.pas. Name the two classes TUrlHandlerGenerateTable and TUrlHandlerDoGenerateTable. Map the two classes to the URL GenerateTable.html and DoGenerateTable.html. For detailed steps, please see lesson 2.<br />
<br><br />
The HTML form include the following code:<br />
<tt><br />
::: <form action="DoGenerateTable.html"<br />
::::: method="GET"<br />
::::: enctype="application/x-www-form-urlencoded"><br />
:::: Enter the number of passwords you want<br />
:::: <input type="TEXT" name="PasswordCount" size="3"><br />
:::: <input type="SUBMIT" value="Generate"><br />
::: </form><br />
</tt><br />
<br><br />
The unfinished new Delphi unit looks like:<br />
<tt><br />
:::'''unit''' OverbyteIcsTutWebAppServerGenerateTable;<br />
:::<br><br />
:::'''interface'''<br />
:::<br><br />
:::'''uses'''<br />
:::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
:::<br><br />
:::'''type'''<br />
:::: TUrlHandlerGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::: TUrlHandlerDoGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::'''implementation'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerGenerateTable.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GenerateTable.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: // Here comes the processing and the AnswerPage<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''end.'''<br />
</tt><br />
<br><br />
The two lines to be inserted in TTutWebAppServerMainForm.FormShow to map the URL are:<br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/GenerateTable.html', TUrlHandlerGenerateTable);<br />
:::: HttpAppSrv1.AddGetHandler('/DoGenerateTable.html', TUrlHandlerDoGenerateTable);<br />
</tt><br />
</li><br />
<li> Write the code to generate the requested number of passwords. Here we have two options: either generate all passwords before generating the actual table, or generate the passwords on the fly while generating each table row. Since the first option gives a code easier to understand, I will use it. The passwords will be generated in a TStringList which will be used later when generating each table row.<br />
<br><br />
Passwords will be generated using Delphi random generator. For simplicity, we will generate passwords containing uppercase and lowercase letters plus all ten digits. Passwords will have 12 characters.<br />
<br><br />
The code looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GeneratePasswords(PasswordCount: Integer);<br />
:::'''var'''<br />
:::: Password : '''String;'''<br />
:::: I : '''Integer;'''<br />
:::'''const'''<br />
:::: PasswordLen = 12;<br />
:::: PasswordChars : '''String''' = 'abcdefghijklmnopqrstuvwxyz' +<br />
:::::::: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +<br />
:::::::: '0123456789';<br />
:::'''begin'''<br />
:::: RandSeed := GetTickCount;<br />
:::: FPasswords := TStringList.Create;<br />
:::: SetLength(Password, PasswordLen);<br />
:::: '''while''' PasswordCount > 0 '''do begin'''<br />
::::: '''for''' I := 1 '''to''' PasswordLen '''do'''<br />
:::::: Password[I] := PasswordChars[1 + Random(Length(PasswordChars))];<br />
::::: FPasswords.Add(Password);<br />
::::: Dec(PasswordCount);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Now that we have a function to generate the passwords, we may use it into the simple procedure TUrlHandlerDoGenerateTable we wrote before:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: GeneratePasswords(StrToInt(PasswordCount));<br />
:::: OnGetRowData := GetRowData;<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GeneratePasswordResult.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
You can see here a new comer: OnGetRowData. This is a kind of event which will be called by AnswerPage whenever a table is found in the template file. A table is marked in a template file using the special tag <#table_rows>. The next step show how to use that tag.</li><br />
<li> Create a new HTML template file for presenting the password list and name it GeneratePasswordResult.html. We will build a real HTML table here. There is nothing special about the HTML table except we only create one row and surround it with the special tags <#table_rows> and <#/table_rows>. When AnswerPage will find the first tag, it starts repeating the bloc until the second tag. In each iteration it call the OnGetRowData event handler to get the data and know if there are more rows.<br />
<br />
Here is how the HTML source code looks like in the body of the HTML file:<br />
<tt><br />
::: &lt;table><br />
:::: &lt;tr>&lt;td>N°&lt;/td>&lt;td>Password&lt;/td>&lt;/tr><br />
:::: &lt;#table_rows PasswordTable><br />
::::: &lt;tr>&lt;td>&lt;#Row>&lt;/td>&lt;td>&lt;#Password>&lt;/td>&lt;/tr><br />
:::: &lt;#/table_rows><br />
::: &lt;/table><br />
</tt><br />
You see a parameter within <#table_rows>. It is used in OnGetRowData so that Delphi code knows which table is currently built because a single HTML template can have multiple tables and tables may be nested.<br />
</li><br />
<li> Write the OnGetRowData event handler with the following code:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;<br />
:::: '''const''' TableName: '''String;''' Row: Integer; TagData: TStringIndex;<br />
:::: '''var''' More: Boolean; UserData: TObject);<br />
:::'''begin'''<br />
:::: More := Assigned(FPasswords) and (Row <= FPasswords.Count);<br />
:::: '''if''' More '''then begin'''<br />
::::: TagData.Add('Row', IntToStr(Row));<br />
::::: TagData.Add('Password', FPasswords[Row - 1]);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
OnGetRowData event handler is called again and again by AnswerPage when a table_rows tag is found. Actually it is called once per data row. AnswerPage stops calling it when the var argument named "more" is set to FALSE. The main purpose of the handler is to call TagData.Add to specify values for the special tags within the table rows. Here we have defined two of them in our template file: "Row" and "Password". The event handler has also to set the var argument More according to the fact that we have more records. Here we set More according to the row index given by the argument "Row" compared to the password stringlist count.<br />
</li><br />
<li> One more step is needed to free the stringlist holding all password. We do that in the destructor:<br />
<tt><br />
:::'''destructor''' TUrlHandlerDoGenerateTable.Destroy;<br />
:::'''begin'''<br />
:::: FreeAndNil(FPasswords);<br />
:::: '''inherited;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li>You can now hit F9 to compile and run the application. Then point your browser to http://127.0.0.1:20080/GenerateTable.html, enter a value and click the button. You you see the table built and filled with the number of passwords you requested.<br />
</ol><br />
<br><br><br />
<br />
== Summary ==<br />
In this lesson you learned how to created a template file having a table and to write code to feed the table rows with dynamic data. You know how to use <#table_rows> tag and how to write a OnGetRowData handler to fetch data for your table.<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 5 - Relocation|Relocation]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 3 - Simple data entry and processing|Simple data entry and processing]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_3_-_Simple_data_entry_and_processing&diff=2298TutWebAppServer Lesson 3 - Simple data entry and processing2009-05-04T18:31:04Z<p>Fpiette: </p>
<hr />
<div>During this lesson, you will learn how to present a data entry form to the user, process entered data and produce a result page. For simplicity, we will use a simple form to enter two numbers, an operator and provide the result in another simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
== Steps ==<br />
<ol><br />
<li>Create a template HTML file for the calculator. Let's name that file SimpleCalculator.html and save it in the template folder we have located at "c:\icstutorial\templates". Menu / File / New / Others / Web documents / HTML page. Add the following HTML code as body:<br />
<tt><br />
:: <form action="DoSimpleCalculator.html"<br />
:::: method="get"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
::: Number 1 <input name="Number1"><br><br />
::: Operator <select name="Operator"><br />
::::: <option>Add</option><br />
::::: <option>Multiply></option><br />
::::: </select><br><br />
::: Number 2 <input name="Number2" type="TEXT"><br><br />
::: <input name="Submit" type="SUBMIT" value="Compute"><br />
:: </form><br />
</tt></li><br />
<li>Create a new unit to hold the calculator code. Menu / File / New / Delphi Unit. Save the unit as "OverbyteIcsTutWebAppServerSimpleCalculator.pas".</li><br />
<li> Create the class to deliver the calculator's form. Actually we could have done a static page as well. Since we made a template, we need to write a class and map the class to the URL. The class and his implementation are quite straigthforward:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::<br />
::'''type'''<br />
::: TUrlHandlerSimpleCaculator = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br />
::'''implementation'''<br />
::<br />
:::'''procedure''' TUrlHandlerSimpleCaculator.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, NO_CACHE, 'SimpleCalculator.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Mapping the class to the URL is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. In order to reference the class, we must also add OverbyteIcsTutWebAppServerSimpleCalculator to the uses clause in OverbyteIcsTutWebAppServerMain.pas.<br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleCalculator.html', TUrlHandlerSimpleCaculator);<br />
</tt><br />
</li><br />
<li>At this stage, you can save all (CTRL-SHIFT-S), compile and run (F9) the application. Then point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You should see the HTML form. If you click the Compute button, you get a 404 error since we have not implemented the form action yet. Let's do it. Stop the program and execute the next steps.</li><br />
<li>Create the class to implement the calculator operation. In the HTML form above, we named the action "DoSimpleCalculator.html", so we will name the class "TUrlHandlerDoSimpleCalculator". We write the class in OverbyteIcsTutWebAppServerSimpleCalculator.pas unit. The declaration looks like:<br />
<tt><br />
:: TUrlHandlerDoSimpleCalculator = '''class'''(TUrlHandler)<br />
:: '''public'''<br />
::: '''procedure''' Execute; '''override;'''<br />
:: '''end;'''<br />
</tt></li><br />
<li>Now write the code for the execute procedure. In this code we have to get the values entered by the user thru the HTML form we have designed. There are 3 fields we named "Number1", "Number2" and "Operator". The form definition specify method "get" and encoding "application/x-www-form-urlencoded". Those values directly impact how we received the values in Delphi. The HTTP server component unit has a function "ExtractURLEncodedValue" designed to get such value. It takes 3 arguments. The first is the parameters sent by the browser, the second is the name of the field and the third is a reference to the string variable to hold the result. The function return a boolean telling if the named parameter is found or not.<br><br />
All in all we have to define 3 variable and call the method 3 times to get their values. Up to here, the code looks like:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String''';<br />
::: N2 : '''String''';<br />
::: Op : '''String''';<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::'''end''';<br />
</tt></li><br />
<li>Now we have to do the computation. Be aware the every parameter is returned as a string. We have to do convertion to be able to compute the result. To hold the result, add an integer variable and name it "R". Add the following lines to the Execute procedure:<br />
<tt><br />
:: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
:: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
:: '''else'''<br />
::: R := 0;<br />
</tt><br />
For simplicity, we have not written any validation nor any exception handling. We are just demonstrating dynamic web design, not Delphi programmming best practices.</li><br />
<li>To display the result, we have to prepare a HTML template and used it to send the answer page to the client's browser. Menu / File / New / Other / Web Document / HTML page. Name the file "SimpleCalculatorResult.html" and save it in the templates directory. As HTML body, write this HTML code:<br />
<tt><br />
:: <#Operator>(<#Number1>, <#Number2>) = <#Result><br />
:: <a href="SimpleCalculator.html">Continue</a><br />
</tt><br />
This HTML code make use of 4 special tags named "Number1", "Number2", "Operator" and "Result". Those tags will be replaced by the actual values we provide by code when calling AnswerPage. The final code for the Execute procedure looks like this:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String;'''<br />
::: N2 : '''String;'''<br />
::: Op : '''String;'''<br />
::: R : '''Integer;'''<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::: '''if''' SameText(Op, 'Add') '''then'''<br />
:::: R := StrToInt(N1) + StrToInt(N2)<br />
::: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
:::: R := StrToInt(N1) * StrToInt(N2)<br />
::: '''else'''<br />
:::: R := 0;<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleCalculatorResult.html', nil,<br />
:::::: ['Number1', N1, 'Number2', N2, 'Operator', Op, 'Result', R]);<br />
::: Finish;<br />
::'''end''';<br />
</tt><br />
You can see that we used NO_CACHE constant in the call to AnswerPage. This constant instruct the client browser to not store the page into his cache. This is very important since it is a dynamic page. If the client navigator store the page in his cache, then the user would see an old version showing old results.<br />
</li><br />
<li>Finally, we have to map our class to an URL. This is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. <br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/DoSimpleCalculator.html', TUrlHandlerDoSimpleCalculator);<br />
</tt><br />
<li>Hit F9 to compile and run the application. Point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You can enter values and submit. You should get the expected result page.</li><br />
</ol><br><br />
<br />
== Summary ==<br />
In this lesson you learned how to get back data from a HTML form, do some processing with it and produce a result page. You also learned how to instruct the client navigator to not store an answer page to his cache.<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 4 - Building tables|Building tables]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 2 - Hello Today|Hello Today]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_2_-_Hello_Today&diff=2297TutWebAppServer Lesson 2 - Hello Today2009-05-04T18:30:25Z<p>Fpiette: </p>
<hr />
<div>Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
== Steps ==<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
== Summary ==<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 3 - Simple data entry and processing|Simple data entry and processing]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 1 - Hello World|Hello World]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_1_-_Hello_World&diff=2296TutWebAppServer Lesson 1 - Hello World2009-05-04T18:29:40Z<p>Fpiette: </p>
<hr />
<div>During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
== Steps ==<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
== Summary ==<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 2 - Hello Today|Hello Today]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_5_-_Relocation&diff=2295TutWebAppServer Lesson 5 - Relocation2009-05-04T18:27:40Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 5 : Relocation ===<br />
In this lesson you will learn how to redirect the client to another URL. This is the relocation process. Under some conditions, you may determine that the requested page is not the correct one. Instead of telling the user where the page is, you may instruct his browser to go directly to that page. In the next lesson, we will see a good place for a relocation: when a user has not logged on yet and can't be grant access to a page. He is then relocated to the login page. For now, we will do something simpler to demonstrate how to do the relocation: we will provide an URL taking one parameter. If that parameter is even, then the user is redirected to a given page and if the parameter is odd, the user is redirected to another page. We will redirect to static pages but there is defenitely no difference relocating to a dynamic page. It's just a matter of the redirection URL.<br />
<br />
Let assume the URL is: <br />
* http://127.0.0.1:20080/RelocateMe?parameter=1<br />
* The even page is RelocateMeEven.html<br />
* The odd page is RelocateMeOdd.html<br />
<br />
==== Steps ====<br />
<ol><br />
<li>Write the RelocateMeEven.html static page. Just enter this in the body:<br />
<tt><br />
Even !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeEven.html.<br />
</li><br />
<li>Write the RelocateMeOdd.html static page. Just enter this in the body:<br />
<tt><br />
Odd !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeOdd.html.<br />
</li><br />
<li> Create a new Delphi unit "OverbyteIcsTutWebAppServerRedirectionDemo.pas". Create a new class to handle the URL. The code looks like:<br />
<tt><br />
:::unit OverbyteIcsTutWebAppServerRedirectionDemo;<br />
::::<br><br />
:::interface<br />
::::<br><br />
:::'''uses'''<br />
:::: Windows, SysUtils, Classes, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::::<br><br />
:::'''type'''<br />
:::: TUrlHandlerRelocateMe = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
::::<br><br />
::::<br><br />
:::'''implementation'''<br />
::::<br><br />
:::'''procedure''' TUrlHandlerRelocateMe.Execute;<br />
:::'''var'''<br />
:::: Parameter : '''String;'''<br />
:::: Location : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'Parameter', Parameter);<br />
:::: '''if''' (StrToIntDef(Parameter, 0) and 1) = 0 '''then'''<br />
::::: Location := '/RelocateMeEven.html'<br />
:::: '''else'''<br />
::::: Location := '/RelocateMeOdd.html';<br />
:::: AnswerString('302 moved', &rsquo;&rsquo;, <br />
:::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::::: '&lt;h tml&gt;&lt;body&gt;&lt;a HREF="' + Location + '"&gt;Click here&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;');<br />
:::: Finish;<br />
:::'''end;'''<br />
::::<br><br />
:::'''end.'''<br />
</tt><br />
As you can see in the code, a relocation is done by sending anything to the client with status "302 moved" and a "location" header line with the new URL. Here we send a simple HTML document without even bothering with a HTML file. The HTML document is given by a string. Of course we could have used an HTML file. <br />
<br />
Why do we return a document ? Because it may happend that the URL is accessed using something that do not automatically follow relocation. The document provide a simple link the user will have to click in case his browser is configured to ignore relocation.<br />
</li><br />
<li> Now map the URL handler class to the actual URL. Add a single line in TTutWebAppServerMainForm.FormShow:<br />
<tt><br />
HttpAppSrv1.AddGetHandler('/RelocateMe', TUrlHandlerRelocateMe);<br />
</tt><br />
Don't forget to add the unit name to the uses clause so that the compiler understand the class name.<br />
</li><br />
<li> You can now point your browser to http://127.0.0.1:20080/RelocateMe?parameter=1 and test. You should get the "Odd" page since the parameter is odd. Enter http://127.0.0.1:20080/RelocateMe?parameter=2 and you should get the "Even" page.<br />
Please pay attention to the URL displayed in your browser: it is the Odd or Even page's URL. This is typical of a relocation: the browser shows the url of the destination page.<br />
</li><br />
</ol><br />
<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 6 - Simple login and session data|Simple login and session data]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 4 - Building tables|Building tables]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_5_-_Relocation&diff=2294TutWebAppServer Lesson 5 - Relocation2009-05-04T18:24:06Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 5 : Relocation ===<br />
In this lesson you will learn how to redirect the client to another URL. This is the relocation process. Under some conditions, you may determine that the requested page is not the correct one. Instead of telling the user where the page is, you may instruct his browser to go directly to that page. In the next lesson, we will see a good place for a relocation: when a user has not logged on yet and can't be grant access to a page. He is then relocated to the login page. For now, we will do something simpler to demonstrate how to do the relocation: we will provide an URL taking one parameter. If that parameter is even, then the user is redirected to a given page and if the parameter is odd, the user is redirected to another page. We will redirect to static pages but there is defenitely no difference relocating to a dynamic page. It's just a matter of the redirection URL.<br />
<br />
Let assume the URL is: <br />
* http://127.0.0.1:20080/RelocateMe?parameter=1<br />
* The even page is RelocateMeEven.html<br />
* The odd page is RelocateMeOdd.html<br />
<br />
==== Steps ====<br />
<ol><br />
<li>Write the RelocateMeEven.html static page. Just enter this in the body:<br />
<tt><br />
Even !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeEven.html.<br />
</li><br />
<li>Write the RelocateMeOdd.html static page. Just enter this in the body:<br />
<tt><br />
Odd !<br><br />
</tt><br />
Save the file in c:\icstutorial\wwwroot\RelocateMeOdd.html.<br />
</li><br />
<li> Create a new Delphi unit "OverbyteIcsTutWebAppServerRedirectionDemo.pas". Create a new class to handle the URL. The code looks like:<br />
<tt><br />
:::unit OverbyteIcsTutWebAppServerRedirectionDemo;<br />
::::<br><br />
:::interface<br />
::::<br><br />
:::'''uses'''<br />
:::: Windows, SysUtils, Classes, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::::<br><br />
:::'''type'''<br />
:::: TUrlHandlerRelocateMe = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
::::<br><br />
::::<br><br />
:::'''implementation'''<br />
::::<br><br />
:::'''procedure''' TUrlHandlerRelocateMe.Execute;<br />
:::'''var'''<br />
:::: Parameter : '''String;'''<br />
:::: Location : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'Parameter', Parameter);<br />
:::: '''if''' (StrToIntDef(Parameter, 0) and 1) = 0 '''then'''<br />
::::: Location := '/RelocateMeEven.html'<br />
:::: '''else'''<br />
::::: Location := '/RelocateMeOdd.html';<br />
:::: AnswerString('302 moved', &rsquo;&rsquo;, <br />
:::::: 'Location: ' + Location + #13#10 + NO_CACHE,<br />
:::::: '&lt;h tml&gt;&lt;body&gt;&lt;a HREF="' + Location + '"&gt;Click here&lt;/a&gt;&lt;/body&gt;&lt;/html&gt;');<br />
:::: Finish;<br />
:::'''end;'''<br />
::::<br><br />
:::'''end.'''<br />
</tt><br />
As you can see in the code, a relocation is done by sending anything to the client with status "302 moved" and a "location" header line with the new URL. Here we send a simple HTML document without even bothering with a HTML file. The HTML document is given by a string. Of course we could have used an HTML file. <br />
<br />
Why do we return a document ? Because it may happend that the URL is accessed using something that do not automatically follow relocation. The document provide a simple link the user will have to click in case his browser is configured to ignore relocation.<br />
</li><br />
<li> Now map the URL handler class to the actual URL. Add a single line in TTutWebAppServerMainForm.FormShow:<br />
<tt><br />
HttpAppSrv1.AddGetHandler('/RelocateMe', TUrlHandlerRelocateMe);<br />
</tt><br />
Don't forget to add the unit name to the uses clause so that the compiler understand the class name.<br />
</li><br />
<li> You can now point your browser to http://127.0.0.1:20080/RelocateMe?parameter=1 and test. You should get the "Odd" page since the parameter is odd. Enter http://127.0.0.1:20080/RelocateMe?parameter=2 and you should get the "Even" page.<br />
Please pay attention to the URL displayed in your browser: it is the Odd or Even page's URL. This is typical of a relocation: the browser shows the url of the destination page.<br />
</li><br />
</ol><br />
<br />
<br><br><br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_4_-_Building_tables&diff=2293TutWebAppServer Lesson 4 - Building tables2009-05-04T18:06:59Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 4 : Building tables ===<br />
During this lesson, you will learn how to build a table with a variable number of rows containing dynamic data. In a typical application, a table is used to show the result of a database query (for example a list of items matching a given search criteria) or to build a list of items to fill a HTML combobox or anything else repetitive.<br />
<br />
In this lesson, to avoid database stuff we have not yet learned, we will do something simple and yet useful: We will create a password generator. The user will be presented a form where he can enter the number of passwords he wants. The program will generated those passwords and present them in a nice HTML table.<br />
<br />
Since we already learned how to handle HTML forms to enter data, I will quickly pass over those steps to come directly tho this lesson's objective: generate a table.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the entry form to enter the number of passwords the user want to get. Save the form to c:\icstutorial\templates\GenerateTable.html. Create the code to handle the form and to get the value back. Save the code into a new unit named OverbyteIcsTutWebAppServerGenerateTable.pas. Name the two classes TUrlHandlerGenerateTable and TUrlHandlerDoGenerateTable. Map the two classes to the URL GenerateTable.html and DoGenerateTable.html. For detailed steps, please see lesson 2.<br />
<br><br />
The HTML form include the following code:<br />
<tt><br />
::: <form action="DoGenerateTable.html"<br />
::::: method="GET"<br />
::::: enctype="application/x-www-form-urlencoded"><br />
:::: Enter the number of passwords you want<br />
:::: <input type="TEXT" name="PasswordCount" size="3"><br />
:::: <input type="SUBMIT" value="Generate"><br />
::: </form><br />
</tt><br />
<br><br />
The unfinished new Delphi unit looks like:<br />
<tt><br />
:::'''unit''' OverbyteIcsTutWebAppServerGenerateTable;<br />
:::<br><br />
:::'''interface'''<br />
:::<br><br />
:::'''uses'''<br />
:::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
:::<br><br />
:::'''type'''<br />
:::: TUrlHandlerGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::: TUrlHandlerDoGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::'''implementation'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerGenerateTable.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GenerateTable.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: // Here comes the processing and the AnswerPage<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''end.'''<br />
</tt><br />
<br><br />
The two lines to be inserted in TTutWebAppServerMainForm.FormShow to map the URL are:<br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/GenerateTable.html', TUrlHandlerGenerateTable);<br />
:::: HttpAppSrv1.AddGetHandler('/DoGenerateTable.html', TUrlHandlerDoGenerateTable);<br />
</tt><br />
</li><br />
<li> Write the code to generate the requested number of passwords. Here we have two options: either generate all passwords before generating the actual table, or generate the passwords on the fly while generating each table row. Since the first option gives a code easier to understand, I will use it. The passwords will be generated in a TStringList which will be used later when generating each table row.<br />
<br><br />
Passwords will be generated using Delphi random generator. For simplicity, we will generate passwords containing uppercase and lowercase letters plus all ten digits. Passwords will have 12 characters.<br />
<br><br />
The code looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GeneratePasswords(PasswordCount: Integer);<br />
:::'''var'''<br />
:::: Password : '''String;'''<br />
:::: I : '''Integer;'''<br />
:::'''const'''<br />
:::: PasswordLen = 12;<br />
:::: PasswordChars : '''String''' = 'abcdefghijklmnopqrstuvwxyz' +<br />
:::::::: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +<br />
:::::::: '0123456789';<br />
:::'''begin'''<br />
:::: RandSeed := GetTickCount;<br />
:::: FPasswords := TStringList.Create;<br />
:::: SetLength(Password, PasswordLen);<br />
:::: '''while''' PasswordCount > 0 '''do begin'''<br />
::::: '''for''' I := 1 '''to''' PasswordLen '''do'''<br />
:::::: Password[I] := PasswordChars[1 + Random(Length(PasswordChars))];<br />
::::: FPasswords.Add(Password);<br />
::::: Dec(PasswordCount);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Now that we have a function to generate the passwords, we may use it into the simple procedure TUrlHandlerDoGenerateTable we wrote before:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: GeneratePasswords(StrToInt(PasswordCount));<br />
:::: OnGetRowData := GetRowData;<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GeneratePasswordResult.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
You can see here a new comer: OnGetRowData. This is a kind of event which will be called by AnswerPage whenever a table is found in the template file. A table is marked in a template file using the special tag <#table_rows>. The next step show how to use that tag.</li><br />
<li> Create a new HTML template file for presenting the password list and name it GeneratePasswordResult.html. We will build a real HTML table here. There is nothing special about the HTML table except we only create one row and surround it with the special tags <#table_rows> and <#/table_rows>. When AnswerPage will find the first tag, it starts repeating the bloc until the second tag. In each iteration it call the OnGetRowData event handler to get the data and know if there are more rows.<br />
<br />
Here is how the HTML source code looks like in the body of the HTML file:<br />
<tt><br />
::: &lt;table><br />
:::: &lt;tr>&lt;td>N°&lt;/td>&lt;td>Password&lt;/td>&lt;/tr><br />
:::: &lt;#table_rows PasswordTable><br />
::::: &lt;tr>&lt;td>&lt;#Row>&lt;/td>&lt;td>&lt;#Password>&lt;/td>&lt;/tr><br />
:::: &lt;#/table_rows><br />
::: &lt;/table><br />
</tt><br />
You see a parameter within <#table_rows>. It is used in OnGetRowData so that Delphi code knows which table is currently built because a single HTML template can have multiple tables and tables may be nested.<br />
</li><br />
<li> Write the OnGetRowData event handler with the following code:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;<br />
:::: '''const''' TableName: '''String;''' Row: Integer; TagData: TStringIndex;<br />
:::: '''var''' More: Boolean; UserData: TObject);<br />
:::'''begin'''<br />
:::: More := Assigned(FPasswords) and (Row <= FPasswords.Count);<br />
:::: '''if''' More '''then begin'''<br />
::::: TagData.Add('Row', IntToStr(Row));<br />
::::: TagData.Add('Password', FPasswords[Row - 1]);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
OnGetRowData event handler is called again and again by AnswerPage when a table_rows tag is found. Actually it is called once per data row. AnswerPage stops calling it when the var argument named "more" is set to FALSE. The main purpose of the handler is to call TagData.Add to specify values for the special tags within the table rows. Here we have defined two of them in our template file: "Row" and "Password". The event handler has also to set the var argument More according to the fact that we have more records. Here we set More according to the row index given by the argument "Row" compared to the password stringlist count.<br />
</li><br />
<li> One more step is needed to free the stringlist holding all password. We do that in the destructor:<br />
<tt><br />
:::'''destructor''' TUrlHandlerDoGenerateTable.Destroy;<br />
:::'''begin'''<br />
:::: FreeAndNil(FPasswords);<br />
:::: '''inherited;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li>You can now hit F9 to compile and run the application. Then point your browser to http://127.0.0.1:20080/GenerateTable.html, enter a value and click the button. You you see the table built and filled with the number of passwords you requested.<br />
</ol><br />
<br><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to created a template file having a table and to write code to feed the table rows with dynamic data. You know how to use <#table_rows> tag and how to write a OnGetRowData handler to fetch data for your table.<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 5 - Relocation|Relocation]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 3 - Simple data entry and processing|Simple data entry and processing]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_3_-_Simple_data_entry_and_processing&diff=2292TutWebAppServer Lesson 3 - Simple data entry and processing2009-05-04T18:03:24Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 3 : Simple data entry and processing ===<br />
During this lesson, you will learn how to present a data entry form to the user, process entered data and produce a result page. For simplicity, we will use a simple form to enter two numbers, an operator and provide the result in another simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
==== Steps ====<br />
<ol><br />
<li>Create a template HTML file for the calculator. Let's name that file SimpleCalculator.html and save it in the template folder we have located at "c:\icstutorial\templates". Menu / File / New / Others / Web documents / HTML page. Add the following HTML code as body:<br />
<tt><br />
:: <form action="DoSimpleCalculator.html"<br />
:::: method="get"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
::: Number 1 <input name="Number1"><br><br />
::: Operator <select name="Operator"><br />
::::: <option>Add</option><br />
::::: <option>Multiply></option><br />
::::: </select><br><br />
::: Number 2 <input name="Number2" type="TEXT"><br><br />
::: <input name="Submit" type="SUBMIT" value="Compute"><br />
:: </form><br />
</tt></li><br />
<li>Create a new unit to hold the calculator code. Menu / File / New / Delphi Unit. Save the unit as "OverbyteIcsTutWebAppServerSimpleCalculator.pas".</li><br />
<li> Create the class to deliver the calculator's form. Actually we could have done a static page as well. Since we made a template, we need to write a class and map the class to the URL. The class and his implementation are quite straigthforward:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::<br />
::'''type'''<br />
::: TUrlHandlerSimpleCaculator = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br />
::'''implementation'''<br />
::<br />
:::'''procedure''' TUrlHandlerSimpleCaculator.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, NO_CACHE, 'SimpleCalculator.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Mapping the class to the URL is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. In order to reference the class, we must also add OverbyteIcsTutWebAppServerSimpleCalculator to the uses clause in OverbyteIcsTutWebAppServerMain.pas.<br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleCalculator.html', TUrlHandlerSimpleCaculator);<br />
</tt><br />
</li><br />
<li>At this stage, you can save all (CTRL-SHIFT-S), compile and run (F9) the application. Then point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You should see the HTML form. If you click the Compute button, you get a 404 error since we have not implemented the form action yet. Let's do it. Stop the program and execute the next steps.</li><br />
<li>Create the class to implement the calculator operation. In the HTML form above, we named the action "DoSimpleCalculator.html", so we will name the class "TUrlHandlerDoSimpleCalculator". We write the class in OverbyteIcsTutWebAppServerSimpleCalculator.pas unit. The declaration looks like:<br />
<tt><br />
:: TUrlHandlerDoSimpleCalculator = '''class'''(TUrlHandler)<br />
:: '''public'''<br />
::: '''procedure''' Execute; '''override;'''<br />
:: '''end;'''<br />
</tt></li><br />
<li>Now write the code for the execute procedure. In this code we have to get the values entered by the user thru the HTML form we have designed. There are 3 fields we named "Number1", "Number2" and "Operator". The form definition specify method "get" and encoding "application/x-www-form-urlencoded". Those values directly impact how we received the values in Delphi. The HTTP server component unit has a function "ExtractURLEncodedValue" designed to get such value. It takes 3 arguments. The first is the parameters sent by the browser, the second is the name of the field and the third is a reference to the string variable to hold the result. The function return a boolean telling if the named parameter is found or not.<br><br />
All in all we have to define 3 variable and call the method 3 times to get their values. Up to here, the code looks like:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String''';<br />
::: N2 : '''String''';<br />
::: Op : '''String''';<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::'''end''';<br />
</tt></li><br />
<li>Now we have to do the computation. Be aware the every parameter is returned as a string. We have to do convertion to be able to compute the result. To hold the result, add an integer variable and name it "R". Add the following lines to the Execute procedure:<br />
<tt><br />
:: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
:: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
:: '''else'''<br />
::: R := 0;<br />
</tt><br />
For simplicity, we have not written any validation nor any exception handling. We are just demonstrating dynamic web design, not Delphi programmming best practices.</li><br />
<li>To display the result, we have to prepare a HTML template and used it to send the answer page to the client's browser. Menu / File / New / Other / Web Document / HTML page. Name the file "SimpleCalculatorResult.html" and save it in the templates directory. As HTML body, write this HTML code:<br />
<tt><br />
:: <#Operator>(<#Number1>, <#Number2>) = <#Result><br />
:: <a href="SimpleCalculator.html">Continue</a><br />
</tt><br />
This HTML code make use of 4 special tags named "Number1", "Number2", "Operator" and "Result". Those tags will be replaced by the actual values we provide by code when calling AnswerPage. The final code for the Execute procedure looks like this:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String;'''<br />
::: N2 : '''String;'''<br />
::: Op : '''String;'''<br />
::: R : '''Integer;'''<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::: '''if''' SameText(Op, 'Add') '''then'''<br />
:::: R := StrToInt(N1) + StrToInt(N2)<br />
::: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
:::: R := StrToInt(N1) * StrToInt(N2)<br />
::: '''else'''<br />
:::: R := 0;<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleCalculatorResult.html', nil,<br />
:::::: ['Number1', N1, 'Number2', N2, 'Operator', Op, 'Result', R]);<br />
::: Finish;<br />
::'''end''';<br />
</tt><br />
You can see that we used NO_CACHE constant in the call to AnswerPage. This constant instruct the client browser to not store the page into his cache. This is very important since it is a dynamic page. If the client navigator store the page in his cache, then the user would see an old version showing old results.<br />
</li><br />
<li>Finally, we have to map our class to an URL. This is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. <br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/DoSimpleCalculator.html', TUrlHandlerDoSimpleCalculator);<br />
</tt><br />
<li>Hit F9 to compile and run the application. Point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You can enter values and submit. You should get the expected result page.</li><br />
</ol><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to get back data from a HTML form, do some processing with it and produce a result page. You also learned how to instruct the client navigator to not store an answer page to his cache.<br />
<br><br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 4 - Building tables|Building tables]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 2 - Hello Today|Hello Today]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_2_-_Hello_Today&diff=2291TutWebAppServer Lesson 2 - Hello Today2009-05-04T17:05:27Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 3 - Simple data entry and processing|Simple data entry and processing]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 1 - Hello World|Hello World]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_1_-_Hello_World&diff=2290TutWebAppServer Lesson 1 - Hello World2009-05-04T17:04:43Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 2 - Hello Today|Hello Today]]<br><br />
Tutorial presentation: [[TutWebAppServer]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_2_-_Hello_Today&diff=2289TutWebAppServer Lesson 2 - Hello Today2009-05-04T17:03:19Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 3 - Simple data entry and processing]]<br><br />
Previous lesson: [[TutWebAppServer Lesson 1 - Hello World]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer_Lesson_1_-_Hello_World&diff=2288TutWebAppServer Lesson 1 - Hello World2009-05-04T17:00:24Z<p>Fpiette: </p>
<hr />
<div>=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
<br />
Next lesson: [[TutWebAppServer Lesson 2 - Hello Today|Hello Today]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2287TutWebAppServer2009-05-03T07:17:18Z<p>Fpiette: Added source code for lesson 1 to 4</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
<br />
== Source code ==<br />
* [{{SERVER}}\arch\OverbyteIcsTutWebAppServerLesson1to4.zip Lesson 1 to 4]<br />
<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br><br />
=== Lesson 3 : Simple data entry and processing ===<br />
During this lesson, you will learn how to present a data entry form to the user, process entered data and produce a result page. For simplicity, we will use a simple form to enter two numbers, an operator and provide the result in another simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
==== Steps ====<br />
<ol><br />
<li>Create a template HTML file for the calculator. Let's name that file SimpleCalculator.html and save it in the template folder we have located at "c:\icstutorial\templates". Menu / File / New / Others / Web documents / HTML page. Add the following HTML code as body:<br />
<tt><br />
:: <form action="DoSimpleCalculator.html"<br />
:::: method="get"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
::: Number 1 <input name="Number1"><br><br />
::: Operator <select name="Operator"><br />
::::: <option>Add</option><br />
::::: <option>Multiply></option><br />
::::: </select><br><br />
::: Number 2 <input name="Number2" type="TEXT"><br><br />
::: <input name="Submit" type="SUBMIT" value="Compute"><br />
:: </form><br />
</tt></li><br />
<li>Create a new unit to hold the calculator code. Menu / File / New / Delphi Unit. Save the unit as "OverbyteIcsTutWebAppServerSimpleCalculator.pas".</li><br />
<li> Create the class to deliver the calculator's form. Actually we could have done a static page as well. Since we made a template, we need to write a class and map the class to the URL. The class and his implementation are quite straigthforward:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::<br />
::'''type'''<br />
::: TUrlHandlerSimpleCaculator = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br />
::'''implementation'''<br />
::<br />
:::'''procedure''' TUrlHandlerSimpleCaculator.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, NO_CACHE, 'SimpleCalculator.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Mapping the class to the URL is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. In order to reference the class, we must also add OverbyteIcsTutWebAppServerSimpleCalculator to the uses clause in OverbyteIcsTutWebAppServerMain.pas.<br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleCalculator.html', TUrlHandlerSimpleCaculator);<br />
</tt><br />
</li><br />
<li>At this stage, you can save all (CTRL-SHIFT-S), compile and run (F9) the application. Then point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You should see the HTML form. If you click the Compute button, you get a 404 error since we have not implemented the form action yet. Let's do it. Stop the program and execute the next steps.</li><br />
<li>Create the class to implement the calculator operation. In the HTML form above, we named the action "DoSimpleCalculator.html", so we will name the class "TUrlHandlerDoSimpleCalculator". We write the class in OverbyteIcsTutWebAppServerSimpleCalculator.pas unit. The declaration looks like:<br />
<tt><br />
:: TUrlHandlerDoSimpleCalculator = '''class'''(TUrlHandler)<br />
:: '''public'''<br />
::: '''procedure''' Execute; '''override;'''<br />
:: '''end;'''<br />
</tt></li><br />
<li>Now write the code for the execute procedure. In this code we have to get the values entered by the user thru the HTML form we have designed. There are 3 fields we named "Number1", "Number2" and "Operator". The form definition specify method "get" and encoding "application/x-www-form-urlencoded". Those values directly impact how we received the values in Delphi. The HTTP server component unit has a function "ExtractURLEncodedValue" designed to get such value. It takes 3 arguments. The first is the parameters sent by the browser, the second is the name of the field and the third is a reference to the string variable to hold the result. The function return a boolean telling if the named parameter is found or not.<br><br />
All in all we have to define 3 variable and call the method 3 times to get their values. Up to here, the code looks like:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String''';<br />
::: N2 : '''String''';<br />
::: Op : '''String''';<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::'''end''';<br />
</tt></li><br />
<li>Now we have to do the computation. Be aware the every parameter is returned as a string. We have to do convertion to be able to compute the result. To hold the result, add an integer variable and name it "R". Add the following lines to the Execute procedure:<br />
<tt><br />
:: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
:: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
:: '''else'''<br />
::: R := 0;<br />
</tt><br />
For simplicity, we have not written any validation nor any exception handling. We are just demonstrating dynamic web design, not Delphi programmming best practices.</li><br />
<li>To display the result, we have to prepare a HTML template and used it to send the answer page to the client's browser. Menu / File / New / Other / Web Document / HTML page. Name the file "SimpleCalculatorResult.html" and save it in the templates directory. As HTML body, write this HTML code:<br />
<tt><br />
:: <#Operator>(<#Number1>, <#Number2>) = <#Result><br />
:: <a href="SimpleCalculator.html">Continue</a><br />
</tt><br />
This HTML code make use of 4 special tags named "Number1", "Number2", "Operator" and "Result". Those tags will be replaced by the actual values we provide by code when calling AnswerPage. The final code for the Execute procedure looks like this:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String;'''<br />
::: N2 : '''String;'''<br />
::: Op : '''String;'''<br />
::: R : '''Integer;'''<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::: '''if''' SameText(Op, 'Add') '''then'''<br />
:::: R := StrToInt(N1) + StrToInt(N2)<br />
::: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
:::: R := StrToInt(N1) * StrToInt(N2)<br />
::: '''else'''<br />
:::: R := 0;<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleCalculatorResult.html', nil,<br />
:::::: ['Number1', N1, 'Number2', N2, 'Operator', Op, 'Result', R]);<br />
::: Finish;<br />
::'''end''';<br />
</tt><br />
You can see that we used NO_CACHE constant in the call to AnswerPage. This constant instruct the client browser to not store the page into his cache. This is very important since it is a dynamic page. If the client navigator store the page in his cache, then the user would see an old version showing old results.<br />
</li><br />
<li>Finally, we have to map our class to an URL. This is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. <br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/DoSimpleCalculator.html', TUrlHandlerDoSimpleCalculator);<br />
</tt><br />
<li>Hit F9 to compile and run the application. Point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You can enter values and submit. You should get the expected result page.</li><br />
</ol><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to get back data from a HTML form, do some processing with it and produce a result page. You also learned how to instruct the client navigator to not store an answer page to his cache.<br />
<br><br><br><br />
<br />
=== Lesson 4 : Building tables ===<br />
During this lesson, you will learn how to build a table with a variable number of rows containing dynamic data. In a typical application, a table is used to show the result of a database query (for example a list of items matching a given search criteria) or to build a list of items to fill a HTML combobox or anything else repetitive.<br />
<br />
In this lesson, to avoid database stuff we have not yet learned, we will do something simple and yet useful: We will create a password generator. The user will be presented a form where he can enter the number of passwords he wants. The program will generated those passwords and present them in a nice HTML table.<br />
<br />
Since we already learned how to handle HTML forms to enter data, I will quickly pass over those steps to come directly tho this lesson's objective: generate a table.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the entry form to enter the number of passwords the user want to get. Save the form to c:\icstutorial\templates\GenerateTable.html. Create the code to handle the form and to get the value back. Save the code into a new unit named OverbyteIcsTutWebAppServerGenerateTable.pas. Name the two classes TUrlHandlerGenerateTable and TUrlHandlerDoGenerateTable. Map the two classes to the URL GenerateTable.html and DoGenerateTable.html. For detailed steps, please see lesson 2.<br />
<br><br />
The HTML form include the following code:<br />
<tt><br />
::: <form action="DoGenerateTable.html"<br />
::::: method="GET"<br />
::::: enctype="application/x-www-form-urlencoded"><br />
:::: Enter the number of passwords you want<br />
:::: <input type="TEXT" name="PasswordCount" size="3"><br />
:::: <input type="SUBMIT" value="Generate"><br />
::: </form><br />
</tt><br />
<br><br />
The unfinished new Delphi unit looks like:<br />
<tt><br />
:::'''unit''' OverbyteIcsTutWebAppServerGenerateTable;<br />
:::<br><br />
:::'''interface'''<br />
:::<br><br />
:::'''uses'''<br />
:::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
:::<br><br />
:::'''type'''<br />
:::: TUrlHandlerGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::: TUrlHandlerDoGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::'''implementation'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerGenerateTable.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GenerateTable.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: // Here comes the processing and the AnswerPage<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''end.'''<br />
</tt><br />
<br><br />
The two lines to be inserted in TTutWebAppServerMainForm.FormShow to map the URL are:<br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/GenerateTable.html', TUrlHandlerGenerateTable);<br />
:::: HttpAppSrv1.AddGetHandler('/DoGenerateTable.html', TUrlHandlerDoGenerateTable);<br />
</tt><br />
</li><br />
<li> Write the code to generate the requested number of passwords. Here we have two options: either generate all passwords before generating the actual table, or generate the passwords on the fly while generating each table row. Since the first option gives a code easier to understand, I will use it. The passwords will be generated in a TStringList which will be used later when generating each table row.<br />
<br><br />
Passwords will be generated using Delphi random generator. For simplicity, we will generate passwords containing uppercase and lowercase letters plus all ten digits. Passwords will have 12 characters.<br />
<br><br />
The code looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GeneratePasswords(PasswordCount: Integer);<br />
:::'''var'''<br />
:::: Password : '''String;'''<br />
:::: I : '''Integer;'''<br />
:::'''const'''<br />
:::: PasswordLen = 12;<br />
:::: PasswordChars : '''String''' = 'abcdefghijklmnopqrstuvwxyz' +<br />
:::::::: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +<br />
:::::::: '0123456789';<br />
:::'''begin'''<br />
:::: RandSeed := GetTickCount;<br />
:::: FPasswords := TStringList.Create;<br />
:::: SetLength(Password, PasswordLen);<br />
:::: '''while''' PasswordCount > 0 '''do begin'''<br />
::::: '''for''' I := 1 '''to''' PasswordLen '''do'''<br />
:::::: Password[I] := PasswordChars[1 + Random(Length(PasswordChars))];<br />
::::: FPasswords.Add(Password);<br />
::::: Dec(PasswordCount);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Now that we have a function to generate the passwords, we may use it into the simple procedure TUrlHandlerDoGenerateTable we wrote before:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: GeneratePasswords(StrToInt(PasswordCount));<br />
:::: OnGetRowData := GetRowData;<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GeneratePasswordResult.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
You can see here a new comer: OnGetRowData. This is a kind of event which will be called by AnswerPage whenever a table is found in the template file. A table is marked in a template file using the special tag <#table_rows>. The next step show how to use that tag.</li><br />
<li> Create a new HTML template file for presenting the password list and name it GeneratePasswordResult.html. We will build a real HTML table here. There is nothing special about the HTML table except we only create one row and surround it with the special tags <#table_rows> and <#/table_rows>. When AnswerPage will find the first tag, it starts repeating the bloc until the second tag. In each iteration it call the OnGetRowData event handler to get the data and know if there are more rows.<br />
<br />
Here is how the HTML source code looks like in the body of the HTML file:<br />
<tt><br />
::: &lt;table><br />
:::: &lt;tr>&lt;td>N°&lt;/td>&lt;td>Password&lt;/td>&lt;/tr><br />
:::: &lt;#table_rows PasswordTable><br />
::::: &lt;tr>&lt;td>&lt;#Row>&lt;/td>&lt;td>&lt;#Password>&lt;/td>&lt;/tr><br />
:::: &lt;#/table_rows><br />
::: &lt;/table><br />
</tt><br />
You see a parameter within <#table_rows>. It is used in OnGetRowData so that Delphi code knows which table is currently built because a single HTML template can have multiple tables and tables may be nested.<br />
</li><br />
<li> Write the OnGetRowData event handler with the following code:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;<br />
:::: '''const''' TableName: '''String;''' Row: Integer; TagData: TStringIndex;<br />
:::: '''var''' More: Boolean; UserData: TObject);<br />
:::'''begin'''<br />
:::: More := Assigned(FPasswords) and (Row <= FPasswords.Count);<br />
:::: '''if''' More '''then begin'''<br />
::::: TagData.Add('Row', IntToStr(Row));<br />
::::: TagData.Add('Password', FPasswords[Row - 1]);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
OnGetRowData event handler is called again and again by AnswerPage when a table_rows tag is found. Actually it is called once per data row. AnswerPage stops calling it when the var argument named "more" is set to FALSE. The main purpose of the handler is to call TagData.Add to specify values for the special tags within the table rows. Here we have defined two of them in our template file: "Row" and "Password". The event handler has also to set the var argument More according to the fact that we have more records. Here we set More according to the row index given by the argument "Row" compared to the password stringlist count.<br />
</li><br />
<li> One more step is needed to free the stringlist holding all password. We do that in the destructor:<br />
<tt><br />
:::'''destructor''' TUrlHandlerDoGenerateTable.Destroy;<br />
:::'''begin'''<br />
:::: FreeAndNil(FPasswords);<br />
:::: '''inherited;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li>You can now hit F9 to compile and run the application. Then point your browser to http://127.0.0.1:20080/GenerateTable.html, enter a value and click the button. You you see the table built and filled with the number of passwords you requested.<br />
</ol><br />
<br><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to created a template file having a table and to write code to feed the table rows with dynamic data. You know how to use <#table_rows> tag and how to write a OnGetRowData handler to fetch data for your table.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2286TutWebAppServer2009-04-30T16:08:25Z<p>Fpiette: Lesson 4 : Building tables</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br><br />
=== Lesson 3 : Simple data entry and processing ===<br />
During this lesson, you will learn how to present a data entry form to the user, process entered data and produce a result page. For simplicity, we will use a simple form to enter two numbers, an operator and provide the result in another simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
==== Steps ====<br />
<ol><br />
<li>Create a template HTML file for the calculator. Let's name that file SimpleCalculator.html and save it in the template folder we have located at "c:\icstutorial\templates". Menu / File / New / Others / Web documents / HTML page. Add the following HTML code as body:<br />
<tt><br />
:: <form action="DoSimpleCalculator.html"<br />
:::: method="get"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
::: Number 1 <input name="Number1"><br><br />
::: Operator <select name="Operator"><br />
::::: <option>Add</option><br />
::::: <option>Multiply></option><br />
::::: </select><br><br />
::: Number 2 <input name="Number2" type="TEXT"><br><br />
::: <input name="Submit" type="SUBMIT" value="Compute"><br />
:: </form><br />
</tt></li><br />
<li>Create a new unit to hold the calculator code. Menu / File / New / Delphi Unit. Save the unit as "OverbyteIcsTutWebAppServerSimpleCalculator.pas".</li><br />
<li> Create the class to deliver the calculator's form. Actually we could have done a static page as well. Since we made a template, we need to write a class and map the class to the URL. The class and his implementation are quite straigthforward:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::<br />
::'''type'''<br />
::: TUrlHandlerSimpleCaculator = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br />
::'''implementation'''<br />
::<br />
:::'''procedure''' TUrlHandlerSimpleCaculator.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, NO_CACHE, 'SimpleCalculator.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Mapping the class to the URL is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. In order to reference the class, we must also add OverbyteIcsTutWebAppServerSimpleCalculator to the uses clause in OverbyteIcsTutWebAppServerMain.pas.<br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleCalculator.html', TUrlHandlerSimpleCaculator);<br />
</tt><br />
</li><br />
<li>At this stage, you can save all (CTRL-SHIFT-S), compile and run (F9) the application. Then point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You should see the HTML form. If you click the Compute button, you get a 404 error since we have not implemented the form action yet. Let's do it. Stop the program and execute the next steps.</li><br />
<li>Create the class to implement the calculator operation. In the HTML form above, we named the action "DoSimpleCalculator.html", so we will name the class "TUrlHandlerDoSimpleCalculator". We write the class in OverbyteIcsTutWebAppServerSimpleCalculator.pas unit. The declaration looks like:<br />
<tt><br />
:: TUrlHandlerDoSimpleCalculator = '''class'''(TUrlHandler)<br />
:: '''public'''<br />
::: '''procedure''' Execute; '''override;'''<br />
:: '''end;'''<br />
</tt></li><br />
<li>Now write the code for the execute procedure. In this code we have to get the values entered by the user thru the HTML form we have designed. There are 3 fields we named "Number1", "Number2" and "Operator". The form definition specify method "get" and encoding "application/x-www-form-urlencoded". Those values directly impact how we received the values in Delphi. The HTTP server component unit has a function "ExtractURLEncodedValue" designed to get such value. It takes 3 arguments. The first is the parameters sent by the browser, the second is the name of the field and the third is a reference to the string variable to hold the result. The function return a boolean telling if the named parameter is found or not.<br><br />
All in all we have to define 3 variable and call the method 3 times to get their values. Up to here, the code looks like:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String''';<br />
::: N2 : '''String''';<br />
::: Op : '''String''';<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::'''end''';<br />
</tt></li><br />
<li>Now we have to do the computation. Be aware the every parameter is returned as a string. We have to do convertion to be able to compute the result. To hold the result, add an integer variable and name it "R". Add the following lines to the Execute procedure:<br />
<tt><br />
:: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
:: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
:: '''else'''<br />
::: R := 0;<br />
</tt><br />
For simplicity, we have not written any validation nor any exception handling. We are just demonstrating dynamic web design, not Delphi programmming best practices.</li><br />
<li>To display the result, we have to prepare a HTML template and used it to send the answer page to the client's browser. Menu / File / New / Other / Web Document / HTML page. Name the file "SimpleCalculatorResult.html" and save it in the templates directory. As HTML body, write this HTML code:<br />
<tt><br />
:: <#Operator>(<#Number1>, <#Number2>) = <#Result><br />
:: <a href="SimpleCalculator.html">Continue</a><br />
</tt><br />
This HTML code make use of 4 special tags named "Number1", "Number2", "Operator" and "Result". Those tags will be replaced by the actual values we provide by code when calling AnswerPage. The final code for the Execute procedure looks like this:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String;'''<br />
::: N2 : '''String;'''<br />
::: Op : '''String;'''<br />
::: R : '''Integer;'''<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::: '''if''' SameText(Op, 'Add') '''then'''<br />
:::: R := StrToInt(N1) + StrToInt(N2)<br />
::: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
:::: R := StrToInt(N1) * StrToInt(N2)<br />
::: '''else'''<br />
:::: R := 0;<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleCalculatorResult.html', nil,<br />
:::::: ['Number1', N1, 'Number2', N2, 'Operator', Op, 'Result', R]);<br />
::: Finish;<br />
::'''end''';<br />
</tt><br />
You can see that we used NO_CACHE constant in the call to AnswerPage. This constant instruct the client browser to not store the page into his cache. This is very important since it is a dynamic page. If the client navigator store the page in his cache, then the user would see an old version showing old results.<br />
</li><br />
<li>Finally, we have to map our class to an URL. This is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. <br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/DoSimpleCalculator.html', TUrlHandlerDoSimpleCalculator);<br />
</tt><br />
<li>Hit F9 to compile and run the application. Point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You can enter values and submit. You should get the expected result page.</li><br />
</ol><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to get back data from a HTML form, do some processing with it and produce a result page. You also learned how to instruct the client navigator to not store an answer page to his cache.<br />
<br><br><br><br />
<br />
=== Lesson 4 : Building tables ===<br />
During this lesson, you will learn how to build a table with a variable number of rows containing dynamic data. In a typical application, a table is used to show the result of a database query (for example a list of items matching a given search criteria) or to build a list of items to fill a HTML combobox or anything else repetitive.<br />
<br />
In this lesson, to avoid database stuff we have not yet learned, we will do something simple and yet useful: We will create a password generator. The user will be presented a form where he can enter the number of passwords he wants. The program will generated those passwords and present them in a nice HTML table.<br />
<br />
Since we already learned how to handle HTML forms to enter data, I will quickly pass over those steps to come directly tho this lesson's objective: generate a table.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the entry form to enter the number of passwords the user want to get. Save the form to c:\icstutorial\templates\GenerateTable.html. Create the code to handle the form and to get the value back. Save the code into a new unit named OverbyteIcsTutWebAppServerGenerateTable.pas. Name the two classes TUrlHandlerGenerateTable and TUrlHandlerDoGenerateTable. Map the two classes to the URL GenerateTable.html and DoGenerateTable.html. For detailed steps, please see lesson 2.<br />
<br><br />
The HTML form include the following code:<br />
<tt><br />
::: <form action="DoGenerateTable.html"<br />
::::: method="GET"<br />
::::: enctype="application/x-www-form-urlencoded"><br />
:::: Enter the number of passwords you want<br />
:::: <input type="TEXT" name="PasswordCount" size="3"><br />
:::: <input type="SUBMIT" value="Generate"><br />
::: </form><br />
</tt><br />
<br><br />
The unfinished new Delphi unit looks like:<br />
<tt><br />
:::'''unit''' OverbyteIcsTutWebAppServerGenerateTable;<br />
:::<br><br />
:::'''interface'''<br />
:::<br><br />
:::'''uses'''<br />
:::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
:::<br><br />
:::'''type'''<br />
:::: TUrlHandlerGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::: TUrlHandlerDoGenerateTable = '''class'''(TUrlHandler)<br />
:::: '''public'''<br />
::::: '''procedure''' Execute; '''override;'''<br />
:::: '''end;'''<br />
:::<br><br />
:::'''implementation'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerGenerateTable.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GenerateTable.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: // Here comes the processing and the AnswerPage<br />
:::: Finish;<br />
:::'''end;'''<br />
:::<br><br />
:::'''end.'''<br />
</tt><br />
<br><br />
The two lines to be inserted in TTutWebAppServerMainForm.FormShow to map the URL are:<br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/GenerateTable.html', TUrlHandlerGenerateTable);<br />
:::: HttpAppSrv1.AddGetHandler('/DoGenerateTable.html', TUrlHandlerDoGenerateTable);<br />
</tt><br />
</li><br />
<li> Write the code to generate the requested number of passwords. Here we have two options: either generate all passwords before generating the actual table, or generate the passwords on the fly while generating each table row. Since the first option gives a code easier to understand, I will use it. The passwords will be generated in a TStringList which will be used later when generating each table row.<br />
<br><br />
Passwords will be generated using Delphi random generator. For simplicity, we will generate passwords containing uppercase and lowercase letters plus all ten digits. Passwords will have 12 characters.<br />
<br><br />
The code looks like:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GeneratePasswords(PasswordCount: Integer);<br />
:::'''var'''<br />
:::: Password : '''String;'''<br />
:::: I : '''Integer;'''<br />
:::'''const'''<br />
:::: PasswordLen = 12;<br />
:::: PasswordChars : '''String''' = 'abcdefghijklmnopqrstuvwxyz' +<br />
:::::::: 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' +<br />
:::::::: '0123456789';<br />
:::'''begin'''<br />
:::: RandSeed := GetTickCount;<br />
:::: FPasswords := TStringList.Create;<br />
:::: SetLength(Password, PasswordLen);<br />
:::: '''while''' PasswordCount > 0 '''do begin'''<br />
::::: '''for''' I := 1 '''to''' PasswordLen '''do'''<br />
:::::: Password[I] := PasswordChars[1 + Random(Length(PasswordChars))];<br />
::::: FPasswords.Add(Password);<br />
::::: Dec(PasswordCount);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Now that we have a function to generate the passwords, we may use it into the simple procedure TUrlHandlerDoGenerateTable we wrote before:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.Execute;<br />
:::'''var'''<br />
:::: PasswordCount : '''String;'''<br />
:::'''begin'''<br />
:::: ExtractURLEncodedValue(Params, 'PasswordCount', PasswordCount);<br />
:::: GeneratePasswords(StrToInt(PasswordCount));<br />
:::: OnGetRowData := GetRowData;<br />
:::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'GeneratePasswordResult.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
You can see here a new comer: OnGetRowData. This is a kind of event which will be called by AnswerPage whenever a table is found in the template file. A table is marked in a template file using the special tag <#table_rows>. The next step show how to use that tag.</li><br />
<li> Create a new HTML template file for presenting the password list and name it GeneratePasswordResult.html. We will build a real HTML table here. There is nothing special about the HTML table except we only create one row and surround it with the special tags <#table_rows> and <#/table_rows>. When AnswerPage will find the first tag, it starts repeating the bloc until the second tag. In each iteration it call the OnGetRowData event handler to get the data and know if there are more rows.<br />
<br />
Here is how the HTML source code looks like in the body of the HTML file:<br />
<tt><br />
::: &lt;table><br />
:::: &lt;tr>&lt;td>N°&lt;/td>&lt;td>Password&lt;/td>&lt;/tr><br />
:::: &lt;#table_rows PasswordTable><br />
::::: &lt;tr>&lt;td>&lt;#Row>&lt;/td>&lt;td>&lt;#Password>&lt;/td>&lt;/tr><br />
:::: &lt;#/table_rows><br />
::: &lt;/table><br />
</tt><br />
You see a parameter within <#table_rows>. It is used in OnGetRowData so that Delphi code knows which table is currently built because a single HTML template can have multiple tables and tables may be nested.<br />
</li><br />
<li> Write the OnGetRowData event handler with the following code:<br />
<tt><br />
:::'''procedure''' TUrlHandlerDoGenerateTable.GetRowData(Sender: TObject;<br />
:::: '''const''' TableName: '''String;''' Row: Integer; TagData: TStringIndex;<br />
:::: '''var''' More: Boolean; UserData: TObject);<br />
:::'''begin'''<br />
:::: More := Assigned(FPasswords) and (Row <= FPasswords.Count);<br />
:::: '''if''' More '''then begin'''<br />
::::: TagData.Add('Row', IntToStr(Row));<br />
::::: TagData.Add('Password', FPasswords[Row - 1]);<br />
:::: '''end;'''<br />
:::'''end;'''<br />
</tt><br />
OnGetRowData event handler is called again and again by AnswerPage when a table_rows tag is found. Actually it is called once per data row. AnswerPage stops calling it when the var argument named "more" is set to FALSE. The main purpose of the handler is to call TagData.Add to specify values for the special tags within the table rows. Here we have defined two of them in our template file: "Row" and "Password". The event handler has also to set the var argument More according to the fact that we have more records. Here we set More according to the row index given by the argument "Row" compared to the password stringlist count.<br />
</li><br />
<li> One more step is needed to free the stringlist holding all password. We do that in the destructor:<br />
<tt><br />
:::'''destructor''' TUrlHandlerDoGenerateTable.Destroy;<br />
:::'''begin'''<br />
:::: FreeAndNil(FPasswords);<br />
:::: '''inherited;'''<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li>You can now hit F9 to compile and run the application. Then point your browser to http://127.0.0.1:20080/GenerateTable.html, enter a value and click the button. You you see the table built and filled with the number of passwords you requested.<br />
</ol><br />
<br><br><br />
<br />
==== Summary ====<br />
In this lesson you learned how to created a template file having a table and to write code to feed the table rows with dynamic data. You know how to use <#table_rows> tag and how to write a OnGetRowData handler to fetch data for your table.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2283TutWebAppServer2009-04-27T07:52:33Z<p>Fpiette: Added lesson 3</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br />
=== Lesson 3 : Simple data entry and processing ===<br />
During this lesson, you will learn how to present a data entry form to the user, process entered data and produce a result page. For simplicity, we will use a simple form to enter two numbers, an operator and provide the result in another simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
==== Steps ====<br />
<ol><br />
<li>Create a template HTML file for the calculator. Let's name that file SimpleCalculator.html and save it in the template folder we have located at "c:\icstutorial\templates". Menu / File / New / Others / Web documents / HTML page. Add the following HTML code as body:<br />
<tt><br />
:: <form action="DoSimpleCalculator.html"<br />
:::: method="get"<br />
:::: enctype="application/x-www-form-urlencoded"><br />
::: Number 1 <input name="Number1"><br><br />
::: Operator <select name="Operator"><br />
::::: <option>Add</option><br />
::::: <option>Multiply></option><br />
::::: </select><br><br />
::: Number 2 <input name="Number2" type="TEXT"><br><br />
::: <input name="Submit" type="SUBMIT" value="Compute"><br />
:: </form><br />
</tt></li><br />
<li>Create a new unit to hold the calculator code. Menu / File / New / Delphi Unit. Save the unit as "OverbyteIcsTutWebAppServerSimpleCalculator.pas".</li><br />
<li> Create the class to deliver the calculator's form. Actually we could have done a static page as well. Since we made a template, we need to write a class and map the class to the URL. The class and his implementation are quite straigthforward:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer, OverbyteIcsHttpSrv;<br />
::<br />
::'''type'''<br />
::: TUrlHandlerSimpleCaculator = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
:::<br />
::'''implementation'''<br />
::<br />
:::'''procedure''' TUrlHandlerSimpleCaculator.Execute;<br />
:::'''begin'''<br />
:::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, NO_CACHE, 'SimpleCalculator.html', nil, []);<br />
:::: Finish;<br />
:::'''end;'''<br />
</tt><br />
</li><br />
<li> Maping the class to the URL is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. In order to reference the class, we must also add OverbyteIcsTutWebAppServerSimpleCalculator to the uses clause in OverbyteIcsTutWebAppServerMain.pas.<br />
<tt><br />
::: HttpAppSrv1.AddGetHandler('/SimpleCalculator.html', TUrlHandlerSimpleCaculator);<br />
</tt><br />
</li><br />
<li>At this stage, you can save all (CTRL-SHIFT-S), compile and run (F9) the application. Then point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You should see the HTML form. If you click the Compute button, you get a 404 error since we have not implemented the form action yet. Let's do it. Stop the program and execute the next steps.</li><br />
<li>Create the class to implement the calculator operation. In the HTML form above, we named the action "DoSimpleCalculator.html", so we will name the class "TUrlHandlerDoSimpleCalculator". We write the class in OverbyteIcsTutWebAppServerSimpleCalculator.pas unit. The declaration looks like:<br />
<tt><br />
:: TUrlHandlerDoSimpleCalculator = '''class'''(TUrlHandler)<br />
:: '''public'''<br />
::: '''procedure''' Execute; '''override;'''<br />
:: '''end;'''<br />
</tt></li><br />
<li>Now write the code for the execute procedure. In this code we have to get the values entered by the user thru the HTML form we have designed. There are 3 fields we named "Number1", "Number2" and "Operator". The form definition specify method "get" and encoding "application/x-www-form-urlencoded". Those values directly impact how we received the values in Delphi. The HTTP server component unit has a function "ExtractURLEncodedValue" designed to get such value. It takes 3 arguments. The first is the parameters sent by the browser, the second is the name of the field and the third is a reference to the string variable to hold the result. The function return a boolean telling if the named parameter is found or not.<br><br />
All in all we have to define 3 variable and call the method 3 times to get their values. Up to here, the code looks like:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String''';<br />
::: N2 : '''String''';<br />
::: Op : '''String''';<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::'''end''';<br />
</tt></li><br />
<li>Now we have to do the computation. Be aware the every parameter is returned as a string. We have to do convertion to be able to compute the result. To hold the result, add an integer variable and name it "R". Add the fdollowing lines to the Execute procedure:<br />
<tt><br />
:: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
:: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
:: '''else'''<br />
::: R := 0;<br />
</tt><br />
For simplicity, we have not written any validation nor any exception handling. We are just demonstrating dynamic web design, not Delphi programmming best practices.</li><br />
<li>To display the result, we have to prepare a HTML template and used it to send the answer page to the client's browser. Menu / File / New / Other / Web Document / HTML page. Name the file "SimpleCalculatorResult.html" and save it in the templates directory. As HTML body, write this HTML code:<br />
<tt><br />
:: <#Operator>(<#Number1>, <#Number2>) = <#Result><br />
:: <br><br><br />
:: <a href="SimpleCalculator.html">Continue</a><br />
</tt><br />
This HTML code make use of 4 special tags named "Number1", "Number2", "Operator" and "Result". Those tags will be replaced by the actual values we provide by code when calling AnswerPage. The final code for the Execute procedure looks like this:<br />
<tt><br />
::'''procedure''' TUrlHandlerDoSimpleCalculator.Execute;<br />
::'''var'''<br />
::: N1 : '''String;'''<br />
::: N2 : '''String;'''<br />
::: Op : '''String;'''<br />
::: R : '''Integer;'''<br />
::'''begin'''<br />
::: ExtractURLEncodedValue(Params, 'Number1', N1);<br />
::: ExtractURLEncodedValue(Params, 'Number2', N2);<br />
::: ExtractURLEncodedValue(Params, 'Operator', Op);<br />
::: '''if''' SameText(Op, 'Add') '''then'''<br />
::: R := StrToInt(N1) + StrToInt(N2)<br />
::: '''else if''' SameText(Op, 'Multiply') '''then'''<br />
::: R := StrToInt(N1) * StrToInt(N2)<br />
::: '''else'''<br />
::: R := 0;<br />
::: AnswerPage(&rsquo;&rsquo;, NO_CACHE, 'SimpleCalculatorResult.html', nil,<br />
:::: ['Number1', N1, 'Number2', N2, 'Operator', Op, 'Result', R]);<br />
::: Finish;<br />
::'''end''';<br />
</tt><br />
</li><br />
<li>Finally, we have to map our class to an URL. This is done by calling AddGetHandler from TTutWebAppServerMainForm.FormShow. <br />
<tt><br />
:::: HttpAppSrv1.AddGetHandler('/DoSimpleCalculator.html', TUrlHandlerDoSimpleCalculator);<br />
</tt><br />
<li>Hit F9 to compile and run the application. Point your browser to http://127.0.0.1:20080/SimpleCalculator.html. You can enter values and submit. You should get the expected result page.</li><br />
</ol><br></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2282TutWebAppServer2009-04-26T17:11:48Z<p>Fpiette: Fixed steps numbering</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br><br><br />
=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create a new VCL forms application.<br />
:: Here in the demo we use a classic GUI application. For a real application, it is likely that you'll create a service application.</li><br />
<li> Rename the form "TutWebAppServerMainForm"</li><br />
<li> On the form just created, drop a THttpAppSrv component.</li><br />
<li> Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.</li><br />
<li> Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.</li><br />
<li> Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
</li><br />
<li> Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".</li><br />
<li> Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"</li><br />
<li> Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
</li><br />
<li> Hit CTRL-SHIFT-S to save all.</li><br />
<li> Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.</li><br />
<li> Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br><br />
=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
<ol><br />
<li> Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.</li><br />
<li> Write the text: "Server time is"</li><br />
<li> Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.</li><br />
<li> Save the template as "c:\icstutorial\templates\HelloToday.html"</li><br />
<li> Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
</li><br />
<li> Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt></li><br />
<li> Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.</li><br />
<li> Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.</li><br />
</ol><br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.<br />
<br><br><br />
=== Lesson 3 : Simple data entry and processing ===<br />
During this lesson, you will learn how to present a data entry form to the user, entered process data and produce a result page. For simplicity, we will use a simple form to enter two number and an operator and provide the result in a simple page. Later, in another lesson, we will use AJAX to update the current page with the computation result.<br />
<br><br />
==== Steps ====<br />
<br />
To be continuited...</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TutWebAppServer&diff=2277TutWebAppServer2009-04-25T19:17:04Z<p>Fpiette: Lesson 1 and Lesson 2</p>
<hr />
<div>== Description ==<br />
This tutorial is about writing a dynamic web application using THttpAppSrv component you can find in ICS version 7.<br />
<br />
A dynamic web application is one which not only deliver static pages and files, but also dynamic web page.<br />
<br />
== Dynamic Pages ==<br />
A dynamic web page is build on a template html file having special tags such as "<#MyTagName>" which are replaced at runtime by content provided by the application. Usually the content is fetched from a database but can comes from any source. The only limit is the developper imagination !<br />
<br />
The component has also special tags to handle tables. Not only html tables, but anything which need to be repeated such as a list content. Using those tags, the developer describe one table row in the template and at runtime, as many rows as needed are created. The developper has full control on the data in each row and of course the number of generated rows.<br />
<br />
<br />
== The tutorial ==<br />
<br />
The tutorial is divided in lessons and each lessons in steps. You must do the lesson in the correct order since most lessons depends on the previous one. In other words, lessons are simply miles stones toward the final<br />
<br />
The steps belows correspond to Delphi 2009. You'll have to adapt somewhat the steps according to the IDE you use. The tutorial is OK with all Delphi versions supported by ICS-V7. There could also be some minor differences according to the settings you use for your ide. I'm using undocked layout with floating VCL designer. I'm using a french localized version so the menu items and button captions I give are translated from french to english and could be slightly different than the original english one.<br />
<br />
Obvioulsy, you must have ICS-V7 installed within the IDE. When you install ICS, you usually add <ics installdir>\Delphi\VC32 to the compiler search path. If don't do that, you must add that path to every project.<br />
<br />
=== Lesson 1 : Hello World ===<br />
<br />
During this lesson, you will learn how to write the simplest website. The website you'll build has only one static page displaying "Hello World".<br />
<br />
==== Steps ====<br />
# Create a new VCL forms application.<br />
:: Here in the demo we use a classic graphic application. For a real application, it is likely that you'll create a service application.<br />
# Rename the form "TutWebAppServerMainForm"<br />
# On the form just created, drop a THttpAppSrv component.<br />
# Save the files you have just created. Menu / File / Save all. Use OverbyteIcsTutWebAppServerMain.pas instead of unit1.pas and OverbyteIcsTutWebAppServer.dproj instead of project1.dproj.<br />
# Hit F9 to compile and run the projet. You should get no error and a blank form. If you have errors, then it is likely you have ICS incorrectly installed. Terminate the application.<br />
# Select the THttpAppSrv you just dropped on a form. Hit F11 to show the oject inspector and set a few property values:<br />
::{| <br />
| Name || HttpAppSrv1<br />
|- <br />
| Port || 20080 <br />
|- <br />
| DocDir || c:\icstutorial\wwwroot <br />
|- <br />
| TemplateDir || c:\icstutorial\templates <br />
|- <br />
| DefaultDoc || index.html <br />
|}<br />
# Create the document directory "c:\icstutorial\wwwroot" and the templates directory "c:\icstutorial\templates".<br />
# Create our static html page: Menu / File / New / Others / Web document / HTML Page. Just enter the body text "Hello World" and save the file as "c:\icstutorial\wwwroot\index.html"<br />
# Add a FormShow event handler to TutWebAppServerMainForm with the code:<br />
<tt><br />
:: HttpAppSrv1.AddGetAllowedPath('/', afBeginBy);<br />
:: HttpAppSrv1.Start;<br />
</tt><br />
# Hit CTRL-SHIFT-S to save all.<br />
# Hit F9 to compile and run the application. You still get an empty form, but actually you already have a web server running ! Depending on your OS and security settings, you may get a message asking you to block or allow the application. Be sure to allow it.<br />
# Now enter the url: "http://127.0.0.1:20080" into your favorite browser. You should get your marvelous "Hello World" static page.<br />
<br />
==== Summary ====<br />
In this lesson you learned how to build the basic webserver to serve static page. Beside the static pages you need, there are only two Delphi code lines to write.<br />
<br><br />
<br />
=== Lesson 2 : Hello Today ===<br />
<br />
Let's add a dynamic webpage to our website. To make it simple, we will just display the current server date and time.<br />
<br />
==== Steps ====<br />
# Create the template for the dynamic web page: Menu / File / New / Others / web document / HTML Page.<br />
# Write the text: "Server time is"<br />
# Switch to the HTML code editor (ALT-PgUP or click "code" tab at bottom of the editor) to enter the special tag "<#DateTime>" where you want to have the date and time shown, that is just after "Server time is". You'll see that Delphi HTML editor add an ending tag we don't need. Just delete "</#DateTime>" Delphi has inserted.<br />
# Save the template as "c:\icstutorial\templates\HelloToday.html"<br />
# Now we must associate the processing required to build our dynamic webpage. This is done by creating a new class deriving from TUrlHandler. Menu / File / New / Other / Delphi Project / Delphi Files / Unit. Save this new unit as "OverbyteIcsTutWebAppServerHelloToday.pas". Enter this code into the unit:<br />
<tt><br />
::'''uses'''<br />
::: SysUtils, OverbyteIcsHttpAppServer;<br />
<br><br />
::'''type'''<br />
::: TUrlHandlerHelloToday = '''class'''(TUrlHandler)<br />
::: '''public'''<br />
:::: '''procedure''' Execute; '''override;'''<br />
::: '''end;'''<br />
<br><br />
::'''implementation'''<br />
<br><br />
::'''procedure''' TUrlHandlerHelloToday.Execute;<br />
::'''begin'''<br />
::: AnswerPage(&rsquo;&rsquo;, &rsquo;&rsquo;, 'HelloToday.html', nil, ['DateTime', DateTimeToStr(Now)]);<br />
::: Finish;<br />
::'''end;'''<br />
</tt><br />
# Switch back to OverbyteIcsTutWebAppServerMain and add "OverbyteIcsTutWebAppServerHelloToday" to the uses clause, add the following line in front of the FormShow event handler:<br />
::<tt>HttpAppSrv1.AddGetHandler('/HelloToday.html', TUrlHandlerHelloToday);</tt><br />
# Hit CTRL-SHIFT-S and F9 to save all, compile and run your application.<br />
# Enter this URL into your browser: http://127.0.0.1:20080/HelloToday.html. You should see the web page as the template your designed with the tag "<#DateTime>" replaced by the date and time. Hit the refresh button several times to see the dynamic page in action: the time is the real time.<br />
<br><br />
==== Summary ====<br />
In this lesson you learned how to write a template for a dynamic page, link the dynamic page URL to a Delphi class, write a Delphi class implementing the processing required to get data and feed it to the template.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=Tutorials&diff=2276Tutorials2009-04-25T14:01:19Z<p>Fpiette: Created page with TutWebAppServer</p>
<hr />
<div>* [[TutWebAppServer]]: Writing a dynamic web application using THttpAppSrv component</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=Main_Page&diff=2267Main Page2008-12-14T13:31:26Z<p>Fpiette: /* '''I'''nternet '''C'''omponent '''S'''uite - Wiki under construction */</p>
<hr />
<div>== '''I'''nternet '''C'''omponent '''S'''uite - Wiki under construction ==<br />
<br />
ICS is a free internet component library for all Delphi, C++Builder, BDS and RAD Studio versions (win32). It includes TCP, UDP, raw sockets, clients, servers, as well as many high level protocols such as FTP, SMTP, POP3, NNTP, HTTP and more. ICS also support SSL and TLS with the help of [http://www.openssl.org OpenSSL]. <br />
<br />
{| align="center" style="background: red; color: yellow; font-weight: bolder; width: 70%;"<br />
|- <br />
| align="center"| <b>The content is preliminary and incomplete.</b><br />
|}<br />
<br />
{| align="center" style="background: yellow; color: blue; font-weight: bolder; width: 70%;"<br />
|- <br />
| align="center"| <b>We are looking for people willing to help writing the content. Contact francois dot piette at overbyte dot be if you want to help.</b><br />
|}<br />
<br />
If you need help with ICS, please visit [http://www.overbyte.be OverByte website] and subscribe to the [http://www.elists.org/mailman/listinfo/twsocket support mailing list].<br />
<br />
You can download latest distribution from [http://www.overbyte.be OverByte website] or download latest code directly from version control repository using [http://svn.overbyte.be:8443/svn/ics http] or using [http://tortoisesvn.net TortoiseSVN] with URL svn://svn.overbyte.be/ics.<br />
<br />
== Access to ICS documentation ==<br />
<br />
{|<br />
| [[ICS_Components_Reference | Components]] |||| ICS components reference <br />
|-<br />
| [[FAQ]] |||| Frequently asked general questions<br />
|-<br />
| [[Glossary]] |||| Glossary of terms<br />
|}<br />
<br />
== Message to Sysops ==<br />
<br />
Please see [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentation on customizing the interface]<br />
and the [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User's Guide] for usage and configuration help.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TSyncSmtpCli&diff=2264TSyncSmtpCli2008-12-06T08:03:17Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS component reference]] -> [[TSyncSmtpCli]]<br />
<br />
== Overview ==<br />
<br />
* '''unit''' SmtpProt<br />
* '''inheritance''' TCustomSmtpCli->TSmtpCli->TSyncSmtpCli<br />
<br />
Component '''TSyncSmtpCli''' implements client-side of the Simple Mail Transfer Protocol. It is the synchronous version of '''TSmtpCli'''. The working is exactly the same except a few methods have been added for synchronous (blocking) operation. This page only shows the differences.<br />
<br />
== Properties ==<br />
<br />
See [[TSmtpCli]]<br />
<br />
== Methods ==<br />
<br />
The new methods are: AbortSync, AuthSync, ConnectSync, DataSync, EhloSync, HeloSync, MailSync, MailFromSync, OpenSync, QuitSync, RcptToSync, RsetSync, VrfySync. They work exactly as their asynchronous version (See [[TSmtpCli]]) except they do not return before their task is done.<br />
<br />
== Events ==<br />
<br />
See [[TSmtpCli]]</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=FAQ&diff=2263FAQ2008-11-29T13:50:23Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[FAQ]]<br />
<br />
<!--<br />
Here, you'll find the most Frequently Asked Questions about the components. Some links refer to articles and others on "How-to-do-things"<br />
--><br />
<br />
Here, you'll find the most frequently asked questions which cover a range of components or all. You will find questions specific to one component in the '''How to''' section of each component.<br />
<br />
== How to get ICS ==<br />
<br />
There are 3 options to get ICS source code:<br />
:# From partner DVD you get from CodeGear when buying Delphi or C++ Builder<br />
:# From [http://www.overbyte.be/eng/products/ics.html OverByte website]<br />
:# From version control repository<br />
<br />
Using partner DVD from CodeGear is probably not such a good idea since it is likely to be an old version build at the time Delphi / C++Builder version was pushed to the marked.<br />
<br />
Using [http://www.overbyte.be/en/products/ics.html OverByte website] you'll get the latest stable release or beta. That's a good choice.<br />
<br />
Using version control repository is the best choice if you want to have the very latest source code. OverByte use SubVersion server and you need to use a subversion client such as [http://tortoisesvn.net TortoiseSVN] or your favorite browser. Once your SVN client is installed, for ICS-V6 you can browse to svn://svn.overbyte.be/ics or http://svn.overbyte.be:8443/svn/ics or for ICS-V5 to: svn://svn.overbyte.be/icsv5 or http://svn.overbyte.be:8443/svn/icsv5. ICS-V7 is a part of V6, in ics/branches/icsv7. All use usercode = ics and password = ics for read access. Write access is only available to TeamICS. <br />
<br />
== How ICS works ==<br />
{|<br />
| width="170" | [[Asynchronous_Paradigm | Asynchronous paradigm]] |||| The non-blocking nature of ICS.<br />
|-<br />
| [[Sending and receiving data]] |||| Draft discussing possible formats of data transfer.<br />
|}<br />
<br />
== FAQ ==<br />
{|<br />
| width="170" valign="top" | [[FAQ.Concatenating data | Concatenating data]] |||| A example on how to concatenate chuncks of data in a CPU / Memory friendly way.<br />
|-<br />
| valign="top" | [[FAQ.Difference | Difference TCP/UDP]] |||| What is the difference between TCP and UDP and which to use when ?<br />
|-<br />
| valign="top" | [[FAQ.General | General]] |||| General questions not belong to other section<br />
|-<br />
| valign="top" | [[FAQ.Internet | Internet]] |||| Specific for internet<br />
|-<br />
| valign="top" | [[FAQ. Microsoft .NET framework | Microsoft .NET framework]] |||| Using ICS with the Microsoft .NET framework<br />
|-<br />
| valign="top" | [[FAQ.MultiThreading | Multi-Threading]] |||| Using ICS components and threads<br />
|-<br />
| valign="top" | [[FAQ.ProgressBar | Progress bar]] |||| Implementing a progress bar<br />
|-<br />
| valign="top" | [[FAQ.Timeout | Timeouts]] |||| Implementing timeouts on connections or protocols<br />
|}<br />
<br />
<!--<br />
* [[THttpCli.FAQ.Timeout | How to implement a timeout for THttpCli in my application?]]<br />
* [[THttpCli.FAQ.Progress | How to implement a progress for THttpCli in my application?]]<br />
* [[THttpCli.FAQ.SizeLimit | How to implement a download size limitation for THttpCli in my application?]]<br />
--></div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=Main_Page&diff=2262Main Page2008-11-29T13:37:58Z<p>Fpiette: </p>
<hr />
<div>== '''I'''nternet '''C'''omponent '''S'''uite - Wiki under construction ==<br />
<br />
ICS is a free internet component library for all Delphi, C++Builder, BDS and RAD Studio versions (win32). It includes TCP, UDP, raw sockets, clients, servers, as well as many high level protocols such as FTP, SMTP, POP3, NNTP, HTTP and more. <br />
<br />
{| align="center" style="background: red; color: yellow; font-weight: bolder; width: 70%;"<br />
|- <br />
| align="center"| <b>The content is preliminary and incomplete.</b><br />
|}<br />
<br />
{| align="center" style="background: yellow; color: blue; font-weight: bolder; width: 70%;"<br />
|- <br />
| align="center"| <b>We are looking for people willing to help writing the content. Contact francois dot piette at overbyte dot be if you want to help.</b><br />
|}<br />
<br />
If you need help with ICS, please visit [http://www.overbyte.be OverByte website] and subscribe to the [http://www.elists.org/mailman/listinfo/twsocket support mailing list].<br />
<br />
You can download latest distribution from [http://www.overbyte.be OverByte website] or download latest code directly from version control repository using [http://svn.overbyte.be:8443/svn/ics http] or using [http://tortoisesvn.net TortoiseSVN] with URL svn://svn.overbyte.be/ics.<br />
<br />
== Access to ICS documentation ==<br />
<br />
{|<br />
| [[ICS_Components_Reference | Components]] |||| ICS components reference <br />
|-<br />
| [[FAQ]] |||| Frequently asked general questions<br />
|-<br />
| [[Glossary]] |||| Glossary of terms<br />
|}<br />
<br />
== Message to Sysops ==<br />
<br />
Please see [http://meta.wikipedia.org/wiki/MediaWiki_i18n documentation on customizing the interface]<br />
and the [http://meta.wikipedia.org/wiki/MediaWiki_User%27s_Guide User's Guide] for usage and configuration help.</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TFtpServer&diff=2153TFtpServer2006-12-03T16:55:21Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] -> [[TFtpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' FtpSrv.pas<br />
*'''inheritance''' TFtpServer - TComponent<br />
<br />
TFtpServer component is implementing the server side FTP protocol described in RFC [http://rfc.net/rfc959.html 959]. FTP protocol is the standard protocol for transfering files.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpServer.Addr | Addr]] |||| IP address of the interface to listen on. Use 0.0.0.0 to listen on all interfaces.<br />
|-<br />
| valign="top" | [[TFtpServer.Port | Port]] |||| TCP port to listen to.<br />
|-<br />
| valign="top" | [[TFtpServer.Banner | Banner]] |||| Welcome message sent to client.<br />
|-<br />
| valign="top" | [[TFtpServer.UserData | UserData]] |||| Data passed to each client instance.<br />
|-<br />
| valign="top" | [[TFtpServer.MaxClient | MaxClient]] |||| Maximum number of simultaneous client to be accepted.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvIpAddr | PasvIpAddr]] |||| IP address used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeStart | PasvPortRangeStart]] |||| TCP port range start to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeSize | PasvPortRangeSize ]] |||| TCP port range size to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.Options | Options]] |||| Options set to change component behaviour.<br />
|-<br />
| valign="top" | [[TFtpClient.ClientCount | ClientCount]] |||| Actual number of connected clients. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Client | Client]] |||| Array of connected clients. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Active | Active]] |||| Set/Get server state. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Handle | Handle]] |||| Handle for underlaying hidden window. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.ServSocket | ServSocket]] |||| Underlaying listening socket. Runtime only.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpClient.Start | Start]] |||| Make the server listening for clients.<br />
|-<br />
| valign="top" | [[TFtpClient.Stop | Stop]] |||| Make the server stop listening for client. Doesn't disconnect connected clients.<br />
|-<br />
| valign="top" | [[TFtpClient.Disconnect | Disconnect]] |||| Disconnect a single client.<br />
|-<br />
| valign="top" | [[TFtpClient.DisconnectAll | DisconnectAll]] |||| Disconnect all clients.<br />
|-<br />
| valign="top" | [[TFtpClient.IsClient | IsClient]] |||| Check if an instance is an actual client.<br />
|}<br />
<br />
== Events ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpClient.OnStart | OnStart]] |||| OnStart.<br />
|-<br />
| valign="top" | [[TFtpClient.OnStop | OnStop]] |||| OnStop.<br />
|-<br />
| valign="top" | [[TFtpClient.OnAuthenticate | OnAuthenticate]] |||| OnAuthenticate.<br />
|-<br />
| valign="top" | [[TFtpClient.OnClientDisconnect | OnClientDisconnect]] |||| OnClientDisconnect.<br />
|-<br />
| valign="top" | [[TFtpClient.OnClientConnect | OnClientConnect]] |||| OnClientConnect.<br />
|-<br />
| valign="top" | [[TFtpClient.OnClientCommand | OnClientCommand]] |||| OnClientCommand.<br />
|-<br />
| valign="top" | [[TFtpClient.OnAnswerToClient | OnAnswerToClient]] |||| OnAnswerToClient.<br />
|-<br />
| valign="top" | [[TFtpClient.OnChangeDirectory | OnChangeDirectory]] |||| OnChangeDirectory.<br />
|-<br />
| valign="top" | [[TFtpClient.OnMakeDirectory | OnMakeDirectory]] |||| OnMakeDirectory.<br />
|-<br />
| valign="top" | [[TFtpClient.OnBuildDirectory | OnBuildDirectory]] |||| OnBuildDirectory.<br />
|-<br />
| valign="top" | [[TFtpClient.OnAlterDirectory | OnAlterDirectory]] |||| OnAlterDirectory.<br />
|-<br />
| valign="top" | [[TFtpClient.OnStorSessionConnected | OnStorSessionConnected]] |||| OnStorSessionConnected.<br />
|-<br />
| valign="top" | [[TFtpClient.OnRetrSessionConnected | OnRetrSessionConnected]] |||| OnRetrSessionConnected.<br />
|-<br />
| valign="top" | [[TFtpClient.OnRetrSessionClosed | OnRetrSessionClosed]] |||| OnRetrSessionClosed.<br />
|-<br />
| valign="top" | [[TFtpClient.OnRetrDataSent | OnRetrDataSent]] |||| OnRetrDataSent.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidatePut | OnValidatePut]] |||| OnValidatePut.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateSize | OnValidateSize]] |||| OnValidateSize.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateDele | OnValidateDele]] |||| OnValidateDele.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateRmd | OnValidateRmd]] |||| OnValidateRmd.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateRnFr | OnValidateRnfr]] |||| OnValidateRnFr.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateRnTo | OnValidateRnTo]] |||| OnValidateRnTo.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateGet | OnValidateGet]] |||| OnValidateGet.<br />
|-<br />
| valign="top" | [[TFtpClient.OnStorDataAvailable | OnStorDataAvailable]] |||| OnStorDataAvailable.<br />
|-<br />
| valign="top" | [[TFtpClient.OnGetUniqueFileName | OnGetUniqueFileName]] |||| OnGetUniqueFileName.<br />
|-<br />
| valign="top" | [[TFtpClient.OnGetProcessing | OnGetProcessing]] |||| OnGetProcessing.<br />
|-<br />
| valign="top" | [[TFtpClient.OnBuildFilePath | OnBuildFilePath]] |||| OnBuildFilePath.<br />
|-<br />
| valign="top" | [[TFtpClient.OnValidateMfmt | OnValidateMfmt]] |||| OnValidateMfmt.<br />
|-<br />
| valign="top" | [[TFtpClient.OnCalculateMd5 | OnCalculateMd5]] |||| OnCalculateMd5.<br />
|}<br />
<br />
== How to ==<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TFtpServer&diff=2152TFtpServer2006-12-03T16:46:05Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] -> [[TFtpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' FtpSrv.pas<br />
*'''inheritance''' TFtpServer - TComponent<br />
<br />
TFtpServer component is implementing the server side FTP protocol described in RFC [http://rfc.net/rfc959.html 959]. FTP protocol is the standard protocol for transfering files.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpServer.Addr | Addr]] |||| IP address of the interface to listen on. Use 0.0.0.0 to listen on all interfaces.<br />
|-<br />
| valign="top" | [[TFtpServer.Port | Port]] |||| TCP port to listen to.<br />
|-<br />
| valign="top" | [[TFtpServer.Banner | Banner]] |||| Welcome message sent to client.<br />
|-<br />
| valign="top" | [[TFtpServer.UserData | UserData]] |||| Data passed to each client instance.<br />
|-<br />
| valign="top" | [[TFtpServer.MaxClient | MaxClient]] |||| Maximum number of simultaneous client to be accepted.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvIpAddr | PasvIpAddr]] |||| IP address used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeStart | PasvPortRangeStart]] |||| TCP port range start to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeSize | PasvPortRangeSize ]] |||| TCP port range size to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.Options | Options]] |||| Options set to change component behaviour.<br />
|-<br />
| valign="top" | [[TFtpClient.ClientCount | ClientCount]] |||| Actual number of connected clients. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Client | Client]] |||| Array of connected clients. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Active | Active]] |||| Set/Get server state. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.Handle | Handle]] |||| Handle for underlaying hidden window. Runtime only.<br />
|-<br />
| valign="top" | [[TFtpClient.ServSocket | ServSocket]] |||| Underlaying listening socket. Runtime only.<br />
|}<br />
<br />
== Methods ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpClient.Start | Start]] |||| Make the server listening for clients.<br />
|-<br />
| valign="top" | [[TFtpClient.Stop | Stop]] |||| Make the server stop listening for client. Doesn't disconnect connected clients.<br />
|-<br />
| valign="top" | [[TFtpClient.Disconnect | Disconnect]] |||| Disconnect a single client.<br />
|-<br />
| valign="top" | [[TFtpClient.DisconnectAll | DisconnectAll]] |||| Disconnect all clients.<br />
|-<br />
| valign="top" | [[TFtpClient.IsClient | IsClient]] |||| Check if an instance is an actual client.<br />
|}<br />
<br />
== Methods ==<br />
<br />
== How to ==<br />
<br />
{{Components_Footer}}</div>Fpiettehttp://wiki.overbyte.eu/wiki/index.php?title=TFtpServer&diff=2151TFtpServer2006-12-03T16:38:46Z<p>Fpiette: </p>
<hr />
<div>[[Main_Page | Main page]] -> [[ICS_Components_Reference | ICS components reference]] -> [[TFtpServer]]<br />
== Overview ==<br />
<br />
*'''unit''' FtpSrv.pas<br />
*'''inheritance''' TFtpServer - TComponent<br />
<br />
TFtpServer component is implementing the server side FTP protocol described in RFC [http://rfc.net/rfc959.html 959]. FTP protocol is the standard protocol for transfering files.<br />
<br />
== Properties ==<br />
<br />
{|<br />
| valign="top" width="150" | [[TFtpServer.Addr | Addr]] |||| IP address of the interface to listen on. Use 0.0.0.0 to listen on all interfaces.<br />
|-<br />
| valign="top" | [[TFtpServer.Port | Port]] |||| TCP port to listen to.<br />
|-<br />
| valign="top" | [[TFtpServer.Banner | Banner]] |||| Welcome message sent to client.<br />
|-<br />
| valign="top" | [[TFtpServer.UserData | UserData]] |||| Data passed to each client instance.<br />
|-<br />
| valign="top" | [[TFtpServer.MaxClient | MaxClient]] |||| Maximum number of simultaneous client to be accepted.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvIpAddr | PasvIpAddr]] |||| IP address used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeStart | PasvPortRangeStart]] |||| TCP port range start to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.PasvPortRangeSize | PasvPortRangeSize ]] |||| TCP port range size to be used for passive mode.<br />
|-<br />
| valign="top" | [[TFtpServer.Options | Options]] |||| Options set to change component behaviour.<br />
|}<br />
<br />
== Methods ==<br />
<br />
== Methods ==<br />
<br />
== How to ==<br />
<br />
{{Components_Footer}}</div>Fpiette