Use screencapture with PHP exec

PHPscreen capture

I can't get screencapture to work work when triggered with exec() command.

$output = exec("/usr/sbin/screencapture -R 0,0,450,150 hehe.png"." 2>&1");
echo $output; //  in /System/Library/Frameworks/ImageIO.framework/Versions/A/ImageIO

I am not sure what the $output message is trying to convey.

php.ini disable_functions is empty.

I have a feeling that this is a osx problem. Can you point me in the right direction regarding solving this problem?

from man screencapture

SECURITY CONSIDERATIONS
     To capture screen content while logged in via ssh, you must launch
     screencapture in the same mach bootstrap hierarchy as loginwindow:

     PID=pid of loginwindow
     sudo launchctl bsexec $PID screencapture

I'm not using any ssh. PID of which process should be used in this case?

exec("sudo launchctl bsexec $PID screencapture -R 0,0,450,150 hehe.png");

Best Answer

All credit goes to patrix.

The problem stems from OSX preventing php script from executing screencapture command. OSX has no problem if you run your script manually, but if it is triggered as a response to a GET or POST request, than it raises the red flag.

To solve this 3 steps are needed:

  1. Add permission to the user that is running httpd (and php) to execute sudo launchctl without password. In my case it is daemon. I got it from Activity Monitor. Edit /etc/sudoers with

    daemon ALL=(ALL) NOPASSWD: /bin/launchctl
    
  2. get the PID of loginWindow. you can use ActivityMonitor for that. PID is subjected to changes so to bullet proof yourself use:

    pgrep loginwindow
    
  3. update your screencapture command:

    sudo launchctl bsexec PIDNUMBERHERE screencapture [options] path/image.png
    

It might be worth mentioning that step 1 adds a slight security risk and probably shouldn't be used in an internet-facing environment (especially with a PHP solution where everybody can easily read the source code).