<commit_before>/*
 * Copyright (C) 2006,2007  <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include "qca_support.h"

#include "qpipe.h"
#include "qca_safeobj.h"

#include <QPointer>
#include <QTextCodec>
#include <QMutex>

#ifdef Q_OS_WIN
# include <windows.h>
#else
# ifdef Q_OS_ANDROID
#  include <termios.h>
# else
#  include <sys/termios.h>
# endif
# include <unistd.h>
# include <fcntl.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#define CONSOLEPROMPT_INPUT_MAX 56

Q_DECLARE_METATYPE(QCA::SecureArray)

namespace QCA {

//----------------------------------------------------------------------------
// ConsoleWorker
//----------------------------------------------------------------------------
class ConsoleWorker : public QObject
{
	Q_OBJECT
private:
	QPipeEnd in, out;
	bool started;
	QByteArray in_left, out_left;

public:
	ConsoleWorker(QObject *parent = 0) : QObject(parent), in(this), out(this)
	{
		started = false;
	}

	~ConsoleWorker()
	{
		stop();
	}

	void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
	{
		Q_ASSERT(!started);

		if(in_id != INVALID_Q_PIPE_ID)
		{
			in.take(in_id, QPipeDevice::Read);
			connect(&in, SIGNAL(readyRead()), SLOT(in_readyRead()));
			connect(&in, SIGNAL(closed()), SLOT(in_closed()));
			connect(&in, SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(in_error(QCA::QPipeEnd::Error)));
			in.enable();
		}

		if(out_id != INVALID_Q_PIPE_ID)
		{
			out.take(out_id, QPipeDevice::Write);
			connect(&out, SIGNAL(bytesWritten(int)), SLOT(out_bytesWritten(int)));
			connect(&out, SIGNAL(closed()), SLOT(out_closed()));
			out.enable();
		}

		started = true;
	}

	void stop()
	{
		if(!started)
			return;

		if(in.isValid())
			in.finalizeAndRelease();
		if(out.isValid())
			out.release();

		in_left = in.read();
		out_left = out.takeBytesToWrite();

		started = false;
	}

public slots:
	bool isValid() const
	{
		return in.isValid();
	}

	void setSecurityEnabled(bool enabled)
	{
		if(in.isValid())
			in.setSecurityEnabled(enabled);
		if(out.isValid())
			out.setSecurityEnabled(enabled);
	}

	QByteArray read(int bytes = -1)
	{
		return in.read(bytes);
	}

	void write(const QByteArray &a)
	{
		out.write(a);
	}

	QCA::SecureArray readSecure(int bytes = -1)
	{
		return in.readSecure(bytes);
	}

	void writeSecure(const QCA::SecureArray &a)
	{
		out.writeSecure(a);
	}

	void closeOutput()
	{
		out.close();
	}

	int bytesAvailable() const
	{
		return in.bytesAvailable();
	}

	int bytesToWrite() const
	{
		return in.bytesToWrite();
	}

public:
	QByteArray takeBytesToRead()
	{
		QByteArray a = in_left;
		in_left.clear();
		return a;
	}

	QByteArray takeBytesToWrite()
	{
		QByteArray a = out_left;
		out_left.clear();
		return a;
	}

signals:
	void readyRead();
	void bytesWritten(int bytes);
	void inputClosed();
	void outputClosed();

private slots:
	void in_readyRead()
	{
		emit readyRead();
	}

	void out_bytesWritten(int bytes)
	{
		emit bytesWritten(bytes);
	}

	void in_closed()
	{
		emit inputClosed();
	}

	void in_error(QCA::QPipeEnd::Error)
	{
		emit inputClosed();
	}

	void out_closed()
	{
		emit outputClosed();
	}
};

//----------------------------------------------------------------------------
// ConsoleThread
//----------------------------------------------------------------------------
class ConsoleThread : public SyncThread
{
	Q_OBJECT
public:
	ConsoleWorker *worker;
	Q_PIPE_ID _in_id, _out_id;
	QByteArray in_left, out_left;
	QMutex call_mutex;

	ConsoleThread(QObject *parent = 0) : SyncThread(parent)
	{
		qRegisterMetaType<SecureArray>("QCA::SecureArray");
	}

	~ConsoleThread()
	{
		stop();
	}

	void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
	{
		_in_id = in_id;
		_out_id = out_id;
		SyncThread::start();
	}

	void stop()
	{
		SyncThread::stop();
	}

	QVariant mycall(QObject *obj, const char *method, const QVariantList &args = QVariantList())
	{
		QVariant ret;
		bool ok;

		call_mutex.lock();
		ret = call(obj, method, args, &ok);
		call_mutex.unlock();

		Q_ASSERT(ok);
		if(!ok)
		{
			fprintf(stderr, "QCA: ConsoleWorker call [%s] failed.\n", method);
			abort();
			return QVariant();
		}
		return ret;
	}

	bool isValid()
	{
		return mycall(worker, "isValid").toBool();
	}

	void setSecurityEnabled(bool enabled)
	{
		mycall(worker, "setSecurityEnabled", QVariantList() << enabled);
	}

	QByteArray read(int bytes = -1)
	{
		return mycall(worker, "read", QVariantList() << bytes).toByteArray();
	}

	void write(const QByteArray &a)
	{
		mycall(worker, "write", QVariantList() << a);
	}

	SecureArray readSecure(int bytes = -1)
	{
#if QT_VERSION >= 0x050000
		return mycall(worker, "readSecure", QVariantList() << bytes).value<SecureArray>();
#else
		return qVariantValue<SecureArray>(mycall(worker, "readSecure", QVariantList() << bytes));
#endif
	}

	void writeSecure(const SecureArray &a)
	{
		mycall(worker, "writeSecure", QVariantList() << qVariantFromValue<SecureArray>(a));
	}

	void closeOutput()
	{
		mycall(worker, "closeOutput");
	}

	int bytesAvailable()
	{
		return mycall(worker, "bytesAvailable").toInt();
	}

	int bytesToWrite()
	{
		return mycall(worker, "bytesToWrite").toInt();
	}

	QByteArray takeBytesToRead()
	{
		QByteArray a = in_left;
		in_left.clear();
		return a;
	}

	QByteArray takeBytesToWrite()
	{
		QByteArray a = out_left;<commit_msg>Don't use obsolete qVariantFromValue<commit_after>/*
 * Copyright (C) 2006,2007  <NAME> <<EMAIL>>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 * 02110-1301  USA
 *
 */

#include "qca_support.h"

#include "qpipe.h"
#include "qca_safeobj.h"

#include <QPointer>
#include <QTextCodec>
#include <QMutex>

#ifdef Q_OS_WIN
# include <windows.h>
#else
# ifdef Q_OS_ANDROID
#  include <termios.h>
# else
#  include <sys/termios.h>
# endif
# include <unistd.h>
# include <fcntl.h>
#endif

#include <stdio.h>
#include <stdlib.h>

#define CONSOLEPROMPT_INPUT_MAX 56

Q_DECLARE_METATYPE(QCA::SecureArray)

namespace QCA {

//----------------------------------------------------------------------------
// ConsoleWorker
//----------------------------------------------------------------------------
class ConsoleWorker : public QObject
{
	Q_OBJECT
private:
	QPipeEnd in, out;
	bool started;
	QByteArray in_left, out_left;

public:
	ConsoleWorker(QObject *parent = 0) : QObject(parent), in(this), out(this)
	{
		started = false;
	}

	~ConsoleWorker()
	{
		stop();
	}

	void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
	{
		Q_ASSERT(!started);

		if(in_id != INVALID_Q_PIPE_ID)
		{
			in.take(in_id, QPipeDevice::Read);
			connect(&in, SIGNAL(readyRead()), SLOT(in_readyRead()));
			connect(&in, SIGNAL(closed()), SLOT(in_closed()));
			connect(&in, SIGNAL(error(QCA::QPipeEnd::Error)), SLOT(in_error(QCA::QPipeEnd::Error)));
			in.enable();
		}

		if(out_id != INVALID_Q_PIPE_ID)
		{
			out.take(out_id, QPipeDevice::Write);
			connect(&out, SIGNAL(bytesWritten(int)), SLOT(out_bytesWritten(int)));
			connect(&out, SIGNAL(closed()), SLOT(out_closed()));
			out.enable();
		}

		started = true;
	}

	void stop()
	{
		if(!started)
			return;

		if(in.isValid())
			in.finalizeAndRelease();
		if(out.isValid())
			out.release();

		in_left = in.read();
		out_left = out.takeBytesToWrite();

		started = false;
	}

public slots:
	bool isValid() const
	{
		return in.isValid();
	}

	void setSecurityEnabled(bool enabled)
	{
		if(in.isValid())
			in.setSecurityEnabled(enabled);
		if(out.isValid())
			out.setSecurityEnabled(enabled);
	}

