Thursday, September 28, 2006

Setting and Using Cookies in ASP

Cookies are used to store information specific to a visitor to your website. A cookie is stored on the visitor's computer. You can set the expiration date of a cookie. If you set that date for sometime in teh future, the cookie will remain on teh visitor's comuter until that date, or until the visitor manually deletes it. If you don't set an expiration date, a cookie last for the duration of the session.

Know that not everyone surfs with cookies on. Estimates are that about 6-10% of people surf with cookies off. If you relay on cookies, you're web site won't work right for these people. Cookies are a very common technology though and almost every site uses them. Still, you might want to check to see if your visitor has cookies enabled before you use them (which is a more complicated process than you might think).

Creating an ASP cookie:
Response.Cookies("FirstName") = "John"
This example creates a cookie named FirstName that stores the value 'John'.

Now that you've stored it, how do you read it? Easy:
If you want, you can assign the value of the cookie to a variable so you can use it without having to call the request object each time
Dim FName
FName = ""
FName = Request.Cookies("FirstName")
If you want the cookie to last longer than the session, you can set an expiration date. Here's a cookie that lasts 10 days:

Response.Cookies("FirstName") = "John"
Response.Cookies("FirstName").Expires = Date() + 10
You can also set a cookie to last until a specific date:
Response.Cookies("FirstName") = "John" 
Response.Cookies("FirstName").Expires = #December 31,2009#
With the previous examples, I've only stored one value to the cookie. But cookies can hold more than one. You can make a cookie array or collection
Response.Cookies("Name")("FirstName") = "John"
Response.Cookies("Name")("MiddleName") = "Samuel"
Response.Cookies("Name")("LastName") = "Smith"
Response.Cookies("Name").Expires = Date() + 365
You address an array or collection item just like you do a single cookie
would show "John" on the screen.

Now go bake some cookies!

Tuesday, September 26, 2006

SQL: Select Distinct with Most Recent Date

I'm going to simplify it, but let's start here: suppose you have a database that keeps track of patients who show up to their doctor appointments. In that database, you have a table called AppointmentsKept; in that table you have two columns: Name and Date.

Name = Patient Name
ApptDate = Date of Appointment

So if a patient has shown up to five appointments, his or her name will be in there five times with five different dates (one for each appointment). How can you get out each name only once, along with the most recent appointment date?

If you try
SELECT DISTINCT Name, ApptDate from AppointmentsKept ORDER BY AppDate DESC
you end up getting each name listed multiple times, once for each date because each appointment date is different (distinct).

Same things happens if you try
SELECT Name, ApptDate from AppointmentsKept GROUP BY Name, ApptDate ORDER BY AppDate DESC
What you need to do is reduce ApptDate down to a distinct value as well. Here's what I ended up with:
FROM AppointmentsKept ORDER BY MAX(ApptDate) DESC
The result is each name only once along with the most recent date for that name.

Added 10/6/06
A reader sent in another suggested method for selecting Distinct with the most recent date:
select Name, ApptDate 
from AppointmentsKept
group by Name
having AppDate = max(AppDate)

Monday, September 25, 2006

Geek Babe Monday

Tricia Helfer is best know for her role as Number 6 on SciFi's Battlestar Galactica.
Tricia Helfer Battlestar GalacticaTricia Helfer Battlestar Galactica
Helfer was born in Stettler County, Alberta and raised on her family's grain farm. At the age of 17, while standing in line at a local movie theatre, she was discovered by modelling agency scout Kelly Streit. Her first leading role was portraying Farrah Fawcett in Behind the Camera: The Unauthorized Story of 'Charlie's Angels'. You can also see her in three upcoming movies: The Green Chain, Spiral, and The Genius Club.

Sunday, September 24, 2006

Manipulating Strings in Classic ASP with Left, Mid, and Right

String manipulation is straightforward in classic ASP using the Left(), Mid(), and Right() functions.

Left() returns the number of specified characters from the left side of a string. It's formatted as Left(string, length). Example:
Left("one two three four five",3)
would return "one" (the left 3 characters).

