Forum Moderators: coopster

Message Too Old, No Replies

Magic Quotes!

some questions..

         

dreamcatcher

2:59 pm on Dec 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Hi Guys,

I just need you to clear up one or two things with Magic Quotes. I`ve been reading up on them, but just need to know that I`m doing the right thing.

I`m passing info from a form to a database, so I`m doing:


if (!get_magic_quotes_runtime())

{

$blah = addslashes($blah);

}

$query = "INSERT INTO table (blah) VALUES ('$blah')";

Is this correct? Or should I use:

get_magic_quotes_gpc()?

If I echo the values of both, my server has the following set:

get_magic_quotes_gpc = 1;
get_magic_quotes_runtime = 0;

Or is it best to forget the above two and use mysql_escape_string?

I`m re-writing a guestbook script I did and before I had problems with single quotes. I just want to make sure I`m doing it the right way this time around.

Thanks for the help.

:)

Xuefer

3:45 pm on Dec 6, 2003 (gmt 0)

10+ Year Member



magic quote mode is "lazy so be safe" mode
it make programers dont need to addslashes(), but when used to echo $_GET['abc']; they need stripslashes()
if u believe all your sql query is safely escaped, loopthrough $_GET $_POST $_REQUEST, stripslashes them if magic_quote_gpc is on
and turn off magic_quote_runtime
it's just a style of program decided by yourself

dreamcatcher

7:26 pm on Dec 6, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Thanks Xeufer. The code seems to be working ok, I`m using stripslashes when I get the info from the database and htmlspecialchars(stripslashes($row['blah']) to get stuff that contains double quotes.

I was just wondering if I should use:


if (!get_magic_quotes_runtime())

or


if (get_magic_quotes_gpc())

I assume there is a difference? Is one for passing info to a database and one for just passing form data to another page?

Xuefer

1:59 am on Dec 7, 2003 (gmt 0)

10+ Year Member



it depend on what's your $blah
gpc=GET/POST/COOKIE
runtime=read in runtime(mysql_* and file* and others which read data)

i don't use magic quote

dreamcatcher

8:58 am on Dec 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



In this situation, $blah is data posted from a form input field, which is then added to the database.

Birdman

1:00 pm on Dec 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



That's funny dreamcatcher, because I was going to start a thread about this after struggling with it for a good part of yesterday. Very confusing stuff.

This is what I came up with, and it seemed to work in my case(somewhat).


function fixQuotes($str){
$fixed = htmlspecialchars(str_replace("''","'",$str), ENT_QUOTES);
return $fixed;[blue]
}

The app I'm working on must pass the info from the original form to a script, which then passes the info to another script via another form with hidden fields(originally the info was just put into a querystring but now it needs to be unlimited length).

If anyone knows a good "magic quotes for dummies" tutorial, please tell me where to find it ;)

Xuefer

2:59 pm on Dec 7, 2003 (gmt 0)

10+ Year Member



go read vbb source, there is something like stripslashes_array() function

for those don't need magic quote:
if (magic_quote_gpc()) {
stripslashes_array($_GET);
stripslashes_array($_POST);
stripslashes_array($_REQUEST);
stripslashes_array($_COOKIE);
}
set_magic_quote_runtime(0);

function stripslashes_array(&$arr) {
foreach (array_keys($arr) as $k) {
$arr[$k] = stripslashes($arr[$k]);
}
}

for those need magic quote:

if (!magic_quote_gpc()) {
addslashes_array($_GET);
addslashes_array($_POST);
addslashes_array($_REQUEST);
addslashes_array($_COOKIE);
}
set_magic_quote_runtime(0);

function addslashes_array(&$arr) {
foreach (array_keys($arr) as $k) {
$arr[$k] = stripslashes($arr[$k]);
}
}

this will make your script independ on php/server config

if u turn it on, u'd better have all your text data in "slashed" mode
echo $blah; should be echo stripslashes($blah);
use magic quote or not is at your own will.

dreamcatcher

3:01 pm on Dec 7, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



LOL! Thanks for that birdman.

This quotes thing really is a pain. I mean if I send a query to a database with addslashes, then get the info from the database for a query string, I use stripslashes to tidy it up. However, when the info is sent back to the database via the info in the query string I have to add the slash back or else it doesn`t recognise the query.

In this book I have called Professional PHP Programming, their example when adding stuff to a database is just:


if (!get_magic_quotes_runtime())
{
$name=addslashes($name);
}

So thats why I`ve been going with that. I`ve posted stuff with single and double quotes, and it seems to be ok. As I mentioned earlier, I`m using stripslashes for single quotes and for code with double quotes that displays in the HTML I`m using htmlspecialchars(stripslashes). Obviously I`m not using either when I use the code myself, but you never know what a visitor is going to type in, so I`m covering both bases.

