I am trying to pass a string from PHP into a Perl script, uppercase each word, and then pass the uppercase string back to PHP where I echo it out. I know I can do that in PHP, but there are other reasons why I will need to pass the string between PHP and Perl.
If the variable $user_input is "first second third" I want the echo statement in the PHP program to echo "FIRST SECOND THIRD", but right now it is only echoing "FIRST".
How do I get my Perl script to read in and uppercase each word, not just the first one? (The variable user_input is not necessarily fixed at a length of three words, it could be more or fewer.)
Here is the relevant PHP:
$result = shell_exec('/usr/bin/perl /var/www/my_site/myperl.pl ' . $user_input);
$user_input = $result;
echo $user_input;
And this is my Perl program (myperl.pl):
#!/usr/bin/perl
use warnings;
my $var1 = shift;
foreach $var ($var1){
print uc $var ;
}
I've tried changing several things in the Perl code (using @var1 for example) but can't seem to get it to work. Thanks in advance for any help you can provide.
CodePudding user response:
Do not use shell_exec()
with unescaped input. This function is really easy to use in an unsafe manner, and can lead to command injection security vulnerabilities. Here, you have run into issues around your lack of escaping. Slightly simplifying things, you are trying to execute the following command:
# shell_exec('/usr/bin/perl /var/www/my_site/myperl.pl ' . $user_input)
/usr/bin/perl /var/www/my_site/myperl.pl first second third
Since the variable contents are just pasted into the command line, it is split at spaces and passed to the command as separate arguments.
The safest approach is to bypass shell expansion and executing the intended program directly. Unfortunately, core PHP does not provide convenient functions for this task.
If you want to continue using the convenient shell_exec()
function, you MUST escape the variable before constructing the shell command. For example:
shell_exec('/usr/bin/perl /var/www/my_site/myperl.pl ' . escapeshellarg($user_input))
This would lead to the following shell command being executed (note the single quotes around the argument):
/usr/bin/perl /var/www/my_site/myperl.pl 'first second third'
After that, your Perl code should work as expected.
CodePudding user response:
Arguments passed to a Perl program are available in the builtin global @ARGV array.
The shift function takes an array name as an argument, and removes and returns its first element. If used without an argument then it operates on @ARGV
, or if in a subroutine on @_
array which holds arguments passed to the subroutine.
So the code you show takes the first argument passed to the program and works with it.† Then, the shown foreach
loop goes over just that one scalar (single-valued) variable.
Instead, you want to extract or copy the whole @ARGV
and then to iterate over that array
use warnings;
use strict;
use feature qw(say);
my @args = @ARGV;
foreach my $arg (@args) {
say uc $arg; # with a new line
# print uc $arg; # no newline, all come out "stuck" together
}
Now you can process those (instead of just uc
-ing them), what I presume is intended.
If you indeed wanted to only put out upper-cased input
print uc for @ARGV;
suffices. (The uc
takes $_
by default.)
† If the PHP program passes one string to the Perl program, not expanded (broken into) words by a shell or some such, then your Perl code should work as it stands. But the code shown here works in that case as well, and it will always process all arguments.
CodePudding user response:
I made changes to my Perl program that zdim suggested, and made changes to my PHP code that amon suggested. Together, they fixed the problem. I can't officially accept both answers on here, but they were both helpful. Thank you to both of you.