How to disallow non-alphanumeric characters in ColdFusion using a RegEx - regex

I am using ColdFusion 9.0.1.
I am trying to test whether a user has provided a non alphanumeric value. If they have, I want to return false. I'm pretty sure I am close, but I keep getting an error:
Complex object types cannot be converted to simple values.
I've tried multiple ways of making this work, but I can't get it to work.
Specifically, I want to allow only a through z and 0 through 9. No spaces, or special characters.
Can you help me tweak this?
<cfscript>
LOCAL.Description = trim(left(ARGUMENTS.Description, 15));
if (len(LOCAL.Description) lte 4) {
return false;
} else if (reMatchNoCase("[^A-Za-z0-9_]", LOCAL.Description) neq "") {
return false;
} else {
return true;
</cfscript>
W

reMatchNoCase returns Array which cannot be compared to the string, use ArrayLen() on the result in order to find out if there any matches
There is actually another problem in your code. First line will produce an error if the length of the description is less than 15, which means that the first IF is obsolete since it will always be false.

reMatchNoCase("[^A-Za-z0-9_]", LOCAL.Description) neq ""
It is because ReMatchNoCase returns an array, not a simple string. Either check the array length, or better yet, use ReFindNoCase instead. It returns the position of the first match, or 0 if it was not found.

You can also try the following approach:
<cfscript>
local.description = trim(local.description);
return reFind("(?i)^[A-Z0-9_]{5,}$", local.description)?true:false;
</cfscript>

I'm late to the party but reFindNoCase is the optimal solution in 2021. Here's how I would handle the code in the original question:
// best practice not to have a local var name identical to an argument var
var myValue = trim( left( arguments.description, 15 ) );
// return false if myValue is less than 4 or has special characters
return(
!len( myValue ) lte 4 &&
!reFindNoCase( "[^a-z0-9]", myValue )
);

Related

using multiple characters as delimiters in Coldfusion list

I am trying to use multiple characters as the delimeter in ColdFusion list like ,( comma and blank) but it ignores the blank.
I then tried to use:
<cfset title = listappend( title, a[ idx ].title, "#Chr(44)##Chr(32)#" ) />
But it also ignores the blank and without blanks the list items to diffucult to read.
Any ideas?
With ListAppend you can only use one delimiter. As the docs say for the delimiters parameter:
If this parameter contains more than one character, ColdFusion uses only the first character.
I'm not sure what a[ idx ].title contains or exactly what the expected result is (would be better if you gave a complete example), but I think something like this will do what you want or at least get you started:
<cfscript>
a = [
{"title"="One"},
{"title"="Two"},
{"title"="Three"}
];
result = "";
for (el in a) {
result &= el.title & ", ";
}
writeDump(result);
</cfscript>
I think there's a fundamental flaw in your approach here. The list delimiter is part of the structure of the data, whereas you are also trying to use it for "decoration" when you come to output the data from the list. Whilst often conveniently this'll work, it's kinda conflating two ideas.
What you should do is eschew the use of lists as a data structure completely, as they're a bit crap. Use an array for storing the data, and then deal with rendering it as a separate issue: write a render function which puts whatever separator you want in your display between each element.
function displayArrayAsList(array, separator){
var list = "";
for (var element in array){
list &= (len(list) ? separator : "");
list &= element;
}
return list;
}
writeOutput(displayAsList(["tahi", "rua", "toru", "wha"], ", "));
tahi, rua, toru, wha
Use a two step process. Step 1 - create your comma delimited list. Step 2
yourList = replace(yourList, ",", ", ", "all");

trying to find the value is numeric or integer from string

With the url string below, I need to find the value of the parameter named construction.
<cfset understand = "http://www.example.com/ops.cfm?id=code&construction=148&construction=150&Building=852&Building=665&Building=348&Building=619&Building=625&Building=626&_=1426353166006&action=SUBMIT">
<cfset understand2 = "http://www.example.com/ops.cfm?id=code&construction=AVENT+Construction+Site&construction=Signore+upper+constructions&Building=852&Building=665&Building=348&Building=619&Building=625&Building=626&_=1426353166006&action=SUBMIT">
I then want to check if the value is numeric or a string. I am doing this:
isDefined('understand') and isnumeric(understand)
But it always returns "NO".
Seems like a good case for REGEX, but that's not my strength. If you are always looking for the value of the same item (construction), you could take advantage of the underlying Java and use the STRING.split() method. Then use the Coldfusion val() function to see what you get. The following solution assumes that 0 is not a valid value. If it is then you have more work to do.
<cfscript>
target=understand;
//target=understand2; //uncomment to try the second values
token="construction=";
potentialValues = target.split(token); //creates an array of values using the token as a separator
for (item in potentialValues )
{
writeoutput(val(item) & "<br />"); //val will grab the numerical value and ignore everything that follows. No number will become 0
}
</cfscript>
Try this:
constructionIsAt = find(understand, "construction");
characterAfterConstruction = mid(understand, constructionIsAt + 13, 1);
if isNumeric(characterAfterConstruction) {
code for numeric
}
else {
code for non numeric
}

using a replace in coldfusion leaving trailing comma

I have a code where the values are coming as:
a,b,c from database..
now i want to remove c from the string based upon condition, c can be at any place, 1st, last or middle.
i am using replace to do it like this:
<cfset answer = Replace('a,b,c','c','','all')>
This works but it leaves a trailing comma at the end or at the start or 2 commas in middle breaking the whole string, what can be my approach here
<cfscript>
input = 'a,b,c';
foundAt = listFind(input, 'c');
answer = foundAt ? listDeleteAt(input, foundAt) : input;
writeOutput(answer);
</cfscript>
Run this code LIVE on TryCF.com
See: List functions
OR use REReplace(). The solution was just one google search away: Regex for removing an item from a comma-separated string?
function listRemoveAll(list, item) {
return REReplace(list, "\b#item#\b,|,\b#item#\b$", "", "all");
}

How to accept numbers and specific words?

i have validating a clothes size field, and want it to accept only numbers and specific "words" like S, M, XL, XXL etc. But i am unsure how to add the words to the pattern. For example, i want it to match something like "2, 5, 23, S, XXXL" which are valid sizes, but not random combinations of letters like "2X3, SLX"
Ok since people are not suggesting regexp solutions i guess i should say that this is part of a larger method of validation which uses regexp. For convenience and code consistency i want to do this with regexp.
Thanks
If they're a known set of values, I am not sure a regex is the best way to do it. But here is one regex that is basically a brute-force match of your values, each with a \b (word boundary) anchor
\b2\b|\b5\b|\b23\b|\bXXXL\b|\bXL\b|\bM\b|\bS\b
Sorry for not giving you a straight answer. regexp might be overkill in your case. A solution without it could, depending on your needs, be more maintainable.
I don't know which language you use so I will just pick one randomly. You could treat it as a piece of pseudo code.
In PHP:
function isValidSize($size) {
$validSizeTags = array("S", "M", "XL", "XXL");
$minimumSize = 2;
$maximumSize = 23;
if(ctype_digit(strval($size))) { // explanation for not using is_numeric/is_int below
if($size >= $minimumSize && $size <= $maxiumSize) {
return true;
}
} else if(in_array($size, $validSizeTags)) {
return true;
} else {
return false;
}
}
$size = "XS";
$isValid = isValidSize($size); // true
$size = 23;
$isValid = isValidSize($size); // true
$size = "23";
$isValid = isValidSize($size); // true, is_int would return false here
$size = 50;
$isValid = isValidSize($size); // false
$size = 15.5;
$isValid = isValidSize($size); // false, is_numeric would return true here
$size = "diadjsa";
$isValid = isValidSize($size); // false
(The reason for using ctype_digit(strval($size)) instead of is_int or is_numeric is that the first one will only return true for real integers, not strings like "15". And the second one will return true for all numeric values not just integers. ctype_digit will however return true for strings containing numeric characters, but return false for integers. So we convert the value to a string using strval before sending it to ctype_digits. Welcome to the world of PHP.)
With this logic in place you can easily inject validSizeTags, maximumSize and minimumSize from a configuration file or a database where you store all valid sizes for this specific product. That would get much messier using regular expressions.
Here is an example in JavaScript:
var patt = /^(?:\d{1,2}|X{0,3}[SML])$/i;
patt.test("2"); // true
patt.test("23"); // true
patt.test("XXXL"); // true
patt.test("S"); // true
patt.test("SLX"); // false
Use Array Membership Instead of Regular Expressions
Some problems are easier to deal with by using a different approach to representing your data. While regular expressions can be powerful, you might be better off with an array membership test if you are primarily interested in well-defined fixed values. For example, using Ruby:
sizes = %w[2 5 23 S XXXL].map(&:upcase)
size = 'XXXL'
sizes.include? size.to_s.upcase # => true
size = 'XL'
sizes.include? size.to_s.upcase # => false
seeing as it is being harder than i had thought, i am thinking to store the individual matched values in an array and match those individually against accepted values. i will use something like
[0-9]+|s|m|l|xl|xxl
and store the matches in the array
then i will check each array element against [0-9]+ and s|m|l|xl|xxl and if it matches any of these, it's valid. maybe there is a better way but i can't dwell on this for too long
thanks for your help
This will accept the alternatives one or more times, separated by whitespace or punctuation. It should be easy enough to expand the separator character class if you think you need to.
^([Xx]{0,3}[SsMmLl]|[0-9]+)([ ,:;-]+([Xx]{0,3}[SsMmLl]))*$
If you can interpolate the accepted pattern into a string before using it as a regex, you can reduce the code duplication.
This is a regular egrep pattern. Regex dialects differ between languages, so you might need to tweak something in order to adapt it to your language of choice (PHP? It's good form to include this information in the question).

Need help for regular expression for percent value

I am trying to pass value as 95%
numexu = 95%
"^((>|GT|>=|GE|<|LT|<=|LE|==|EQ|!=|NE)?\\s*\\d?[%]?)$
if (!regex.IsMatch(numexu))
throw new ArgumentException("Percent expression is in an invalid format.");
it is throwing exception in code.
Regards,
Regex
You are checking only for 1 number \\d?, try instead this: \\d{0,2}, this accepts 0, 1 or 2 numbers. The ? makes it 0 or 1 times matching.
I am not sure if you need to escape the %, if so then \\%. Additionally if you have only one character you can skip the brackets [%], so % (or \\%, if needed to escape)
This Function will work for your requirement
function check() {
var txtfield; txtfield =document.getElementById('txtbox').value;
var reg=/^(\d{0,2}%?$)/;
if(reg.test(txtfield)){
alert("match");
}
else { alert("Try again"); }
}