Good job I`m going down the pub tonight to clear my head! :)

Thanks for the info Xeufer, that might be useful.

coopster

11:55 pm on Dec 7, 2003 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



To break it down to a very low level for sake of clarity, both configuration options are for adding slashes to data. The difference is from where the data is obtained:

magic-quotes-gpc ------> browser (via get, post, cookie)
magic_quotes_runtime --> database

If the directive is off, no slashes will be added automatically. If on, slashes are magically added. The example in the PHP manual [php.net] illustrates this point for us:


<?php
echo get_magic_quotes_gpc(); # ........... 1 <-- it's on, adds slashes magically!
echo $_POST['lastname']; # ............... O\'reilly
echo addslashes($_POST['lastname']); # ... O\\\'reilly
if (!get_magic_quotes_gpc()) {
$lastname = addslashes($_POST['lastname']);
} else {
$lastname = $_POST['lastname'];
}
echo $lastname; # ........................ O\'reilly
$sql = "INSERT INTO lastnames (lastname) VALUES ('$lastname')";
?>

It is extremely important that you understand how your server is configured before you read data and write data to and from your browser and/or your database tables! See what could happen if we added slashes to the posted variable and then wrote the value to our table called lastnames? We would have incorrect data! The column

lastname
would contain
O\'reilly
, which is not what we want!

Here it is from the PHP Manual pages:
-------------------------------------
magic_quotes_gpc [php.net]
Sets the magic_quotes state for GPC (Get/Post/Cookie) operations. When magic_quotes are on, all ' (single-quote), " (double quote), \ (backslash) and NUL's are escaped with a backslash automatically.

magic_quotes_runtime [php.net]
If magic_quotes_runtime is enabled, most functions that return data from any sort of external source including databases and text files will have quotes escaped with a backslash.

Important Note!
The Sybase functions [php.net] have a very specific impact on these settings when used!



These are fun configuration options, no doubt. These two configuration directives are two that can really throw your code into a tizzy if you program or use copies on different servers and the servers are configured differently (and you don't have any control over the configuration, such as hosting on a shared server). I tend to program one way or the other (for example, assume both options are always off), and ALWAYS check the implementation before bringing the code up live. One good thing is that both configuration options can be modified by dropping your own .htaccess file in the parent directory of your code and override your server settings (assuming Apache is configured to allow per-directory overrides).

Clear as mud? :)

ergophobe

12:21 am on Dec 8, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Clear as mud? :)

At least that clear! Great explanation.

Assuming that you do not have access to php.ini, what do you prefer to do in practice?

1. use your .htaccess to set these to your preference.

2. if AllowOverride prevents you from using .htaccess to set magic_quotes_gpc, do you then set m_q_runtime to match that setting (since you can't turn on m_q_gpc at runtime and you said you go for both or neither). It seems like even minimal portability would still require you to check each time.

3. check each time you have a value (as in the PHP Manual example) and branching as required? It seems like the biggest hassle but the most portable.

4. other things I haven't considered.

Tom

coopster

1:58 am on Dec 8, 2003 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



>> and you said you go for both or neither
I tend to program one way or the other (for example, assume both options are always off)

I was being hypothetical ("For example..."). I'm sorry, I didn't mean to cause the confusion there. My acutal preference is magic_quotes_gpc ON and magic_quotes_runtime OFF, but that's just me and my programming style -- it fits me better. I'm typically getting information from the user agent to process further, therefore, being a lazy programmer, I like the slashes there for me magically. If I'm getting information from the database it's usually to send to a user agent so I don't want to have to stripslashes before I run it through the htmlentities function.

>> Assuming that you do not have access to php.ini, what do you prefer to do in practice?

Order of preference?

  1. Control the server (provide the hosting) ;) OK, we can't count that one since you said I wouldn't have access to the php.ini
  2. .htaccess
  3. Customized configuration script

And quite honestly, if a shared hosting provider won't allow or set an .htaccess file, I'll recommend to the client right away that there are restrictions being imposed by their hosting provider that I am uncomfortable with and encourage them to consider alternatives. The wording "changes beyond our control" or "performed by current hosting provider outside of our control" will also make it into a contract for the obvious reasons.

If I'm developing for a client I prefer to keep the environment in a state that I can control/update very quickly. For example, let's say I develop a small system consisting of ten or so scripts. Everything works fine, I implement and three months later the client calls stating that the site is failing. A quick assessment shows that their hosting provider has updated the PHP configuration and now changed the magic_quotes gpc and/or runtime options. It is much easier to update with an .htaccess file. If I knew that wasn't an option going into the contract, I would have developed a customized configuration script that is included on every php parsed file which would contain a set_magic_quotes_runtime() as well as an addslashes function something like what follows:

my_config_script.inc.php

set_magic_quotes_runtime(0); # Turn off the database-type addslashes
$mq = get_magic_quotes_gpc();
function add_slashes($value) {
if (is_array($value)) {
foreach ($value as $key => $val) {
$return[$key] = addslashes($val);
}
return($return);
}
return addslashes($value);
}

Of course, as you stated, we would have to evaluate our $mq variable for each script that we want to handle $_GET, $_POST, $_COOKIE data:

some_script.php

include_once("my_config_script.inc.php");
foreach ($_POST as $value)) {
if (!$mq) $value = add_slashes($value);
extract($value);
}

This is by no means complete, mind you. Alternatively, I would opt for the .htaccess. And ultimately, I'll go for the hosting control ;)

ergophobe

5:23 am on Dec 8, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month




Control the server (provide the hosting) ;) OK, we can't count that one since you said I wouldn't have access to the php.ini

Too easy! I had to count that one out.

I like the idea of just running through the POST data right away and then moving on. I plan to steal that if I ever have the need.

That said, I think you meant...


include_once("my_config_script.inc.php");
foreach ($test_array as $key => $value) {
if (!$mq) $value = add_slashes($value);
$$key = $value;
}

extract expects an array as an arg

Tom

[edited to fix my dumb mistake]

Birdman

12:21 pm on Dec 8, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Coopster, thanks for the great explanation. That's makes it much more clear. Thanks to Xuefer, as well.

coopster

12:39 pm on Dec 8, 2003 (gmt 0)

WebmasterWorld Administrator 10+ Year Member



You're welcome! I cut and pasted that from existing code and you are correct, ergophobe, the particular loop I copied from was specific to array processing. But, as you said, the foundation/concept is there -- roll with it. Thanks for catching that and making the correction.

dreamcatcher

4:51 pm on Dec 8, 2003 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member



Yep, thanks for the explanations guys, appreciate it :)