PHP and magic quotes

Wednesday 22 October 2003This is nearly 21 years old. Be careful.

I just added a preview button to my comment system (try it out!), and along the way was reminded about what is good and bad about PHP. It isn’t two different things, it’s one thing: magic.

As I was working on the preview button, I was nagged by something which had bothered me before: string quoting with slashes. Looking at the data I was getting back from POSTed web forms, it already had slashes in it to quote apostrophes, double quotes, and so on. I thought I had added them myself somewhere, but could not find the place I had called addslashes. It’s natural that while passing strings from posted forms to MySQL and back to HTML, there’s a lot of slash-munging. I figured I had an old call to addslashes somewhere.

It turns out I didn’t. There is a configuration setting which automatically applies slash-quoting to the values retrieved from GET, POST, and COOKIE values. The setting is called magic_quotes_gpc. It can be set in the php.ini file, and its value can be checked with the get_magic_quotes_gpc function. There is no way to programmatically change its setting.

There’s another similar setting called magic_quotes_runtime which applies quoting automatically to external data such as databases and file contents. It can be queried with the get_magic_quotes_runtime function, and also changed programmatically with the set_magic_quotes_runtime function. Why can one be changed at runtime and the other cannot? I don’t know. Maybe there’s a good reason, maybe not.

These magic settings are just the sort of thing PHP is famous for. They do exactly the right thing for the beginner who wants to write code to run on his web server. They are special purpose functions which do a specific web job really well. If you are moving up from HTML and JavaScript, and have to write server-side code, PHP will fit you like a glove. If you approach coding empirically, then magic_quotes_gpc is no problem. You try the code, and see that slashes have been applied, and deal with it.

But if you have a more analytical approach, then magic_quotes_gpc is the kind of thing that will drive you nuts. I spent twenty minutes today rediscovering this magic quoting feature, because I couldn’t figure out why there were slashes in my POST data.

PHP is not clean. Its strength is that it is grungy, but in precisely the right ways to make simple server-side coding tasks easy. It provides tight integration between the programming language and the web server, it has a rich library for doing lots of webby stuff, and it has a simple forgiving feel to it. But once you graduate to larger coding projects, or delivering software to someone else’s server, or structuring your code for more modularity, then PHP begins to run out of steam, and its initial strengths become weaknesses.

» 8 reactions

Comments

[gravatar]
I couldn't agree more. magic_quotes is especially irritating when you are trying to write software for distribution as you have no idea if the server the software will run on will have magic quotes on or off - so you don't know if you need to apply addslashes() to data before sending it to a database. I've written a couple of functions that ensure your data is all either escaped or unescaped: http://scripts.incutio.com/magic_quotes/

I much prefer the way Python handles database escaping. In Python you simply say cursor.execute('insert into table values (%s, %s)', (value1, value2)) and the Python database layer figures out the quoting for you.
[gravatar]
magic_quotes are more than just annoying, they are pure evil. If they are on you end up writing super-dumb stuff like "INSERT INTO comments VALUES ('$comment')". If you use some databases besides MySQL and Postgres this might not even work, since some databases don't use backslash quoting. But even if not, someone will do something dumb like "SELECT ... LIMIT $limit" where $limit comes from the request. This showed up inside some (open source) code for a set of sites I help administer -- in a way it was comforting, because it made me realize that no one had it in for us. But it also would have allowed anyone to delete the entire database by using limit=1;delete+from+table (to compound things, Postgres will take multiple statements in one query).

So then you think it's best to just turn magic_quotes off. Then you get the evil backslashes. It's the worst with preview forms and the like, because one ' turns into a \', then in the preview it turns into \\\', then \\\\\\\', etc. as it is resubmitted or re-edited.

If PHP made magic quotes manditory then it wouldn't be a big deal -- you'd learn to unquote when necessary. (Well, many people would be too lazy to do it, but at least you *could* do the right thing). But by making it an option it's the worst of both worlds. If you don't specifically check for the setting you are either unsafe or sloppy.
[gravatar]
I with you guys on this, I really dislike magic_quotes! It's just one of the many, really stupid things in PHP that drives me completely nuts.
[gravatar]
You can control most of the php.ini settings with .htaccess, magic quotes included.

In previous versions you had no choice, you needed magic "on" (if I remember correctly). Now you set as you wish.
[gravatar]
Mr. Dias makes a good point, but this varies from isp to isp. If you run your own box, then playing with php.ini or .htaccess is a fine idea. On shared hosting, most magic quotes settings are locked by the admin, so .htaccess changes result in a 500 error. Very frustrating. Would be nice if phpinfo highlighted things that might bite you like memory size, magic quotes settings, path, etc.

Enjoy, Michael
[gravatar]
“But once you graduate to larger coding projects, or delivering software to someone else’s server, or structuring your code for more modularity, then PHP begins to run out of steam, and its initial strengths become weaknesses.”

...and then it’s time to move to Python. ;-)

IMHO the problem is that PHP’magic_quotes fixes the ‘escaping stuff that has to go in a database’-problem in the wrong place. As Simon illustrated above, the Python DB-api takes care of any escaping when sending your query to the database, where this should be done.

Besides, magic quotes does not make any sense when you want to do something else with the posted data besides storing it in a relational database.
[gravatar]
Its not that bad, just use stripslashes(); and it will get rid of them ;)
[gravatar]
My way around being locked into magic_quotes_gpc:

function escape_data ($data) {
if (get_magic_quotes_gpc()) $data=stripslashes($data);
return mysql_escape_string(trim($data));
}

This way, my data's escaped the way MySQL likes it, my SELECT queries return strings that I can work with immediately, and I can easily move my pages from server to server without adjustments.

Add a comment:

Ignore this:
Leave this empty:
Name is required. Either email or web are required. Email won't be displayed and I won't spam you. Your web site won't be indexed by search engines.
Don't put anything here:
Leave this empty:
Comment text is Markdown.