2 #include <QProcessEnvironment>
4 #include <QCoreApplication>
153 , _user(
"unknownuser")
198 QMutexLocker l(&
_lock);
212 {
VFS::ERROR( QString(
"Could not find _sourcePathMap reference for 0x%1 (%2). Not applying diff for '%3'").arg((quintptr)source, QT_POINTER_SIZE * 2, 16, QChar(
'0')).arg(source->className()).arg(t->
_initialPath), 0, t->
_user );
299 QJsonObject dob = d.object();
300 QJsonObject attrs = dob[
"attributes"].toObject();
301 QString tag = dob[
"command"].toString();
318 QJsonObject::iterator i = attrs.begin();
320 while (i != attrs.end() )
325 QJsonValue v = i.value();
328 if (v.toBool()==
true)
331 m[
"container"] =
true;
336 VFS::ERROR( QString(
"Useless create request on '%1'. Value was false." ).arg(path), 5,
_user );
367 QJsonObject::iterator i = attrs.begin();
369 while (i != attrs.end() )
372 bool s = i.value().toBool();
393 VFS::ERROR( QString(
"Useless rm request on '%1'. Value was false." ).arg(path), 5,
_user );
401 if (tag ==
"subscribe")
403 QJsonObject::iterator i = attrs.begin();
407 while (i != attrs.end() )
410 int c = i.value().toInt();
417 VFS::LOG( QString(
"Subscribing +%1 to '%2'").arg(c).arg(path), 8,
_user );
422 VFS::ERROR( QString(
"Useless subscribe request on '%1': count was %2." ).arg(path).arg(c), 5,
_user );
432 QJsonObject::iterator i = attrs.begin();
434 while (i != attrs.end() )
440 if (i.value().isDouble())
442 int c = i.value().toInt();
448 VFS::LOG( QString(
"Reading from '%1'").arg(path), 8,
_user );
453 VFS::ERROR( QString(
"Useless read request on '%1': count was %2." ).arg(path).arg(c), 5,
_user );
455 else if (i.value().isObject())
457 QJsonObject m = i.value().toObject();
461 VFS::LOG( QString(
"Reading with metadata from '%1'").arg(path), 8,
_user );
466 VFS::ERROR( QString(
"Malformed read request on '%1'." ).arg(path), 5,
_user );
474 if (tag ==
"submit" || tag ==
"write")
476 QJsonObject::iterator i = attrs.begin();
478 while (i != attrs.end() )
481 QJsonObject data = i.value().toObject();
493 VFS::LOG( QString(
"%1 to '%2'").arg(tag[0].toUpper()+tag.mid(1)).arg(path), 8,
_user );
505 QJsonObject::iterator i = attrs.begin();
507 while (i != attrs.end() )
510 QJsonObject data = i.value().toObject();
527 if (tag ==
"unsubscribe")
529 QJsonObject::iterator i = attrs.begin();
531 while (i != attrs.end() )
536 int c = i.value().toInt();
545 VFS::LOG( QString(
"Unsubscribing -%1 from '%2'").arg(c).arg(path), 8,
_user );
550 VFS::ERROR( QString(
"Useless unsubscribe request on '%1': count was %2." ).arg(path).arg(c), 5,
_user );
560 QJsonObject::iterator i = attrs.begin();
562 while (i != attrs.end() )
564 QString
id = i.key();
565 QJsonObject o = i.value().toObject();
566 QString path = o[
"path"].toString();
567 QJsonObject m = o[
"metadata"].toObject();
585 if (tag ==
"metadata")
587 QJsonObject::iterator i = attrs.begin();
589 while (i != attrs.end() )
607 if (tag ==
"requestlock")
609 QJsonObject::iterator i = attrs.begin();
611 while (i != attrs.end() )
614 QJsonObject data = i.value().toObject();
616 VFS::LOG( QString(
"Request lock on '%1'").arg(path), 8,
_user );
628 if (tag ==
"releaselock")
630 QJsonObject::iterator i = attrs.begin();
632 while ( i != attrs.end() )
635 QJsonObject data = i.value().toObject();
637 VFS::LOG( QString(
"Release lock on '%1'").arg(path), 8,
_user );
651 QJsonObject::iterator i = attrs.begin();
653 while ( i != attrs.end() )
655 QString library = i.key();
666 QMetaObject::invokeMethod(c->
_origin,
"executeRequest",Qt::AutoConnection,Q_ARG(
VFS_request*, c));
671 { QJsonObject o = c->
_data.object();
720 QString command = d.object()[
"command"].toString();
722 if ( command!=
"identify")
729 r[
"command"] =
"authorization";
730 a[
"accepted"] =
false;
739 QJsonObject o = d.object()[
"attributes"].toObject();
770 QString s = QString(
"user: %1\ntype: %2").arg(
_user).arg(
_type);
845 QJsonObject o = t->
_data.object();
846 _user = o[
"username"].toString();
847 _type = o[
"type"].toString();
851 printf(
"AUTH:\n%s\n",qUtf8Printable(t->
toJson(0,
true)));
853 VFS::LOG( QString(
"'%1' authenticated by '%2' on %3").arg(
_user).arg(t->
_initialPath).arg(QDateTime::currentDateTime().toString(Qt::SystemLocaleLongDate)), 3 );
870 QString m =
"Authentication denied.";
871 QString user = t->
_data.object()[
"username"].toString();
878 { m = QString(
"Authentication denied for user '%1'").arg(user);
883 r[
"command"] =
"authorization";
885 a[
"accepted"] =
false;
905 r[
"command"] =
"authorization";
906 r[
"attributes"] = t->
_data.object();
913 QString m = QString(
"Authorization denied for user '%1'").arg(t->
_user);
920 r[
"command"] =
"authorization";
922 a[
"accepted"] =
false;
952 QMutexLocker l(&
_lock);
976 QMutexLocker l(&
_lock);
987 VFS::WARN( QString(
"Could not remove null sender %1 from sourcePathMap.").arg((quintptr)sender()) );
1011 r[
"command"] =
"diff";
1018 a[
"diff"] = QJsonValue::Null;
1020 a[
"diff"] =
diff.object();
1022 r[
"attributes"] = a;
1023 QJsonDocument rd(r);
1048 r[
"command"] =
"read";
1052 a[
"type"] =
metadata[
"type"].toString();
1056 a[
"data"] = QJsonValue::Null;
1058 a[
"data"] = data.object();
1060 r[
"attributes"] = a;
1061 QJsonDocument rd(r);
1087 r[
"command"] =
"write";
1091 a[
"type"] =
metadata[
"type"].toString();
1095 a[
"data"] = QJsonValue::Null;
1097 a[
"data"] = data.object();
1099 r[
"attributes"] = a;
1100 QJsonDocument rd(r);
1124 r[
"command"] =
"rm";
1129 r[
"attributes"] = a;
1130 QJsonDocument rd(r);
1157 r[
"command"] =
"subscribe";
1161 a[
"type"] =
metadata[
"type"].toString();
1165 a[
"data"] = QJsonValue::Null;
1167 a[
"data"] = data.object();
1169 r[
"attributes"] = a;
1170 QJsonDocument rd(r);
1198 r[
"command"] =
"ls";
1204 a[
"data"] = data.object();
1206 r[
"attributes"] = a;
1208 QJsonDocument rd(r);
1232 r[
"command"] =
"metadata";
1240 r[
"attributes"] = a;
1241 QJsonDocument rd(r);
1268 r[
"command"] =
"requestlock";
1272 a[
"data"] = data.object();
1274 r[
"attributes"] = a;
1275 QJsonDocument rd(r);
1302 r[
"command"] =
"releaselock";
1306 a[
"data"] = data.object();
1308 r[
"attributes"] = a;
1309 QJsonDocument rd(r);
1335 r[
"command"] =
"code";
1341 if (!
error.isEmpty())
1342 { a[
"error"] =
error;
1346 r[
"attributes"] = a;
1347 QJsonDocument rd(r);
1368 r[
"command"] =
"codeDirectory";
1373 if (!
error.isEmpty())
1374 { a[
"error"] =
error;
1378 r[
"attributes"] = a;
1379 QJsonDocument rd(r);
1401 r[
"command"] =
"error";
1402 a[
"message"] = message;
1403 r[
"attributes"] = a;
1404 QJsonDocument rd(r);
1427 r[
"command"] =
"requesterror";
1428 a[
"command"] = command;
1430 a[
"reason"] = reason;
1431 r[
"attributes"] = a;
1432 QJsonDocument rd(r);
1457 r[
"command"] =
"requestsuccess";
1458 a[
"command"] = command;
1460 if (!data.isEmpty())
1461 a[
"data"] = data.object();
1464 r[
"attributes"] = a;
1465 QJsonDocument rd(r);
1535 _reason = QString(
"remotoserver_request::read was not successful on '%1'.").arg(
_initialPath);
1553 _reason = QString(
"remotoserver_request::subscribe was not successful on '%1'.").arg(
_initialPath);
1590 _reason =
"remotoserver_request::write was not successful.";
1611 _reason =
"remotoserver_request::submit was not successful.";
1687 _reason = QString(
"remotoserver_request::metadata was not successful on '%1'.").arg(
_initialPath);
1726 QJsonObject o =
_data.object();
1727 QString name = o[
"name"].toString();
1728 QString
code = o[
"code"].toString();
1737 _reason = QString(
"remotoserver_request::code was not successful on '%1'.").arg(
_initialPath);
1753 VFS::ERROR(
"COULD NOT CAST TO REMOTOSERVER_CLIENT... was it deleted?\n");
QPair< VFS_node *, QString > notifyException
static VFS_request * code(VFS_request *r)
Resolve a request for code.
VFS_node is the base class from which all other VFS_node classes derive.
virtual void metadata(VFS_request *r)
Fetch the metadata of this node.
virtual void issueRequest(VFS_request *t)
A convenience function.
static bool __isNode(VFS_node *)
Check to see if a node is in the global registry.
static QString code(QString nodename, QString libname, QString &error)
Fetch code or any other resource from a node.
void unmounted(VFS_node *self)
Emitted when a node is unmount()ed.
void diff(VFS_node *origin, VFS_request *t)
Emit a diff, which will trigger notifySubscribers() for a mounted node.
QString className()
Return the class name of a node.
QMutex _lock
A recursive mutex that is local to this node.
virtual void applyDiff(VFS_request *r)
Apply a diff received via subscription.
virtual void receiveResponse(VFS_request *t)
Once a VFS_request has been completed, a response will be issued back to its _origin.
A subclass of VFS_websocket_client that implements the remoto websocket protocol and handles requests...
virtual QJsonDocument receive(QByteArray data)
Receive a message from a connected websocket client.
QString _type
The remote client type, which may be "browser" or "unity" or any other id string.
virtual void authenticate(QJsonDocument d)
Authenticate a user using VFS_websocket_server::authenticate().
bool writeUICode(QString libname, QString code, QString error, bool binary=false)
Write a VFS_request::code response to a connected client.
bool writeRequestError(QString command, QString path, QString reason, bool binary=false)
Write a requesterror command to a connected client.
QMap< VFS_node *, QString > _sourcePathMap
A map relating path requests from a client to path requests on the VFS.
bool writeUIRequestLock(QString path, QJsonDocument data, bool binary=false)
Write the results of a VFS_request::requestlock to a connected client.
bool writeError(QString message, bool binary=false)
Write an error state to a connected client.
void addSourcePathMap(VFS_node *source, QString path)
Add a VFS_remotoserver_client::_sourcePathMap entry for a path from a client's perspective to a VFS_n...
friend class VFS_remotoserver_request
bool writeUIWrite(QString path, QJsonDocument data, QJsonObject metadata, bool binary=false)
Write data to a connected client.
virtual void applyDiff(VFS_request *t)
Apply a diff to this node.
bool writeUIReleaseLock(QString path, QJsonDocument data, bool binary=false)
Write the results of a VFS_request::releaselock to a connected client.
bool writeUIMetadata(QString path, QJsonObject metadata, bool binary=false)
Write a VFS_request::metadata response to a connected client.
QJsonObject _parameters
Parameters provided during the auth process.
virtual void receiveResponse(VFS_request *t)
Receive a response from an issueRequest().
bool writeUIRead(QString path, QJsonDocument data, QJsonObject metadata, bool binary=false)
Send the results of a VFS_request::read command to a client.
QJsonObject parameters() const
Return the parameters provided to this client when authentication was granted.
virtual ~VFS_remotoserver_client()
VFS_session * _session
The session associated with this client connection.
virtual void write(VFS_request *r)
Write form or interface information back to a user.
QString _user
The authenticated client's username.
bool writeUICodeDirectory(QJsonObject o, QString error, bool binary=false)
Write a VFS_request::codeDirectory response to a connected client.
virtual void removeSourcePathMap(VFS_node *n)
Remove a VFS_remotoserver_client::_sourcePathMap entry for a VFS_node.
virtual VFS_node * find(VFS_request *r)
VFS_remotoserver_client cannot contain children, but instead points to a websocket client,...
virtual QString reportDetails()
Report the _user and _type of a connected client.
virtual VFS_request * createRequest(VFS_request::requestType type, QString path, QString user="unknown", QJsonDocument data=QJsonDocument(), QJsonObject metadata=QJsonObject(), bool dontDelete=false)
Create a VFS_remotoserver_request to service a request received from a client.
bool writeRequestSuccess(QString command, QString path, QJsonDocument data=QJsonDocument(), QJsonObject metadata=QJsonObject(), bool binary=false)
VFS_remotoserver_client::writeRequestSuccess.
bool writeUIDiff(QString path, QJsonDocument diff, QString user, bool binary=false)
Send a diff command to a client when something interesting happens on a subscribed VFS_node.
bool writeUIRM(QString path, bool binary=false)
Send an RM command to a connected client.
virtual void rm(VFS_request *r)
Send an RM command to a user.
bool writeUISubscribe(QString path, QJsonDocument data, QJsonObject metadata, bool binary=false)
Write a VFS_request::subscribe response to a connected client.
VFS_remotoserver_client(QWebSocket *socket, VFS_websocket_server *server)
bool writeUILS(QString id, QString path, QJsonDocument data, QJsonObject metadata, bool binary=false)
Write a VFS_request::ls response to a connected client.
A subclass of VFS_request used for websocket (VFS_remotoserver) communication.
bool _binary
Binary mode flag for websocket messages.
virtual void execute()
Dynamically cast the _origin node to a VFS_remotoserver_client and write the results of a request to ...
virtual ~VFS_remotoserver_request()
VFS_remotoserver_request(VFS_request::requestType type, VFS_remotoserver_client *origin, QString path="", QString user="unknown", QJsonDocument data=QJsonDocument(), QJsonObject metadata=QJsonObject(), bool binary=false)
virtual void clientTextMessage(QString message)
The client has received as text websocket message.
Q_INVOKABLE VFS_remotoserver(quint16 port, QString auth, QString sessions, QHostAddress addr=QHostAddress::Any, QWebSocketServer::SslMode ssl=QWebSocketServer::NonSecureMode, QString sslCertPath="", QString sslKeyPath="")
virtual QString reportDetails()
Report the _port number.
virtual VFS_websocket_client * createWebsocketClient(QWebSocket *s)
Create a VFS_remotoserver_client to host a new connection.
static int count
The global count of VFS_remotoserver instances, used to create a config.json file if needed.
virtual void clientBinaryMessage(QByteArray message)
The client has received as binary websocket message.
virtual ~VFS_remotoserver()
The base class for all requests between nodes.
requestType
Requests perform one of these actions.
@ read
read full contents (4)
@ requestlock
request a lock (13)
@ unsubscribe
unsubscribe from a path (10)
@ ls
list children of a node (1)
@ metadata
read metadata (6)
@ create
create a new file/path (2)
@ write
write full contents (5)
@ code
request code from a node (15)
@ releaselock
release a lock (14)
@ subscribe
subscribe to a path (9)
@ rm
delete an existing file/path (3)
VFS_node * _responder
the receiver of the request
VFS_node * _origin
the origin of the request
bool hasCallback()
Check if this request has a callback set.
requestType _requestType
the action this request is performing or requesting
QString _initialPath
the target path when the request was made (relative to the responder)
QStringList _prefixPath
the prefix elements found while searching for the target
QString _user
who initiated this request, mostly for logging
virtual void execute()
after a request has completed, a request may have a special execute function.
VFS_session * _session
The session associated with this request. This is an optional value, and care should be taken to chec...
QString _reason
if something (probably bad) happened, this is the reason
QString _path
the target path remnant... the remaining path element once the request has found its target
QList< notifyException > _notifyExceptions
a list of nodes not to send responses to for this transaction. For instance if a node submits to a no...
bool _success
if the request was successfully completed
QJsonDocument _data
the request payload
virtual QByteArray toJson(postID id=0, bool ignoreSuccess=false, bool includeInitialPath=false)
Serialize this request.
QJsonObject _metadata
the request payload
A VFS_node that manages a QWebSocket connection.
QHostAddress _address
The network address of the connected client.
virtual void authorized()
Notify the node that it has received authorization from some auth method.
bool _authorized
if this connection has a session
VFS_websocket_server * _server
owning server
bool _authenticated
if auth has taken place and succeeded
virtual void close()
Close the socket if it is connected.
virtual bool writeBinary(QByteArray data)
Write binary data over the websocket.
void error(QAbstractSocket::SocketError)
There has been a socket error.
virtual bool writeText(QString data)
Write text data over the websocket.
virtual QJsonDocument receive(QByteArray message)
VFS_websocket_VFSclient::receive.
A VFS_websocket server will listen for incoming websocket connections, optionally using ssl.
virtual bool authenticate(VFS_websocket_client *client, QJsonObject credentials)
Authenticate a client based on received credentials.
quint16 _port
Port to listen on.
QString _sessionsPath
The path to the sessionManager node.
virtual void authorize(VFS_websocket_client *client, QJsonObject authdata)
Authorize a client and create a session based on type and username.
static void LOG(QString message, int level=0, QString user="server")
Send a message to the VFS::_messages VFS_stream.
static void ERROR(QString message, int level=0, QString user="server")
Send a message to the VFS::_errors VFS_stream.
static void WARN(QString message, int level=0, QString user="server")
Send a message to the VFS::_warnings VFS_stream.
message(m)
Change the message of an existing arrowMessage.
setter name
a setter DOCME
setter type
a setter DOCME
getter path
a getter DOCME
QString cleanPath(QString path)
Clean and normalize a VFS path.