Skip to main content
September 17, 2009
Answered

Trouble getting UDF to work

  • September 17, 2009
  • 1 reply
  • 2150 views

I am trying to validate a form to find HTML after it is submitted (yes, I plan to code before submission as well, but I need to get this to work first).  My UDF looks like this:

<cffunction name="checkChars" output="no" returntype="numeric">

<!--- define arguments --->
    <cfargument name="Qfield" type="string" required="yes">

<!--- define variable(s) --->
    <cfset Var dirtyParam = Arguments.Qfield>
    <cfset Var QbadChar = 0>

<!--- check to see if HTML exists in Qfield --->
    <cfif REFind("<",dirtyParam) NEQ 0><cfset QbadChar = 1></cfif>
    <cfif REFind(">",dirtyParam) NEQ 0><cfset QbadChar = 1></cfif>
    <cfif REFind("//",dirtyParam) NEQ 0><cfset QbadChar = 1></cfif>
    <cfif REFind("c:",dirtyParam) NEQ 0><cfset QbadChar = 1></cfif>

<!--- If HTML exists, notify user and return to previous page --->
    <cfif QbadChar NEQ 0>
        <cfscript>
            WriteOutput('
                <script language="JavaScript">
                <!--
                alert("The data submitted in your form contains unallowable characters, please remove all non-alphanumeric characters.")
                //-->
                </script>
            ');
            WriteOutput('
                <script language="JavaScript">
                <!--
                history.back()
                //-->
                </script>
            ');
        </cfscript>
    </cfif>
    <cfreturn QbadChar>
</cffunction>

It is saved in a separate template and included in the applicable template at the beginning with:

<cfinclude template="Libraries/formValidation.cfm">

I am testing it on a field called "Lessor" by calling the UDF in the same template with:

<cfif isdefined ("FORM.Lessor")><cfset #checkChars("Form.Lessor")#></cfif>

Unfortunately, it doesn't work because when I use HTML in the "Lessor" field, it goes ahead and saves it.  Any ideas what I'm missing?

This topic has been closed for replies.
Correct answer ilssac

I set the entire "passfail NEQ" block inside the "isdefined" block:

<cfinclude template="Libraries/formValidation.cfm">
<cfif isdefined ("FORM.Lessor")>
<cfset passFail = checkChars(Form.Lessor)>
<cfif passFail NEQ 0>
  <cfscript>
   WriteOutput('
    <script language="JavaScript">
    <!--
    alert("Your form contains HTML, please remove unalowable characters and resubmit")
    //-->
    </script>
   ');
   WriteOutput('
    <script language="JavaScript">
    <!--
    history.back()
    //-->
    </script>
   ');
  </cfscript>
</cfif>
</cfif>

So now the page runs, but it still lets me save HTML characters in the field "Lessors"


The <cfstoredProc...> tag is what puts the information into the database.

What is the relationship of the <cfstoredProc...> tag to the <cfiif passFail NEQ 0> block?  How would this relationship determine when the strored procedure is run and when it is not run.

Remember what I said in my first post.  A JavaScript history.back() function is not going to have any affect on the server where the CFML is running.  All the CFML that is to be run will be ran before any HTML or JavaScript is sent to the client where they will run.

1 reply

ilssac
Inspiring
September 17, 2009

The first weirdness I see is that you set your output to "no" which means that all output in the function will not be sent to response buffer.

Then you try to output javascirpt content that must be sent to the response buffer so that it will run on the client.

So I would guess that this will never happen.

Secondly you do not show it in the the code you provided, but It looks like you expect this javascript to stop the processing of the cfml.  This will not happen.  All the CFML will be processed bofore anything is sent back to the browser.  So, the page continues to process and puts the data into a database.  That is going to happen, whether or not that JavaScript is sent to the browser to do something.

What you need to do is test the string.

IF the string passess

process the data into the database, provide appropiate feedback to the user.

ELSE the string fails

don't process the data into the database, provide appropiate feedback to the user.

September 17, 2009

Okay, I changed my UDF to:

<cffunction name="checkChars" output="yes" returntype="numeric">

<!--- define arguments --->
<cfargument name="Qfield" type="string" required="yes">

<!--- define variable(s) --->
<cfset Var QbadChar = 0>

<!--- check to see if HTML exists in Qfield --->
<cfif REFind("<",Qfield) NEQ 0><cfset QbadChar = 1></cfif>
<cfif REFind(">",Qfield) NEQ 0><cfset QbadChar = 1></cfif>
<cfif REFind("//",Qfield) NEQ 0><cfset QbadChar = 1></cfif>
<cfif REFind("c:",Qfield) NEQ 0><cfset QbadChar = 1></cfif>

<!--- return 1 if field contains HTML, 0 if clean --->
<cfreturn QbadChar>
</cffunction>

Then I assigned the result to a variable (in the processing template) like this:

<cfif isdefined ("FORM.Lessor")><cfset passFail = #checkChars("Form.Lessor")#></cfif>

And finally used the result to stop the form processing (right below the above code in the processing template) with:

<cfif passFail NEQ 0>
<cfscript>
   WriteOutput('
    <script language="JavaScript">
    <!--
    alert("Your form contains HTML, please remove unalowable characters and resubmit")
    //-->
    </script>
   ');
   WriteOutput('
    <script language="JavaScript">
    <!--
    history.back()
    //-->
    </script>
   ');
  </cfscript>
</cfif>

But not I get the error: "Variable PASSFAIL is undefined"

ilssac
Inspiring
September 17, 2009
<cfset passFail = #checkChars("Form.Lessor")#>

This line does not need the pound|hash characters and it can not have the quotes.  I.E. it should look like this:

<cfset passFail = checkChars(Form.Lessor)>

But I don't see how this would cause the failure you say you got.  It would caused to you always test the literal string "Form.Lessor" and not the value of the Form.Lessor variable, so that it will have always passed, but I would have expected it to return a value.

Can you provide the entire file? is it large?  I think the code you posted should have returned a vaule.