<?xml version="1.0" encoding="iso-8859-1"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Matlus ISAPI, TCP/IP and Webservice Related Articles</title><link>http://exposureroom.com/members/skumar/</link><atom:link href="http://rss.exposureroom.com/MemberJournalRssProvider.aspx/skumar/articles/" rel="self" type="application/rss+xml" /><description><![CDATA[]]></description><pubDate>Wed, 15 Feb 2012 07:38:11 GMT</pubDate><generator>ExposureRoom RSS Feed Generator v1.0</generator><language>en</language><item><title>Why you Should Not Letterbox your Videos</title><pubDate>Wed, 13 Aug 2008 14:31:06 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/44/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/44/</guid><description><![CDATA[There are a few reasons why you'd want/need to letterbox your videos. However in this article, I present reasons for NOT leterboxing your videos. The two cases in which I feel letterboxing is not desired are as follows:<br>
<ol>
    <li>You want your HD videos (16:9 aspect) to look like Cinemascope film (2.35:1 aspect). Image 1 below shows an example of this.<br>
    </li>
    <li>You've probably encoded your video for DVD/Blu-ray and tweaked those settings for online video and ended up with a video that has an aspect of 4:3 with the picture inside it with the normal aspect but with letterboxing (black bars on the top and bottom). Image 2 below shows an example of this.<br>
    </li>
</ol>
<img alt="Image1: Video is in 16:9 aspect, but picture is in wide screen aspect (2.35:1)" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=6">
<div><span style="font-weight: bold;">Image1: Video is in 16:9 aspect, but picture is in Cinemascope aspect (2.35:1)</span><br>
</div>
<div>&nbsp;</div>
<div><img alt=" Image 2: Picture is in HD aspect (16:9) but video is in SD aspect (4:3)" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=7"> <span style="font-weight: bold;">Image 2: Picture is in HD aspect (16:9) but video is in SD aspect (4:3)</span><br>
</div>
<div>&nbsp;</div>
<div>
<h3>Letter boxing </h3>
</div>
<div>The concept of letterbox was introduced in order to fit film to video or actually your standard (4:3) TV screen. On ExposureRoom, we retain the original dimensions and aspect ratio of your videos, so there is no real need for you to letterbox your video, since there is nothing to try and fit it into. So use this feature to your advantage and make the best of what we offer you.</div>
<div>&nbsp;</div>
<h3>Crop your Cinemascope (2.35:1) Video.</h3>
<div>If the first case above applies to your video (see image 1 above) then I strongly suggest cropping your videos to the desired dimensions using Adobe Premiere Pro CS3, Quicktime Pro,&nbsp;Sorenson Squeeze or other tools. If you've gone through the trouble of shooting within the confines of a 2.35:1 frame, and edited your video with black bars on the top and bottom, why not go through one more step to get the most out of this effort by <span style="font-weight: bold;">cropping your videos</span>? I'll explain why in a moment.<br>
</div>
<div>&nbsp;</div>
<div>
<h3>HD Videos in HD Aspect </h3>
</div>
<div>If the second case above applies to your video (see image 2 above) then the issue really is the wrong encoding settings. Your video is really a 16:9 aspect (SD wide or HD) and you should render it as such. Please look at the article titled, <a href="http://exposureroom.com/help/view.aspx/207/">Getting your videos to show in the correct Aspect</a> in our <a href="http://exposureroom.com/help/">online help</a> section for how to get the correct aspect for your videos.</div>
<div>&nbsp;</div>
<h3>Problems with Letterboxing your Videos</h3>
There are two reasons you should not letter box videos or actually Not crop your videos (as the case may be). In the first case you're intentionally letterboxing but you're not cropping&nbsp; your video to the actual dimensions, and the issues with this are:<br>
<ol>
    <li>The video looks a whole lot better without letterboxing.</li>
    <li>The picture quality is not as good as what it would be if you cropped your video instead of simply letterboxing. </li>
</ol>
The second case has one issue and that is the picture quality is not as good as what it would be if you encoded your video correctly in order to produce a video with the correct dimensions.
<h3>Why the Picture Quality suffers</h3>
<div>You probably know that the <strong>video bit rate</strong> plays a major role in the quality of your video. If you don't understand this, please read the article title, <a href="http://exposureroom.com/help/view.aspx/89/">Encoding Videos for online Viewing</a>. So what does it mean, when you're encoding your video at say 3,500kbps? Before I try and explain what it means, let's establish some points of reference for this discussion. We'll use a video that has been encoded with dimensions of 1280x720 (16:9 aspect) but with letterboxing (see image 1 above), lets also assume that this video has a frame rate of 30p.</div>
<div>&nbsp;</div>
<div>Now when you encode your video at 3,500kbps (kilo bits per second) you're indirectly saying you're using 3,500 kilo bits of information to represent 30 frames or images, where each image has a dimension of 1280x720. Some of you have probably figured out where I'm headed with this, but I'll explain anyway.</div>
<div>&nbsp;</div>
<div>If the dimensions if the video were smaller you'd have more bits to represent each frame. In other words, if you crop your wide screen video to the actual size of the picture rather than leave the letterboxing in place, you'd get a video that has dimensions of 1280x544. Each frame is actually smaller and given the same video bit rate you have more bits available to represent each frame and so the picture quality improves a bit.</div>
<div>&nbsp;</div>
<div><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=8"> <span style="font-weight: bold;">Image 3: Cinemascope aspect (2.35:1) picture and video. For&nbsp;Cinemascope video, crop the video to the correct dimensions.</span><br style="font-weight: bold;">
</div>
<div>&nbsp;</div>
<div>The same applies for case 2 above. If your video is encoded with the correct dimensions, the actual frame size is smaller (for the same given width) since the height is smaller and so once again you have more bits to represent each frame. <br>
</div>
<div>&nbsp;</div>
<div><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=9"><span style="font-weight: bold;">Image 4: HD Video in HD aspect (16:9). Not letterboxing.</span><br>
</div>
<br>
I hope this explanation helps you understand why you <span style="font-weight: bold;">should not</span> use letterboxing for your online videos and in particular on ExposureRoom since we retain the dimensions of your video.]]></description><category>Video</category><category>Aspect Ratio</category><category>HD Video</category><category>Letterboxing</category><category>Widescreen 16:9</category></item><item><title>Getting Your HD Videos to show in the Correct Aspect</title><pubDate>Wed, 25 Jun 2008 08:46:08 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/33/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/33/</guid><description><![CDATA[<h4>The Problem</h4>
<div>One would think that of all things, getting your video to show in the correct aspect ratio&nbsp;would be something that just happens. In reality, we find however that this is not the case. The most common problem people seem to have is what I call a "squished" video. A squished video is one where it seems the video is too tall or that it got squished from the sides (pressed in). Another common problem is that that the video frame is really in 4:3 aspect ratio while the picture (the video) within is in 16:9 but a lot of space is wasted due to letterboxing. In other words, it's not as wide as it should be or the actual video is not the dimensions you expect.&nbsp;<br>
<br>
The image below shows a frame of an HD Video that is in the correct aspect ratio of 16:9.</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=1" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=1&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>This next image shows a frame of the same HD Video but "Squished". Notice that the video is really in a 4:3 aspect ratio and not 16:9 aspect ratio as it should be. Things look taller and thiner (squished).</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=2" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=2&amp;reduced=true" border="0"></a>I </div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>This image shows another common problem. The video picture appears in the correct aspect ratio of 16:9, however the video itself is in a 4:3 aspect ratio. The encoder has compensated for the difference by letterboxing the video, effectively making the video a lot smaller than it should be in order to fit.</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=3" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=3&amp;reduced=true" border="0"></a>&nbsp;</div>
<div>&nbsp;</div>
<h4>Why does something so simple end up being so difficult</h4>
<div>I think these issues stem from a few things that are seemingly disconnected.</div>
<ol>
    <li>The way your camera records and outputs video</li>
    <li>The editing software you use and the abundant choices it offers for encoding, none of which really seem to apply to what you're trying to do. </li>
</ol>
<h4>HD, HDV, Full Raster</h4>
<div>The video output by HD Video cameras comes in at least 3 flavors. This is directly related to the type of HD video your camera captures or outputs. Standard HD (or full HD) is 1920x1080 (16:9 aspect ratio) or also called full raster. Here are some of the HD formats and their raster dimensions.</div>
<div>&nbsp;</div>
<div>
<table style="border: 1px dotted #7f7c75;">
    <tbody>
        <tr>
            <td style="border: 1px dotted #7f7c75;">HDV, XDCAM</td>
            <td style="border: 1px dotted #7f7c75;">1440x1080</td>
        </tr>
        <tr>
            <td style="border: 1px dotted #7f7c75;">AVCHD, XDCAM EX</td>
            <td style="border: 1px dotted #7f7c75;">1920x1080</td>
        </tr>
        <tr>
            <td style="border: 1px dotted #7f7c75;">DVCPro HD</td>
            <td style="border: 1px dotted #7f7c75;">1280x1080</td>
        </tr>
    </tbody>
</table>
</div>
<div>&nbsp;</div>
<h4>Pixel Aspect Ratio</h4>
<div>Before going on, I'd like you to understand another concept. Pixel aspect ratio or PAR. Yes, I do mean pixel aspect ratio and not video aspect ratio. TV screens&nbsp;have rectangular pixels. That is each pixel is wider than it is taller. Wider by a factor of 1.3333333333333333333. So the pixel aspect ratio of TV monitors is 1.3333333333333333333:1. Computer monitors have square pixels (and so a pixel aspect ratio of 1:1). Are you beginning to see where we're going with this? No? Ok, no problem. If you multiplied 1440 x 1.333333333333333333 you'll get 1920. What this means is that a squished video would actually look normal when viewed on a TV monitor, because the TV stretches your video out.</div>
<div><br>
This might actually confuse you more instead of clearing things up, but bear with me a moment. It's important to know that there is a difference between encoding for DVD or Blu-ray and for online viewing. The trick is to keep in mind, that when encoding video for online purposes, be sure to choose the Square Pixel option. That's not the only thing but just one of the things to keep in mind.</div>
<div>&nbsp;</div>
<h4>Video Editing Software</h4>
Video editing software have their own terminology for the various attributes one can choose when attempting to encode video. To further aggravate matters, your editing software most likely compensates for the difference in pixel aspect ratios, while editing and so you don't see the issue at the time of editing but only notice that your video is squished after encoding.
<h4>The Solution&nbsp;</h4>
<div>Finally, here are the settings you should use to ensure your video is rendered with the correct aspect ratio.</div>
<ul>
    <li>Choose <strong>Square pixels</strong>&nbsp; - <em>Do not choose Widescreen 16:9, HD Anamorphic 1080 or any other option</em></li>
    <li>Make sure you choose or set the <strong>correct dimensions </strong>(1920x1080 or 1280x720). For most online video hosting services that support HD video you'd probably choose to encode at 1280x720. </li>
</ul>
<p>The image below shows and annotated version of Adobe Premiere Pro CS3's Media Encoder screen with the wrong settings.</p>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=4" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=4&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>The image below shows and annotated version of Adobe Premiere Pro CS3's Media Encoder screen with the <strong>Correct settings</strong>.</div>
<div><a href="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=5" target="_blank"><img alt="" src="http://exposureroom.com/GetMemberJournalImage.aspx?j=Articles&amp;id=5&amp;reduced=true" border="0"></a></div>
<div>&nbsp;</div>
<div>I hope this article has helped you better understand the cause of your issues and the solution.</div>
<div>&nbsp;</div>
<div class="MsoNormal" style="margin: 0in 0in 0pt;"><span style="font-size: 12pt; font-family: 'Arial','sans-serif';">I've encoded the same source video using the above two settings so you can see the difference for yourselves.<o:p></o:p></span> The first one is the correct aspect ratio, while the second is the squished aspect ratio version.</div>
<div class="MsoNormal" style="margin: 0in 0in 0pt;">&nbsp;</div>
<div><a href="http://exposureroom.com/members/skumar.aspx/assets/b61032c949084f0e89bc1d47cf3e57f2/" target="_blank"><img title="Click Here to View The Video Titled: Correct Aspect HD Video" alt="Click Here to View The Video Titled: Correct Aspect HD Video" src="http://exposureroom.com/getassetthumbnailimage.aspx?id=b61032c949084f0e89bc1d47cf3e57f2&amp;size=sm" border="0"></a>&nbsp;</div>
<div>&nbsp;</div>
<div><a href="http://exposureroom.com/members/skumar.aspx/assets/a77701f64859431a9c07abf03ced8546/" target="_blank"><img title="Click Here to View The Video Titled: Incorrect Aspect Ratio - HD Video" alt="Click Here to View The Video Titled: Incorrect Aspect Ratio - HD Video" src="http://exposureroom.com/getassetthumbnailimage.aspx?id=a77701f64859431a9c07abf03ced8546&amp;size=sm" border="0"></a></div>]]></description><category>Video</category><category>Aspect Ratio</category><category>HD Video</category><category>Letterboxing</category><category>Widescreen 16:9</category></item><item><title>What are WebServices</title><pubDate>Fri, 11 Jan 2008 14:34:12 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/1/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/1/</guid><description><![CDATA[WebServices are - No wait! I'm not going to give you yet another definition. If you're like me, you'll probably understand it better with as example. That's what I'll try and do. 
<p>So here is a simple example. Lets say, FedEx has a WebService that allows customers to get information regarding a certain package, given the shipment no. So if you access this WebService, call it's method and supply the shipment No. you'll be given the estimated date and time of receiving your package. This sort of thing is easy to perceive in terms of a web site and user interface is it not? Well, WebServices are really very similar except with one key difference. They allow for non-interactive access. That is, machine to machine communication, without the need for human intervention. </p>
<p>Lets say, you were building a large system and one of it's functionalities was to be able to retrieve information about a certain FedEx package given the Shipment No. What you will do then, is use the "service" provided by FedEx to do this non-interactively (without human intervention) through your system. </p>
<p>Lets imagine that there are other similar "services" you could utilize in your system and you'd like to use these services rather than have to build them yourself. Essentially, you are building a system by "re-using" components that someone else has built and made available to you. It does not matter to you, what platform the service is running under or what tool was used to develop it. All you really care about is that you can find out how to use the service. This means your system is effectively decoupled from these "services" since you're not tied to using these services on a certain platform or using a certain development tool. </p>
<p>Lets sum it up now: 
<ol>
<li>Re-useable "components". 
<li>Platform agnostic. 
<li>Implementation agnostic. 
<li>Following certain published specifications/standards. 
<li>Decoupled or loosely coupled. </li></li></li></li></li></ol>That's what WebServices are all about. The ability to build distributed systems that are loosely coupled, dynamically integrated, using re-usable "components". 
<h3>SOAP for the Delphi developer</h3>SOAP (<b>S</b>imple <b>O</b>bject <b>A</b>ccess <b>P</b>rotocol) is an XML application. That's how everyone describes it. I prefer to say, SOAP is an application of XML (i.e. a way in which XML can be used). XML-RPC (XML Remote Procedure Call) is SOAP's predecessor. A company called UserLand Software developed XML-RPC back in 1998. XML-RPC later evolved into SOAP as a more mature protocol and is supported by big names in the IT industry such as, IBM, Microsoft, Sun, Apache etc. 
<h3>Why SOAP</h3>As if we don't already have our plates full with tons of other technologies/buzz words huh? Well, this one really does make sense. To better understand why, we need to take a look at what technologies SOAP intends to replace and the problems with these technologies today. 
<p>Most distributed systems today use technologies such as DCOM and CORBA. Systems built with these technologies are: </p>
<ol>
<li>Tightly coupled. 
<li>Often platform specific and therefore not interoperable. 
<li>Need to be configured on the client machines. 
<li>Have security issues, primarily when it comes to firewalls and the ability to get past them without having to punch holes through them to get them to function normally. </li></li></li></li></ol>SOAP sets out to try and overcome most of the issues cited above. Probably, <b><i>the</i></b> most important aspect of SOAP is not technology, but the fact that everyone (well, everyone that matters or can make a difference) has agreed to work together and formulate standards and adhere to them. The rest of what SOAP is, is really these specifications that everyone has agreed to abide by. So SOAP is not some fancy new technology. It is a simple technology (if you want to call it that), we're only just using our heads this time around, learning from mistakes in the past. Swallowing our egos and pride and making the effort of working with competitors to provide the rest of us with a <b>S</b>imple <b>O</b>bject <b>A</b>ccess <b>P</b>rotocol (that fit quite well didn't it?) 
<p>So SOAP sets out to achieve: </p>
<ol>
<li>Interoperability. 
<li>Decoupled distributed systems. 
<li>Easy access through Firewalls etc. </li></li></li></ol>The need for configuration still remains, as this depends on the software used to build the client applications. Configuration issues related to security will most probably not exist on the client. 
<p>Essentially, if you want to use a "service" you should not need to know the platform on which this service is running and nor should you be concerned about the implementation details. This is very similar to HTTP and Web Browsers. You can use a Web Browser today and surf the world wide web without the need to know what kind of server is serving you the web pages (platform, server vendor etc.) nor how it is serving you these pages (implementation - static pages, dynamic pages, ISAPI, ASP etc.). All you should need to know, is: 
<ol>
<li>What are the methods of the service and parameters to these methods, and the types of these parameters (string, integer etc.) 
<li>If a method is returning some information, then what are the details of that (parameters, types etc.) </li></li></ol>SOAP is a W3C recommendation and is being supported by most of the big names in the industry (IBM, Microsoft, Developmentor, Apache, Sun etc.). To me, it looks like everything is going to be a WebService in some form or the other. Microsoft' s .NET strategy also revolves around SOAP. 
<h3>Wire Protocol</h3>SOAP is a wire protocol. What that means is SOAP is used across the wire or SOAP comes into play between the two end points. When information needs to be sent across the wire, SOAP is used. It doesn't matter what was used to send it across the wire and it doesn't matter what technology is used once it gets to the other end (You are free to use COM/DCOM and/or CORBA etc. at the client end and server end). To this end, SOAP is (transport) protocol agnostic. You're free to use any transport protocol such as, HTTP, FTP, SMTP etc. however, most implementations of SOAP use HTTP as the transport protocol. There are additional specifications for SOAP bindings to HTTP as well. I personally think, HTTP is probably going to be used by 95% of SOAP implementations (but that's my personal opinion). 
<p>For those of you who are interested and know something about HTTP, a typical SOAP packet (including HTTP header) might look like this: </p>
<div class="codeblockouter">Showing a typical HTTP Header and SOAP Envelope. 
<div class="codeblockinner"><pre>POST http://webservices.matlus.com/MyService HTTP/1.0
Accept: application/octet-stream, text/xml
SOAPAction: "urn:MyServiceIntf-IMyService"
Content-Type: text/xml
User-Agent: Borland SOAP 1.1
Host: webservices.matlus.com
Content-Length: 521
Proxy-Connection: Keep-Alive
Pragma: no-cache

