0

I'm trying to compile a Sass (.scss) file's contents using shell_exec or exec, not proc_open. Don't ask me why I don't just pass the file itself or use proc_open, the goal here is to pass the contents via stdin, piped with echo.

I think there are some characters in the string that break the command but I can't figure out which. I'm on Ubuntu 14.04, running PHP 5.6 and in this case CLI.

You can run this to see for yourself (will need Ruby and Sass installed):

sudo apt-get install Ruby && sudo gem install sass

<?php

/** Should work with '$large = true' and '$download = false' **/

// to prove that a small file DOES compile via stdin
$large = true;

// to prove that it's compilable as a file, rather than stdin
$download = false;

$domain = "http://test.fhmp.net";
$file = $large ? 'large' : 'small';

// grab a valid .scss file
$input = file_get_contents("$domain/$file.scss");

if($download){

    // create temp file
    $temp = tempnam(sys_get_temp_dir(), '');
    file_put_contents($temp, $input);

    // compile temp file
    var_dump(shell_exec("sass --scss '$temp' 2>&1"));

    // delete temp file
    @unlink($temp);

} else {

    // attempt to escape it
    $esc = escapeshellarg($input);

    // dump the results of the shell call
    var_dump(shell_exec("echo $esc | sass --scss --stdin 2>&1"));
}
rtheunissen
  • 7,347
  • 5
  • 34
  • 65
  • 1
    You should really post the error here, and where it's happening. – Brad Sep 20 '14 at 02:45
  • Sorry for the potentially dumb comment but for a ternary, don't you need a comparison operator for what you are trying to do here? --> $file = $large ? 'large' : 'small'; //Should be $file === $large ? 'large' : 'small'; //right? – The One and Only ChemistryBlob Sep 20 '14 at 02:47
  • @TheOneandOnlyChemistryBlob, I'm actually assigning a string to `$file`, which will be either 'large' or 'small' depending on the truthness of `$large` – rtheunissen Sep 20 '14 at 02:48
  • @Brad Okay will do. When `$large` is true and `$download` is false, it'll try to pipe the string as input for the sass compiler, but `shell_exec` returns NULL. – rtheunissen Sep 20 '14 at 02:53
  • Look at `escapeshellarg()`. It may proove helpful. – Cobra_Fast Sep 20 '14 at 02:55
  • @Cobra_Fast I'm aware of it, and it's part of my question. – rtheunissen Sep 20 '14 at 02:56
  • I'm surprised nobody's mentioned that there's at least one very decent implementation of SCSS written in PHP rather than Ruby, which would remove the need for this whole process: http://leafo.net/scssphp/ – IMSoP Nov 02 '14 at 23:20
  • @IMSoP see that an just an example, rather than a concrete use case. What if I wanted to use Myth or Stylus or Coffeescript the same way? The question was asked to learn about escaping shell arguments, rather than 'how can I compile .sass using shell_exec'. – rtheunissen Nov 03 '14 at 01:14
  • @paranoid-android Fair enough. It wasn't meant as a criticism of the question, I just thought you might find it a useful alternative. – IMSoP Nov 04 '14 at 23:37
  • @IMSoP Thanks for suggesting it. I'm sure someone else might find it useful in the future. – rtheunissen Nov 04 '14 at 23:40

2 Answers2

0

You should try :

$esc = '$'.escapeshellarg($input);

the escapeshellarg() function escapes single quotes with a backslash which means that: escapeshellarg("//where's the quote") become 'where\'s the quote'. You can not echo single quotes inside single quotes in the (bash) shell, see: How to escape a single quote in single quote string in Bash?

Community
  • 1
  • 1
Bass Jobsen
  • 48,736
  • 16
  • 143
  • 224
0

I think the problem here was that the command was too long when I'm interpolating the entire input string. The solution is to use proc_open or popen to write to standard input rather than pipe using |.

rtheunissen
  • 7,347
  • 5
  • 34
  • 65