Need to know what this regex does, is it safe? - php

Updating someone else's old PHP project and I'm unfamiliar with regular expressions.
Question one is: What does this do?
preg_match('/^[0-9]+[.]?[0-9]*$/', $variable)
Question two is: Is this a safe filter for insertion into a mysql DB without mysql_real_escape_string()? I know the answer is prob no, but it is set up to use mysql_real_escape_string() only if this regex doesn't pass.
Thanks.

^ // start of string
[0-9]+ // one or more numbers (could also be \d+)
[.]? // zero or one period (could also be \.?)
[0-9]* // zero or more numbers (could also be \d*)
$ //end of string
So, it makes sure the input is a number, such as 12 or 3.6 (52. will also match). It will not match .35 or 12a6.
It seems safe enough for DB insertion, because it only allows numbers.

it matches strings that:
start with at least 1 digit from 0-9
have a decimal point after the first n digits 0 or 1 time
have any digit after a char 0 or more times

It does not sanitise string for database.
It checks if $variable matches this pattern...
starts with one or more digits (^[0-9]+)
followed by optional . ([.]?)
followed by as many or as few digits as you like ([0-9]*)
followed by the end of the string ($)

It's attempting to match a decimal number (albeit poorly). It doesn't modify $variable anyway, so you would need to escape it properly before passing to MySQL.

That will match a number that has at least one digit before the decimal point (if there is a decimal point). If the value matches this regex, I don't see how it could be unsafe to insert it into the database.

looks if the a exact match.
it matches
234234232432343.231313132321
and
2232233223
and
322332.
and not
.32232
and not

Is this a safe filter for insertion into a mysql DB without mysql_real_escape_string()?
Assuming the possible use of this variable, I'd say that mysql_real_escape_string() would be quite useless for it.
Need the query assembling code to be certain though.

Related

PCRE(php) Is it possible to check if sequence of numbers contains only unique number for that sequence?

Assuming I have a set of numbers (from 1 to 22) divided by some trivial delimiters (comma, point, space, etc). I need to make sure that this set of numbers does not contain any repetition of the same number. Examples:
1,14,22,3 // good
1,12,12,3 // not good
Is it possible to do via regular expression?
I know it's easy to do using just php, but I really wander how to make it work with regex.
Yes, you could achieve this through regex via negative looahead.
^(?!.*\b(\d+)\b.*\b\1\b)\d+(?:,\d+)+$
(?!.*\b(\d+)\b.*\b\1\b) Negative lookahead at the start asserts that the there wouldn't be a repeated number present in the match. \b(\d+)\b.*\b\1\b matches the repeated number.
\d+ matches one or more digits.
(?:,\d+)+ One or more occurances of , , one or more digits.
$ Asserts that we are at the end .
DEMO
OR
Regex for the numbers separated by space, dot, comma as delimiters.
^(?!.*\b(\d+)\b.*\b\1\b)\d+(?:([.\s,])\d+)(?:\2\d+)*$
(?:([.\s,])\d+) capturing group inside this non-capturing group helps us to check for following delimiters are of the same type. ie, the above regex won't match the strings like 2,3 5.6
DEMO
You can use this regex:
^(?!.*?(\b\d+)\W+\1\b)\d+(\W+\d+)*$
Negative lookahead (?!.*?(\b\d+)\W+\1\b) avoids the match when 2 similar numbers appear one after another separated by 1 or more non-word characters.
RegEx Demo
Here is the solution that fit my current need:
^(?>(?!\2\b|\3\b)(1\d{1}|2[0-2]{1}|\d{1}+)[,.; ]+)(?>(?!\1\b|\3\b)(1\d{1}|2[0-2]{1}|\d{1}+)[,.; ]+)(?>(?!\1\b|\2\b)(1\d{1}|2[0-2]{1}|\d{1}+))$
It returns all the sequences with unique numbers divided by one or more separator and also limit the number itself from 1 to 22, allowing only 3 numbers in the sequence.
See working example
Yet, it's not perfect, but work fine! Thanks a lot to everyone who gave me a hand on this!

