Reputation: 32296
echo "sed -i 's/NULL/\\N/g' ".$_REQUEST['para'].".sql";
The above statement works. But it fail when I use it in exec like this...
exec("sed -i 's/NULL//\/\/\N/g' ".$_REQUEST['para'].".sql");
Upvotes: 1
Views: 5900
Reputation: 39376
Building on ghostdog's idea, here's code that will actually do what you want (the original code he posted didn't actually read content of the file in):
//basename protects against directory traversal
//ideally we should also do a is_writable() check
$file = basename($_REQUEST['para'].".sql");
$text = file_get_contents($file);
$text = str_replace('NULL', '\\N', $text); //no need for a regex
file_put_contents($file, $text);
Admittedly, however, if the file in question is more than a few meg, this is inadvisable as the whole file will be read into memory. You could read it in chunks, but that'd get a bit more complicated:
$file = basename($_REQUEST['para'].".sql");
$tmpFile = tempnam("/tmp", "FOO");
$in = fopen($file, 'r');
$tmp = fopen($tmpFile, 'w');
while($line = fgets($in)) {
$line = str_replace('NULL', '\\N', $line);
fputs($tmp, $line);
}
fclose($tmp);
fclose($in);
rename($tmpFile, $file);
If the file is 100+ meg, honestly, calling sed directly like you are will be faster. When it comes to large files, the overhead of trying to reproduce a tool like sed/grep with its PHP equivalent just isn't worth it. However, you need to at least take some steps to protect yourself if you're going to do so:
Taking some basic steps to secure amnom's code:
$file = basename($_REQUEST['para'].".sql");
if(!is_writable($file))
throw new Exception('bad filename');
exec("sed -i 's/NULL/\\\\N/g' ".escapeshellarg($file));
/etc/passwd; rm -rf /; #
, you'd end up with the command sed 's/blah/blah/' /etc/passwd; rm -rf /; #.sql
. It should be clear that while that exact command may not work, finding one that actually would is trivial.Upvotes: 1
Reputation: 342849
Although it's entirely up to you, but my advice is not to call system commands unnecessarily. In PHP, you can use preg_replace() to do the functionality of sed.
preg_replace("/NULL/","\\N",file_get_contents("$_REQUEST['para']"."sql") )
Upvotes: 3
Reputation: 7772
You should escape backslashes with backslashes, not with forward slashes, like this:
exec("sed -i 's/NULL/\\\\N/g' ".$_REQUEST['para'].".sql");
EDIT I wrote the answer without looking at what the code actually does. Don't do this, because $_REQUEST['para']
can be whatever the user wants, which can be used for code injection. Use the PHP functions as the other answer suggests.
Upvotes: 5