diff --git a/common/src/include/lib3270/ipc-glib.h b/common/src/include/lib3270/ipc-glib.h index 7412103..85a6fde 100644 --- a/common/src/include/lib3270/ipc-glib.h +++ b/common/src/include/lib3270/ipc-glib.h @@ -75,7 +75,7 @@ void ipc3270_response_append_int32(GObject *object, gint32 value); void ipc3270_response_append_uint32(GObject *object, guint32 value); - void ipc3270_response_append_3270_string(GObject *object, const char *text, GError **error); + void ipc3270_response_append_string(GObject *object, const gchar *text); gboolean ipc3270_response_has_values(GObject *object); GVariant * ipc3270_response_steal_value(GObject *object); @@ -96,7 +96,7 @@ void ipc3270_export_object(GObject *object, const char *name, GError **error); /** - * @brief Convert UTF-8 string to lib3270 charset. + * @brief Convert from native charset to lib3270 charset. * * @param object ipc3270 Object. * @param string UTF-8 string to convert. @@ -105,7 +105,7 @@ * @return Converted string in lib3270 charset. * */ - gchar * ipc3270_convert_output_string(GObject *object, const gchar *string, GError **error); + gchar * ipc3270_convert_to_3270(GObject *object, const gchar *string, GError **error); /** * @brief Convert lib3270 received string to UTF-8. @@ -117,7 +117,7 @@ * @return The string converted to UTF-8. * */ - gchar * ipc3270_convert_input_string(GObject *object, const gchar *string, GError **error); + gchar * ipc3270_convert_from_3270(GObject *object, const gchar *string, GError **error); /** * @brief Create a GVariant from a lib3270 string. @@ -140,7 +140,7 @@ void ipc3270_set_error(GObject *object, int errcode, GError **error); - void ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *request, GObject *response, GError **error); + int ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *request, GObject *response, GError **error); gboolean ipc3270_set_property(GObject *object, const gchar *property_name, GVariant *value, GError **error); GVariant * ipc3270_get_property(GObject *object, const gchar *property_name, GError **error); diff --git a/server/pw3270-plugin-ipc.cbp b/server/pw3270-plugin-ipc.cbp index 7b92da2..01092c3 100644 --- a/server/pw3270-plugin-ipc.cbp +++ b/server/pw3270-plugin-ipc.cbp @@ -82,9 +82,25 @@ + + + + + + + + + + + diff --git a/server/src/core/linux/gobject.c b/server/src/core/linux/gobject.c index 3f08a64..326be92 100644 --- a/server/src/core/linux/gobject.c +++ b/server/src/core/linux/gobject.c @@ -62,6 +62,8 @@ static void ipc3270_finalize(GObject *object) { v3270_set_session_name(ipc->terminal,widget_name); lib3270_set_session_id(ipc->hSession, 0); + g_free(ipc->charset); + G_OBJECT_CLASS(ipc3270_parent_class)->finalize(object); } @@ -82,6 +84,12 @@ static void ipc3270_init(ipc3270 *object) { debug("%s",__FUNCTION__); object->error_domain = g_quark_from_static_string(PACKAGE_NAME); + // Get charset + const gchar * scharset = NULL; + g_get_charset(&scharset); + + object->charset = g_strdup(scharset); + } GObject * ipc3270_new() { @@ -138,8 +146,8 @@ void ipc3270_add_terminal_introspection(GString *introspection) { " " \ " " \ " " \ - " " \ - " " \ + " " \ + " " \ " " \ " " \ " " \ @@ -247,10 +255,18 @@ H3270 * ipc3270_get_session(GObject *object) { } void ipc3270_set_error(GObject *object, int errcode, GError **error) { - g_set_error(error,IPC3270(object)->error_domain,errcode,"%s",strerror(errcode)); + if(!*error) + g_set_error(error,IPC3270(object)->error_domain,errcode,"%s",strerror(errcode)); } GQuark ipc3270_get_error_domain(GObject *object) { return IPC3270(object)->error_domain; } +gchar * ipc3270_convert_to_3270(GObject *object, const gchar *string, GError **error) { + return g_convert_with_fallback(string,-1,lib3270_get_display_charset(IPC3270(object)->hSession),IPC3270(object)->charset,"?",NULL,NULL,error); +} + +gchar * ipc3270_convert_from_3270(GObject *object, const gchar *string, GError **error) { + return g_convert_with_fallback(string,-1,IPC3270(object)->charset,lib3270_get_display_charset(IPC3270(object)->hSession),"?",NULL,NULL,error); +} diff --git a/server/src/core/linux/gobject.h b/server/src/core/linux/gobject.h index ee697f4..eb3a78c 100644 --- a/server/src/core/linux/gobject.h +++ b/server/src/core/linux/gobject.h @@ -64,6 +64,7 @@ } dbus; H3270 * hSession; + gchar * charset; GtkWidget * terminal; GQuark error_domain; }; diff --git a/server/src/core/methods/get.c b/server/src/core/methods/get.c new file mode 100644 index 0000000..600d067 --- /dev/null +++ b/server/src/core/methods/get.c @@ -0,0 +1,84 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#include "private.h" + +int ipc3270_method_get_string(GObject *session, GVariant *request, GObject *response, GError **error) { + + H3270 *hSession = ipc3270_get_session(session); + + lib3270_autoptr(char) text = NULL; + + switch(g_variant_n_children(request)) { + case 0: // No arguments + { + + } + break; + + case 3: // address, length, line-delimiter + { + gint addr; + guint len; + guchar lf; + + g_variant_get(request, "(iiy)", &addr, &len, &lf); + + text = lib3270_get_string_at_address(hSession, addr, len, lf); + + } + break; + + case 4: // row, col, length, line-delimiter + { + guint row,col,len; + guchar lf; + g_variant_get(request, "(uuuy)", &row, &col, &len, &lf); + + text = lib3270_get_string_at(hSession, row, col, len, lf); + + } + break; + + default: + return EINVAL; + } + + debug("text:\n%s\n",text); + + if(!text) + return errno; + + g_autofree gchar * converted = ipc3270_convert_from_3270(session,text,error); + ipc3270_response_append_string(response, converted); + + return 0; + +} + diff --git a/server/src/core/methods/methods.c b/server/src/core/methods/methods.c index 870b64b..2a41626 100644 --- a/server/src/core/methods/methods.c +++ b/server/src/core/methods/methods.c @@ -32,183 +32,60 @@ * */ -#include -#include -#include -#include +#include "private.h" #include #include -void ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *request, GObject *response, GError **error) { +int ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *request, GObject *response, GError **error) { - size_t ix; - H3270 * hSession = ipc3270_get_session(object); - - lib3270_trace_event(hSession,"Method %s called on session %c\n",method_name,lib3270_get_session_id(hSession)); - - debug("%s(%s)",__FUNCTION__,method_name); - - if(!g_ascii_strcasecmp(method_name,"getString")) - { - lib3270_autoptr(char) str = lib3270_get_string_at_address(hSession,0,-1,'\n'); - ipc3270_response_append_3270_string(response,str,error); - return; - } - else if(!g_ascii_strcasecmp(method_name,"setString")) - { - gchar *text = NULL; - g_variant_get(request, "(&s)", &text); - - g_autofree gchar * converted = ipc3270_convert_output_string(object, text, error); - if(lib3270_input_string(hSession,(const unsigned char *) converted, -1)) - { - // Failed! - debug("%s failed: %s",method_name,strerror(errno)); - ipc3270_set_error(object,errno,error); - return; - } - - // Suceeded - debug("%s Suceeds",method_name); - ipc3270_response_append_int32(response, 0); - return; - - } - else if(!g_ascii_strcasecmp(method_name,"setStringAt")) - { - guint row,col; - gchar *text = NULL; - g_variant_get(request, "(ii&s)", &row, &col, &text); - - g_autofree gchar * converted = ipc3270_convert_output_string(object, text, error); - if(lib3270_set_string_at(hSession,row,col,(const unsigned char *) converted) < 0) - { - // Failed! - ipc3270_set_error(object,errno,error); - return; - } - - // Suceeded - ipc3270_response_append_int32(response, 0); - return; - - } - else if(!g_ascii_strcasecmp(method_name,"getStringAt")) - { - guint row,col,len; - guchar lf; - g_variant_get(request, "(uuuy)", &row, &col, &len,&lf); - - lib3270_autoptr(char) str = lib3270_get_string_at(hSession, row, col, len, lf); - ipc3270_response_append_3270_string(response,str,error); - return; - - } - else if(!g_ascii_strcasecmp(method_name,"setStringAtAddress")) - { - gint addr; - gchar *text = NULL; - g_variant_get(request, "(i&s)", &addr, &text); + static const struct Methods { + const char *name; + int (*call)(GObject *session, GVariant *request, GObject *response, GError **error); + } methods[] = { - g_autofree gchar * converted = ipc3270_convert_output_string(object, text, error); - if(lib3270_set_string_at_address(hSession,addr,(unsigned char *) converted, -1) < 0) - { - // Failed! - ipc3270_set_error(object,errno,error); - return; - } + { "connect", ipc3270_method_connect }, + { "disconnect", ipc3270_method_disconnect }, - // Suceeded - ipc3270_response_append_int32(response, 0); - return; + { "wait", ipc3270_method_wait }, + { "waitforready", ipc3270_method_wait_for_ready }, + { "waitforupdate", ipc3270_method_wait_for_update }, - } - else if(!g_ascii_strcasecmp(method_name,"getStringAtAddress")) - { - gint addr; - guint len; - guchar lf; - g_variant_get(request, "(iuy)", &addr, &len, &lf); + { "getString", ipc3270_method_get_string }, + { "getStringAt", ipc3270_method_get_string }, + { "getStringAtAddress", ipc3270_method_get_string }, - debug("lf=%02x",(int) lf); + { "setString", ipc3270_method_set_string }, + { "setStringAt", ipc3270_method_set_string }, + { "setStringAtAddress", ipc3270_method_set_string }, - lib3270_autoptr(char) str = lib3270_get_string_at_address(hSession, addr, len, lf); - ipc3270_response_append_3270_string(response,str,error); - return; + { "getFieldAttribute", ipc3270_method_get_field_attribute }, + { "getFieldAttributeAt", ipc3270_method_get_field_attribute }, + { "getFieldAttributeAtAddress", ipc3270_method_get_field_attribute }, - } - else if(!g_ascii_strcasecmp(method_name,"waitforready")) - { - guint timeout = 1; - if(request) { - g_variant_get(request, "(u)", &timeout); - } - ipc3270_response_append_int32(response, lib3270_wait_for_ready(hSession,timeout)); - return; + }; - } - else if(!g_ascii_strcasecmp(method_name,"connect")) - { - gchar *text = NULL; - g_variant_get(request, "(&s)", &text); + size_t ix; + H3270 * hSession = ipc3270_get_session(object); - g_autofree gchar * converted = ipc3270_convert_output_string(object, text, error); - if(lib3270_connect_url(hSession,converted,0)) - { - // Failed! - ipc3270_set_error(object,errno,error); - return NULL; - } + lib3270_trace_event(hSession,"Method %s called on session %c\n",method_name,lib3270_get_session_id(hSession)); - // Suceeded - ipc3270_response_append_int32(response, 0); - return; + for(ix = 0; ix < G_N_ELEMENTS(methods); ix++) { - } - else if(!g_ascii_strcasecmp(method_name,"disconnect")) - { - if(lib3270_disconnect(hSession)) - { - // Failed! - ipc3270_set_error(object,errno,error); - return; - } + if(!g_ascii_strcasecmp(methods[ix].name,method_name)) { - // Suceeded - ipc3270_response_append_int32(response, 0); - return; + int rc = methods[ix].call(object,request,response,error); - } - else if(!g_ascii_strcasecmp(method_name,"getFieldAttributeAt")) - { - guint row,col; - g_variant_get(request, "(uu)", &row, &col); - ipc3270_response_append_int32(response, lib3270_get_field_attribute(hSession,lib3270_translate_to_address(hSession,row,col))); - return; - } - else if(!g_ascii_strcasecmp(method_name,"getFieldAttributeAtAddress")) - { - gint addr; - g_variant_get(request, "(i)", &addr); + if(rc) + ipc3270_set_error(object,rc,error); - ipc3270_response_append_int32(response, lib3270_get_field_attribute(hSession,addr)); - return; - } - else if(!g_ascii_strcasecmp(method_name,"waitForUpdate")) - { - guint timeout = 1; - if(request) { - g_variant_get(request, "(u)", &timeout); + return 0; } - - ipc3270_response_append_int32(response, lib3270_wait_for_update(hSession,timeout)); - return; } - // Check action table. + // Check actions table. const LIB3270_ACTION_ENTRY * actions = lib3270_get_action_table(); - for(ix = 0; actions[ix].name; ix++) - { + for(ix = 0; actions[ix].name; ix++) { + if(!g_ascii_strcasecmp(actions[ix].name,method_name)) { int rc = actions[ix].call(hSession); @@ -221,16 +98,16 @@ void ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *re // Suceeded ipc3270_response_append_int32(response, 0); - return; + return 0; } } - // Check int methods + // Check lib3270 internal methods const IPC_METHOD_INT_ARG * int_methods = ipc3270_get_int_arg_methods(); - for(ix = 0; int_methods[ix].name; ix++) - { + for(ix = 0; int_methods[ix].name; ix++) { + if(!g_ascii_strcasecmp(int_methods[ix].name,method_name)) { gint value; @@ -246,13 +123,13 @@ void ipc3270_method_call(GObject *object, const gchar *method_name, GVariant *re // Suceeded ipc3270_response_append_int32(response, 0); - return; + return 0; } } g_message("Unknown method \"%s\"",method_name); - ipc3270_set_error(object,ENOENT,error); + return ENOENT; } diff --git a/server/src/core/methods/network.c b/server/src/core/methods/network.c new file mode 100644 index 0000000..480dc87 --- /dev/null +++ b/server/src/core/methods/network.c @@ -0,0 +1,48 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#include "private.h" + +int ipc3270_method_connect(GObject *session, GVariant *request, GObject *response, GError **error) { + + gchar *text = NULL; + g_variant_get(request, "(&s)", &text); + + g_autofree gchar * converted = ipc3270_convert_to_3270(session,text,error); + + if(!*error) + return lib3270_connect_url(ipc3270_get_session(session),converted,0); + + return 0; + +} + +int ipc3270_method_disconnect(GObject *session, GVariant *request, GObject *response, GError **error) { + return lib3270_disconnect(ipc3270_get_session(session)); +} diff --git a/server/src/core/methods/private.h b/server/src/core/methods/private.h new file mode 100644 index 0000000..e840ab5 --- /dev/null +++ b/server/src/core/methods/private.h @@ -0,0 +1,57 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Referências: + * + * https://github.com/joprietoe/gdbus/blob/master/gdbus-example-server.c + * https://github.com/bratsche/glib/blob/master/gio/tests/gdbus-example-export.c + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#ifndef IPC_METHODS_H_INCLUDED + + #define IPC_METHODS_H_INCLUDED + + #include + #include + #include + + G_GNUC_INTERNAL int ipc3270_method_connect(GObject *session, GVariant *request, GObject *response, GError **error); + G_GNUC_INTERNAL int ipc3270_method_disconnect(GObject *session, GVariant *request, GObject *response, GError **error); + + G_GNUC_INTERNAL int ipc3270_method_get_string(GObject *session, GVariant *request, GObject *response, GError **error); + + G_GNUC_INTERNAL int ipc3270_method_set_string(GObject *session, GVariant *request, GObject *response, GError **error); + + G_GNUC_INTERNAL int ipc3270_method_wait(GObject *session, GVariant *request, GObject *response, GError **error); + G_GNUC_INTERNAL int ipc3270_method_wait_for_ready(GObject *session, GVariant *request, GObject *response, GError **error); + G_GNUC_INTERNAL int ipc3270_method_wait_for_update(GObject *session, GVariant *request, GObject *response, GError **error); + + G_GNUC_INTERNAL int ipc3270_method_get_field_attribute(GObject *session, GVariant *request, GObject *response, GError **error); + +#endif // IPC_METHODS_H_INCLUDED + diff --git a/server/src/core/methods/wait.c b/server/src/core/methods/wait.c new file mode 100644 index 0000000..d863205 --- /dev/null +++ b/server/src/core/methods/wait.c @@ -0,0 +1,54 @@ +/* + * "Software pw3270, desenvolvido com base nos códigos fontes do WC3270 e X3270 + * (Paul Mattes Paul.Mattes@usa.net), de emulação de terminal 3270 para acesso a + * aplicativos mainframe. Registro no INPI sob o nome G3270. + * + * Copyright (C) <2008> + * + * Este programa é software livre. Você pode redistribuí-lo e/ou modificá-lo sob + * os termos da GPL v.2 - Licença Pública Geral GNU, conforme publicado pela + * Free Software Foundation. + * + * Este programa é distribuído na expectativa de ser útil, mas SEM QUALQUER + * GARANTIA; sem mesmo a garantia implícita de COMERCIALIZAÇÃO ou de ADEQUAÇÃO + * A QUALQUER PROPÓSITO EM PARTICULAR. Consulte a Licença Pública Geral GNU para + * obter mais detalhes. + * + * Você deve ter recebido uma cópia da Licença Pública Geral GNU junto com este + * programa; se não, escreva para a Free Software Foundation, Inc., 51 Franklin + * St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Este programa está nomeado como - e possui - linhas de código. + * + * Contatos: + * + * perry.werneck@gmail.com (Alexandre Perry de Souza Werneck) + * erico.mendonca@gmail.com (Erico Mascarenhas Mendonça) + * + */ + +#include "private.h" + +int ipc3270_method_wait(GObject *session, GVariant *request, GObject *response, GError **error) { + + guint seconds = 1; + g_variant_get(request, "(u)", &seconds); + return lib3270_wait(ipc3270_get_session(session),seconds); + +} + +int ipc3270_method_wait_for_ready(GObject *session, GVariant *request, GObject *response, GError **error) { + + guint seconds = 1; + g_variant_get(request, "(u)", &seconds); + return lib3270_wait_for_ready(ipc3270_get_session(session),seconds); + +} + +int ipc3270_method_wait_for_update(GObject *session, GVariant *request, GObject *response, GError **error) { + + guint seconds = 1; + g_variant_get(request, "(u)", &seconds); + return lib3270_wait_for_update(ipc3270_get_session(session),seconds); + +} diff --git a/server/src/core/windows/gobject.c b/server/src/core/windows/gobject.c index 79acc41..0b56f98 100644 --- a/server/src/core/windows/gobject.c +++ b/server/src/core/windows/gobject.c @@ -107,3 +107,9 @@ GQuark ipc3270_get_error_domain(GObject *object) { return IPC3270(object)->error_domain; } +gchar * ipc3270_convert_to_3270(GObject *object, const gchar *string, GError **error) { + return g_convert_with_fallback(string,-1,ipc3270_get_display_charset(object),"UTF-8","?",NULL,NULL,error); +} + + + diff --git a/server/testscripts/getstring.sh b/server/testscripts/getstring.sh new file mode 100755 index 0000000..3c61129 --- /dev/null +++ b/server/testscripts/getstring.sh @@ -0,0 +1,12 @@ +#!/bin/bash +# +# https://stackoverflow.com/questions/48648952/set-get-property-using-dbus-send +# + +dbus-send \ + --session \ + --dest=br.com.bb.pw3270.a\ + --print-reply \ + "/br/com/bb/tn3270/session" \ + "br.com.bb.tn3270.session.getString" + -- libgit2 0.21.2