&lt;?xml version="1.0" encoding='UTF-8'?&gt;
&lt;SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/1999/XMLSchema" xmlns:xsi="http://www.w3.org/1999/XMLSchema-instance" xmlns:SOAP-ENC=http://schemas.xmlsoap.org/soap/encoding/&gt;
  &lt;SOAP-ENV:Body&gt;
    &lt;NS1:MethodName xmlns:NS1="urn:MyServiceIntf-IMyService" SOAP-ENV:encodingStyle=http://schemas.xmlsoap.org/soap/encoding/&gt;
      &lt;NS1:MethodParameter xsi:type="xsd:string"&gt;ParameterValue&lt;/NS1: MethodParameter&gt;
    &lt;/NS1:MethodName&gt;
  &lt;/SOAP-ENV:Body&gt;
&lt;/SOAP-ENV:Envelope&gt;
</pre></div></div>Those of you who understand XML may be able to make more sense of this than others. At this point it's not required that you understand this at all. Except that you understand that a SOAP packet or envelope is really XML. 
<h3>Why HTTP as a Transport Protocol</h3>HTTP probably has the largest investment in infrastructure today. The WWW uses HTTP (Web servers) primarily. HTTP is a stateless protocol and so is highly scaleable since it can service 100s even 1000s of requests seemingly simultaneously. Most organizations today have firewalls for protection. HTTP traffic is generally allowed past these firewalls and so SOAP traffic can get in and out without the need to configure firewalls. There are some HTTP headers that SOAP messages must contain and so firewalls can be configured to block SOAP messages if so desired ( The <code><b>SOAPAction</b></code> HTTP header is one of them. If you look at the HTTP Header above, you'll see it there). Currently, SOAP uses port 80, which is the standard for the HTTP protocol. This may change in time, but for now it is port 80. 
<h3>WebService Description Language (WSDL)</h3>This is one of those things that the powers that be have agreed on. A language that is capable of describing a web service. Essentially, the information you are able glean from a WSDL file (it's an XML file) are: 
<ol>
<li>Where is the WebService located (the URL) 
<li>What are the methods available 
<li>What are the parameters and type of these parameters 
<li>What is being returned (if anything) and what are the types </li></li></li></li></ol>Given the above information, it should be simple enough to be able to use this service, without consideration of the platform on which the actual service is running on and it's implementation details. 
<p>Ideally, given a WSDL file for a specific WebService, you should be able to build a client application that uses the services of this WebService. If the SOAP and WSDL specs are adhered to, you have all the information you need to start using the service. Similarly, when you build a WebService, you should make sure you adhere to the SOAP and WSDL specs and publish a WSDL file so others can access your WebService without a problem. </p>
<h3>WebServices Today and Tomorrow</h3>WebServices have been accepted by the IT industry. There is no question about that. This is good, since it means we're all in agreement. That's the first step. As things stand today, the WebServices available to use are primarily toys. People are feeling their way around, building simple to use WebServices, while others build WebService clients to test issues such as interoperability, usage etc. As a Delphi developer, I strongly urge you to part take in this endeavor. There are a number of websites that host WebServices. My new website at <a href="http://www.delphisoap.com/" target="blank" rel="nofollow">http://www.delphisoap.com/</a> is one of them. There are others such as: 
<ol>
<li><a href="http://www.xmethods.com/" target="_blank" rel="nofollow">http://www.xmethods.com/</a>
<li><a href="http://www.salcentral.com/" target="_blank" rel="nofollow">http://www.salcentral.com/</a> </li></li></ol>to name a few. Using these services listed at these sites, one can build clients for these web services using Delphi quite easily. 
<div class="note"><img alt="exclamation.gif" src="http://www.matlus.com/images/exclamation.gif" border="0"> Please note, that things will not always be smooth sailing. This is due to a number of reasons, some of them are: 
<ol>
<li>Some of these services were built conforming to earlier specs 
<li>Due to constantly changing specs. Delphi implementation may not always be current. I'm sure Borland on their part will do their best to release patches, fixes, upgrades etc. as soon as possible. </li></li></ol></div>There is a lot of work still remaining in the WebServices arena, to make using SOAP in Enterprise level applications feasible. Soon you should see people publishing enterprise level applications of WebServices. There is no doubt in my mind, that WebServices will change the way we look at distributed system in the near future. 
<p>There are about 35-40 implementations of SOAP today. Each employing different methodologies or catering to different platforms and development tools. Most of them are free and most of them do their best to conform to the SOAP spec. At this point in time, differences in conformance are to be expected. </p>
<p><b>Let the games begin!</b> </p>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category><category>WebServices</category></item><item><title>Delphi does WebServices</title><pubDate>Thu, 10 Jan 2008 14:34:12 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/2/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/2/</guid><description><![CDATA[<STRONG>Delphi 6 Enterprise</STRONG> makes building WebServices a breeze. This does not mean that one can't build WebServices with Delphi 6 Pro or even earlier versions of Delphi. It is possible. However, since no framework exists, you'll either have to build one yourself or use a third party toolset if it is available. In this article however, I mean Delphi 6 Enterprise whenever I say "Delphi" or "Delphi 6". Before I go on, I'd also like to say, that in order to build WebServices with Delphi 6, you don't really need to know the finer details of XML, SOAP or WebService. Having a good understanding (of SOAP, WebServices and Delphi's implementation) will most definitely go a long way in better designing, building and debugging WebServices. Please read the article <a rel="nofollow" href="http://www.matlus.com/scripts/website.dll/Tutorials?DelphiWebServices&amp;WhatAreWebServices&amp;1" target="_blank">What are WebServices</A> if you haven't already. This article assumes you read the above mentioned article. 
<H3>Delphi's SOAP Architecture and Implementation</H3>As I said earlier, SOAP itself is implementation agnostic. That said, it is important to realize that different tools implement SOAP differently. This is important to remember, since the way you develop SOAP applications depends on the implementation of the development tools you are using. In this article, I attempt to explain Delphi's implementation and architecture of SOAP and WebServices. 
<P>Before I take you into the SOAP world as Delphi sees it, I'd like to touch upon one of the advantages of exiting distributed technologies such as DCOM, CORBA and Java RMI (Remote Method Invocation). </P>
<P>The one thing that these technologies have in common is the concept of a <B><I>"Stub"</I></B>. In terms of COM and CORBA, this is a type library (IDL). One of the advantages of having a stub, besides the fact that one gets to see the interface of the object (it's methods and their parameters, properties etc.), is that the compiler can help detect errors in code at compile time. In most implementations of SOAP this is one aspect that is missing and developers that have no real need for some of the advantages that SOAP has to offer, see no point in using SOAP simply due to this fact. </P>
<P>Delphi however, has the best of both worlds. Delphi's run time type library has been enhanced and some new classes have been provided to allow for the way SOAP is implemented in Delphi. A brand new interface <CODE><B>IInvokable</B></CODE> two new classes <CODE><B>TRemotable</B></CODE> and <CODE><B>TRIO</B></CODE> and the <CODE><B>Invocation Registry</B></CODE>, make up the core of how Delphi implements SOAP. You can read about these in the on-line help. 
<P>You should also realize, that it is not required, that one accesses an "Object" in a WebService, even though SOAP has the word Object in it. Once a WebService receives a request for a certain method, how it implements this request is totally up to the WebService. It may or may not use an object in its implementation. In Delphi however, we use objects that implement Interfaces. This is not new to the Delphi developer, so when building WebServices with Delphi, you'll find yourself in familiar territory. </P>
<H3>Method Invocation - Object Pascal style</H3>In Delphi WebServices, one actually instantiates an object and invokes its methods, sending it any parameters that may have been sent in the SOAP request. It all happens seamlessly. This aspect of invoking methods and sending it any parameters that the request might contain is handled by <CODE><B>TSOAPPascalInvoker</B></CODE>. In fact, when writing a WebService, you need only to be concerned with describing your interface and implementing it in a class. The framework does the actual instantiation and method invocation automatically. 
<P></P>
<P><a rel="nofollow" href="http://www.matlus.com/images/DelphiWebServiceImpl.jpg" target="_blank"><IMG src="http://www.matlus.com/scripts/website.dll/GetThumbnailImage?reduction=2&amp;imagefile=DelphiWebServiceImpl.jpg" border=0></A> </P><BR><B>Figure 1: Showing the SOAP Request Cycle</B> 
<P>Refer to <B>Figure 1</B> 
<OL>
<LI>A SOAP Request is received by a Delphi built WebService. 
<LI>The SOAP Dispatcher recognizes this to be a SOAP Request and so, hands the Request over to the PascalInvoker. 
<LI>The PascalInvoker, parses the request. After parsing the request, It figures out the class that needs to be instantiated and the method that needs to be called. It instantiates an instance of the required class and calls the appropriate method, sending it any parameters if applicable. </LI></OL>
<P></P>
<P>Similarly, when you build a client for the WebService, and your WebService returns an object, an instance of this class/Interface is automatically created for you. That's great is it not? Yes, that's great when <B>you</B> build a WebService and the client that uses this WebService. What about when someone attempts to use your WebService and he or she is using Java on a Mac for example? Here is the beauty of it. The Delphi implementation conforms to the SOAP spec. So when others call on your WebServices, they don't see anything untoward about the response sent back by a Delphi built WebService. It's the way that a Delphi built client interprets the SOAP message (This is handled for you by <CODE><B>TRIO</B></CODE> or <B>R</B>emote <B>I</B>nterface <B>O</B>bject) that is unique. In other words, when a Delphi built client application receives a SOAP message as a response to a request, it instantiates instances it requires. That's just the way it has been implemented. Similarly, if you build a Delphi client for a non-Delphi built WebService, you still work with objects if that is how the response gets interpreted. So it doesn't really matter what platform the WebService is running under or the tool used to build it. If you build a WebService client in Delphi you work with classes and interfaces. </P>
<H3>The Interface Stub</H3>Given a WSDL file (or URL to a WSDL file) Delphi is capable of interpreting/parsing this WSDL and creating the interface and class stubs for you, no matter what platform or tool the WebService is written in! This makes it really simple to use, since you get compile time checking and further, you see the "Interface" of this WebService in a language that you are familiar with. Did you hear me mention XML anywhere in all of this? That's because, the Delphi architecture handles it all for you. What you "see" is classes and interfaces. The XML stuff happens in the background for you. 
<H3>What about the WSDL</H3>Now lets not forget the importance of publishing the interface to WebServices we develop. This is a key aspect of SOAP. For someone to use our WebService, we need to publish a WSDL file that describes our WebService in terms of a WSDL (as per SOAP Specs.). Now, we really have to work with XML, since a WSDL file is really an XML document. Well, even here, Delphi comes to the rescue. A WebService application you built with Delphi is capable of generating a WSDL file automatically based on the Interface you describe and any special types (also known as complexTypes) you may have declared. So essentially, even this aspect of SOAP is taken care of for you by Delphi. 
<P>I can image that a lot of the things I've said in this article don't make much sense. It seems to be out of context in a way. I suggest you read the next few tutorials and you'll find things will start to fall in place. Unfortunately, there is so much to be said about so many things, that I can't say much about one thing without including the other. So please bear with me. </P>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category><category>WebServices</category></item><item><title>The Multi-Module ISAPI Framework</title><pubDate>Wed, 09 Jan 2008 14:39:04 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/3/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/3/</guid><description><![CDATA[The Matlus Multi-Module ISAPI Frame work allows you to use multiple WebModules in your ISAPI Projects. Due to this, team development of ISAPI applications has been made simple/possible, since each team member can work with her own set of modules to be later seamlessly merged with the main application. But that's not all. The Matlus Multi-Module ISAPI framework has a number of features (that are lacking in WebBroker) built into it. This framework has been built with robust, Industrial strength applications in mind, thus providing required features out of the box. Complimenting the Multi-Module framework is a component suite enables building such systems 
<H2>Basic Concepts</H2>Basically, there is a <B>Multi-Module</B> Project Expert that plugs into the IDE. The options you have in the Expert are: <BR><IMG alt="Showing the Multi-Module ISAPI Expert Dialog" src="http://www.matlus.com/MMFw/images/ExpertDialog.png" border=0> 
<OL>
<LI>The Number of Slave Web Modules for Multi-Module ISAPI project 
<LI>Addtional Components (that are part of my package) 
<LI>Output Folder (such as C:\inetpub\scripts) 
<LI>The Host Application (used for debugging) </LI></OL>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> It should be noted that currently, only the default settings are implemented. That is you can build a multi-module ISAPI extension, you can choose the number of slave modules and you can determine the output folder of the compiled dll and the host application. </DIV>
<P>The expert then builds one Master WebModule (You can have only one Master WebModule per project), and one or more Slave WebModules (in reality, you don't want any slave modules, until you've named your Master Web Wodule. The reason for this will be explained later). There is also a <B>New Slave Module Expert</B> so you can add additional slave modules at a later time. </P>
<P><IMG alt="The Multi-Module framework architecture" src="http://www.matlus.com/MMFw/images/MultiModuleArchitecture.png" border=0> </P>
<DIV class=codeblockouter>The Master WebModule unit the Project Expert Creates 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#808080>{**********************************************}
{  Multi-Module Support for ISAPI Applications }
{       Developed by Shiv R. Kumar (2001)      }
{              Master Web Module               }
{**********************************************}
</FONT><FONT color=#0000ff><B>unit </B></FONT><FONT color=#000080>Unit1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>interface

uses
  </B></FONT><FONT color=#000080>Windows</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Messages</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>SysUtils</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Classes</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>MsMultiModule</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>HTTPApp</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsMasterWebModule1 </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsMasterWebModule</FONT><FONT color=#ff0000>)
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>MsMasterWebModuleCreate</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>);
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#808080>{ private declarations }
  </FONT><FONT color=#0000ff><B>public
    </B></FONT><FONT color=#808080>{ public declarations }
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>var
  </B></FONT><FONT color=#000080>MsMasterWebModule1</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>implementation

</B></FONT><FONT color=#808080>{$R *.DFM}


</FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsMasterWebModuleCreate</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
</B></FONT><FONT color=#808080>{***************************************************************}
{ If you add Slave WebModules to your project, be sure to       }
{ to include a call to the ModuleFactory of the Salve WebModule }
{ Example usage of ModuleFactory                                }
{ ModuleFactory(TMsSlaveWebModule2, True, True);                }
{***************************************************************}
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>.
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<H2>The Dispatching Mechanism</H2>The Master WebModule is an extension of the normal WebBroker WebModule. Therefore it has actions, that function similar to the normal WebModule. Slave WebModules are almost identical to a regular WebModule and so also have their own actions. Both kinds of Web Modules can also have <B>default</B> actions. 
<P>The Master WebModule's dispatcher fields <B>all</B> requests made on the ISAPI Dll. The Master WebModule's dispatcher handles dispatching requests either to itself, or the other Slave WebModules. </P>When a request comes in, the Master dispatcher first tries to determine if the request is for one of it's own actions. If so, it dispatches it to the relevant action. If not, it then tries to determine if the request is for an action in one of the Slave WebModules that have been registered with it. It does this by matching the <B>Class Name</B> (not including the "T") of each of the Slave WebModules and the Request URL (<CODE>PathInfo</CODE>). 
<P>
<P>Lets assume the name of the ISAPI dll is <CODE>Multimodule.dll</CODE>. A URL like this: <PRE>http://www.matlus.com/scripts/multimodule.dll/MyPathInfo
</PRE>will be dispatched to the Master WebModule's action whose <CODE>PathInfo</CODE> is <CODE>/MyPathInfo</CODE>. If an action with this <CODE>PathInfo</CODE> does not exist it will dispatch it to it's default action. On the other hand, a URL like this: <PRE>http://www.matlus.com/scripts/multimodule.dll/SlaveModule1/MyPathInfo
</PRE>will be dispatched to the Slave WebModule whose <CODE>ClassName</CODE> is <CODE>TSlaveModule1</CODE>. The Master WebModule's dispatcher does not try and determine if a corresponding action exists in the Slave WebModule. It simply hands the request over to the Slave WebModule. The Slave WebModule then dispatch the request to the appropriate action. If no action exists, with a matching <CODE>PathInfo</CODE> the Slave WebModule's dispatcher will dispatch it to its default action if one exists. If a default action does not exist, the Request is bounced back to the Master WebModule and will then be handled by the default action of the Master WebModule. The actual handling of a request once it has been dispatched to an action is identical to the way you'd handle it in a normal WebBroker application. That is to say, you code the OnAction event of the actions you define to get the job done. 
<P></P>
<H2>Session Management</H2>The Session Management is comprised of a TMsSessionInfo object. This object holds session information for each session. A TMsSessionBroker object. This object is a thread safe hash table that maintains the list of TMsSessionInfo objects and manages the expiration of sessions etc. For the programmer, the Master WebModule surfaces a TMsSessionManager object. The SessionManager object's methods are similar to the SessionBroker, in that it allows access to an instance of TMsSessionInfo, thereby giving the programmer access to any information stored in the session. Besides a list of Name-Value pairs, the SessionInfo object also has a "Data" property (Pointer). 
<P>The Session Management has been built with Remote Session Management in mind and will allow session information to reside across application and machine boundaries. (there is a Port and Server property available at design time as part of the Master WebModule). <B>This feature has not been implemented as yet</B>, but the hooks are in place. </P>
<P></P>
<DIV class=codeblockouter>Here is a class declaration of the SessionManager object. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#808080>{ TMsSessionManager }
  </FONT><FONT color=#000080>TMsSessionManager </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TPersistent</FONT><FONT color=#ff0000>)
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#000080>FSessionManagerIndentifier</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FSessionManagerTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FSessionBroker</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsSessionBroker</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FCurrentSessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FServer</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FPort</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetSessionIdentifier</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetSessionManagerTimeOut</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionManagerTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SetData</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetData</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>SessMgrOnBeforeDeleteSession</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>SessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
  </FONT><FONT color=#0000ff><B>public
    constructor </B></FONT><FONT color=#000080>Create</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>destructor </B></FONT><FONT color=#000080>Destroy</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>override</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>CreateSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>overload</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>CreateSession</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TimeOutInMinutes</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD</FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>overload</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>ClearSessionInfo</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>AddSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Value</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>DeleteSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>Name</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>);
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>DeleteSession</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetSessionData</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>CurrentSessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FCurrentSessionID </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>FCurrentSessionID</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetData </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>SetData</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>published
    property </B></FONT><FONT color=#000080>SessionTimeOut</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>DWORD </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetSessionManagerTimeOut </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>SetSessionManagerTimeOut</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>SessionIdentifier</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FSessionManagerIndentifier </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>SetSessionIdentifier</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Server</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FServer </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FServer</FONT><FONT color=#ff0000>;</FONT><FONT color=#808080>{ TODO -oShiv -cFuture : To be Implemented }
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>Port</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FPort </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FPort</FONT><FONT color=#ff0000>;</FONT><FONT color=#808080>{ TODO -oShiv -cFuture : To be Implemented }
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The Session Management can use Fat URLs, Cookies or Hidden fields. The order of precedence is in that order. By default, the <CODE>SessionIdentifier</CODE> is <CODE><B>sid</B></CODE>, which means when you pass the session id back and forth between the browser and ISAPI, it should be in the form: </P><PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid={12805C36-7ABE-4E4D-B6B5-31C3CA0B9BA8}
  </CODE>
</PRE>In code however, you would do it like this: <PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid=
  </CODE>
</PRE>
<P>If you're using cookies, then it should be in the form</P><PRE>  <CODE>
    sid={12805C36-7ABE-4E4D-B6B5-31C3CA0B9BA8}
  </CODE>
</PRE>
<P>If you're using a hidden field then the name of the field should be <B>sid</B>.</P>
<P>The Master WebModule has a property called <CODE>SessionIdentifier</CODE>. The value is this property is <CODE>sid</CODE> by default. If you change this property to something else, be sure to use this new value everywhere including the special tag <CODE></CODE>.</P>Creating a new session is as simple as: <PRE>  <CODE>
    SessionManager.CreateNewSession;
  </CODE>
</PRE>
<P>The <CODE>CreateNewSession</CODE> method has a default parameter called <CODE>SessionTimeOut</CODE>. This property is defaulted to whatever the Master WebModule's <CODE>SessionTimeOut</CODE> property is. The Session Manager allows for each session to have it's own timeout. If you need to use this feature, you simply set the value at the time of creating a new session. The timeout value is in minutes.</P>
<P>When you create a new session, the <CODE>SessionManager.CurrentSessionID</CODE> is set to a GUID. You should hardly ever need to use this property, since where you need to put the GUID (in html) you can simply use the special tag <CODE></CODE>. </P>
<P>When a Request comes in, the Session Manager automatically puts you in the context of the session. So any operations you do with respect to the Session Manager is with the session that was identified in the URL (or cookie or hidden field). </P>
<P>In practice, you never have to put the GUID in the URL yourself. If the html you send as a Response is in the form </P><PRE>  <CODE>
    http://www.matlus.com/scripts/multimodule.dll/somepathinfo?sid=&lt;#sid&gt;
  </CODE>
</PRE>
<P>The Master WebModule will automatically replace the <CODE>&lt;#sid&gt;</CODE> tag with the GUID of the current session. So no matter where you put the <CODE>&lt;#sid&gt;</CODE> tag in your html, it will be replaced by the Master WebModule's in built PageProducer. This PageProducer understands some other tags as well. Such as: </P>
<UL>
<LI>&lt;#scriptname&gt; is replaced by: Request.ScriptName 
<LI>&lt;#sid name="NameOfSessionItem"&gt; is replaced by the <CODE>Value</CODE> of the item 
<LI>&lt;#sid name="sessioninfo"&gt; is replaced by an html page listing all the name=value pairs of the current session </LI></UL>
<P>
<H2>Tagging objects with Sessions</H2>The ability to tag an object with the session is really useful. I've used this to tag a DataModule that contains other component/objects and has it's own methods etc. This ability allows different users to have their own connections to databases, and data access objects, where you might need to have different users connect to different databases (or with different user names). I've used this also in cases where a TMsDataSetTableProducer (the component produces "pages" of a result set, with Paging and navigation etc.) can be used for search results, where each user can potentially get totally different result sets. Besides the fact that you don't need to query the database each time for each user, since each user gets her own instance of a dataset, the cursor remains where you left it, and as a result, you don't need to navigate to the first record only to move to the 200th record say. This speeds the response of the application quite significantly. All in all, Session Management without the ability to tag objects is quite useless in the "real world". 
<P></P>Of course, what good is the ability to tag objects with a session if you don't have the ability to free these objects when the session is deleted? The Master WebModule surfaces an OnBeforeDeleteSession for this purpose. The event prototype looks like this: 
<DIV class=codeblockouter>The OnBeforeDelete event of the Master WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsMasterWebModuleBeforeDeleteSession</FONT><FONT color=#ff0000>(
  </FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>SessionID</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Data</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Pointer</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin

end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>Since the <CODE>Data</CODE> property is a pointer, you are free to tag any object to the session. It could be an ObjectList or a DataModule that has other objects and Objects lists. </P>
<H2>Additional Events</H2>
<P>In addition to the events of a normal WebModule, the Master WebModule publishes the following events:</P>
<DIV class=codeblockouter>Other Events the Master WebModule surfaces. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnModuleHTMLTag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnModuleHTMLTag </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnModuleHTMLTag </FONT><FONT color=#0000ff><B>Write </B></FONT><FONT color=#000080>FOnModuleHTMLTag</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnException</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TExceptionEvent </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnException </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnException</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnSessionInvalid</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnSessionInvalid </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnSessionInvalid </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnSessionInvalid</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnSessionExpired</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnSessionExpired </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnSessionExpired </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnSessionExpired</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>OnBeforeDeleteSession</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>FOnBeforeDeleteSession </FONT><FONT color=#0000ff><B>write </B></FONT><FONT color=#000080>FOnBeforeDeleteSession</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P></P>
<DIV class=codeblockouter>Signatures of some of the additional events. 
<DIV class=codeblockInner><CODE><PRE><FONT face="Courier New">  <FONT color=#000080>TExceptionEvent</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></FONT> <FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>TObject</FONT><FONT color=#ff0000>;</FONT> <FONT color=#000080>E</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>Exception</FONT><FONT color=#ff0000>;</FONT> <FONT color=#0000ff><B>var</B></FONT> <FONT color=#000080>Handled</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>Boolean</FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT>
  <FONT color=#000080>TOnSessionInvalid</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></FONT> <FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>TObject</FONT><FONT color=#ff0000>;</FONT> <FONT color=#000080>SessionID</FONT><FONT color=#ff0000>:</FONT> <FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT>
  <FONT color=#000080>TOnSessionExpired</FONT> <FONT color=#ff0000>=</FONT> <FONT color=#0000ff><B>procedure</B></FONT> <FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>:</FONT> <FONT color=#000080>TObject</FONT><FONT color=#ff0000>;</FONT> <FONT color=#000080>SessionID</FONT><FONT color=#ff0000>:</FONT> <FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>)</FONT> <FONT color=#0000ff><B>of</B></FONT> <FONT color=#0000ff><B>object</B></FONT><FONT color=#ff0000>;</FONT></FONT>
</PRE></CODE></DIV></DIV>
<P>The Master WebModule has a few "helper" methods as well. They are:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>ExtractMultipleRequestFields</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>FieldName</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetRequestFieldValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>FieldName</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>): </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The <CODE>ExtractMultipleRequestFields</CODE> coms in handy when you have a multi-select list box in a form and you need to find out which items were selected (The WebBroker framewrork does not support this out of the box). This method (given the field name) returns the <CODE>StringList</CODE> containing all the <CODE>Values</CODE> that were selected in the list box.</P>
<P>The <CODE>GetRequestFieldValue</CODE> makes processing Requests easier since it decouples code from the need to know the <B>type of method</B> (GET or POST) that was used. Frequently, one needs to process boths kinds of <CODE>Requests</CODE> in a certain action. Internally, this method determines the method type of the Request and uses either the Request.ContentFields property or the Request.QueryFields property and returns the <CODE>Value</CODE> for a given <CODE>Name</CODE>.</P>
<P>The (read only) <B>property</B> <CODE>ModuleName</CODE> returns the Path and File name of the ISAPI Dll. The read access method of this property uses the <B>GetModuleFileName</B> API.</P>
<H2>Handling Special tags - A "Catch All" OnHTMLTag event (built in Page Producer)</H2>Every Response, leaving the application passes through the Master WebModule's internal PageProducer. Besides, processing the tags it understands, as mentioned earlier, the programmers has the opportunity to process tags as well. In case the programmer replaced some tags with tags that this PageProducer understands, these tags will be replaced once again. This makes is really convenient when designing applications, since no matter where (which module) you put these tags, they can be processed at a single point if required. Or no matter where you put in the special tags that the Session Manager understands (as listed above), they are guaranteed to be processed by the Master WebModule. 
<H2>Communicating between Slave WebModules and the Master WebModule</H2>To create a new Slave Module, you use the New Slave WebModule Expert. This expert creates a WebModule whose class looks like this: 
<P>
<DIV class=codeblockouter>The unit generated by the New Slave WebModule Expert. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#808080>{**********************************************}
{  Multi-Module Support for ISAPI Applications }
{       Developed by Shiv R. Kumar (2001)      }
{               Slave Web Module               }
{**********************************************}
</FONT><FONT color=#0000ff><B>unit </B></FONT><FONT color=#000080>Unit2</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>interface

uses
  </B></FONT><FONT color=#000080>Windows</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Messages</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>SysUtils</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Classes</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>MsMultiModule</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>HTTPApp</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Unit1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsSlaveWebModule2 </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsSlaveWebModule</FONT><FONT color=#ff0000>)
    </FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#808080>{ private declarations }
  </FONT><FONT color=#0000ff><B>public
    property </B></FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1 </FONT><FONT color=#0000ff><B>read </B></FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#808080>{ public declarations }
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>var
  </B></FONT><FONT color=#000080>MsSlaveWebModule2</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>implementation

</B></FONT><FONT color=#808080>{$R *.DFM}

</FONT><FONT color=#0000ff><B>function </B></FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>GetMaster</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>begin
  </B></FONT><FONT color=#000080>Result </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>TMsMasterWebModule1</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>MasterWebModule</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>.
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>Notice that the expert has included the Master WebModule's unit (<CODE>Unit1</CODE> in this case) in the uses clause of the <B><CODE>Interface</CODE></B> section. Notice also, that the (read only) <B>property</B> <CODE>Master</CODE>, returns a type <CODE>TMsMasterWebModule1</CODE>. This happens to be the class name of the Master WebModule at the time of creating the new Slave WebModule.</P>
<P></P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> It is therefore recommended that one should first name and save the Master WebModule (class and unit) before creating additional Slave WebModule. The Expert will then use the unit name and class name when generating the code for the Slave WebModule class. </DIV>
<P></P>So essentially, <B>All</B> Slave WebModules, have a <B>property</B> called <CODE>Master</CODE>, that returns a reference to the Master WebModule instance. So when you need to reference the Master WebModule's Session Manager, your code would look like this: 
<DIV class=codeblockouter>Referencing the Master WebModule's Session Manager from a Slave WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>MsSlaveWebModule2WebActionItem1Action</FONT><FONT color=#ff0000>(
  </FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebRequest</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Response</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebResponse</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>Handled</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Boolean</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
  </B></FONT><FONT color=#808080>{ Adding "ProductID" to the Current Session as received from a Posted Form }
  </FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>SessionManager</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>AddSessionInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'ProductID'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>Master</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>GetRequestFieldValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'ProductID'</FONT><FONT color=#ff0000>));
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<H2>Registering Slave WebModules</H2>Each time you add a new Slave WebModule to your project, you need to register it with the Master Module's Module Factory. An example of the code you need to use is provided as comments in the OnCreate event of the Master WebModule. For the Slave WebModule class shown above, the code would look like this: 
<DIV class=codeblockouter>Registering Slave WebModules with the Master WebModule. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#000080>ModuleFactory</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsSlaveWebModule2</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>True</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>True</FONT><FONT color=#ff0000>);
</FONT></FONT>
</CODE></PRE></DIV></DIV>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>Best Practice - Using the TPageProducer Component</title><pubDate>Tue, 08 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/4/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/4/</guid><description><![CDATA[In my experience with Delphi's WebBroker framework since Delphi 3, I've found the TPageProducer to be the single most useful component (out of the box). I have put this component to many uses in many different applications. Over a period of time, I've come up with a set of rules that define the ways in which I use this component. In this article, I'd like to show you, what I think is the best way to use this component. 
<H2>Fixing A Minor Flaw</H2>Before we look at the "best practice" use of this component, I'd like to highlight a flaw (in my opinion) in the component. When the component encounters a tag that you don't process (in the OnHTMLTag Event), it "swallows" this tag. This behavior prevents you from being able to chain page producer one after the next (which by the way is a good use of this component). If you're not familiar with the use of the TPageProducer, I suggest reading the tutorial titled - Using Cookies Hidden Fields and the TPageProducer. 
<P>To circumvent this issue in the OnHTMLTag event of your PageProducer, you could have code like this:</P>
<DIV class=codeblockouter>Circumventing the "flaw" in the TPageProducer 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TForm1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>PageProducer1HTMLTag</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Tag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TTag</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>ReplaceText</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
  if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'sometag'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'Something'
  </FONT><FONT color=#0000ff><B>else
  begin
    if </B></FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Text </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'' </FONT><FONT color=#0000ff><B>then
      </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;#%s&gt;'</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>])
    </FONT><FONT color=#0000ff><B>else
      </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;#%s %s&gt;'</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Text</FONT><FONT color=#ff0000>]);
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P></P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No:1 HTML should not be mixed in with code. </DIV>In real world Applications, I don't like to have HTML mixed with code in my ISAPI applications. This "rule" has a number of benefits: 
<OL>
<LI>Makes the code cleaner and therefore more maintainable/manageable. 
<LI>Speeds up the application quite a bit. (Due primarily to the intricacies related to string handling in 32 bit Delphi) 
<LI>Allows the use of HTML designers (designers being either tools or people) to design the "templates", while you the programmer can code the business rules. (yea right if only we were that lucky!) 
<LI>Allows for changing the page layout of your web sites/applications without the need to re-compile the application. </LI></OL>
<P>The TPageProducer has a property called HTMLFile. You should use this property to load up static html templates at run time. If you're having problems loading up files/images at run time due to "path" issues, I suggest reading the article titled - Relative/Virtual Paths Explained.</P>
<H2>Defining a Language</H2>
<P>I won't go into HTML/JavaScript specific things here, but rather talk about how templates should be designed from the perspective of using a TPageProducer to "process" templates.</P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No:2 Define a minimal "tag language" that you use over and over again across applications. </DIV>This rule goes a very long way in: 
<OL>
<LI>Streamlining your templates 
<LI>Making your templates more readable/maintainable/configurable 
<LI>When working in a team where there are HTML designers (people) they start to understand your "language" and can start to apply it in templates they build for you. </LI></OL>
<P>So what is this language about? It's simple really. It's tags that you "re-use". Tags that have "attributes" that when set control the "behavior" of the processing. Kind of like an object that has properties and setting different properties change the behavior slightly. The more generic you make your tags, the more reusable they become.</P>In the process of building web applications, there are quite a few things we seem to repeat. For example: 
<OL>
<LI>We use Request.ScriptName wherever we need the "path" of our application to be included in things like hyperlinks, form actions and the like. 
<LI>The action attribute of forms. 
<LI>The target attribute of forms. 
<LI>The src attribute of images. </LI></OL>For such needs I suggest you use tags like: <CODE>&lt;#scriptname&gt;</CODE> 
<P>All your page producers should "understand" this tag (Or at least one PageProducer in your application should). In the OnHTML event you could have code like the following:</P><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>If </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'scriptname'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
  </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Scriptname</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE>
<P>Similarly for the "form" tag <CODE>&lt;#form action="" target="" method=""&gt;</CODE></P><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'form'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
  </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'&lt;form action="%s" target="%s" method="%s" /&gt;'</FONT><FONT color=#ff0000>, [
    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'action'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'target'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'method'</FONT><FONT color=#ff0000>]]);
</FONT></FONT>
</CODE></PRE>
<P>This kind of tag gives you the flexibility to define attributes in your template while also giving you the flexibility to change them later. Granted, if you're using templates, you could simply change them there (the hard coded value of a form action say). But believe you me a time will come, when you wished you used tags in the template! For example, you might need to change either the target or the action of the form depending on some condition. Instead of having two similar templates (that need to be synchronized each time there is a change) you can have just one.</P>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> Rule No: 3 - Get used to coding your html in xhtml style. That is all tags and attributes in lowercase, all attribute values within double quotes and all empty tags closed. </DIV>
<H2>Designing Templates</H2>As our first exercise we'll look at some design aspects related to templates for HTML Forms. This form may contain various "controls" to allow for data entry. I propose the following: 
<OL>
<LI>All &lt;input&gt; elements will have one and only one tag. 
<LI>All &lt;select&gt; elements will have one and only one tag. </LI></OL>
<P>Of course one could go a step further and say that we need have only one tag for ALL controls. This is the kind of thing I do personally in fact. But I have a component that does this for me (and a lot more). But for this discussion we'll stick to the 2 proposed above.</P>
<P>We won't be talking about the html aspects of the design here (the look and feel). We'll only look at the tags involved. The tags shown below can satisfy our needs for any type of &amp;lg;input&gt; tag we need in our forms:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#ff0000>&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etText</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>10</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>10</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etHidden</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>maxlength</FONT><FONT color=#ff0000>="</FONT><FONT color=#800080>0</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etCheckBox</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>caption</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>bar</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>checked</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>false</FONT><FONT color=#ff0000>" /&gt;
&lt;</FONT><FONT color=#008000>#</FONT><FONT color=#000080>input </FONT><FONT color=#0000ff><B>type</B></FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>name</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>foo</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>value</FONT><FONT color=#ff0000>="" </FONT><FONT color=#000080>caption</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>bar</FONT><FONT color=#ff0000>" </FONT><FONT color=#000080>checked</FONT><FONT color=#ff0000>="</FONT><FONT color=#000080>false</FONT><FONT color=#ff0000>" /&gt;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>It goes without saying that this is only one tag. As a result, we can process these tags using one conditional statement in our code. It's the attributes that make all the difference. The code that processes these tags might look like this:</P>
<DIV class=codeblockouter>Sample code to process the proposed Tag Language. 
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#0000ff><B>type
  </B></FONT><FONT color=#000080>TMsHTMLElementType </FONT><FONT color=#ff0000>= (</FONT><FONT color=#000080>etText</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etHidden</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etComboBox</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etLookUpCombo</FONT><FONT color=#ff0000>,
    </FONT><FONT color=#000080>etMemo</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etCheckBox</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etButton</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>etLabel</FONT><FONT color=#ff0000>);
...
...
...
...

</FONT><FONT color=#0000ff><B>implementation

</B></FONT><FONT color=#808080>{$R *.dfm}

</FONT><FONT color=#0000ff><B>uses </B></FONT><FONT color=#000080>TypInfo</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TForm1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>PageProducer1HTMLTag</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Tag</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TTag</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#0000ff><B>const </B></FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TStrings</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>ReplaceText</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>String</B></FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>const
  </B></FONT><FONT color=#000080>sHTMLTextInput </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'&lt;input type="%s" name="%s" value="%s" maxlength="%s" /&gt;'</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#000080>sHTMLCheckRadio </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'&lt;input type="%s" name="%s" value="%s" maxlength="%s"%s /&gt;nbsp;%s'</FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>var
  </B></FONT><FONT color=#000080>sChecked</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
  </FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
</FONT><FONT color=#0000ff><B>begin
  If </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'input'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    case </B></FONT><FONT color=#000080>TMsHTMLElementType</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>GetEnumValue</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TypeInfo</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TMsHTMLElementType</FONT><FONT color=#ff0000>), </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'type'</FONT><FONT color=#ff0000>])) </FONT><FONT color=#0000ff><B>of
      </B></FONT><FONT color=#000080>etText    </FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'text'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etPassword</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'password'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etHidden  </FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLTextInput</FONT><FONT color=#ff0000>, [</FONT><FONT color=#008000>'hidden'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
                    </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>]]);
      </FONT><FONT color=#000080>etCheckbox</FONT><FONT color=#ff0000>,
      </FONT><FONT color=#000080>etRadioButton</FONT><FONT color=#ff0000>:
        </FONT><FONT color=#0000ff><B>begin
          if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'type'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>'etCheckBox'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
            </B></FONT><FONT color=#000080>sRadioOrCheck </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'checkbox'
          </FONT><FONT color=#0000ff><B>else
            </B></FONT><FONT color=#000080>sRadioOrCheck </FONT><FONT color=#ff0000>:= </FONT><FONT color=#008000>'radio'</FONT><FONT color=#ff0000>;
          </FONT><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'checked'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>'true'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
            </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLCheckRadio</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
              </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>' checked="checked"'</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'caption'</FONT><FONT color=#ff0000>]])
          </FONT><FONT color=#0000ff><B>else
            </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>sHTMLCheckRadio</FONT><FONT color=#ff0000>, [</FONT><FONT color=#000080>sRadioOrCheck</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'name'</FONT><FONT color=#ff0000>],
              </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'value'</FONT><FONT color=#ff0000>], </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'maxlength'</FONT><FONT color=#ff0000>], </FONT><FONT color=#008000>''</FONT><FONT color=#ff0000>, </FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'caption'</FONT><FONT color=#ff0000>]])
        </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P></P>
<P>Similarly, you could define a tag that (depending) on an attribute can become either a Combo Box or a List Box. Better yet, if it's a list box, whether it's a multi-select list box or a normal list box. You can then go on to define a "data aware" combo box tag that will allow you to define the stored procedure to use to populate it, the "name" field, then "value" field and so on.</P>
<P>Sooner or later you're going to want to build a specialized descendant component that does all of this for you thus allowing you to reuse your vocabulary. That's what object oriented programming is about. So don't let anyone stop you!</P>
<P>One could go in all sorts of directions with this concept. For instance, you could define a template that has a special tag like so:</P>
<P><CODE>&lt;#embedtemplate filename=""&gt;</CODE></P>
<P>buried deep inside it somewhere. The filename attribute is the name of another template, a template for an html form for instance. That way, the same basic template can be used over and over throughout your system. You could even determine the embedded template to use at run time. Or the template to use is determined by the value of a parameter in the URL or content fields of a posted form. It's up to you really. But where ever you do, make sure the concept is re-usable and is generic enough to be reusable. Give a lot of thought to naming your tags and the attributes they can/should have.</P>
<P></P>
<DIV class=codeblockouter>A sample Template that allows for embeding other templates. 
<DIV class=codeblockInner><PRE><CODE>
&lt;html&gt;
  &lt;head&gt;
    &lt;link rel="stylesheet" type="text/css" href="&lt;#statevar name="StyleSheet"&gt;
    &lt;title&gt;&lt;#title&gt;&lt;/title&gt;
    &lt;script&gt;
    &lt;#script&gt;
    &lt;/script&gt;
  &lt;/head&gt;
&lt;#body&gt;
  &lt;table border="0" cellpadding="0" cellspacing="0" width="100%" align="" valign=""&gt;
    &lt;tr&gt;
      &lt;td colspan="2"&gt;Page Header goes here&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td&gt;&lt;#embedtemplate id="1" name="LoginForm"&gt;&lt;/td&gt;&lt;td&gt;&lt;#childtemplate&gt;&lt;/td&gt;
    &lt;/tr&gt;
    &lt;tr&gt;
      &lt;td colspan="2"&gt;Page Footer goes here&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;
</CODE></PRE></DIV></DIV>
<H2>A Template that Shows Database information</H2>This kind of thing is really simple to do. Depending on your template, you should generally be able to "fill in the blanks" using one line of code. 
<P>Take a look at the template below:</P>
<DIV class=codeblockouter>A simple Template that can show information from a database. (single record) 
<DIV class=codeblockInner><PRE><CODE>
&lt;table&gt;
  &lt;tr class="tableheaderrow"&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Customer ID&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Company Name&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Address&lt;/td&gt;
  &lt;/tr&gt;
  &lt;tr class="tablerowrow"&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="CUST_ID "&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="COMPANY_NAME"&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="ADDRESS "&gt;&lt;/td&gt;
  &lt;/tr&gt;
&lt;/table&gt;
</CODE></PRE></DIV></DIV>
<P>Given a dataset that holds a record, the code to process this template might look like this:</P>
<DIV class=codeblockouter>
<DIV class=codeblockInner><PRE><CODE><FONT face="Courier New"><FONT color=#000000>  </FONT><FONT color=#0000ff><B>if </B></FONT><FONT color=#000080>AnsiCompareText</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagString</FONT><FONT color=#ff0000>, </FONT><FONT color=#008000>'fieldvalue'</FONT><FONT color=#ff0000>) = </FONT><FONT color=#800080>0 </FONT><FONT color=#0000ff><B>then
    </B></FONT><FONT color=#000080>ReplaceText </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>MyDataSet</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>FieldByName</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TagParams</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>Values</FONT><FONT color=#ff0000>[</FONT><FONT color=#008000>'fieldname'</FONT><FONT color=#ff0000>]).</FONT><FONT color=#000080>AsString</FONT><FONT color=#ff0000>;
</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>The next thing that comes to mind is; "Ok, now how do we do this for a record set that contains a number of records?". This is probably a more common need than the previous one. So let's explore this case a bit. The solution is to break up your templates in "snippets". </P>
<OL>
<LI>A Main "Table" template 
<LI>A Header Template 
<LI>A Row Template 
<LI>A Footer Template </LI></OL>
<P>The Main "Table" template essentially, has "place holders" for the other templates. This template might look like this:</P>
<DIV class=codeblockouter>The Main "Table" template used for showing Multiple Records from a Dataset 
<DIV class=codeblockInner><PRE><CODE>
&lt;table border="0" cellpadding="0" cellspacing="0" width="100%" align="" valign=""&gt;
  &lt;tr&gt;
    &lt;#tableheadertemplate name="SoAndSoTableHeaderTemplate"&gt;
  &lt;/tr&gt;
  &lt;#tablerowtemplate name="SoAndSoTableRowTemplate"&gt;
&lt;/table&gt;
</CODE></PRE></DIV></DIV>
<P>Notice that the "insertion" point where "Rows" are inserted does not have the <CODE>&lt;tr&gt;</CODE> tags around it. Unlike the tag for the header.</P>
<P>Using the earlier templates as a starting point, the header template would look like this:</P>
<DIV class=codeblockouter>A Table Header Template. 
<DIV class=codeblockInner><PRE><CODE>
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Customer ID&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Company Name&lt;/td&gt;
    &lt;td class="tableheadercell" align="center" style="font-size: smaller;"&gt;Address&lt;/td&gt;
</CODE></PRE></DIV></DIV>
<P>The Row Template would look like this:</P>
<DIV class=codeblockouter>A Table "Row" Template. Make sure you include the <CODE>&lt;tr&gt;</CODE> tags. 
<DIV class=codeblockInner><PRE><CODE>
  &lt;tr class="tablerowrow"&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="CUST_ID "&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="COMPANY_NAME"&gt;&lt;/td&gt;
    &lt;td class="tablerowcell" align="center" style="font-size: smaller;"&gt;&lt;#fieldvalue fieldname="ADDRESS "&gt;&lt;/td&gt;
  &lt;/tr&gt;
</CODE></PRE></DIV></DIV>
<P>Notice that the "row" template has the <CODE>&lt;tr&gt;</CODE> tags, while the "header" template does not.</P>
<P>I hope this article has shown you how best to utilize the power of the TPageProducer component.</P>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>The Internet and Internet Applications</title><pubDate>Mon, 07 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/5/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/5/</guid><description><![CDATA[<UL>
<LI>TCP/IP 
<LI>Domain names and IP Addresses 
<LI>Domain name registration and DNS servers 
<LI>Ports and services 
<LI>Other TCP/IP services 
<LI>Web Servers 
<LI>Web Server software 
<LI>Web sites and HTML Pages 
<LI>DHTML 
<LI>ActiveX / Java Applets 
<LI>Web Server Extensions 
<LI>CGI 
<LI>Win-CGI 
<LI>ISAPI / NSAPI 
<LI>ASP 
<LI>CGI and ISAPI 
<LI>Differences 
<LI>Advantages / disadvantages 
<LI>Browser based applications 
<LI>Internet enabled applications </LI></UL><B>
<P>Domain names and IP Addresses </P></B>
<P>Web sites on the Internet are known by their Domain Names, such as www.Microsoft.com / www.Datasourceinc.com. Domain names actually resolve to an IP address such as 207.176.25.218. So actually, to get to the DataSource web site one could actually type in http://205.177.16.151 and the browser will take you to the site. But remembering numbers such as these is not easy and so Domain Names were introduced. Domain Names (that end in - .com or .org) have to be registered with an organization called INTERNIC. There is an annual charge of $35 for this registration and the Domain Name has to be unique! When one types in a domain name, the browser actually goes to Internic's DNS (Domain Name Service) server, that resolves the Domain name to an IP address from a lookup database and gives the browser the IP address of the web site in question. The browser then goes to the IP Address. The IP address is also a unique Address. No two servers on the same network can have the same IP address. The WWW can bee looked at as one big network. Each server on the Internet can be uniquely identified by its IP address. So it follows that typing in the IP address will be a lot faster than using the domain name. </P><B>
<P>TCP/IP </P></B>
<P>Transfer Control Protocol / Internet Protocol. This is the protocol used by the WWW. For this protocol to work we have what are called clients and servers. These are software applications that can "talk" to each other. The server application has to be up and running and "listening" on a certain port number (just a number from 1 to 65535). The client application that wants to talk to the server application must use the same port number and must know the IP address of the server application. Once a connection is established between the client and server, the two can communicate. </P>
<P>Services such as HTTP, FTP, POP, SMTP are what are called "known services" and therefore use a fixed port. </P>
<P>HTTP: Port 80 </P>
<P>FTP: Port 21 </P>
<P>POP: Port 110 </P>
<P>SMTP: Port 25 </P>
<P>Again, the names of the service can be used instead of the port No., such as http://www.datasourceinc.com actually resolves to http://205.177.16.151:80. This really tells the browser and the server to use the HTTP protocol on port 80. Since port 80 is the default port, one need not specify it (and so one normally does not). One is free to use any port for "unknown services". On any one server machine/PC one can have one and only one server application listening on a port. So for a given IP address (that uniquely identifies a PC), you can only one server application listening on a given port. </P><B>
<P>Web server software </P></B>
<P>Web servers are both a physical machine as well as a software application that is listening on port 80. An FTP server is another application (also called service or more accurately TCP/IP service) listening on port 21. So you could have both, an HTTP server (Web server) and an FTP server on one single machine, since they use different ports.</P>
<P>Also one can build ones own TCP/IP applications that "talk" across the Internet using a certain port. The server application needs to be listening on a certain port and the client application needs to know the IP address and the port to use. Only clients can connect to servers. Servers can not initiate a connection by themselves. Servers typically "service" multiple clients and so the name - Server. To learn more about TCP/IP and protocols take a look at th eTCP/IP tutorials in the Tutorials section on my web site.</P><B>
<P>Web sites and HTML pages </P></B>
<P>One can have multiple web site on a single machine. The web server (application) has a way of understanding which site is required by which HTTP request it receives. Web servers have what is known as the "root" folder. The root folder is the equivalent of the "C:\" folder of the hard drive. This root folder can be any subfolder on the HDD but the server needs to be informed of it's root folder. The web server in turn can not "see" anything before this root folder. This is to provide for some form of security. The root folder is the starting point for the web server. It can "see" all the folders and subfolders in its tree. Most folders are read access only but some are read/write/execute access. Normally, one of the subfolders of the web server is /scripts (or /cgi-bin) and it is only this folder that has read/write/execute access. </P>
<P>The home page is an HTML page in the root folder by the name default.htm. So when a surfer types in the URL (Uniform Resource Locator) for your web site, the web server (application) looks for a file in its root folder by the name default.htm and sends it back, to the surfer's browser via TCP/IP or more accurately the HTTP protocol which is nothing but a layer over the TCP/IP protocol. The most common and the easiest way to have a web site is to have numerous HTML pages as physical files on the server that are hyper-linked to help navigate through the web site. This kind of site is also called a static web site. Each time you want to make a change to the web site, you have to edit/change/add the HTML pages you want. For large sites this can be a nightmare to manage. Most sites are a mix between dynamic pages and static pages. If some of your web site's information needs to come from a database of some kind, these pages need to be generated dynamically (on request) by some form of script (application programs). Examples are CGI, ISAPI, ASP etc. For your information, the contents of this page are stored in a database. When you linked to this page, an ISAPI application extracted the information for this particular page from a database and dynamically converted the information into HTML format and sent it back to you, for you to see in your browser. In fact this web site is 100% dynamic, which means there are no static HTML pages on the server's hard disk. All content resides in a database and is servered to you dynamically.</P><B>
<P>DHTML / ActiveX / Java Applets </P></B>
<P>Since HTML is very "static" and does not "respond" to the surfer of your web page, Dynamic HTML was introduced. DHTML is a combination of HTML and JavaScript or VBScript. Combining HTML with a scripting language allows for a more dynamic or active web page. Due to scripts embedded within the HTML document the browser is able to respond to certain events, similar to normal event driven programming tools. Events such as mouse moves, mouse clicks etc. are exposed by the browser to your HTML page and the HTML page can in turn "react" to these events. In this way, the HTML pages produced seem to be more responsive or alive than regular static (HTML) pages. </P>
<P>One needs to know one of the scripting languages in order to create DHTML pages. Further, DHTML is supported only by version 4.0 of both IE and Netscape. JavaScript is supported by IE and Netscape while VBScript is supported only by IE. The level of support differs between these browsers. This means that certain DHTML pages may not "work" on all browsers unlike pure HTML (HTML version 3.0 is supported by most browsers in the market today). </P>
<P>ActiveX is Microsoft's answer to Java applets. Once again ActiveX is supported only by IE version 3.02 onwards, and not by Netscape. Java applets are supported by both IE (3.02 and above) and Netscape versions 3 and is also Windows platform dependent. Besides the incompatibility issue there is a big security risk with ActiveX on a web page. The ActiveX control or document is fully capable. In that, it can access any resource on the PC. It has full access to the Win32API and all of the drives and folders. Ironically, it's these "benefits" that are the downfall of ActiveX. ActiveX is better implemented in an Intranet environment where the platform is the same, the browser versions are compatible and the ActiveX document comes from a trusted source (such as the internal IT department). </P>
<P>Java applets on the other hand are platform independent. But once again, it due to it's benefits that it has limitations. The fact that these applets are platform independent means that these applets can not make use of certain functions (API or the UI capabilities) of the operating system. The moment an applet tries to use platform specific features it looses its platform independence. For a Java applet to run in the browser the target machine needs to have the JVM (Java Virtual Machine) installed on it to be able to interpret the Java byte code in the applet. The JVM comes in many flavors and versions and is most times the cause for applet misbehavior on certain machines. Once again, Java Applets are best suited in an Intranet environment where the environment can be better controlled. Java Applets that are very basic in functionality and made for earlier versions of the JVM are and can be used in Internet applications provided of course that the browsers' version understands them. </P><B>
<P>Web server extensions </P></B>
<P>Seeing that static HTML is very limited in what it can do, web server developers designed a way to allow programmers to extend their capabilities by providing server extensions. Server extensions in their simplest form a scripts that are executed on the server side with the help of interpreters. Examples of these are Perl and Rexx and later came JavaScript and VB script. Scripts allow for server side processing and return HTML pages. Scripts allowed for data access on the server side as well. So with the help of a script, one could query a database local to the server and in return, send back the result set in the form of HTML that the web server sends back to the requester. CGI (Common Gateway Interface) is the interface that most web servers understand. This interface allows web pages to send parameters to the script via the URL and the script processes these parameters and sends back the information via the standard I/O. </P><B>
<P>Win-CGI</B> is specific to the Windows platform and Microsoft's Internet Information Server (IIS) and other compatible web server software. Here, the parameters are sent to the CGI application (normally a .exe file) via an .ini file. The script in turn writes data (the result) in this same .ini file which the web server reads and send back to the requester. </P><B>
<P>ISAPI</B> (Internet Server Application Programming Interface) is specific to IIS and other IIS compatible web server software. Microsoft, went a step further (after Netscape introduced NSAPI - Netscape Server API) to provide more functionality and faster response by introducing the Internet Server API. Using this API, one has access to the web server's functionality. ISAPI application can be written with any tool that produces a compiled native machine code output. The compiled code is generated in the form of a DLL (Dynamic Link Library). This DLL is loaded into memory by the web server upon the first request (by a web page) and is kept in memory until the HTTP service is stopped or the machine is re-booted. ISAPI applications have no limitations on the number of parameters that can be passed to them (CGI applications have a limit of 255 bytes). Further, the way the data is transferred or handed to the ISAPI is much faster than the way CGI applications are pass information to and fro. </P><B>
<P>Advantages / Disadvantages of CGI and ISAPI application. </P></B>
<P>CGI applications are generally .exe files. This means that each time a request is made via the web server, an instance of the exe is loaded into memory and the data passed to it. This exe file is later unloaded once its job is done. So, if you had 100 surfers hitting your site simultaneously and making the same request, you'll actually have 100 instances of the CGI application, all loaded in memory at the same time. The system resources required for such a feat are phenomenal. Besides that, the time it takes for an instance of a CGI application to load and initialize causes a performance hit. </P>
<P>ISAPI applications on the other hand are DLL files. A DLL is run in the process of the calling application (in this case the web server application) and only one instance is loaded. The ISAPI DLL has to be built in such a way as to incorporate safe multi-threading. For each request, the web server spawns a new thread and does not need to load and initialize the ISAPI application. Since there is no load time involved and multi-threading is employed instead of multi-instancing, the system resources required are at a minimum and the response times are far less than those with CGI applications. </P>
<P>On the other hand CGI applications, by virtue of the fact that they are .exe files and don't need to cater for multi-threading are far simpler to build than ISAPI applications. Also, since an ISAPI runs in the process space of its calling application has the capability of crashing the calling application if errors are not handled internal to the DLL. Basically, this means that if an ISAPI DLL crashes, it takes the web server application down with it. This means all web-sites hosted by that web server will not be accessible until the machine is re-booted. This is one of the primary reasons ISPs (Internet Service providers such as AOL, Erols etc.) do not allow ISAPI applications. </P><B>
<P>Browser Based Applications </P></B>
<P>Web applications or browser based applications use the browser as the front end with some form of web server extension application (CGI/ISAPI/NSAPI/ASP) running at the back end. Ideally these applications are a very powerful technology. They are zero configuration thin clients. Which means, the surfer has to do nothing on his/her PC to be able to use these applications. They are platform independent as well as browser and browser version independent. But in reality, these applications are never zero-configuration. Due to the speed with which technology is moving and the inability of individuals to keep upgrading their machines, operating systems and browsers, the zero configuration thin client can not use the new and emerging technologies. Thus browser- based applications will always have to built to conform to earlier versions of operating systems as well as browsers. </P>
<P>Besides the compatibility issues stated above, browsers, by their very nature are isolated from the PC, such that they can not access the resources of the machine they are running on. Therefore they are very limited in their capability to integrate/interface with existing systems or use the Os's API or GUI capability for better and more functional/feature rich UIs. Even in corporate environments, where operating system versions and browser versions can be controlled, these kinds of applications are not the best suited for such a need as 9 times out of 10, these applications will need to interface/integrate with existing systems in the corporate environment. </P>
<P>Browser based application therefore tend to be used for very simple needs. </P><B>
<P>Internet-Enabled Applications. </P></B>
<P>These are applications built as normal PC based applications but access data over the Internet. Effectively, these applications use the Internet infrastructure as their network. This allows for remote connectivity to data from anywhere in the world. Similar to browser based applications. With the advantage of being able to access the resources of the machine on which they are executed and thereby allowing for integration with other existing corporate systems. </P>
<P>On the GUI side, these applications are fully capable, thus allowing for "standard" features such as drag/drop, tree-views and list-views (like in windows Explorer [not Internet Explorer]). This not only gives the user of the application an interface s/he is familiar with but also saves on training needs. The UI is not limited in any way. </P>
<P>Advantages and Disadvantages of Web based and Internet based Applications </P>
<P>Each technology has its place. Where a simple data entry, data view and reporting capability is required, browser based applications are very well suited. On the other hand, if you require the full functionality and capability of a standard PC application as the front end, but need the "remote" connectivity as well, then Internet enabled applications are ideal. In most corporate scenarios, you will find a combination of browser based and Internet enabled applications. For the simple user or "on off" user (surfer) you'll find a web interface and for the power/corporate user you'll find Internet enabled applications. </P>
<P>When the user/surfer is unknown, that is the browser type, platform etc. in not known or controllable, a browser-based application has its advantages. On the other hand, if cross-platform is not an issue and the environment can be controlled to a high degree, then Internet enabled applications are the right choice, due to their interfacing/integrating capability and UI capability. </P></FONT>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>ISAPI Versus CGI/ASP</title><pubDate>Sun, 06 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/6/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/6/</guid><description><![CDATA[<H2>CGI - Common Gateway Interface</H2>CGI comes in the form of scripts or executables. In this article, the comparison between ISAPI and CGI assumes we're talking about CGI executables and not scripts. Considering the fact that executables are faster than scripts due to the interpreted nature of scripts. Lets take a look at the CGI model. 
<P><IMG src="http://www.matlus.com/images/CGIModel.jpg"> <BR><B>Figure 1: Showing the Process of a client request in terms of a browser and web server</B> 
<P>As shown in <B>Figure 1</B>: <BR>
<OL>
<LI>The client sends a request to the web server via an HTTP GET or POST method. 
<LI>The connection persists while the web server spawns a new process to handle the request. 
<LI>The CGI application processes the request, builds the output and sends it back to the web server. 
<LI>The Web server adds the protocol (HTTP) headers and passes all of it back to the requesting client. </LI></OL>While this is going on, the web server can receive and process other requests simultaneously. But for every request, the web server has to spawn a new process to handle the request. The implication of this is that it takes a certain amount of time to spawn a new process and each process requires a certain amount of resources (memory). It's easy to see that in a busy web site, the server can very easily get bogged down spawning new processes and running low on resources in an attempt to service multiple simultaneous requests. 
<P>
<H2>ISAPI</H2>The Internet Server Application Programming Interface is an API that allows a developer to add extensions to the Internet Information Server (IIS), replacing or enhancing programming duties typically performed either by CGI scripts or an HTTP server. An ISAPI extension is an application extension (DLL) that executes on the server, in the process space of the server. The request performs some function on the server and returns a response to the client. ISAPI extensions, then, replace the functionality typically associated with CGI scripts/executables. 
<P>Looking at <B>Figure 1</B> again, let see what would happen if the CGI executable were to be replaced by an ISAPI extension application. 
<P>An ISAPI application, does not spawn a new process after it has been called the first time by a request. Rather, it runs in the server's process space, thus reducing both memory overhead and startup time. Only a single copy of this server extension is loaded and is then shared if additional client requests for the same application come in. Furthermore, once an ISAPI application is loaded into the process space, it stays loaded until IIS is stopped and restarted, or until some unspecified period when IIS decides to unload it. This means new requests for the ISAPI will get much quicker responses and resource utilization is kept low due to a single instance model, rather than a multiple instance model in the case of a CGI. 
<P>All in all, this speed improvement is a strong argument for using ISAPI to do anything that requires back-end server processing over a CGI. If one were to look at CGI scripts or any other scripting mechanism, its easy to see that these types of applications will perform far slower than even CGI executables as they are interpreted rather than compiled. One should also note, that the interpreter needs to be loaded in memory to do its job as well. So resource utilization is much higher in scripting mechanisms such as, Perl, ASP etc. and performance is poor due to the interpreted nature. 
<H2>As per Microsoft</H2>
<BLOCKQUOTE><B>Designing High-Performance ISAPI Applications</B> 
<P>ISAPI is the highest-performance interface for Web applications. If you create an ISAPI extension or filter, it will outperform ASP scripts or even components performing similar tasks. 
<P>However, the inherent speed of the ISAPI interface does not mean that you can ignore performance and scalability considerations. Indeed, ISAPI cannot utilize much of the application support services provided by ASP and COM. If you would like your ISAPI application to maintain session state, for instance, much of that session-state functionality would have to be implemented by you. </P></BLOCKQUOTE><B>My Note</B> : Quite easily achieved using Delphi. 
<P>
<BLOCKQUOTE>Quote continues... 
<H2>Here are some suggestions for improving the scalability and performance of your ISAPI extensions:</H2>
<UL>
<LI>Avoid ISAPI filters, unless adding an ISAPI filter is absolutely necessary to your application architecture. You should especially avoid filters that perform processing on raw incoming or outgoing data. If you determine that a filter is absolutely necessary, be sure to carefully optimize the main code paths through the filter event notification code. 
<LI>Create your own worker thread pool, so that the main I/O threads can be freed to accomplish other tasks. This option is available only for ISAPI extensions, and not for ISAPI filters. For more information about how IIS processes requests, see IIS Request Processing. A sample that demonstrates a worker thread pool, implemented in an ISAPI extension, is available in ISAPI Examples. 
<LI>Consider using asynchronous operations and I/O completion ports, when feasible. IIS supports asynchronous reading and writing by using the I/O completion ports, available in Windows NT 4.0, and Windows 2000 or later. Depending on the type of I/O operations being performed, asynchronous operations can make better use of the CPU time available, and generally work particularly well when implemented using a worker thread pool. 
<LI>ISAPI extensions should use the Win32 TransmitFile function, exposed by the HSE_REQ_TRANSMIT_FILE ServerSupportFunction. 
<LI>Use Connection: Keep-Alive headers. Keeping persistent HTTP connections will provide better performance than using non-persistent connections, in most cases. 
<LI>Minimize need for thread synchronization by maintaining state information with the request context. If thread synchronization is required, make sure that critical sections are kept short. 
<LI>If your ISAPI application uses the heap intensively, consider other heap alternatives. Intensive use of the Windows? heap can cause resource contention. Several memory allocation alternatives are worth exploring, including: 
<UL>
<LI>Heap Partitioning, accomplished by creating multiple custom heaps, in addition to the default process heap. Each custom heap would then be controlled by a separate, non-global lock, and lock contention would be reduced. 
<LI>Cached Allocation, which involves using custom allocation operations that operate at a middle layer between the object users and the heap. Calls to the Win32 heap are made infrequently, and only for large memory blocks. These blocks are then subdivided and managed by the custom allocator. 
<LI>Stack Allocation, using the C run-time function _alloca to allocate memory for your objects on the stack instead of the heap. This method is feasible only for relatively small objects, because the space available on the stack is limited. In addition, your newly allocated object will be available only within the current functions, or functions called by that function. Once the current function returns, the storage allocated on the stack will be lost. </LI></UL>
<LI>Object Encapsulation, accomplished by simply incorporating a buffer as a member data structure of a class. This buffer is then used for tasks that would otherwise require accesses to the Win32 heap. 
<LI>Avoid using global locks within your ISAPI, if possible. Global locks can often adversely affect scalability. </LI></UL></BLOCKQUOTE><B>My Note</B>: A lot of these issues are dealt with in a Delphi ISAPI extension with the help of the Web Broker technology, thus freeing the Delphi programmer from such tasks. 
<P><B>An intersting page on the Microsoft site compares ASP and ISAPI performance, scalability etc. Check it out <a rel="nofollow" href="http://msdn.microsoft.com/library/techart/docu2kbench.htm" target="_new">here</A></B> 
<P>
<H2>ISAPI and the Web Application Architecture</H2>The set of interfaces that make up ISAPI were designed to provide application developers with a powerful way to extend the functionality of IIS. ISAPI extensions and filters have the following advantages over some of the other Web application technologies available: 
<UL>
<LI>Highest performance: A properly planned, developed, and used ISAPI-particularly ISAPI extensions-can outperform any other Web application technology available currently for IIS. 
<LI>Low-level control: From an ISAPI extension or filter, you have access to the whole array of Win32 API functions. For instance, you can create a customized worker-thread pool for your ISAPI extension to speed processing, using the Win32 thread functions to access the native thread functionality of Windows 2000. 
<LI>Often, ISAPI extensions and filters are best positioned to solve critical bottlenecks in your Web application-especially if you expect scalability to be an important issue for your application, due to high traffic volumes. For instance, if you would like to create your own Web search application on IIS, creating the actual search engine with ISAPI might be the best option if fast performance and scalability are an important goal. </LI></UL>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>What are Cookies?</title><pubDate>Sat, 05 Jan 2008 14:40:55 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/7/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/7/</guid><description><![CDATA[<CENTER>
<H2>What are Cookies?</H2></CENTER>Cookies are a general mechanism which server side applications, such as CGI/ISAPI can use store information on the client side of the connection and later retrieve this same information. The addition of a simple, persistent, client side state significantly extends the capabilities of browser-based client/server applications. 
<H2>Overview</H2>A server, when returning an HTTP object (request) to a client, may also send a piece of state information, which the client will store. Included in that state object is a description of the range of URLs for which that state is valid. Any future HTTP requests made by the client that fall in that range will include a transmittal of the current value of the state object from the client back to the server. The state object is called a cookie, for no compelling reason. 
<P>This simple mechanism provides a powerful new tool, which enables a host of new types of applications to be written for browser-based environments. Shopping cart applications can now store information about the currently selected items. The server side of the connection controls the storage of information on the client. The information can be stored for a length of time or only during that current session. The current session terminates when the browser (application) on the client side of the connection is closed. The server side of the connection has access only to information that it stored. This forms a kind of protection mechanism in that, a server can not get information that another server had previously stored. 
<H2>Specification</H2>A cookie is introduced to the client by including a Set-Cookie header as part of an HTTP response. Typically this will be generated by a CGI, ISAPI, and ASP application. <B>Syntax of the Set-Cookie HTTP Response Header</B> 
<P>This is the format a web application would use to add cookie information to the HTTP headers. <BR><KBD>Set-Cookie: NAME=VALUE; expires=DATE; path=PATH; domain=DOMAIN_NAME; secure </KBD><PRE><B>NAME=VALUE</B>
</PRE>This string is a sequence of characters excluding semi-colon, comma and white space. If there is a need to place such data in the name or value, some encoding method such as URL style %XX encoding is recommended, though no encoding is defined or required. This is the only required attribute on the Set-Cookie header. <PRE><B>expires=DATE</B>
</PRE>The expires attribute specifies a date string that defines the valid life of that cookie. Once the expiration date has been reached, the cookie will no longer be stored or given out. The date string is formatted as: <BR><KBD>Wdy, DD-Mon-YYYY HH:MM:SS GMT </KBD>This is based on RFC 822, RFC 850, RFC 1036, and RFC 1123, with the variations that the only legal time zone is GMT and the separators between the elements of the date must be dashes.<KBD>expires</KBD> is an optional attribute. If not specified, the cookie will expire when the user's session ends. 
<P><B>Note:</B> There is a bug in Netscape Navigator version 1.1 and earlier. Only cookies whose path attribute is set explicitly to "/" will be properly saved between sessions if they have an expires attribute. <PRE><B>domain=DOMAIN_NAME</B>
</PRE>When searching the cookie list for valid cookies, a comparison of the domain attributes of the cookie is made with the Internet domain name of the host from which the URL will be fetched. If there is a tail match, then the cookie will go through path matching to see if it should be sent. "Tail matching" means that domain attribute is matched against the tail of the fully qualified domain name of the host. A domain attribute of "matlus.com" would match host names "delphi.matlus.com" as well as "delphi.isapi.matlus.com". 
<P>Only hosts within the specified domain can set a cookie for a domain and domains must have at least two (2) or three (3) periods in them to prevent domains of the form: ".com", ".edu", and "va.us". Any domain that fails within one of the seven special top-level domains listed below only require two periods. Any other domain requires at least three. The seven special top level domains are: "COM", "EDU", "NET", "ORG", "GOV", "MIL", and "INT". The default value of domain is the host name of the server, which generated the cookie response. <PRE><DIV class=note>
<IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0>
Use <B>127.0.0.1</B> instead of <CITE><B>localhost</B></CITE> in your URLs when building and testing applications locally.<P>
Using <CITE><B>localhost</B></CITE> will <B>not</B> persist cookies on the target (local) machine.<P>This issue has been one of the key factors related to issues programmers have when using cookies in the web applications/web sites.
</P></DIV>
<B>path=PATH</B>
</PRE>The path attribute is used to specify the subset of URLs in a domain for which the cookie is valid. If a cookie has already passed domain matching, then the pathname component of the URL is compared with the path attribute, and if there is a match, the cookie is considered valid and is sent along with the URL request. The path "/foo" would match "/foobar" and "/foo/bar.html". The path "/" is the most general path. If the path is not specified, it as assumed to be the same path as the document being described by the header which contains the cookie. <PRE><B>secure</B>
</PRE>If a cookie is marked secure, it will only be transmitted if the communications channel with the host is a secure one. Currently this means that secure cookies will only be sent to HTTPS (HTTP over SSL) servers. If <B>secure</B> is not specified, a cookie is considered safe to be sent in the clear over unsecured channels. 
<P><B>Syntax of the Cookie HTTP Request Header</B> <BR>When requesting a URL from an HTTP server, the browser will match the URL against all cookies and if any of them match, a line containing the name/value pairs of all matching cookies will be included in the HTTP request (automatically). Here is the format of that line: <BR><KBD>Cookie: NAME1=OPAQUE_STRING1; NAME2=OPAQUE_STRING2 ... </KBD>
<P><B>Additional Notes</B> <BR>
<LI>Multiple Set-Cookie headers can be issued in a single server response. 
<LI>Instances of the same path and name will overwrite each other, with the latest instance taking precedence. Instances of the same path but different names will add additional mappings. 
<LI>Setting the path to a higher-level value does not override other more specific path mappings. If there are multiple matches for a given cookie name, but with separate paths, all the matching cookies will be sent. 
<LI>The expires header lets the client know when it is safe to purge the mapping but the client is not required to do so. A client may also delete a cookie before its expiration date arrives if the number of cookies exceeds its internal limits. 
<LI>When sending cookies to a server, all cookies with a more specific path mapping should be sent before cookies with less specific path mappings. For example, a cookie "name1=foo" with a path mapping of "/" should be sent after a cookie "name1=foo2" with a path mapping of "/bar" if they are both to be sent. 
<LI>There are limitations on the number of cookies that a client can store at any one time. This is a specification of the minimum number of cookies that a client should be prepared to receive and store. 
<OL>
<LI>300 total cookies 
<LI>4 kilobytes per cookie, where the name and the OPAQUE_STRING combine to form the 4 kbyte limit. 
<LI>20 cookies per server or domain. (note that completely specified hosts and domains are treated as separate entities and have a 20 cookie limitation for each, not combined) </LI></OL>
<LI>Servers should not expect clients to be able to exceed these limits. When the 300 cookie limit or the 20 cookie per server limit is exceeded, clients (browsers) should delete the least recently used cookie. When a cookie larger than 4 kb is encountered, the cookie should be trimmed to fit, but the name should remain intact as long as it is less than 4 kilobytes. 
<LI>If a web application (CGI/ISAPI) script wishes to delete a cookie, it can do so by returning a cookie with the same name, and an expires time which is in the past. The path and name must match exactly in order for the expiring cookie to replace the valid cookie. This requirement makes it difficult for anyone but the originator of a cookie to delete a cookie. 
<LI>When caching HTTP, as a proxy server might do, the Set-cookie response header should never be cached. 
<LI>If a proxy server receives a response which contains a Set-cookie header, it should propagate the Set-cookie header to the client, regardless of whether the response was 304 (Not Modified) or 200 (OK). 
<LI>Similarly, if a client request contains a Cookie: header, it should be forwarded through a proxy, even if the conditional If-modified-since request is being made. 
<H2>EXAMPLES</H2>Here are some sample exchanges, which are designed to illustrate the use of cookies.<BR><B>First Example transaction sequence:</B> <BR>Client requests a document, and receives in the response: <BR><KBD>Set-Cookie: CUSTOMER=WILE_E_COYOTE; path=/; expires=Wednesday, 09-Nov-99 23:12:40 GMT</KBD> <BR>When client requests a URL in path "/" on this server, it sends: <BR><KBD>Cookie: CUSTOMER=WILE_E_COYOTE</KBD> <BR>Client requests a document, and receives in the response: <BR><KBD>Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/</KBD> <BR>When client requests a URL in path "/" on this server, it sends: <BR><KBD>Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001</KBD> <BR>Client receives: <BR><KBD>Set-Cookie: SHIPPING=FEDEX; path=/foo</KBD> <BR>When client requests a URL in path "/" on this server, it sends: <BR><KBD>Cookie: CUSTOMER=WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001</KBD> <BR>When client requests a URL in path "/foo" on this server, it sends: <BR><KBD>Cookie: CUSTOMER=SHIPPING=FEDEX;WILE_E_COYOTE; PART_NUMBER=ROCKET_LAUNCHER_0001</KBD> <BR><B><I>(Notice the order in which cookies are sent.)</I></B> 
<P><B>Second Example transaction sequence:</B> <BR><I>Assume all mappings from above have been cleared.</I> <BR>Client receives: <BR><KBD>Set-Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001; path=/</KBD> <BR>When client requests a URL in path "/" on this server, it sends: <BR><KBD>Cookie: PART_NUMBER=ROCKET_LAUNCHER_0001</KBD> <BR>Client receives: <BR><KBD>Set-Cookie: PART_NUMBER=RIDING_ROCKET_0023; path=/ammo</KBD> <BR>When client requests a URL in path "/ammo" on this server, it sends: <BR><KBD>Cookie: PART_NUMBER=RIDING_ROCKET_0023; PART_NUMBER=ROCKET_LAUNCHER_0001</KBD> <BR><B>NOTE:</B> There are two name/value pairs named "PART_NUMBER" due to the inheritance of the "/" mapping in addition to the "/ammo" mapping. 
<P><B>So What Is A Cookie?</B> A cookie is a small piece of information that is sent by a web server to be stored on a web browser, so that it can later be read back from that browser the next time this unique visitor returns to that web server. This becomes useful for having the browser remember specific information about this visitor like location of their last visit, time spent, or user preferences (like style sheets). The cookie is a text file that is saved in the browser's directory and is stored in RAM while the browser is running. Also, the cookie may be stored on the computer's hard drive once you log off from the web site or web server. 
<P><B>What Are Cookies Used For?</B> One use of cookies is for storing passwords and user ID's for specific web sites. The actual password may not be stored in the cookie per se, but a unique identifier for the user may be stored that can later be used to retrieve information from a database about the user. Also, they are used to store preferences of start pages. On sites with personalized viewing, your web browser will be requested to utilize a small amount of space on your computer's hard drive to store these preferences. That way, each time you log on to that web site, your browser will check to see if you have any pre-defined preferences (a cookie) for that unique server. If you do, the browser will send the cookie to the server along with your request for a web page. Microsoft and Netscape use cookies to create personal start pages on their web sites. Common uses for which companies utilize cookies, include: 
<UL>
<LI>on-line ordering systems 
<LI>site personalization 
<LI>web site tracking. </LI></UL>Etc. 
<H2>Delphi and Cookies</H2>All this said, Delphi as is expected makes things a lot simpler. The <KBD><B>TWebResponse</B></KBD> object has a method called <KBD><B>SetCookieFields</B></KBD>. From the on-line help file: <BR><B>TWebResponse.SetCookieFields</B> <BR>Adds a cookie header to the response message. <PRE><B>procedure</B> SetCookieField(Values: TStrings; <B>const</B> ADomain, APath: <B>string</B>;
   AExpires: TDateTime; ASecure: Boolean);
</PRE><KBD>Description <BR>Call SetCookieField to add a cookie header to the Cookies property. Each cookie header contains a set of name/value pairs that can be passed on by the client application. Use the Values parameter to specify the name/value pairs as strings of the form Name=Value. Use the ADomain and APath parameters to indicate which URLs the cookie should be sent to. Use the AExpires parameter to indicate when the cookie is no longer valid. Use the ASecure property to indicate whether the cookie should only be passed on by the client if a secure connection is used. </KBD>
<P>The method name <KBD>SetCookieFields</KBD>, may be a bit confusing initially. It pertains to the fact that this method sets the Cookie fields of the HTTP header. While building CGI/ISAPI using Delphi, we don't really work directly with the HTTP header even though we do have full access to it if we need it. 
<P>Another thing to understand is that each <KBD>Name=Value</KBD> pair is a cookie in and of itself. The method SetCookieFields, can set a whole list of cookies in one method call. But due to the nature of this, all cookies set will have the same path, domain, expiration date etc. This may not be what you want to do all the time. There will be times when you want to "expire" just one cookie or set just one cookie. The Method SetCookieFields can do that, but you need to explicitly create a <KBD>TStrings</KBD> derived object and free it. 
<P>To overcome this confusion/limitation, I find myself frequently using a function called <KBD>SetCookie</KBD> that allows me to set just one cookie and frees me from having to create a <KBD>TStrings</KBD> derived object (normally a <KBD>TStringList</KBD>) and free it. Besides, it keeps the code clean and readable. Similarly, I create a function called GetCookie that returns the <KBD>Value</KBD> (part of the <KBD>Name=Value</KBD> pair) of the given <KBD>Name</KBD>. 
<P>For further reading you might want to look at RFC 2109 that specifies <a rel="nofollow" href="http://www.w3.org/Protocols/rfc2109/rfc2109.txt">Session State Management</A>. </P></LI>]]></description><category>Programming</category><category>Work</category><category>Delphi</category><category>Internet</category><category>ISAPI</category></item><item><title>Authentication and Security in IIS</title><pubDate>Fri, 04 Jan 2008 14:44:36 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/8/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/8/</guid><description><![CDATA[This article describes the Authentication &amp; Security Features of Microsoft Internet Information Server. 
<H2>Integration with Windows NT</H2>The World Wide Web (WWW), Gopher, and FTP services included with the Microsoft Internet Information Server are fully integrated with Windows NT Server user accounts and file access permissions. 
<P>Every access to a resource (for example, a file, an HTML page, an Internet Server API (ISAPI) application, etc.) is done by the services on behalf of a Windows NT user. The service impersonates the user by supplying a username/password pair in the attempt to read/execute the resource for the client. IIS starts the process using the CreateProcessAsUser System API. 
<P>The Windows NT File System (NTFS) allows Access Control Lists (ACLs) to be assigned to files and directories. ACLs grant and/or deny access to the associated file or directory by specific Windows NT user accounts, or groups of users. When an Internet service attempts to read or execute a file on behalf of a client request, the user account offered by the service must have permission, as determined by the ACL associated with the file, to read or execute the file, as appropriate. If the user account does not have permission to access the file, the request fails, and a response is returned, informing the client that access has been denied. File and directory ACLs are configured using the Windows NT File Manager. 
<H2>Anonymous Connections</H2>An anonymous connection is processed when a client request does not contain a username and password. This occurs in the following cases: 
<OL>
<LI>An FTP client logs on with the username Anonymous. 
<LI>All Gopher requests. 
<LI>A WWW (HTTP) request's headers do not contain a username and password. </LI></OL>Each Internet service maintains a Windows NT username and password to be used for the processing of anonymous requests. When an anonymous request is received, the service impersonates the user configured as the <B>anonymous-logon user</B>. The request will succeed if the anonymous-logon user has permission to access the requested resource, as determined by the resource's ACL. For WWW only, if the user does not have permission to access the resource, the response returned to the client contains a list of supported authentication schemes for gaining access to the resource. 
<P>The anonymous-logon user account can be viewed and modified on the Service property page of the Internet Service Manager. Multiple Internet Information Server services running on the same computer can use the same, or different anonymous-logon user accounts. Including the 'anonymous logon' user account in file or directory ACLs allows for precise control of the resources available to 'anonymous' clients. 
<P>The anonymous-logon user account specified must be a valid Windows NT user account on the server computer, and the password specified must match the password for this user in the computer's user database. User accounts and passwords are configured using the Windows NT User Manager. 
<P>When the Internet Information Server product is installed, Setup creates a user account on the server computer to be used for anonymous connections. The username of this account has the form <B>IUSR_&lt;computer_name&gt;</B>. For example, if the server computer name is MATLUS, the username created will be IUSR_MATLUS. The same anonymous-logon user account is set up for all Internet Information Server services installed on the computer. The account is made a member of the computer's Guest group. This will, in most cases, give anonymous client requests access to public content published on the server. Run the Control Panel/Network applet to see the computer name configured for the Windows NT Server computer. 
<P>A randomly generated password is created for the IUSR_<COMPUTER_NAME> account. For maximum convenience and security, we suggest that you change the password associated with this account to a password that you will remember, but is not easily guessed. To do this, you must specify the new password for the account in User Manager, and on the Service page of the Internet Service Manager for each Internet Information Server service installed. 
<P>When the Internet Information Server is installed on a primary or secondary domain controller, the anonymous-logon user account is created in the user account database of the domain. When Internet Information Server is installed on a domain member-server, or a stand-alone server, the account is created on the local machine. 
<P>If Internet Information Server is installed on multiple domain controllers of the same domain, a separate user account is created in the domain user database for each Internet server computer. This does not cause any conflicts since each username is unique, containing the name of the associated computer. 
<P>However, you may find it more convenient to create a single anonymous-logon user account in the domain to use for all Internet Information Server domain controllers in the domain. This can simplify administration of ACLs. 
<H2>Client Requests Containing Credentials</H2>A request containing credentials is one of the following: 
<OL>
<LI>An FTP client logs on with a valid Windows NT username and password. This requires that the FTP service checkbox labeled <KBD>Allow Only Anonymous Connections</KBD> be unchecked. <B>WARNING:</B> FTP sends passwords across the network in clear text. 
<LI>A WWW (HTTP) request's headers contain a username and password. This is HTTP <B>Basic Authentication</B>.<B>WARNING:</B> HTTP Basic Authentication sends passwords across the network in clear text. 
<LI>A WWW browser supports NTLM (Windows NT native) authentication, and an anonymous client request is denied access to a resource. In this case, the browser automatically sends the Windows client's username and password to the Internet Information Server Web server using the encrypted NTLM protocol. Currently only IE browser 2.0 and above support NTLM authentication. </LI></OL>When an Internet Information Server service receives a client request that contains credentials (a username and password), the anonymous-logon user account is not used in processing the request. Instead, the username and password received by the client are used by the service. If the service is not granted permission to access the requested resource while impersonating the specified user, the request fails, and an error notification is returned to the client. 
<P>For WWW (HTTP) only, when an anonymous request fails because the anonymous-logon user account does not have permission to access the desired resource, the response to the client indicates which authentication schemes the service supports. This is determined by the configuration of the WWW service authentication features. If the response indicates to the client that the service is configured to support HTTP basic authentication, most Web browsers will pop up a username/password dialog box, and reissue the anonymous request as a request with credentials, including the username and password entered by the user. 
<P>If a Web browser supports NTLM authentication, and the Web service is configured to support NTLM authentication, an anonymous WWW request failing due to permissions, will result in automatic use of the NTLM protocol to send a username and encrypted password from the client to the service. The client request will then be reprocessed, using the client's user information. The user account obtained from the client is that with which the user is logged into the client computer. As this account, including its Windows NT domain, must be a valid account on the Web server machine, NTLM authentication is most useful in an intranet environment, where the client and server machines are in the same, or trusted domains. Internet Explorer for Windows 95/98 is the only browser that supports NTLM authentication. 
<H2>Internet Service Manager Authentication Options</H2>In addition to the anonymous-logon username and password fields, the Internet Service Manager Service property page contains the following authentication options: 
<P><B>For WWW:</B> 
<OL>
<LI>Allow Anonymous. When this check box is checked, anonymous connections are processed, and the anonymous-logon username/password are used for these connections. When this checkbox is unchecked, all anonymous connections are rejected. In this case, basic or NTLM authentication can be used to access content. 
<LI>Basic Authentication When this check box is checked, the Web service will process requests using basic authentication. <B>WARNING:</B> Basic authentication sends Windows NT usernames and passwords across the network without encryption. This checkbox is unchecked by default for security reasons. 
<LI>Windows NT Challenge/Response. When this check box is checked, the service will honor requests by clients to send user account information using the Windows NT Challenge/Response (NTLM) protocol. This protocol uses encryption for secure transmission of passwords. The NTLM authentication process is initiated automatically as a result of an 'access denied' error on an anonymous client request. Currently, NTLM authentication only works with Internet Explorer 2.0 and above. </LI></OL>
<H2>How NT Challenge/Response works</H2>IIS supports Microsoft Windows NT Challenge/Response authentication, which identifies users without requiring the transmission of actual passwords or account information across a network. Instead, the Web server authenticates users by carrying out a procedure that challenges the user's Web browser to carry out a specific mathematical computation involving the password and to respond by returning the results of the computation to their Web server. 
<P>Next, your Web server duplicates this computation using the user's account password information, and compares this result to the user's result. If both results match, your Web server recognizes that the user has the correct password and grants access. 
<P>Your server will not switch to another authentication method if the user is initially denied access. Instead, the user's Web browser will prompt the user for a user name and password, which the browser will process and send to your Web server as part of the Windows NT Challenge/Response authentication protocol. If this second authentication attempt fails, the user will be denied access to the Web server. 
<P>You will find Windows NT Challenge/Response authentication useful in an Intranet environment only, where both user and Web server computers are in the same, secure domain. Additionally, you can only use Windows NT Challenge/Response to authenticate users that logon with Web browsers capable of supporting this method. Currently, Microsoft Internet Explorer version 2.0 or later is the only Web browser that supports Windows NT Challenge\Response. 
<P><B>For FTP:</B> 
<OL>Allow Anonymous Connections. When this check box is checked, FTP logons in which the user enters a username of 'anonymous' will be processed. These anonymous connections will be processed on behalf of the Windows NT user account specified on the Service property page. When this check box is unchecked, users will be required to enter valid Windows NT usernames and passwords to log on to the FTP service. 
<LI>Allow only anonymous connections. When this checkbox is checked, user logons with a username other than anonymous will be rejected. <B>WARNING:</B> FTP User names and passwords are sent across the network in clear text. When this check box is unchecked, Windows NT passwords will be sent to the server without encryption. This check box is checked by default for security reasons. </LI></OL>
<H2>Other Authentication Issues</H2><B>SSL:</B> 
<P>SSL is a WWW feature that supports data encryption and server authentication. All data sent to or from the client using SSL is encrypted. If HTTP basic authentication is used in conjunction with SSL, the username and password are transmitted after being encrypted by the client's SSL support 
<P><B>'INTERACTIVE' and 'NETWORK' Users</B> 
<P>If you use the predefined Windows NT user accounts 'INTERACTIVE' and 'NETWORK' for access control, your use of these accounts may affect client access to some resources. In order for a file to be accessed by anonymous client requests or client requests using basic authentication, the requested file must be accessible by the INTERACTIVE user. In order for a file to be accessible by a client request using NTLM authentication, the file must be accessible by the NETWORK user. 
<P><B>Log On Locally User Right</B> 
<P>In User Manager, when configuring a Windows NT user account to be used either as the Internet Information Server anonymous-logon account, or as a user account specified by client requests using HTTP basic authentication, be sure that the user account is granted the 'Log on locally' user right. This is specified in User Manager's Policies menu. 
<H2>Customized Authentication</H2>If you need a WWW request authentication scheme <B>not</B> supported by the service directly, you need to build an ISAPI filter to do the job. ISAPI Filter Authentication methods can perform a superior authentication scheme that is customized to suit the specific needs of an Enterprise. This article does not go into the details of developing an ISAPI filter DLL, but will leave this topic for later. 
<H2>Digest Authentication</H2>Digest Authentication is new to Windows 2000 and Internet Information Services 5.0. This form of authentication encrypts the user's password information, and provides a mechanism for aiding in the prevention of some common server attacks (such as a replay attack). 
<P>In order to use Digest Authentication in Windows 2000, the server must have access to an Active Directory Server that is set up for Digest Authentication. 
<P>If the server running IIS is not a Active Directory Server, or does not have access to the Active Directory, this authentication will not work. For more information about making the server a Directory Server, see the Windows 2000 documentation. 
<P>If the server is already a Directory Server, perform the following steps: 
<OL>
<LI>Open the Active Directory Users and Computers. 
<LI>Open the domain that you want to administer. 
<LI>Double-click the user name that you want to use with Digest Authentication. 
<LI>In Account Options, select Store password using reversible encryption. 
<LI>Click OK. 
<LI>Reset the user's password now in order for the encryption to take place. To reset the user's password, right-click the user name in the directory and click Reset Password. 
<LI>Click OK. </LI></OL>In order for Internet Information Services 5.0 to use Digest Authentication, you must select it in Internet Service Manager. To do this, perform the following steps: 
<OL>
<LI>Open Internet Services Manager. 
<LI>Expand the Web server that you want to make the change in, and then open the Web site's properties. 
<LI>Click the Directory Security tab. 
<LI>Under Anonymous Access and Authentication Control, click Edit. 
<LI>Select Digest Authentication from the list, and then click OK, </LI></OL>
<H2>Basic Authentication Scheme</H2>The "Basic" authentication scheme is based on the model that the user agent must authenticate itself with a user-ID and a password for each realm. The realm value should be considered an opaque string which can only be compared for equality with other realms on that server. The server will authorize the request only if it can validate the user-ID and password for the protection space of the Request-URI. There are no optional authentication parameters. 
<P>Upon receipt of an unauthorized request for a URI within the protection space, the server should respond with a challenge like the following: <PRE>  WWW-Authenticate: Basic realm="DelphiTutorials"
</PRE>where "DelphiTutorials" is the string assigned by the server to identify the protection space of the Request-URI. 
<P>To receive authorization, the client sends the user-ID and password, separated by a single colon (":") character, within a base64 [5] encoded string in the credentials. <PRE>  basic-credentials = "Basic" SP basic-cookie
  
  basic-cookie      = <BASE64 [5] encoding of userid-password, except not limited to 76 char line>
  
  userid-password   = [ token ] ":" *TEXT
</PRE>If the user agent wishes to send the user-ID "skumar" and password "Delphi", it would use the following header field: <PRE>  Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==
</PRE>The basic authentication scheme is a non-secure method of filtering unauthorized access to resources on an HTTP server. It is based on the assumption that the connection between the client and the server can be regarded as a trusted carrier (such as SSL). As this is not generally true on an open network, the basic authentication scheme should be used accordingly. In spite of this, clients should implement the scheme in order to communicate with servers that use it. 
<H2>Security Ramifications for IIS Applications</H2>
<P>
<H2>Anonymous Authentication</H2>Setting Anonymous Authentication in IIS Manager means that IIS will not use any HTTP authentication mechanism to control access to resources on the machine. By default, when IIS is installed, it creates a user account called IUSR_&lt;servername&gt;, where &lt;servername&gt; is the name of the server on which IIS is running. This user account is added to the "Guests" group on the machine, which implies that its access to resources is limited. When an HTTP request is received by IIS with Anonymous authentication being used, IIS will impersonate the IUSR_&lt;servername&gt; account in order to execute any code or access any files that are involved in the request. This allows a level of security by limiting the accessibility to such things as system files by an unauthenticated user. IIS is able to impersonate the IUSR_&lt;servername&gt; account because the username and password credentials for this account are known by IIS. 
<P>You can change the account that is used for anonymous authentication in Internet Service Manager. You can also change the security privileges for the IUSR_&lt;servername&gt; account in Windows NT User Manager. Be aware that any changes will result in changes to every anonymous HTTP request that is serviced by IIS. Also note that if the anonymous account configured in Internet Manager does not have the "Log On Locally" right (not a right given to "Guest" accounts by default on domain controllers), then IIS will not be able to service any anonymous requests. The IIS installation specifically gives you the "Log On Locally" right to the IUSR_&lt;servername&gt; account. 
<P>Most resources, such as the IUSR_&lt;servername&gt; account, that allow Guests to access them, do so by allowing access to the special group "Everyone." You can set permissions on files and other resources specifically to allow or disallow the IUSR_&lt;servername&gt; account to access them, but most people end up managing access by controlling access to the groups "Everyone" or "Guests." 
<H2>Basic Authentication</H2>Basic authentication is a scheme that causes the client to be prompted for a Username and Password that are then Base64-encoded and passed to IIS. IIS receives the username and password credentials and verifies them against the Windows NT-user database on the machine or the applicable domain controllers in any trusted Windows NT domains. If the credentials are valid, IIS will impersonate the specified user when allowing access to resources by IIS or any applications that the request is launching. Thus, the application that is being executed, whether it is an ISAPI extension a DLL, a CGI application, or a scripting mechanism, will be executed with the permissions of the corresponding user account passed by the Basic authentication. 
<P>Because Basic authentication provides the username and password credentials to IIS, access to items that require credential knowledge can successfully be performed when using Basic authentication. For example, if an ISAPI application mapped a drive letter across a network, then it would require knowledge of the current user's credentials. Because IIS is given the username and password credentials as part of Basic authentication, this task will succeed if the account specified has access to the network resource. 
<H2>Windows NT Challenge/Response Authentication</H2>Windows NT Challenge/Response authentication (often called NTLM authentication) is the most secure form of authenticating a user because the username and password are not sent across the wire. Rather, the Windows Security Provider interface is used to provide an encrypted challenge/response handshake mechanism that is functionally unbreakable. The Windows security provider interface allows IIS to validate and impersonate the user. Unlike Basic authentication, NTLM authentication does not prompt users for their user name and password by default. The current Windows user account on the client machine is used for the NTLM authentication. Then, if this fails, it will prompt the user for the username and password to be used. If NTLM authentication succeeds, the requested application or resource is executed in the context of the specified user. 
<P>Because of the one way encryption is used, NTLM authentication validates the user for IIS without providing knowledge of the user's password to IIS. Therefore, a full set of username and password credentials is not available to IIS for doing such tasks as mapping a network drive. If an ISAPI application calls WNetAddConnection2 without specifying a username and password, it will fail under NTLM authentication. 
<H2>Multiple Authentication Schemes Selected</H2>You can select any combination of Anonymous, Basic, and NTLM authentication in Internet Manager. If Anonymous authentication is checked, the request will try to be handled without any actual authentication and IIS will execute the request in the context of the IUSR_&lt;servername&gt; account. If, for some reason, the IUSR_&lt;servername&gt; account does not have access to the resource, IIS will send back an access-denied error to the client indicating that the client needs to use one of the other authentication schemes. This scenario could occur if you limited access to the actual ISAPI DLL file to a specific user, such as User1. IIS would receive the initial anonymous request and attempt to launch the ISAPI DLL under the IUSR_&lt;servername&gt; user context, only to get an access-denied error from the NTFS file system. IIS would respond to the client with a message saying that access was denied and the client needs to submit the request using either the Basic or NTLM authentication schemes (depending on which one is enabled, possibly even both). The client can then resubmit the request with the Basic authentication credentials or with the initial NTLM challenge/response sequence. If either of these responses provides validation of the User1 account, then IIS will impersonate the User1 account and successfully launch the ISAPI DLL. 
<P>It is worth noting that if both NTLM and Basic authentication schemes are checked, IIS responds to requests indicating that both schemes are acceptable. It is up to the client to determine which authentication schemes it supports and to respond appropriately. For browsers, such as Internet Explorer, which support both Basic and NTLM Authentication, they will respond using the first supported authentication scheme indicated by IIS. On IIS 1.0, when both Basic and NTLM authentication schemes were checked, Basic authentication was listed first. On IIS 2.0, NTLM is now listed before Basic. The result is that for a server running IIS 1.0 using both, Internet Explorer will use Basic authentication. For an IIS 2.0 server using both, Internet Explorer will use NTLM authentication. Many IIS applications access resources provided by other software components. For instance, an ISAPI extension DLL may call an OLE automation server from a third-party software company, or a CGI application. These components may have persistent information stored in the registry that they require in order to execute properly. For standard desktop use of these components, the registry information is read from the profile of the user currently logged on the Windows NT machine. These applications often have problems when launched by IIS because the profile made available to an IIS application is that of the "default user." The default-user profile is filled with information generic to all users, but, unfortunately, is specific to no users. Therefore, a component may run as expected when User1 executes it interactively on his or her desktop because it is reading information from User1's profile in the registry. The same application may not run at all from IIS because it will not have access to User1's profile. This is true even if IIS is impersonating User1's account using Basic or NTLM authentication. 
<H2>Desktop Issues</H2>Windows NT uses the concept of having multiple desktops on the same machine. A desktop can be thought of as the screen that you view when you are logged on an NT machine. Your desktop receives all the mouse and keyboard messages that you create as the user in front of the machine, and it allows for applications to interact with one another to a certain extent. For instance, one application on a desktop can post messages to other applications on the desktop. NT supporting multiple desktops implies that there are other desktops running; you just can't see them and you have no way of sending keyboard or mouse messages to them. This may seem like a futile concept, but, in fact, many applications that run as Windows NT Services require the capabilities that a desktop provides yet don't want to interact with the interactive user's desktop. Therefore, each service gets its own desktop that won't be interfered with by the currently logged-on user. 
<P>The implications of this to IIS applications are that the IIS service has its own desktop. If your IIS application interacts with a desktop in any way (for instance, if it displays a message box), then it will display that message box on a desktop that cannot be seen on the computer's monitor. Similarly, an IIS application will not be able to send or post messages to an application on the interactive desktop. If your IIS application needs to interact with the interactive desktop, then you should use another form of inter-process communication such as named pipes. 
<H2>ISAPI Filter DLLs</H2>ISAPI Filter DLLs, not to be confused with ISAPI Extension DLLs, run in the original context of the IIS service. All services run by default under the Local System account of the machine on which they are installed. The Local System account has access to almost all resources on the local machine not specifically denied to it, and no resources on any other machines on the network. 
<H2>COM and OLE Permissions</H2>Launching an OLE or COM object on an NT 4.0 machine requires certain permissions. This is normally not an issue for most interactive users because the default permissions for launching and accessing OLE and COM objects on an NT machine allow access to anyone logged on the local machine interactively. An IIS application, whether it is running in the context of the IUSR_&lt;servername&gt; account or an impersonated user account from Basic or NTLM authentication, is *NOT* interactively logged on. Therefore, the default permissions for launching and accessing OLE and COM objects will not allow an ISAPI extension DLL, CGI application, or Internet script to launch these objects successfully by default. 
<P>The utility DCOMCNFG on Windows NT 4.0 allows you to set the default permissions for *ALL* COM and OLE objects on your machine. You can use this utility to provide OLE and COM access to the IUSR_&lt;servername&gt; account as well as all user accounts that might be impersonated by your IIS configuration. You can even grant permissions to the "Everyone" group. 
<P>However, providing global access to all OLE and COM objects may not be in your best interest, so DCOMCNFG will also allow you to specify permissions for specific applications so you could provide access to only the applications you will need to access from your IIS application. OLE and COM applications also have the ability to determine what permissions are associated with launching and accessing themselves. To do this from inside your OLE or COM server, see the CoInitializeSecurity function new to Windows NT 4.0, as well as CoCreateInstanceEx (in particular, the COSERVERINFO and COAUTHINFO structures) for manipulating OLE access from the client side. 
<P>Distributed COM (DCOM), also referred to as Remote Automation, requires all of the OLE/COM permissions discussed above. In addition, it needs to access resources across the network. If a request is received using Anonymous authentication, the IUSR_&lt;servername&gt; account username and password credentials will be used to connect to the remote DCOM server. Unless your IIS server machine is also a domain controller, the remote machine by default will not know who the IUSR_&lt;servername&gt; account is (it only exists on the local IIS server machine). Adding access and launch permissions to the group "Everyone" does not help in this case because DCOM will not map access by an unknown account to the guest account in the same way that the Lanman Server service does for file sharing. The DCOM server machine must explicitly know the account that is being used. 
<P>To deal with a scenario where you have IIS applications accessing resources (including DCOM resources) on remote machines, you need to have all the machines involved participate in a domain relationship. Then, in Internet Manager, you can change your anonymous account to an account in the local or trusted domain. Now, all machines in the domain structure will recognize the account and can explicitly add/delete access to their network resources for that account or any group that account is a member of. 
<P>Be aware that if Basic authentication is used for an IIS request, access to network resources (including DCOM servers) will be done in the context of the user whose credentials were passed with the request. If the user specified does not have permissions to launch or access the DCOM server, the request will fail. 
<P>If the IIS request is validated using NTLM authentication, the impersonation level does not imply knowledge of the username and password credentials. Therefore, access to network resources, regardless of the permissions on the resource, will be denied (with the exception of NULL Session resources). </P>]]></description><category>Programming</category><category>Delphi</category><category>ISAPI</category></item><item><title>Relative Paths, Virtual Folders Explained</title><pubDate>Thu, 03 Jan 2008 14:44:36 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/9/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/9/</guid><description><![CDATA[While building Web sites/application, you're bound to come across issues with regard to "paths". Sometimes these paths are related to URLs and sometime these "paths" are related to physical paths to images or html templates on your web server. In this article we'll see how to tackle some of these issues. 
<H3>Relative Paths</H3>These are the primarily URLs that seem to be in short form or a partial URL in HTML. For example, lets take the <CODE>&lt;img&gt;</CODE> tag. The <CODE>&lt;img&gt;</CODE> tag has an attribute called <CODE>src</CODE>. The value of this attribute needs to be the URL where the image can be found. Lets experiment a bit. We'll build a very simple html page: 
<P></P>
<DIV class=codeblockouter>The Simple HTML File for testing. 
<DIV class=codeblockinner><CODE><PRE>&lt;html&gt;
  &lt;head&gt;
    &lt;title&gt;Experimenting with Relative Paths&lt;/title&gt;
  &lt;/head&gt;
&lt;body&gt;
  &lt;img src="http://www.matlus.com/images/MatlusTabs_Base.png" border="0" /&gt;
&lt;/body&gt;
&lt;/html&gt;
</PRE></CODE></DIV></DIV>
<P></P>I assume you create this page using notepad and save it as RelativePaths.htm. Now open this file in your browser by double clicking on the file. You should see an image in there. This image is downloaded from my web site. That was pretty obvious since the <CODE>src</CODE> attribute contains the <B>full</B> URL to that image. When you're building web sites/applications you don't want to hard code the complete URL to your images in the <CODE>src</CODE> attribute. This is because you may re-use your code/templates for another site or application or the domain name changes etc. So ideally you want to use a URL of the form <CODE><PRE>&lt;img src="/images/MatlusTabs_Base.png" border="0" /&gt;
</PRE></CODE>
<P>The <CODE>src</CODE> attribute is in the form of a relative path. If you navigate to my web site, and take a look at some of the html there, you'll notice that the src attribute of the <CODE>&lt;img&gt;</CODE> tags do not contain the domain name as it did earlier. But you still see the images. Now modify the <CODE>&lt;img&gt;</CODE> tag in the html page you made earlier to be like that shown above. You'll notice that you don't see an image any more. </P>
<P>I'd like to explain this in terms of how a web browser works. When a browser is pointed to an html page, it retrieves this html page. First all it does is it gets the html (this is what you see when you do a "view source menu option"). It then parses this html. While parsing the html it comes across the <CODE>&lt;img&gt;</CODE> tag. It looks at the src attribute. What? No domain? Ok, then I'll just assume the domain is the same domain that the html came from (It resolves the relative path)! But there is no image in this path. 
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> <B>Difference between opening an HTML page by double clicking it and "browsing" to it.</B> 
<P></P>If you double clicked on the html file (the physical file), the browser looks for the image in this case in a sub folder of the folder in which the html file resides. If you have a web server running locally and called this html file using a url such as <CODE>http://localhost/test.htm</CODE> then when the browser makes a request on the web server for the image, it expects to find an image in a subfolder (or virtual folder). </DIV>
<P></P>This applies to other tags that may use relative paths as well, such as the <CODE>&lt;link&gt;</CODE> tag's <CODE>href</CODE> attribute, or an <CODE>&lt;a&gt;</CODE> tag's <CODE>href</CODE> attribute. For tags that have attributes such as the <CODE>href</CODE> attribute, the browser actually makes additional requests on the web server (one additional request for tag with such an attribute). In the first go, it only retrieves the <B>HTML</B>. This is important to know, since it effects the speed and scalability of the systems you build. 
<P></P>
<P>You will have noticed relative paths that include the ISAPI dll or CGI exe file name as well. In code, you use the Request.ScriptName property. This results in something like /scripts/myisapi.dll. In this case, you don't want to hard code the name of the application either. It's best using Request.ScriptName. But again, a relative path only makes sense if the ISAPI (in this case) is in the same domain as the web page that uses this relative path. </P>
<H3>Virtual folders and the TPageProducer</H3>The "images" part of the url for the image we've been using is a virtual folder. This folder can be one of two things: 
<OL>
<LI>A sub folder of your Web Server's root folder. (C:\inetpub\wwwroot\images in case of IIS) 
<LI>A virtual folder defined in your web server for the web site. This virtual folder has the name "images" but it could be virtually anywhere on the server's hard disk. A network share or an URL. </LI></OL>
<DIV class=note><IMG alt=exclamation.gif src="http://www.matlus.com/images/exclamation.gif" border=0> When creating a virtual folder in IIS, make sure the User name is in the form MACHINENAME\UserName where MACHINENAME is the name of the machine on the network on which the physical folder exists. Just UserName will not work. </DIV>
<P>If in your environment your development machine's directory structure does not match that of the target production machine, you should create virtual folders on your development machine (and also production machine if need be) that map to the target machine. Never hard code paths in the html that is returned to the browser. Following this rule will go a long way in smoothening out the deployment process while also allowing for changes later, in the production environment. </P>
<P>In Delphi we have this wonderful component called the TPageProducer. We won't go into the details of how to use it here. However, it has a property called HTMLFile. The value of this property is normally the path and name of an html template (a file that has special tags that the Page Producer understands). Now the PageProducer, needs a physical path (not URL) for the physical .htm file. The IUSR_<MACHINENAME> user needs to have read access to this folder and file. </P>
<P>Lets say you've defined a virtual folder called HTMLTemplates in your WebServer. This virtual folder points to a physical location on your hard drive. You can get the physical path of the virtual folder by using the Request object's TranslateURI method. </P>
<P>If you leave the parameter (to the TranslateURI method) empty, you'll get the physical path to the root folder of your web server (C:\Inetpub\wwwroot in the case of IIS). If you supply '/images' as the parameter you'll get the physical path of the "images" virtual folder. If no such folder exists (that is a virtual folder has not been defined), you'll simply get the word "\images" appended to the web server's root folder path (notice the way the forward slash changes to a back slash for physical paths). </P>
<P>Given this knowledge, you should be able to get your page producer to load an html template from any folder on your web server . Simple code like that shown below works really well and can be used in all your ISAPIs if you follow a trend. 
<DIV class=codeblockouter>One way of implementing Mapping of Virtual Paths to Physical Paths 
<DIV class=codeblockinner><PRE><CODE><FONT face="Courier New" size=3><FONT color=#000000>  </FONT><FONT color=#000080>TWebModule1 </FONT><FONT color=#ff0000>= </FONT><FONT color=#0000ff><B>class</B></FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>TWebModule</FONT><FONT color=#ff0000>)
    </FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>WebModuleBeforeDispatch</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>;
      </FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebRequest</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Response</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebResponse</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>Handled</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Boolean</FONT><FONT color=#ff0000>);
  </FONT><FONT color=#0000ff><B>private
    </B></FONT><FONT color=#000080>FHTMLTemplatePath</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string</B></FONT><FONT color=#ff0000>;
    </FONT><FONT color=#0000ff><B>property </B></FONT><FONT color=#000080>HTMLTemplatePath</FONT><FONT color=#ff0000>: </FONT><FONT color=#0000ff><B>string read </B></FONT><FONT color=#000080>FHTMLTemplatePath</FONT><FONT color=#ff0000>;
    </FONT><FONT color=#808080>{ Private declarations }
  </FONT><FONT color=#0000ff><B>public
    </B></FONT><FONT color=#808080>{ Public declarations }
  </FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>var
  </B></FONT><FONT color=#000080>WebModule1</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebModule1</FONT><FONT color=#ff0000>;

</FONT><FONT color=#0000ff><B>implementation

</B></FONT><FONT color=#808080>{$R *.DFM}

</FONT><FONT color=#0000ff><B>procedure </B></FONT><FONT color=#000080>TWebModule1</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>WebModuleBeforeDispatch</FONT><FONT color=#ff0000>(</FONT><FONT color=#000080>Sender</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TObject</FONT><FONT color=#ff0000>;
  </FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebRequest</FONT><FONT color=#ff0000>; </FONT><FONT color=#000080>Response</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>TWebResponse</FONT><FONT color=#ff0000>; </FONT><FONT color=#0000ff><B>var </B></FONT><FONT color=#000080>Handled</FONT><FONT color=#ff0000>: </FONT><FONT color=#000080>Boolean</FONT><FONT color=#ff0000>);
</FONT><FONT color=#0000ff><B>begin
  if </B></FONT><FONT color=#000080>HTMLTemplatePath </FONT><FONT color=#ff0000>= </FONT><FONT color=#008000>'' </FONT><FONT color=#0000ff><B>then
    </B></FONT><FONT color=#000080>FHTMLTemplatePath </FONT><FONT color=#ff0000>:= </FONT><FONT color=#000080>Format</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'%s\'</FONT><FONT color=#ff0000>,[</FONT><FONT color=#000080>Request</FONT><FONT color=#ff0000>.</FONT><FONT color=#000080>TranslateURI</FONT><FONT color=#ff0000>(</FONT><FONT color=#008000>'/HTMLTemplates'</FONT><FONT color=#ff0000>)]);
</FONT><FONT color=#0000ff><B>end</B></FONT><FONT color=#ff0000>;

</FONT></FONT>
</CODE></PRE></DIV></DIV>
<P>It is assumed here that either you've defined a virtual folder in your web server called HTMLTemplates, or you've got a physical folder under your web server's root folder by this name. </P>
<P>Further, the "scripts" folder generally has "read/execute" access. It is not advisable to keep your html templates in this "kind" of folder. Under W2K, sub folders of this folder automatically inherit the parent folder's property. My advice is that you create a sub folder under your web server's root folder (they will automatically have the correct access rights), or create a folder under inetpub and map a virtual folder to it. </P>]]></description><category>Programming</category><category>Delphi</category><category>Internet</category></item><item><title>What is TCP/IP</title><pubDate>Wed, 02 Jan 2008 14:44:36 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/10/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/10/</guid><description><![CDATA[<H2>Do you really need to know all this?</H2>No, not really. A basic understanding is good enough. You don't need to go really deep into the workings. At any time, if you feel, you're getting in too deep, don't worry. Just skip on to the next article. I put it in simpler terms there. 
<H2>TCP</H2>TCP is a connection-oriented transport protocol that sends data as an unstructured stream of bytes. By using sequence numbers and acknowledgment messages, TCP can provide a sending node with delivery information about packets transmitted to a destination node. Where data has been lost in transit from source to destination, TCP can retransmit the data until either a timeout condition is reached or until successful delivery has been achieved. TCP can also recognize duplicate messages and will discard them appropriately. If the sending computer is transmitting too fast for the receiving computer, TCP can employ flow control mechanisms to slow data transfer. TCP can also communicate delivery information to the upper-layer protocols and applications it supports. 
<H2>IP</H2>IP is the primary layer 3 protocol in the Internet suite. In addition to internetwork routing, IP provides error reporting and fragmentation and reassembly of information units called datagrams for transmission over networks with different maximum data unit sizes. IP represents the heart of the Internet protocol suite. 
<P>IP addresses are globally unique, 32-bit numbers assigned by the Network Information Center. Globally unique addresses permit IP networks anywhere in the world to communicate with each other. 
<P>An IP address is divided into three parts. The first part designates the network address, the second part designates the subnet address, and the third part designates the host address. 
<P>IP addressing supports three different network classes. Class A networks are intended mainly for use with a few very large networks, because they provide only 8 bits for the network address field. Class B networks allocate 16 bits, and Class C networks allocate 24 bits for the network address field. Class C networks only provide 8 bits for the host field, however, so the number of hosts per network may be a limiting factor. In all three cases, the leftmost bit(s) indicate the network class. IP addresses are written in dotted decimal format; for example, 24.28.0.1 
<P>
<H2>Ports and Sockets</H2>This section introduces the concepts of port and socket, which are necessary to exactly determine which local process at a given host actually communicates with which process at which remote host using which protocol. If this sounds confusing, consider the following 
<OL>
<LI>An application process is assigned a process identifier (process ID) which is likely to be different each time that process is started. 
<LI>Process IDs differ between each operating system platforms, hence they are not uniform. 
<LI>A server process can have multiple connections to multiple clients at a time, hence simple connection identifiers would not be unique. </LI></OL>The concept of ports and sockets provides a way to uniformly and uniquely identify connections, and programs and hosts that are engaged in them, irrespective of the specific process IDs. 
<H2>Ports</H2>Each process that wants to communicate with another processs identifies itself to the TCP/IP protocol suite by one or more ports. A port is a 16-bit number, used by the host-to-host protocol to identify to which higher level protocol or application program(process) it must deliver incoming messages. There are two types of port: 
<H2>Well-Known Ports</H2>Well-Known ports belong to the standard servers, for example Telnet uses port 23. Well-known port numbers range between 1 and 1023. Well-known port numbers are typically odd, because early systems using the port concept required an odd/even pair of ports for duplex (two-way) operation. Most servers require only a single port. Exceptions are BBOTP server which uses port 67 &amp; 68 and the FTP server, which uses 20 &amp; 21. The well-known ports are controlled and assigned by the Internet central authority (IANA) and on most systems can only be used by system processes or by programs executed by privileged users. The reason for well-known ports is to allow clients to be able to find servers without configuration information. 
<H2>Ephemeral Ports</H2>Clients do not need well-known port numbers because they initiate communication with servers and the port number they are using is contained in the UDP data grams sent to the server. Each clients process is also allocated a port number as long as it needs it, by the host it is running on. Ephemeral port numbers have values greater than 1023, normally in the range 1024 to 65535. A client can use any number allocated to it, as long as the combination of <TRANSPORT protocol, IP address, port number>is unique. Ephemeral ports are not controlled by IANA and on most systems can be used by ordinary user developed programs. Confusion due to two different applications trying to use the same port numbers on one host is avoided by writing those applications to request an available port from TCP/IP. Because this port number is dynamically assigned, it may differ from one invocation of an application to the next. UDP, TCP and ISO TP-4 all use the same port principle. To the extent possible, the same port numbers are used for the same services on top of UDP, TCP and ISO TP-4. Normally, servers will use either TCP or UDP, but there are exceptions. For example, domain name server use both UDP port 53 and TCP port 53. 
<H2>Sockets</H2>A Socket is a name given to the package of subroutines that provide access to TCP/IP on most systems. A combination of an IP Address and a port is considered a socket. 
<H2>Summary</H2>TCP and IP were developed by a Department of Defense (DOD) research project to connect a number different networks designed by different vendors into a network of networks (the "Internet"). It was initially successful because it delivered a few basic services that everyone needs (file transfer, electronic mail, remote logon) across a very large number of client and server systems. Several computers in a small department can use TCP/IP (along with other protocols) on a single LAN. The IP component provides routing from the department to the enterprise network, then to regional networks, and finally to the global Internet. On the battlefield a communications network will sustain damage, so the DOD designed TCP/IP to be robust and automatically recover from any node or phone line failure. This design allows the construction of very large networks with less central management. However, because of the automatic recovery, network problems can go undiagnosed and uncorrected for long periods of time. 
<P>As with all other communications protocol, TCP/IP is composed of layers: 
<P>IP - is responsible for moving packets of data from node to node. IP forwards each packet based on a four byte destination address (the IP number). The Internet authorities assign ranges of numbers to different organizations. The organizations assign groups of their numbers to departments. IP operates on gateway machines that move data from department to organization to region and then around the world. TCP - is responsible for verifying the correct delivery of data from client to server. Data can be lost in the intermediate network. TCP adds support to detect errors or lost data and to trigger retransmission until the data is correctly and completely received. </P>]]></description><category>Programming</category><category>Delphi</category><category>Internet</category></item><item><title>PART 1 - Understanding Client/Server</title><pubDate>Tue, 01 Jan 2008 14:46:45 GMT</pubDate><link>http://exposureroom.com/members/skumar/articles/post/11/</link><guid isPermaLink="true">http://exposureroom.com/members/skumar/articles/post/11/</guid><description><![CDATA[<P>TCP/IP stands for - <B>T</B>ransmission <B>C</B>ontrol <B>P</B>rotocol / <B>I</B>nternet <B>P</B>rotocol. This protocol is widely used throughout the world and is a standard way of communication across the Internet. With the way things are going, Internet enabled", I thought I'd try and explain TCP/IP by way of examples and projects. 
<P>
<P>I personally am totally in love with this technology. It is VERY powerful and has opened up the whole world to me (literally). Today, I understand a lot of what is going on and how it's done, primarily because I now understand TCP/IP. In the short time that I've been playing around with TCP/IP, I have done some really wonderful things with it. Let's get down to it.. 
<P>
<P>For this protocol to work there has to be a client and a server socket. A socket is referred to as an end point. An application that contains a client socket is called a client while an application that contains a server socket is called a server. The client establishes a connection with the server and once this connection is established data can be transferred from the client to the server or server to client (Also known as full duplex) over the same connection. For a connection to be established the client needs to know the IP address and a port number (also known as a SOCKET). 
<P>
<P>TCP/IP is a connection-oriented protocol. Data is transferred from one socket to the other in the form of bytes. The TCP/IP protocol guarantees that all data sent will be received (as long as a connection is maintained). It does not guarantee however that the data will be received in the way it was sent. But it does guarantee that the data will be received in the order in which it was sent. 
<P>
<P>Let me explain the above a bit more with some example. Let's say we have a client application and a server application that have established a connection. Let's say that we send the string "Borland" and then "Delphi" from the client to the server. Just because you first sent the string "Borland" and later sent the string "Delphi", does not mean that the server gets it as two packets. The server will receive all the data, but not as you sent it. It could receive it all in one packet (BorlandDelphi) or in any combination. Even one byte at a time! Only the order is guaranteed and what was sent will be received. The time it takes and the way it is received all depends on the network speed and traffic. 
<P>
<P>Seeing this possibility, one generally has to devise ones own protocol "on top of" the TCP/IP protocol. The simplest thing one could do is, transmit every string with an ending carriage return and line feed. Then on the server side, you break up the bytes received by scanning for a carriage return and line feed combination. So you will then know that the string "Borland" was sent and then the string "Delphi" was sent. You will always define your own "protocol" when working with TCP/IP for this reason. Some protocols that have already been defined are HTTP, SMTP, POP, FTP etc. These are standards. An HTTP Client (Browser) knows how to "talk" to an HTTP server (web server) since the protocol is a standard. Therefore you can use any browser with any web server. 
<P>
<P>Lets look at a real example of this. To try this example, you will need: 
<OL>
<LI>A connection to the Internet. 
<LI>The IP address or host name of your POP3 server. 
<LI>Your user name /account for this server. 
<LI>Your password for the account. 
<LI>A telnet client. (Win95/98/NT has a telnet client). </LI></OL>
<P>Lets say, my email address is <KBD><a rel="nofollow" href="mailto:shivk@erols.com" target="_blank">shivk@erols.com</A></KBD> 
<P>Generally, the POP3 server name is - pop.erols.com. (or pop3.erols.com or even erols.com) 
<P>The port POP3 uses is 110. (its a standard) 
<P>The user name is <KBD>shivk</KBD> 
<P>Let's say my password is <KBD>delphi</KBD>. 
<P>
<P>I'll use the telnet client that comes with win95/98/NT for this example. 
<P>
<OL>
<LI>Choose Start | Run from the task bar and type - telnet and then click OK. 
<LI>From the telnet client's Connect menu choose - <KBD>Remote System</KBD>. 
<LI>Type in your POP3 server name in the Host Name field. (<KBD>pop.erols.com</KBD>) 
<LI>Type in <KBD>110</KBD> in the port field. 
<LI>Click OK. 
<LI>The telnet client will connect to your POP3 server and you should see a response from the server. The POP3 protocol says that a POP3 server should respond with a <KBD>" OK"</KBD>. What you see after the first 4 characters is dependent on the server application. 
<LI>In the telnet screen type the words - <KBD>user shivk</KBD> and press the Enter key.(use your account name instead of - shivk). 
<LI>Again, if you typed it correctly, you should see that the server responds with a <KBD>" OK"</KBD>. 
<LI>Next type - <KBD>pass delphi</KBD> and press the Enter key (use your password instead of - delphi). 
<LI>The server should respond with a <KBD>" OK"</KBD> once again. 
<LI>You have now logged into you email server directly. This is what your email client does for you. 
<LI>Next type in - <KBD>list</KBD> and press the Enter key.. 
<LI>The server should respond with a <KBD>" OK"</KBD> and the number of messages and their sizes. 
<LI>If you have any messages, type in - <KBD>retr 1</KBD> and press the Enter key (1 is the first message). 
<LI>You should see the first email that the server has waiting for you. This email will contain the full header as well as the message itself. 
<LI>If you want to Delete this message, you would type <KBD>Dele 1</KBD>. I suggest you DON'T do this ! </LI></OL>There are other commands a POP3 server understands, such as DELE etc. What you need to understand here is that all of the above is a protocol. Even pressing the Enter key after each command is a part of the protocol. A way of communication established for a POP3 server. Your email client knows of this protocol and is doing what you just did, to retrieve your email from your email server. It's a more user friendly way to doing it. The POP3 server responds with a "-ERR" if you type in a command it does not understand or if your commands are not in the right sequence. 
<P>As another example, I have built a VERY simple TCP/IP server that is running on my PC. I've established a certain protocol that you need to use to communicate with it. Use the same telnet client for this. 
<P></P>
<P>The host name is <KBD><a rel="nofollow" href="http://www.matlus.com" target="_blank">www.matlus.com</A></KBD> 
<P>The port is <KBD>3232</KBD>. 
<P>
<P>Basically, it will respond with whatever you send it, along with a " OK" and your IP address and the date and time on my PC at the time of responding. 
<P>
<P>A "command" it understands is - <KBD>About</KBD>. See what happens when you type in the word - <KBD>about</KBD>. 
<P>
<P>This server is also capable of sending back information from a database. The TQuery component is connected to the DBDEMOS Alias. To fire a query on the server the command is SQL: followed by the SQL statement you want it to execute. So if you wanted to see all records of the table, you type: 
<P><KBD>SQL: SELECT * FROM CUSTOMER</KBD> 
<P>Any valid SQL statement is allowed. You will also notice that the first line returned is the fields names. And also, that each field is delimited by a special character <KBD>#0183</KBD> and that each line is delimited with <KBD>#1086</KBD>. I've chosen these just because I like them ! This is my <KBD>Protocol</KBD> 
<P>
<P>This will come in handy when we build the client application for this server (rather than use telnet). 
<P>
<P>If you want to join a list server dedicated to this tutorial, have a look at my <a rel="nofollow" href="http://www.matlus.com/scripts/website.dll/articles?ListServers" target="_blank">List Server</A> link. 
<P>
<P>If you liked this article and would like to see more, please let me know.<a rel="nofollow" href="mailto:shivk@erols.com" target="_blank">email me</A> </P>]]></description><category>Programming</category><category>Work</category><category>Delphi</category></item></channel></rss>
