Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/php
- <?php
- /*
- rmate.php by Michael Newton <http://mike.eire.ca/>
- Based on rmate Ruby script included with TextMate 2.0
- TextMate is © MacroMates Ltd., 2011
- */
- //hide errors that will pop up if the file is missing
- $err = error_reporting(E_ALL & ~E_WARNING);
- if (!(include 'Console/CommandLine.php')) {
- msg('This program requires the PEAR package Console_CommandLine to be installed!');
- exit(1);
- }
- error_reporting($err);
- define('DEFAULT_HOST', 'localhost');
- define('DEFAULT_PORT', 52698);
- class Settings {
- function __construct() {
- self::read_disk_settings();
- self::parse_cli_options();
- }
- function read_disk_settings() {
- }
- function parse_cli_options() {
- $options = array('description'=>'Uses an SSH tunnel to open the specified file in a remote instance of TextMate.', 'version'=>'1.3php (2011-10-18)');
- $parser = new Console_CommandLine($options);
- $parser->addOption('host', array(
- 'long_name' => '--host',
- 'description' => 'Connect to host. Use "auto" to detect the host from SSH. Defaults to "' . DEFAULT_HOST . '" if not specified, or use the RMATE_HOST environment variable.',
- 'action' => 'StoreString',
- 'default' => getenv('RMATE_HOST') ? getenv('RMATE_HOST') : DEFAULT_HOST,
- 'help_name' => 'name',
- ));
- $parser->addOption('port', array(
- 'short_name' => '-p',
- 'long_name' => '--port',
- 'description' => 'Port number to use for connection. Defaults to ' . DEFAULT_PORT . ' if not specified, or use the RMATE_PORT environment variable.',
- 'action' => 'StoreInt',
- 'default' => getenv('RMATE_PORT') ? (int)getenv('RMATE_PORT') : DEFAULT_PORT,
- 'help_name' => '#',
- ));
- $parser->addOption('wait', array(
- 'short_name' => '-w',
- 'long_name' => '--wait',
- 'description' => 'Wait for file to be closed by TextMate.',
- 'action' => 'StoreTrue',
- 'default' => false,
- ));
- $parser->addOption('force', array(
- 'short_name' => '-f',
- 'long_name' => '--force',
- 'description' => 'Open even if the file is not writable.',
- 'action' => 'StoreTrue',
- 'default' => false,
- ));
- $parser->addOption('verbose', array(
- 'short_name' => '-v',
- 'long_name' => '--verbose',
- 'description' => 'Verbose logging messages. Use twice for even more verbosity.',
- 'action' => 'Counter',
- ));
- $parser->addArgument('file', array(
- 'description' => 'The file to open',
- ));
- try {
- $result = $parser->parse();
- $this->host = $result->options['host'];
- if ($this->host === 'auto' && getenv('SSH_CONNECTION')) {
- list($this->host,) = explode(' ', getenv('SSH_CONNECTION'), 2);
- }
- $this->port = $result->options['port'];
- $this->wait = $result->options['wait'];
- $this->force = $result->options['force'];
- $this->verbose = $result->options['verbose'];
- $this->files = is_array($result->args) ? $result->args : array($result->args);
- }
- catch (Exception $exc) {
- $parser->displayError($exc->getMessage());
- }
- }
- }
- class Command {
- public $command = '';
- public $variables = array();
- public $data = null;
- public $size = null;
- function __construct($name) {
- $this->command = $name;
- }
- function set($key, $value) {
- $this->variables[$key] = $value;
- }
- function get($key = null) {
- return $key === null ? $this->variables : $this->variables[$key];
- }
- function read_file($path) {
- $this->size = filesize($path);
- $this->data = file_get_contents($path);
- }
- function send($socket) {
- global $settings;
- fwrite($socket, "$this->command\n");
- foreach($this->variables as $k=>$v) {
- if ($v === true) $v = 'yes';
- msg("Sending $k: $v", 2);
- fwrite($socket, "$k: $v\n");
- }
- if ($this->data) {
- msg("Sending $this->size bytes of data", 2);
- fwrite($socket, "data: $this->size\n");
- fwrite($socket, "$this->data\n");
- }
- }
- }
- function msg($message, $verbose = 0) {
- global $settings;
- if ($verbose === 0 || ($verbose > 0 && $verbose <= $settings->verbose)) {
- fwrite(STDERR, trim($message) . "\n");
- }
- }
- function handle_save($socket, $variables, $data) {
- global $settings;
- $path = $variables['token'];
- msg("Saving $path", 1);
- if ($result = file_exists($path)) {
- copy($path, "$path~");
- if ($result = file_put_contents($path, $data)) {
- unlink("$path~");
- }
- }
- if ($result === false) {
- msg("Save failed! Backup in $path~");
- }
- }
- function handle_close($socket, $variables, $data) {
- global $settings;
- $path = $variables['token'];
- msg("Closed $path", 1);
- }
- function handle_cmd($socket) {
- global $settings;
- $cmd = trim(fgets($socket));
- msg("Command: $cmd", 2);
- $variables = array();
- $data = '';
- while (($line = fgets($socket)) !== false) {
- $line = trim($line);
- if (empty($line)) {
- break;
- }
- list($name, $value) = explode(': ', $line);
- if ($name === 'data') {
- $data .= fread($socket, $value);
- }
- else {
- msg("Received $name: $value", 2);
- $variables[$name] = $value;
- }
- }
- if ($cmd === 'save') {
- handle_save($socket, $variables, $data);
- }
- elseif ($cmd === 'close') {
- handle_close($socket, $variables, $data);
- }
- else {
- msg("Received unknown command $cmd, exiting");
- exit(1);
- }
- }
- function connect_and_handle_commands($host, $port, $commands) {
- global $settings;
- $stream = stream_socket_client("$settings->host:$settings->port");
- if ($stream === false) {
- msg("Unable to connect to $settings->host on port $settings->port, exiting");
- exit(1);
- }
- $server_info = trim(fgets($stream));
- msg("Connect: '$server_info'", 1);
- foreach($commands as $cmd) {
- $cmd->send($stream);
- }
- fwrite($stream, ".\n");
- while (!feof($stream)) {
- handle_cmd($stream);
- }
- fclose($stream);
- msg("Done", 1);
- }
- $settings = new Settings;
- $cmds = array();
- foreach($settings->files as $file) {
- if (!is_writable($file) || !file_exists($file)) {
- $err = file_exists($file) ? 'is not writable' : 'does not exist';
- if (!$settings->force) {
- msg("File $file $err, use --force to open anyway.");
- die(1);
- }
- else {
- msg("File $file $err. Opening anyway.");
- }
- }
- $cmd = new Command('open');
- $cmd->set('display-name', php_uname('n') . ':' . $file);
- $cmd->set('real-path', realpath($file));
- $cmd->set('data-on-save', true);
- $cmd->set('re-activate', true);
- $cmd->set('token', $file);
- if (file_exists($file)) {
- $cmd->read_file($file);
- }
- else {
- $cmd->set('data', 0);
- }
- $cmds[] = $cmd;
- }
- if (!$settings->wait && function_exists('pcntl_fork')) {
- $pid = pcntl_fork();
- if ($pid > 0) {
- //we are the parent
- exit(0);
- }
- elseif ($pid === -1) {
- //we are still the parent, there is no child
- msg("Error while forking, use --wait to prevent forking.");
- exit(1);
- }
- elseif ($pid === 0) {
- //we are the child
- connect_and_handle_commands($settings->host, $settings->port, $cmds);
- }
- }
- else {
- if (!$settings->wait && !function_exists('pcntl_fork')) {
- msg("Unable to fork, ensure that pcntl_* functions are enabled.");
- }
- connect_and_handle_commands($settings->host, $settings->port, $cmds);
- }
- ?>
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement