<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>johna's blog</title>
<link>https://johna.compoutpost.com/</link>
<description>...mostly about web development and programming, with a little bit of anything else related to the Internet, computers and technology.</description>
<item>
<title>Custom error pages for ASP.NET Web Forms and Classic ASP in IIS 7 and 8.5</title>
<link>https://johna.compoutpost.com/blog/1003/custom-error-pages-for-asp-net-web-forms-and-classic-asp-in-iis-7-and-8-5/</link>
<description>I was recently doing some work on a website which has a mixture of older Classic ASP pages and ASP.NET Web Forms pages. The website is running on IIS 8.5 and .NET framework 4.x.&lt;br&gt;&lt;br&gt;The website has some code that sent email notifications of any Classic ASP server errors, but nothing for .NET errors. It also has custom 404 and 500 error pages for Classic ASP but nothing for ASP.NET.&lt;br&gt;&lt;br&gt;I attempted to create some custom error pages and email notification for .NET but ran into some troubles along the way.&lt;br&gt;&lt;br&gt;Here's what you need to do and some of the things that can go wrong.&lt;br&gt;&lt;br&gt;&lt;b&gt;httpErrors element&lt;/b&gt;&lt;br&gt;&lt;br&gt;This is under system.webServer in the web.config file and is used for non-aspx pages.&lt;br&gt;&lt;br&gt;Here you can set your custom 404 page not found errors for Classic ASP and other non-aspx pages, like images or folders.&lt;br&gt;&lt;br&gt;You can also set your custom error pages for 500 internal server errors.&lt;br&gt;&lt;br&gt;My Classic ASP error email notification code is in the custom 500 error page (coded in Classic ASP of course). One problem I came across here was that Server.GetLastError was not reporting any error. I found that you must specify the 100 subStatusCode of the 500 error here to get the details of the error with Server.GetLastError.&lt;br&gt;&lt;br&gt;Here's a sample of this section from my working web.config:&lt;br&gt;&lt;br&gt;&lt;pre&gt;&amp;lt;system.webServer&amp;gt;&lt;br&gt;	&amp;lt;httpErrors errorMode=&quot;Custom&quot;&amp;gt;&lt;br&gt;		&amp;lt;remove statusCode=&quot;404&quot; subStatusCode=&quot;-1&quot; /&amp;gt;&lt;br&gt;		&amp;lt;error statusCode=&quot;404&quot; prefixLanguageFilePath=&quot;&quot; path=&quot;/_Error404.aspx&quot; responseMode=&quot;ExecuteURL&quot; /&amp;gt;&lt;br&gt;		&amp;lt;remove statusCode=&quot;500&quot; subStatusCode=&quot;100&quot; /&amp;gt;&lt;br&gt;		&amp;lt;error statusCode=&quot;500&quot; subStatusCode=&quot;100&quot; prefixLanguageFilePath=&quot;&quot; path=&quot;/_Error500.asp&quot; responseMode=&quot;ExecuteURL&quot; /&amp;gt;&lt;br&gt;	&amp;lt;/httpErrors&amp;gt;&lt;br&gt;&amp;lt;/system.webServer&amp;gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;Note that I use an aspx page for my custom 404 error page so I only need one for all 404 errors, but I have a asp page for my custom 500 error page so I can send email notifications.&lt;br&gt;&lt;br&gt;&lt;b&gt;customErrors element&lt;/b&gt;&lt;br&gt;&lt;br&gt;This is under system.web in the web.config and is used for aspx pages.&lt;br&gt;&lt;br&gt;Here's a sample from my working web.config:&lt;br&gt;&lt;br&gt;&lt;pre&gt;&amp;lt;system.web&amp;gt;&lt;br&gt;	&amp;lt;customErrors mode=&quot;On&quot; redirectMode=&quot;ResponseRewrite&quot;&amp;gt;&lt;br&gt;		&amp;lt;error statusCode=&quot;404&quot; redirect=&quot;/_Error404.aspx&quot; /&amp;gt;&lt;br&gt;	&amp;lt;/customErrors&amp;gt;&lt;br&gt;&amp;lt;/system.web&amp;gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;Note that I only trap for 404 errors for aspx page requests here.&lt;br&gt;&lt;br&gt;Setting the redirectMode to ResponseRewrite means that the user does not get redirected to the custom error pages. However, one problem that I ran into with this setting is that my aspx custom 404 error page didn't show, I just saw an application error. The problem is that Session is not available if you use ResponseRewrite so you must not attempt to access the Session object in your custom error page.&lt;br&gt;&lt;br&gt;&lt;b&gt;Trapping 500 internal server errors for aspx pages&lt;/b&gt;&lt;br&gt;&lt;br&gt;You could trap these errors also in the customErrors element but I chose to do this instead in the global.asax page.&lt;br&gt;&lt;br&gt;I send my email error notification then use Server.Transfer to show the custom 500 error page, like this:&lt;br&gt;&lt;br&gt;&lt;pre&gt;void Application_Error(object sender, EventArgs e)&lt;br&gt;{&lt;br&gt;	//error notification code here&lt;br&gt;&lt;br&gt;	Server.Transfer(&quot;/_Error500.aspx&quot;);&lt;br&gt;}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;Notes about custom 500 error pages&lt;/b&gt;&lt;br&gt;&lt;br&gt;It should be obvious but your custom 500 error pages should not include any code that might cause an error itself, or at least it should be handled properly.&lt;br&gt;&lt;br&gt;For this reason I generally use a very simple custom 500 error page with no database calls. I don't use my website's MasterPage as that usually has code for things like logged-in user, or shopping cart lookups that might result in errors.&lt;br&gt;&lt;br&gt;If you're sending email notifications it's also a good idea to handle mail sending errors in case your mail server is down. That way the user still sees your friendly error message.&lt;br&gt;&lt;br&gt;Custom 404 errors don't have this problem (except for the abovementioned Session object issue) so can be rich in content and have full functionality. In fact it's good practice to make your custom 404 error pages as helpful as possible: attempt to offer an alternate page that you think matches the user's original request; briefly explain what your website is all about; and, offer a next relevant step for the user so that hopefully they don't leave your site.</description>
<comments>https://johna.compoutpost.com/blog/1003/custom-error-pages-for-asp-net-web-forms-and-classic-asp-in-iis-7-and-8-5/#comments</comments>
<pubDate>2019-02-20T12:00:00+10:00</pubDate>
<category>ASP.NET Web Forms</category>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/1003</guid>
</item>
<item>
<title>Sending email using Amazon SES with Classic ASP</title>
<link>https://johna.compoutpost.com/blog/823/sending-email-using-amazon-ses-with-classic-asp/</link>
<description>I recently needed to change a client's website to send emails using Amazon SES and encountered a few issues.&lt;br&gt;&lt;br&gt;The client's code was using jMail COM component but I couldn't make this work, most likely because Amazon SES requires use of TLS and I could not find how to enable this in jMail, if it supports it at all.&lt;br&gt;&lt;br&gt;So the solution was to change to CDOSYS, but this required some experimentation before it would work.&lt;br&gt;&lt;br&gt;Some of the errors I received along the way were:&lt;br&gt;&lt;br&gt;&amp;bull; The server rejected the sender address&lt;br&gt;&amp;bull; The server response was: 530 Authentication required&lt;br&gt;&amp;bull; 530 Must issue a STARTTLS command first&lt;br&gt;&lt;br&gt;To use CDOSYS with Amazon SES you must specify a remote server, authenticate using basic authentication, use port 25, and use SSL (not TLS as I attempted).&lt;br&gt;&lt;br&gt;This sample code worked for me. You will of course need to include your own Amazon SES SMTP login details, server name, and verified sender address.&lt;br&gt;&lt;br&gt;&lt;pre&gt;Dim objMessage&lt;br&gt;Set objMessage = CreateObject(&quot;CDO.Message&quot;)&lt;br&gt;objMessage.Subject = &quot;Your subject&quot;&lt;br&gt;objMessage.From = &quot;test@exampledomain.com&quot;&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/sendusing&quot;) = 2&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpserver&quot;) = &quot;email-smtp.us-west-2.amazonaws.com&quot; 'Change if using a different Amazon SES server&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpauthenticate&quot;) = 1&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/sendusername&quot;) = &quot;Your Amazon SES SMTP username, usually starts with AKI...&quot;&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/sendpassword&quot;) = &quot;Your Amazon SES SMTP password&quot;&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpserverport&quot;) = 25&lt;br&gt;objMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpusessl&quot;) = True&lt;br&gt;objMessage.Configuration.Fields.Update&lt;br&gt;objMessage.TextBody = &quot;This is a test email&quot;&lt;br&gt;objMessage.To = &quot;success@simulator.amazonses.com&quot;&lt;br&gt;&lt;br&gt;On Error Resume Next&lt;br&gt;objMessage.Send&lt;br&gt;&lt;br&gt;If Err.Number = 0 Then&lt;br&gt;	Response.Write(&quot;OK&quot;)&lt;br&gt;Else&lt;br&gt;	Response.Write(&quot;FAIL: &quot; + Err.Description)&lt;br&gt;End If&lt;/pre&gt;&lt;br&gt;</description>
<comments>https://johna.compoutpost.com/blog/823/sending-email-using-amazon-ses-with-classic-asp/#comments</comments>
<pubDate>2017-03-21T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/823</guid>
</item>
<item>
<title>Classic ASP class constructors with parameters</title>
<link>https://johna.compoutpost.com/blog/806/classic-asp-class-constructors-with-parameters/</link>
<description>Although probably no one cares about Classic ASP, except those who still need to support it, I was refreshing my memory today on how to use classes in Classic ASP and found a couple of options for simulating constructors with parameters.&lt;br&gt;&lt;br&gt;We start with a simple class and add a default function that returns the current instance:&lt;br&gt;&lt;br&gt;&lt;pre&gt;Class MyClass&lt;br&gt;     Private m_myvalue&lt;br&gt; &lt;br&gt;     Public Default Function Init(myvalue)&lt;br&gt;         m_myvalue= myvalue&lt;br&gt;         &lt;br&gt;         Set Init = Me&lt;br&gt;     End Function&lt;br&gt;     &lt;br&gt;     Public Property Get MyValue &lt;br&gt;         MyValue = m_myvalue&lt;br&gt;     End Property&lt;br&gt;End Class&lt;/pre&gt;&lt;br&gt;Then we can create an instance of our class with a faux constructor, like this...&lt;br&gt;&lt;br&gt;&lt;pre&gt;Set myobject = (New MyClass)(123)&lt;/pre&gt;&lt;br&gt;...or, if you prefer, this...&lt;br&gt;&lt;br&gt;&lt;pre&gt;Set myobject = New MyClass.Init(123)&lt;/pre&gt;&lt;br&gt;Sources: &lt;a href=&quot;http://www.visualbasicscript.com/Initializing-a-Class-with-parameters-m76239.aspx&quot; target=&quot;_blank&quot;&gt;www.visualbasicscript.com/Initializing-a-Class-with-parameters-m76239.aspx&lt;/a&gt; and &lt;a href=&quot;http://brendangadd.blogspot.com.au/2011/06/constructors-in-asp-classic.html&quot; target=&quot;_blank&quot;&gt;brendangadd.blogspot.com.au/2011/06/constructors-in-asp-classic.html&lt;/a&gt;.</description>
<comments>https://johna.compoutpost.com/blog/806/classic-asp-class-constructors-with-parameters/#comments</comments>
<pubDate>2016-06-08T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/806</guid>
</item>
<item>
<title>Classic ASP cookie with no name hacking attack causing error 80004005</title>
<link>https://johna.compoutpost.com/blog/782/classic-asp-cookie-with-no-name-hacking-attack-causing-error-80004005/</link>
<description>As of July 2015, many of my Classic ASP websites have started logging strange errors, either 80004005 or not reporting any error code at all.&lt;br&gt;&lt;br&gt;After carefully looking through the HTTP headers for these requests I found a common link: they all had at least one cookie with no name.&lt;br&gt;&lt;br&gt;It appears that Classic ASP can't handle this and will stop executing your script with an error whenever a cookie with no name exists and you attempt to access the cookies, either by Request.Cookies(), Response.Cookies() or Request().&lt;br&gt;&lt;br&gt;These requests are obviously some type of attack on the website, and based on forum posts and Q&amp;A website posts I have seen, many other sites have been attacked starting around the same time.&lt;br&gt;&lt;br&gt;It could possibly be a &lt;a href=&quot;https://en.wikipedia.org/wiki/Denial-of-service_attack&quot; target=&quot;_blank&quot;&gt;denial of service attack&lt;/a&gt;. By causing these types of errors some websites may eventually stop working due to not closed or destroying certain objects.&lt;br&gt;&lt;br&gt;Alternately it could be some sort of other attack not specifically for Classic ASP websites using cookie names normally used by common website platforms with values that may be intended to cause issues or gain access.&lt;br&gt;&lt;br&gt;To avoid this problem I looked at several alternatives but the simplest one for me to implement was to add some code to check whether the cookies could be read and terminate the script if it they couldn't be read, using error trapping. As most of my Classic ASP websites have an &quot;include&quot; file that is used by all scripts this only needed to be added in one place.&lt;br&gt;&lt;br&gt;&lt;pre&gt;On Error Resume Next&lt;br&gt;Request.Cookies(&quot;test&quot;)&lt;br&gt;If Err.Number &lt;&gt; 0 Then Response.End&lt;br&gt;On Error Goto 0&lt;/pre&gt;&lt;br&gt;There are other interesting options including IIS URL rewrite rules and regular expressions. There has been some interesting discussion at &lt;a href=&quot;https://forums.iis.net/t/1226865.aspx?Request+Cookies+generate+80004005+2147467259+error+if+cookie+with+no+name&quot; target=&quot;_blank&quot;&gt;forums.iis.net&lt;/a&gt;.</description>
<comments>https://johna.compoutpost.com/blog/782/classic-asp-cookie-with-no-name-hacking-attack-causing-error-80004005/#comments</comments>
<pubDate>2015-07-31T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/782</guid>
</item>
<item>
<title>Classic ASP functions for database queries and SQL injection protection</title>
<link>https://johna.compoutpost.com/blog/749/classic-asp-functions-for-database-queries-and-sql-injection-protection/</link>
<description>If writing database queries in SQL in Classic ASP for SQL Server, rather than using ADO or parameterised queries, you can use these functions to correctly format your data and protect against SQL injection.&lt;br&gt;&lt;br&gt;&lt;b&gt;Numeric fields&lt;/b&gt;&lt;br&gt;&lt;br&gt;ForceNumeric ensures that only numeric values are passed.&lt;br&gt;&lt;br&gt;&lt;pre&gt;Function ForceNumeric(sngValue)&lt;br&gt;	If IsNull(sngValue) Then&lt;br&gt;		ForceNumeric = 0&lt;br&gt;	ElseIf sngValue = &quot;&quot; Or Not IsNumeric(sngValue)  Then&lt;br&gt;		ForceNumeric = 0&lt;br&gt;	Else&lt;br&gt;		ForceNumeric = CSng(sngValue)&lt;br&gt;	End If&lt;br&gt;End Function&lt;/pre&gt;&lt;br&gt;&lt;b&gt;String fields&lt;/b&gt;&lt;br&gt;&lt;br&gt;Quotes adds single quotes around the string, and escapes single quotes within the string.&lt;br&gt;&lt;br&gt;&lt;pre&gt;Function Quotes(strValue)&lt;br&gt;	If IsNull(strValue) Then&lt;br&gt;		Quotes = &quot;null&quot;&lt;br&gt;	Else&lt;br&gt;		Quotes = &quot;'&quot; &amp; Replace(strValue, &quot;'&quot;, &quot;''&quot;) &amp; &quot;'&quot;&lt;br&gt;	End If&lt;br&gt;End Function&lt;/pre&gt;&lt;br&gt;&lt;b&gt;Date fields&lt;/b&gt;&lt;br&gt;&lt;br&gt;FormatDateSql adds quotes and formats dates to a SQL friendly format (yyyy-mm-dd). If not a valid date or a null value then it returns &quot;null&quot;.&lt;br&gt;&lt;br&gt;FormatDateTimeSql does the same except it adds the time too, down to seconds.&lt;br&gt;&lt;br&gt;&lt;pre&gt;Function FormatDateSql(datValue)&lt;br&gt;	If IsNull(datValue) Then &lt;br&gt;		FormatDateSql = &quot;Null&quot;&lt;br&gt;	ElseIf datValue = &quot;&quot; Then&lt;br&gt;		FormatDateSql = &quot;Null&quot;&lt;br&gt;	ElseIf IsDate(datValue) Then&lt;br&gt;		FormatDateSql = Quotes(Year(datValue) &amp; &quot;-&quot; &amp; Right(&quot;0&quot; &amp; Month(datValue), 2) &amp; &quot;-&quot; &amp; Right(&quot;0&quot; &amp; Day(datValue), 2))&lt;br&gt;	Else&lt;br&gt;		FormatDateSql = &quot;Null&quot;&lt;br&gt;	End If&lt;br&gt;End Function&lt;/pre&gt;&lt;br&gt;&lt;pre&gt;Function FormatDateTimeSql(datValue)&lt;br&gt;	If IsNull(datValue) Then &lt;br&gt;		FormatDateTimeSql = &quot;Null&quot;&lt;br&gt;	ElseIf datValue = &quot;&quot; Then&lt;br&gt;		FormatDateTimeSql = &quot;Null&quot;&lt;br&gt;	ElseIf IsDate(datValue) Then&lt;br&gt;		FormatDateTimeSql = Quotes(Year(datValue) &amp; &quot;-&quot; &amp; Right(&quot;0&quot; &amp; Month(datValue), 2) &amp; &quot;-&quot; &amp; Right(&quot;0&quot; &amp; Day(datValue), 2) &amp; &quot; &quot; &amp; Right(&quot;0&quot; &amp; Hour(datValue), 2) &amp; &quot;:&quot; &amp; Right(&quot;0&quot; &amp; Minute(datValue), 2) &amp; &quot;:&quot; &amp; Right(&quot;0&quot; &amp; Second(datValue), 2))&lt;br&gt;	Else&lt;br&gt;		FormatDateTimeSql = &quot;null&quot;&lt;br&gt;	End If&lt;br&gt;End Function&lt;/pre&gt;&lt;br&gt;&lt;b&gt;Boolean fields&lt;/b&gt;&lt;br&gt;&lt;br&gt;CBit returns 1 or 0 to represent true or false.&lt;br&gt;&lt;br&gt;&lt;pre&gt;Function CBit(booleanvalue)&lt;br&gt;	If booleanvalue Then&lt;br&gt;		CBit = 1&lt;br&gt;	Else&lt;br&gt;		CBit = 0&lt;br&gt;	End If&lt;br&gt;End Function&lt;/pre&gt;</description>
<comments>https://johna.compoutpost.com/blog/749/classic-asp-functions-for-database-queries-and-sql-injection-protection/#comments</comments>
<pubDate>2014-07-28T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/749</guid>
</item>
<item>
<title>How to share Session securely between Classic ASP and ASP.NET</title>
<link>https://johna.compoutpost.com/blog/737/how-to-share-session-securely-between-classic-asp-and-asp-net/</link>
<description>Looking at the Google search results, it seems that there has been plenty of demand to share Session values between Classic ASP and ASP.NET. This is usually a result of supporting legacy Classic ASP with new development in ASP.NET.&lt;br&gt;&lt;br&gt;Most of the solutions I found either did not handle sharing securely or required modifications to the Classic ASP code (such as the top ranking Microsoft solution).&lt;br&gt;&lt;br&gt;Deep into the search results I found what seems like a great solution but doesn't seem to have had much support in the form of comments and social shares.&lt;br&gt;&lt;br&gt;Like most of the solutions, it uses a Classic ASP script to return requested session variables. But it does this securely by locking down this script to internal requests only (by IP address), and retrieving by a server-side HTTP request. As a server-side request would usually use the user Session of the web server itself rather than the user's Session, the author of this code cleverly retrieves the Classic ASP cookie and passes it in the request headers. A very clever solution.&lt;br&gt;&lt;br&gt;The only improvement I could suggest is that the IP address could be faked so instead I would possibly suggest using a password protected folder or some other method of authentication.&lt;br&gt;&lt;br&gt;I also found that when I tried to access the Classic ASP session using the HTTPS protocol it would not work. The only way I could get it to work was to change the IIS setting &quot;New ID On Secure Connect&quot; to false which allows the use of the same Session in both HTTP and HTTPS.&lt;br&gt;&lt;br&gt;You can find the original solution at &lt;a href=&quot;http://devproconnections.com/aspnet/share-session-state-between-asp-and-aspnet-apps&quot; target=&quot;_blank&quot;&gt;http://devproconnections.com/aspnet/share-session-state-between-asp-and-aspnet-apps&lt;/a&gt;.&lt;br&gt;&lt;br&gt;I have used that concept and made my own version that allows you to get or set a Classic ASP Session variable from ASP.NET:&lt;br&gt;&lt;br&gt;AspSession.cs&lt;br&gt;&lt;br&gt;&lt;pre&gt;using System;&lt;br&gt;using System.IO;&lt;br&gt;using System.Net;&lt;br&gt;using System.Web;&lt;br&gt;&lt;br&gt;public class AspSession&lt;br&gt;{&lt;br&gt;	public static object Get(string name)&lt;br&gt;	{&lt;br&gt;		HttpContext context = HttpContext.Current;&lt;br&gt;		object value = null;&lt;br&gt;		String[] cookies = context.Request.Cookies.AllKeys;&lt;br&gt;		for (int i = 0; i &lt; cookies.Length; i++)&lt;br&gt;		{&lt;br&gt;			HttpCookie cookie = context.Request.Cookies[cookies[i]];&lt;br&gt;			if (cookie.Name.StartsWith(&quot;ASPSESSION&quot;))&lt;br&gt;			{&lt;br&gt;				System.Uri uri = context.Request.Url;&lt;br&gt;				HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri.Scheme + &quot;://&quot; + uri.Host + &quot;:&quot; + uri.Port.ToString() + &quot;/Services/AspSession.asp?mode=get&amp;name=&quot; + name);&lt;br&gt;				request.Headers.Add(&quot;Cookie: &quot; + cookie.Name + &quot;=&quot; + cookie.Value);&lt;br&gt;				HttpWebResponse response = (HttpWebResponse)request.GetResponse();&lt;br&gt;				Stream responseStream = response.GetResponseStream();&lt;br&gt;				System.Text.Encoding encode = System.Text.Encoding.GetEncoding(&quot;utf-8&quot;);&lt;br&gt;				StreamReader readStream = new StreamReader(responseStream, encode);&lt;br&gt;				value = readStream.ReadToEnd();&lt;br&gt;				response.Close();&lt;br&gt;				readStream.Close();&lt;br&gt;				break;&lt;br&gt;			}&lt;br&gt;		}&lt;br&gt;		return value;&lt;br&gt;	}&lt;br&gt;&lt;br&gt;	public static void Set(string name, object value)&lt;br&gt;	{&lt;br&gt;		HttpContext context = HttpContext.Current;&lt;br&gt;&lt;br&gt;		String[] cookies = context.Request.Cookies.AllKeys;&lt;br&gt;&lt;br&gt;		for (int i = 0; i &lt; cookies.Length; i++)&lt;br&gt;		{&lt;br&gt;			HttpCookie cookie = context.Request.Cookies[cookies[i]];&lt;br&gt;&lt;br&gt;			if (cookie.Name.StartsWith(&quot;ASPSESSION&quot;))&lt;br&gt;			{&lt;br&gt;				System.Uri uri = context.Request.Url;&lt;br&gt;&lt;br&gt;				HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri.Scheme + &quot;://&quot; + uri.Host + &quot;:&quot; + uri.Port.ToString() + &quot;/Services/LegacySession.asp?mode=set&amp;name=&quot; + context.Server.UrlEncode(name) + &quot;&amp;value=&quot; + context.Server.UrlEncode(value.ToString()));&lt;br&gt;				request.Headers.Add(&quot;Cookie: &quot; + cookie.Name + &quot;=&quot; + cookie.Value);&lt;br&gt;				HttpWebResponse response = (HttpWebResponse)request.GetResponse();&lt;br&gt;				Stream responseStream = response.GetResponseStream();&lt;br&gt;				break;&lt;br&gt;			}&lt;br&gt;		}&lt;br&gt;	}&lt;br&gt;}&lt;/pre&gt;&lt;br&gt;&lt;br&gt;/services/aspsession.asp&lt;br&gt;&lt;br&gt;&lt;pre&gt;&amp;lt;%&lt;br&gt;Dim strMode, strName, strValue&lt;br&gt;&lt;br&gt;If Request.ServerVariables(&quot;REMOTE_ADDR&quot;) = Request.ServerVariables(&quot;LOCAL_ADDR&quot;) Then&lt;br&gt;	strMode = Request.QueryString(&quot;mode&quot;)&lt;br&gt;	strName = Request.QueryString(&quot;name&quot;)&lt;br&gt;	If strMode = &quot;get&quot; Then&lt;br&gt;		Response.Write(Session(strName))&lt;br&gt;	ElseIf strMode = &quot;set&quot; Then&lt;br&gt;		strValue = Request.QueryString(&quot;value&quot;)&lt;br&gt;		Session(strName) = strValue&lt;br&gt;	End If&lt;br&gt;End If&lt;br&gt;%&amp;gt;&lt;/pre&gt;&lt;br&gt;&lt;br&gt;&lt;b&gt;Update 22-Dec-2017:&lt;/b&gt; I've since found there is an issue with this script. Sometimes in Classic ASP there will be multiple session cookies for the same user. I suspect the last one is the one Classic ASP uses. The ASP.NET code needs to be modified to either use the last cookie or try each cookie until it finds one that returns the value. Further investigation and changes are necessary.</description>
<comments>https://johna.compoutpost.com/blog/737/how-to-share-session-securely-between-classic-asp-and-asp-net/#comments</comments>
<pubDate>2014-03-22T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<category>ASP.NET Web Forms</category>
<guid>https://johna.compoutpost.com/blog/737</guid>
</item>
<item>
<title>Review of ABCPDF.NET from webSupergoo</title>
<link>https://johna.compoutpost.com/blog/736/review-of-abcpdf-net-from-websupergoo/</link>
<description>I have been using ABCpdf for generating PDF documents in Classic ASP and ASP.NET for many years, and have always found it to be the simplest way to generate and manipulate PDF documents.&lt;br&gt;&lt;br&gt;Not only can you create empty documents and add text and images wherever and however you like, but the feature I find most useful is conversion from HTML to PDF.&lt;br&gt;&lt;br&gt;As an example, on one website I need to generate nice looking brochures from content from a database which changes frequently. I have created a protected ASPX page which retrieves the content from the database and displays it in HTML. I also have created some attractive PDF templates -- a different one for page one and for subsequent pages. Using ABCpdf I load the appropriate PDF template then overlay the HTML page. The result is exactly what I needed. ABCpdf also overlays page numbers and allows me to save the resulting PDF to the file system or send it straight to the browser as a dynamic PDF.&lt;br&gt;&lt;br&gt;With my HTML and CSS I can also control things like how different parts of the content will break across pages, and ABCpdf understands and obeys this. About the only thing I found it wouldn't do were custom web fonts that weren't available on the server.&lt;br&gt;&lt;br&gt;Let's face it, creating a PDF by placing items on different parts of a page is time-consuming and requires lots of tweaking along the way. If you're a web developer you know HTML and CSS and can probably produce results quicker working that way and converting to PDF using ABCpdf.&lt;br&gt;&lt;br&gt;Of course if you have to generate PDFs by placing items on the page, ABCpdf does have a very useful feature where it will add a grid to the page during your development which really helps with positioning and adjustments.&lt;br&gt;&lt;br&gt;I looked at other PDF components and found none that could do all of this so well, and quickly, and as easy. I know there are free PDF tools out there and ABCpdf is a comparatively a little pricey (starts at US$329), but for all the extra effort you would have to put in to get the free tools generating something like what you need, you could get ABCpdf doing the job quicker and better.&lt;br&gt;&lt;br&gt;The other good thing about ABCpdf is that despite several version updates over the years, even the latest version is still backwards compatible so my old Classic ASP code and works side-by-side with newer .NET code.&lt;br&gt;&lt;br&gt;You can download a free trial or purchase ABCpdf.NET from &lt;a href=&quot;http://www.websupergoo.com/abcpdf-1.htm&quot; target=&quot;_blank&quot;&gt;webSupergoo's website&lt;/a&gt;.</description>
<comments>https://johna.compoutpost.com/blog/736/review-of-abcpdf-net-from-websupergoo/#comments</comments>
<pubDate>2014-03-05T12:00:00+10:00</pubDate>
<category>ASP.NET Web Forms</category>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/736</guid>
</item>
<item>
<title>Classic ASP Master Pages</title>
<link>https://johna.compoutpost.com/blog/456/classic-asp-master-pages/</link>
<description>When developing websites most of them have common elements like headers, footers and navigational menus that are common throughout the site. In Classic ASP we mostly use multiple server side includes to accomplish this. I like ASP.NET master pages and this page details the technique I use to achieve something similar in Classic ASP.&lt;br&gt;&lt;br&gt;My technique involves creating a master page ASP file which has all the common elements. Where ever I want content to be added I add a call to a sub routine.&lt;br&gt;&lt;br&gt;Then in my content pages when I want the master page content to be added I include it at that point. I then create a sub routine for each content area and put my content inside these. You can have as many content sub routines as required but they must exist in every content page that uses that master page.&lt;br&gt;&lt;br&gt;The following example shows a master page and content page with two content areas: one inside the head tag (called HeadPlaceHolder in this example) so I can easily add title and meta tags, and add JavaScript and CSS within the head tag if required; and one inside the body tag between the header and footer (called ContentPlaceHolder in this example).&lt;br&gt;&lt;br&gt;Any ASP variables that are needed by more than one content area should be created outside of the sub routines.&lt;br&gt;&lt;br&gt;&lt;b&gt;masperpage.asp&lt;/b&gt;&lt;br&gt;&lt;br&gt;&lt;pre&gt;&amp;lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Transitional//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&quot;&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&amp;gt;&lt;br&gt;&amp;lt;head&amp;gt;&lt;br&gt;	&amp;lt;% Call HeadPlaceHolder() %&amp;gt;&lt;br&gt;	&amp;lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;stylesheet.css&quot; /&amp;gt;&lt;br&gt;	&amp;lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;/java.js&quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br&gt;&amp;lt;/head&amp;gt;&lt;br&gt;&amp;lt;body&amp;gt;&lt;br&gt;		&amp;lt;div id=&quot;header&quot;&amp;gt;&lt;br&gt;			Logo etc etc&lt;br&gt;		&amp;lt;/div&amp;gt;&lt;br&gt;		&amp;lt;div id=&quot;content&quot;&amp;gt;&lt;br&gt;			&amp;lt;% Call ContentPlaceHolder() %&amp;gt;&lt;br&gt;		&amp;lt;/div&amp;gt;&lt;br&gt;		&amp;lt;div id=&quot;footer&quot;&amp;gt;&lt;br&gt;			Copyright etc etc&lt;br&gt;		&amp;lt;/div&amp;gt;&lt;br&gt;&amp;lt;/body&amp;gt;&lt;br&gt;&amp;lt;/html&amp;gt;&lt;br&gt;&lt;/pre&gt;&lt;br&gt;&lt;b&gt;content-page.asp&lt;/b&gt;&lt;br&gt;&lt;br&gt;&lt;pre&gt;&lt;br&gt;&amp;lt;!--#include virtual=&quot;masterpage.asp&quot;--&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;%&lt;br&gt;'Any ASP variables that are needed by multiple contenbt areas should be declared&lt;br&gt;'outside of the sub routines&lt;br&gt;'It's a good practice to keep your ASP script at the beginning of your pages anyway&lt;br&gt;%&amp;gt;&lt;br&gt;&amp;lt;% Sub HeadPlaceHolder() %&amp;gt;&lt;br&gt;&lt;br&gt;	&amp;lt;title&amp;gt;My page title&amp;lt;/title&amp;gt;&lt;br&gt;	&amp;lt;meta content=&quot;My meta description&quot; name=&quot;description&quot; /&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;% End Sub %&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;% Sub ContentPlaceHolder() %&amp;gt;&lt;br&gt;&lt;br&gt;	&amp;lt;p&amp;gt;My page content goes here&amp;lt;/p&amp;gt;&lt;br&gt;&lt;br&gt;&amp;lt;% End Sub %&amp;gt;&lt;br&gt;&lt;/pre&gt;</description>
<comments>https://johna.compoutpost.com/blog/456/classic-asp-master-pages/#comments</comments>
<pubDate>2010-03-27T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/456</guid>
</item>
<item>
<title>CAPCTHAs and alternatives</title>
<link>https://johna.compoutpost.com/blog/449/capcthas-and-alternatives/</link>
<description>CAPTCHAs and their alternatives&lt;br&gt;&lt;br&gt;The basic purpose of a CAPTCHA (Completely Automatic Public Turing Test to Tell Computers and Humans Apart) is to prevent robots from submitting web forms. By displaying an image that cannot be &#8220;read&#8221; by a computer, only a human can submit the form successfully.&lt;br&gt;&lt;br&gt;Most of the time CAPTCHAs are an irritation to legitimate users, and can also cause issues with accessibility unless an alternative audible version of the text or numbers in the CAPTCHA image is also available.&lt;br&gt;&lt;br&gt;My technique for CAPTCHA in Classic ASP is an image only system which works like this:&lt;br&gt;&lt;br&gt;When the form is displayed two random numbers are generated. One is used as the number that is generated into an image. The other random number is used as the name of a session variable which contains the first number. This second number is stored as a hidden form field (it doesn't matter that this second number can be easily read). I use a random session variable name so as not to cause problems if the user has multiple forms open, this way each should submit without any conflict. On form submit the script gets the hidden field value and then the value of this session variable and compares this with the user's input. If they don't match the user (or robot) is redirected back to the form and two new random numbers are generated so the process repeats.&lt;br&gt;&lt;br&gt;A more simple but less effective system that prevents some robots but avoids irritation to legitimate users and accessibility problems is to use a system similar to the CAPTCHA system described above where a random number is generated and added as a hidden form field and also stored in a session variable. On form post the hidden form field value is compared with the session variable value and succeeds only if they match. This means that the form can only be submitted if the user or robot visited the web form page first and posts the random number. This prevents robots that just simulate a form post to a URL from succeeding but doesn't stop the robot if they are willing to retrieve the web form page each time they post a form.&lt;br&gt;&lt;br&gt;An improvement to this system would be to use a JavaScript script to add the value to the hidden field. Again, this would be fairly easy for a robot to simulate but would mean that the robot would have to be written specifically for the site.&lt;br&gt;&lt;br&gt;Creating an image or audible CAPTCHA is not possible for some websites, for example in Classic ASP it usually requires a third party server component (although it can be done without one). There are other alternatives.&lt;br&gt;&lt;br&gt;* Instead of creating a random number you could generate a random mathematical question, for example:&lt;br&gt;&lt;br&gt;What is five plus twenty-three?&lt;br&gt;&lt;br&gt;* You could create a database of random questions and answers, for example:&lt;br&gt;&lt;br&gt;Which is not a colour? Blue, green, apple, orange or black?&lt;br&gt;&lt;br&gt;* You could show several photos of different objects and ask the visitor to pick which picture contains a certain object.&lt;br&gt;&lt;br&gt;All of these techniques are easy to produce using a system similar to what I described near the beginning of this article.&lt;br&gt;&lt;br&gt;* You could create a textbox and set it to display:none in CSS. A robot is likely to fill this field so you can void any form submissions where this textbox is not empty.&lt;br&gt;&lt;br&gt;* Dynamically change the names of form fields and store their new names in a session variable.</description>
<comments>https://johna.compoutpost.com/blog/449/capcthas-and-alternatives/#comments</comments>
<pubDate>2009-12-09T12:00:00+10:00</pubDate>
<category>Web Security</category>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/449</guid>
</item>
<item>
<title>Obtaining Image Properties in ASP Without a Component</title>
<link>https://johna.compoutpost.com/blog/448/obtaining-image-properties-in-asp-without-a-component/</link>
<description>You don't need a third party server component to determine the height and width of an image file in Classic ASP. The LoadPicture command will load an image into and object and you can then access the height and width, such as in this example:&lt;br&gt;&lt;br&gt;&lt;pre&gt;Dim objImage&lt;br&gt;Set objImage = LoadPicture(Server.MapPath(&quot;image.ext&quot;)) &lt;br&gt;intWidth = objImage.Width&lt;br&gt;intHeight = objImage.Height&lt;/pre&gt;&lt;br&gt;4GuysFromRoll.com has an interesting article on resizing images without a component - see &lt;a href=http://www.4guysfromrolla.com/webtech/050300-1.shtml&gt;http://www.4guysfromrolla.com/webtech/050300-1.shtml&lt;/a&gt;.&lt;br&gt;&lt;br&gt;The following link contains some other code that can access image properties as well as modify GIF images: &lt;a href=http://www.u229.no/stuff/&gt;http://www.u229.no/stuff/&lt;/a&gt;.&lt;br&gt;&lt;br&gt;Lastly the following link is for a component-less CAPTCHA genertor which generates a BMP image from ASP.It may help you understand how to create and modify BMP files. See &lt;a href=http://www.tipstricks.org/&gt;http://www.tipstricks.org/&lt;/a&gt;.</description>
<comments>https://johna.compoutpost.com/blog/448/obtaining-image-properties-in-asp-without-a-component/#comments</comments>
<pubDate>2009-12-09T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/448</guid>
</item>
<item>
<title>Classic ASP Title Case</title>
<link>https://johna.compoutpost.com/blog/416/classic-asp-title-case/</link>
<description>Need a function that capitalises the first letter of each word, as used in titles?
&lt;p&gt;
Unlike some title case functions, this one doesn't just look for spaces, but capitilises the first letter after each non-alpha character which means that hyphenated words and words after numbers are considered new words.
&lt;p&gt;
&lt;textarea cols=40 rows=10 style=&quot;width:95%&quot;&gt;Function TitleCase(byVal strValue)
       Dim intChat, intLastChar, blnUCase
       strValue = LCase(strValue)
       For intChar = 1 To Len(strValue)
              blnUCase = False
              If intChar = 1 Then
                     blnUCase = True
              Else
                     intLastChar = Asc(Mid(strValue, intChar - 1, 1))
                     If Not ((intLastChar &gt;= 97 And intLastChar &lt;= 122) Or (intLastChar &gt;= 65 And intLastChar &lt;= 90)) Then
                           blnUCase = True
                     End If
              End If
              If blnUCase Then
                     strValue = Left(strValue, intChar - 1) &amp; UCase(Mid(strValue, intChar, 1)) &amp; Mid(strValue, intChar + 1)
              End If 
       Next
       TitleCase = strValue
