I am trying to loop through a file of blocked IP address.
I seem to be unable to do this even when they should match.
Here is the code that checks.
$blocked_ips = file("/home/block_list.txt");
for ( $i = 0; $i < count($blocked_ips); $i++) {
if ( $_SERVER["REMOTE_ADDR"] == $blocked_ips[$i] ) {
exit;
}
}
And here is the code I use to add the ip address to the file.
if ( $_SESSION["LogInAttempts"] >= "10" ) {
$block_ip = $_SERVER["REMOTE_ADDR"];
$block_ip = $block_ip . "\r\n";
file_put_contents("/home/block_list.txt", $block_ip, FILE_APPEND);
}
And here is a list of ip addresses in the file. (example only)
169.254.51.183
192.168.0.1
192.168.10.84
I'm not to sure what I am doing wrong.
Make sure to account for whitespace when reading from files or receiving user input. trim() is your friend for such cases, though, as Jack noted in the comments, using FILE_IGNORE_NEW_LINES in file() will solve that for you. As the documentation says:
FILE_IGNORE_NEW_LINES
Do not add newline at the end of each array element
Furthermore, you might find foreach a little more comfortable than your for loop, but that's a question of personal taste, ultimately. Here's a variant with the additional parameter in file() and with foreach:
$blocked_ips = file("/home/block_list.txt", FILE_IGNORE_NEW_LINES);
foreach($blocked_ips as $ip) {
if ($_SERVER["REMOTE_ADDR"] == $ip) {
exit;
}
}
Note also that you shouldn't have quotes around that 10 in your code below, though with PHP's type juggling feature your code will work, of course. However, it's always a good idea to be as precise as possible. If for nothing else, for clarity: it will make the intention of your code easier to understand – also for you when you'll be looking at your code after a long time.
You can also append a string to REMOTE_ADDR without a problem (again, a question of personal taste). Finally, note that getting the IP address of a user is not as straightforward as simply calling $_SERVER['REMOTE_ADDR'] if we want to be very correct, but for most purposes it will suffice. Nevertheless, there's a very interesting discussion about getting the IP address of a user in PHP on StackOverflow I recommend everyone to read.
if ($_SESSION["LogInAttempts"] >= 10) {
$block_ip = $_SERVER["REMOTE_ADDR"] . "\r\n";
file_put_contents("/home/block_list.txt", $block_ip, FILE_APPEND);
}
You don't need a loop at all. You can do that with in_array().
<?php
// Read in blocked ips list.
$blockedIps = file('/home/block_list.txt', FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
// Check if ip is blocked.
if(in_array($_SERVER['REMOTE_ADDR'], $blockedIps)) {
exit;
}
Related
So I'm making a webshop, well, trying to atleast for a course project using WAMP. But when trying to register new users and in the process checking their password against a list of common ones the use of fgets() returns an empty string.
if(empty(trim($_POST["password"]))){
...
} elseif (!checkPassword($_POST["password"])) {
$password_err = "Password to common.";
echo "<script>alert('Password to common.'); location.href='index.php';</script>";
}
The checkPassword() is where the fault lies.
function checkPassword($passwordtocheck) {
$passwordtocheck = strtolower($passwordtocheck);
$common_passwords = fopen("commonpasswords.txt", "r");
while(!feof($common_passwords)) {
$check_against = fgets($common_passwords);
echo "<script>alert('Checking $passwordtocheck against $check_against.'); location.href='index.php';</script>";
if($check_against == $passwordtocheck) {
fclose($common_passwords);
return false;
}
}
fclose($common_passwords);
return true;
}
Lets say that I input the password 12345678 when registering, then the scripted alert will say "Checking 12345678 against ." and send me back to index.php. So it looks like it doesn't succeed in reading the file at all. The commonpasswords.txt is in the same folder as the rest of the files and with a single password on each row.
And there is no problem opening the file to begin with either, if I do this instead:
$common_passwords = fopen("commonpasswords.txt", "a");
fwrite($common_passwords, "test");
'test' will appear at the bottom of the file under the existing words on its own row without a hitch. And this is where I'm at, would appreciate whatever input people can give!
EDIT; I do understand that this probably breaks a ton of good-practice 'rules' in general and regarding security. But the website is not really supposed to function or look good, it just need to barely work so that we can later try and use different methods of attacking it and the connected database.
If you insist on doing this yourself – which I do not recommend – you can simplify things a lot by using the file() function. This returns an array of every line in the file. Then use array_filter(); it runs a callback on each element of the array where you can check if there's a match with your password. If the callback returns false, the element is removed from the array. After that, if you have any elements left you know there was a match.
function checkPassword($pwd) {
$pwd = strtolower($pwd);
$common = file("commonpasswords.txt", FILE_IGNORE_NEW_LINES);
$results = array_filter($common, function($i) use ($pwd) {return $i == $pwd;});
return count($results) === 0;
}
But really, there are dozens of libraries out there to check password strength. Use one of them.
Or, as pointed out in the comment, even simpler array_search:
function checkPassword($pwd) {
$pwd = strtolower($pwd);
$common = file("commonpasswords.txt", FILE_IGNORE_NEW_LINES);
return array_search($pwd, $common) === false;
}
I want to extrect all usernames and passwords each from his file and output it nicely.
I wrote a code on my appserv 2.5.1 on my computer but only the last loop gave the username output.
Tested the code on other machines and it worked perfectly.
Dont know what is the problem ...
usernames.txt content :
user1
user2
user3
passwords.txt content :
pass1
pass2
pass3
script content :
$usernames = explode("\n", file_get_contents("usernames.txt"));
$passwords = explode("\n", file_get_contents("passwords.txt"));
foreach( $usernames as $username )
{
foreach( $passwords as $password )
{
echo $username.":".$password."\n";
}
}
output :
:pass1
:pass2
:pass3
:pass1
:pass2
:pass3
user3:pass1
user3:pass2
user3:pass3
for ($i=0;$i<count($usernames) && $i<count($password); $i++) {
echo $usernames[$i].':'.$passwords[$i];
}
But $password[x] must be related to $usernames[x]
There's always those that will say you don't need it (and you often don't) but I tend to use regular expressions whenever I'm parsing these kind of flat files - there's always some quirky character, extra line-break or difference that finds it's way into a text file - be it from transferring servers, restoring backups or simply user-interference. You could also make use of array_combine in this situation if you'd prefer to carrying on using a foreach loop - I know some folks prefer it for readability.
preg_match_all('/\w+/m', file_get_contents('usernames.txt'), $usernames);
preg_match_all('/\w+/m', file_get_contents('passwords.txt'), $passwords);
if(count($usernames[0]) !== count($passwords[0]))
die('Computer says: mismatch!'); // some resemblance of error handling...
$result = array_combine($usernames[0], $passwords[0]);
foreach($result as $name => $pass)
echo "{$name}:{$pass}\n";
demo
After debugging with the post author, I guessed that the problem was with the line return character. Using a \r\n fixed the problem:
$usernames = explode("\n\r", file_get_contents("usernames.txt"));
$passwords = explode("\n\r", file_get_contents("passwords.txt"));
For reference, please note that it is very important not to assume your input data is right. If you see that something is wrong and it points obviously to a mistake you made previously (in that case it is clearly not the foreach function that is buggy, but the array), then you need to swallow your pride and debug your own code. I have been programming PHP for 10 years, and I still have to remember that every single day.
My code that reads an XML file is as follows:
<?php
if ( $dance['block'] == $dance['user']['ip'] ) : ?>
<?php e(o("N/A")) ?>
Right now, that if() statement is reading the entire XML file as one string. So next I used:
$array6 = explode(",", $this->block);
$result['block'] = (string) $array6;
This was supposed to explode each $dance['user']['ip'], but I'm not sure why it's not working.
Any ideas, fixes, or tips?
Casting an array to a string will unhelpfully give you the string "Array" as well as throw a nifty warning. I'm not quite sure what you are trying to accomplish there.
For your test to see if a user's ip is in the block list you should do the following:
$blockList = explode(",", $blockedIpString);
if (in_array($dance['user']['ip'], $blockList)){
// user is blocked
} else {
// user is not blocked
}
I am having one hell of a time coming up with a decent way make this if statement search a file for these codes. I set up the text file to read from as such:
myfile.txt
r)
0Y7
1a6
q.
#g
#(
#a
!P
T[
V}
0,
Here is a brief of what I got going.
$subject = file_get_contents(fvManager_Path . 'myfile.txt');
if ( preg_match('/^[a-zA-Z0-9,]+$/',$result['fmbushels_itemCode'], $subject) ) {
Basically I am trying to search the text file line by line to see if the whole string exists. They are case sensitive as well.
$result['fmbushels_itemCode'] is from a sql query and always returns a code like the above in the text.
I'd appreciate any help on this. If someone knows a better way of doing this or a different command, I'd be willing to give that a shot as well :)
edit:
private function _fvShareBushels() {
$subject = file_get_contents(fvManager_Path . 'myfile.txt');
if (count($vShareArray) > 0) {
$vCntMoves = count($vShareArray);
for ($vI = 0;$vI < $vRunMainLoop;$vI++) {
sell $result['fmbushels_itemCode']);
}
}
}
This is a snippet of a big code. I had to rip most out because of post limitation. The area I could be working with is:
if (count($vShareArray) > 0) {
If I could make this something like:
if (count($vShareArray) > 0 && $result['fmbushels_itemCode'] **is not in** $subject) {
If you want to do line by line, use the file() function.
$f = file(fvManager_Path . 'myfile.txt');
foreach($f AS $line){
// $line is current line at file
}
I'm not to sure if you understand completely how preg_match works. The first parameter is the regular expression pattern, the second is what you want to match the pattern to, and the third is an array of matches. So for every valid pattern matched in the second parameter a new index on the array is created.
I'm not 100% on what you're trying to accomplish. Are you trying to see if the $result['fmbushels_itemCode'] exists in the file?
If the above is the correct case you simply just need to do something like:
$f = file('myfile.txt');
array_map('trim', $f);
if(in_array($result['fmbushels_itemCode'], $f)){
// success
}
How to validate a substring is true in PHP for example if user1 is in the string it should be true?
textfile:
user1 : pass1
user2 : pass2
user3 : pass3
if(in_array($_SERVER['user1'] . "\r\n", $textfile)){ //not the way want this to be true
printf("Ok user1 is in this row somewhere");
}
I would advice against this kind of authentication system as is prone to errors or abuse. Use other system like ACL or database user/password hash check.
As those above have said, this is not a good approach as far as user authentication goes. If you want something basic, look at using HTTP Authentication or something at least.
That said, you can do what you have asked using PHP's file function, e.g.
function validUser($file, $user, $pass) {
// Check file exists
if (!is_file($file)) {
return FALSE;
}
// Read file
$lines = file($file);
if ($lines === FALSE) {
return FALSE;
}
// Go over the lines and check each one
foreach ($lines as $line) {
list($fuser, $fpass) = explode(':', trim($line));
if ($user == $fuser && $pass == $fpass) {
return TRUE;
}
}
// No user found
return FALSE;
}
if (validUser('passwords.txt', 'foo', 'bar')) {
echo 'The user was found';
}
Note that this assumes each line is of the form "username:password" with nothing else; you may need to adjust exactly how you match your lines depending on your format. An example file which would be validated by this would have a line such as
foo:bar
If you are using this for authentication; for the sake of your users consider a different (more secure) approach. By the way the reply to the OP is correct that just about nothing in that PHP code would work as appears to be intended.
However, if the idea is to use the value of an array by key $arr['key'] to look up configuration settings that need not be protected (for the world to see, basically) you can use the parse_ini_file() and friends. Again: this is not a good idea for truly sensitive data.
EDIT: Also, it is probably a good idea to use the PHP_EOL constant for end-of-line characters rather than assuming "\r\n".