Regex for two latitudes and longitudes not working

I am using some data which gives paths for google maps either as a path or a set of two latitudes and longitudes. I have stored both values as a BLOB in a mySql database, but I need to detect the values which are not paths when they come out in the result. In an attempt to do this, I have saved them in the BLOB in the following format:
array(lat,lng+lat,lng)
I am using preg_match to find these results, but i havent managed to get any to work. Here are the regex codes I have tried:
^[a]{1}[r]{2}[a]{1}[y]{1}[\(]{1}[1-9\.\,\+]{1*}[\)]{1}^
^[a]{1}[r]{2}[a]{1}[y]{1}[\(]{1}(\-?\d+(\.\d+)?),(\-?\d+(\.\d+)?)\+(\-?\d+(\.\d+)?),(\-?\d+(\.\d+)?)[\)]{1}^
Regex confuses me sometimes (as it is doing now). Can anyone help me out?
Edit:
The lat can be 2 digits followed by a decimal point and 8 more digits and the lng can be 3 digits can be 3 digits follwed by a decimal point and 8 more digits. Both can be positive or negative.
Here are some example lat lngs:
51.51160000,-0.12766000
-53.36442000,132.27519000
51.50628000,0.12699000
-51.50628000,-0.12699000
So a full match would look like:
array(51.51160000,-0.12766000+-53.36442000,132.27519000)
Further Edit
I am using the preg_match() php function to match the regex.
Here are some pointers for writing regex:
If you have a single possibility for a character, for example, the a in array, you can indeed write it as [a]; however, you can also write it as just a.
If you are looking to match exactly one of something, you can indeed write it as a{1}, however, you can also write it as just a.
Applying this lots, your example of ^[a]{1}[r]{2}[a]{1}[y]{1}[\(]{1}[1-9\.\,\+]{1*}[\)]{1}^ reduces to ^array\([1-9\.\,\+]{1*}\)^ - that's certainly an improvement!
Next, numbers may also include 0's, as well as 1-9. In fact, \d - any digit - is usually used instead of 1-9.
You are using ^ as the delimiter - usually that is /; I didn't recognize it at first. I'm not sure what you can use for the delimiter, so, just in case, I'll change it to the usual /.This makes the above regex /array\([\d\.\,\+]{1*}\)/.
To match one or more of a character or character set, use +, rather than {1*}. This makes your query /array\([\d\.\,\+]+\)/
Then, to collect the resulting numbers (assuming you want only the part between the brackets, put it in (non-escaped) brackets, thus: /array\(([\d\.\,\+]+)\)/ - you would then need to split them, first by +, then by ,. Alternatively, if there are exactly two lat,lng pairs, you might want: /array\(([\d\.]+),([\d\.]+)\+([\d\.]+),([\d\.]+)\)/ - this will return 4 values, one for each number; the additional stuff (+, ,) will already be removed, because it is not in (unescaped) brackets ().
Edit: If you want negative lats and longs (and why wouldn't you?) you will need \-? (a "literal -", rather than part of a range) in the appropriate places; the ? makes it optional (i.e. 0 or 1 dashes). For example, /array\((\-?[\d\.]+),(\-?[\d\.]+)\+(\-?[\d\.]+),(\-?[\d\.]+)\)/
You might also want to check out http://regexpal.com - you can put in a regex and a set of strings, and it will highlight what matches/doesn't match. You will need to exclude the delimiter / or ^.
Note that this is a little fast and loose; it would also match array(5,0+0,1...........). You can nail it down a little more, for example, by using (\-?\d*\.\d+)\) instead of (\-?[\d\.]+)\) for the numbers; that will match (0 or 1 literal -) followed by (0 or more digits) followed by (exactly one literal dot) followed by (1 or more digits).
This is the regex I made:
array\((-*\d+\.\d+),(-*\d+\.\d+)\+(-*\d+\.\d+),(-*\d+\.\d+)\)
This also breaks the four numbers into groups so you can get the individual numbers.
You will note the repeated pattern of
(-*\d+\.\d+)
Explanation:
-* means 0 or more matches of the - sign ( so - sign is optional)
\d+ means 1 or more matches of a number
\. means a literal period (decimal)
\d+ means 1 or more matches of a number
The whole thing is wrapped in brackets to make it a captured group.

