diff --git a/index.php b/index.php new file mode 100644 index 0000000..11c754f --- /dev/null +++ b/index.php @@ -0,0 +1,78 @@ + $value) { + $headers[] = $key . ": " . $value; + } + + curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $_SERVER["REQUEST_METHOD"]); + + if($_SERVER["REQUEST_METHOD"] === "POST") { + + curl_setopt($curl, CURLOPT_POST, 1); + curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($_POST)); + + } + + $resp = curl_exec($curl); + + if($resp === false) { + + header('HTTP/1.0 404 Not Found'); + exit; + + } else { + + list($head, $body) = explode("\r\n\r\n", $resp, 2); + $headarr = explode("\n", $head); + foreach($headarr as $headval) { + header($headval); + } + echo $body; + + } + + curl_close($curl); +} + +function node_dispatch() { + isset($_GET['path']) ? node_serve($_GET['path']) : node_serve(); +} + +node_dispatch(); diff --git a/node.php b/node.php index b725b9f..e43dfef 100644 --- a/node.php +++ b/node.php @@ -1,36 +1,111 @@ $value) + { + if (substr($name, 0, 5) == 'HTTP_') + { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} -define("NODE_PORT", 49999); +function recurse_copy($src, $dst) +{ + if ( ! is_dir($src) ) + return false; + $dir = opendir($src); + @mkdir($dst); + while(false !== ( $file = readdir($dir)) ) { + if (( $file != '.' ) && ( $file != '..' )) { + if ( is_dir($src . _DS . $file) ) { + recurse_copy($src._DS.$file, $dst._DS.$file); + } + else { + copy($src._DS.$file, $dst._DS.$file); + } + } + } + closedir($dir); + return true; +} -function node_install() { +function recurse_delete($directory, $options = array()) +{ + if(!isset($options['traverseSymlinks'])) + $options['traverseSymlinks'] = false; + $files = array_diff(scandir($directory), array('.', '..')); + foreach ($files as $file) + { + $dirfile = $directory._DS.$file; + if (is_dir($dirfile)) + { + if(!$options['traverseSymlinks'] && is_link(rtrim($file, _DS))) { + unlink($dirfile); + } else { + recurse_delete($dirfile, $options); + } + } else { + unlink($dirfile); + } + } + return rmdir($directory); +} + +function node_install() +{ if(file_exists(NODE_DIR)) { - echo "Node.js is already installed.\n"; + echo "Node.js is already installed.
\n"; return; } if(!file_exists(NODE_FILE)) { - echo "Downloading Node.js from " . NODE_URL . ":\n\n"; + echo "Downloading Node.js from " . NODE_URL . ":
\n\n"; $fp = fopen(NODE_FILE, "w"); flock($fp, LOCK_EX); $curl = curl_init(NODE_URL); @@ -40,27 +115,50 @@ function node_install() { curl_close($curl); flock($fp, LOCK_UN); fclose($fp); - echo $resp === true ? "Done.\n" : "Failed. Error: curl_error($curl)\n"; + echo $resp === true ? "Done.
\n" : "Failed. Error: curl_error($curl)
\n"; + } + echo "\n
Installing Node.js:
\n"; + if (NODE_OS == '-win-') + { + $zip = new ZipArchive; + $ret = $zip->open(NODE_FILE); + if ($ret === TRUE) { + $zip->extractTo('.'); + $zip->close(); + } + } else { + // decompress from gz + $p = new PharData(NODE_FILE); + $p->decompress(); // creates *.tar + + // unarchive from the tar + $archive = new PharData(str_replace(NODE_FILE, 'node-v10.tar', NODE_FILE)); + $archive->extractTo('.'); + unlink('node-v10.tar'); + + //passthru("tar -xzf " . NODE_FILE . " 2>&1 && mv " . NODE_FOLDER . " " . NODE_DIR . " && touch nodepid && rm -f " . NODE_FILE, $ret); } - echo "Installing Node.js:\n"; - passthru("tar -xzf " . NODE_FILE . " 2>&1 && mv node-" . NODE_VER . "-linux-" . NODE_ARCH . " " . NODE_DIR . " && touch nodepid && rm -f " . NODE_FILE, $ret); - echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\nTry putting node folder via (S)FTP, so that " . __DIR__ . "/node/bin/node exists."; + if (recurse_copy(NODE_FOLDER, NODE_DIR)) + $ret = touch('nodepid'); + recurse_delete(NODE_FOLDER); + echo (!$ret) ? "Done.\n" : "Failed. Error: $ret\nTry putting node folder via (S)FTP, so that " . __DIR__ . "/node/bin/node exists."; } -function node_uninstall() { +function node_uninstall() +{ if(!file_exists(NODE_DIR)) { echo "Node.js is not yet installed.\n"; return; } echo "Unnstalling Node.js:\n"; - passthru("rm -rfv " . NODE_DIR . " nodepid", $ret); - passthru("rm -rfv node_modules", $ret); - passthru("rm -rfv .npm", $ret); - passthru("rm -rfv nodeout", $ret); - echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\n"; + + $ret = recurse_delete(NODE_DIR); + unlink('nodepid'); + echo ($ret) ? "Done.\n" : "Failed. Error: $ret\n"; } -function node_start($file) { +function node_start($file) +{ if(!file_exists(NODE_DIR)) { echo "Node.js is not yet installed. Install it.\n"; return; @@ -72,14 +170,69 @@ function node_start($file) { } $file = escapeshellarg($file); echo "Starting: node $file\n"; - $node_pid = exec("PORT=" . NODE_PORT . " " . NODE_DIR . "/bin/node $file >nodeout 2>&1 & echo $!"); + + $node_pid = run($file, NODE_DIR, ['PORT' => NODE_PORT]); echo $node_pid > 0 ? "Done. PID=$node_pid\n" : "Failed.\n"; - file_put_contents("nodepid", $node_pid, LOCK_EX); + + file_put_contents("nodepid", $node_pid, LOCK_EX); + if ($node_pid>0) { + file_put_contents('nodestart', $file, LOCK_EX); + } sleep(1); //Wait for node to spin up - echo file_get_contents("nodeout"); } -function node_stop() { +function kill($pid) +{ + return (NODE_OS == '-win-') ? exec("taskkill /F /T /PID $pid") : exec("kill -9 $pid"); +} + +function run($cmd, $startDir = null, $env = array()) +{ + if(NODE_OS == '-win-') { + $descriptorspec = array ( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + ); + + //proc_open — Execute a command + //'start /b' runs command in the background + if ( is_resource( $prog = proc_open('start /b node '.$cmd, $descriptorspec, $pipes, $startDir, $env) ) ) { + //Get Parent process Id + $ppid = proc_get_status($prog); + $pid = $ppid['pid']; + } else { + echo("Failed to execute!"); + exit(); + } + + $output = array_filter(explode(" ", shell_exec("wmic process get parentprocessid,processid | find \"$pid\""))); + array_pop($output); + + $pid = end($output); + } else { + $descriptorspec = array ( + 0 => array("pipe", "r"), + 1 => array("pipe", "w"), + ); + + //proc_open — Execute a command + //'nohup' command line-utility will allow you to run command/process or shell script that can continue running in the background + if (is_resource($prog = proc_open('nohup bin'._DS.'node '.$cmd, $descriptorspec, $pipes, $startDir, $env) ) ) { + //Get Parent process Id + $ppid = proc_get_status($prog); + $pid = $ppid['pid']; + + $pid = $pid + 1; + } else { + echo("Failed to execute!"); + exit(); + } + } + return $pid; +} + +function node_stop() +{ if(!file_exists(NODE_DIR)) { echo "Node.js is not yet installed. Install it.\n"; return; @@ -91,12 +244,13 @@ function node_stop() { } echo "Stopping Node.js with PID=$node_pid:\n"; $ret = -1; - passthru("kill $node_pid", $ret); + $ret = kill($node_pid); echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret\n"; file_put_contents("nodepid", '', LOCK_EX); } -function node_npm($cmd) { +function node_npm($cmd) +{ if(!file_exists(NODE_DIR)) { echo "Node.js is not yet installed. Install it.\n"; return; @@ -108,13 +262,26 @@ function node_npm($cmd) { echo $ret === 0 ? "Done.\n" : "Failed. Error: $ret. See npm-debug.log\n"; } -function node_serve($path = "") { - if(!file_exists(NODE_DIR)) { +function node_serve($path = "") +{ + if (!file_exists(NODE_DIR)) { node_head(); echo "Node.js is not yet installed. Switch to Admin Mode and Install it.\n"; node_foot(); return; + } elseif ($RESTART_PROCESS && $node_pid && !posix_getpgid($node_pid)) { + $nodestart = file_get_contents('nodestart'); + if($nodestart){ + node_start($nodestart); + //wait for node process to start, then retry to node_serve + sleep(5); + node_serve($path); + return; + } + echo "Please switch to Admin Mode and manually restart the server. Start it\n"; + return; } + $node_pid = intval(file_get_contents("nodepid")); if($node_pid === 0) { node_head(); @@ -122,7 +289,11 @@ function node_serve($path = "") { node_foot(); return; } - $curl = curl_init("http://127.0.0.1:" . NODE_PORT . "/$path"); + $url = "http://127.0.0.1:" . NODE_PORT . "/$path"; + //header('HTTP/1.1 307 Temporary Redirect'); + //header("Location: $url"); + + $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 1); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); $headers = array(); @@ -132,9 +303,25 @@ function node_serve($path = "") { curl_setopt($curl, CURLOPT_HTTPHEADER, $headers); curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $_SERVER["REQUEST_METHOD"]); if($_SERVER["REQUEST_METHOD"] === "POST") { - curl_setopt($curl, CURLOPT_POST, 1); - curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($_POST)); - } + curl_setopt($curl, CURLOPT_POST, 1); + if (count($_POST)==0) { //strlen($str_json_params) > 0) && isValidJSON($json_params)) { + $str_json_params = file_get_contents('php://input'); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + curl_setopt($curl, CURLOPT_POSTFIELDS, $str_json_params); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + }else{ + //$str_header = implode(",", $headers); + $fields = http_build_query($_POST); + curl_setopt($curl, CURLOPT_POSTFIELDS, $fields); + //error_log("post json=$str_json_params "); + } + } else if($_SERVER["REQUEST_METHOD"] === "PUT" || $_SERVER["REQUEST_METHOD"] === "DELETE"){ + curl_setopt($curl, CURLOPT_CUSTOMREQUEST, $_SERVER["REQUEST_METHOD"]); + curl_setopt($curl, CURLOPT_POSTFIELDS, file_get_contents('php://input')); + curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: application/json')); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); + } + //error_log("url=$url"); $resp = curl_exec($curl); if($resp === false) { node_head(); @@ -151,37 +338,51 @@ function node_serve($path = "") { curl_close($curl); } -function node_head() { +function node_head() +{ echo 'Node.php

Node.php

';
 }
 
-function node_foot() {
+function node_foot() 
+{
 	echo '

Powered by node.php

'; } -function node_dispatch() { - if(ADMIN_MODE) { +function node_dispatch() +{ + $checkScript = (realpath($_SERVER['argv'][0]) == __FILE__); + $checkArgs = isset($_SERVER['argv'][1]); + $checkAdmin = ($checkScript && $checkArgs) && ($_SERVER['argv'][1] == '--admin'); + $getCommand = (($checkScript && $checkArgs) && !$checkAdmin) ? $_SERVER['argv'][1] : (($checkAdmin) ? $_SERVER['argv'][2] : ''); + if(ADMIN_MODE || $checkAdmin) { node_head(); - if(isset($_GET['install'])) { + if (isset($_GET['install']) || ($getCommand == 'install')){ node_install(); - } elseif(isset($_GET['uninstall'])) { + } elseif (isset($_GET['uninstall']) || ($getCommand == 'uninstall')) { node_uninstall(); - } elseif(isset($_GET['start'])) { + } elseif (isset($_GET['start']) || ($getCommand == 'start')) { node_start($_GET['start']); - } elseif(isset($_GET['stop'])) { + } elseif (isset($_GET['stop']) || ($getCommand == 'stop')) { node_stop(); - } elseif(isset($_GET['npm'])) { - node_npm($_GET['npm']); + } elseif (isset($_GET['npm']) || ($getCommand == 'npm')) { + if (empty($getCommand)) + node_npm($_GET['npm']); + else { + $getCommand = $_SERVER['argv']; + unset($getCommand[0]); + unset($getCommand[1]); + node_npm($getCommand); + } } else { echo "You are in Admin Mode. Switch back to normal mode to serve your node app."; } node_foot(); - } else { - if(isset($_GET['path'])) { - node_serve($_GET['path']); - } else { - node_serve(); - } + } elseif (isset($_SERVER['REQUEST_URI'])) { + $full_url = $_SERVER['REQUEST_URI']; + $path = explode("?path=",$full_url); + node_serve($path[1]); + } elseif (isset($getCommand)) { + node_serve($getCommand); } }