Combination of rules with Regex - android

In an android project, im trying to validate a password that the user inputs, and it must follow some rules
The rules are:
it must have 7 characters and 3 of the following conditions
**
-One lowercase character
-One uppercase character
-One number
-One special character
**
for example:
asd123!!!
PPPppp000
TTT999###
i was trying with this regex
^(?=.*?[A-Z])(?=.*?[a-z])(?=.*?[0-9])(?=.*?[#?!#$%^&*-]).{7,}+$
but this enforces all rules at same time.

The approach is wrong here. The regex you created looks like a monster from under the bed, and is highly illegible even for someone regex-literate.
Why not split it into 4 (or as much as there are rules) regexes and check against whether 3 of them return a match? Not only will you make your regexes cleaner, but you will be able to add more rules if need be without changing whole regex.
You can also use inbuilt methods for checking (if applicable under Android development kit).
Some pseudocode would look like this:
result1 = Regex.IsMatch(password, rule1regex)
result2 = Regex.IsMatch(password, rule2regex)
...
resultN = Regex.IsMatch(password, rule3regex)
if(three_out_of_four_rules_apply)
password_valid = true
You can also apply method suggested in comments by #pskink and iterate over each character of a password and set the output accordingly.

Without going into the details of your lookaheads (which seem correct), here's how you would need to implement "three out of four criteria" in pure regex :
(?=.*A)(?=.*B)(?=.*C)|(?=.*A)(?=.*B)(?=.*D)|(?=.*A)(?=.*C)(?=.*D)|(?=.*B)(?=.*C)(?=.*D)
You can test it here.
Factorizing doesn't really make it better :
(?=.*A)(?:(?=.*B)(?=.*(?:C|D))|(?=.*C)(?=.*D))|(?=.*B)(?=.*C)(?=.*D)
I obviously recommend using a higher level language to implement these sorts of constraints.

Related

Regular Expression failed when I try to get all files that name only contains number

I try to list all the files under "/proc" on my android device,and get all those files' names only contain numbers,such as '123','435'.I try to filter those by regular expression.I tried three expressions below but all of these failed sometimes:
^[0-9]+$
[0-9]+
\d+
I wonder how can the three expressions can match such as "14971" but can't match "15003"?
I think boober Bunz is right, that the file extension is the difference.
All three of your expressions match both
"14971"
and
"15003"
the best way is to pull the extensions off the fileNames, and then use the most restrictive expression you need to: ^[0-9]+$
or if you want to just leave the extension on, this would most likely work for you:
"^[0-9]+[.][^.]*$"
start of string, one or more digits, must have a . and then any number of non . end of string. this would not match:
"123.123.txt"

Password regex string in strings.xml file in android

I have declared a regex for password validation purposes in strings.xml file.
The criteria is
-should be atleast 8 characters
-should contain atleast one upper case letter
-should contain atleast one lower case letter
-should contain atleast one special character within these "##$%^+&="
So my whole regex looks like this now
^(?=.[0-9])(?=.[a-z])(?=.[A-Z])(?=.[##$%^+&=])(?=\S+$).{8,}$
But when I enter this, I get an error saying that & is
"Unescaped or non terminated character entity/reference"
So instead I used the escape sequence as & but the validation fails for &
I would b glad if anyone could help me out on this!!
Use * quantifers in the look-aheads. Right now, you check if 2nd character in the string meets your conditions. We need to test them all in the string.
^(?=.*[0-9])(?=.*[a-z])(?=.*[A-Z])(?=.*[##$%^+&=])(?=\S+$).{8,}$
Here is a demo.
EDIT
Since the regex is located inside the XML code, it should be properly encoded. Or, use it inside CDATA block.
Are you missing a parameter in your curly braces? The last bit "{8,}" seems off.

Changing text input to also treat "u" as "ü", "ss" as "ß", etc. for word suggestions

I have the following idea:
In German we have four extra letters (ä, ö, ü, ß) and I don't know any other language which has these vocals but I think French people with their accents also know this problem. We have a lot of apps in the Google Play store for cities, bus stations, trains and other stuff like that. Now it is really exhausting that we always have to write these letters if we are on the go. It would be much easier to write Munchen (=München [de] = Munich [en]), Osterreich (Österreich [de] = Austria [en]) or something like Uberwasserstrasse (Überwasserstraße [de] = Over-Water-Street [en]). So my question is now:
A lot of apps show suggestions for our just typed word. I think in the code it is something like this:
String current = editText.getText().toString();
db.lookUp(current); // Of course SQL statement
Can we hook this so that Android thinks that we have typed an ä, ö, ü, ß if we write an a, o, u, ss and the system looks for words with one of these vowels and suggests both? Here I do not want to ask for code - I want to discuss if we are able to write a hack or hook for the Android system. Also, root-rights can be assumed with the solution. I'm looking forward to your ideas.
You could do this the other way around, by "normalizing" typed characters into their related non-diacritical versions. You can use the java.Text.Normalizer class for this. A good snippet can be found in this article:
public static String removeAccents(String text) {
return text == null ? null :
Normalizer.normalize(text, Form.NFD)
.replaceAll("\\p{InCombiningDiacriticalMarks}+", "");
}
When applied to "Münich", this returns "Munich". That way, you can use a simple string comparison using these normalized versions.
This wouldn't work for "ß" though. If that's the only special case, you could handle it separately.
What you are looking for is called accent-insensitive collating sequence. SQLite's COLLATE operator can be used to do such searches, but I learned from another post that there might be bugs you'll need to look out for.

pathPattern in intent-filter matching literal period

I have read quite a few other SOs on this - in particular the highly-voted answer to this question: Android intent filter for a particular file extension?
My scenario is somewhat simpler - I simply want to match a particular filename on our website - e.g. http://our_domain/filename.extn - but taking into account some minor variance in case (I call this out further down).
I've written my intent-filter as follows:
<data
android:scheme="http"
android:host="our_domain"
android:pathPattern="/filename\\.extn" />
Double-escaping the \ so that it will be read out of the XML as \., thus escaping the period so that the pattern matcher sees a literal . instead of the 'any' character.
For my tests I've written a small app that takes a string from a text box, creates an ACTION_VIEW intent with the given URI, and starts it - then checking whether the browser launches or whether I see a chooser with my app listed.
The app is correctly identified for the exact path - e.g. http://our_domain/filename.extn, but it is also being identified if I replace the . with any other character that's valid in a URI path - e.g, all of the following also trigger a match:
http://our_domain/filename'extn
http://our_domain/filename~extn
http://our_domain/filenameaextn
The last of which is the most worrying!
How can I set the path pattern to ensure that only a literal period matches?
Please note, I am aware that simply using path instead of pathPattern might work - however, the pattern also incorporates some minor case-insensitivity - e.g. F*f*ileN*n*ame - I have removed this stuff for the question as it makes no difference to the behaviour of this period-matching.
Is it possible that matching only literal . characters is actually not supported by the intent-filter system (not by design but by bug), and that they'll always be treated as 'any'?
Is it possible that matching only literal. characters is actually not supported by the intent-filter system (not by design but by bug), and that they'll always be treated as 'any'?
Yes, this looks like an android bug. I've just gone through the source code of android's PatternMatcher and this behaviour (bug?) is present to this day.
I.e. it looks like matching the . literal only works in one case - when it's preceded by a * expression. Only then it is properly escaped in code - \\ is taken into consideration). That's why people who are just trying to match a file extension are able to use a pattern like this:
<data android:pathPattern=".*\\.ext" />
As soon as the escape sequence (\\) is preceded by something else than *, the escaping is not taken into account and the dot (.) is treated as a wildcard rather than as a literal and matches any character.
I've been thinking whether I should report this bug, but it might not be worth it, considering how few people have run into it. I looked for similar SO questions, but haven't found any. Also, the . wildcard is not even mentioned as a valid wildcard in the documentation. The only valid wildcards according to the documentation are .* and *.
Just guessing here, you might try (hack) wrapping it in [], like this: pattern="filename[.]extn", so you're only accepting characters from the following list: "." - give it a shot?
There are plenty of other regex games you could probably play, but that's the first one that comes to mind.

Android: converting between Strings, SpannedStrings and Spannablestrings

I have a string resource called "foo". It may be a simple string... or it may contain HTML. This may change over time: I should be able to box it up as at least a SpannableString immediately upon reading whether it's HTML or not (but how??)
I want to get that raw CharSequence and first be able to display it as-is (the exact characters, not Android's "interpretation" of it). Right now I can't do that... toString() decides to rip out the parts it doesn't think I want to see.
I'd then like to be able to create a SpannableString from this and other Strings or SpannableStrings via concatenation using some method (none of the normal ones work). I'd like to then use that SpannableString to display the HTML-formatted text in a TextView.
This shouldn't be difficult, but clearly I'm not doing it right (there's very little info out there about this that I've found so far). Surely there is a way to accurately interconvert between between Strings, SpannedStrings and even Spannablestrings, without losing the markups along the way?
Note that I've already played with the somewhat broken Linkify, but I want better control over the process (no dangling unformatted "/"s, proper hrefs, etc.) I can get this all to work IF I stay in HTML at all steps, though I can't concatenate anything.
Edit 1: I've learned I can use the following to always ensure I get my raw string (instead of whatever Android decides it thinks the CharSequence really is). Nice... now, how to coax this into a SpannableString?
<string name="foo"><![CDATA[
<b>Some bold</b>
]]>
</string>
Edit 2: Not sure why this didn't work earlier, but... if foo1 and foo2 are strings marked up as above (as CDATA), then one can apparently do this:
String foo1 = (String)getResources().getText(R.string.foo1);
String foo2 = (String)getResources().getText(R.string.foo2);
SpannedString bar = new SpannedString(Html.fromHtml(foo1+foo2));
Curious: is there a more straightforward solution than this? Is this CDATA business actually necessary? It seems convoluted (but not as convoluted as never quite knowing what the resource type will be... String, Spannable, etc.)
I had the same problem. There are two solutions according to Google API Guides.
First is to escape < mark with < in the string resource. Unfortunately, String conversion removes the tag in the background.
Second is to use Format Strings instead of XML/HTML tags. It seems simpler, faster, and evades hidden conversion problems. getString(resource, ...) works like a printf(string, ...) here.
Both work and require some code to replace given part of the string anyway (handle tags or format strings). Enjoy! =)
It appears there isn't a more straightforward way to accomplish this.

Categories

Resources