Regular Expression for starting woth specfic number

How to write regular expression for following conditions:
Should have only numbers
Must be 8 digits long
Must start with 8 or 9 or 6
So for I can do only for first two conditions. I am not sure how to do the third conditions
My code is
if (!preg_match('/^[0-9]{8}$/', $number))
You're almost there. Simply remove the first number from the character class and validate it at the start of your pattern...
/^(8|9|6)\d{7}$/
FYI - \d is the escape sequence for digits. I suppose you could also use this
/^[896]\d{7}$/
as it means about the same thing when you're only watching for a single character at the start.

Using regex/preg_match() to check if a set of coordinates in decimal degrees is valid

I've learnt a bit of basic regex to wet my feet, but it's all still a bit too complicated for me. I need to take a set of user-inputted coordinates in decimal degrees (example):
$latitude = -42.323432
$longitude = 176.232123
and check whether they're valid using the preg_match() function in PHP. Seems simple, but I can't write the regular expression for the life of me that would ensure that no bad data gets through. I'll check the northing and easting separate of each other so this preg_match() will be iterated through twice using a foreach loop.
I think I've figured out all the necessary conditions:
The first character can either be a minus, a plus, or a number. The minuses and pluses are optional.
The total count of numbers before the decimal point can be 1 to 3, but not 0 or above 3.
Therefore there must be a decimal point in either the second place, or the fourth place. (2.2332, -123.422)
There must be at EXACTLY one decimal point in the whole string, there can be 0 OR 1 minuses or pluses in the whole string.
I want at least 3 decimal places of precision AFTER the decimal point. There is no maximum limit (I'll simply round it to 6 dp myself)
If there are any characters besides numbers, a decimal point, and an optional plus and minus, reject it.
After this though, I'm stuck! Any help would be appreciated in writing the regex expression. Thanks...
Let's take a stab at it:
/^[+\-]?[0-9]{1,3}\.[0-9]{3,}\z/
Broken down:
^ - start of string
[+\-]? - zero or one from set of `+` and `-`
[0-9]{1,3} - 1 to 3 digits
\. - decimal point
[0-9]{3,} - 3 or more digits
\z - end of string
(note, this is untested ;))

Sha 1 php, possible variations and regex

First,
Is it possible for a sha1 hash to be all numbers or letters,
And second is there any need for the start and end delimiters when using a regex to check for a sha 1 hash, ie,
/^[0-9a-f]{40}$/i
inplace of
/[0-9a-f]{40}/i
Is there any need to use the delimeters?
I ask as should I check if the pattern has at least one number and at least one letter, or does this not matter?
A sha1 hash is a 160 bit value that can be between all 0s and all 1s. This means that yes, in theory it can be all numbers or all letters (more specifically, the hex representation of it can be).
As for the beginning and ending markers, they are required unless you check the string in other ways. The two patterns you posted are not equivalent:
/^[0-9a-f]{40}$/i
A string that consists of and only of 40 character in 0-9 or a-f.
/[0-9a-f]{40}/i
A string that contains 40 character in 0-9 or a-f in a row.
In other words, the first pattern would consider this invalid whereas the second would not:
|0000000000000000000000000000000000000000|
The second pattern would match the 40 valid characters in the middle and not care about the rest of it.
You could effectively turn the second pattern into the first if you also used strlen to verify that the string is exactly 40 characters. This would be a bit redundant though, as you'd essentially then have a pattern of:
A string that: (contains 40 characters in 0-9 or a-f in a row) and (is exactly 40 characters).
The first version expresses it more compactly, though the second is a bit more obvious.

Categories