Erebot  latest
A modular IRC bot for PHP 7.0+
Prompt.php
1 <?php
2 /*
3  This file is part of Erebot, a modular IRC bot written in PHP.
4 
5  Copyright © 2010 François Poirotte
6 
7  Erebot is free software: you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation, either version 3 of the License, or
10  (at your option) any later version.
11 
12  Erebot is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with Erebot. If not, see <http://www.gnu.org/licenses/>.
19 */
20 
21 namespace Erebot;
22 
45 class Prompt implements \Erebot\Interfaces\ReceivingConnection
46 {
48  protected $bot;
49 
51  protected $socket;
52 
54  protected $io;
55 
99  public function __construct(
100  \Erebot\Interfaces\Core $bot,
101  $connector = null,
102  $group = null,
103  $perms = 0660
104  ) {
105  $this->bot = $bot;
106 
107  if ($connector === null) {
108  $connector = sys_get_temp_dir() .
109  DIRECTORY_SEPARATOR .
110  'Erebot.sock';
111  }
112  $this->socket = stream_socket_server(
113  "udg://".$connector,
114  $errno,
115  $errstr,
116  STREAM_SERVER_BIND
117  );
118  if (!$this->socket) {
119  throw new \Exception("Could not create prompt (".$errstr.")");
120  }
121 
122  // Cleanup on shutdown.
123  register_shutdown_function(
124  function ($socket) {
125  @unlink($socket);
126  },
127  $connector
128  );
129 
130  // Change group.
131  if ($group !== null) {
132  if (!@chgrp($connector, $group)) {
133  throw new \Exception(
134  "Could not change group to '$group' for '$connector'"
135  );
136  }
137  }
138 
139  // Change permissions.
140  if (!chmod($connector, $perms)) {
141  throw new \Exception(
142  "Could not set permissions to $perms on '$connector'"
143  );
144  }
145 
146  // Flush any received data on the socket, because
147  // any data sent before the group and permissions
148  // were set may have come from an untrusted source.
149  $flush = array($this->socket);
150  $dummy = null;
151  while (stream_select($flush, $dummy, $dummy, 0) == 1) {
152  if (fread($this->socket, 8192) === false) {
153  throw new \Exception("Error while flushing the socket");
154  }
155  }
156 
157  $this->io = new \Erebot\LineIO(\Erebot\LineIO::EOL_ANY, $this->socket);
158  $logger = \Plop\Plop::getInstance();
159  $logger->info(
160  $bot->gettext('Prompt started in "%(path)s"'),
161  array('path' => $connector)
162  );
163  }
164 
166  public function __destruct()
167  {
168  $this->disconnect();
169  }
170 
171  public function connect()
172  {
173  $this->bot->addConnection($this);
174  }
175 
176  public function disconnect($quitMessage = null)
177  {
178  $this->bot->removeConnection($this);
179  if ($this->socket !== null) {
180  stream_socket_shutdown($this->socket, STREAM_SHUT_RDWR);
181  }
182  $this->socket = null;
183  }
184 
185  public function isConnected()
186  {
187  return true;
188  }
189 
190  public function getSocket()
191  {
192  return $this->socket;
193  }
194 
195  public function getIO()
196  {
197  return $this->io;
198  }
199 
200  public function read()
201  {
202  $res = $this->io->read();
203  if ($res === false) {
204  throw new \Erebot\ConnectionFailureException('Disconnected');
205  }
206  return $res;
207  }
208 
210  public function process()
211  {
212  for ($i = $this->io->inReadQueue(); $i > 0; $i--) {
213  $this->handleMessage($this->io->pop());
214  }
215  }
216 
224  protected function handleMessage($line)
225  {
226  $pos = strpos($line, ' ');
227  if ($pos === false) {
228  return;
229  }
230 
231  $pattern = preg_quote(substr($line, 0, $pos), '@');
232  $pattern = strtr($pattern, array('\\?' => '.?', '\\*' => '.*'));
233  $line = substr($line, $pos + 1);
234  if ($line === false) {
235  return;
236  }
237 
238  foreach ($this->bot->getConnections() as $connection) {
239  if (!($connection instanceof \Erebot\Interfaces\SendingConnection) || $connection == $this) {
240  continue;
241  }
242 
243  $config = $connection->getConfig(null);
244  $netConfig = $config->getNetworkCfg();
245  if (preg_match('@^'.$pattern.'$@Di', $netConfig->getName())) {
246  $connection->getIO()->push($line);
247  }
248  }
249  }
250 
251  public function getBot()
252  {
253  return $this->bot;
254  }
255 
256  public function getConfig($chan)
257  {
258  return null;
259  }
260 }
A simple prompt which can be used to send commands remotely.
Definition: Prompt.php:45
$bot
A bot object implementing the Erebot::Interfaces::Core interface.
Definition: Prompt.php:48
Provides core functionalities for Erebot.
Definition: Core.php:59
process()
Processes commands queued in the input buffer.
Definition: Prompt.php:210
$socket
The underlying socket, represented as a stream.
Definition: Prompt.php:51
$io
I/O manager for the socket.
Definition: Prompt.php:54
__destruct()
Destructor.
Definition: Prompt.php:166
__construct(\Erebot\Interfaces\Core $bot, $connector=null, $group=null, $perms=0660)
Definition: Prompt.php:99
handleMessage($line)
Definition: Prompt.php:224