Commit 9375f88f authored by Carsten  Rose's avatar Carsten Rose

Merge branch 'master' into 'develop'

Master

See merge request !281
parents 8f9bd35d ef98e435
Pipeline #3764 passed with stages
in 4 minutes and 1 second
......@@ -496,11 +496,11 @@ The STORE_RECORD will always be merged with previous content. The Level Keys are
.. important::
Multiple columns, with the same column name, can't be accessed individually. Only the last column is available.
Multiple columns, with the same column name, can't be accessed individually. Only the last column is available.
.. important::
Retrieving the *final* value of :ref:`special-column-names` is possible via '{{&<column>:R}} (there is an '&' direct behind '{{')
Retrieving the *final* value of :ref:`special-column-names` is possible via '{{&<column>:R}} (there is an '&' direct behind '{{')
Example::
......@@ -2201,25 +2201,30 @@ Sending messages via WebSocket and receiving the answer is done via: ::
SELECT 'w:ws://<host>:<port>/<path>|t:<message>' AS _websocket
Instead of '... AS _websocket' it's also possible to use '... AS _link'.
Instead of ``... AS _websocket`` it's also possible to use ``... AS _link`` (same syntax).
The answer is written to output and stored in the given column (in this case 'websocket' or 'link').
The answer from the socket (if there is something) is written to output and stored in STORE_RECORD by given column (in this
case 'websocket' or 'link').
.. tip::
To suppress the direct output, add '_hide' to the column name::
To suppress the direct output, add ``|_hide`` to the column name.
Example::
SELECT 'w:ws://<host>:<port>/<path>|t:<message>' AS '_websocket|_hide'
.. tip::
To define a uniq column name (to access it later via STORE_RECORD)::
To define a uniq column name (easy access by column name via STORE_RECORD) add ``|myName`` (replace *myName*).
Example::
SELECT 'w:ws://<host>:<port>/<path>|t:<message>' AS '_websocket|myName'
.. tip::
Get the answer from STORE_RECORD by using '{{&...'. Check `access-column-values`_.
Get the answer from STORE_RECORD by using ``{{&...``. Check `access-column-values`_.
Example::
......@@ -2230,7 +2235,6 @@ Example::
'{{myName:R}}' >> 'w:ws://<host>:<port>/<path>|t:<message>'
'{{&myName:R}}' >> '<received socket answer>'
.. _drag_and_drop:
Drag and drop
......
......@@ -30,7 +30,6 @@ use IMATHUZH\Qfq\Core\Helper\Support;
use IMATHUZH\Qfq\Core\Helper\Token;
use IMATHUZH\Qfq\Core\Store\Sip;
use IMATHUZH\Qfq\Core\Store\Store;
use IMATHUZH\Qfq\Core\Report\WebSocket;
/*
* a:AltText
......@@ -538,22 +537,32 @@ class Link {
}
$urlParts = parse_url($param[TOKEN_WEBSOCKET]);
if (empty($urlParts['host']) || empty($urlParts['port']) || empty($urlParts['path'])) {
$urlParts = array_merge(['scheme' => 'ws', 'host' => '', 'port' => 80, 'path' => ''], $urlParts);
if (empty($urlParts['host'])) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Target URL incomplete',
ERROR_MESSAGE_TO_DEVELOPER =>
'host:' . $urlParts['host'] . ', ' .
'port:' . $urlParts['port'] . ', ' .
'path:' . $urlParts['path']])
'host: ' . $urlParts['host'] . ', ' .
'port: ' . $urlParts['port'] . ', ' .
'path: ' . $urlParts['path']])
, ERROR_MISSING_VALUE);
}
// Check for wss >> ssl
if ($urlParts['scheme'] == 'wss') {
$urlParts['host'] = 'ssl://' . $urlParts['host'];
if ($urlParts['port'] == 0) {
$urlParts['port'] = 443;
}
}
// Open Socket
if (false === $websocket->connect($urlParts['host'], $urlParts['port'], $urlParts['path'])) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Failed connect websocket',
$errorMsg = '';
if (false === $websocket->connect($urlParts['host'], $urlParts['port'], $urlParts['path'], '', $errorMsg)) {
throw new \UserFormException(json_encode([ERROR_MESSAGE_TO_USER => 'Failed connect websocket: ' . $errorMsg,
ERROR_MESSAGE_TO_DEVELOPER =>
'host:' . $urlParts['host'] . ', ' .
'port:' . $urlParts['port'] . ', ' .
'path:' . $urlParts['path']])
'host: ' . $urlParts['host'] . ', ' .
'port: ' . $urlParts['port'] . ', ' .
'path: ' . $urlParts['path']])
, ERROR_MISSING_VALUE);
}
......
......@@ -62,6 +62,7 @@ class WebSocket {
* @return bool
*/
public function sendData(string $data, string $type = 'text', bool $masked = true) {
if ($this->connected === false) {
trigger_error("Not connected", E_USER_WARNING);
return false;
......@@ -142,9 +143,10 @@ class WebSocket {
* @param int $port
* @param string $path
* @param string $origin
* @param string $errorMsg # In case of an error, return error msg.
* @return bool
*/
public function connect(string $host, int $port, string $path, string $origin = '') {
public function connect(string $host, int $port, string $path, string $origin = '', &$errorMsg = '') {
$this->host = $host;
$this->port = $port;
$this->path = $path;
......@@ -170,12 +172,18 @@ class WebSocket {
@fwrite($this->socket, $header);
$response = @fread($this->socket, 1500);
$errorMsg = $response;
$this->connected = false;
preg_match('#Sec-WebSocket-Accept:\s(.*)$#mU', $response, $matches);
if ($matches) {
$keyAccept = trim($matches[1]);
$expectedResponse = base64_encode(pack('H*', sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
$this->connected = ($keyAccept === $expectedResponse) ? true : false;
if ($keyAccept === $expectedResponse) {
$this->connected = true;
$errorMsg = '';
}
}
return $this->connected;
......
......@@ -57,18 +57,21 @@ i.@{spinner_class} {
cursor: pointer;
height: 0;
width: 0;
-moz-appearance: none;
/*Radios don't scale correctly on Firefox with zoom*/
}
/* Customize the label (the container) */
.radio-inline, .radio {
display: inline-block;
position: relative;
padding-left: 1.8em;
padding-left: 25px;
padding-top: 0 !important;
margin-top: 7px !important;
margin-right: 10px;
cursor: pointer;
font-size: 1em;
line-height: 20px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
......@@ -84,8 +87,8 @@ i.@{spinner_class} {
position: absolute;
top: 0;
left: 0;
height: 18px;
width: 18px;
height: 20px;
width: 20px;
background-color: #fff;
border-radius: 50%;
border: 2px solid #ccc;
......@@ -114,8 +117,8 @@ i.@{spinner_class} {
/* Style the indicator (dot/circle) */
.radio-inline .checkmark:after, .radio .checkmark:after {
top: 3px;
left: 3px;
top: 4px;
left: 4px;
width: 8px;
height: 8px;
border-radius: 50%;
......@@ -124,24 +127,27 @@ i.@{spinner_class} {
/* CUSTOM CHECKBOXES */
/* Hide the browser's default radio */
.checkbox-inline>input[type=checkbox] {
.checkbox-inline>input[type=checkbox], .checkbox>input[type=checkbox] {
position: absolute;
opacity: 0;
cursor: pointer;
height: 0;
width: 0;
-moz-appearance: none;
/*Checkboxes don't scale correctly on Firefox with zoom*/
}
/* Customize the label (the container) */
.checkbox-inline, .checkbox {
display: inline-block;
position: relative;
padding-left: 1.8em;
padding-left: 26px;
padding-top: 0 !important;
margin-top: 7px !important;
margin-right: 10px;
cursor: pointer;
font-size: 1em;
line-height: 20px;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
......@@ -169,10 +175,10 @@ i.@{spinner_class} {
position: absolute;
top: 0;
left: 0;
height: 18px;
width: 18px;
height: 20px;
width: 20px;
background-color: #fff;
border-radius: 4px;
border-radius: 5px;
border: 2px solid #ccc;
}
......@@ -209,9 +215,9 @@ i.@{spinner_class} {
/* Style the indicator (dot/circle) */
.checkbox-inline .checkmark:after, .checkbox .checkmark:after {
top: 1px;
left: 4px;
left: 5px;
width: 6px;
height: 10px;
height: 12px;
border: solid white;
border-width: 0 3px 3px 0;
-webkit-transform: rotate(45deg);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment