Creating a regex to check for a strong password - c#

Say I have a regex that checks for alphanumeric.
I now want to create another regex that checks for at least 1 number in the password.
And I want to check if it has at least 1 non-alphanumeric character (somethign other than a letter or number).
Should I just call each one seperatley, and if one fails return false or is there a way to combine them into 1 call?

Depends on exactly what criteria you're using, but it would probably be better to do a single pass through the string and set a number of flags based on what you've seen:
hasDigit
hasAlpha
hasSymbol
etc
Then use these at the end to decide if the password is complex enough.
Even Better:
As lexu suggests, using counts instead of flags would allow greater flexibility.

I would compose small methods using &&:
internal bool HasDigit(string password) { .. }
internal bool HasNonAlpha(string password) { .. }
bool IsStrong(string password) {
return HasDigit(password) && HasNonAlpha(password);
}

I think this is what you're looking for:
^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$
(will match a password with a minimum length of 6, with at least one digit and one non-alphanumerical character)
In code:
public bool PasswordOk(string pwd)
{
return Regex.IsMatch(pwd,#"^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$");
}

You should use two calls. For a bit more advanced testing you can use The password meter. It is freely available for distribution under GPL.

IMHO, it's a question of style whether to make one or two statements from it.
Why not check for it in any of the two orders that they may appear. (As regular expressions go, we don't have something like a counter for braces or parantheses, thus we have to honor the possible ordering of things.
That one might work for perl:
(\d.*[^[:alnum:]])|([^[:alnum:]].*\d)
Might be easier to read to make two statements from it, especially because then every semantical condition is only occurring once.

You add an | (or) operator into the regex e.g.
[0-9]|[A-Z]

Regex is not the fastest way.
Give this a try:
string Password = "Pass12!";
bool ValidPassword = Password.Any(char.IsDigit)
&& !Password.All(char.IsLetterOrDigit)
&& Password.Length >= 6;
Instead of:
string Password = "Pass12!";
bool ValidPassword = Regex.IsMatch(Password, #"^.{6,}(?<=\d.*)(?<=[^a-zA-Z0-9].*)$");
I you iterate through it 1 million times it will take the first 157ms and the second 1251ms.
And the most important thing the others said already: much better to maintain.

Related

How to compare in IF condition

I am returning a value from SQL. Let's give it a name as ReturnedFromSQL. In my application, I am giving an input. Let's give it a name as Input. I want to compare these two and do an activity. Currently, I am doing this with an IFcondition.
Let's say, from SQL I am getting FAB01and as the Input I am getting Fab01. What I want to do is to jump to ELSEpart after comparing these two if these two are not same and execute IF part if these two are same.
It is obvious that just the letters have changed but the idea is same. Since these two are same, I need to execute what is in IFpart instead of jumping to ELSE. But it is not happening now. How do I do that? Can anyone help me? Thank you in advance.
IF (ReturnedFromSQL == Input )
{
return RedirectToAction("Exist");
}
else
{
//Doing Something
}
Assuming that both ReturnedFromSQL and Input are strings. This code will convert both the value to lower for comparison so no issue if any of the string has same character but in different level(upper/lower)
if (ReturnedFromSQL.ToLower().Trim() == Input.ToLower().Trim() )
{
return RedirectToAction("Exist");
}
else
{
//Doing Something
}
You can use string.Equals(). The best part is that you do not need to trim or lowercase explicitly.
if(string.Equals(ReturnedFromSQL, Input, StringComparison.CurrentCultureIgnoreCase))
{
return RedirectToAction("Exist");
}
Take care if you follow the advice in some of the other answers. ToLower() is only safe in English and a handful of other languages. In many languages, there may be multiple upper/lower case representations of the same letter or letter combination, or certain accents may be considered equal or not equal, breaking such logic. There be the dragons.
Try this instead, changing the StringComparison as per your use case:
using System;
public class Program
{
public static void Main()
{
string ReturnedFromSQL = "FAB01";
string Input = "Fab01";
if (String.Equals(ReturnedFromSQL, Input, StringComparison.CurrentCultureIgnoreCase))
{
Console.WriteLine("Equal");
}
else
{
Console.WriteLine("Different");
}
}
}
if both values are string then you can apply ToLower() and Trim() (as in x.Trim().ToLower()) functions on both party in order to have a unified value. but even without that you still should be good, so i guess the problem is something else. i advise debugging the condition and check the value of both sides and see if either one is null or empty.
Your condition can use Equals
if (String.Equals(ReturnedFromSQL, Input, StringComparison.OrdinalIgnoreCase))

How to include and exclude patterns in one regex

Snippet
Let's say there are two regexes - one with patterns that are good and another with patterns that are wrong:
var allowed = new Regex("^(a.*|b.*)$");
var disallowed = new Regex("^(aa|bb|.*c)$");
When this snippet is run:
var cases = new[] {"a", "aa", "aaa", "b", "bb", "bbb", "ac", "bc", "ad", "ad"};
foreach (var c in cases)
Console.WriteLine($"{c}: {allowed.IsMatch(c) && !disallowed.IsMatch(c)}");
It works.
Questions
Is there a way to merge those two regexes into one?
Would it be a better design to create a set of regexes and enumerate over them to test if the input string matches any of the good patterns and none of the bad patterns?
You can simple put them together using a negative lookahead assertion:
(?!^(aa|bb|.*c)$)^(a.*|b.*)$
DEMO
You can shorten this regex by only specifying the parts you don't want. The rest should match:
(?!^(aa|bb|.*c)$)^.*$
DEMO
Using this you don't have the problem that you try to combine including and excluding regexes in one regex.
And finally you can try this regex:
^(a|b)(?!\1$).*(?<!c)$
DEMO
In answer to your second question: Depends on whether you want maintainability or speed.
If your rule sets are subject to constant change then I would think multiple sets would be easier to maintain, each set being specific enough to name them.
If you're looking for speed, let's say your parsing long documents or what have you, then a single one would be faster. Making them static readonly and then the difference is very negligible and MUCH, MUCH faster (around 10 times faster). The 'static readonly' really only applies when you move the logic out into a separate method, you wouldn't want to recreate the regex every call.
However, if you are looking both ... do it in code! There are many ways to write this, but they all seem to be around the same speed and that is over 6 times faster than the compiled regex. I believe this would be easier to maintain even without the comments but with a few comments it becomes very clear.
private bool IsAllowed(string word)
{
// empty string or whitespace is allowed
if (string.IsNullOrWhiteSpace(word)) return true;
// any word ending in the letter c is not allowed
if (word[word.Length - 1] == 'c') return false;
// any length that is not two letter is allowed
if (word.Length != 2) return true;
// allow anything except aa or bb
return word != "aa" && word != "bb";
}
Typically exclude regexes are very hard to write, even more so when combined with including matches. You could try using negative lookahead/lookbehind to do this.
Typically even when possible, the result is not very maintainable. Having seperate regexes for include and exclude is almost always better from an "I want to understand this code when I come back to it in 3 months" point of view.
You can combine the "good" patterns into a single regex - this should always be possible. It might even improve performance, as the regex compiler can optimise over all the patterns at once. But if there are a lot of them it then it may make maintenance more difficult - no one wants to read a 200 character regex.
So in summary, seperate regexes for include and exclude patterns, but smaller numbers of each are better, provided they don't get too complex. You'll have to use your judgement to work out what is best for your individual case.

C# read and react to a text string

assume that there is a string named "message", and assume an user type in the console,
"!My FB List", but words "FB" and "List" could be change. But "!My" won't change. So, I want to save the text the user type. Only if user used "!My" before the other words.
So, I don't know how to get this to 'if' command. Plz help me.
if (message == "!My "
Do you mean something like this?
if (message.StartsWith("!My "))
{
// do something
}
This code works in most situations. However, if you need to resolve situations like Kshitij Mehta mentioned in the comments, you'd be probably better off with a Split method parsing the string and comparing the first object of the array to the required string.
When you've split the input string into an array, you will just compare strings in a typical fashion (==), probably no need for fancy methods in that scenario.
One more "however" to consider - if your input string is long, splitting might not be the best idea to do. In that case I'd probably use regular expressions to compare the beginning of the inputted string.
The implementation depends on your needs. Just pick what suits you the best :)
It sounds like you want to accept commands and then do specific things based on those commands. Apparently, the "command" is the first word in the text typed by the user.
Thus, I'd split the message at whitespace and then switch for the first word:
var words = message.Split();
var command = words[0];
switch (command) {
case "!My":
// Do something
...
break;
case "!SomethingElse":
// Do something else
...
break;
...
}
Afterwards, you can use words[1] to get "FB" and words[2] to get "list". Be sure to use words.Length to verify if the required number of parameters has been specified before trying to access them.
String class includes many static methods, among which is StartsWith().
so your if statement can simply be
if(UserString.StartsWith("!My"))
{
// other conditional code here
}
It is not clear from your question whether you want to include cases where the user types "!My" before typing anything else, but he/she does NOT type a space immediately after typing !My.
If you only want to process the code if the three characters "!My" were followed by a space, then, (as suggested by #Walther), add a space to the test string in the StartsWith() method
if(UserString.StartsWith("!My "))
{
// other conditional code here
}

validate excel worksheet name

I'm getting the below error when setting the worksheet name dynamically. Does anyone has regexp to validate the name before setting it ?
The name that you type does not exceed 31 characters. The name does
not contain any of the following characters: : \ / ? * [ or ]
You did not leave the name blank.
You can use the method to check if the sheet name is valid
private bool IsSheetNameValid(string sheetName)
{
if (string.IsNullOrEmpty(sheetName))
{
return false;
}
if (sheetName.Length > 31)
{
return false;
}
char[] invalidChars = new char[] {':', '\\', '/', '?', '*', '[', ']'};
if (invalidChars.Any(sheetName.Contains))
{
return false;
}
return true;
}
To do worksheet validation for those specified invalid characters using Regex, you can use something like this:
string wsName = #"worksheetName"; //verbatim string to take special characters literally
Match m = Regex.Match(wsName, #"[\[/\?\]\*]");
bool nameIsValid = (m.Success || (string.IsNullOrEmpty(wsName)) || (wsName.Length > 31)) ? false : true;
This also includes a check to see if the worksheet name is null or empty, or if it's greater than 31. Those two checks aren't done via Regex for the sake of simplicity and to avoid over engineering this problem.
Let's match the start of the string, then between 1 and 31 things that aren't on the forbidden list, then the end of the string. Requiring at least one means we refuse empty strings:
^[^\/\\\?\*\[\]]{1,31}$
There's at least one nuance that this regex will miss: this will accept a sequence of spaces, tabs and newlines, which will be a problem if that is considered to be blank (as it probably is).
If you take the length check out of the regex, then you can get the blankness check by doing something like:
^[^\/\\\?\*\[\]]*[^ \t\/\\\?\*\[\]][^\/\\\?\*\[\]]*$
How does that work? If we defined our class above as WORKSHEET, that would be:
^[^WORKSHEET]*[^\sWORKSHEET][^WORKSHEET]*$
So we match one or more non-forbidden characters, then a character that is neither forbidden nor whitespace, then zero or more non-forbidden characters. The key is that we demand at least one non-whitespace character in the middle section.
But we've lost the length check. It's hard to do both the length check and the regex in one expression. In order to count, we have to phrase things in terms of matching n times, and the things being matched have to be known to be of length 1. But in order to allow whitespace to be placed freely - as long as it's not all whitespace - we need to have a part of the match that is not necessarily of length 1.
Well, that's not quite true. At this point this starts to become a really bad idea, but nevertheless: onwards, into the breach! (for educational purposes only)
Instead of using * for the possibly-blank sections, we can specify the number we expect of each, and include all the possible ways for those three sections to add up to 31. How many ways are there for two numbers to add up to 30? Well, there's 30 of them. 0+30, 1+29, 2+28, ... 30+0:
^[^WORKSHEET]{0}[^\sWORKSHEET][^WORKSHEET]{30}$
|^[^WORKSHEET]{1}[^\sWORKSHEET][^WORKSHEET]{29}$
|^[^WORKSHEET]{2}[^\sWORKSHEET][^WORKSHEET]{28}$
....
|^[^WORKSHEET]{30}[^\sWORKSHEET][^WORKSHEET]{0}$
Obviously if this was a good idea, you'd write a program that expression rather than specifying it all by hand (and getting something wrong). But I don't think I need to tell you it's not a good idea. It is, however, the only answer I have to your question.
While admittedly not actually answering your question, I think #HatSoft has the right approach, encoding the conditions directly and clearly. After all, I'm now satisfied that an answer to your question as asked is not actually a helpful thing.
You might want to do a check for the name History as this is a reserved sheet name in Excel.
Something like that?
public string validate(string name)
{
foreach (char c in Path.GetInvalidFileNameChars())
name = name.Replace(c.ToString(), "");
if (name.Length > 31)
name = name.Substring(0, 31);
return name;
}

Phone Number Formatting, OnBlur

I have a .NET WinForms textbox for a phone number field. After allowing free-form text, I'd like to format the text as a "more readable" phone number after the user leaves the textbox. (Outlook has this feature for phone fields when you create/edit a contact)
1234567 becomes 123-4567
1234567890 becomes (123) 456-7890
(123)456.7890 becomes (123) 456-7890
123.4567x123 becomes 123-4567 x123
etc
A fairly simple-minded approach would be to use a regular expression. Depending on which type of phone numbers you're accepting, you could write a regular expression that looks for the digits (for US-only, you know there can be 7 or 10 total - maybe with a leading '1') and potential separators between them (period, dash, parens, spaces, etc.).
Once you run the match against the regex, you'll need to write the logic to determine what you actually got and format it from there.
EDIT: Just wanted to add a very basic example (by no means is this going to work for all of the examples you posted above). Geoff's suggestion of stripping non-numeric characters might help out a bit depending on how you write your regex.
Regex regex = new Regex(#"(?<areaCode>([\d]{3}))?[\s.-]?(?<leadingThree>([\d]{3}))[\s.-]?(?<lastFour>([\d]{4}))[x]?(?<extension>[\d]{1,})?");
string phoneNumber = "701 123-4567x324";
Match phoneNumberMatch = regex.Match(phoneNumber);
if(phoneNumberMatch.Success)
{
if (phoneNumberMatch.Groups["areaCode"].Success)
{
Console.WriteLine(phoneNumberMatch.Groups["areaCode"].Value);
}
if (phoneNumberMatch.Groups["leadingThree"].Success)
{
Console.WriteLine(phoneNumberMatch.Groups["leadingThree"].Value);
}
if (phoneNumberMatch.Groups["lastFour"].Success)
{
Console.WriteLine(phoneNumberMatch.Groups["lastFour"].Value);
}
if (phoneNumberMatch.Groups["extension"].Success)
{
Console.WriteLine(phoneNumberMatch.Groups["extension"].Value);
}
}
I think the easiest thing to do is to first strip any non-numeric characters from the string so that you just have a number then format as mentioned in this question
I thought about stripping any non-numeric characters and then formatting, but I don't think that works so well for the extension case (123.4567x123)
Lop off the extension then strip the non-numeric character from the remainder. Format it then add the extension back on.
Start: 123.4567x123
Lop: 123.4567
Strip: 1234567
Format: 123-4567
Add: 123-4567 x123
I don't know of any way other than doing it yourself by possibly making some masks and checking which one it matches and doing each mask on a case by case basis. Don't think it'd be too hard, just time consuming.
My guess is that you could accomplish this with a conditional statement to look at the input and then parse it into a specific format. But I'm guessing there is going to be a good amount of logic to investigate the input and format the output.
This works for me. Worth checking performance if you are doing this in a tight loop...
public static string FormatPhoneNumber(string phone)
{
phone = Regex.Replace(phone, #"[^\d]", "");
if (phone.Length == 10)
return Regex.Replace(phone,
"(?<ac>\\d{3})(?<pref>\\d{3})(?<num>\\d{4})",
"(${ac}) ${pref}-${num}");
else if ((phone.Length < 16) && (phone.Length > 10))
return Regex.Replace(phone,
"(?<ac>\\d{3})(?<pref>\\d{3})(?<num>\\d{4})(?<ext>\\d{1,5})",
"(${ac}) ${pref}-${num} x${ext}");
else
return string.Empty;
}

Categories

Resources