End Function&lt;/textarea&gt;</description>
<comments>https://johna.compoutpost.com/blog/416/classic-asp-title-case/#comments</comments>
<pubDate>2008-07-29T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/416</guid>
</item>
<item>
<title>SQL Injection Protection - b.js</title>
<link>https://johna.compoutpost.com/blog/407/sql-injection-protection-b-js/</link>
<description>There is a automated SQL injection attack doing the rounds at the moments which injects some html (&amp;lt;script src=http://www.domain.com/b.js&amp;gt;&amp;lt;/script&amp;gt;) into certain fields in all the tables in a database.
&lt;p&gt;
If you have been attacked don't feel bad as an Internet search of &quot;b.js&quot; reveals tens of thousands of hacked sites.
&lt;p&gt;
The attack cleverly appends a series of SQL commands onto  your querystrings and if your code is unprotected, and you don't use Access databases, the commands may be passed on to your SQL server and the damage done.
&lt;p&gt;
Considering the damage that could be done by this sort of attack, I guess we are lucky that they chose only to append their little JavaScript.
&lt;p&gt;
However, this attack could render your website as &quot;unsafe&quot; in search engine results.
&lt;p&gt;
&lt;strong&gt;Reversing the Damage&lt;/strong&gt;
&lt;p&gt;
We are also extremely fortunate that the changes can be easily reversed with a few changes of the attackers original SQL commands.
&lt;p&gt;
Simply execute the following to clean up the damage. If you have been attacked multiple times (ie. you have multiple script blocks appended to your SQL data) then you will need to execute the following script for each attack.
&lt;p&gt;
&lt;textarea cols=5 rows=10 style=&quot;width:95%&quot;&gt;DECLARE @T varchar(255), @C varchar(255);
DECLARE Table_Cursor CURSOR FOR
SELECT a.name, b.name
FROM sysobjects a, syscolumns b
WHERE a.id = b.id AND a.xtype = 'u' AND
(b.xtype = 99 OR
b.xtype = 35 OR
b.xtype = 231 OR
b.xtype = 167);
OPEN Table_Cursor;
FETCH NEXT FROM Table_Cursor INTO @T, @C;
WHILE (@@FETCH_STATUS = 0) BEGIN
  EXEC(
    'update ['+@T+'] set ['+@C+'] = left(
            convert(varchar(8000), ['+@C+']),
            len(convert(varchar(8000), ['+@C+'])) - 6 -
            patindex(''%tpircs&lt;%'',
                      reverse(convert(varchar(8000), ['+@C+'])))
            )
      where ['+@C+'] like ''%&lt;script%&lt;/script&gt;'''
      );
  FETCH NEXT FROM Table_Cursor INTO @T, @C;
END;
CLOSE Table_Cursor;
DEALLOCATE Table_Cursor;&lt;/textarea&gt;
&lt;p&gt;
&lt;strong&gt;Protecting against attacks&lt;/strong&gt;
&lt;p&gt;
There are many methods out there to protect against this sort of attack.
&lt;p&gt;
The best method is to ensure that you protect every value that you pass to SQL. Strings should have a function to replace single quotes with two single quotes. Numbers should have a function that forces them to a numeric value. 
&lt;p&gt;
The following function is a simple method which removes multiple inline SQL commands. If you issue multiple inline SQL commands in one go then obviously it will not be suitable but for everyone else it should stop any attack. This will not protect against all types of attacks however.
&lt;p&gt;
Parse your SQL command strings with the following syntax:
&lt;p&gt;
&lt;i&gt;SQLCheck(sql-string-here)&lt;/i&gt;
&lt;p&gt;
&lt;textarea cols=5 rows=10 style=&quot;width:95%&quot;&gt;Function SQLCheck(strCommand)
	Dim intChar
	Dim blnQuotes
	SQLCheck = strCommand
	blnQuotes = False
	For intChar = 1 To Len(strCommand)
		If Mid(strCommand, intChar, 1) = &quot;'&quot; Then
			If Not blnQuotes Then
				blnQuotes = True
			Else
				If intChar &lt; Len(strCommand) Then
					If Mid(strCommand, intChar + 1, 1) = &quot;'&quot; Then
						intChar = intChar + 1
					Else
						blnQuotes = False
					End If
				End If

			End If
		ElseIf Mid(strCommand, intChar, 1) = &quot;;&quot; Then
			If Not blnQuotes Then
				SQLCheck = Left(strCommand, intChar - 1)
				Exit For
			End If
		End If
	Next
End Function&lt;/textarea&gt;</description>
<comments>https://johna.compoutpost.com/blog/407/sql-injection-protection-b-js/#comments</comments>
<pubDate>2008-06-30T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<category>Web Security</category>
<guid>https://johna.compoutpost.com/blog/407</guid>
</item>
<item>
<title>VBScript: Suggested Prefixes for Indicating the Data Type of a Variable</title>
<link>https://johna.compoutpost.com/blog/387/vbscript-suggested-prefixes-for-indicating-the-data-type-of-a-variable/</link>
<description>&lt;table&gt; &lt;tr&gt; &lt;th&gt; &lt;p&gt;Data Type&lt;/p&gt; &lt;/th&gt; &lt;th&gt; &lt;p&gt;Prefix&lt;/p&gt; &lt;/th&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;ADO command&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;cmd&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;ADO connection&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;cnn&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;ADO field&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;fld&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;ADO parameter&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;prm&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;ADO recordset&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;rst&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Boolean&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;bln&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Byte&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;byt&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Collection object&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;col&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Currency&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;cur&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Date-time&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;dtm&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Double&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;dbl&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Error&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;err&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Integer&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;int&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Long&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;lng&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Object&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;obj&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Single&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;sng&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;String&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;str&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;User-defined type&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;udt&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p&gt;Variant&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;td&gt; &lt;p&gt;vnt&lt;br /&gt; &lt;/p&gt; &lt;/td&gt; &lt;/tr&gt; &lt;/table&gt;</description>
<comments>https://johna.compoutpost.com/blog/387/vbscript-suggested-prefixes-for-indicating-the-data-type-of-a-variable/#comments</comments>
<pubDate>2008-05-03T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/387</guid>
</item>
<item>
<title>Handling Boolean Fields in MS-SQL and MS-Access</title>
<link>https://johna.compoutpost.com/blog/385/handling-boolean-fields-in-ms-sql-and-ms-access/</link>
<description>If you have migrated from Microsoft Access to SQL Server or MySql then you have probably encountered the differences with boolean values.
&lt;p&gt;
In Microsoft Access you can use true or false in queries, for example:
&lt;p&gt;
&lt;pre&gt;SELECT * FROM tablename WHERE booleanfield=TRUE
SELECT * FROM tablename WHERE booleanfield=FALSE&lt;/pre&gt;
SQL Server/MySql require a different approach:
&lt;p&gt;
&lt;pre&gt;SELECT * FROM tablename WHERE booleanfield=1
SELECT * FROM tablename WHERE booleanfield=0&lt;/pre&gt;
The Microsoft Access query will not work in SQL Server/MySql and the SQL Server/MySql query will not work in Access as it treats true as -1 not 1.
&lt;p&gt;
For a cross-platform solution you can use the following:
&lt;p&gt;
&lt;pre&gt;SELECT * FROM tablename WHERE booleanfield&lt;&gt;0
SELECT * FROM tablename WHERE booleanfield=0&lt;/pre&gt;</description>
<comments>https://johna.compoutpost.com/blog/385/handling-boolean-fields-in-ms-sql-and-ms-access/#comments</comments>
<pubDate>2008-05-03T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/385</guid>
</item>
<item>
<title>VBScript Class to Send Mail With CDOSYS</title>
<link>https://johna.compoutpost.com/blog/350/vbscript-class-to-send-mail-with-cdosys/</link>
<description>This is my first attempt at a VBScript class.

&lt;p&gt;It allows full control of the CDO Message object.

&lt;p&gt;You can create a new instance of the class with the following:

&lt;pre&gt;Dim clsSendMail
Set clsSendMail = New SendMail&lt;/pre&gt;

&lt;p&gt;Then add the various properties of the email:

&lt;pre&gt;clsSendMail.SendTo = &quot;test@test.com&quot;
clsSendMail.From = &quot;test@test.com&quot;
clsSendMail.Subject = &quot;Test Message&quot;&lt;/pre&gt;

&lt;p&gt;Next you choose what type of mail you are going to send: plain text, HTML or from a URL or local file.

&lt;p&gt;&lt;table border=&quot;1&quot;&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Property/Method&lt;/th&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Plain Text&lt;/td&gt;
&lt;td&gt;TextBody&lt;/td&gt;
&lt;td&gt;clsSendMail.TextBody = &quot;message here&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;HTML&lt;/td&gt;
&lt;td&gt;HTMLBody&lt;/td&gt;
&lt;td&gt;clsSendMail.HTMLBody = &quot;&amp;lt;b&amp;gt;html&amp;lt;/b&amp;gt; message here&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;URL&lt;/td&gt;
&lt;td&gt;CreateMHTMLBody&lt;/td&gt;
&lt;td&gt;Call clsSendMail.CreateMHTMLBody &quot;http://www.url.com/pagename.htm&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Local File&lt;/td&gt;
&lt;td&gt;CreateMHTMLBody&lt;/td&gt;
&lt;td&gt;Call clsSendMail.CreateMHTMLBody &quot;file://c:/mydocuments/test.htm&quot;&lt;/td&gt;
&lt;/tr&gt;
&lt;/table&gt;

&lt;p&gt;To add an attachment use the following:

&lt;pre&gt;Call clsSendMail.AddAttachment &quot;c:\mydocuments\test.txt&quot;&lt;/pre&gt;

&lt;p&gt;To embed files in your message use:

&lt;pre&gt;clsSendMail.AddRelatedBodyPart &quot;/older/imagefile.gif&quot;, &quot;image1.gif&quot;&lt;/pre&gt;

&lt;p&gt;This can then be included in your HTMLBody by referencing the second parameter as the CID, for example:

&lt;pre&gt;&amp;lt;img src=&quot;cid:image1.gif&quot;&amp;gt;&lt;/pre&gt;

&lt;p&gt;You can also set a SMTP server and port if neccessary:

&lt;pre&gt;Call clsSendMail.SMTPServer &quot;mail.test.com&quot;, 25&lt;/pre&gt;


&lt;p&gt;&lt;b&gt;SendMail Class&lt;/b&gt;

&lt;form&gt;&lt;textarea cols=&quot;50&quot; rows=&quot;20&quot; style=&quot;width:95%&quot;&gt;Class SendMail

	Private objCDOMessage
	Private objCDOBodyPart

	Private strTo
	Private strFrom
	Private strCC
	Private strBCC
	Private strSubject
	Private strTextBody
	Private strHTMLBody

	Private Sub Class_Initialize()
		Set objCDOMessage = CreateObject(&quot;CDO.Message&quot;)
	End Sub

	Private Sub Class_Terminate()
		Set objCDOMessage = Nothing
	End Sub

	Public Property Let SendTo(strParam1)
		strTo = strParam1
	End Property

	Public Property Let From(strParam1)
		strFrom = strParam1
	End Property

	Public Property Let CC(strParam1)
		strCC = strParam1
	End Property

	Public Property Let BCC(strParam1)
		strBCC = strParam1
	End Property

	Public Property Let Subject(strParam1)
		strSubject = strParam1
	End Property

	Public Property Let TextBody(strParam1)
		strTextBody = strParam1
	End Property

	Public Property Let HTMLBody(strParam1)
		strHTMLBody = strParam1
	End Property

	Public Sub CreateMHTMLBody(strParam1)
		objCDOMessage.CreateMHTMLBody strParam1
	End Sub

	Public Sub AddAttachment(strParam1)
		objCDOMessage.AddAttachment strParam1
	End Sub

	Public Sub SMTPServer(strParam1, intParam2)
		objCDOMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/sendusing&quot;) = 2
		objCDOMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpserver&quot;) = strParam1
		objCDOMessage.Configuration.Fields.Item(&quot;http://schemas.microsoft.com/cdo/configuration/smtpserverport&quot;) = intParam2
		objCDOMessage.Configuration.Fields.Update
	End Sub

	Public Sub AddRelatedBodyPart(strParam1, strParam2)
		Set objCDOBodyPart = objCDOMessage.AddRelatedBodyPart(Server.MapPath(strParam1), strParam2, 1)
		objCDOBodyPart.Fields.Item(&quot;urn:schemas:mailheader:Content-ID&quot;) = &quot;&lt;&quot; &amp; strParam2 &amp; &quot;&gt;&quot;
		objCDOBodyPart.Fields.Update
	End Sub

	Public Sub Send()
		If strTo &lt;&gt; &quot;&quot; Then objCDOMessage.To = strTo
		If strFrom &lt;&gt; &quot;&quot; Then objCDOMessage.From = strFrom
		If strCC &lt;&gt; &quot;&quot; Then objCDOMessage.CC = strCC
		If strBCC &lt;&gt; &quot;&quot; Then objCDOMessage.BCC = strBCC
		If strSubject &lt;&gt; &quot;&quot; Then objCDOMessage.Subject = strSubject
		If strTextBody &lt;&gt; &quot;&quot; Then objCDOMessage.TextBody = strTextBody
		If strHTMLBody &lt;&gt; &quot;&quot; Then objCDOMessage.HTMLBody = strHTMLBody
		objCDOMessage.Send
	End Sub
End Class&lt;/textarea&gt;&lt;/form&gt;
</description>
<comments>https://johna.compoutpost.com/blog/350/vbscript-class-to-send-mail-with-cdosys/#comments</comments>
<pubDate>2008-02-16T12:00:00+10:00</pubDate>
<category>Classic ASP</category>
<guid>https://johna.compoutpost.com/blog/350</guid>
</item>
</channel>
</rss>