Mid is a little more complex. It returns the number of characters specified from the starting point specified. It's formatted as Mid(string, start, length). Note that a length variable is optional; if omitted, Mid it will get the remaining character in the string from the starting point (just like a Right()). Example:
Mid("one two three four five",4,3)
would return "two" (start at character 4 and get the next 3 characters.

Right() return the number of characters specified from the right side of the string. It's formatted as Right(string, length.)xample:
Right("one two three four five",4)
would return "five" (the right 4 characters).

By using Left(), Mid(), and Right() in combination with Instr(), you should be able to get any peice of any string you need.

Friday, September 22, 2006

How to Send Email in ASP from Windows Server 2003

Sending an email from a web page in ASP on a Windows 2003 server is easily accomplished. Be aware, however, that this method won't work on Windows NT/2000. In Windows Server 2003, mail is sent using CDOSYS. Windows NT/2000 uses CDONTS, but I'll talk about that in another article.

Here's a simple Windows 2003 example that sends a text email. In this example, I constructed it as though I were grabbing information from a form submission:
Set myMail=CreateObject("CDO.Message")
myMail.Subject = "Sending email with CDO"
myMail.From = ""
myMail.To = ""
myMail.Bcc = ""
myMail.Cc = ""
myMail.TextBody = "This is a message."
set myMail=nothing
You can also send HTML formatted emails:
Set myMail=CreateObject("CDO.Message")
myMail.Subject = "Sending email with CDO"
myMail.From = ""
myMail.To = ""
myMail.HTMLBody = "<h1>This is a message.</h1>"
set myMail = nothing
You can send both a text version and an HTML versions
Set myMail=CreateObject("CDO.Message")
myMail.Subject ="Sending email with CDO"
myMail.From =""
myMail.To =""
myMail.HTMLBody = "<h1>This is a message.</h1>"
myMail.TextBody ="This is a message."
set myMail=nothing
You can include CCs and BCCs:
Set myMail=CreateObject("CDO.Message")
myMail.Subject = "Sending email with CDO"
myMail.From = ""
myMail.To = ""
myMail.Bcc = ""
myMail.Cc = ""
myMail.TextBody = "This is a message."
myMail.HTMLBody = "<h1>This is a message.</h1>"
set myMail=nothing
You can easily mail a web page:
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.CreateMHTMLBody ""
set myMail=nothing
You can send an HTML file:
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.CreateMHTMLBody "file://c:/inetpub/wwwroot/mywebsite/test.htm"
set myMail=nothing
And you can send a mail with an attachment
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.TextBody="This is a message."
myMail.AddAttachment "c:\inetpub\wwwroot\mywebsite\test.txt"
set myMail=nothing
It's not to difficult to have a form that passes the values to your mail object.

Use a properly formatted return address. Many spam filters these days will automatically block emails that don't have a return address. Some block emails where the return address isn't a real address as well.

Wednesday, September 20, 2006

Black Hat SEO: How to get Inbound Links from Authority Sites

In this article I'm going to talk about a black hat SEO method of getting inbound links from authority sites.

If you decide to use the methods and techniques explained below, know that you could incur search engine penalties or even outright banning. I present this information for educational purtposes only, and to assist webmasters who are constructing sites and want to prevent this from happening to them.

It's no secret that inbound liks exert a strong influence on a site's ranking. An inbound link from a well-respected authority site is very valuable, especially when such a site is an .edu or .gov. But getting links from these sites is next to impossible.

Or is it?

HTML injection is the technique of including HTML code when filling out a form. By so doing, it's sometimes possible to get the targeted site to do or display something 'out of the ordinary'. Using HTML injection techniques, unscrupulous individuals can insert code that results in the display of links to other sites, along with some key words.

For the purposes of this example, I'll use a .edu site:
This site uses a search application called WebGlimpse. Glimpse stands for GLobal IMPicit SEarch and is an indexing and query application. At the bottom of the page, you can see the form for entering a search into their WebGlimpse application. While newer versions of Glimpse have been updated to account for HTML injection, there are plenty of sites out there still using older verions.

Here's where HTML injection comes in. Cut and paste the following into the search box, execute the search, and see what happens:
If you URL decode this you get:
What you end up with on the results page is a link to, along with whatever keywords you appended to the end of the search string. Look in the address bar; you'll see that the address contains the search string you just typed in (along with some other stuff):
Trimming the variables results in:
Cut and past this into your browser and you get the search results page directly. So, in theory, you could put this out as a link somewhere, search engine spiders would follow it to the WebGlimpse page, then follow that link to... well, wherever you had it pointing.

Many times the WebGlimpse search isn't readily accessible. In that case, you'll need to play detective to figure out how to build the URL.

Here's an URL decoder/encoder.

Remember - he (or she) who flys above the radar gets shot down.

Tuesday, September 19, 2006

Removing SQL Server Full Text Noise Words from a Search String

Remove SQL Full Text Noise Words

I'm not going to get into the specifics on constructing full text queries (at least not yet). In this article I'm going to tell you the full text noise words and provide a function for stripping them from queries so you don't get an error.

Have you ever gotten this error when executing a search against your full text index:
Microsoft OLE DB Provider for SQL Server error '80040e14' 

Execution of a full-text operation failed. A clause of the query contained only ignored words.
SQL Server Full Text Indexing provides support for sophisticated word and phrase searches. The full text index stores information about words and their location within a given column, This information is used to quickly complete full text queries that search for rows with particular words or combinations of words.

The noise words (assuming you did a standard install of SQL Server 2000) are located at:
\Program Files\Microsoft SQL Server\MSSQL\FTDATA\SQLServer\Config
In that directory, you'll see a bunch of files named noise with different extensions. The extension indicates the language. The English noise files is noise.eng. If you open that file with a text editor, you can see all the noise words (and symbols, like the $ for example). A search containing any of these words or symbols will cause an error.

There are a couple of options here for preventing that error. One is to remove the noise word from the noise file, then rebuild your full text index. I did this for a site where I aggregated video games for price comparison. I needed visitors to be able to search on Playstation 2. Well, the number 2 is in the noise file, so I took it out.

Even if you decide to take some words out of the noise file, you'll still need to prep your search string by removing any noise words that are left. The easiest way to do that is a function. When someone does a search, pass their search phrase into the function and then return the phrase with the noise words stripped out. There are several ways to do this, but here's the method I went with:
Function PrepSearchString(sOriginalQuery)
strNoiseWords = "1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | $ | ! | @ | # | $ | % | ^ | & | * | ( | ) | - | _ | + |
= | [ | ] | { | } | about | after | all | also | an | and
| another | any | are | as | at | be | because | been | before | being | between |
both | but | by | came | can | come | could | did | do | does | each | else | for |
from | get | got | has | had | he | have | her | here | him | himself | his | how |
if | in | into | is | it | its | just | like | make | many | me | might | more |
most | much | must | my | never | now | of | on | only | or | other | our | out |
over | re | said | same | see | should | since | so | some | still | such | take |
than | that | the | their | them | then | there | these | they | this | those |
through | to | too | under | up | use | very | want | was | way | we | well | were |
what | when | where | which | while | who | will | with | would | you | your | a |
b | c | d | e | f | g | h | i | j | k | l | m | n | o | p | q | r | s | t | u | v |
w | x | y | z"

arrNoiseWord = Split(strNoiseWords,"|")

For i = 0 to UBound(arrNoiseWord)
sOriginalQuery = " "&LCase(sOriginalQuery)&" "
sOriginalQuery = Replace(sOriginalQuery," "&Trim(arrNoiseWord(i))&" "," ")
PrepSearchString = Trim(sOriginalQuery)
End Function
How it works:

  • I took all the noise words and put them in one long pipe delimited string
  • Split the string to make an array
  • Loop through the array looking for noise words
  • When I find one, replace it with a space

    Some other considerations:

    In the function above, I added an extra space before and after the pipe. This was to allow the long string to break and fit onto the page. To account for that, I use the Trim command referring to an item in the array. If you build the string without the spaces, you won't need the Trim (though it won't hurt anything).

    I took the original query and put a space on either end. This is to account for a noise word being at either the beginning or the end of the search phrase.

    I also use LCase to put the original query into all lower case. I could do a vbTextCompare, but it was easier for just make the term all lower case.

    Lastly, I trim the original query when assigning it to go back to account for a space being at either end (when the noise word started or ended the query)

    Once you have the noise word free search string, you can build your query. Be aware: if the search query contains noise words only, this returns an empty string. You should for that in your code.
  • Monday, September 18, 2006

    Geek Babe Monday

    Sometimes programming can be so.... boring, so I thought I'd liven up RetroWebDev with a new feature: Geek Babe Monday.

    Every Monday, I'll post a Hot Geek Babe. Don't be shy if you have suggestions for future features!
    Kristanna Loken Terminator 2Kristanna Loken Terminator 2

    Kristanna Loken from Terminator 3, the ScFi Movie Dark Kingdom, BloodRayne, and the upcoming In the Name of the King: A Dungeon Seige Tale (due out in 2007).

    Sunday, September 17, 2006

    ASP Function to Capitalize the First Letter of All Words in a Sentence

    Here's a function you can use that will capitalize the first letter of all words in a sentence. Simply pass in the text string containing the words you want capitalized.

    You send in: "The quick brown fox"
    You get out: "The Quick Brown Fox"

    First call the function:
    YourString="The quick brown fox"
    strCaps = Capitalize(YourString)
    The Function:
    Function Capitalize(X)
    'return a string with the first letter of the word capitalised
    If IsNull(X) Then
    Exit Function
    lowercaseSTR = CStr(LCase(X))
    OldC = " "
    MyArray = Split(lowercaseSTR," ")
    For IntI = LBound(MyArray) To UBound(MyArray)
    For I = 1 To Len(MyArray(IntI))
    If Len(MyArray(IntI)) = 1 Then
    newString = newString & UCase(MyArray(IntI)) & " "
    ElseIf I=1 Then
    newString = newString & UCase(Mid(MyArray(IntI), I, 1))
    ElseIf I = Len(MyArray(IntI)) Then
    newString = newString & Mid(MyArray(IntI), I, 1) & " "
    newString = newString & Mid(MyArray(IntI), I, 1)
    End If
    Next 'IntI
    Capitalize = Trim(newString)
    End If
    End Function

    Tuesday, September 12, 2006

    Archive Calendar for Blogger Blogs

    After I'd gotten numerous posts in my RetroWebDev blog, I noticed that it can be difficult to locate a post after clicking on one of the monthly links under the Archive section.

    It didn't take much research to find a handly script that generates an Archive Calendar for blogger. To see it in action, click on one of the monthly links uder the Archive section on the left.

    With the Archive Calendar, you can click right a specific day to see the post(s) on that day. I like.

    Mucho thanks to whomever created this script.

    ASP Includes Explained

    Include files are external files that you can easily add to any page:
    It's important to note that include files are processed and inserted BEFORE scripts on the page are run. Included files can contain functions, sub-routines, navigational elements, or just about anything else. Include files are at the heart of making efficient ASP based sites, as they allow you to put you code into easily re-usable chunks.

    There are two forms of the include statement: Virtual and File:

    By using Virtual, you can include any file no matter what its location because Virtual starts as the root directory of the site. In contrast, the File statement starts in the CURRENT directory (the same directory as the file containing the Include).

    Example #1
    could include a file from the AAA directory, even if the page with this statement is in the /BBB/ folder.

    Example #2:
    would fail when used in any file not located in the AAA directory.

    Example #3:
    will succeed from any directory on the same level as the AAA directory. It's instructing the include to go up one directory and then into the AAA directory to get the file. However, if the page that contains the include is moved to a different level in the directory structure, the Include statement would fail.

    I almost always use the Virtual format. That way I know I'm starting at the site root. Even if I move the page containing the include to a different directory, it will still work.

    Sunday, September 10, 2006

    SQL to get Records for Last 24 Hours using DateAdd

    One of the applications I wrote is a logging system. One of the requested modifications is that I make it easy for managers to look at entries made in the last 24 hours. Right now, I have hard-coded links for Current Day, Yesterday, Last 7, etc.

    Current Day shows entries made since midnight. Yesterday shows entries made for the previous day. So right now there's no quick way to get the entries for the last 24 hours.

    The solution was simple:
    Select * from Entries where DateAdded >= " & DateAdd("d",-1, Now())
    How it works:

    The VBScript Now() function gets the current date and time. I then use the DateAdd funciton to subtract 1 day. I then get all entries with a DateAdded timestamp great than or equal to resulting date and time.

    Alternately, you could subtract hours:
    Select * from Entries where DateAdded >= " & DateAdd("h",-24, Now())

    DateAdd is pretty nifty.

    DateAdd(datepart, number, date)

    Datepart can be (abbreviation):
    year (yyyy)
    quarter (q)
    month (m)
    day (d)
    week (ww)
    hour (h)
    minute (n)
    second (s)

    1 month from today: DateAdd("m", 1, Now())
    100 years ago: DateAdd("yyyy", -100, Now())
    10 minutes from now: DateAdd("m", 10, Now())
    1 quarter (3 months) ago: DateAdd("q", -1, Now())

    Friday, September 08, 2006

    WWW Versus Non-WWW URLs: Dupe Content and Redirecting

    I'm not real clear on the technical reasons behind it all, but the consensus in the SEO community is that it's detrimental because of duplicate content penalities to have your web site operating on both the www and non-www addresses. Ideally, you should pick one address or the other and have visitors (human and otherwise) who come to the other forwarded using a permanent redirect. So if you choose as your web web address, you should have all visitors to forwarded to

    This is easy enough to do for one page, but how about some handy code that will automatically forward all your pages using a search engine friendly 301 redirect?

    This code that will forward any visitor to the www version of your site, no matter what the entry page. Place this code at the top of every page:

    Dim strDomain, strURL, strQueryString, strHTTPPath,vTempNum

    'Get page domain
    strDomain = LCase(request.ServerVariables("HTTP_HOST"))

    'Check for www
    If Left(strDomain, 3) <> "www" Then
    strHTTPPath = Request.ServerVariables("PATH_INFO")

    'If page is default.asp, send to root
    If right(strHTTPPath, 12) = "/default.asp" Then
    vTempNum = Len(strHTTPPath)-11
    strHTTPPath = Left(strHTTPPath,vTempNum)
    End If

    'If page is index.asp, send to root
    If right(strHTTPPath, 10) = "/index.asp" Then
    vTempNum = Len(strHTTPPath)-9
    strHTTPPath = Left(strHTTPPath,vTempNum)
    End If

    'Set the new URL
    strQueryString = Request.ServerVariables("QUERY_STRING")
    strURL = "http://www." & strDomain & strHTTPPath

    'If any, pass on query string variables
    If len(strQueryString) > 0 Then strURL = strURL & "?" & strQueryString

    '301 Redirect to www version
    Response.Status = "301 Moved Permanently"
    Response.AddHeader "Location", strURL
    End If
    Likewise, here is code that will redirect to the non-www version:

    Dim strDomain, strURL, strQueryString, strHTTPPath,vTempNum

    'Get Page domain
    strDomain = lcase(request.ServerVariables("HTTP_HOST"))

    'Check for www
    If Left(strDomain, 3) = "www" Then
    'Change to non-www version
    vTempNum = Len(strDomain)-4
    strDomain = Right(strDomain,vTempNum)
    strHTTPPath = Request.ServerVariables("PATH_INFO")

    'If page is default.asp, send to root
    If right(strHTTPPath, 12) = "/default.asp" Then
    vTempNum = Len(strHTTPPath)-11
    strHTTPPath = Left(strHTTPPath,vTempNum)
    End If

    'If page is index.asp, send to root
    If right(strHTTPPath, 10) = "/index.asp" Then
    vTempNum = Len(strHTTPPath)-9
    strHTTPPath = Left(strHTTPPath,vTempNum)
    End If

    'Set new URL
    strQueryString = Request.ServerVariables("QUERY_STRING")
    strURL = "http://" & strDomain & strHTTPPath

    'If any, pass on query string variables
    if len(strQueryString) > 0 Then strURL = strURL & "?" & strQueryString

    '301 redirect to non-www version
    Response.Status = "301 Moved Permanently"
    Response.AddHeader "Location", strURL
    End If

    Thursday, September 07, 2006

    Scraping Search Engines for Page Content

    It's no secret that optimized page content can help you rank better in organic search engine results. While page content is not the deciding factor, it's stil important, especially for long tail search terms. No matter what your page content, you're probably not going to be able to rank well for the term 'dvd player' (or any other exceptionally competetive term). But you might be able to rank on a long tail term such as 'panasonic portable dvd player model 123ABCxyz'. For such a long tail phrase, optimized page content can help.

    But how to get the content? Well, you could write it. Or buy it. Or... scrape it from somewhere else.

    If you chose the scraping solution, I highly recommend that you have some original content on the page. Write a capsule review, or your own description, or anything else that likely doesn't exist on some other site (until, of course, someone scrapes it).

    The following process will step you through scraping content from a search engine and adding it to your page.

    WARNING: Implementing these techniques could very well get you banned from the search engines!

    1. Decide on the keyword you want to generate content for. For this example, I'll use the fictitious Panasonic DVD model from above.

    2. Decide how many search engines you're going to scrape content from. For this example, I'll use 3: MSN, Yahoo, and Gigablast.

    3. Since I'm using 3 search engines, I generate a random number between 1 and 3.

    4. Now pass the number into a page scraping function to go out and get the search results for that phrase from the search engine. The way you might do it is pass the number and keyword into the function:
    strContent = ScrapeContent(intRandNum,"panasonic portable dvd player model 123ABCxyz')
    Then, in the function, have a Case statement to assign the url based on the random number:
    Function ScrapeContent(TheEngine, TheTerm)
    Select Case TheEngine
    Case 1
    URL = ""&TheTerm&""
    Case 2
    URL = ""&TheTerm"&"
    Case 3
    URL = ""&TheTerm&""
    End Select

    Set xmlObj = Server.CreateObject("MSXML2.ServerXMLHTTP")

    xmlObj.Open "GET", url, true
    Call xmlObj.Send()

    On Error Resume Next

    If xmlObj.readyState <> 4 Then xml.waitForResponse 3

    If Err.Number <> 0 Then
    ScrapeContent = "There was an error retreiving the remote page"
    If (xmlObj.readyState <> 4) Or (xml.Status <> 200) Then
    ScrapeContent = "Problem communicating with remote server..."
    ScrapeContent = xmlObj.ResponseText
    End If
    End If
    End Function
    5. In the above example. we know have the remote content assigned to a variable named strContent. Parse that string to strip out eveything between the body tags:
    strContent = Mid(strContent,Instr(strContent,"<body>")+6,Instr(strContent,"</body>"))
    6. Now that you have the body content, replace all the breaks with a space; this is because words might run to gether otherwise:
    strContent = Replace(strContent,"<br>"," ")
    7. There are some extraneous words that have no relevancy to your search term that you're probably going to want to strip out as well. For example, Yahoo has additional links that follow the listing: 'Cached', 'More from this site', 'Save' etc. I recommend customizing a function to strip out all the non keyword related carp that clutters the search results you just scraped.

    8. Now you have fairly clean copy relevant to your keyword, the last thing to do strip out the HTML.

    The end result: a big chunk of text directly relevant to your keyword.

    There's a few things you can do with it: plop it right on the page (not recommended), hide it in a div, or - my recommendation - hide it in a div and reverse cloak it, so that only search engines can see it. Hopefully your pages will start climbing higher in the organic results.

    Leverage those favorable results quickly! Sooner or later you'll find your site banned, either because the spiders got smarter or a competitor reported you.

    Good luck!

    Saturday, September 02, 2006

    CSS Overflow Property

    I'm working on a site where visitors will be able to upload their own images, which I will then be displaying. In order to keep page formating, I'll be automatically resizing the images to 125 pixels in height. The image itself will be placed in a 125x125 div. But what if it's wider than 125? I wanted it to be cropped so as not to mess up the page format. Enter the overflow property
    <div style="height:125px;width:125px;overflow:hidden;">
    Overflow has other parameters as well:

    overflow: auto - This will insert a scrollbar - horizontal, vertical or both only if the content in the block requires it. For practical purposes, this is probably the most useful for creating a scrolling area.

    overflow: scroll - This will will insert horizontal and vertical scrollbars. They will become active only if the content requires it.

    overflow: visible - This will cause the block to expand to view the content.

    overflow: hidden - This forces the block to only show content that fits in the block. Other content will be clipped and not hidden with no scrollbars.

    Friday, September 01, 2006

    How to Strip out HTML with an ASP Reg Exp Function

    Ever wanted an easy way to strip out all the HTML from a string? There are a variety of reasons you might want to do this. Maybe you offer a mail page feature and want to strip out the HTML to send a text email. Or maybe you're a Black Hat SEO Sith Master and are scraping content from millions of pages to build an AdSense empire!

    In any case, here's an easy way, using regular expressions, to strip out all the HTML from a string.

    This function accepts a string input (the string whose HTML tags are to be stripped). The regular expression pattern <(.|\n)+?> is used to get all matches of < and > characters with at least one character in-between. The Replace method of the regular expression object is then used to replace all instances with an empty string (""). Finally, all remaining < and > signs are replaced with their respective HTML encoded forms.

    Something to consider: if you strip out the <BR> tags and you're re-displaying the string, it will all run together. The fix there would be to do a straight replace BEFORE sending the string to the stripHTML Function:
    TheString = Replace(TheString,"<BR>","{}",1)
    This replaces all the Break tags (those in both upper and lowercase) with {} right next to each other. Then send TheString to the StripHTML Function:
    Function stripHTML(strHTML)
    Dim objRegExp, strOutput
    Set objRegExp = New Regexp

    objRegExp.IgnoreCase = True
    objRegExp.Global = True
    objRegExp.Pattern = "<(.|\n)+?>"

    'Replace all HTML tag matches with the empty string
    strOutput = objRegExp.Replace(strHTML, "")

    strOutput = Replace(strOutput, "<", "&lt;")
    strOutput = Replace(strOutput, ">", "&gt;")

    stripHTML = strOutput 'Return the value of strOutput

    Set objRegExp = Nothing
    End Function
    Now you have a string with all the HTML stripped out and all the Break tags replace with {}. Now do one last Replace to put the Break tags back in:
    TheString = Replace(TheString,"{}","<BR>",1)

    That's it!