I'm thinking about an application which recieves massive Data from the User.
But this data has to be verified in php:
f.e. $_GET['id'] has to be a number every Element of an array must be a value between a specific range.
so how efficient are functions like is_int($x) or isset($x) ?
Maybe if($x!=null) is faster or (int) x is causing same results.
What is the best way to handle Data that needs to get to Database quick but needs to be verified? Is there any difference in $_GET and $_POST in speed?
Maybe implementing a class doing that improves something?
Maybe for an more concret chance to answer, here a bit inefficent code:
if(isset($_GET["x"]) && $_GET["x"] > 0) { $x = $_GET["x"]; }
if(isset($_GET["y"]) && $_GET["y"] > 0) { $y = $_GET["y"]; }
if(isset($_GET["winWidth"]) && $_GET["winWidth"] > 0) { $winWidth = $_GET["winWidth"]; }
if(isset($_GET["winHeight"]) && $_GET["winHeight"] > 0) { $winHeight = $_GET["winHeight"]; }
if(isset($_GET["a"])) { $a = $_GET["a"]; }
UPDATE:
What about further security functions like:
mysql_real_escape_string($str);
or
stripslashes()
?
Please Stackoverflow, show me the magic :)
Harry
The fastest way to check if something has been posted and whether it's a positive integer:
if (isset($_POST['field']) && ctype_digit($_POST['field']))
mysql_real_escape_string is incredibly slow, compared to addslashes. However, it's definitely more secure.
However, it's normally not necessary to worry about all this too much. We're talking about billionths of a second here.
Related
I have code as bellow :
number_format(($hasilz->harga>100000 ? $hasilz->harga+2000 :
($hasilz->harga>300000 ? $hasilz->harga+4000 :
($hasilz->harga>400000 ? $hasilz->harga+8000 :
$hasilz->harga+10000))), 0, ',', '.')
this code result and read +2000 and +10000 only
any idea ?
Let's see what you got there (simplified):
if (hagara > 100000) {
harga+2000
} else if (hagara > 300000) {
hagara+4000
} else if (hagara > 400000) {
hagara+8000
} else {
hagara+10000
}
If you write it like this, its easy to see. hagara is either >100000 which results in +2000 or it is less, then it results in +10000.
In other words, the two else if will never be true, because if they were, the first if would already be true.
I think this is also a good example, when you should NOT use the tenary operator. It just makes it really hard to read and understand... sometimes the good old it-approach ist just the better solution. ;)
EDIT: To answer the question, you have to use a different order of the if-statements, beginning with the biggest one (or write them completely different). However, as already mentioned, you shouldn't do that.
Just in case anyone was not familiar with Joomla, countModules is a function built into it. Also keep in mind I am NOT very familiar with PHP.. and I'm rather new to using it. Please try to keep any solutions simple for understanding. Thanks.
My questions is could I condense this:
if($this->countModules('Top1A and Top1B') >= 1) $modCellRow1 = "col2";
if($this->countModules('Top1B and Top1C') >= 1) $modCellRow1 = "col2";
if($this->countModules('Top1A and Top1C') >= 1) $modCellRow1 = "col2";
into this:
if ($this->countModules('Top1A and Top1B') >= 1) || ($this->countModules('Top1A and Top1B') >= 1) || ($this->countModules('Top1A and Top1C')
{
$modCellRow1 = "col2";
}
If you do know Joomla and countModules... or even if you don't, keep in mind I am checking to see if there is anything in each of the module positions rather then counting how many actual modules there are. In other words, I DO need to use AND as an operator. Also, I don't want to include all three because that is another line in my code... for example:
if($this->countModules('Top1B and Top1B and Top1C') >= 1) $modCellRow1 = "col3";
What I'm checking on those other statements is whether there is something in just TWO of the module positions... (I.E. only two of the three that are equal to or greater the one... but not all three).
ADDITIONAL COMMENT / QUESTION:
Would this work then?
$topRow1Count = 0;
foreach(array('Top1A','Top1B','Top1C','Top1D') as $position) {
if ($this->countModules($position)) {$colCount += 1;}
}
$modColCountTopRow1 = "col" . $topRow1Count;
if ($topRow1Count == 0) { $modTopRow1 = " hidden"; }
$topRow2Count = 0;
foreach(array('Top2A','Top2B','Top2C','Top2D') as $position) {
if ($this->countModules($position)) {$colCount += 1;}
}
$modColCountTopRow2 = "col" . $topRow2Count;
if ($topRow2Count == 0) { $modTopRow2 = " hidden"; }
if ($topRow1Count + $topRow2Count == 0) { $topModCont1 = " hidden"; }
Yes it will work. But let's consider performance and readability.
Performance
You are invoking countModules 3 times for the "col2" case, once for the "col3" case assuming you are starting with "col1" it will be 4 invocations,each with multiple "positions" to check for.
Now the countModules() code is pretty optimized, falling back to a single static class that will not query the db at every iteration; but you're still making your program 10 times slower than it should be even in a small site with few modules.
Readability & code quality
You might have read that code should not look like it's copied and pasted. That makes sense at least because it's easier to read code that avoids duplication, additionally it will be less prone to typos.
In the spirit of condensing multiple statements, instead of joining lines, why not consider:
$colCount = 0;
foreach(array('Top1A','Top1B','Top1C') as $position) {
if ($this->countModules($position)) {
$colCount += 1;
}
}
$modCellRow1 = "col" . $colCount;
This will return "col0" if no modules are in any of the positions, "col1" if modules are present only in one and so on.
I wrote it so it's easiest to read,
I am creating a web application that takes in a user input (Scientific Paper DOI) and queries a database to display a graph. I've been trying to limit the connections made to the database since its on a remote server (private DMZ with web server) by checking the user input if it matches a correct DOI.. if it doesn't then no connection to the database will be made, I hope this will help speed up the application if there are many users at once making queries.
Pseudo: All paper DOIs start with "10.1103/" because they are all physics papers. This part I have implemented correctly using substr. Next I want to check every character in the input to make sure it only consists of only these characters:
Letter
Number
"/"
"."
Example DOIs:
10.1103/RevModPhys.9.1
10.1103/RevModPhys.76.1015
10.1103/PhysRevLett.95.208304
Here is my code:
function checkDOI($doi) {
if (substr($doi, 0, 8) != "10.1103/") {
echo "Invalid DOI";
return false;
}
for ($n = 0; $n < strlen($doi)+1; $n++) {
if ( !ctype_alnum($doi[n]) && $doi[n] != "." && $doi[n] != "/") {
echo "Invalid DOI";
return false;
}
}
echo "Valid DOI";
return true;
}
if(isset($_POST['submit'])) {
$doi_input = $_POST['doi_input'];
checkDOI($doi_input);
}
I am working with PHP and javascript for the very first time, the pseudo is fairly simple but for some reason, there is something wrong with the 2nd if statement. Not sure if I can really do that. The Echos are just for tests.
Do you think doing this check for every input will slow down the application significantly? Is it worth it to limit the amount of connections to mysql?
The bottom of the code will be modified once I have this working to only query the database if checked returns true.
Thanks for the help!
to check every character in the input to make sure it only consists of only these characters
I suggest you to use preg_match.Try this:
$value="10.1103/RevModPhys.9.1";
if(preg_match("/^[a-zA-Z0-9\/.]+$/", $value)){
echo "match found";
}else{
echo "no match found";
}
Check here: Demo
For more info: preg_match
Your error is $doi[n], it is not an array and should it be the index is invalid.
So use a function like
$chars_doi = str_split($doi);
Before the loop to get an array of characters then use in your loop
$chars_doi[$n]
So you should have something like:
$chars_doi = str_split($doi);
$size = sizeof($chars_doi) - 1;
for ($n = 0; $n < $size; $n++) {
if (!ctype_alnum($chars_doi[$n]) && $chars_doi[$n] != "." && $chars_doi[$n] != "/") {
echo "Invalid DOI";
return false;
}
}
Little tip, avoid use functions such as strlen / sizeof as a loop argument or it will get called at each iteration. It is better for performance to store the value in a variable beforehand.
I would just do:
if (! preg_match ('#^10\.1103/[\p{L}\p{N}.-_]+$#', $doi)) {
... // bad
return;
}
// good
Reference:
http://www.php.net/manual/en/reference.pcre.pattern.syntax.php
http://php.net/manual/en/regexp.reference.unicode.php
I am working on a little project of designing a website for my friends and myself.
I am currently building the user registration system and am wondering if the way I am checking user's entries is the best it could be.
Um, ignore the api stuff, it is for eve and likely irrelevant.
I have plans for the elses.
Essentially, I would like to know if this is acceptable in terms of... everything.
And if not, what could I do to improve this.
I am newer to PHP, please be kind :)
So, this is what I am currently using:
if (!empty($_POST['username'])
&& !empty($_POST['password1'])
&& !empty($_POST['password2'])
&& !empty($_POST['email1'])
&& !empty($_POST['email2'])
&& !empty($_POST['keyID'])
&& !empty($_POST['vCode'])
){
$api = new EVEAPI();
if ($api->getCharacterID($_POST['username']) != 0){
//The username is valid.
if ($_POST['password1'] == $_POST['password2']){
//Passwords match.
if ($_POST['email1'] == $_POST['email2']
&& filter_var($_POST['email1'], FILTER_VALIDATE_EMAIL)
){
//Emails match and are in valid format.
if ($api->isValidAPI($_POST['keyID'], $_POST['vCode'])){
//If the API returns something that is not an error, continue.
$xml = $api->getAPIKeyInfo($_POST['keyID'], $_POST['vCode']);
if ($xml->result->key->attributes()->type == 'Account'){
//If the 'type' of the returned API info is 'Account', continue.
foreach ($xml->result->key->rowset->row as $apiRow){
$charID = (int) $apiRow->attributes()->characterID;
if ($charID == $api->getCharacterID($_POST['username'])){
//DO SOMETHING WITH INFO
}
else{
}
}
}
else{
}
}
else{
}
}
else{
}
}
else{
}
}
else{
}
Efficiency wise this isn't going to matter all that much, but for maintainability's sake it will.
Instead of nesting so many ifs like that, try early failure with your ifs. Something like this:
if ($api->getCharacterID($_POST['username']) == 0) {
// Fail early. Throw an exception, die, or whatever
}
// Continue along as normal, not in an else.
if ($_POST['email1'] != $_POST['email2']) {
// Fail early. Throw an exception, die, or whatever
}
// Etc.
That sort of strategy will generally serve you well unless there's a very good reason to not use it.
It is hard to read and not very clean. The way I do it is use negative if statements. By that I mean the following:
if ($api->getCharacterID($_POST['username']) == 0){
// Username is not valid, so stop execution
}
if ($_POST['password1'] != $_POST['password2']) {
// Send error to user and stop execution
}
// ...etc.
Now how do you stop execution? Well you have few options
Throw an exception
Use die statement
have a parameter that you change everytime you enter an if block, then check if you should continue.
some other solution
But the point is, this approache makes your code cleaner.
Cheers.
These days mostly programmer use jquery / Javascript for forms validations, but if you are using pure PHP the try below code, hope it will be good and secure obviously :)
$username = mysql_real_escape_string($_POST['username']);
if($username == "")
{
$username_required = '<div>Please enter your username</div>';
} else {
$username_ok = true;
}
Typically in most validation patterns out there they have this errors array where you check for all the conditions and add error messages into the array if the array is empty at the end it only means that there are no errors..
For me i wouldn't want my code to look too nested like this i would use variables to dictate each step.
From there you can decide whether to display just the first error. It doesnt hurt to validate through everything at once because the processing should not be that extensive unless you have like 5000 form fields. I think it's ok.
When you code you must remember because code is written for humans and you will want to be kind to your eyes or for those who read your code.. Basically nested is ok. it saves some further processing and it also depends on the logic you need.
Yes its good to save time but at times you do things too nicely to minimize processing you have to weigh the needs if you do it so nice but in the end the time you save is so substantial then it makes no point.. The compiler is not going to pat your back and say good job anyways..
$errors = array();
$usernameValid = $api->getCharacterID($_POST['username']) != 0;
if (!$usernameValid) $errors[] = 'Username is not valid';
//If you want to store which attribute caused the error you can use the attribute name as array key
//if (!$usernameValid) $errors['username'] = 'Username is not valid';
$passwordMatches = $_POST['password1'] == $_POST['password2'];
if (!$passwordMatches) $errors[] = 'Password does not match';
if ($usernameValid && $passwordMatches)
{
//What to do if user name and password passes validation. wooo hoo~
}
//Etc etc..
So I have an affiliate program that's lately been getting a lot of bad leads from countries we don't service, which we tell affiliates will be voided. Anyways, this is going to cause our reversal rate to be through the roof. So I want to do something about it.
So I want to use geoip, which gets me the stuff as a 2 letter country code.
<?php
$output = shell_exec('geoip-lookup '.$_SERVER['REMOTE_ADDR']);
?>
So how do I put that together?
Would this be correct?
<?php
$output = shell_exec('geoip-lookup '.$_SERVER['REMOTE_ADDR']);
if($_SESSION['check']!=1) && ($output=='US' || $output=='AU' || $output=='GB' || $output=='CA')
{
$submission = $_POST['submission_id'];
$_SESSION['check']=1;
echo 'insert pixel';
}
?>
You'll want to verify $output is what you expect (i.e. a string - var_dump($output)).
However, provided it is, you'll need to quote your country codes to do a string comparison. Also, as noted by heximal, be sure to use == for comparison. Otherwise, it's an assignment.
if ($_SESSION['check'] != 1 && ($output == 'US' || $output == 'AU' ...)) {
Otherwise, the rest of you code appears correct (without knowing your exact logic).
I am not familiar with "geoip-lookup" but I have "geoiplookup" working in my Ubuntu shell. Hopefully I can assume they are the same?
Putting $_SERVER values into a shell command has the potential for disaster, because they can be spoofed, so be careful with that.
Try the following:
// Make sure that the remote address is an IP and not something harmful, like "1.1.1.1; rm ../ -rf".
$found = preg_match('/^(?:\d{1,3}\.){3}\d{1,3}$/', $_SERVER['REMOTE_ADDR']);
if($found)
{
$command = escapeshellcmd('geoiplookup '.escapeshellarg($_SERVER['REMOTE_ADDR']));
$output = shell_exec($command);
if(($_SESSION['check']!=1) && (strpos($output,'US')!==false || strpos($output,'AU')!==false || strpos($output,'GB')!==false || strpos($output,'CA')!==false))
{
$submission = $_POST['submission_id'];
$_SESSION['check'] = 1;
echo 'insert pixel';
}
}
Be careful with $output=US
if you want to compare two operands you should use == operator