I'm writing a set of PHP scripts that'll be run in some different setups, some of them shared hosting with magic quotes on (the horror). Without the ability to control PHP or Apache configuration, can I do anything in my scripts to disable PHP quotes at runtime?
It'd be better if the code didn't assume magic quotes are on, so that I can use the same scripts on different hosts that might or might not have magic quotes.
Only magic_quoted_runtime can be disabled at runtime. But magic_quotes_gpc can’t be disabled at runtime (PHP_INI_ALL changable until PHP 4.2.3, since then PHP_INI_PERDIR); you can only remove them:
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
For further information see Disabling Magic Quotes.
Magic quotes cannot be disabled at runtime, but you can use a .htaccess file in the directory to disable it.
php_flag magic_quotes_gpc off
The only real advantage this has is you can put it once in a directory and it works for the whole directory and subdirectories. Really nice if you need this for an application you didn't write and need to get it to work without magic quotes.
I have a little script for this similar to Gumbo's (but of course I like mine better :):
if(function_exists('get_magic_quotes_runtime') && get_magic_quotes_runtime())
set_magic_quotes_runtime(false);
if(get_magic_quotes_gpc()) {
array_stripslashes($_POST);
array_stripslashes($_GET);
array_stripslashes($_COOKIES);
}
function array_stripslashes(&$array) {
if(is_array($array))
while(list($key) = each($array))
if(is_array($array[$key]))
array_stripslashes($array[$key]);
else
$array[$key] = stripslashes($array[$key]);
}
Another solution for PHP 5.3+:
if (get_magic_quotes_gpc() === 1)
{
$_GET = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_GET, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_POST = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_POST, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_COOKIE = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_COOKIE, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
$_REQUEST = json_decode(stripslashes(preg_replace('~\\\(?:0|a|b|f|n|r|t|v)~', '\\\$0', json_encode($_REQUEST, JSON_HEX_APOS | JSON_HEX_QUOT))), true);
}
Handles keys, values and multi-dimensional arrays.
It cannot be done at runtime :(
Related
If you are calling php page from web, you can give as
../../somepage.php?myid=1&trackno=2&anotherparam=3
and then you can use $_REQUEST or $_GET to retrieve the information
In command line, you can use
$options = getopt("a:b:c:"); to get the options that are passed through arguments
How to make sure, same source works either in web or in command line?
Let say your requests are like following;
WEB: http://domain.com/somepage.php?myid=1&trackno=2&anotherparam=3
CLI: php /path/to/this/php/file/somepage.php 1 2 3
You can use following php code;
<?php
if (!empty($_REQUEST)) {
$myid = $_REQUEST["myid"];
$trackno = $_REQUEST["trackno"];
$anotherparam = $_REQUEST["anotherparam"];
} else if (!empty($argv)) {
$myid = $argv[1];
$trackno = $argv[2];
$anotherparam = $argv[3];
} else {
die("Invalid request!");
}
You have already know how to handle web requests, you can refer here for more detail about $argv. Simply,
$argv[0] => scriptname(somepage.php),
$argv[1] => first param, ...,
$argv[n] => (n-1)th param
Edit:
In order to not miss order of commandline arguments, you can use naming conventions like;
php somepage.php myid_1 anotherparam_2 trackno_3
and you can use following to handle this;
foreach ($argv as $k => $v) {
if ($k == 0) continue;
$temp = explode("_", $v);
${$temp[0]} = $temp[1];
}
Simply,
myid_3 becomes $myid = 3;
variable names hidden in the values so you don't need to know about sequences
I've a html form which handle by Php. When I submit the form it's show a backslashes if i write for example: 5 rue de l'ourq. If a again submit the form because of I wrongly input any other field of the form then it's show 5 rue de l\'ourq and again 5 rue de l\\'ourq. This is happened in address filed.
Php Variable:
$address = $_POST['address'];
$title = inputvalid($_POST['title']);
$f_name = inputvalid($_POST['f_name']);
The problem is $address variable. I don't why it's show the backslashes. That's why I didn't put inputvalid function to that variable but can't fix this. Any idea ?
Sounds like you have magic_quotes turned on. You need to turn them off in you php settings.
If you can't turn off magic_quotes, I would make the first thing your inputvalid() function does is check to see if magic_quotes are enabled, if they are then stripslashes() on values.
http://php.net/manual/en/security.magicquotes.disabling.php
According to link above you can simulate disabling at runtime by adding the following code, but it is really just doing the same thing as I said above, checking if magic_quotes are on then stripslashes() on input arrays:
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
Put this in your config file:
ini_set('magic_quotes_gpc', 'off');
OR, if this is not allowed on your server, put this in config:
##/ Special Code to stop get_magic_quotes_gpc
function stop_magic_quotes($in)
{
$out = $in;
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
if(is_array($out))
{
foreach($out as $k=>$v)
{
$v = stop_magic_quotes($v);
$out[$k] = $v;
}
}
else
{
$out = stripslashes($out);
}
}
return $out;
}//end func................
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc())
{
$_GET = array_map('stop_magic_quotes', $_GET);
$_POST = array_map('stop_magic_quotes', $_POST);
}//end if....
PHP adds backslashes to escape the ' because it would literally mean the opening of a string.
Use stripslashes() to remove them.
Your inputvalid function is preventing SQL injections which are used to load and modify information from your database. The function escapes ' and " to prevent the injections. Your code should be able to translate those escaped characters back to a human-readable form after loading the information from the database.
From my comment to this question:
Check magic_quotes_gpc option in your php.ini file and set it to Off. Don't forget to restart the php process. If you don't have a direct access to the php.ini file, try this:
<?php ini_set('magic_quotes_gpc', 'Off'); ?>
Using tinymce for content, it works fine on local server but break formatting on remote server.
saving content:
mysql_real_escape_string( htmlentities($slide_name,ENT_QUOTES,'UTF-8'))
when retrieve:
html_entity_decode($slide_name, ENT_QUOTES,'UTF-8')
on local server it display content correctly:
<p><strong style="text-decoration: underline;">Contact:</strong> 0000-<span style="color: #ff0000;">245</span></p>
on remote (after 1st update):
<p><span style="\"><strong style="\">Contact:</strong></span> 0000-<span style="\">245</span></p>
use utf8_general_ci collation for both databases (remote/local)
After lot of searching and Toby Allen hint I found a solution.
Here was a problem:
magic_quotes_gpc were ON on remote server and magic_quotes_gpc were OFF on Local server.
As we can't control remote server up to php configuration level so we need to OFF magic_quotes_gpc run time.
Found a code snip from php.net
<?php
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
?>
if possible OFF magic_quotes_gpc using php.ini otherwise we can use function like above to switch OFF magic_quotes_gpc runtime.
I am posting this answer for future searchers.
I have a problem with CKEditor. When I try to add a link with it
foo
it always replaces " with \"
foo
This kind of notation seems like working when I print it on a page but if I e-mail it with a php script, gmail renders it like
<a>foo</a>
Can anyone have an idea about that?
Can I achieve this with config.js?
Note: This is not about the mailer php script because I have tested it without CKEditor.
UPDATE: I have disabled the magic quotes in my php script and working properly.
to avoid disabling magic_quotes for example for a shared server i have used (caus i had a problem in mailto link converted to \ )
stripslashes($text)
or as i have found in php.net manual example #2
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
I am needing to write portable code that will run on a shared server with magic_qoutes_gpc enabled and I am unable to change that in php.ini or .htaccess. (the server is running php 5.2)
It seems there are numerous functions to stripslaches from all of the $_GET, $_POST etc superglobals but I'm not sure which is the best. Also some comments here seem to say that the keys also have slashes added which need to be stripped as well. So should I use the one on the PHP website:
if (get_magic_quotes_gpc()) {
$process = array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST);
while (list($key, $val) = each($process)) {
foreach ($val as $k => $v) {
unset($process[$key][$k]);
if (is_array($v)) {
$process[$key][stripslashes($k)] = $v;
$process[] = &$process[$key][stripslashes($k)];
} else {
$process[$key][stripslashes($k)] = stripslashes($v);
}
}
}
unset($process);
}
or something like this: (from this answer: PHP - Shorter Magic Quotes Solution)
function strip_slashes_recursive(&$value) {
if (!is_array($value)) {
$value = strip_slashes($value);
} else {
foreach (array_keys($value) as $key) {
$arrayValue = strip_slashes_recursive($value[$key]);
unset($value[$key]);
$value[strip_slashes($key)] = $arrayValue;
}
}
}
foreach (array(&$_GET, &$_POST, &$_COOKIE, &$_REQUEST) as &$array) {
strip_slashes_recursive($array);
}
// don't forget to unset references or it can lead to very nasty bugs
unset($array);
or even something like this:
if (get_magic_quotes_gpc()) {
function undoMagicQuotes($array, $topLevel=true) {
$newArray = array();
foreach($array as $key => $value) {
if (!$topLevel) {
$key = stripslashes($key);
}
if (is_array($value)) {
$newArray[$key] = undoMagicQuotes($value, false);
}
else {
$newArray[$key] = stripslashes($value);
}
}
return $newArray;
}
$_GET = undoMagicQuotes($_GET);
$_POST = undoMagicQuotes($_POST);
$_COOKIE = undoMagicQuotes($_COOKIE);
$_REQUEST = undoMagicQuotes($_REQUEST);
}
Can someone explain the pros/cons of each approach and/or a totally different approach and how thorough they are and if they strip slashes from the key as well as the value.
(also is this method any good: PHP: how to (correctly) remove escaped quotes in arrays when Magic Quotes are ON)
(and also it seems like all of these methods are incomplete as they don't strip slashes from all the affected superglobals Which superglobals are affected by magic_quotes_gpc = 1?)
Here's another one mostly from PHP: how to (correctly) remove escaped quotes in arrays when Magic Quotes are ON but with my own changes:
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
function unMagicQuotify($array) {
$fixed = array();
foreach ($array as $key=>$val) {
if (is_array($val)) {
$fixed[stripslashes($key)] = unMagicQuotify($val);
} else {
$fixed[stripslashes($key)] = stripslashes($val);
}
}
return $fixed;
}
$_GET = unMagicQuotify($_GET);
$_POST = unMagicQuotify($_POST);
$_COOKIE = unMagicQuotify($_COOKIE);
$_REQUEST = unMagicQuotify($_REQUEST);
$_FILES = unMagicQuotify($_FILES);
}
Pro's
They work for both arrays and single variables
Does strip the key
Does not use references
Con's
May change the order of variables
Note the inclusion of $_FILES as magic quotes also affects it.
As for reading a file (file_get_contents) and/or using php://input I couldn't tell whether magic quotes affects them, but you would have to stripslashes() as and when you are reading them and would not be able to do something like this. I didn't manage to check $HTTP_RAW_POST_DATA but it isn't populated by default so things should be ok leaving it out.
You can get rid of slashes by performing this:
$_REQUEST = array_map('stripslashes', $_REQUEST);
I think it's easier and makes code smaller and more laconic.
I'm sure you know about what problems could appear while using the magic quotes directive (here is an article http://www.sitepoint.com/magic-quotes-headaches/). But IMO it's better for you to move your apps to another hosting provider in case that your current provider can't turn magic quotes off. Also, it's not very good idea to use an outdated version of PHP.
First Method
Pro's
They work for both arrays and single variables
Does strip the key
Con's
The code is too long for what it needs to be
Second Method
Pro's
They work for both arrays and single variables
Con's
The code is too long for what it needs to be
Does not strip the key
Third Method
Pro's
They work for both arrays and single variables
Does strip the key
Con's
The code is too long for what it needs to be
I've been using this, which works ok (Found it in osTicket, I love open source):
function strip_slashes($var){
return is_array($var)?array_map('strip_slashes',$var):stripslashes($var);
}
if(function_exists('get_magic_quotes_gpc') && get_magic_quotes_gpc()) {
$_POST = strip_slashes($_POST);
$_GET = strip_slashes($_GET);
$_REQUEST = strip_slashes($_REQUEST);
$_COOKIE = strip_slashes($_COOKIE);
}
Pro's
They work for both arrays and single variables
Con's
Does not strip the keys
I've never come across the need to strip the keys as well though. Many open source libraries don't do it (e.g Wordpress, osTicket). Generally I only use name for $_POST and $_GET data that will never be escaped.