21 namespace Erebot\Proxy;
27 class SOCKS extends \Erebot\Proxy\Base
29 public function proxify(\Erebot\URIInterface $proxyURI, \Erebot\URIInterface $nextURI)
31 $port = $nextURI->getPort();
32 $scheme = $nextURI->getScheme();
35 $port = getservbyname($scheme,
'tcp');
37 if (!is_int($port) || $port <= 0 || $port > 65535) {
38 throw new \Erebot\InvalidValueException(
'Invalid port');
42 $this->
write(
"\x05\x02\x00\x02");
43 $line = $this->
read(2);
45 if ($line[0] !=
"\x05") {
46 throw new \Erebot\InvalidValueException(
'Bad SOCKS version');
49 switch (ord($line[1])) {
56 throw new \Erebot\InvalidValueException(
'No acceptable method');
60 $host = $nextURI->getHost();
63 pack(
"Ca*n", strlen($host), $host, $port)
66 $line = $this->
read(4);
67 if ($line[0] !=
"\x05") {
68 throw new \Erebot\InvalidValueException(
'Bad SOCKS version');
71 $error = ord($line[1]);
76 'General SOCKS server failure',
77 'Connection not allowed by ruleset',
78 'Network unreachable',
82 'Command not supported',
83 'Address type not supported',
85 if (!isset($errors[$error])) {
86 throw new \Erebot\InvalidValueException(
'Unknown error');
88 throw new \Erebot\InvalidValueException($errors[$error]);
91 switch (ord($line[3])) {
97 $len = ord($this->
read(1));
106 throw new \Erebot\InvalidValueException(
107 'Address type not supported'
123 protected function userpass(\Erebot\URIInterface $proxyURI)
125 $username = $proxyURI->asParsedURL(PHP_URL_USER);
126 $password = $proxyURI->asParsedURL(PHP_URL_PASS);
128 if ($username === null || $password === null) {
129 throw new \Erebot\InvalidValueException(
130 'No username or password supplied'
134 $ulen = strlen($username);
135 $plen = strlen($password);
137 throw new \Erebot\InvalidValueException(
138 'Username too long (max. 255)'
143 throw new \Erebot\InvalidValueException(
144 'Password too long (max. 255)'
157 $line = $this->
read(2);
159 if ($line[0] !=
"\x01") {
160 throw new \Erebot\InvalidValueException(
161 'Bad subnegociation version'
165 if ($line[1] !=
"\x00") {
166 throw new \Erebot\InvalidValueException(
'Bad username or password');
183 for ($written = 0, $len = strlen($line); $written < $len; $written += $fwrite) {
184 $fwrite = fwrite($this->socket, substr($line, $written));
185 if ($fwrite ===
false) {
186 throw new \Erebot\Exception(
'Connection closed by proxy');
205 while (!feof($this->socket) && $clen < $len) {
206 $read = fread($this->socket, $len - $clen);
207 if ($read ===
false) {
208 throw new \Erebot\Exception(
'Connection closed by proxy');
211 $clen = strlen($contents);
userpass(\Erebot\URIInterface $proxyURI)
Proxies data through a SOCKS 5 proxy.