looping, comparing multiple table values - php

I've been having a problem & not sure the logic I need.
I'm trying to build a basic PHP & MySQL registration page though with a check to see if they've changed IP addresses, check to see if the addresses have been registered with 3 different accounts, if so, return false.
Here is my logic.
Account registers -> Database (site_registration) -> Email verified -> Database (users) -> Account logs in -> Database (account_logins) (only if new IP)
Account tries to reregister after 3 entries -> Check Database (site_registration) IP field -> Check Database (account_logins) account IP fields -> Throw all IP's for the account into an array -> Check array against site_registration -> If IPs are found on 3 accounts, throw registration error -> Database (suspicious_logs)
This is the mysql code I need, but not sure how to loop it.
//SELECT * FROM users WHERE (idnumber = '75.143.xxx.xxx') OR (idnumber = '76.94.xxx.xxx') OR (idnumber = '76.94.xxx.xxx')
$username = $_SESSION['login'];
$check_ip_site = $MySQL->consult("SELECT * FROM site_registration WHERE (username = '$username')");
$check_ip_logins = $MySQL->consult("SELECT * FROM site_logins WHERE (username = '$username')");
$check_ip_user = $MySQL->consult("SELECT * FROM users");
for($i = 0; $login_array[$i] = mysql_fetch_assoc($check_ip_logins); $i++);
array_pop($login_array);
for($i = 0; $user_array[$i] = mysql_fetch_assoc($check_ip_user); $i++);
array_pop($user_array);
foreach ($login_array["ip"] as $login_ips) {
if (in_array($login_ips, $user_array["ip"]) > 3) {
return true;
} else {
return false;
}
}
Though this syntax doesn't work, it's what I need, I want to find if ANY of the IPs are found on 3 records in the user database, if they are return false.

This is what works for me. I had to set it into a foreach for it to loop the query. Also, my for loop works like that as I had nothing to do inside of the loop. If anyone sees a better way of doing this, please let me know! Before I accept my answer, I'll see if anyone has a better solution.
//Check if username is set, if it's not use the current IP instead (add cookie handling later to keep from destroying evidence)
$ip = $_SERVER['REMOTE_ADDR'];
if ($username == NULL){
$check_ip_logins = $MySQL->consult("SELECT * FROM site_logins WHERE (ip = '$ip')");
}
else
{
$check_ip_logins = $MySQL->consult("SELECT * FROM site_logins WHERE (username = '$username')");
}
for($i = 0; $login_array[$i] = mysql_fetch_assoc($check_ip_logins); $i++);
array_pop($login_array); //Deletes the null array at the end of the for loop
foreach ($login_array as $la)
{
$lips = $la["ip"]; //Place just the IP's into it's own array
$check_ip_user = $MySQL->consult("SELECT * FROM users WHERE (idnumber = '$lips')"); //Loop through all IP's associated with account & check the users database
while($test = mysql_fetch_assoc($check_ip_user)) {
$names[] = $test["name"]; // This is used as a way to count, any thing can be used here.
}
}
if (count($names) > 3)
{
echo 'you have too many accounts you cannot create anymore';
}
else
{
echo 'you are able to create an account';
}

Related

php statement for multiple users not working

