Skip to content

Commit

Permalink
Merge pull request #36 from clue-labs/login
Browse files Browse the repository at this point in the history
Support passing authentication as part of URI
  • Loading branch information
clue authored May 30, 2018
2 parents 87b0982 + cee51e9 commit 72f7d44
Show file tree
Hide file tree
Showing 11 changed files with 618 additions and 215 deletions.
25 changes: 23 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ and probing for the correct protocol to use.
```php
$factory->createClient('localhost')->then(
function (Client $client) {
// client connected
// client connected (and authenticated)
},
function (Exception $e) {
// an error occured while trying to connect client
// an error occured while trying to connect (or authenticate) client
}
);
```
Expand All @@ -90,6 +90,27 @@ if your Quassel IRC core is not using the default TCP/IP port `4242`:
$factory->createClient('quassel://localhost:4242');
```

Quassel supports password-based authentication. If you want to create a "normal"
client connection, you're recommended to pass the authentication details as part
of the URI. You can pass the password `h@llo` URL-encoded (percent-encoded) as
part of the URI like this:

```php
$factory->createClient('quassel://user:h%40llo@localhost')->then(
function (Client $client) {
// client sucessfully connected and authenticated
$client->on('data', function ($data) {
// next message to follow would be "SessionInit"
});
}
);
```

Note that if you do not pass the authentication details as part of the URI, then
this method will resolve with a "bare" `Client` right after connecting without
sending any application messages. This can be useful if you need full control
over the message flow, see below for more details.

> This method uses Quassel IRC's probing mechanism for the correct protocol to
use (newer "datastream" protocol or original "legacy" protocol).
Protocol handling will be abstracted away for you, so you don't have to
Expand Down
46 changes: 9 additions & 37 deletions examples/01-channels.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,31 @@
use Clue\React\Quassel\Io\Protocol;

require __DIR__ . '/../vendor/autoload.php';

$host = '127.0.0.1';
$user = array();
if (isset($argv[1])) { $host = $argv[1]; }

echo 'Server: ' . $host . PHP_EOL;

echo 'User name: ';
$user['name'] = trim(fgets(STDIN));
$user = trim(fgets(STDIN));

echo 'Password: ';
$user['password'] = trim(fgets(STDIN));
$pass = trim(fgets(STDIN));

$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient($host)->then(function (Client $client) use ($loop, $user) {
$uri = rawurlencode($user) . ':' . rawurlencode($pass) . '@' . $host;

$factory->createClient($uri)->then(function (Client $client) {
var_dump('CONNECTED');

$await = array();

$client->on('data', function ($message) use ($client, $user, &$await) {
$type = null;
if (is_array($message) && isset($message['MsgType'])) {
$type = $message['MsgType'];
}

if ($type === 'ClientInitAck') {
if (!$message['Configured']) {
var_dump('core not configured yet');
$client->close();
return;
}
var_dump('core ready, now logging in');
$client->writeClientLogin($user['name'], $user['password']);

return;
}
if ($type === 'ClientLoginReject') {
var_dump('Unable to login', $message['Error']);

var_dump('Now closing connection');
$client->close();

return;
}
if ($type === 'ClientLoginAck') {
var_dump('successfully logged in, now waiting for a SessionInit message');

return;
}
if ($type === 'SessionInit') {
$client->on('data', function ($message) use ($client, &$await) {
// session initialized => initialize all networks
if (isset($message['MsgType']) && $message['MsgType'] === 'SessionInit') {
var_dump('session initialized');

foreach ($message['SessionState']['NetworkIds'] as $nid) {
Expand Down Expand Up @@ -104,8 +78,6 @@
$client->on('close', function () {
echo 'Connection closed' . PHP_EOL;
});

$client->writeClientInit();
})->then(null, function ($e) {
echo $e;
});
Expand Down
52 changes: 12 additions & 40 deletions examples/02-chatbot.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,62 +5,36 @@
use Clue\React\Quassel\Io\Protocol;

require __DIR__ . '/../vendor/autoload.php';

$host = '127.0.0.1';
$user = array();
if (isset($argv[1])) { $host = $argv[1]; }

echo 'Server: ' . $host . PHP_EOL;

echo 'User name: ';
$user['name'] = trim(fgets(STDIN));
$user = trim(fgets(STDIN));

echo 'Password: ';
$user['password'] = trim(fgets(STDIN));
$pass = trim(fgets(STDIN));

echo 'Keyword: ';
$user['keyword'] = trim(fgets(STDIN));
$keyword = trim(fgets(STDIN));

if (strlen($user['keyword']) < 3) {
if (strlen($keyword) < 3) {
die('Keyword MUST contain at least 3 characters to avoid excessive spam');
}

$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient($host)->then(function (Client $client) use ($loop, $user) {
var_dump('CONNECTED');

$client->on('data', function ($message) use ($client, $user, $loop) {
$type = null;
if (is_array($message) && isset($message['MsgType'])) {
$type = $message['MsgType'];
}

if ($type === 'ClientInitAck') {
if (!$message['Configured']) {
var_dump('core not configured yet');
$client->close();
return;
}
var_dump('core ready, now logging in');
$client->writeClientLogin($user['name'], $user['password']);

return;
}
if ($type === 'ClientLoginReject') {
var_dump('Unable to login', $message['Error']);

var_dump('Now closing connection');
$client->close();
$uri = rawurlencode($user) . ':' . rawurlencode($pass) . '@' . $host;

return;
}
if ($type === 'ClientLoginAck') {
var_dump('successfully logged in, now waiting for a SessionInit message');
$factory->createClient($uri)->then(function (Client $client) use ($loop, $keyword) {
var_dump('CONNECTED');

return;
}
if ($type === 'SessionInit') {
$client->on('data', function ($message) use ($client, $keyword, $loop) {
// session initialized
if (isset($message['MsgType']) && $message['MsgType']=== 'SessionInit') {
var_dump('session initialized, now waiting for incoming messages');

// send heartbeat message every 30s to check dropped connection
Expand All @@ -87,7 +61,7 @@
if (isset($message[0]) && $message[0] === Protocol::REQUEST_RPCCALL && $message[1] === '2displayMsg(Message)') {
$data = $message[2];

if (strpos($data['content'], $user['keyword']) !== false) {
if (strpos($data['content'], $keyword) !== false) {
$client->writeBufferInput($data['bufferInfo'], 'Hello from clue/quassel-react :-)');

echo date('Y-m-d H:i:s') . ' Replied to ' . $data['bufferInfo']['name'] . '/' . explode('!', $data['sender'], 2)[0] . ': "' . $data['content'] . '"' . PHP_EOL;
Expand All @@ -99,8 +73,6 @@
$client->on('close', function () {
echo 'Connection closed' . PHP_EOL;
});

$client->writeClientInit();
})->then(null, function ($e) {
echo $e;
});
Expand Down
46 changes: 9 additions & 37 deletions examples/03-pingbot.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,31 @@
use Clue\React\Quassel\Io\Protocol;

require __DIR__ . '/../vendor/autoload.php';

$host = '127.0.0.1';
$user = array();
if (isset($argv[1])) { $host = $argv[1]; }

echo 'Server: ' . $host . PHP_EOL;

echo 'User name: ';
$user['name'] = trim(fgets(STDIN));
$user = trim(fgets(STDIN));

echo 'Password: ';
$user['password'] = trim(fgets(STDIN));
$pass = trim(fgets(STDIN));

$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient($host)->then(function (Client $client) use ($loop, $user) {
$uri = rawurlencode($user) . ':' . rawurlencode($pass) . '@' . $host;

$factory->createClient($uri)->then(function (Client $client) use ($loop) {
var_dump('CONNECTED');

$nicks = array();

$client->on('data', function ($message) use ($client, $user, &$nicks, $loop) {
$type = null;
if (is_array($message) && isset($message['MsgType'])) {
$type = $message['MsgType'];
}

if ($type === 'ClientInitAck') {
if (!$message['Configured']) {
var_dump('core not configured yet');
$client->close();
return;
}
var_dump('core ready, now logging in');
$client->writeClientLogin($user['name'], $user['password']);

return;
}
if ($type === 'ClientLoginReject') {
var_dump('Unable to login', $message['Error']);

var_dump('Now closing connection');
$client->close();

return;
}
if ($type === 'ClientLoginAck') {
var_dump('successfully logged in, now waiting for a SessionInit message');

return;
}
if ($type === 'SessionInit') {
$client->on('data', function ($message) use ($client, &$nicks, $loop) {
// session initialized => initialize all networks
if (isset($message['MsgType']) && $message['MsgType'] === 'SessionInit') {
var_dump('session initialized, now waiting for incoming messages');

foreach ($message['SessionState']['NetworkIds'] as $nid) {
Expand Down Expand Up @@ -136,8 +110,6 @@
$client->on('close', function () {
echo 'Connection closed' . PHP_EOL;
});

$client->writeClientInit();
})->then(null, function ($e) {
echo $e;
});
Expand Down
69 changes: 8 additions & 61 deletions examples/04-connect.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,79 +6,28 @@

require __DIR__ . '/../vendor/autoload.php';

$debug = false;
$host = '127.0.0.1';
$user = array();
if (isset($argv[1])) { $host = $argv[1]; }

echo 'Server: ' . $host . PHP_EOL;

echo 'User name: ';
$user['name'] = trim(fgets(STDIN));
$user = trim(fgets(STDIN));

echo 'Password: ';
$user['password'] = trim(fgets(STDIN));
$pass = trim(fgets(STDIN));

$loop = \React\EventLoop\Factory::create();
$factory = new Factory($loop);

$factory->createClient($host)->then(function (Client $client) use ($loop, $user, $debug) {
var_dump('CONNECTED');

if ($debug) {
$client->on('data', function ($message) {
var_dump($message);
});
}

$client->on('data', function ($message) use ($client, $user, $loop) {
$type = null;
if (is_array($message) && isset($message['MsgType'])) {
$type = $message['MsgType'];
}

if ($type === 'ClientInitAck') {
if (!$message['Configured']) {
var_dump('core not configured yet, you may want to issue a setup call manually');
print_r($message['StorageBackends']);

echo 'Hit enter to set-up server with defaults, otherwise cancel program now';
fgets(STDIN);

$client->writeCoreSetupData($user['name'], $user['password']);

return;
}
var_dump('core ready, now logging in');
$client->writeClientLogin($user['name'], $user['password']);

return;
}
if ($type === 'CoreSetupAck') {
var_dump('core set-up, now logging in');
$client->writeClientLogin($user['name'], $user['password']);
$uri = rawurlencode($user) . ':' . rawurlencode($pass) . '@' . $host;

return;
}
if ($type === 'CoreSetupReject') {
var_dump('Unable to set-up core', $message['Error']);

return;
}
if ($type === 'ClientLoginReject') {
var_dump('Unable to login', $message['Error']);

var_dump('Now closing connection');
$client->close();

return;
}
if ($type === 'ClientLoginAck') {
var_dump('successfully logged in, now waiting for a SessionInit message');
$factory->createClient($uri)->then(function (Client $client) use ($loop) {
var_dump('CONNECTED');

return;
}
if ($type === 'SessionInit') {
$client->on('data', function ($message) use ($client, $loop) {
// session initialized => initialize all networks and buffers
if (isset($message['MsgType']) && $message['MsgType'] === 'SessionInit') {
var_dump('session initialized');

foreach ($message['SessionState']['NetworkIds'] as $nid) {
Expand Down Expand Up @@ -145,8 +94,6 @@
$client->on('close', function () {
echo 'Connection closed' . PHP_EOL;
});

$client->writeClientInit();
})->then(null, function ($e) {
echo $e;
});
Expand Down
Loading

0 comments on commit 72f7d44

Please sign in to comment.