void ClipboardClient::start(const QStringList &arguments) { QScriptEngine engine; ScriptableProxy scriptableProxy(nullptr, nullptr); Scriptable scriptable(&engine, &scriptableProxy); const auto serverName = clipboardServerName(); ClientSocket socket(serverName); connect( &socket, &ClientSocket::messageReceived, this, &ClipboardClient::onMessageReceived ); connect( &socket, &ClientSocket::disconnected, this, &ClipboardClient::onDisconnected ); connect( &socket, &ClientSocket::connectionFailed, this, &ClipboardClient::onConnectionFailed ); connect( &scriptableProxy, &ScriptableProxy::sendMessage, &socket, &ClientSocket::sendMessage ); connect( this, &ClipboardClient::functionCallResultReceived, &scriptableProxy, &ScriptableProxy::setFunctionCallReturnValue ); connect( this, &ClipboardClient::inputDialogFinished, &scriptableProxy, &ScriptableProxy::setInputDialogResult ); connect( &socket, &ClientSocket::disconnected, &scriptable, &Scriptable::abort ); connect( &socket, &ClientSocket::disconnected, &scriptableProxy, &ScriptableProxy::clientDisconnected ); connect( &scriptable, &Scriptable::finished, &scriptableProxy, &ScriptableProxy::clientDisconnected ); bool hasActionId; #if QT_VERSION < QT_VERSION_CHECK(5,5,0) auto actionId = qgetenv("COPYQ_ACTION_ID").toInt(&hasActionId); #else auto actionId = qEnvironmentVariableIntValue("COPYQ_ACTION_ID", &hasActionId); #endif const auto actionName = getTextData( qgetenv("COPYQ_ACTION_NAME") ); if ( socket.start() ) { if (hasActionId) scriptable.setActionId(actionId); scriptable.setActionName(actionName); const int exitCode = scriptable.executeArguments(arguments); exit(exitCode); } }
void ScriptableWorker::run() { if ( hasLogLevel(LogDebug) ) { bool isEval = m_args.length() == Arguments::Rest + 2 && m_args.at(Arguments::Rest) == "eval"; for (int i = Arguments::Rest + (isEval ? 1 : 0); i < m_args.length(); ++i) { QString indent = isEval ? QString("EVAL:") : (QString::number(i - Arguments::Rest + 1) + " "); foreach (const QByteArray &line, m_args.at(i).split('\n')) { SCRIPT_LOG( indent + getTextData(line) ); indent = " "; } } } bool hasData; const quintptr id = m_args.at(Arguments::ActionId).toULongLong(&hasData); QVariantMap data; if (hasData) data = Action::data(id); const QString currentPath = getTextData(m_args.at(Arguments::CurrentPath)); QScriptEngine engine; ScriptableProxy proxy(m_wnd, data); Scriptable scriptable(&proxy); scriptable.initEngine(&engine, currentPath, data); if (m_socket) { QObject::connect( proxy.signaler(), SIGNAL(sendMessage(QByteArray,int)), m_socket, SLOT(sendMessage(QByteArray,int)) ); QObject::connect( &scriptable, SIGNAL(sendMessage(QByteArray,int)), m_socket, SLOT(sendMessage(QByteArray,int)) ); QObject::connect( m_socket, SIGNAL(messageReceived(QByteArray,int)), &scriptable, SLOT(setInput(QByteArray)) ); QObject::connect( m_socket, SIGNAL(disconnected()), &scriptable, SLOT(abort()) ); QObject::connect( &scriptable, SIGNAL(destroyed()), m_socket, SLOT(deleteAfterDisconnected()) ); if ( m_socket->isClosed() ) { SCRIPT_LOG("TERMINATED"); return; } m_socket->start(); } QObject::connect( &scriptable, SIGNAL(requestApplicationQuit()), qApp, SLOT(quit()) ); QByteArray response; int exitCode; if ( m_args.length() <= Arguments::Rest ) { SCRIPT_LOG("Error: bad command syntax"); exitCode = CommandBadSyntax; } else { const QString cmd = getTextData( m_args.at(Arguments::Rest) ); #ifdef HAS_TESTS if ( cmd == "flush" && m_args.length() == Arguments::Rest + 2 ) { log( "flush ID: " + getTextData(m_args.at(Arguments::Rest + 1)), LogAlways ); scriptable.sendMessageToClient(QByteArray(), CommandFinished); return; } #endif QScriptValue fn = engine.globalObject().property(cmd); if ( !fn.isFunction() ) { SCRIPT_LOG("Error: unknown command"); const QString msg = Scriptable::tr("Name \"%1\" doesn't refer to a function.").arg(cmd); response = createLogMessage(msg, LogError).toUtf8(); exitCode = CommandError; } else { /* Special arguments: * "-" read this argument from stdin * "--" read all following arguments without control sequences */ QScriptValueList fnArgs; bool readRaw = false; for ( int i = Arguments::Rest + 1; i < m_args.length(); ++i ) { const QByteArray &arg = m_args.at(i); if (!readRaw && arg == "--") { readRaw = true; } else { const QScriptValue value = readRaw || arg != "-" ? scriptable.newByteArray(arg) : scriptable.input(); fnArgs.append(value); } } engine.evaluate(m_pluginScript); QScriptValue result = fn.call(QScriptValue(), fnArgs); if ( engine.hasUncaughtException() ) { const QString exceptionText = QString("%1\n--- backtrace ---\n%2\n--- end backtrace ---") .arg( engine.uncaughtException().toString(), engine.uncaughtExceptionBacktrace().join("\n") ); SCRIPT_LOG( QString("Error: Exception in command \"%1\": %2") .arg(cmd, exceptionText) ); response = createLogMessage(exceptionText, LogError).toUtf8(); exitCode = CommandError; } else { response = serializeScriptValue(result); exitCode = CommandFinished; } } } if (exitCode == CommandFinished && hasData) Action::setData(id, scriptable.data()); scriptable.sendMessageToClient(response, exitCode); SCRIPT_LOG("DONE"); }
void ScriptableWorker::run() { MONITOR_LOG("starting"); QScriptEngine engine; ScriptableProxy proxy(m_wnd); Scriptable scriptable(&proxy); scriptable.initEngine( &engine, QString::fromUtf8(m_args.at(Arguments::CurrentPath)), m_args.at(Arguments::ActionId) ); if (m_socket) { QObject::connect( &scriptable, SIGNAL(sendMessage(QByteArray,int)), m_socket, SLOT(sendMessage(QByteArray,int)) ); QObject::connect( m_socket, SIGNAL(messageReceived(QByteArray,int)), &scriptable, SLOT(setInput(QByteArray)) ); QObject::connect( m_socket, SIGNAL(disconnected()), &scriptable, SLOT(abort()) ); QObject::connect( &scriptable, SIGNAL(destroyed()), m_socket, SLOT(deleteAfterDisconnected()) ); if ( m_socket->isClosed() ) { MONITOR_LOG("terminated"); return; } m_socket->start(); } QObject::connect( &scriptable, SIGNAL(requestApplicationQuit()), qApp, SLOT(quit()) ); QByteArray response; int exitCode; if ( m_args.length() <= Arguments::Rest ) { MONITOR_LOG("Error: bad command syntax"); exitCode = CommandBadSyntax; } else { const QString cmd = QString::fromUtf8( m_args.at(Arguments::Rest) ); if ( hasLogLevel(LogDebug) ) { MONITOR_LOG("Client arguments:"); for (int i = Arguments::Rest; i < m_args.length(); ++i) MONITOR_LOG( " " + QString::fromUtf8(m_args.at(i)) ); } #ifdef HAS_TESTS if ( cmd == "flush" && m_args.length() == Arguments::Rest + 2 ) { MONITOR_LOG( "flush ID: " + QString::fromUtf8(m_args.at(Arguments::Rest + 1)) ); scriptable.sendMessageToClient(QByteArray(), CommandFinished); return; } #endif QScriptValue fn = engine.globalObject().property(cmd); if ( !fn.isFunction() ) { MONITOR_LOG("Error: unknown command"); response = createLogMessage("CopyQ client", Scriptable::tr("Name \"%1\" doesn't refer to a function.") .arg(cmd), LogError).toUtf8(); exitCode = CommandError; } else { QScriptValueList fnArgs; for ( int i = Arguments::Rest + 1; i < m_args.length(); ++i ) fnArgs.append( scriptable.newByteArray(m_args.at(i)) ); QScriptValue result = fn.call(QScriptValue(), fnArgs); if ( engine.hasUncaughtException() ) { const QString exceptionText = engine.uncaughtException().toString(); MONITOR_LOG( QString("Error: exception in command \"%1\": %2") .arg(cmd).arg(exceptionText) ); response = createLogMessage("CopyQ client", exceptionText, LogError).toUtf8(); exitCode = CommandError; } else { response = serializeScriptValue(result); exitCode = CommandFinished; } } } scriptable.sendMessageToClient(response, exitCode); MONITOR_LOG("finished"); }