I am helping in some PHP design for a friends text game and have come to a stump.
I have scheduled a cron job to call the following page / following code, which is working correctly
<?php require("connect.php"); ?>
<?php
$sql = "SELECT id, name, health FROM users";
$query = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_object($query);
while($row = mysql_fetch_object($query)) {
$id = htmlspecialchars($row->id);
$name = htmlspecialchars($row->name);
$health = htmlspecialchars($row->health);
$sql = "SELECT * FROM property WHERE living='1' AND ownerid='$id'";
$query = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_object($query);
while($row = mysql_fetch_object($query)) {
$OwnerName = htmlspecialchars($row->ownername);
$OwnerID = htmlspecialchars($row->ownerid);
$RaidPropBonus = htmlspecialchars($row->raidperc);
$RaidPropMoney = htmlspecialchars($row->raidcash);
$PropertyLvl = htmlspecialchars($row->proplvl);
$Living = htmlspecialchars($row->living);
if($PropertyLvl == '5' && $Living == '1'){
if($health < '100'){
$result = mysql_query("UPDATE users SET health=$health + '1' WHERE id='$id'")
or die(mysql_error());
} else { }
} else { }
}
}
?>
Although this only works for ONE user only. I cannot understand why this is. Any other logged in / out accounts that have met the criteria have been ignored. I can maybe only think I am missing a loop? As the ID that is being met first is number 1 and it has stopped there?
Anybody advice at all maybe?
UPDATE - It seems correct I need to get a loop in there, but am so far failing to get this loop working correct. No matter where I seem to amend / add a loop it does not help. Please may somebody suggest anything?
UPDATE2 - As requested, updated with the new version of loop
For what I've understood, the loops should be made on the mysql_fetch_object that will get the each row from the query.
Take a look at the snippet
<?php
require("connect.php");
// here prepare the $userQuery (the one that fetches all users)
// then the first loop that will read each usew row
// AFAICT this should afect all script
while($userRow = mysql_fetch_object($userQuery))
{
// prepare data fetched from the $userQuery
// prepare the $propertyQuery (the one that fetches all properties of the user)
// then the second loop to read all user property rows
// and this will afect the updates
while($propertyRow = mysql_fetch_object($propertyQuery))
{
// prepare data fetched from $propertyQuery
// add logic here
}
}
?>
Also #Matthew Carpenter had a valid point, that mysql_* is deprecated, you should consider in using mysqli_*, or in my opinion take a look at PDO

What did I do wrong? (PHP prepare statement)

