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:
Request.Cookies("FirstName")
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")
Response.write(FName)
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
Response.write(Request.Cookies("Name")("FirstName"))
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:
SELECT DISTINCT Name, MAX(ApptDate)
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)
Thanks!

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@mydomain.com"
myMail.To = "someone@somedomain.com"
myMail.Bcc = "someoneelse@somedomain.com"
myMail.Cc = "someoneelse2@somedomain.com"
myMail.TextBody = "This is a message."
myMail.Send
set myMail=nothing
You can also send HTML formatted emails:
Set myMail=CreateObject("CDO.Message")
myMail.Subject = "Sending email with CDO"
myMail.From = "mymail@mydomain.com"
myMail.To = "someone@somedomain.com"
myMail.HTMLBody = "<h1>This is a message.</h1>"
myMail.Send
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@mydomain.com"
myMail.To ="someone@somedomain.com"
myMail.HTMLBody = "<h1>This is a message.</h1>"
myMail.TextBody ="This is a message."
myMail.Send
set myMail=nothing
You can include CCs and BCCs:
Set myMail=CreateObject("CDO.Message")
myMail.Subject = "Sending email with CDO"
myMail.From = "mymail@mydomain.com"
myMail.To = "someone@somedomain.com"
myMail.Bcc = "someoneelse@somedomain.com"
myMail.Cc = "someoneelse2@somedomain.com"
myMail.TextBody = "This is a message."
myMail.HTMLBody = "<h1>This is a message.</h1>"
myMail.Send
set myMail=nothing
You can easily mail a web page:
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.From="mymail@mydomain.com"
myMail.To="someone@somedomain.com"
myMail.CreateMHTMLBody "http://www.w3schools.com/asp/"
myMail.Send
set myMail=nothing
You can send an HTML file:
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.From="mymail@mydomain.com"
myMail.To="someone@somedomain.com"
myMail.CreateMHTMLBody "file://c:/inetpub/wwwroot/mywebsite/test.htm"
myMail.Send
set myMail=nothing
And you can send a mail with an attachment
Set myMail=CreateObject("CDO.Message")
myMail.Subject="Sending email with CDO"
myMail.From="mymail@mydomain.com"
myMail.To="someone@somedomain.com"
myMail.TextBody="This is a message."
myMail.AddAttachment "c:\inetpub\wwwroot\mywebsite\test.txt"
myMail.Send
set myMail=nothing
It's not to difficult to have a form that passes the values to your mail object.

Tip:
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.

DISCLAIMER
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:
http://cluster.space.swri.edu/
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:
%22%3E%3Ca+href%3Dhttp%3A%2F%2Fwww.widgets.com%3EGreat+Widgets%3C%2Fa%3E+widgets+are+great
If you URL decode this you get:
"><a+href=http://www.widgets.com>Great+Widgets</a>+widgets+are+great
What you end up with on the results page is a link to www.widgets.com, 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):
http://cluster.space.swri.edu/cgi-bin/webglimpse/public/web?query=
%2522%253E%253Ca%2Bhref%253Dhttp%253A%252F%252Fwww.widgets.com%253EGreat%2B
Widgets%253C%252Fa%253E%2Bwidgets%2Bare%2Bgreat
&errors=0&age=&maxfiles=50&maxlines=30
Trimming the variables results in:
http://cluster.space.swri.edu/cgi-bin/webglimpse/public/web?query=
%2522%253E%253Ca%2Bhref%253Dhttp%253A%252F%252Fwww.widgets.com%253E
Great%2BWidgets%253C%252Fa%253E%2Bwidgets%2Bare%2Bgreat
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))&" "," ")
Next
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
    Else
    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) & " "
    Else
    newString = newString & Mid(MyArray(IntI), I, 1)
    End If
    Next
    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.