David Heisnam
David Heisnam

Reputation: 2491

Why is this regular expression matching unwanted special characters?

I'm using the following regular expression in PHP to test password validity.

I'm allowing numbers, letters and special characters ~!@#$%^&*()-_=+[]{}\|;:'",.<>/?

preg_match('/^[`~\!@#\$%\^&*\(\)\-_\=\+\[\]\{\}\\\|;\:\'",\.\<\>\/\?a-zA-Z\d]+$/', $password);

It seems to work because it returns true when $password is~!@#$%^&*()-_=+[]{}\|;:'",.<>/? but returns false when I add a whitespace in between.

My problem is that when the password contains and similar characters, it returns true. This is really undesirable. How do I fix this?

I know little about regex so if there is a better way to do this, please let me know.

Upvotes: 0

Views: 65

Answers (3)

Shiping
Shiping

Reputation: 1327

I tried it and it worked (the match returned false(0)) with the special character ♣ if I added the meta line. Without the meta line, the matching returned true(1). Not sure if you already have the meta line in head.

<head>
<meta charset="UTF-8">
...
</head>

Upvotes: 0

chris85
chris85

Reputation: 23892

Since the var_dump of has a length of 7 you have &#9827; not the character, . This information is obtainable by viewing the source of the page. Don't debug in a standard browser page because not everything is displayed there.

After chatting with you and seeing your form the issue is that you don't have the character set for your page so the browser is converting multibyte characters to their decimal entities. Adding

<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />

should resolve the issue.

You also are over escaping, in a character there are a small number of characters that need escaping. Here's a simplified regex:

^[`~!@#$%\^&*()\-_=+\[\]{}\\|;:\'",.<>\/?a-zA-Z\d]+$

The entity matched your rule because &s, #s, ;s, and numbers are allowed.

Upvotes: 1

ssc-hrep3
ssc-hrep3

Reputation: 16079

Add a u flag after the regular expression to support Unicode characters (The flag is after the final slash):

preg_match('/^[`~\!@#\$%\^&*\(\)\-_\=\+\[\]\{\}\\\|;\:\'",\.\<\>\/\?a-zA-Z\d]+$/u', $password);

See the official PHP documentation for further information.

Upvotes: 1

Related Questions