Mentioned below is a dummy Email ID say,
abcdefghij#gmail.com
How to mask this email ID partially using PHP?
Output i need as
a*c*e*g*i*#gmail.com
I have tried the below code, But it not works for below requirement
$prop=3;
$domain = substr(strrchr($Member_Email, "#"), 1);
$mailname=str_replace($domain,'',$Member_Email);
$name_l=strlen($mailname);
$domain_l=strlen($domain);
for($i=0;$i<=$name_l/$prop-1;$i++)
{
$start.='*';
}
for($i=0;$i<=$domain_l/$prop-1;$i++)
{
$end.='*';
}
$MaskMail = substr_replace($mailname, $start,2, $name_l/$prop).substr_replace($domain, $end, 2, $domain_l/$prop);
Give a try like this.
$delimeter = '#';
$mail_id = 'abcdefghij#gmail.com';
$domain = substr(strrchr($mail_id, $delimeter), 1);
$user_id = substr($mail_id,0,strpos($mail_id, $delimeter));
$string_array = str_split($user_id);
$partial_id = NULL;
foreach($string_array as $key => $val){
if($key % 2 == 0){
$partial_id .=$val;
}else{
$partial_id .='*' ;
}
}
echo $partial_id.$delimeter.$domain;
Here's a no loop approach to replace every second character of an email username with a mask.
Custom PHP function using native functions split, preg_replace with regex /(.)./, and implode:
echo email_mask('abcdefghi#gmail.com');
// a*c*e*g*i*k*#gmail.com
function email_mask($email) {
list($email_username, $email_domain) = split('#', $email);
$masked_email_username = preg_replace('/(.)./', "$1*", $email_username);
return implode('#', array($masked_email_username, $email_domain));
}
Regex Explanation:
The regular expression starts at the beginning of the string, matches 2 characters and captures the first of those two, replaces the match with the first character followed by an asterisk *. preg_replace repeats this throughout the remaining string until it can no longer match a pair of characters.
$mail='abcdefghij#gmail.com';
$mail_first=explode('#',$mail);
$arr=str_split($mail_first[0]);
$mask=array();
for($i=0;$i<count($arr);$i++) {
if($i%2!=0) {
$arr[$i]='*';
}
$mask[]=$arr[$i];
}
$mask=join($mask).'#'.$mail_first[1];
echo $mask;
Result is :
a*c*e*g*i*#gmail.com
Does it need to have that many asterisks?
It's so hard to read that way.
I will suggest you keep things simple.
Maybe something like this is enough
https://github.com/fedmich/PHP_Codes/blob/master/mask_email.php
Masks an email to show first 3 characters and then the last character before the # sign
ABCDEFZ#gmail.com becomes
A*****Z#gmail.com
Here is the full code that is also in that Github link
function mask_email( $email ) {
/*
Author: Fed
Simple way of masking emails
*/
$char_shown = 3;
$mail_parts = explode("#", $email);
$username = $mail_parts[0];
$len = strlen( $username );
if( $len <= $char_shown ){
return implode("#", $mail_parts );
}
//Logic: show asterisk in middle, but also show the last character before #
$mail_parts[0] = substr( $username, 0 , $char_shown )
. str_repeat("*", $len - $char_shown - 1 )
. substr( $username, $len - $char_shown + 2 , 1 )
;
return implode("#", $mail_parts );
}
Related
I searched the system but couldn't find any help I could understand on this, so here goes...
I need to find an approximate match for a string in php.
Essentially I'm checking that all the $names are in the $cv string and if not it sets a flag to true.
foreach( $names as $name ) {
if ( strrpos( $cv, $name ) === false ) {
$nonameincv = true;
}
}
It works fine. However, I had a case of $cv = "marie_claire" and a $name = "clare" which set the flag (of course) but which I'd have liked for strpos to have "found" as it were.
Is it possible to do an approximate match so that if a string has 1 extra letter anywhere in it, it would match? For example so that:
$name = "clare" is found in $cv = "marie_claire"
$name = "caire" is found in $cv = "marie_claire"
$name = "laire" is found in $cv = "marie_claire"
and so on...
Note: This will work perfectly fine when there is difference of 1 character, as stated in question above.
Try this code snippet here
<?php
ini_set('display_errors', 1);
$stringToSearch="mare";
$wholeString = "marie_claire";
$wholeStringArray= str_split($wholeString);
for($x=0;$x<strlen($wholeString);$x++)
{
$tempArray=$wholeStringArray;
unset($tempArray[$x]);
if(strpos(implode("", $tempArray), $stringToSearch)!==false)
{
echo "Found: $stringToSearch in ".implode("", $wholeStringArray);
break;
}
}
Try this, not considering performance, but would work for your case.You can play with the the number of different chars deviation you want to accept.
$names = array("clare", "caire", "laire");
$cv = "marie_claire";
foreach( $names as $name ) {
$sname = str_split($name);
$words = explode('_', $cv);
foreach($words as $word) {
$sword = str_split($word);
$result = array_diff($sword, $sname);
if(count($result) < 2)
echo $name. ":true\r\n";
}
}
How could this be done with regex?
return ( $s=='aa' || $s=='bb' || $s=='cc' || $s=='dd' ) ? 1 : 0;
I am trying:
$s = 'aa';
$result = preg_match( '/(aa|bb|cc|dd)/', $s );
echo $result; // 1
but obviously this returns 1 if $s contains one or more of the specified strings (not when it is equal to one of them).
You need to use start ^ and end $ anchors to do an exact string match.
$result = preg_match( '/^(aa|bb|cc|dd)$/', $s );
$s = 'aa';
$result = preg_match( '/^(aa|bb|cc|dd)$/', $s );
echo $result;
Use ^ and $ to specify the to match from the beginning of the input till the end.
I think RegEx overkill for this problem.
My solution:
$results = array('aa', 'bb', 'cc', 'dd');
$c = 'aa';
if(in_array($c, $results, true)) {
echo 'YES';
} else {
echo 'NO';
}
I'm doing some maintenance on a clients website that uses the simple mysql_query() function for all of their database queries. On one of their pages, a query is done to pull user information based on their nickname. The file is very robust and going through and changing every instance to pull from user IDs instead of nicknames is not really feasible.
They're running into problems with some nicknames, particularly "Link", "Echo", "Slayer". I see why link and echo could potentially cause issues with the query, but not so much Slayer. Is there anything I can do (aside from preventing creation of these names in the future) to help the query go through and pull the information I need?
Edit:
The whole function:
function userInfo($username){
global $username_array;
$username = prepare($username);
$username_array = mysql_fetch_array(mysql_query("SELECT * FROM `users` WHERE `name` = '$username' LIMIT 1"));
}
It should return an array $username_array back to the original script. With 99% of users, this works fine. For some reason, the users above, this done not work.
function prepare($val,$type=0){
$val = XSS($val);
$val = sqlInjection($val);
return $val;
}
function XSS($val) {
// remove all non-printable characters. CR(0a) and LF(0b) and TAB(9) are allowed
$val = preg_replace('/([\x00-\x08][\x0b-\x0c][\x0e-\x20])/', '', $val);
// straight replacements, the user should never need these since they're normal characters
// this prevents like <IMG SRC=@avascript:alert('XSS')>
$search = 'abcdefghijklmnopqrstuvwxyz';
$search .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$search .= '1234567890!##$%^&*()';
$search .= '~`";:?+/={}[]-_|\'\\';
for ($i = 0; $i < strlen($search); $i++) {
// ;? matches the ;, which is optional
// 0{0,7} matches any padded zeros, which are optional and go up to 8 chars
// @ # search for the hex values
$val = preg_replace('/(&#[x|X]0{0,8}'.dechex(ord($search[$i])).';?)/i', $search[$i], $val); // with a ;
// @ # 0{0,7} matches '0' zero to seven times
$val = preg_replace('/(�{0,8}'.ord($search[$i]).';?)/', $search[$i], $val); // with a ;
}
// now the only remaining whitespace attacks are \t, \n, and \r
$ra1 = Array('javascript', 'vbscript', 'expression', 'applet', 'blink', 'script', 'iframe', 'frameset', 'ilayer', 'bgsound');
$ra2 = Array('onabort', 'onactivate', 'onafterprint', 'onafterupdate', 'onbeforeactivate', 'onbeforecopy', 'onbeforecut', 'onbeforedeactivate', 'onbeforeeditfocus', 'onbeforepaste', 'onbeforeprint', 'onbeforeunload', 'onbeforeupdate', 'onblur', 'onbounce', 'oncellchange', 'onchange', 'onclick', 'oncontextmenu', 'oncontrolselect', 'oncopy', 'oncut', 'ondataavailable', 'ondatasetchanged', 'ondatasetcomplete', 'ondblclick', 'ondeactivate', 'ondrag', 'ondragend', 'ondragenter', 'ondragleave', 'ondragover', 'ondragstart', 'ondrop', 'onerror', 'onerrorupdate', 'onfilterchange', 'onfinish', 'onfocus', 'onfocusin', 'onfocusout', 'onhelp', 'onkeydown', 'onkeypress', 'onkeyup', 'onlayoutcomplete', 'onload', 'onlosecapture', 'onmousedown', 'onmouseenter', 'onmouseleave', 'onmousemove', 'onmouseout', 'onmouseover', 'onmouseup', 'onmousewheel', 'onmove', 'onmoveend', 'onmovestart', 'onpaste', 'onpropertychange', 'onreadystatechange', 'onreset', 'onresize', 'onresizeend', 'onresizestart', 'onrowenter', 'onrowexit', 'onrowsdelete', 'onrowsinserted', 'onscroll', 'onselect', 'onselectionchange', 'onselectstart', 'onstart', 'onstop', 'onsubmit', 'onunload');
$ra = array_merge($ra1, $ra2);
$found = true; // keep replacing as long as the previous round replaced something
while ($found == true) {
$val_before = $val;
for ($i = 0; $i < sizeof($ra); $i++) {
$pattern = '/';
for ($j = 0; $j < strlen($ra[$i]); $j++) {
if ($j > 0) {
$pattern .= '(';
$pattern .= '(&#[x|X]0{0,8}([9][a][b]);?)?';
$pattern .= '|(�{0,8}([9][10][13]);?)?';
$pattern .= ')?';
}
$pattern .= $ra[$i][$j];
}
$pattern .= '/i';
$replacement = substr($ra[$i], 0, 2).'<x>'.substr($ra[$i], 2); // add in <> to nerf the tag
$val = preg_replace($pattern, $replacement, $val); // filter out the hex tags
if ($val_before == $val) {
// no replacements were made, so exit the loop
$found = false;
}
}
}
return $val;
}
function sqlInjection($val){
if (get_magic_quotes_gpc()){
$val = stripslashes($val);
}
if(version_compare(phpversion(),"4.3.0") == "-1"){
return mysql_escape_string($val);
}else{
return mysql_real_escape_string($val);
}
}
There should be no problem since no user input should ever be directly executed.
Make sure you escape the strings properly and consider using prepared statements incase someone has a nasty suprise waiting such as this.
Using strings that are php reserved words is not the issue with your problem.
you can have strings that are reserved words $test = 'function'; is valid. The issue lies elsewhere.
http://www.php.net/manual/en/reserved.keywords.php
I'm looking for a php function which can mask credit card & bank information such as routing number and account numbers. I need to mask many formats, so the existing stack overflow answers don't help me that much.
So for example, if the input is 304-443-2456, the function should return xxx-xxx-2456.
Sometimes the number has dashes, and can be in various lengths.
I'm looking for something generic, that I can extend as needed, preferably a zend framework view helper class.
Some little regex in a function of it own, configuration available:
$number = '304-443-2456';
function mask_number($number, $count = 4, $seperators = '-')
{
$masked = preg_replace('/\d/', 'x', $number);
$last = preg_match(sprintf('/([%s]?\d){%d}$/', preg_quote($seperators), $count), $number, $matches);
if ($last) {
list($clean) = $matches;
$masked = substr($masked, 0, -strlen($clean)) . $clean;
}
return $masked;
}
echo mask_number($number); # xxx-xxx-2456
If the function fails, it will return all masked (e.g. a different seperator, less than 4 digits etc.). Some child-safety build in you could say.
Demo
<?php
function ccmask($cc, $char = '#') {
$pattern = '/^([0-9-]+)([0-9]*)$/U';
$matches = array();
preg_match($pattern, $cc, $matches);
return preg_replace('([0-9])', $char, $matches[1]).$matches[2];
}
echo ccmask('304-443-2456'), "\n";
echo ccmask('4924-7921-9900-9876', '*'), "\n";
echo ccmask('30-43-56', 'x'), "\n";
Outputs:
###-###-2456
****-****-****-9876
xx-xx-56
I use a view helper for that. I tend to avoid Regex though as it always takes me ages to work out what it does, especially if I come back to code after a while.
class Zend_View_Helper_Ccmask
{
public function ccmask($ccNum)
{
$maskArray = explode('-', $ccNum);
$sections = count($maskArray) - 1;
for($i = 0; $i < $sections ; $i++){
$maskArray[$i] = str_replace(array(1,2,3,4,5,6,7,8,9,0), 'x', $maskArray[$i]);
}
return implode('-', $maskArray);
}
}
In your view
echo $this->ccmask('304-443-2456');
//output = xxx-xxx-2456
A good way to look at this is at what won't be masked and outputing xs for everything else. A simple, inexpensive solution is:
function cc_mask( $cc_raw, $unmask_count ){
$cc_masked = '';
for( $i=0; $i < ( strlen( $cc_raw ) - $unmask_count ) ; $i++ ){
//If you want to maintain hyphens and special characters
$char = substr( $cc_raw, $i, 1 );
$cc_masked .= ctype_digit( $char ) ? "*" : $char;
}
$cc_masked .= substr( $cc_raw , -$unmask_count );
return $cc_masked;
}
echo cc_mask("304-443-2456",4);
//Output
***-***-2456
Would be even faster if there was no need to maintain the hyphens and special characters
I am using an api to retrieve data from another server the data returned is something like this:
accountid=10110 type=prem servertime=1263752255 validuntil=1266163393
username= curfiles=11 curspace=188374868 bodkb=5000000 premkbleft=24875313
This is a whole string I need two values out of whole string, I am currently using preg_match to get it, but just to learn more and improve my coding is there any other way or function in which all values are automatically convert to array?
Thank You.
Sooo, my faster-than-preg_split, strpos-based function looks like this:
function unpack_server_data($serverData)
{
$output = array();
$keyStart = 0;
$keepParsing = true;
do
{
$keyEnd = strpos($serverData, '=', $keyStart);
$valueStart = $keyEnd + 1;
$valueEnd = strpos($serverData, ' ', $valueStart);
if($valueEnd === false)
{
$valueEnd = strlen($serverData);
$keepParsing = false;
}
$key = substr($serverData, $keyStart, $keyEnd - $keyStart);
$value = substr($serverData, $valueStart, $valueEnd - $valueStart);
$output[$key] = $value;
$keyStart = $valueEnd + 1;
}
while($keepParsing);
return $output;
}
It looks for an equals character, then looks for a space character, and uses these two to decide where a key name begins, and when a value name begins.
Using explode is the fastest for this, no matter what.
However, to answer you question, you can do this many ways. But just because you can, doesn't mean you should. But if you really wanna make it weird, try this.
UPdated using strpos
$arr = array();
$begin = 0;
$str = trim($str); # remove leading and trailing whitespace
while ($end = strpos($str, ' ', $begin)) {
$split = strpos($str, '=', $begin);
if ($split > $end) break;
$arr[substr($str, $begin, $split-$begin)] = substr($str, $split+1, $end-$split-1);
$begin = $end+1;
}
try out parse_str maybe you need to do str_replace(' ', '&', $string); before