	QByteArray read(int bytes = -1)
	{
		return in.read(bytes);
	}

	void write(const QByteArray &a)
	{
		out.write(a);
	}

	QCA::SecureArray readSecure(int bytes = -1)
	{
		return in.readSecure(bytes);
	}

	void writeSecure(const QCA::SecureArray &a)
	{
		out.writeSecure(a);
	}

	void closeOutput()
	{
		out.close();
	}

	int bytesAvailable() const
	{
		return in.bytesAvailable();
	}

	int bytesToWrite() const
	{
		return in.bytesToWrite();
	}

public:
	QByteArray takeBytesToRead()
	{
		QByteArray a = in_left;
		in_left.clear();
		return a;
	}

	QByteArray takeBytesToWrite()
	{
		QByteArray a = out_left;
		out_left.clear();
		return a;
	}

signals:
	void readyRead();
	void bytesWritten(int bytes);
	void inputClosed();
	void outputClosed();

private slots:
	void in_readyRead()
	{
		emit readyRead();
	}

	void out_bytesWritten(int bytes)
	{
		emit bytesWritten(bytes);
	}

	void in_closed()
	{
		emit inputClosed();
	}

	void in_error(QCA::QPipeEnd::Error)
	{
		emit inputClosed();
	}

	void out_closed()
	{
		emit outputClosed();
	}
};

//----------------------------------------------------------------------------
// ConsoleThread
//----------------------------------------------------------------------------
class ConsoleThread : public SyncThread
{
	Q_OBJECT
public:
	ConsoleWorker *worker;
	Q_PIPE_ID _in_id, _out_id;
	QByteArray in_left, out_left;
	QMutex call_mutex;

	ConsoleThread(QObject *parent = 0) : SyncThread(parent)
	{
		qRegisterMetaType<SecureArray>("QCA::SecureArray");
	}

	~ConsoleThread()
	{
		stop();
	}

	void start(Q_PIPE_ID in_id, Q_PIPE_ID out_id)
	{
		_in_id = in_id;
		_out_id = out_id;
		SyncThread::start();
	}

	void stop()
	{
		SyncThread::stop();
	}

	QVariant mycall(QObject *obj, const char *method, const QVariantList &args = QVariantList())
	{
		QVariant ret;
		bool ok;

		call_mutex.lock();
		ret = call(obj, method, args, &ok);
		call_mutex.unlock();

		Q_ASSERT(ok);
		if(!ok)
		{
			fprintf(stderr, "QCA: ConsoleWorker call [%s] failed.\n", method);
			abort();
			return QVariant();
		}
		return ret;
	}

	bool isValid()
	{
		return mycall(worker, "isValid").toBool();
	}

	void setSecurityEnabled(bool enabled)
	{
		mycall(worker, "setSecurityEnabled", QVariantList() << enabled);
	}

	QByteArray read(int bytes = -1)
	{
		return mycall(worker, "read", QVariantList() << bytes).toByteArray();
	}

	void write(const QByteArray &a)
	{
		mycall(worker, "write", QVariantList() << a);
	}

	SecureArray readSecure(int bytes = -1)
	{
#if QT_VERSION >= 0x050000
		return mycall(worker, "readSecure", QVariantList() << bytes).value<SecureArray>();
#else
		return qVariantValue<SecureArray>(mycall(worker, "readSecure", QVariantList() << bytes));
#endif
	}

	void writeSecure(const SecureArray &a)
	{
		mycall(worker, "writeSecure", QVariantList() << QVariant::fromValue<SecureArray>(a));
	}

	void closeOutput()
	{
		mycall(worker, "closeOutput");
	}

	int bytesAvailable()
	{
		return mycall(worker, "bytesAvailable").toInt();
	}

	int bytesToWrite()
	{
		return mycall(worker, "bytesToWrite").toInt();
	}

	QByteArray takeBytesToRead()
	{
		QByteArray a = in_left;
		in_left.clear();
		return a;
	}

	QByteArray takeBytesToWrite()
	{
		QByteArray a = out_left;
{'fraction_non_alphanumeric': 0.1832207488950046, 'fraction_numerical': 0.00600450337753315, 'mean_word_length': 3.307471264367816, 'pattern_counts': {'":': 0, '<': 61, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7425951', 'n_tokens_mistral': 4621, 'n_tokens_neox': 4243, 'n_words': 980}