Skip to content

Commit

Permalink
Merge pull request #419 from p4p1/dev
Browse files Browse the repository at this point in the history
Added scroll to Widget and Dialog
  • Loading branch information
S4ntiagoP authored Oct 20, 2023
2 parents e1adedb + 4e40156 commit dfabe00
Show file tree
Hide file tree
Showing 7 changed files with 248 additions and 42 deletions.
1 change: 1 addition & 0 deletions client/Include/Havoc/PythonApi/PythonApi.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ namespace PythonAPI
{
PY_FUNCTION( Load )
PY_FUNCTION( GetDemons )
PY_FUNCTION( GetListeners )
PY_FUNCTION_KW( RegisterCommand )
PY_FUNCTION( RegisterModule )
PY_FUNCTION( RegisterCallback )
Expand Down
12 changes: 10 additions & 2 deletions client/Include/Havoc/PythonApi/UI/PyDialogClass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@
#include <global.hpp>

#include <QVBoxLayout>
#include <QScrollArea>
#include <QDialog>
#include <QLabel>
#include <QPushButton>
#include <QCheckBox>
#include <QLineEdit>
#include <QCalendarWidget>
#include <QDial>
#include <QSlider>

typedef struct
{

QDialog* window;
QVBoxLayout* layout;
QDialog* window;
QVBoxLayout* layout;
QScrollArea* scroll;
QWidget* root;
QVBoxLayout* root_layout;

} PyDialogQWindow, *PPyDialogQWindow;

Expand Down Expand Up @@ -49,5 +55,7 @@ PyObject* DialogClass_addLineedit( PPyDialogClass self, PyObject *args );
PyObject* DialogClass_addCalendar( PPyDialogClass self, PyObject *args );
PyObject* DialogClass_replaceLabel( PPyDialogClass self, PyObject *args );
PyObject* DialogClass_addImage( PPyDialogClass self, PyObject *args );
PyObject* DialogClass_addDial( PPyDialogClass self, PyObject *args );
PyObject* DialogClass_addSlider( PPyDialogClass self, PyObject *args );

#endif
12 changes: 10 additions & 2 deletions client/Include/Havoc/PythonApi/UI/PyWidgetClass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@
#include <QCheckBox>
#include <QLineEdit>
#include <QCalendarWidget>
#include <QScrollArea>
#include <QDial>
#include <QSlider>

typedef struct
{

QWidget* window;
QVBoxLayout* layout;
QWidget* window;
QVBoxLayout* layout;
QScrollArea* scroll;
QWidget* root;
QVBoxLayout* root_layout;

} PyWidgetQWindow, *PPyWidgetQWindow;

Expand Down Expand Up @@ -49,5 +55,7 @@ PyObject* WidgetClass_addCalendar( PPyWidgetClass self, PyObject *args );
PyObject* WidgetClass_replaceLabel( PPyWidgetClass self, PyObject *args );
PyObject* WidgetClass_clear( PPyWidgetClass self, PyObject *args );
PyObject* WidgetClass_addImage( PPyWidgetClass self, PyObject *args );
PyObject* WidgetClass_addDial( PPyWidgetClass self, PyObject *args );
PyObject* WidgetClass_addSlider( PPyWidgetClass self, PyObject *args );

#endif
17 changes: 17 additions & 0 deletions client/Source/Havoc/PythonApi/Havoc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ namespace PythonAPI::Havoc
PyMethodDef PyMethode_Havoc[] = {
{ "LoadScript", PythonAPI::Havoc::Core::Load, METH_VARARGS, "load python script" },
{ "GetDemons", PythonAPI::Havoc::Core::GetDemons, METH_VARARGS, "get list of demon ID's" },
{ "GetListeners", PythonAPI::Havoc::Core::GetListeners, METH_VARARGS, "get list of Listeners" },
{ "RegisterCommand", ( PyCFunction ) PythonAPI::Havoc::Core::RegisterCommand, METH_VARARGS | METH_KEYWORDS, "register a command/alias" },
{ "RegisterModule", PythonAPI::Havoc::Core::RegisterModule, METH_VARARGS, "register a module" },
{ "RegisterCallback", PythonAPI::Havoc::Core::RegisterCallback, METH_VARARGS, "register a callback" },
Expand Down Expand Up @@ -82,6 +83,22 @@ PyObject* PythonAPI::Havoc::Core::Load( PyObject *self, PyObject *args )
Py_RETURN_TRUE;
}

PyObject* PythonAPI::Havoc::Core::GetListeners( PyObject *self, PyObject *args )
{
auto Listeners = HavocX::Teamserver.Listeners;
uint32_t NumberOfSessions = Listeners.size();
PyObject* ListenerObjects = PyList_New( NumberOfSessions );
PyObject* ListenerID = NULL;

for ( int i = 0; i < NumberOfSessions; ++i )
{
ListenerID = Py_BuildValue( "s", Listeners[ i ].Name.c_str() );
PyList_SetItem( ListenerObjects, i, ListenerID );
}

return ListenerObjects;
}

PyObject* PythonAPI::Havoc::Core::GetDemons( PyObject *self, PyObject *args )
{
auto DemonSessions = HavocX::Teamserver.Sessions;
Expand Down
4 changes: 2 additions & 2 deletions client/Source/Havoc/PythonApi/PyAgentClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ PyObject* AgentClass_Command( PPyAgentClass self, PyObject *args )

if ( ! PyArg_ParseTuple( args, "ssO", &TaskID, &Name, &CommandArg ) )
Py_RETURN_NONE;

CommandLen = PyBytes_GET_SIZE( CommandArg );
CommandArg = PyBytes_AS_STRING( CommandArg );
Command = QByteArray( CommandArg, CommandLen );
Expand All @@ -179,4 +179,4 @@ PyObject* AgentClass_Command( PPyAgentClass self, PyObject *args )
}

Py_RETURN_NONE;
}
}
125 changes: 107 additions & 18 deletions client/Source/Havoc/PythonApi/UI/PyDialogClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ PyMethodDef PyDialogClass_methods[] = {
{ "addCombobox", ( PyCFunction ) DialogClass_addCombobox, METH_VARARGS, "Insert a checkbox in the window" },
{ "addLineedit", ( PyCFunction ) DialogClass_addLineedit, METH_VARARGS, "Insert a Line edit in the window" },
{ "addCalendar", ( PyCFunction ) DialogClass_addCalendar, METH_VARARGS, "Insert a Calendar in the window" },
{ "addDial", ( PyCFunction ) DialogClass_addDial, METH_VARARGS, "Insert a Dial in the window" },
{ "addSlider", ( PyCFunction ) DialogClass_addSlider, METH_VARARGS, "Insert a Slider in the window" },
{ "replaceLabel", ( PyCFunction ) DialogClass_replaceLabel, METH_VARARGS, "Replace a label with supplied text" },
{ "clear", ( PyCFunction ) DialogClass_clear, METH_VARARGS, "clear the dialog" },

Expand Down Expand Up @@ -83,40 +85,69 @@ PyTypeObject PyDialogClass_Type = {

void DialogClass_dealloc( PPyDialogClass self )
{
Py_XDECREF( self->title );
delete self->DialogWindow->window;
free(self->DialogWindow);

Py_TYPE( self )->tp_free( ( PyObject* ) self );
if (self) {
if (self->title)
Py_XDECREF( self->title );
if (self->DialogWindow && self->DialogWindow->window)
delete self->DialogWindow->window;
if (self->DialogWindow)
free(self->DialogWindow);
Py_TYPE( self )->tp_free( ( PyObject* ) self );
}
}

PyObject* DialogClass_new( PyTypeObject *type, PyObject *args, PyObject *kwds )
{
PPyDialogClass self;

self = ( PPyDialogClass ) PyType_Type.tp_alloc( type, 0 );

if (self == NULL)
return NULL;
self->DialogWindow = NULL;
self->title = NULL;
self->DialogWindow = (PPyDialogQWindow)malloc(sizeof(PyDialogQWindow));
if (self->DialogWindow == NULL) {
Py_TYPE( self )->tp_free( ( PyObject* ) self );
return NULL;
}
self->DialogWindow->window = NULL;
self->DialogWindow->layout = NULL;
self->DialogWindow->scroll = NULL;
self->DialogWindow->root = NULL;
self->DialogWindow->root_layout = NULL;
return ( PyObject* ) self;
}

int DialogClass_init( PPyDialogClass self, PyObject *args, PyObject *kwds )
{
if ( PyType_Type.tp_init( ( PyObject* ) self, args, kwds ) < 0 )
return -1;

char* title = NULL;
const char* kwdlist[] = { "title", NULL };
char* title = NULL;
PyObject* scrollable = NULL;
int width = 400;
int height = 300;
const char* kwdlist[] = { "title", "scrollable", "width", "height", NULL };

if ( ! PyArg_ParseTupleAndKeywords( args, kwds, "s", const_cast<char**>(kwdlist), &title ) )
if ( ! PyArg_ParseTupleAndKeywords( args, kwds, "s|Oii", const_cast<char**>(kwdlist), &title, &scrollable, &width, &height) )
return -1;
AllocMov( self->title, title, strlen(title) );
self->DialogWindow = (PPyDialogQWindow)malloc(sizeof(PyDialogQWindow));
if (self->DialogWindow == NULL)
return -1;

self->DialogWindow->window = new QDialog(HavocX::HavocUserInterface->HavocWindow);
self->DialogWindow->window->setWindowTitle(title);
self->DialogWindow->layout = new QVBoxLayout(self->DialogWindow->window);
self->DialogWindow->window->resize(width, height);

self->DialogWindow->root = new QWidget();
self->DialogWindow->layout = new QVBoxLayout(self->DialogWindow->root);

if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True) {
self->DialogWindow->scroll = new QScrollArea(self->DialogWindow->window);
self->DialogWindow->scroll->setWidgetResizable(true);
self->DialogWindow->scroll->setWidget(self->DialogWindow->root);
}

self->DialogWindow->root_layout = new QVBoxLayout(self->DialogWindow->window);
if (scrollable && PyBool_Check(scrollable) && scrollable == Py_True)
self->DialogWindow->root_layout->addWidget(self->DialogWindow->scroll);
else
self->DialogWindow->root_layout->addWidget(self->DialogWindow->root);
return 0;
}

Expand Down Expand Up @@ -162,9 +193,10 @@ PyObject* DialogClass_addImage( PPyDialogClass self, PyObject *args )
PyObject* DialogClass_addButton( PPyDialogClass self, PyObject *args )
{
char *text = nullptr;
char *style = nullptr;
PyObject* button_callback = nullptr;

if( !PyArg_ParseTuple( args, "sO", &text, &button_callback) )
if( !PyArg_ParseTuple( args, "sO|s", &text, &button_callback, &style) )
{
Py_RETURN_NONE;
}
Expand All @@ -174,6 +206,8 @@ PyObject* DialogClass_addButton( PPyDialogClass self, PyObject *args )
return NULL;
}
QPushButton* button = new QPushButton(text, self->DialogWindow->window);
if (style)
button->setStyleSheet(style);
self->DialogWindow->layout->addWidget(button);
QObject::connect(button, &QPushButton::clicked, self->DialogWindow->window, [button_callback]() {
PyObject_CallFunctionObjArgs(button_callback, nullptr);
Expand All @@ -185,9 +219,10 @@ PyObject* DialogClass_addButton( PPyDialogClass self, PyObject *args )
PyObject* DialogClass_addCheckbox( PPyDialogClass self, PyObject *args )
{
char *text = nullptr;
char *style = nullptr;
PyObject* checkbox_callback = nullptr;

if( !PyArg_ParseTuple( args, "sO", &text, &checkbox_callback) )
if( !PyArg_ParseTuple( args, "sO|s", &text, &checkbox_callback, &style) )
{
Py_RETURN_NONE;
}
Expand All @@ -197,6 +232,8 @@ PyObject* DialogClass_addCheckbox( PPyDialogClass self, PyObject *args )
return NULL;
}
QCheckBox* checkbox = new QCheckBox(text, self->DialogWindow->window);
if (style)
checkbox->setStyleSheet(style);
self->DialogWindow->layout->addWidget(checkbox);
QObject::connect(checkbox, &QCheckBox::clicked, self->DialogWindow->window, [checkbox_callback]() {
PyObject_CallFunctionObjArgs(checkbox_callback, nullptr);
Expand Down Expand Up @@ -286,6 +323,58 @@ PyObject* DialogClass_addCalendar( PPyDialogClass self, PyObject *args )
Py_RETURN_NONE;
}

PyObject* DialogClass_addDial( PPyDialogClass self, PyObject *args )
{
PyObject* cal_callback = nullptr;

if( !PyArg_ParseTuple( args, "O", &cal_callback) )
{
Py_RETURN_NONE;
}
if ( !PyCallable_Check(cal_callback) )
{
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}

QDial* dial = new QDial(self->DialogWindow->window);
self->DialogWindow->layout->addWidget(dial);
QObject::connect(dial, &QDial::valueChanged, self->DialogWindow->window, [cal_callback](long value) {
PyObject* pyLong = PyLong_FromLong(value);
PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);
});
Py_RETURN_NONE;
}

PyObject* DialogClass_addSlider( PPyDialogClass self, PyObject *args )
{
PyObject* cal_callback = nullptr;
PyObject* vertical = nullptr;

if( !PyArg_ParseTuple( args, "O|O", &cal_callback, &vertical) )
{
Py_RETURN_NONE;
}
if ( !PyCallable_Check(cal_callback) )
{
PyErr_SetString(PyExc_TypeError, "parameter must be callable");
return NULL;
}

QSlider* slider = nullptr;
if (vertical && PyBool_Check(vertical) && vertical == Py_True) {
slider = new QSlider(Qt::Vertical);
} else {
slider = new QSlider(Qt::Horizontal);
}
self->DialogWindow->layout->addWidget(slider);
QObject::connect(slider, &QSlider::valueChanged, self->DialogWindow->window, [cal_callback](long value) {
PyObject* pyLong = PyLong_FromLong(value);
PyObject_CallFunctionObjArgs(cal_callback, pyLong, nullptr);
});
Py_RETURN_NONE;
}

PyObject* DialogClass_replaceLabel( PPyDialogClass self, PyObject *args )
{
char* to_find = NULL;
Expand Down
Loading

0 comments on commit dfabe00

Please sign in to comment.