Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
JasonV
Dec 8, 2003

fletcher posted:

Just use PDO and avoid creating Yet Another Layer.

Whether it's msyqli prepared statements or PDO prepared statements it's the same issue.

Every time you use one there's a bunch of repeated code. Best to have that in one spot -- like, say, in a database class -- instead of scatter all over the application, no?

That way if you wanted to, you know, switch from mysqli to PDO you only have to change code in one place.

Adbot
ADBOT LOVES YOU

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

JasonV posted:

Whether it's msyqli prepared statements or PDO prepared statements it's the same issue.

Every time you use one there's a bunch of repeated code. Best to have that in one spot -- like, say, in a database class -- instead of scatter all over the application, no?

That way if you wanted to, you know, switch from mysqli to PDO you only have to change code in one place.

And in doing so you throw out all the performance benefits of using a prepared statement. For a simple application, using PDO will allow you to switch database vendors fairly easily. For everything else, there will be a ton of work involved in changing database vendors anyways.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!
I have a question about prepared statements... I am learning how to use prepared statements and get away from old queries. The one thing i've run into is mysql_insert_id. I will insert data into a table and then get the id of that last insert to use in a different table. Specifically when creating a new user, I'll insert the user info into the users table and then insert detailed info about the user into another table with the id.

I would always use $id = mysql_insert_id(); to get the ID. I've read that using PDO there is a very similar function but I've also read not to use it because it really only works witn MySQL, but even then can cause issues.
$id = $DB->lastInsertId();

Is there a preferred method for doing what I am trying to do without doing extra queries to select the id from the database using the username or some other unique value to be sure to get the proper id?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

DarkLotus posted:

Is there a preferred method for doing what I am trying to do without doing extra queries to select the id from the database using the username or some other unique value to be sure to get the proper id?

Yeah I have always avoided lastInsertId and instead just issue another query to grab the id for whatever was just inserted. Bit of a pain in the rear end, but it works.

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

fletcher posted:

Yeah I have always avoided lastInsertId and instead just issue another query to grab the id for whatever was just inserted. Bit of a pain in the rear end, but it works.

I figured that is the most compatible way of doing it but thought since PDO is so awesome there must be a more efficient way.

FuzzyBuddha
Dec 7, 2003

Recently, I "inherited" a website, and, at least temporarily, I'm responsible for keeping the pages up to date while the company I work for looks for a permanent employee. A case of "well, he's done it in the past, so he can do it until then..."

A recent security audit of the website has shown a vulnerability to javascript injections. I traced it down to a particular file, and unfortunately, it's a short php file that is included in nearly every page of our site. It pretty much just contains the following:
code:
if($_GET['print']) {
        include_once('print.php');

} else {
        include_once('screen.php');
}
Basically, it chooses a template depending on if you want the normal web page or a printable page. I see there's no sanity checking on the value of 'print'.

So I hunt down a decent regex for php that might do some basic sanity checking and update the code to:
code:
$notAllowedExp = array(	
			'/<[^>]*script.*\"?[^>]*>/','/<[^>]*style.*\"?[^>]*>/',
			'/<[^>]*object.*\"?[^>]*>/','/<[^>]*iframe.*\"?[^>]*>/',
			'/<[^>]*applet.*\"?[^>]*>/','/<[^>]*window.*\"?[^>]*>/',
			'/<[^>]*docuemnt.*\"?[^>]*>/','/<[^>]*cookie.*\"?[^>]*>/',
			'/<[^>]*meta.*\"?[^>]*>/','/<[^>]*alert.*\"?[^>]*>/',
			'/<[^>]*form.*\"?[^>]*>/','/<[^>]*php.*\"?[^>]*>/','/<[^>]*img.*\"?[^>]*>/'
			);//not allowed in the system

foreach($_GET as $queryString => $value) {
	foreach($notAllowedExp as $exp) {
		if (preg_match($exp, $value)) exit;
	}
}

if($_GET['print'] == "true") {
	include_once('print.php');
	
} else {
	include_once('screen.php');
}
Not great, but at this point, all I want it to do is stop everything if some unwanted items are put in the GET. However this doesn't actually seem to do anything. My php skills are pretty weak, so I'm not exactly sure what I've done wrong, and was hoping someone could spot it. Been quite a while since I was in the web development game.

FuzzyBuddha fucked around with this message at 23:31 on Jun 24, 2010

Lumi
Apr 26, 2006
I watched the sky.

Plorkyeran posted:

You can't. HTTP redirects only support GET and HEAD. Stick the data in the session or something.

