This is a discussion on ColdFusion Tips & Tricks within the ColdFusion Programming forums, part of the Web Development category; Access is Restricted to this ColdFusion Service. This copy of Allaire ColdFusion is licensed for use by a single user ...
| |||||||
| Register | FAQ | Members List | Calendar | Mark Forums Read |
| |||
| Access is Restricted to this ColdFusion Service. This copy of Allaire ColdFusion is licensed for use by a single user only. The ColdFusion server is currently configured to accept requests exclusively from IP address 127.0.0.1. (Your request was made from xxx.xxx.xx.xx.) The ColdFusion engine must be stopped and restarted to reset the permitted IP address. ------ Ever wonder how the single-user version of Cold Fusion determines which IP address it would work for? This has baffled many programmers (myself included) in trying to figure it out. It doesn't clearly state how it works but a hint is provided in the error message: "The ColdFusion engine must be stopped and restarted to reset the permitted IP address." The single-user version of the Cold Fusion server will only respond to the IP address that sends the first request to it. If you have an application on your computer that you want to demonstrate from another computer, restart the Cold Fusion server. As long as you do not run any templates on your computer, you should be able to execute it fine from any other computer. |
| Sponsored Links |
| |||
| Allowing commas in a numeric CFINPUT text field Normally, you can not enter numbers with a comma in a numeric CFINPUT field, the Javascript function generated by Cold Fusion will reject it. Nice thing about Javascript, you can define a function more than once without it going kablooie all over your nice computer. The function defined last is the one used. Here's an example. I copy-n-pasted the generated Javascript into the template and added a comma to the list of approved numeric characters. Code:
<CFFORM name="MyForm">
<cfinput type="Text" name="i_value" validate="float" message="Bad value! Bad!">
</cfform>
<script language="Javascript">
// Override the numeric validation generated by Cold Fusion
function _CF_checknumber(object_value)
{
//Returns true if value is a number or is NULL
//otherwise returns false
if (object_value.length == 0)
return true;
//Returns true if value is a number defined as
// having an optional leading + or -.
// having at most 1 decimal point.
// otherwise containing only the characters 0-9.
var start_format = " .+-0123456789";
// Comma added to allowed characters
var number_format = " .,0123456789";
var check_char;
var decimal = false;
var trailing_blank = false;
var digits = false;
//The first character can be + - . blank or a digit.
check_char = start_format.indexOf(object_value.charAt(0))
//Was it a decimal?
if (check_char == 1)
decimal = true;
else if (check_char < 1)
return false;
//Remaining characters can be only . or a digit, but only one decimal.
for (var i = 1; i < object_value.length; i++)
{
check_char = number_format.indexOf(object_value.charAt(i))
if (check_char < 0)
return false;
else if (check_char == 1)
{
if (decimal) // Second decimal.
return false;
else
decimal = true;
}
else if (check_char == 0)
{
if (decimal || digits)
trailing_blank = true;
// ignore leading blanks
}
else if (trailing_blank)
return false;
else
digits = true;
}
//All tests passed, so...
return true
}
</script> |
| |||
| Automatic FTP Utility This utility will allow you to transfer many files from many servers at the click of a button based on command files that gives a list of servers and files to transfer. In the zip file listed below, there are two files - ftp.cfm and test.ftp ftp.cfm is the FTP utility and test.ftp is an example command file. Contents of test.ftp: Code: ; FTP Transfer File ; ; These command files must have a .FTP file extension ; ; Commands: ; open ; Syntax: open [server:port] [UserID] [Password] ; ; close ; Syntax: close ; ; dl (download) ; Syntax: dl [protocol (B=Binary, A=ASCII)] [full directory and filename on remote server] [full directory path ONLY local server] ; ; ul (upload) ; Syntax: ul [method (B=Binary, A=ASCII)] [full directory and filename on local server] [full directory path ONLY on remote server] ; ; email (Email results) ; Syntax: email [email address] ; ; The Local and Remote file names for Uploading and Downloading can be dynamic using CF functions. ; Example: ; dl B /apps/www/logs/archive/apache.logs.#DateFormat(Now(),"mm.dd.yy")#.tar C:/Internet/Webalizer/iwof2.tar ; ; The remote file name will be evaluated out to /apps/www/logs/archive/apache.logs.12.22.04.tar ; ; WARNING: File names are CaSe SeNsAtIvE!!! Even if it's Windows, this tool expects the case to match. While transfers will still work ; otherwise, the transfer information will only display if it matches. ; ; Note: ";" identifies a comment line, don't use it for your actual command list. ; ; ====================================================================================================================================== ; ; Example of downloading a static text file with ASCII protocol open ftp.mozilla.org:21 anonymous anonymous dl A /pub/mozilla.org/README C:\ReadMe.txt close |
| |||
| Automatically purging old generated files If your website generates reports on the fly and makes them available for the user to download by saving them to a temp directory on the server, it would be a good idea to delete old files to prevent all your disk space from being chewed up. The program listed below will purge files older than a specified number of days for an unlimited number of directories that you can specify. If you schedule it to be executed every day, you can rest assured that your temp directory doesn't get stuffed and a surprise "Out of Disk Space" error doesn't occur. Example HTML/CFML code: Code: <!---
Directory Purge, by John Bartlett
john.bartlett@attws.com
Ver 1.01
--->
<cfsetting enablecfoutputonly="Yes">
<!---
The Directory array contains a list of directories to scan and how many days old the files can be before they are purged.
If you set the history value to -1, all files will be deleted. Note that this is the number of days from the current time.
If you specify a history of 0 (kill files over 24 hours old), a file that was generated two hours ago will not be deleted.
<CFSET Directory[1][2]=2> Files over 2 days old (or 24 hours) will be deleted
<CFSET Directory[1][2]=3> Files over 3 days old (or 72 hours) will be deleted
--->
<CFSET Directory=ArrayNew(2)>
<CFSET Directory[1][1]="C:\WINNT\TEMP">
<CFSET Directory[1][2]=7>
<CFLOOP index="loop" from="1" to="#ArrayLen(Directory)#">
<CFIF Directory[loop][1] CONTAINS "/">
<CFSET PathChar="/"> <!--- Unix Directory --->
<CFELSE>
<CFSET PathChar="\"> <!--- NT Directory --->
</CFIF>
<cfdirectory action="LIST" directory="#directory[loop][1]#" name="dir">
<CFSET kill=0>
<CFSET nokill=0>
<CFSET cantkill=0>
<CFLOOP query="dir">
<CFSET cr=CurrentRow>
<CFIF dir.type[cr] EQ "File">
<CFSET tot=tot + 1>
<CFSET Age=DateDiff("d",dir.DateLastModified[cr],Now())>
<CFIF Age GT Directory[loop][2]>
<CFTRY>
<cffile action="DELETE" file="#Directory[loop][1]##PathChar##dir.Name[cr]#">
<CFOUTPUT>#dir.name[cr]# is #Age# days old, deleting<br>#Chr(10)#</CFOUTPUT>
<CFSET kill=kill+1>
<CFCATCH Type="Any">
<CFOUTPUT>#dir.name[cr]# is #Age# days old, *** UNABLE TO DELETE ***<br>#Chr(10)#</CFOUTPUT>
<CFSET cantkill=cantkill + 1>
<CFSET nokill=nokill + 1>
</CFCATCH>
</CFTRY>
<CFELSE>
<CFSET nokill=nokill + 1>
</CFIF>
</CFIF>
</CFLOOP>
</CFLOOP>
<CFOUTPUT>#tot# files total, #kill# files deleted, #nokill# files skipped, unable to delete #cantkill# files</CFOUTPUT> |
| |||
| Blocking site rippers You spend weeks building a website, pour hours of your life into it, and discovered recently that someone site-ripped all of your generated HTML and published it elsewhere. Now that sucks. Here's a function that will help prevent against site rippers yet allow spiders and normal users to browse unrestricted. The way it works is to count the number of page views per IP address per minute and if that count exceeds a predefined value, block access. Note that if you set the max page hit to 30 and the user browses your site 29 times in a minute on the clock, they won't be blocked unless they view 31 pages in the next minute on the clock. While I understand that this is not ideal, it's a compromise between speed an functionality. Originally, I created a dynamic query that stored the time stamp of every page view. However, when I tried to clean up the query by selecting only records that occurred in the previous x amount of time, the Query of Queries can not properly handle time objects such as those created with the CreateODBCDateTime function. So instead of manually rebuilding the query row for row on every page view, I opted for this method. Example HTML/CFML code: Code: <!---
MaxHits: The maximum number of page views allowed in a given minute
While doing this much work inside an exclusive lock of the application scope is undesireable, it's the
only way to defeat multi-threaded site rippers.
--->
<CFSET MaxHits=30>
<!--- Only check if not identified as a spider, allow most spiders to browse unrestricted (remove if not wanted) http://www.psychedelix.com/agents.html --->
<CFIF ListContainsNoCase(CGI.HTTP_User_Agent,"bot,spider,spyder,agent,altavista,crawl,arachno,24x,seek,search,fetch,deadlink,index,diagem,google") EQ 0>
<CFSET UserIP="IP_" & Replace(CGI.Remote_Addr,".","_","ALL")>
<cflock timeout="30" throwontimeout="Yes" type="EXCLUSIVE" scope="APPLICATION">
<CFIF IsDefined("Application.IPHistory") EQ "No">
<CFSET Application.IPHistory=StructNew()>
<CFSET Application.IPHistory.Cnt=0>
</CFIF>
<CFIF IsDefined("Application.IPHistory.#UserIP#") EQ "No">
<CFSET "Application.IPHistory.#UserIP#"=StructNew()>
<CFSET History=StructNew()>
<CFSET History.TimeStamp=TimeFormat(Now(),"HH:mm")>
<CFSET History.Cnt=0>
<CFELSE>
<CFSET History=Duplicate(Evaluate("Application.IPHistory.#UserIP#"))>
</CFIF>
<CFSET CurrentTimeStamp=TimeFormat(Now(),"HH:mm")>
<CFIF CurrentTimeStamp NEQ History.TimeStamp>
<CFSET History.TimeStamp=CurrentTimeStamp>
<CFSET History.Cnt=0>
</CFIF>
<CFSET History.Cnt=History.Cnt + 1>
<CFSET "Application.IPHistory.#UserIP#"=Duplicate(History)>
<!--- Keep track of the overall page hits for all users and remove IP's that haven't accessed the site in the past 10 minutes --->
<CFSET Application.IPHistory.Cnt=Application.IPHistory.cnt + 1>
<CFIF Application.IPHistory.Cnt GT 1000>
<CFSET Application.IPHistory.Cnt=0>
<CFLOOP index="CurrIP" list="#StructKeyList(Application.IPHistory)#">
<CFIF CurrIP NEQ "CNT">
<CFSET TS=DateFormat(Now(),"mm/dd/yyyy") & " " & Evaluate("Application.IPHistory.#CurrIP#.TimeStamp") & ":00">
<CFIF DateDiff("n",TS,Now()) GT 10>
<CFSET tmp=StructDelete(Application.IPHistory,CurrIP)>
</CFIF>
</CFIF>
</CFLOOP>
</CFIF>
</cflock>
<CFIF History.Cnt GT MaxHits>
<CFOUTPUT>
<h1>Access Denied</h1>
Your access has been temporarly blocked due to excessive access.
</CFOUTPUT>
<CFABORT>
</CFIF>
</CFIF> |
| |||
| Changing form fields in a different frame If you need to change form fields in one frame based of what a user selectes in another frame, here's a basic example on how to do so, all using plain html and Javascript. There are three files: 1. Frames.html Defines the layout of the frames 2. Left.html Creates a dropdown selection box and the Javascript that is used to populate the Right frame 3. Right.html Creates two text fields that are populated by the Javascript in the left frame Simply copy-n-paste these files onto your ISP and jump to Frames.html to see it in action or use it as a guide. Example HTML/CFML code: Code: <!--- Frames.html --->
<frameset cols="50%,*">
<frame name="Left" src="Left.html" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
<frame name="Right" src="Right.html" marginwidth="10" marginheight="10" scrolling="auto" frameborder="0">
</frameset>
<!--- Left.html --->
<html>
<head>
<script language="Javascript1.2">
function PopulateRightForm()
{
// Get the index of the drop-down box
var idx=document.LeftForm.LeftDropdown.selectedIndex;
// Get the value of the selected item of the dropdown box
var n=document.LeftForm.LeftDropdown.options[idx].value;
// Get the text of the selected item of the dropdown box
var t=document.LeftForm.LeftDropdown.options[idx].text;
// Populate the values of the text boxes in the right frame
parent.frames['Right'].document.RightForm.RightText.value=t;
parent.frames['Right'].document.RightForm.RightValue.value=n;
}
</script>
</head>
<body bgcolor="FFFFFF">
<form name="LeftForm">
Select a number:
<select name="LeftDropdown" size="1" onChange="PopulateRightForm()">
<option value="1">One</option>
<option value="2">Two</option>
<option value="3">Three</option>
<option value="4">Four</option>
<option value="5">Five</option>
</select>
</form>
</body>
</html>
<!--- Right.html --->
<html>
<body bgcolor="FFFFFF">
<form name="RightForm">
Text passed from left form: <input type="Text" name="RightText"><br>
Value passed from left form: <input type="Text" name="RightValue">
</form>
</body>
</html> |
| |||
| Changing the action field of a form tag If you want to have one form but have it jump to different pages based off of what button a user clicks on, you can use the following example to change the form.action value. Example HTML/CFML code: Code: <html>
<head>
<!--- Set up the javascript to change the action url --->
<script language="Javascript">
function SetURL(site)
{
if (site == '1') document.myform.action='http://www.allaire.com/';
if (site == '2') document.myform.action='http://www.allaire.com/developer/gallery/index.cfm?objectID=6800';
document.myform.submit();
}
</script>
</head>
<body>
<!--- No action field specified, will default to load the same document --->
<center>
<form name="myform" method="get">
<input type="Button" value="Allaire's Homepage" onClick="SetURL('1')"><br><br>
<input type="Button" value="Tag Gallery" onClick="SetURL('2')"><br>
</form>
</center>
</body> |
| |||
| Cold Fusion ate my webserver! The only means that I know of that Cold Fusion can lock up IIS is if IIS is only configured to allow a certain number of tasks to be executed. For example, Personal Web Server will only allow two tasks to execute at any given time. The snag here is when you perform a call against the database. If a third-party call (such as a database query) does not respond back to Cold Fusion, CF will sit there and wait forever until the database sends something back to it. Timeouts do not apply here. If Cold Fusion never finishes a task and therefore never notifies IIS that it has finished, IIS will keep waiting for it and you'll eventually run out of free "sessions" and IIS will stop responding to new page requests Under Windows 95/98, the only option is to reboot. Under NT, you may be able to stop the Cold Fusion service to see if it'll free up the tasks. Otherwise, you'll have to reboot. But you need to look into your database access to find out where the problem lies. It's not with Cold Fusion, it's with your database. |
| |||
| Creating a logfile of a programs execution If you want to create a log file of a programs execution (ideal for programs that run via the Scheduler), here is a tag that I wrote to perform the task for you. All you need to do is to copy-n-paste the code below into a file called "DumpQuery.cfm" located in your \CFUSION\CustomTags directory. Note that the program traps any file errors so that if you fubar something with the file name, it doesn't stop the program from executing. So if you run your program and get no log file, check your file path to ensure that it is valid. Example HTML/CFML code: Code: <cfsetting enablecfoutputonly="Yes">
<!---
Creates a log file
Passed Attributes
Action: Open Kills any existing log file allowing a fresh log file to be created
Initilizes session variable
Close Writes any pending information to the log file
<none> Append to the specified log file
file: Full path information and file name of the log file. If not specified, it
will check to see if a variable "logfile" was defined in the calling template.
If so, it will use the file information from the logfile variable. Otherwise,
it will create a log file as the same as the template calling it with an
".log" appended to the end of the cfm. Ie: C:\InetPub\www\index.cfm.log
timestamp: Y/N If Y, the current date and time is prepended to the text to record
text: The text to append to the log file
loghistorysize: A number in bytes to cache. Once the logfile history exceedes this amount, it
is appended to the log file. Defaults to 10k.
You can only write to one log file at a time. If you start to write to a 2nd log file, be sure to close the first one first.
If you wish to append to a already existing log file without deleting it first, do not specify the "open" action.
If you do not close a log file, any pending information to be written will be lost.
Examples:
Delete any existing logfile and open a fresh file:
<CF_Log file="C:\Inetput\WWW\History.log" action="open">
Append a string of text to a logfile defined with "logfile" with a timestamp
<CF_Log text="User viewed home page">
Same as above but without a timestamp
<CF_Log text="User viewed home page" timestamp="N">
Done with program, want to flush out the log cache
<CF_Log action="close">
--->
<CFPARAM name="attributes.action" default="">
<CFPARAM name="attributes.file" default="">
<CFIF attributes.file NEQ "">
<CFSET caller.logfile=attributes.file>
</CFIF>
<CFPARAM name="caller.logfile" default="#CF_TEMPLATE_PATH#.log">
<CFPARAM name="file" default="#caller.logfile#">
<CFPARAM name="attributes.timestamp" default="Y">
<CFPARAM name="attributes.text" default="">
<CFPARAM name="attributes.loghistorysize" default="10240">
<CFPARAM name="caller.loghistory" default="">
<CFSET attributes.action=LCase(attributes.action)>
<CFIF attributes.timestamp EQUAL "Y">
<CFSET ts=DateFormat(Now(),"mm-dd-yyyy") & " " & TimeFormat(Now(),"HH:mm:ss") & " ">
<CFELSE>
<CFSET ts="">
</CFIF>
<CFTRY>
<CFIF attributes.action EQUAL "open">
<cffile action="DELETE"
file="#file#">
<cffile action="WRITE" file="#file#" output="#ts#Log Opened" mode="777" addnewline="Yes">
<CFSET caller.loghistory="">
</CFIF>
<CFCATCH type="any">
<!--- Eat any file errors --->
</CFCATCH>
</CFTRY>
<CFTRY>
<CFIF attributes.action EQUAL "close">
<CFSET caller.loghistory=caller.loghistory & Chr(13) & Chr(10) & ts & "Log Closed">
<cffile action="APPEND"
file="#file#"
output="#caller.loghistory#"
addnewline="Yes"
mode="777">
<CFSET caller.loghistory="">
</CFIF>
<CFCATCH type="any">
<!--- Eat any file errors --->
</CFCATCH>
</CFTRY>
<CFTRY>
<CFIF Trim(attributes.action) NOT EQUAL "open" AND Trim(attributes.action) NOT EQUAL "close">
<!--- <CFOUTPUT>#ts##attributes.text#<br></CFOUTPUT> --->
<CFIF caller.loghistory EQUAL "">
<CFSET caller.loghistory=ts & attributes.text>
<CFELSE>
<CFSET caller.loghistory=caller.loghistory & Chr(13) & Chr(10) & ts & attributes.text>
</CFIF>
<CFIF Len(caller.loghistory) GREATER THAN attributes.loghistorysize>
<cffile action="APPEND"
file="#file#"
output="#caller.loghistory#"
addnewline="Yes"
mode="777">
<CFSET caller.loghistory="">
</CFIF>
</CFIF>
<CFCATCH type="any">
<!--- Eat any file errors --->
</CFCATCH>
</CFTRY> |
| |||
| Creating arrays of more than three dimensions According to the CF Docs, you can only create an array of three dimensions max. So you can have a one dimensional array referenced as MyArray[a], a two dimensional array as MyArray[a][b], and a three dimensional array as MyArray[a][b][c]. But you could not create a four dimensional array as MyArray[a][b][c][d] because <CFSET MyArray=ArrayNew(4)> would generate an error. However, the one really sweet feature about Cold Fusion is that you can store any type of variable inside another variable. You can store a query or structure inside an array element. For example: Code: <CFSET MyArray=ArrayNew(1)>
<CFSET MyArray[1]=StructNew()>
<CFSET MyArray[1].MyQuery=QueryNew("field1,field2")> Now the trick with creating an array of more than three dimensions is to create an array inside an array. To give an example, you can create a 2D array with the following command: Code: <CFSET MyArray=ArrayNew(2)> <CFSET MyArray[1][1]="A"> Code: <CFSET MyArray=ArrayNew(1)> <CFSET MyArray[1]=ArrayNew(1)> <CFSET MyArray[1][1]="A"> Code: <!--- Assign six dimensional loop --->
<CFLOOP index="d1" from="1" to="3">
<CFSET MyArray[d1]=ArrayNew(1)>
<CFLOOP index="d2" from="1" to="3">
<CFSET MyArray[d1][d2]=ArrayNew(1)>
<CFLOOP index="d3" from="1" to="3">
<CFSET MyArray[d1][d2][d3]=ArrayNew(1)>
<CFLOOP index="d4" from="1" to="3">
<CFSET MyArray[d1][d2][d3][d4]=ArrayNew(1)>
<CFLOOP index="d5" from="1" to="3">
<CFSET MyArray[d1][d2][d3][d4][d5]=ArrayNew(1)>
<CFLOOP index="d6" from="1" to="3">
<CFSET MyArray[d1][d2][d3][d4][d5][d6]="#d1#,#d2#,#d3#,#d4#,#d5#,#d6#">
</CFLOOP>
</CFLOOP>
</CFLOOP>
</CFLOOP>
</CFLOOP>
</CFLOOP>
<CFDUMP var="#MyArray#"> |
| |||
| Database issue with URL ID fields - possible for web users to KILL your database tables If you allow users to display records from your database based off of an ID field that is passed via the URL, you need to ensure that the value is numeric prior to your CFQUERY command if you use embedded SQL. If you don't and don't have your query's trapped in case of an error, a remote user can effectively delete every record in your table using only their browser. For example, say you have the following URL: The browser is not supported. The URL parameter viewrec is the ID of the record in question that you want to display. However, if the remote user changes the url so that the number is invalid, say a non-numeric value... The browser is not supported. This would cause the SQL command to fail and depending on the debug settings, it could display to the user the SQL command you used including the table name(s). Thus armed with the knowledge of the table name that contains the records, they can delete ALL data from that table by entering the following URL (assuming the table in question is named "widgets"): The browser is not supported. It does work - I tried it after someone warned me that my CF Tips-N-Tricks website is vulnerable to it. (Call it my morbid sense of curiosity and yes, I did back up the table first.) Everything in the table was gone. |
| |||
| Debugging your program with the Remote Development Server (RDS) Adding a Remote Development Server (RDS) On the Resource Tab, click on the "Remote Files" tab (the computer with a globe behind it). On the top window of the Resources, it should display "Remote Servers". Right-click your mouse inside this window and a small menu should display showing "Add RDS Server" and "Add FTP Server". Select "Add RDS Server". You should now see a dialog box titled "Configure RDS Server". In the Description field, type in anything you want to allow you to easily identify the RDS Server (such as "Development"). For the Host Name field, enter in the URL that you use to access the website - do not use "http://" or "https://". The Port field, which defaults to 80, is the webserver port. If you use SSL for your website, enter Port 443 and set the checkbox next to "Use Secure Socket Layer". Next, you may enter in the User Name and Password configured in the Cold Fusion Administrator for the RDS. If you do not enter the information here, you will be prompted for it the first time you access the RDS Server. Once you are successfully able to browse the remote server via the Remote Files tab, you're ready to configure the Development Mappings. Configuring the Development Mappings Click on the Debug menu item and select "Development Mappings". The first time you enter this dialog box, the window with all mapping information should be empty. Select the RDS server you wish to map via the drop-down selection box at the top next to "Cold Fusion Server". If you configured your RDS Server with a description of "Development", then you would select "Development" here. At the bottom of the dialog box, you should see three fields, one each for "Studio Path", "CF Server Path", and "Browser Path". For the Studio Path, enter the physical directory on your computer that you use to edit your templates. This could be "N:\Internet\WWW" or "\\Webserver\Internet\WWW". Now for the CF Server Path. This is the path to the same directory entered for the Studio Path except that it is the physical path on the webserver itself. For example, it could be "D:\Internet\WWW". For the Browser Path, enter in the URL you use in your web browser to view your website. For example, enter "www.mysite.com". Once you have entered in all of the information, click on the Add button and then click on the OK button. Configuring the Debug Settings Now, let's tell Studio how to debug the program. Click on the Debug menu item and select "Debug settings". Ensure that the RDS server displayed under option #1 is correct. Next, you'll most likely have to monkey around with the URL in item #2 to correct it to point to the correct page. In every page that I debugged for the first time, there was always something wrong with the URL. However, Studio remembers any modifications you entered and normally will display the correct URL the next time you debug your program. Now remember that the time you have to execute your program step-by-step is the same amount of time configured for the Timeout on the Cold Fusion Administration page. If it's set to 30 seconds, you only have 30 seconds to run your program step-by-step before you get a timeout error. To get around this, add "RequestTimeout=300" to the URL in the Debug Settings. Don't forget to add any other URL variables your program needs to run (if any). Click the OK button when finished. Debugging your program Now that you have all the required configuration information set, let's start to debug your program! But before we start, check to see if you are performing any kind of Login function that will force the user to enter their UserID/Password to view the page. If you do, disable it. Otherwise, you won't be able to execute your code because you'll always be prompted to enter your UserID/Password! If you do not have the Debug tab on your Quickbar (the same one that has "Common, Fonts, Tables, Frames" and others), right-click your mouse on the Quickbar itself and select "Debug" in the menu that is displayed. Click on the Debug tab. This brings up a whole set of buttons to help you debug your program. Now in order to display useful information in the Debug window, you need to have a Breakpoint (a stopping point) configured somewhere in your code. The first time around using the Debug feature, go ahead and scroll down to the bottom of your program and click on the gray section to the left of the last line of code. This will cause the line to be highlighted in red and a little stop sign will show up in the gray area you clicked on. On the Debug tab of your Quickbar, click on the VCR Play button (Start/Continue) which will start the execution of your program. This will again display the Remote Development Settings dialog box. Double check the URL and if everything looks okay, click on the OK button. If you don't want this dialog box to be displayed every time you click on the Start button, set the checkbox next to "Don't prompt for these settings at next debug session". If everything was configured correctly, your program will run up to the Breakpoint you configured. At this point, a neat little window will pop up that gives you all kinds of information about the current state of your program such as variables and their values. If you look at the left side of the Status bar at the bottom of the Studio window, you'll notice a set of blue boxes showing up, slowly moving from left to right. This is the timer - you have until the boxes reaches the right side of the status bar to complete your debug session. When they reach the right side, your program will now time out. If you have your Cold Fusion timeout set to 30 seconds, it will take only 30 seconds to reach the right side. This is why it's a good idea to add "RequestTimeout=300" to the URL in the Remote Development Settings dialog box. If you want to step through your program line by line, set a Breakpoint where you want to start stepping through your code. If you currently have a debug session running, you will have to first click on the VCR Stop button (next to the Play button) to end the current debug session. Now start a new debug session and the program will execute up until it hits your breakpoint and which point it'll stop like it did before. If you look at the Debug Quickbar, there is a button to the right of the Stop button that displays "Step Into" when you hold your mouse stationary over it. Clicking this button will allow you to execute your program one line at a time. Any new variables that are defined will now be shown in the Debug window. If you click on the little red stop sign of a Breakpoint, it will turn into a white stop sign and the line will be highlighted in a dark gold. This is a disabled Breakpoint. It won't stop your program but it'll allow you to quickly find where it is in your program. Clicking on the Breakpoint a 3rd time will remove it. The Debug Window The Debug window is a wonderful thing! By now, I'm sure you're already in love with it. I will go into the different tabs listed at the bottom of the Debug window. Watches If you want to view the contents of a variable or watch its current value as you step through your program but don't want to be distracted by seeing all of the defined variables on the Variables tab, this is the tab for you. In the text box, type in the variable name in question. If you want to see it's current value, click on the Evaluate button. However, if you want to see its value as the program runs, click on the Watch button and it'll be added to the Watch List. Recordsets This tab will show you all of the query variables defined, the amount of records it returned, and the SQL used to perform the query. Tag Stack This tab will show you the current template you are running which is handy if you are stepping through included templates. Additional information is also displayed such as if you are currently inside a CFOUTPUT block. Output This tab will show you the currently generated HTML so far. Breakpoints All breakpoints defined in your program are displayed here with the template the Breakpoint exists, the line number of the Breakpoint, and the Breakpoint condition. You can activate/deactivate any Breakpoints by double-clicking on it here. If you want to add a condition to a Breakpoint, right-click on the Breakpoint and select "Edit Condition". The condition you enter follows the same syntax you would use in a conditional cfloop. For example, you only want to stop at this particular Breakpoint when the variable "Total" is equal to zero. So, you would enter "total equal 0" as the condition. Variables All defined variables in your program are displayed here. |
| |||
| Decoding form fields If you are using a version of Cold Fusion prior to 4.5, you may encounter a small glitch where a form field is not decoded when your program runs. For example, %20 is not replaced with a space. This normally occures when you pass hidden form fields where the value was encoded with the URLEncodedFormat function. The code below will take a variable and replace all escaped characters with the actual character. Example HTML/CFML code: Code: <CFSET str=result>
<CFSET ck=0>
<CFLOOP CONDITION="ck EQUAL 0">
<CFSET loc=Find("%",str)>
<CFIF loc EQUAL 0>
<CFSET ck=1>
<CFELSE>
<CFIF Mid(str,loc,3) EQUAL "%25">
<CFSET loc=Find("%",str,loc+1)>
<CFIF loc EQUAL 0>
<CFSET ck=1>
<CFELSE>
<CFSET str=Replace(str,Mid(str,loc,3),Chr(InputBaseN(Mid(str,loc + 1,2),16)),"ALL")>
</CFIF>
<CFELSE>
<CFSET str=Replace(str,Mid(str,loc,3),Chr(InputBaseN(Mid(str,loc + 1,2),16)),"ALL")>
</CFIF>
</CFIF>
</CFLOOP>
<CFSET str=Replace(str,"+"," ","ALL")>
<CFSET str=Replace(str,"%25","%","ALL")>
<CFOUTPUT>#str#</CFOUTPUT> |
| |||
| Display the Browser Print function If you have a page that the user has to print out (such as Shipping information that needs to be included with the package), it's real easy to bring up the print dialog box. Simply modify your <body> tag to add the following attribute: onLoad="print()". As soon as the page finishes loading, the Print dialog box will be displayed. If you want to display the Print dialog box and automatically redirect to another page, that's easy too. Change the onLoad attribute to read onLoad="print();window.location='../home.cfm';" |
| |||
| Dumping a Javascript array If you have a large multidimensional array, debugging your Javascript could be about as fun as finding out that your computer just infected the entire corporate network with a virus and now everybody is giving you funny looks. I found a set of Javascript functions that will dump out an entire Javascript array into a series of lists. However, being the ColdFusion geek that I am, I modified it so that the Javascript dump looks somewhat like the results produced by the <cfdump> tag. As an added benefit, the script comes with functions to allow for the easy addition and deletion of rows from an array. Click here to download. Take the following Javascript code: Code: <script language="Javascript">
var tmpArray=new Array(1);
tmpArray[0]='a';
tmpArray[1]=new Array(1);
tmpArray[1][0]='b';
tmpArray[1][1]=new Array(1);
tmpArray[1][1][0]='c';
tmpArray[1][1][1]='d';
tmpArray[1][2]='e';
tmpArray[1][3]=new Array('f','g');
tmpArray[1][3][2]=new Array('h','i','j','k');
tmpArray[1][4]='l';
tmpArray[2]='m';
</script> Now if I make a call to the function dumpArrayValues, it displays the table. Code: <script language="Javascript"> dumpArrayValues(tmpArray); </script> ![]() The original function, renamed to dumpArrayValuesList, would return the dump as below: Code: <script language="Javascript"> dumpArrayValuesList(tmpArray); </script> ![]() |
| |||
| Duplicating the Session scope If you find a program or custom tag that places an exclusive lock around the session scope and then performs some timely processes, here's a means you can use to release the bottleneck that can pretty much freeze up the server under even a light load. First thing you need to do is to duplicate the session scope in a local scope. You can use the Request scope or copy it to the variables scope - the choice is yours. However, in this example, I will use the variables scope because this process is occurring in a custom tag and I wish for the copy of the session scope to be removed from memory upon completion of the tag's execution. Code: <cflock timeout="30" throwontimeout="Yes" type="READONLY" scope="SESSION"> <CFSET variables.LSess=Duplicate(session)> </cflock> Now comes the important step - copying the local copy of the session structure back to the actual session scope. Despite what you may think, the Duplicate function will not work for this. For example: Code: <cflock timeout="30" throwontimeout="Yes" type="EXCLUSIVE" scope="SESSION"> <CFSET session=Duplicate(variables.LSess)> </cflock> However, there is another way to ensure that everything gets copied back over to the session scope though it's not as efficient as the original copy. You have to Duplicate() each key under the local session structure over to the session scope. Code: <cflock timeout="30" throwontimeout="Yes" type="EXCLUSIVE" scope="SESSION">
<CFLOOP index="Key" list=#StructKeyList(variables.LSess)#>
<CFSET "Session.#Key#"=Duplicate(Evaluate("variables.LSess.#Key#"))>
</CFLOOP>
</cflock> |
| |||
| Dynamically creating a Microsoft Rich Text Document The accompanied HTML/CFML Code contains a working template to create a RTF Word Document. This code will allow you to create a multi-sectioned report. I was handed a printout of a report from a mainframe program and told to duplicate it (real fun, no specs) in Cold Fusion and they wanted it to look exactly the same. I came up with the following to get around of the headaches of forcing a pagebreak at a predefined point on a web page. I simply define the header, the footer, and pump all the data out and let Word handle the page breaks. This program only generates text with the font Courier New though support for Times New Roman is also in there. Any formatting codes are acceptable and you'll see that I boldfaced the header on section two and used italics on the footer of section three. You can use "\f1 " (note the trailing space) to change the font to Times New Roman and "\f2 " for Courier New. Microsoft has a white paper on RTF somewhere on their website but good luck finding it. Every time I had to search for it, it took on average of 30 minutes to find it. Example HTML/CFML code: Code: <CFSETTING ENABLECFOUTPUTONLY="Yes">
<!--- Define the pysical directory to generate the report --->
<CFSET cf_report="C:\Internet\WWW\">
<!--- Define the URL directory --->
<CFSET cf_view="http://127.0.0.1/">
<!--- Amount of data to "cache" before writing the data to the rtf file. 20*1024 = 20k --->
<CFSET report_size=20*1024>
<!--- The character to represent a line break, must NOT be generated anywhere else in the report --->
<CFSET cr=Chr(3)>
<!--- Define special breaks and formatting --->
<CFSET page_break="\par \page ">
<CFSET section_break="\par \sect }\sectd \linex0\endnhere\sectdefaultcl ">
<CFSET new_header=section_break & "{\header \pard\plain \s15\widctlpar\tqc\tx4320\tqr\tx8640\adjustright \fs20\cgrid {\f2 ">
<CFSET new_footer="\par }}{\footer \pard\plain \s16\widctlpar\tqc\tx4320\tqr\tx8640\adjustright \fs20\cgrid {\f2 ">
<CFSET new_body="\par }}\pard\plain \widctlpar\adjustright \fs20\cgrid {\f2 ">
<CFSET new_line="\par ">
<CFSET eof="\par }}" & cr>
<!--- Initilize header and footer arrays --->
<CFSET head=ArrayNew(1)>
<CFSET foot=ArrayNew(1)>
<!--- The following four variables define the documents information, purely for informational sake --->
<CFSET title="Example RTF Report">
<CFSET author="John Bartlett">
<CFSET operator="">
<CFSET company="">
<!--- The next five variables define the margins. "twips" defines how much space is in each tenth of
an inch and should not be modifed. To set a margin of 1.0", multiply twips by 10. To set a
margin of 0.5", multiply twips by 5. --->
<CFSET twips=144>
<CFSET top_margin=twips * 15> <!--- Set top margin to 1.5 inches --->
<CFSET bottom_margin=twips * 15> <!--- Set bottom margin to 1.5 inches --->
<CFSET left_margin=twips * 10> <!--- Set left margin to 1 inch --->
<CFSET right_margin=twips * 10> <!--- Set right margin to 1 inch --->
<!--- Page setup --->
<CFSET page_width=twips * 85> <!--- Define the width of the paper to 8.5 inches --->
<CFSET page_height=twips * 110> <!--- Define the height of the paper to 11 inches. Use "140" for legal stock --->
<CFSET landscape=""> <!--- Set to "\landscape" for landscape reports, don't forget to reverse the page width and height --->
<!--- Create the text to display in the header field, must have at least two lines --->
<CFSET head[1]="Example Microsoft Word">
<CFSET head[2]="Rich Text Document Generator">
<CFSET head[3]="">
<CFSET numhead=3>
<!--- Create the text to display in the footer field --->
<CFSET foot[1]="">
<CFSET foot[2]="This is the footer field.">
<CFSET numfoot=2>
<!--- Generate the top of the Rich Text Document --->
<CFSET yr=DateFormat(Now(),"yyyy")>
<CFSET mo=Trim(DateFormat(Now(),"mm"))>
<CFSET dy=Trim(DateFormat(Now(),"dd"))>
<CFSET hr=Trim(TimeFormat(Now(),"HH"))>
<CFSET min=Trim(TimeFormat(Now(),"mm"))>
<CFSET tim="\yr" & yr & "\mo" & mo & "\dy" & dy & "\hr" & hr &
"\min" & min & "}">
<CFSET header="{\rtf1\ansi\ansicpg1252\uc1 \deff0\deflang1033" &
"\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2" &
"{\*\panose 02020603050405020304}Times New Roman;}" &
"{\f2\fmodern\fcharset0\fprq1{\*" &
"\panose 02070309020205020404}Courier New;}}" &
"{\colortbl;\red0\green0\blue0;" & cr>
<CFSET header=header & "\red0\green0\blue255;\red0\green255\blue255;" &
"\red0\green255\blue0;\red255\green0\blue255;\red255" &
"\green0\blue0;\red255\green255\blue0;\red255\green255" &
"\blue255;\red0\green0\blue128;\red0\green128\blue128;" &
"\red0\green128\blue0;\red128\green0\blue128;" & cr>
<CFSET header=header & "\red128\green0\blue0;\red128\green128\blue0;" &
"\red128\green128\blue128;\red192\green192\blue192;}" &
"{\stylesheet{\widctlpar\adjustright \fs20\cgrid " &
"\snext0 Normal;}{\*\cs10 \additive Default Paragraph " &
"Font;}{\s15\widctlpar\tqc\tx4320\tqr\tx8640\" &
"adjustright " & cr>
<CFSET header=header & "\fs20\cgrid \sbasedon0 \snext15 header;}" &
"{\s16\widctlpar\tqc\tx4320\tqr\tx8640\adjustright " &
"\fs20\cgrid \sbasedon0 \snext16 footer;}}{\info" &
"{\title " & title & "}" & cr>
<CFSET header=header & "{\author " & author & "}{\operator " &
operator & "}" & cr>
<CFSET header=header & "{\creatim" & tim & cr>
<CFSET header=header & "{\revtim" & tim & cr>
<CFSET header=header & "{\printim" & tim & cr>
<CFSET header=header & "{\*\company " & company & "}{\nofcharsws0}" &
"{\vern113}}" & cr>
<CFSET header=header & "\paperw" & page_width & "\paperh" &
page_height & landscape & cr>
<CFSET header=header & "\margl" & left_margin & "\margr" &
right_margin & "\margt" & top_margin & "\margb" &
bottom_margin & " " & cr>
<CFSET header=header & "\widowctrl\ftnbj\aenddoc\hyphcaps0\formshade" &
"\viewkind1\viewscale88\viewzk2\pgbrdrhead\pgbrdrfoot " &
"\fet0\sectd \linex0\endnhere\sectdefaultcl {\header " &
cr>
<CFSET header=header & "\pard\plain \s15\widctlpar\tqc\tx4320\tqr" &
"\tx8640\pvpara\phpg\posx10944\posy0\adjustright " &
"\fs20\cgrid {\field{\fldrslt {\cs17\f2\lang1024 1}}}" &
"{\cs17\f2 " & cr>
<CFSET header=header & "\par }\pard \s15\ri360\widctlpar\tqc\tx4320" &
"\tqr\tx8640\adjustright {\f2 " & head[1] & cr>
<CFSET header=header & "\par }\pard \s15\widctlpar\tqc\tx4320\tqr" &
"\tx8640\adjustright {\f2 " & head[2] & cr>
<!--- Append the head variable --->
<CFIF numhead GREATER THAN 0>
<CFLOOP INDEX="loop" FROM="3" TO="#numhead#">
<CFIF loop GREATER THAN 1>
<CFSET header=header & "\par ">
</CFIF>
<CFSET header=header & head[loop]>
</CFLOOP>
</CFIF>
<!--- Generate the footer part of Rich Text Document --->
<CFSET footer="\par }}{\footer \pard\plain \s16\widctlpar\tqc" &
"\tx4320\tqr\tx8640\adjustright \fs20\cgrid {\f2 " & cr>
<CFIF footer GREATER THAN 0>
<CFLOOP INDEX="loop" FROM="1" TO="#numfoot#">
<CFIF loop GREATER THAN 1>
<CFSET header=header & "\par ">
</CFIF>
<CFSET footer=footer & foot[loop]>
</CFLOOP>
</CFIF>
<!---
The physical path and file name on the server for the report being
generated.
NOTE: Make sure that you use some unique filename (ie: user id) so
that if two users generate the same report at the same time, it
doesn't trip over each other.
--->
<CFSET file="Example.rtf">
<CFSET file_name=cf_report & file>
<!--- Delete this report if it already exists, prevents this report from simply being appended onto the last report --->
<CFDIRECTORY ACTION="LIST"
DIRECTORY="#cf_report#"
NAME="dir">
<CFLOOP QUERY="dir">
<CFIF dir.name[CurrentRow] EQUAL file>
<CFFILE ACTION="DELETE" FILE="#file_name#">
<CFBREAK>
</CFIF>
</CFLOOP>
<!--- Generate the start of the actual report --->
<CFSET report=header & footer>
<CFSET report=report & "\par }}{\*\pnseclvl1\pnucrm\pnstart1\" &
"pnindent720\pnhang{\pntxta .}}{\*\pnseclvl2\pnucltr" &
"\pnstart1\pnindent720\pnhang{\pntxta .}}{\*\pnseclvl3" &
"\pndec\pnstart1\pnindent720\pnhang{\pntxta .}}" &
"{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang" &
"{\pntxta )}}" & cr>
<CFSET report=report & "{\*\pnseclvl5\pndec\pnstart1\pnindent720" &
"\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl6" &
"\pnlcltr\pnstart1\pnindent720\pnhang{\pntxtb (}" &
"{\pntxta )}}{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720" &
"\pnhang{\pntxtb (}{\pntxta )}}{\*\pnseclvl8" & cr>
<CFSET report=report & "\pnlcltr\pnstart1\pnindent720\pnhang" &
"{\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1" &
"\pnindent720\pnhang{\pntxtb (}{\pntxta )}}\pard" &
"\plain \widctlpar\adjustright \fs20\cgrid {\f2 ">
<!--- Insert your report code here --->
<CFLOOP index="loop1" from="1" to="10">
<CFLOOP index="loop2" from="1" to="20">
<CFSET report=report & "#loop2# ">
</CFLOOP>
<CFSET report=report & cr & new_line>
<!---
Write the generated report to the file if report generated so far
is in excess of our defined size to keep the memory allocated
to this task to a reasonable amount.
--->
<CFIF Len(report) GREATER THAN report_size>
<CFSET ck=0>
<CFSET data=0>
<CFLOOP CONDITION="ck equal 0">
<CFSET data=data+1>
<CFSET out=GetToken(report,data,cr)>
<CFIF out EQUAL "">
<CFSET ck=1>
<CFELSE>
<CFFILE ACTION="Append"
FILE="#file_name#"
OUTPUT="#out#">
</CFIF>
</CFLOOP>
<CFSET report="">
</CFIF>
</CFLOOP>
<!--- Generate Section Two --->
<!--- Redefine the header and don't generate a footer. Note that the header is flushed with the top of the page
and the report won't display until after the margin so you may need to padd the header as I have done here. --->
<CFSET head[1]="Section Two Header">
<CFSET head[2]="">
<CFSET head[3]="">
<CFSET head[4]="">
<CFSET head[5]="\b Line Random Number\b0">
<CFSET head[6]="\b ==== =============\b0">
<CFSET numhead=6>
<CFSET numfoot=0>
<CFSET report=report & new_header>
<CFLOOP INDEX="loop" FROM="1" TO="#numhead#">
<CFIF loop GREATER THAN 1>
<CFSET report=report & "\par ">
</CFIF>
<CFSET report=report & head[loop] & cr>
</CFLOOP>
<CFSET report=report & new_footer>
<CFLOOP INDEX="loop" FROM="1" TO="#numfoot#">
<CFIF loop GREATER THAN 1>
<CFSET report=report & "\par ">
</CFIF>
<CFSET report=report & foot[loop] & cr>
</CFLOOP>
<CFSET report=report & new_body>
<!--- Insert your report code here for section 2 --->
<CFLOOP index="loop" from="1" to="60">
<CFIF loop GREATER THAN 1>
<CFSET report=report & new_line>
</CFIF>
<CFSET report=report & "#RJustify(loop,4)# #RJustify(RandRange(1,99999999),13)#" & cr>
<!---
Write the generated report to the file if report generated so far
is in excess of our defined size to keep the memory allocated
to this task to a reasonable amount.
--->
<CFIF Len(report) GREATER THAN report_size>
<CFSET ck=0>
<CFSET data=0>
<CFLOOP CONDITION="ck equal 0">
<CFSET data=data+1>
<CFSET out=GetToken(report,data,cr)>
<CFIF out EQUAL "">
<CFSET ck=1>
<CFELSE>
<CFFILE ACTION="Append"
FILE="#file_name#"
OUTPUT="#out#">
</CFIF>
</CFLOOP>
<CFSET report="">
</CFIF>
</CFLOOP>
<!--- Generate Section Three --->
<CFSET head[1]="Section Three">
<CFSET head[2]="">
<CFSET numhead=2>
<CFSET foot[1]="">
<CFSET foot[2]="\i WooHoo!\i0">
<CFSET numfoot=2>
<CFSET report=report & new_header>
<CFLOOP INDEX="loop" FROM="1" TO="#numhead#">
<CFIF loop GREATER THAN 1>
<CFSET report=report & "\par ">
</CFIF>
<CFSET report=report & head[loop] & cr>
</CFLOOP>
<CFSET report=report & new_footer>
<CFLOOP INDEX="loop" FROM="1" TO="#numfoot#">
<CFIF loop GREATER THAN 1>
<CFSET report=report & "\par ">
</CFIF>
<CFSET report=report & foot[loop] & cr>
</CFLOOP>
<CFSET report=report & new_body>
<!--- Insert your report code here for section 3 --->
<CFLOOP index="loop" from="0" to="25">
<CFIF loop GREATER THAN 0>
<CFSET report=report & cr & new_line>
</CFIF>
<CFLOOP index="alpha" from="65" to="90">
<CFSET char=alpha + loop>
<CFIF char GREATER THAN 90>
<CFSET char=char - 26>
</CFIF>
<CFSET report=report & Chr(char)>
</CFLOOP>
<!---
Write the generated report to the file if report generated so far
is in excess of our defined size to keep the memory allocated
to this task to a reasonable amount.
--->
<CFIF Len(report) GREATER THAN report_size>
<CFSET ck=0>
<CFSET data=0>
<CFLOOP CONDITION="ck equal 0">
<CFSET data=data+1>
<CFSET out=GetToken(report,data,cr)>
<CFIF out EQUAL "">
<CFSET ck=1>
<CFELSE>
<CFFILE ACTION="Append"
FILE="#file_name#"
OUTPUT="#out#">
</CFIF>
</CFLOOP>
<CFSET report="">
</CFIF>
</CFLOOP>
<!--- END OF REPORT --->
<CFSET report=report & eof>
<!--- Write the rest of the generated report to the file --->
<CFSET ck=0>
<CFSET loop=0>
<CFLOOP CONDITION="ck equal 0">
<CFSET loop=loop+1>
<CFSET out=GetToken(report,loop,cr)>
<CFIF out EQUAL "">
<CFSET ck=1>
<CFELSE>
<CFFILE ACTION="Append"
FILE="#file_name#"
OUTPUT="#out#">
</CFIF>
</CFLOOP>
<CFOUTPUT>
<a href="#CF_VIEW##file#">View report</a>
</CFOUTPUT> |
| |||
| Ending a session when the user closes their browser One of the features of session variables is that the user can close their browser, shut down their computer, take a nap, power their computer back up and their shopping basket would still be there on your web site if the session timeout had not expired. But say you don't want that. You want the session to end if they close their browser. Below is the code you need to copy-n-paste into your Application.cfm to make this happen. How it works Cold Fusion uses two cookies set on the user's computer, CFID and CFTOKEN, to tie them to a set of session variables. By default, these two cookies are set to never expire. By re-saving the cookies with the same name and value, any existing session variables will be maintained but the browser will set the cookies to automatically delete when the browser closes. If the user opens their browser back up and goes back to your page, the Cold Fusion server detects that there is no CFID/CFTOKEN cookies set and will generate a new combination - thus a new session. Example HTML/CFML code: Code: <cfif IsDefined("Cookie.CFID") AND IsDefined("Cookie.CFTOKEN")>
<cfset Variables.cfid_local = Cookie.CFID>
<cfset Variables.cftoken_local = Cookie.CFTOKEN>
<cfcookie name="CFID" value="#Variables.cfid_local#">
<cfcookie name="CFTOKEN" value="#Variables.cftoken_local#">
</cfif> |
| |||
| Fetching the contents of generated field names Say you have an HTML form that contain x number of date fields. Say you want to use Cold Fusion's automatic validation of the date fields using the CFINPUT tag. Catch is, you can not use the same name for more than one CFINPUT field like you can in a normal HTML input field. First we want to build the form. The user has prompted in a previous page that they will be entering 10 dates (stored in num_dates). Code: <CFFORM action="nextpage.cfm">
<CFLOOP index="1" to="#num_dates#">
<CFOUTPUT>
Date ###loop#:
<CFINPUT type="text"
name="date_#loop#"
validate="date"
required="Yes"
message="You must enter a valid date for date field number #loop#">
<br>
</CFOUTPUT>
</cfloop>
<CFOUTPUT>
<input type="Hidden" name="num_dates" value="#num_date#">
</CFOUTPUT>
</CFFORM> <CFSET curr_date=date_#loop#> It would blow up. If we used: Code: <CFSET curr_date="date_#loop#"> However, we can use the Evaluate function to grab the contents of the variable. Code: <CFLOOP index="loop" from="1" to="#num_dates#">
<CFSET curr_date=Evaluate("date_#loop#")>
</CFLOOP> |
| |||
| File time stamp changes with Daylight Savings on NT machines If you are storing document date/time stamps in a database in order to check for modifcations, you will experience problems when the server's system clock changes in observance of Daylight Savings. On Saturday, April 1st 2000, you saved a document at 2:15 pm. On Sunday, April 2nd 2000, you check the date/time stamp of the file - it'll be displayed as 3:15 pm. If you have a program that compares the date/time stamps of files against a database, your program will think that all of the documents have been modified. According to Microsoft's Knowledge Base article Q129574, this is by design and is not a bug. This affects the following platforms: * Windows NT operating system version 3.1 * Windows NT Advanced Server * Windows NT Workstation versions 3.5, 3.51, 4.0 * Windows NT Server versions 3.5, 3.51, 4.0 * Windows 2000 Professional * Windows 2000 Server * Windows 2000 Advanced Server Here is an excerpt from the KB article: This behavior occurs because of the way that Windows NT stores time information. All times displayed in Windows NT for event log events and files on NTFS partitions are computed as offsets to Greenwich Mean Time (GMT). When you set the time on your system, you are setting the value for GMT. When you select your local time zone for the system, the appropriate number of hours are added or subtracted to the stored GMT value. This adjusted time is displayed. When "Automatically Adjust for Daylight Saving Time" is selected, an additional hour is added to GMT during daylight savings time (the first Sunday in April through the last Sunday in October). If you are viewing another machine remotely across one or more time zones through Event Viewer, the times for events on the remote system appear relative to your local time. In other words, if you are viewing an event remotely that actually occurred at 8:00 PM Central Daylight Time, the time displayed for the event on your computer will be 6:00 PM when you view the event from the Pacific Daylight Time zone. When Windows95 or Windows NT clients access network resources they are passed the GMT time of the file stored on the NTFS partition. When the client receives the time stamp in GMT they then adjust the time stamp (+) plus or (-) minus the time zone they are set for. In the case of WINDOWS NT - it also adjusts for daylight savings time and displays the file's time stamp for the correct local time including Daylight Savings Time setting. In the case of WINDOWS95 - The time returned by the file system is not adjusted for Daylight Savings Time. This feature is by design, and was implemented to work with servers such as NetWare that do not support the Daylight Savings time APIs and time functions in Windows 95. In this case the files will display off by one hour. this is BY DESIGN for WINDOWS95 clients. |
![]() |
| Thread Tools | |
| Display Modes | |
| |
Similar Threads | ||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| C# .Net Tips & Tricks | oxygen | C# Programming | 85 | 01-08-2009 12:25 AM |
| SAP Tips & Tricks | leoraja8 | Operating Systems | 0 | 03-29-2008 12:11 AM |
| PHP Tips and Tricks | Sabari | PHP Programming | 20 | 12-18-2007 05:26 AM |
| .NET tricks & Tips | Karpagarajan | VB.NET Programming | 1 | 04-23-2007 08:17 AM |
| SEO Tips & Tricks | spid4r | Search Engine Optimization | 0 | 03-08-2007 11:03 PM |
Our Partners |