First time I'm using a prepare function, and I got it to partially work. Basically, I'm copying user passwords from one database to another (part of a WordPress plugin I'm making to transfer users). The code runs and does exactly what I want, but only for the first user it finds in the wp_users table. I need it to continue running for all the users in that table so they all get their passwords transfered. This is the code I wrote below:
For getting the user password from the original database (Basically, this finds the passwords for all the users and puts them in an array. I'm posting this code just for context. This code works perfectly fine):
$i = 0;
//set $user_count-1 because $i needs to start at 0 to represent the indexes and it also prevents the statement from being looped an extra time.
while($i <= $user_count-1) {
if($result = $conn->query("SELECT * FROM wp_users")) {
if($count = $result->num_rows) {
//echo $count . ' users found.';
while($row = $result->fetch_object()) {
$user_password[] = $row->user_pass;
}
}
$i++;
}
To retrieve the index values (This is the code I'm using to actually retrieve those index values and put them in the sql query. Like I said, it works fine for the first user, but not the rest of the users):
$stmt = $conn->prepare("UPDATE `wp_plugin_development`.`wp_users` SET `user_pass` = ? WHERE `wp_users`.`user_login` = ?");
$stmt->bind_param('ss', $user_password[$i], $user_login[$i]);
$stmt->execute();
I'm thinking maybe the syntax is wrong? I don't know. I hope I made my question clear enough. Thanks for any help!
I figured it out!
Originally, I put the code to prepare the statement and the code to execute it together. prepare and bind_param needs to be placed before $i auto-increments. The execute needs to be placed after $i auto-increments. Here's the code that works:
$i = 0;
//using $user_count-1 because $i needs to start at 0 to represent the indexes and it also prevents the statement from being looped an extra time.
while($i <= $user_count-1) {
if($result = $conn->query("SELECT * FROM wp_users")) {
if($count = $result->num_rows) {
//echo $count . ' users found.';
while($row = $result->fetch_object()) {
$user_password[] = $row->user_pass;
$stmt = $conn->prepare("UPDATE `wp_plugin_development`.`wp_users` SET `user_pass` = ? WHERE `user_login` = ?");
$stmt->bind_param('ss', $user_password[$i], $user_login[$i]);
}
}
$i++;
if(!$stmt->execute()){trigger_error("there was an error....".$conn->error, E_USER_WARNING);}
}
Thank you everyone for your input!

set int from sql query

I am trying to set an int value from an sql query. In my ios app I can assign an int value to a photo ID, store it and retrieve it fine. The problem comes if I want to overwrite the photo with a new jpg but still using the existing IdPhoto and therefore the same filename, e.g. 1.jpg. I first check whether the user exists. If so I update the photo (this is where I need to set the IdPhoto) otherwise I create a photo with a new ID (works fine).
function uploadDetails($Name, $Location, $photoData, $IdPhoto) {
$uploads = query("SELECT Name, IdPhoto FROM users WHERE Name = '%s' limit 1",$Name);
if (count($uploads['result'])>0) {
$result = query("UPDATE users SET Name='$Name', Location='$Location', IdPhoto='$IdPhoto' WHERE Name = '%s'", $Name);
//Need to define IdPhoto from users table
if (move_uploaded_file($photoData['tmp_name'], "icons/".$IdPhoto.".jpg")) {
thumb("icons/".$IdPhoto.".jpg", 180);
//I can print out confirmation to the iPhone app
print json_encode(array('$IdPhoto'=>$IdPhoto));
} else {
//print out an error message to the iPhone app
errorJson('Upload on server problem');
};
}
else {
if ($photoData['error']==0) {
$result = query("INSERT INTO users(Name, Location) VALUES('%s','%s')", $Name, $Location);
if (!$result['error']) {
// fetch the active connection to the database (it's initialized automatically in lib.php)
global $link;
// get the last automatically generated ID in the table
$IdPhoto = mysqli_insert_id($link);
if (move_uploaded_file($photoData['tmp_name'], "icons/".$IdPhoto.".jpg")) {
thumb("icons/".$IdPhoto.".jpg", 180);
print json_encode(array('successful'=>1));
} else {
errorJson('Upload on server problem');
};
} else {
errorJson('Upload database problem.'.$result['error']);
}
}
}
}
So the problem lies in the first part of the code where I need to update the photo but still use the same IdPhoto
EDIT
The piece of code I needed was as follows:
$getID = mysqli_fetch_assoc(mysqli_query($link, "SELECT IdPhoto FROM users WHERE Name = '$Name'"));
$IdPhoto = $getID['IdPhoto'];
Although I got to the answer eventually myself, I appreciate feedback of how to phrase questions better in future. And writing out the full code probably helped me look at the bigger picture and see where I was going wrong.
Your question is extremely vague but I'm going to take the following assumptions:
Your query will only ever return a single record
You are using MySQLi
Once you have run the query and stored the results into $result you can use the following code to get the IdPhoto:
//Store a row from results into variable
$row = $result->fetch_assoc();
//Store IdPhoto into variable
$IdPhoto = $row['IdPhoto'];
Note: Also you are selecting Name from the database when you already have the Name since you're using it to fetch the record

How to email all users with user-specific information.

I've built a contest system for a website, how it works is a user logs in, submits a ballot based on a real life event (sale of a particular object), and then at the end of the month, a random ballot is chosen and the owner of that ballot is the winner.
I've been asked to create a script which will email all users in the database the current amount of ballots they have in the system.
My current login/registration system is a heavily edited version of HTML-Form-Guies Simple PHP Registration System.
I know the pseudo code for what I want to do.
Step by step, the method needed goes like this.
Call on EmailUsersTotalEntries, populates an array with all the users in the database, pick the first entry in the array, user 1, find the sum of the all the rows in the itemsold column with the userid 1. then send user one an email with the results of the select sum(itemsold) from ballots where userid = 1; to user 1. Then the loop goes to user 2 and does the same thing, until it has sent an email to every user in the database.
Here are a few of the methods that I have either written or that are from the login system that will be used to accomplish this. My only problem is I dont know how to make a loop so that it will start from user 1 and then keep going all the way to user 2, and I dont know how to query the database for the user_id of whatever user the database/loop is currently on.
Methods are as follows:
This is the main method, it will call sub methods to collect the users and then send the actual email. I'm not sure if TotalEntries should be an array or not
function EmailTotalEntries()
{
if(empty($_POST['email']))
{
$this->HandleError("Email is empty!");
return false;
}
$user_rec = array();
if(false === $this->GetUsers($user_rec))
{
return false;
}
**/* $TotalEntries = array(); */**
if(false === $this->GetTotalEntriesForEmail($user_rec, $TotalEntries)
{
return false;
}
//At this point, I have an array, user_rec, populated with all the data from my users table, and an array $TotalEntries that will have nothing since its trying to pull from user_rec, which usually is one user but right now is all of the users.
//This is where I know I should have already started the loop, so chosen the first element in user_rec, and applied the GetTotalEntriesForEmail method, then the SendUserEmail method, then gone to the top of the loop and gone to the second user_rec element and repeat.
if(false === $this->SendUsersEmail($user_rec, $TotalEntries))
{
return false;
}
return true;
}
This is the method that collects the users
function GetUsers(&$user_rec)
{
if(!$this->DBLogin())
{
$this->HandleError("Database login failed!");
return false;
}
$result = mysql_query("Select * from $this->tablename",$this->connection);
$user_rec = mysql_fetch_assoc($result);
return true;
}
Here is the method I wrote to get the TotalEntries for a user that is logged in (checking his control panel to see how many entries he has)
function GetTotalEntries()
{
if(!$this->CheckLogin())
{
$this->HandleError("Not logged in!");
return false;
}
$user_rec = array();
if(!$this->GetUserFromEmail($this->UserEmail(),$user_rec))
{
return false;
}
$qry = "SELECT SUM(itemsold) AS TotalEntries FROM entries WHERE user_id = '".$user_rec['id_user']."'";
$result = mysql_query($qry,$this->connection);
while($row = mysql_fetch_array($result))
{
echo $row['TotalEntries'];
}
}
And here is how I believe it needs to be adapted to work in the email.
function GetTotalEntriesForEmail($user_rec, &$TotalEntries)
{
if(!$this->DBLogin())
{
$this->HandleError("Database login failed!");
return false;
}
$qry = "SELECT SUM(itemsold) FROM entries WHERE user_id = '".$user_rec['id_user']."'"; //$user_rec['id_user'] should the be id of the user the loop is currently on.
$result = mysql_query($qry,$this->connection);
$TotalEntries = mysql_fetch_assoc($result);
return true;
}
Heres the actual email
function SendUsers($user_rec, $TotalBallots)
{
$email = $user_rec['email']; //should be the for the user the loop is currently on.
$mailer = new PHPMailer();
$mailer->CharSet = 'utf-8';
$mailer->AddAddress($email,$user_rec['name']); //user the loop is currently on.
$mailer->Subject = "Total Ballots to Date";
$mailer->From = $this->GetFromAddress();
$mailer->Body ="Hello ".$user_rec['name']."\r\n\r\n". //Same thing
"To date you have: "/* .$TotalBallots. */" ballots.\r\n" //Same thing
if(!$mailer->Send())
{
return false;
}
return true;
}
I'm not very good at PHP, and this whole thing is a learning experience for me, so help is greatly appreciated.
If I havent been clear, maybe giving an example in another language would be clearer, so heres what I want to do, but in java
for(x = 0; x <= user_rec.length; x++)
{
int ballots = getTotalEntriesForUser(x);
sendEmailToUser(ballots)
}
If I havent been clear enough, please let me know and I will try to clarify as best as possible.
How can I combine the above code with a loop that will send all users an email, one by one, each email unique to the user it is sent to?
Are your functions part of a class? You wouldn't necessarily need them to do this. Here's my recommendation, which you can turn into functions, or a class, if you want. Also, you may want to consider looking into, and using MySQLi, and taking advantage of the classes it uses. Again, all just my recommendations.
Without knowing your table structure, I'm just taking a guess at this.
$sql = mysql_query("SELECT u.*,
u.user_id AS user,
COALESCE(SUM(e.itemssold), 0) AS total_items
FROM users u
LEFT JOIN entries e ON e.user_id = u.user_id
GROUP BY u.user_id");
while($row = mysql_fetch_array($sql))
{
$user = $row['user'];
$email = $row['user_email'];
$items = $row['total_items'];
yourEmailFunction($email, $items);
}
This pulls information from your users table, and your entries table based on matching User ID's. It sets the User ID from the user table as user so you don't have to try and distinguish between the two later. To learn about the COALESCE function, read here. The while() function will loop through every user it pulls from that SQL statement.
This hasn't been tested in any way, but that's basically what you need. Just pass the User's email, and the total Items, and write your email function to send that info to that email address.
However, if you know your functions work properly, and want to use a for loop, such as the one you provided in Java, here's how you'd write it in PHP.
for($x = 0; $x <= count($user_rec); $x++)
{
$ballots = getTotalEntriesForUser($x);
sendEmailToUser($ballots);
}

While loop refusing to work

I did make a post previously but was not able to properly explain my issue nor was I able to get it resolved. This is what I have.
$shoutlines = file($shout_file);
$aTemp = array();
foreach($matches['user'] as $user) {
$aTemp[] = "'" . $user . "'";
}
$user = implode(",", $aTemp);
$rara = "SELECT * FROM accounts WHERE username IN ( $user )"; // Tried this statment both as a query and prepared statement
$getlevel = $db->query("SELECT * FROM accounts WHERE username IN '( ".$user." )'"); // Tried this both as a query and prepared statement
//$getlevel->bind_param('s', $user);
//$getlevel->execute();
//$level = $getlevel->get_result();
//$getlevel->store_result();
while($getdb = $getlevel->fetch_assoc()){
//output the html
for($i = 0; $i < (1000); $i++)
{
if(isset($shoutlines[$i]))
{
$shoutline = preg_replace('/<\/div>\n/', ' ', $shoutlines[$i], 1);
echo showSmileys($shoutline) . "<div class='delete'><a href='javascript: delete_shoutline({$i});' title='Delele'>delete</a></div></div>";
}
}
}
I have a for loop within the while loop that will not run within it, if I move the for loop outside of the while it works fine, but I need it in the while loop to make checks of the users for post titles, abilities etc., that are saved in my database. I have shown what I have tried so far when to comes to identifying the problem, I have tried dieing out errors if the query, binds, or executes weren't showing true, but got now hits. The code for this is pulled out so there isn't too much clutter for your reading abilities, any help with this would be greatly appreciated.
When "exploding" the username, you need ot wrap each username in quotes, not the whole thing. Also make the names safe for data entry.
$aTemp = array();
foreach($matches['user'] as $user) {
$aTemp[] = '"' . mysql_real_escape_string($user) . '"';
}
$user = implode(",", $aTemp);
Then use the first query:
"SELECT * FROM accounts WHERE username IN ( $user )";
Edit: adding error checking:
$getlevel = $db->query("SELECT * FROM accounts WHERE username IN ( $user )");
if ($getlevel == false) {
// Normally you'll build into a function or class, but this is the simple example
// Never output SQL errors on a live site, but log to file or (if you can do it safely) the database.
echo 'Whoopsie<br />';
var_dump($db->errorInfo());
exit();
}
Using data binding with IN clauses is not that nice, so if you really need IN and don't care about using the old, deprecated mysql_* function, try this:
$user="'".implode("','",array_map(function($s){
return mysql_real_escape_string($s);
},$matches["user"])."'";
$rara="SELECT * FROM accounts WHERE username IN ($user)";

Categories