Thanks. I'll do that carefully.

Tad Naff
Jul 8, 2004

I told you you'd be sorry buying an emoticon, but no, you were hung over. Well look at you now. It's not catching on at all!
:backtowork:

FuzzyBuddha posted:


code:
if($_GET['print']) {
        include_once('print.php');
} else {
        include_once('screen.php');
}

I don't really see the security hole here, since the value stored in $_GET['print'] isn't actually used. Maybe it throws an undefined index warning? That would be fixed with

code:
if(isset($_GET['print'])) {
        include_once('print.php');
} else {
        include_once('screen.php');
}

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

FuzzyBuddha posted:


Not great, but at this point, all I want it to do is stop everything if some unwanted items are put in the GET. However this doesn't actually seem to do anything. My php skills are pretty weak, so I'm not exactly sure what I've done wrong, and was hoping someone could spot it. Been quite a while since I was in the web development game.

I'm a bit confused here. Are you passing in a bunch of HTML in through the url? And you want to prevent naughty bits of HTML from getting through?

FuzzyBuddha
Dec 7, 2003

fletcher posted:

I'm a bit confused here. Are you passing in a bunch of HTML in through the url? And you want to prevent naughty bits of HTML from getting through?

One of two things occurs: either nothing is passed in the URL or "print=true" is being passed. Based on this, this php file chooses which template to utilize.

What we found is if you append the url to pretty much any page with something like:
?"><script>alert('test')</script>

then the script gets executed. My guess is, it's because of this small php script, as no other include file seems to deal with $_GET at all...

EDIT - Hmmm, I lied...
Looks like another include does a $_SERVER['REQUEST_URI'] that does no sanity checking, either...

FuzzyBuddha fucked around with this message at 01:56 on Jun 25, 2010

snare
May 28, 2010
Blacklisting is generally a bad idea since it can be computationally expensive and difficult to keep current. The best way to approach data sanitisation for Cross-Site Scripting is to encode the tainted data with HTML entities before it is output. If this data is not being used in database queries etc and is simply reflected, just use htmlentities() to encode the data when it is output.

Check out the OWASP ESAPI for PHP too, it provides a bunch of encoding, data validation, access control, etc functionality.

FuzzyBuddha
Dec 7, 2003

snare posted:

...

If this data is not being used in database queries etc and is simply reflected, just use htmlentities() to encode the data when it is output.

...

Wow. That did it. :) No, the data's not being sent to a database, so gave that a shot with the second include and it fixed the issue across the site.

Also, thanks for the references. I can't believe how rusty I've gotten with this.

Peanut and the Gang
Aug 24, 2009

by exmarx
Speaking of security:
http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2010-2225

Stefan Esser posted:

The 0-day I showed at SyScan Singapore was a use-after-free vulnerability in PHP's unserialize().Unserializing user input==remote code exec.

Stefan Esser posted:

The exploitation path I demoed at SyScan will only work against non Suhosin protected servers. More complicated exploits allow to bypass Suhosin.

A lot of php applications use unserialize on user input. Codeigniter, for instance, unserializes passed cookie data, even when you enable the option to store "session" data in the database. And I use Codeigniter at work!

Edit: I spoke too soon on Codeigniter. It checks a hash of the string with a unique key before running unserialize

Peanut and the Gang fucked around with this message at 21:26 on Jun 25, 2010

snare
May 28, 2010
Yeah that vuln is cool, I'd be interested to see what's required to bypass Suhosin.

Begby
Apr 7, 2005

Light saber? Check. Black boots? Check. Codpiece? Check. He's more machine than kid now.

fletcher posted:

Yeah I have always avoided lastInsertId and instead just issue another query to grab the id for whatever was just inserted. Bit of a pain in the rear end, but it works.

Darklotus:

Be careful with this and make sure you grab the key correctly. If your app is being used by more than one user then it could result in a race condition where you end up with the wrong ID if you just try to fetch the largest value or something like that. What fletcher is most likely doing is running a query for the exact record he just inserted. That could fail though if more than one record is identical, and that depends on what kind of records you are inserting.

Some databases have specific functions you can call to get the last inserted id for the current connection. But then you have to change your code to be database specific and then it might get whacky if you are sharing connections.

Begby fucked around with this message at 15:28 on Jun 25, 2010

butt dickus
Jul 7, 2007

