Welcome to my blog! Feel free to post comments.
- Andrew


Visit Coldfusion Community


<< January, 2007 >>
SMTWTFS
123456
78910111213
14151617181920
21222324252627
28293031
Search Blog

Categories
Archives
RSS


Powered by
BlogCFM v1.14

Cookies empty after <cflocation> (and similar)
29 January 2007

I just ran into an interesting issue.  I've actually seen this issue before, and fixed it before, but have never documented it before.

Here is the issue:

You have a page that initiates a session and maybe sets session variables.  At the end of the page, you <cflocate> somewhere else.

On that "somewhere else" page, the session variable will not be set (not even defined).  This only seems to happen in some browsers (it seems [maybe] to be slower or older computers? -- haven't been able to confirm this)

In order to really understand this, you need to know that when you set any cookies (and sessions set several -- most notably the CFID and CFTOKEN), the server sends a header to the page to set the cookie value.  That is main way your browser can know to set a cookie.  (you can also set cookies using javascript, however this is not applicable to the current discussion)

So, when you have a page that initiates a session or sets a session variable, it needs to send something to your browser in order to include that cookie header.  Make sense?  You can't get the cookie header if you get no web page from the server!

Taking that logic a step further with the above situation: If you have a page that DOES NOT OUTPUT anything to the user (i.e. a form action page is the most common I should think...), and you are setting cookies or initiating sessions, setting session variables, etc. anything that requires cookies.. if you do a cflocation tag before you send anything to your browser, those cookies can get lost, because you send them to a new page, and that page sends its content without the cookie headers.

To fix this, we go back to web 101, and simply use the good old META refresh tag.  Instead of doing a <cflocation>, we output html code with a META refresh where we want to go.  (the key here is the output of page content to the browser, which ensures your cookies are set).

So in this scenario, this code is bad:

<cfset cookie.something = "newvalue">
<cflocation url="some_other_page.cfm">

However, this code is a very suitable fix:

<cfset cookie.something = "newvalue">
<html>
    <head>
        <META HTTP-EQUIV="Refresh" CONTENT="1;URL=some_other_page.cfm">
    </head>
</html>

In summary, sometimes (and usually at the worst time), cookie values will not be set properly if you do not output any content to the browser, usually in combination with a <cflocation> tag.  This can be fixed by forcing output of html content to browser and using a meta refresh to redirect the user to the appropriate URL.  The same can be done with Javascript if you feel more comfortable with that.

Hope this helps somebody.  ciao

Posted by aschwabe at 11:30 AM | Link | 1 comment


CF United 2007
15 January 2007

Well i've been invited to come back to CF United again in 2007 to speak.  This year I will be talking about XML and specifically about ColdFusion's built in functions for creating and manipulating XML constructs.

If you are a ColdFusion developer, this really is a fantastic conference and no matter what skill level you are, you always learn a ton of new things.

I personally am looking forward to learning more about integrating CF and Flex 2.  For more info and registration info, click the nice picture below.

CFUNITED
Posted by aschwabe at 5:40 PM | Link | 0 comments

Flex 360: I'm Headed to San Jose in March
14 January 2007

In case you haven't picked up on the excitement about Flex 2 yet, its worth checking out.  Go to www.flex.org and see what its all about.  In my efforts for self improvement, I have signed up to go to flex360 in San Jose California March 5-7 2007.

Last I checked, it was filling up like crazy, so if you wants it... you better register post haste.

Posted by aschwabe at 12:00 AM | Link | 0 comments

Bad day

Sometimes a work day just sucks.  Thats when you need to be a procrastinator, and blast nazis in Call of Duty 2.  Just my $0.02.  Oh, and get a bmw motorcycle.

Note the december calendar even though it is January....

Posted by aschwabe at 12:00 AM | Link | 0 comments

vchkrcpt.sh - my kick butt script for vpopmail
12 January 2007

This script is for those who have build a qmail+vpopmail server (including qmr and some of the other distributions).

This script also requires the vchkrcpt patch, which you may need to mangle to work with your config.  It seems that this patch fell through the cracks and didn't get into most of the main distributions.  It is a terrible shame, because almost all default qmail setups have a severe security issue:  they accept all email for a domain, and if an account doesn't exist, they bounce it later.  This is terrible, what with the age of SpamCop and other "spam trap" and realtime black hole lists out there. 

Ponder this batman:  Somebody spams you at your domain with a bad recipient address like not_there@yourcompany.com and forges the sender to be some spamtrap like qazwsx123@spamcop.net.  If your server accepts all mail for "yourcompany.com" and then bounces it later, then it will accept this message.  It will then generate a bounce message, which it sends to the forged email address.  In this scenario, somebody else spammed you, but you sent email to a spam trap, which often automatically blacklists your mail server.  nice, huh...

SO... the point of that little bunny trail is that you shouldn't accept email when it is addressed to a non-existant mailbox.  Thats where vchkrcpt comes in.  Patch your qmail so you can use it (not covered here), and once you can support it, use my script.

And here it is in all its goodness and tested wonder.  Quick warranty and disclaimer:  don't be dumb.  edit this for your server and tested it on a non-production server.  If you don't do these things, its nobody's fault but your own for crashing your mail server.

#!/bin/bash
#
# Andrew's kick-ass chkrcpt script for qmail+vpopmail
# Author: aschwabe@gmail.com
#
# This script makes qmail check for the existance of a user before email is accepted.
# Will check vpopmail accounts, and look for .qmail* files to determine real accounts.
# Logs all checks in the /var/log/maillog, and then refers to it to throttle spammers.

set -- $RECIPIENT
set -- $SENDER
MY_TEST=""

#echo `whoami`

if [ "$RECIPIENT" == "" ]; then
    # uncomment these lines and the "echo" lines throughout to test at the command line
    #echo "sender:"
    #read SENDER
    #echo "recipient:"
    #read RECIPIENT
    exit 100
fi

# email sender addresses explicitly allowed:
allowed[1]="override@yourcompany.comiexp.com"
for index in 1 2
do
  if [ "$SENDER" == "${allowed[index]}" ]; then
        /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : ok (sender explicitly allowed: ${allowed[index]})"
        exit 0
  fi
done

USERPART=`echo "$RECIPIENT" |cut -d@ -f1`
DOMAIN=`echo "$RECIPIENT" |cut -d@ -f2`

# We reject any emails with more than one @ sign
THIRDPART=`echo "$RECIPIENT" |cut -d@ -f3`
if [ "$THIRDPART" != "" ]; then

  #echo "Invalid username - multiple or no @ signs"
  /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : illegal username"
  exit 100

fi
# We reject any emails with ! in the name
EXCL_CHECK=`echo $USERPART |grep '!' >/dev/null 2>&1; echo $?|grep "1" > /dev/null 2>&1 ; echo $?`
if [ "$EXCL_CHECK" == "1" ]; then

  #echo "Invalid username"
  /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : illegal username"
  exit 100

fi

# We reject any emails with a percent sign in the name
PERCENT_CHECK=`echo $USERPART |grep '%' >/dev/null 2>&1; echo $?|grep "1" > /dev/null 2>&1 ; echo $?`
if [ "$PERCENT_CHECK" == "1" ]; then

  #echo "Invalid username"
  /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : illegal username"
  exit 100

fi

# We reject if this sender has had 3 or more bad recipients recently
if [ "$SENDER" != "" ]; then

    SPAMMER_CHECK=`tail -n300 /var/log/maillog|grep vchkrcpt|grep $SENDER |grep 'bounce-no-mailbox'|wc -l`
    #echo 'result of spammer check:'
    #echo $SPAMMER_CHECK

    if [ "$SPAMMER_CHECK" -gt "2" ]; then
        #echo "Too many invalid recipients.  Mail will not be accepted."
        /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : spammer=bounce-no-mailbox"
        exit 100
    fi
fi

# check for valid account
MY_TEST=`/home/vpopmail/bin/vuserinfo -d $RECIPIENT |/usr/bin/head -n1`

if [ "$MY_TEST" == "" ] || [ "${MY_TEST:0:7}" == "no such" ]; then

  # it wasn't a real pop user, so check if its an alias
  MY_TEST=`/home/vpopmail/bin/valias $RECIPIENT|/usr/bin/head -n1`

  # if the address has a dash in it, re-build a default alias address
  USER_ALIAS_CHECK=`echo $USERPART |grep '\-' >/dev/null 2>&1; echo $?|grep "1" > /dev/null 2>&1 ; echo $?`
  if [ "$USER_ALIAS_CHECK" == "1" ]; then
    ALIAS_USERPART=`echo $USERPART | cut -d - -f1`
    ALIAS_USERPART=$ALIAS_USERPART"-default"
    ALIAS_RECIPIENT=$ALIAS_USERPART"@"$DOMAIN
    MY_TEST2=`/home/vpopmail/bin/valias $ALIAS_RECIPIENT|/usr/bin/head -n1`
  else
    MY_TEST2=""
  fi

  if [ "$MY_TEST" != "" ]; then

    # this is a valid alias
    #echo "valid alias"
    /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : alias ok"
    exit 0

  elif [ "$MY_TEST2" != "" ]; then

    # this is a valid user alias
    #echo "valid user-alias"
    /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : user-alias ok"
    exit 0

  else

    # look for a .qmail-default file, and see it if has a real account in it

    DEFAULT_RECIPIENT="default@"$DOMAIN
    #echo "default recipient = $DEFAULT_RECIPIENT"

    DEFAULT_BOUNCE=`/home/vpopmail/bin/valias $DEFAULT_RECIPIENT | /usr/bin/head -n1|grep bounce-no-mailbox \
        >/dev/null 2>&1; echo $? |grep "1" > /dev/null 2>&1 ; echo $?`
    #echo "DEFAULT_BOUNCE result = $DEFAULT_BOUNCE"

    if [ "$DEFAULT_BOUNCE" == "1" ]; then
      #echo ".qmail-default = bounce"
      #echo "invalid recipient"
      /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : catchall=bounce-no-mailbox"
      exit 100
    fi
    DEFAULT_DELETE=`/home/vpopmail/bin/valias $DEFAULT_RECIPIENT | /usr/bin/head -n1|grep ' delete' \
        >/dev/null 2>&1; echo $? |grep "1" > /dev/null 2>&1 ; echo $?`
    #echo "DEFAULT_DELETE result = $DEFAULT_DELETE"

    if [ "$DEFAULT_DELETE" == "1" ]; then
      #echo ".qmail-default = delete"
      #echo "invalid recipient"
      /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : catchall=delete"
      exit 100
    fi

    MY_TEST=`/home/vpopmail/bin/valias $DEFAULT_RECIPIENT | /usr/bin/head -n1`
    #echo "ALIAS DEFAULT result = $MY_TEST"

    if [ "$MY_TEST" == "" ]; then

      #echo "invalid recipient (no default alias)"
      /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : catchall=none"
      exit 100

    else

      #echo "valid recipient (.qmail-default)"
      /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : catchall=ok"
      exit 0

    fi

  fi
else

  #echo "valid mailbox"
  /usr/bin/logger -p mail.info -t vchkrcpt "mail from <$SENDER> to <$RECIPIENT> : account ok"
  exit 0

fi

 

Posted by aschwabe at 6:20 PM | Link | 0 comments

Server side HTTP Post using JSP
11 January 2007

Ok, so I use a rapid application development technology (ColdFusion or PHP) most of the time because customers demand such quick turnaround.  This time I needed to go back to goold old Java and do some integration.

Our email list management service (Sound-Off 3) manages people's email lists and lets them schedule mailings, etc.  I needed to integrate a website build on JRun (using Java Server Pages aka jsp) so that when people register, it relays the info to Sound-Off 3.

In ColdFusion, you can easily do this with a CFHTTP tag.  In JSP it is a little more involved.  My struggle is your benefit, b/c here is the code that does it in JSP.

This code will do an HTTP POST from the WEB SERVER to the remote site, all behind the scenes on the server.  The "parameters" string contains the form values that will be sent to the remove server.  Note the leading/trailing &'s and that the form values must be URL encoded.

try
{
    String stuff = null;
    String pagecontent = "";
    String parameters = "&message=hello+world&";
    java.net.URL url = new java.net.URL(http://www.yourhost.com/page.cfm);
    java.net.HttpURLConnection conn = (java.net.HttpURLConnection)url.openConnection();
    conn.setRequestMethod("POST");
    conn.setRequestProperty("Content-Length", "" + Integer.toString(parameters.getBytes().length));
    conn.setRequestProperty("Content-Language", "en-US");
    conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
    conn.setDoInput(true);
    conn.setDoOutput(true);
    conn.setUseCaches(false);
    conn.setAllowUserInteraction(true);
    java.io.DataOutputStream printout = new java.io.DataOutputStream (conn.getOutputStream ());
    printout.writeBytes (parameters);
    printout.flush ();
    printout.close ();
    java.io.BufferedReader in = new java.io.BufferedReader(new java.io.InputStreamReader(conn.getInputStream()));
    while ((stuff = in.readLine()) != null)
    {
         pagecontent += stuff;
    }
    in.close();

    %>success! <%
}
catch (Exception e)
{
    %>error!<%
}
%>

And thats it!   You can (and should) do further error checking by examinging the contents of "pagecontent" which will have the html code returned from remote website.

Have fun...

Posted by aschwabe at 12:00 AM | Link | 0 comments