My site has this about-page with a list of links to click with diffrent classes. These links obviously takes you to diffrent sub-content.
Why do these links have diffrent classes? Because i use javascript and jquery, to grab some content out from a database and smack it in a div on the without reloading... The database has 3 fields: id, headline and content.
The javascript works fine. It does what it should do. it takes the links' class (which is the an ID in the database) and uses it to grab the right content..
Basically:
<?php
//take the post'ed variable you've been given.
if(isset($_POST['id']));
//for convenience use this variable insted
$id = $_POST['id'];
//connect to the database
mysql_connect("localhost","root","") or die('Could not connect: ' . mysql_error());
//select database
mysql_select_db("ropox");
mysql_query("SET NAMES utf8");
//Grab this data
$query = mysql_query("SELECT * FROM about WHERE id=$id");
while($row = mysql_fetch_array($query))
{
//echo it bask to the original page. This is printed on the original page
echo $row['content'];
}
?>
When you click the link, it takes 1,03 second before the content appears on the page. At first it was 2 seconds, but I've managed to cut it down. all of my other database connects happens almost instantly and they even echo lots of content through loops. Why is this so slow?
Addressing the SQL Injection aspect:
How can I be vulnerable to SQL injection? There is no way for the user
to input a custom value. I know they could change the ID but what fun
would that be? it would then load nothing...
You're pulling $id directly from the post.
$id = $_POST['id'];
Assuming we have a smart attacker, manipulating the post's data isn't difficult. The SQL Injection attack type that #DanielA.White is warning you of banks on the fact that you're not making sure $id is a number. Because of that, let's pretend that I set the value for id in the post to:
'3; DROP TABLE about;'
Now you're in trouble - the table you were referencing is gone. See http://xkcd.com/327/ for more info. ;)
Sanitizing your input is actually pretty simple - just look here: What's the best method for sanitizing user input with PHP?
write to phpmyadmin the sql: Explain SELECT * FROM about WHERE id=5
if is nagging for id is not indexed, than there you have the problem, easy:)
if you have a loooot of fields in about table, better use field1,field2 instead of *
That is all what can you do for speed up select from sql, others are settings, and hardware, like mysql sever has 1Mb free to run you server and need to do a lot of swapping or your processor is Intel Pentium 1 or 2 something like that...bcause you are connection to localhost, not remote
Related
Lets say I have this PHP function:
function strlow($string){
strtolower(trim($string));
}
Now lets say I have a table with 2 columns [id - title] and I want to make all titles that are going to be inserted into the table in lowercase, The usual way is
$title = strlow($title);
$query = "INSERT INTO table (title) VALUES ($title);
Is there for example a way to implant in the column itself in the database the function, So instead of doing the strlow() by the PHP, the Database does it?
If yes, I wish for an example built on mine.
You could update your query to handle this if you really wanted (but I would still rather do this in the application layer) using the MySQL TRIM and LOWER commands:
INSERT INTO table (title) VALUES (TRIM(LOWER(($title)))
The reason I say I would rather do this in the application layer is that if you decide to switch database systems in future, you need to remember to port over all your database formatting rules such as these at that time too which although doesn't seem too bad now, trust me, in the future, you will forget.
In addition to this, if you ever want to add further logic to what you are putting in to the database you will likely find your options more limited in MySQL than you will in your application layer.
Also, please for my sanity look up how to use parametrized queries because you are wide open to SQL injection attacks at the moment. There is a great post here that covers this.
$query = "INSERT INTO table (title) VALUES (LCASE($title));
I have this code from another Stack Overflow question answered here.
I have a mysql table called track in my database.
$server = "host";
$username = "user";
$password = "pass";
$database = "database";
$connId = mysql_connect($server,$username,$password) or die("Cannot connect to server");
$selectDb = mysql_select_db($database,$connId) or die("Cannot connect to database");
$tracking_page_name="example";
$ref=$_SERVER['HTTP_REFERER'];
$agent=$_SERVER['HTTP_USER_AGENT'];
$ip=$_SERVER['REMOTE_ADDR'];
$host_name = gethostbyaddr($_SERVER['REMOTE_ADDR']);
$strSQL = "INSERT INTO track (tm, ref, agent, ip, tracking_page_name, host_name) VALUES(curdate(),'$ref','$agent','$ip','$tracking_page_name','$host_name')";
$test=mysql_query($strSQL);
Basically I want all the data this script collects to be put into my database. However, no matter what I type, even if I change the variables to text, nothing gets written into the database. I can read from the database just fine using another script, but I can't get this one to add any piece of info to the db. Is there a typo I just can't seem to find?
I just want information about anyone who visits the page this gets included in.
EDIT: I was trying to fill a field called "host_name", but in my database it had a different name. The original script shown here would not show the error and I did not ever run a check to see if all my fields are in order. That was the error.
Many possibilities:
If the user user has read permissions but not write permissions on the database or the table, read ops will succeed but write ops will fail.
If this is a MyISAM table, the table may be locked by another process. Read operations would work but write operations would not
Maybe the table or a field you're trying to write to does not exist or is misspelled
Change...
$test=mysql_query($strSQL);
to...
if(!$test=mysql_query($strSQL)) die(mysql_error());
It will show you why the operation failed (docs).
Also, if you're starting don't use MySQL functions. They are being removed from PHP so you're just giving yourself more work to do in the future. Use MySQLi or PDO_MySQL instead (docs).
Finally, never just insert text you got from the browser in an SQL query. The values of $_SERVER['HTTP_REFERER'] and $_SERVER['HTTP_USER_AGENT'] can be manipulated by your user to be anything, including a string that causes you to execute whatever query the user wants (delete your tables, exfiltrate your data...). Learn about prepared statements and parameterized queries and use them instead
echo this line:
$strSQL = "INSERT INTO track (tm, ref, agent, ip, tracking_page_name, host_name) VALUES(curdate(),'$ref','$agent','$ip','$tracking_page_name','$host_name')"
and run it on a SQL console. Lookout for errors and make sure the values are being passed in.
I have made a makegroup.php site which is supposed to create a group, and put the person in the connection table between UserID and GroupID.
..but I am not sure how to go on. The logged in user is saved in session variable $usid, but how what about GroupID? How do I fetch that right after on another page? Need I make this in steps? Including quick DB scheme.
Thanks in advance.
I guess GrouID is autonumeric?
So you leave db create the id for you.
Also loos like you are trying to concat the $groupname value
$sql = "INSERT INTO group (Groupname) VALUES ('".$groupname."') ";
But you dont want do that because that method is vulnerable to SQL Injection attack
Use parametrized values instead
How can I prevent SQL injection in PHP?
G'day,
I'm not familiar with MySQL and this will probably be an easy question!
I am trying to mod a Joomla plugin and am working with this code that works well for a similar function:
$q="SELECT `".$naming."` AS naming FROM `#__users` WHERE `id`='".$jomsocial_event->creator."' ";
$db->setQuery($q);
$eventcreatorname = $db->loadResult();
$eventcreator = ''.addslashes($eventcreatorname).'';
What I need to do is lookup the field id in the table community_groups and return the matching field name. What I have is (note that $jomsocial_event->contentid contains the group ID):
$q="SELECT `".$naming."` AS naming FROM `#__community_groups` WHERE `id`='".$jomsocial_event->contentid."' ";
$db->setQuery($q);
$eventgroupname = $db->loadResult();
$eventgroup = ''.addslashes($eventcreatorname).'';
It returns nothing as the query is wrong; what should it be for my usage?
I'd work backwards from the database.
i.e. turn on SQL logging and look at what's actually arriving in the database. Tweak as necessary by playing with the resulting SQL until you get what you want (and expect) and then implement that in your code.
Take a look at your generated query in the debugging from Joomla.
Run it against mysql directly and see where it goes wrong.
Also, I'd use the JDatabaseQuery API because you are much less likely to get errors with quoting etc. It looks to me like you are treating id as a string not an integer.
Instead of hard coding sql queries like Select * from users where user_id =220202 can these be made dynamic like Select * from $users where $user_id = $input.
Reason i ask is when changes are needed to table/column names i can just update it in one place and don't have to ask developers to go line by line to find all references to update. It is very time consuming. And I do not like the idea of exposing database stuff in the code.
My major concern is load time. Like with dynamic pages, the database has to fetch the page content, same way if queries are dynamic first system has to lookup the references then execute the queries, so does it impact load times?
I am using codeignitor PHP.
If it is possible then the next question is where to store all the references? In the app, in a file, in the DB, and how?
---EDIT:
Even better: Can the SQL query itself be made dynamic? I can just reference $sqlA instead of the whole query? This way if I have to re-write the query I can just update 1 file.
Because you are using Codeigniter, I would reccomend utilizing the Active Record Class to accomplish what you are trying to do.
The active record class enables you to build queries dynamically in steps allowing you to build them logically. So to take your example using active record...
( this could be accomplished with less code, I'm just trying to illustrate Active Record )
$this->db->select('*');
$this->db->from($table);
$this->db->where($user_id, $input);
and so to show what I mean about building the query logically, you can build whatever logic you want INTO the query building process. Lets say you have a $limit variable that you set if you want to limit the number of results you get. BUT if it isn't set (or NULL) you don't want to set the limit clause.
if ( $isset($limit) ) {
$this->db->limit($limit);
}
and now to execute your query now that it has been built
$query = $this->db->get();
Then just deal with $query with your database class just like you would any other CodeIgniter query object.
Of course you can, if that's what you wish. I'd rather recommend you taking more time to design you database but changes in the schema are inevitable in the long run.
I don't think load time would be an issue with this because ussually the bottleneck in this applications is in the database.
Finally my recommendation is to save this in a file just by declaring the column names as php variables
It depends on the database driver(s) you are using. The old PHP database drivers did not support placeholders (PHP 3.x). The modern (PDO) ones do. You write the SQL with question marks:
SELECT * FROM Users WHERE User_ID = ?
You then provide the value of the user ID when you execute the query.
However, you cannot provide the column name like this - only values. But you could prepare a statement from a string such as:
SELECT * FROM Users WHERE $user_id = ?
Then you provide the value at execute time.
mysql_query() takes a string and it doesn't need to be a constant string, it can be a variable.
$SQL = "SELECT foo FROM bar b";
SQLSet = mysql_query($SQL);
Aa you can see, you can use ordinary string manipulation to build your whole SQL query.
$SQL="SELECT * FROM MyTable";
$BuzID = 5;
$Filter = "Buz=".$BuzID;
if (is_numeric($BuzID)) SQL .= " WHERE ".$Filter;
SQLSet = mysql_query($SQL);
This will expand to "SELECT * FROM MyTable WHERE Buz=5" if $BuzID is set to any number.
If not the statement will just be "SELECT * FROM MyTable"
As you can see, you can build very complex SQL statements on the fly without need of variable support in the SQL server.
IF you want constants such as database name, user login, you can but them in a separate include located outside the public directory.
SecretStuff.inc.php
$__DatabaseName = "localhost";
$__UserName = "DatabaseAccess";
$__Password = "E19A4F72B4AA091C6D2";
Or have the whole PHP database connection code in the same file.