top ten juiced up coaches
and the top ten juiced up players
Thanks, Begby. I'm now using mysql_insert_id() instead of retardedly building a query to find what I just inserted.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe
If, in the headers of an email, I specify that it is Content-Type: text/plain; charset=utf-8, then there is no need to escape HTML special characters, correct? (I have functionality where my users can opt to allow other users to send them email messages, mediated by the site. I'm in the middle of rewriting the code.)

DarkLotus
Sep 30, 2001

Lithium Hosting
Personal, Reseller & VPS Hosting
30-day no risk Free Trial &
90-days Money Back Guarantee!

Begby posted:

Darklotus:

Be careful with this and make sure you grab the key correctly. If your app is being used by more than one user then it could result in a race condition where you end up with the wrong ID if you just try to fetch the largest value or something like that. What fletcher is most likely doing is running a query for the exact record he just inserted. That could fail though if more than one record is identical, and that depends on what kind of records you are inserting.

Some databases have specific functions you can call to get the last inserted id for the current connection. But then you have to change your code to be database specific and then it might get whacky if you are sharing connections.

mysql_insert_id() does this safely without grabbing the wrong id. I'm looking for a way to do this with PDO. Any suggestions?

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Hammerite posted:

If, in the headers of an email, I specify that it is Content-Type: text/plain; charset=utf-8, then there is no need to escape HTML special characters, correct? (I have functionality where my users can opt to allow other users to send them email messages, mediated by the site. I'm in the middle of rewriting the code.)

IE gives no gently caress and will detect and use HTML anyway.

Huh, and Safari decided it needed to be downloaded like an octet stream.

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Munkeymon posted:

IE gives no gently caress and will detect and use HTML anyway.

Huh, and Safari decided it needed to be downloaded like an octet stream.

What HTML, all html? So my users could goatse each other? Send each other malicious scripts? Maybe I should just send minimalist HTML emails, then.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Hammerite posted:

What HTML, all html? So my users could goatse each other? Send each other malicious scripts? Maybe I should just send minimalist HTML emails, then.

I don't know where the cutoff is, but if I add the text/plain content header to my normal php whipping boy/testing script, IE still renders it as HTML. To be fair, the first thing in the file is an HTML opening tag, but still, if it's going to ignore your content headers, then you can't just rely on them.

That was IE8, by the way, so it's not like it'd just be the users in the IE6 ghetto that'd get goatse'd.

There aren't any PEAR classes that will display an email safely? Something in the framework you're using if your using one?

edit: messed with it a bit more and it seems inconsistent. If I had an opening pre or img within the first 202 characters, it was HTML, but not an i tag or a b tag. Break tags don't trip it anywhere, so I'm guessing at this point that an opening tag of a tag that has to be closed and is not a single letter somewhere within the first ~200 bytes will trip HTML mode.

I'd say be afraid - be very afraid.

Munkeymon fucked around with this message at 21:38 on Jun 25, 2010

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

Munkeymon posted:

I don't know where the cutoff is, but if I add the text/plain content header to my normal php whipping boy/testing script, IE still renders it as HTML. To be fair, the first thing in the file is an HTML opening tag, but still, if it's going to ignore your content headers, then you can't just rely on them.

That was IE8, by the way, so it's not like it'd just be the users in the IE6 ghetto that'd get goatse'd.

There aren't any PEAR classes that will display an email safely? Something in the framework you're using if your using one?

How the email displays is not under my control, only the content is. If a user opts in to receiving emails from other users, then any other user can use a form page to send them an email (they don't see the address).

epswing
Nov 4, 2003

Soiled Meat

Hammerite posted:

If, in the headers of an email, I specify that it is Content-Type: text/plain; charset=utf-8, then there is no need to escape HTML special characters, correct?

Hammerite posted:

How the email displays is not under my control, only the content is.

Sounds like you answered your own question there chief.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

DarkLotus posted:

mysql_insert_id() does this safely without grabbing the wrong id. I'm looking for a way to do this with PDO. Any suggestions?

That is a MySQL specific thing and not all database vendors support it, so there isn't a reliable function to use in PDO for that.

http://php.net/manual/en/pdo.lastinsertid.php

quote:

Note: This method may not return a meaningful or consistent result across different PDO drivers, because the underlying database may not even support the notion of auto-increment fields or sequences.

Instead, just issue an extra query to grab the id for what was just inserted:

php:
<?
$insert = $db->prepare("INSERT INTO user (username, email, password) VALUES (:username, :email, :password)");
$insert->bindParam("username", $username);
$insert->bindParam("email", $email);
$insert->bindParam("password", $password);

if ($insert->execute()) {
    $query = $db->prepare("SELECT id FROM user WHERE username = :username AND email = :email AND password = :password");
    //etc
}
?>

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

epswing posted:

Sounds like you answered your own question there chief.

What I wanted to find out was whether I could rely on commonly-used software to pay attention to the content-type header and not attempt to detect and display HTML. Which, disregarding for a minute the fact that a lot of software does retarded things, is not an unreasonable thing to imagine might be the case.

Turns out I cannot do that though, so I now propose to HTML-escape the user's email and send it as an HTML email.

I mean, I'm responding to your post in as much as what you typed actually makes sense. Quoting me saying that I've no control over how content is displayed and making a snarky comment to the effect of "Well then you'd better not send the data in XXX format or it may be willfully misinterpreted in YYY fashion!" really makes only a very facile point (I'd better not send any text that contains the letter "G", either, as it might be viewed using software that replaces the letter "G" with Goatse).

ShoulderDaemon
Oct 9, 2003
support goon fund
Taco Defender

Hammerite posted:

Turns out I cannot do that though, so I now propose to HTML-escape the user's email and send it as an HTML email.

The only software that has been mentioned as ignoring Content-type and detecting based on heuristics so far is Internet Explorer.

You are sending email. Internet Explorer is not an email program.

epswing
Nov 4, 2003

Soiled Meat
Ok, I guess I'll clarify. You're sending text to an email program, and you can "suggest" but can't control if the content is displayed in plaintext or html, so your options are really simple: if you want to prevent users sending each other html, then escape (or strip) html chars, otherwise don't.

I'm not trying to argue with you, I just think you already knew that, and assumed you answered your own question.

epswing fucked around with this message at 06:34 on Jun 26, 2010

Sylink
Apr 17, 2004

I have some dumb memory leak trying to resize a lot of images about 1mb in size each.

The script fails through a loop over a directory about half way through when it reaches the server memory limit.

Imagedestroy() is supposed to solve this but it apparently isnt.

The main function:
code:
<?php

function createthumb($name,$filename,$new_w,$new_h)
{	

	$system=explode(".",$name);
	if (preg_match("/jpg|jpeg|JPG/",$system[1])){$src_img=imagecreatefromjpeg($name);}
	if (preg_match("/png/",$system[1])){$src_img=imagecreatefrompng($name);}
	$old_x=imageSX($src_img);
	$old_y=imageSY($src_img);
	if ($old_x > $old_y) 
	{
		$thumb_w=$new_w;
		$thumb_h=$old_y*($new_h/$old_x);
	}
	if ($old_x < $old_y) 
	{
		$thumb_w=$old_x*($new_w/$old_y);
		$thumb_h=$new_h;
	}
	if ($old_x == $old_y) 
	{
		$thumb_w=$new_w;
		$thumb_h=$new_h;
	}
	$dst_img=ImageCreateTrueColor($thumb_w,$thumb_h);
	imagecopyresampled($dst_img,$src_img,0,0,0,0,$thumb_w,$thumb_h,$old_x,$old_y); 
	if (preg_match("/png/",$system[1]))
	{
		imagepng($dst_img,$filename); 
	} else {
		imagejpeg($dst_img,$filename); 
	}
	imagedestroy($dst_img); 
	imagedestroy($src_img); 
	
}


?>
And the loop its in

code:
foreach ($images as $item) {
		if (file_exists('../thumbs/small_' . $item)){
			}
			else {
				createthumb($item,'../thumbs/small_' . $item  ,100,100);
				}
		echo '<a rel="images" href="' .$item. '" title=""><img alt="" src="maindirectory/thumbs/small_'.$item. '" /></a>';
	}
Generates the error Fatal error: Allowed memory size of 94371840 bytes exhausted (tried to allocate 60196 bytes) in etc

I dont get it.

s0beit
Sep 23, 2008
I WISH GRANDMA HAD DIED SO I WOULDN'T HAVE TO TALK TO LIBERALS
Definitely doesn't need its own thread but i am sort of assuming PHP programmers have run across the same issue.

My youtube video downloader is broken because "get_video" no longer exists, has anybody solved this (quasi-non-php question i know)?

JasonV
Dec 8, 2003

Sylink posted:


code:

	if (preg_match("/jpg|jpeg|JPG/",$system[1])){$src_img=imagecreatefromjpeg($name);}
	if (preg_match("/png/",$system[1])){$src_img=imagecreatefrompng($name);}
	

What happens if neither of these are true ?

Hammerite
Mar 9, 2007

And you don't remember what I said here, either, but it was pompous and stupid.
Jade Ear Joe

JasonV posted:

What happens if neither of these are true ?

Also, what happens if you have a file name like "png.jpg"?

SiCk
Jul 4, 2003

My name's SiCk, and I'm the Biggest Idiot Ever!

Hammerite posted:

Also, what happens if you have a file name like "png.jpg"?

or something.like.this.jpg surely?

DoctorScurvy
Nov 11, 2005
More of a passing curiosity, really
Would this be a suitable alternative?
php:
<?
$imginfo = getimagesize($name) or die("Invalid image filename provided");
$imgtype = $imginfo['mime'];
switch ($imgtype) {
    case 'image/jpeg':
        $src_img=imagecreatefromjpeg($name);
        break;
    case 'image/png':
        $src_img=imagecreatefrompng($name);
        break;
    default:
        die("Image format ".$imgtype." not supported");
}
$old_x = $imginfo[0];
$old_y = $imginfo[1];
?>

KuruMonkey
Jul 23, 2004

DoctorScurvy posted:

Would this be a suitable alternative?

Personally I use this (well, the actual version I use is one method of a GD2Image class, but I extracted this bit in isolation):

php:
<?
    // load an image file into gd2, from any given file type
    function imagecreatefromfile($path)
    {
        // want more image loaders? just edit this array...
        $image_loaders = array(
            IMAGETYPE_JPEG=>'imagecreatefromjpeg',
            IMAGETYPE_GIF=>'imagecreatefromgif',
            IMAGETYPE_PNG=>'imagecreatefrompng'
        );

        if(!file_exists($path))
            throw new Exception("File Not Found");

        $imagetype = exif_imagetype($path);

        if(!array_key_exists($imagetype, $image_loaders))
            throw new Exception("Unsupported Image Type");

        $gd2image = call_user_func($image_loaders[$imagetype], $path);

        if($gd2image === FALSE)
            throw new Exception("Image Create Error");

        return $gd2image;    
    }
?>
exif_imagetype is nice.
the exceptions in this above are bodged, as they are all defined in the class and used all over, I hastily extracted this function, if you see what I mean...

Master_Odin
Apr 15, 2010

My spear never misses its mark...

ladies
After several online searches, I couldn't find an answer to this.

When I do this:
code:
<?php
echo include("/pages/what-s-happening.page.php");
?>
a 1 appears after the block of text that's printed. I've seen this before when doing something like print_r($array), but never with using echo and I'm unsure of what this means. The file I'm including is just HTML coding for a page:
code:
<p>text</p>
so I'd see:
code:
<p>text</p>1
and since nothing ever mentions this, I'm confused about it and how to make it so that 1 doesn't appear.

e: fixed it by changing it to get rid of the echo, but an explanation of the 1 would still be appreciated.

Master_Odin fucked around with this message at 19:20 on Jul 3, 2010

duz
Jul 11, 2005

Come on Ilhan, lets go bag us a shitpost


Master_Odin posted:

e: fixed it by changing it to get rid of the echo, but an explanation of the 1 would still be appreciated.

The include succeeded so it returned a 1 which you then echoed.

JasonV
Dec 8, 2003
I need to write a little php script that will let users upload a CSV file, parse it and then insert records into an sql datbase.

The problem I'm having is these CSV files can be pretty big, each line needs some logic to determine what updates and/or inserts need to be run and the whole thing can involve a few thousand queries. The user is left wondering if the script has crashed, I'm stuck upping the max execution time, but any arbitrary limit I set might not be high enough, etc..

I can think of a few ideas how to deal with it, but they seem kind of hackish and was wondering what a good way to do this would be?

Sneaking Mission
Nov 11, 2008

I'd probably just save the uploaded file to a processing directory and have a separate program monitoring for new uploads and running them when they appear. That way the PHP handler for that user's connection isn't the one running the job. You could redirect the user to a status page where the processing program can update them on its progress.

JasonV
Dec 8, 2003

Sneaking Mission posted:

I'd probably just save the uploaded file to a processing directory and have a separate program monitoring for new uploads and running them when they appear. That way the PHP handler for that user's connection isn't the one running the job. You could redirect the user to a status page where the processing program can update them on its progress.

Unfortunately, getting that kind of access to the server would involve a lot of red tape and probably get turned down. I'm replacing what is now a manual process which everyone is pretty much happy with, except the poor people who have to spend days doing it by hand...

Adbot
ADBOT LOVES YOU

spiritual bypass
Feb 19, 2008

Grimey Drawer
When it comes to gigantic file uploads, it seems to me that web apps just aren't the right tool for the job. No chance of reimplementing it in something like Java, I suppose?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply