From 7113c142cb2c8917b86f4dd25ef0ec7e7d2ccc4e Mon Sep 17 00:00:00 2001 From: perry.werneck@gmail.com Date: Wed, 9 May 2012 14:53:53 +0000 Subject: [PATCH] Melhorando tratamento de erros SSL --- src/include/lib3270.h | 16 ++++++++++++++++ src/include/lib3270/popup.h | 10 ---------- src/include/lib3270/session.h | 13 +++++++++---- src/lib3270/XtGlue.c | 8 ++++++++ src/lib3270/init.c | 8 ++++++++ src/lib3270/screen.c | 12 ++++++++++++ src/lib3270/telnet.c | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------------------------------------------------------------------------------------------- src/pw3270/v3270/genmarshal | 1 + src/pw3270/v3270/iocallback.c | 6 +++--- src/pw3270/v3270/oia.c | 8 +++++--- src/pw3270/v3270/private.h | 2 ++ src/pw3270/v3270/v3270.h | 1 + src/pw3270/v3270/widget.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- src/pw3270/window.c | 38 +++++++++++++++++++++++++++++++------- 14 files changed, 249 insertions(+), 119 deletions(-) diff --git a/src/include/lib3270.h b/src/include/lib3270.h index 4c5e0ca..af079c5 100644 --- a/src/include/lib3270.h +++ b/src/include/lib3270.h @@ -211,6 +211,22 @@ LIB3270_CONNECTED_TN3270E /**< connected in TN3270E mode, 3270 mode */ } LIB3270_CSTATE; + + /** + * Notification message types. + * + */ + typedef enum _LIB3270_NOTIFY + { + LIB3270_NOTIFY_INFO, /**< Simple information dialog */ + LIB3270_NOTIFY_WARNING, + LIB3270_NOTIFY_ERROR, + LIB3270_NOTIFY_CRITICAL, /**< Critical error, user can abort application */ + + LIB3270_NOTIFY_USER /**< Reserved, always the last one */ + } LIB3270_NOTIFY; + + #ifdef __cplusplus extern "C" { #endif diff --git a/src/include/lib3270/popup.h b/src/include/lib3270/popup.h index c30a16e..5cc35eb 100644 --- a/src/include/lib3270/popup.h +++ b/src/include/lib3270/popup.h @@ -33,16 +33,6 @@ #define LIB3270_POPUP_INCLUDED 1 - typedef enum _LIB3270_NOTIFY - { - LIB3270_NOTIFY_INFO, /**< Simple information dialog */ - LIB3270_NOTIFY_WARNING, - LIB3270_NOTIFY_ERROR, - LIB3270_NOTIFY_CRITICAL, /**< Critical error, user can abort application */ - - LIB3270_NOTIFY_USER /**< Reserver, always the last one */ - } LIB3270_NOTIFY; - LIB3270_EXPORT void lib3270_set_popup_handler(int (*popup_handler)(H3270 *, void *, LIB3270_NOTIFY, const char *, const char *, const char *, va_list)); LIB3270_EXPORT void lib3270_popup_dialog(H3270 *session, LIB3270_NOTIFY id , const char *title, const char *message, const char *fmt, ...); diff --git a/src/include/lib3270/session.h b/src/include/lib3270/session.h index f76bde4..9a63ec7 100644 --- a/src/include/lib3270/session.h +++ b/src/include/lib3270/session.h @@ -36,6 +36,11 @@ #define LIB3270_LUNAME_LENGTH 16 #define LIB3270_FULL_MODEL_NAME_LENGTH 13 + #if defined(HAVE_LIBSSL) + #include + #include + #endif + /** extended attributes */ struct ea { @@ -71,11 +76,8 @@ int net_sock; LIB3270_CSTATE cstate; /**< Connection state */ - #if defined(_WIN32) - HANDLE sock_handle; - #endif - // flags + int bgthread : 1; /**< Running on a background thread ? */ int selected : 1; /**< Has selected region? */ int rectsel : 1; /**< Selected region is a rectangle ? */ @@ -155,6 +157,7 @@ #if defined(HAVE_LIBSSL) /*[*/ unsigned long last_ssl_error; + SSL * ssl_con; #endif // State change callbacks. @@ -183,6 +186,8 @@ void (*set_selection)(H3270 *session, unsigned char on); void (*ctlr_done)(H3270 *session); + void (*message)(H3270 *session, LIB3270_NOTIFY id , const char *title, const char *message, const char *text); + }; diff --git a/src/lib3270/XtGlue.c b/src/lib3270/XtGlue.c index 3ccb31d..028d4d5 100644 --- a/src/lib3270/XtGlue.c +++ b/src/lib3270/XtGlue.c @@ -985,9 +985,17 @@ LIB3270_EXPORT int lib3270_call_thread(int(*callback)(H3270 *h, void *), H3270 * lib3270_main_iterate(0); if(callbacks->callthread) + { + h->bgthread = 1; + trace("%s: background thread for %p starts",__FUNCTION__,h); rc = callbacks->callthread(callback,h,parm); + trace("%s: background thread for %p ends",__FUNCTION__,h); + h->bgthread = 0; + } else + { rc = callback(h,parm); + } lib3270_main_iterate(0); if(h->set_timer) diff --git a/src/lib3270/init.c b/src/lib3270/init.c index 1aeedd6..8a8322b 100644 --- a/src/lib3270/init.c +++ b/src/lib3270/init.c @@ -111,6 +111,13 @@ static void set_cursor(H3270 *session, LIB3270_CURSOR id) { } +static void message(H3270 *session, LIB3270_NOTIFY id , const char *title, const char *message, const char *text) +{ + lib3270_write_log(session,"%s",title); + lib3270_write_log(session,"%s",message); + lib3270_write_log(session,"%s",text); +} + static void lib3270_session_init(H3270 *hSession, const char *model) { int ovc, ovr; @@ -136,6 +143,7 @@ static void lib3270_session_init(H3270 *hSession, const char *model) hSession->update_oia = update_oia; hSession->update_selection = update_selection; hSession->cursor = set_cursor; + hSession->message = message; hSession->sock = -1; hSession->model_num = -1; diff --git a/src/lib3270/screen.c b/src/lib3270/screen.c index 76d4209..843a6cf 100644 --- a/src/lib3270/screen.c +++ b/src/lib3270/screen.c @@ -596,6 +596,8 @@ void show_3270_popup_dialog(H3270 *session, LIB3270_NOTIFY type, const char *tit { CHECK_SESSION_HANDLE(session); + trace("%s: title=%s msg=%s",__FUNCTION__,title,msg); + if(!fmt) fmt = ""; @@ -618,6 +620,8 @@ void Error(H3270 *session, const char *fmt, ...) CHECK_SESSION_HANDLE(session); + trace("%s: title=%s fmt=%s",__FUNCTION__,"3270 Error",fmt); + va_start(arg_ptr, fmt); popup_handler(session,session->widget,LIB3270_NOTIFY_ERROR, _( "3270 Error" ),NULL,fmt,arg_ptr); va_end(arg_ptr); @@ -630,6 +634,8 @@ void Warning(H3270 *session, const char *fmt, ...) CHECK_SESSION_HANDLE(session); + trace("%s: title=%s fmt=%s",__FUNCTION__,"3270 Warning",fmt); + va_start(arg_ptr, fmt); popup_handler(session,session->widget,LIB3270_NOTIFY_WARNING, _( "3270 Warning" ),NULL,fmt,arg_ptr); va_end(arg_ptr); @@ -643,6 +649,8 @@ extern void popup_an_error(H3270 *session, const char *fmt, ...) CHECK_SESSION_HANDLE(session); + trace("%s: title=%s fmt=%s",__FUNCTION__,"3270 Error",fmt); + va_start(args, fmt); popup_handler(session,session->widget,LIB3270_NOTIFY_ERROR,_( "3270 Error" ),NULL,fmt,args); va_end(args); @@ -655,6 +663,8 @@ void popup_system_error(H3270 *session, const char *title, const char *message, CHECK_SESSION_HANDLE(session); + trace("%s: title=%s msg=%s",__FUNCTION__,"3270 Error",message); + va_start(args, fmt); popup_handler(session,session->widget,LIB3270_NOTIFY_ERROR,title ? title : _( "3270 Error" ), message,fmt,args); va_end(args); @@ -764,6 +774,8 @@ LIB3270_EXPORT void lib3270_popup_dialog(H3270 *session, LIB3270_NOTIFY id , con CHECK_SESSION_HANDLE(session); + trace("%s: title=%s msg=%s",__FUNCTION__,"3270 Error",message); + va_start(args, fmt); popup_handler(session,session->widget,id,title ? title : _( "3270 Error" ), message,fmt,args); va_end(args); diff --git a/src/lib3270/telnet.c b/src/lib3270/telnet.c index b058c94..4ffc0d7 100644 --- a/src/lib3270/telnet.c +++ b/src/lib3270/telnet.c @@ -61,10 +61,6 @@ #endif /*]*/ #include -#if defined(HAVE_LIBSSL) /*[*/ - #include - #include -#endif /*]*/ #include "tn3270e.h" #include "3270ds.h" @@ -196,7 +192,7 @@ static void net_rawout(unsigned const char *buf, int len); static void check_in3270(void); static void store3270in(unsigned char c); static void check_linemode(Boolean init); -// static int non_blocking(Boolean on); +static int non_blocking(Boolean on); static void net_connected(H3270 *session); #if defined(X3270_TN3270E) /*[*/ static int tn3270e_negotiate(void); @@ -308,11 +304,13 @@ static const char *trsp_flag[2] = { "POSITIVE-RESPONSE", "NEGATIVE-RESPONSE" }; #define XMIT_COLS h3270.maxCOLS // #endif /*]*/ +// #if defined(HAVE_LIBSSL) +// static SSL *ssl_con; +// #endif + #if defined(HAVE_LIBSSL) /*[*/ -static SSL_CTX *ssl_ctx; -static SSL *ssl_con; static Boolean need_tls_follows = False; -static void ssl_init(void); +static void ssl_init(H3270 *session); #if OPENSSL_VERSION_NUMBER >= 0x00907000L /*[*/ #define INFO_CONST const #else /*][*/ @@ -600,14 +598,8 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo #endif /* set the socket to be non-delaying */ -/* -#if defined(_WIN32) - if (non_blocking(False) < 0) -#else if (non_blocking(True) < 0) -#endif close_fail; -*/ #if !defined(_WIN32) /* don't share the socket with our children */ @@ -616,26 +608,14 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo /* init ssl */ #if defined(HAVE_LIBSSL) - session->last_ssl_error = 0; + session->last_ssl_error = !0; if (session->ssl_host) - ssl_init(); + ssl_init(session); #endif /* connect */ status_connecting(session,1); - if(connect_sock(session, session->sock, &haddr.sa,ha_len) == 0) - { - trace_dsn("Connected.\n"); - net_connected(session); - } - else - { - popup_a_sockerr(session, N_( "Can't connect to %s:%d" ),session->hostname, session->current_port); - close_fail; - } - -/* switch(connect_sock(session, session->sock, &haddr.sa,ha_len)) { case 0: // Connected @@ -650,9 +630,9 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo case SE_EINPROGRESS: *pending = True; trace_dsn("Connection pending.\n"); -#if !defined(_WIN32) +// #if !defined(_WIN32) output_id = AddOutput(session->sock, session, output_possible); -#endif +// #endif break; default: @@ -660,7 +640,6 @@ int net_connect(H3270 *session, const char *host, char *portname, Boolean ls, Bo close_fail; } -*/ /* set up temporary termtype */ if (appres.termname == CN && session->std_ds_host) @@ -784,25 +763,40 @@ static void net_connected(H3270 *session) /* Set up SSL. */ if(session->ssl_host && !session->secure_connection) { - if (SSL_set_fd(ssl_con, session->sock) != 1) + int rc; + + if (SSL_set_fd(session->ssl_con, session->sock) != 1) { trace_dsn("Can't set fd!\n"); + popup_system_error(&h3270,_( "Connection failed error" ), _( "Can't set SSL socket file descriptor" ), "%s", SSL_state_string_long(session->ssl_con)); } - if (SSL_connect(ssl_con) != 1) + non_blocking(False); + rc = SSL_connect(session->ssl_con); + + if(rc != 1) { - unsigned long e = ERR_get_error(); + unsigned long e = ERR_get_error(); + const char * state = SSL_state_string_long(session->ssl_con); + + trace_dsn("TLS/SSL tunneled connection failed with error %ld, rc=%d and state=%s",e,rc,state); + + host_disconnect(session,True); + if(e != session->last_ssl_error) { - popup_system_error(&h3270,_( "Connection failed error" ), _( "SSL negotiation failed" ), "%s", SSL_state_string_long(ssl_con)); + session->message( &h3270, + LIB3270_NOTIFY_ERROR, + _( "Connection failed" ), + _( "SSL negotiation failed" ), + state); session->last_ssl_error = e; } - - trace_dsn("TLS/SSL tunneled connection failed with error %ld.",e); - trace("%s: SSL_connect failed with error %ld",__FUNCTION__,e); - host_disconnect(session,True); return; + } + non_blocking(True); + session->secure_connection = True; trace_dsn("TLS/SSL tunneled connection complete. Connection is now secure.\n"); @@ -864,15 +858,11 @@ static void net_connected(H3270 *session) */ static void connection_complete(void) { -/* -#if !defined(_WIN32) if (non_blocking(False) < 0) { host_disconnect(&h3270,True); return; } -#endif -*/ host_connected(&h3270); net_connected(&h3270); } @@ -903,14 +893,14 @@ static void output_possible(H3270 *session) * net_disconnect * Shut down the socket. */ -void -net_disconnect(void) +void net_disconnect(void) { #if defined(HAVE_LIBSSL) /*[*/ - if (ssl_con != NULL) { - SSL_shutdown(ssl_con); - SSL_free(ssl_con); - ssl_con = NULL; + if (h3270.ssl_con != NULL) + { + SSL_shutdown(h3270.ssl_con); + SSL_free(h3270.ssl_con); + h3270.ssl_con = NULL; } h3270.secure_connection = False; #endif /*]*/ @@ -991,13 +981,13 @@ void net_input(H3270 *session) ansi_data = 0; #endif /*]*/ -#if defined(_WIN32) /*[*/ - (void) ResetEvent(session->sock_handle); -#endif /*]*/ +// #if defined(_WIN32) +// (void) ResetEvent(session->sock_handle); +//#endif /*]*/ #if defined(HAVE_LIBSSL) - if (ssl_con != NULL) - nr = SSL_read(ssl_con, (char *) netrbuf, BUFSZ); + if (session->ssl_con != NULL) + nr = SSL_read(session->ssl_con, (char *) netrbuf, BUFSZ); else #endif // HAVE_LIBSSL /* @@ -1013,7 +1003,7 @@ void net_input(H3270 *session) return; } #if defined(HAVE_LIBSSL) /*[*/ - if (ssl_con != NULL) + if(session->ssl_con != NULL) { unsigned long e; char err_buf[120]; @@ -1026,11 +1016,11 @@ void net_input(H3270 *session) trace_dsn("RCVD SSL_read error %ld (%s)\n", e,err_buf); - lib3270_popup_dialog( session, - LIB3270_NOTIFY_CRITICAL, - N_( "SSL Error" ), - N_( "SSL Read error" ), - "%s", err_buf); + h3270.message( &h3270, + LIB3270_NOTIFY_ERROR, + _( "SSL Error" ), + _( "SSL Read error" ), + err_buf ); host_disconnect(session,True); return; @@ -1074,13 +1064,11 @@ void net_input(H3270 *session) if (HALF_CONNECTED) { -/* if (non_blocking(False) < 0) { host_disconnect(session,True); return; } -*/ host_connected(session); net_connected(session); } @@ -2022,8 +2010,8 @@ net_rawout(unsigned const char *buf, int len) # define n2w len #endif #if defined(HAVE_LIBSSL) /*[*/ - if (ssl_con != NULL) - nw = SSL_write(ssl_con, (const char *) buf, n2w); + if(h3270.ssl_con != NULL) + nw = SSL_write(h3270.ssl_con, (const char *) buf, n2w); else #endif /*]*/ @@ -2037,7 +2025,8 @@ net_rawout(unsigned const char *buf, int len) nw = send(h3270.sock, (const char *) buf, n2w, 0); if (nw < 0) { #if defined(HAVE_LIBSSL) /*[*/ - if (ssl_con != NULL) { + if (h3270.ssl_con != NULL) + { unsigned long e; char err_buf[120]; @@ -3196,11 +3185,11 @@ net_snap_options(void) /* * Set blocking/non-blocking mode on the socket. On error, pops up an error * message, but does not close the socket. - */ /* -static int -non_blocking(Boolean on) + */ +static int non_blocking(Boolean on) { #if !defined(BLOCKING_CONNECT_ONLY) + # if defined(FIONBIO) int i = on ? 1 : 0; @@ -3209,7 +3198,9 @@ non_blocking(Boolean on) popup_a_sockerr(NULL, N_( "ioctl(%s)" ), "FIONBIO"); return -1; } + # else + int f; if ((f = fcntl(sock, F_GETFL, 0)) == -1) @@ -3226,42 +3217,52 @@ non_blocking(Boolean on) popup_an_errno(NULL,errno, N_( "fcntl(%s)" ), "F_GETFL"); return -1; } -# endif -#endif +#endif // FIONBIO + +#endif // !BLOCKING_CONNECT_ONLY + return 0; } -*/ #if defined(HAVE_LIBSSL) /*[*/ /* Initialize the OpenSSL library. */ -static void ssl_init(void) +static void ssl_init(H3270 *session) { - static Boolean ssl_initted = False; + static SSL_CTX *ssl_ctx = NULL; - if (!ssl_initted) { + if(ssl_ctx == NULL) + { + lib3270_write_log(session,"%s","Initializing SSL context"); SSL_load_error_strings(); SSL_library_init(); - ssl_initted = True; ssl_ctx = SSL_CTX_new(SSLv23_method()); - if (ssl_ctx == NULL) { + if(ssl_ctx == NULL) + { popup_an_error(NULL,"SSL_CTX_new failed"); - h3270.ssl_host = False; + session->ssl_host = False; return; } SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL); + SSL_CTX_set_info_callback(ssl_ctx, client_info_callback); + SSL_CTX_set_default_verify_paths(ssl_ctx); } - ssl_con = SSL_new(ssl_ctx); - if (ssl_con == NULL) { - popup_an_error(NULL,"SSL_new failed"); - h3270.ssl_host = False; + if(session->ssl_con) + SSL_free(session->ssl_con); + + session->ssl_con = SSL_new(ssl_ctx); + if(session->ssl_con == NULL) + { + popup_an_error(session,"SSL_new failed"); + session->ssl_host = False; + return; } - SSL_set_verify(ssl_con, 0/*xxx*/, NULL); - SSL_CTX_set_info_callback(ssl_ctx, client_info_callback); + SSL_set_verify(session->ssl_con, 0/*xxx*/, NULL); /* XXX: May need to get key file and password. */ + /* if (appres.cert_file) { if (!(SSL_CTX_use_certificate_chain_file(ssl_ctx, @@ -3277,8 +3278,7 @@ static void ssl_init(void) appres.cert_file, err_buf); } } - - SSL_CTX_set_default_verify_paths(ssl_ctx); + */ } /* Callback for tracing protocol negotiation. */ @@ -3343,8 +3343,7 @@ static void client_info_callback(INFO_CONST SSL *s, int where, int ret) } /* Process a STARTTLS subnegotiation. */ -static void -continue_tls(unsigned char *sbbuf, int len) +static void continue_tls(unsigned char *sbbuf, int len) { int rv; @@ -3364,15 +3363,17 @@ continue_tls(unsigned char *sbbuf, int len) trace_dsn("%s FOLLOWS %s\n", opt(TELOPT_STARTTLS), cmd(SE)); /* Initialize the SSL library. */ - ssl_init(); - if (ssl_con == NULL) { + ssl_init(&h3270); + if(h3270.ssl_con == NULL) + { /* Failed. */ net_disconnect(); return; } /* Set up the TLS/SSL connection. */ - if (SSL_set_fd(ssl_con, h3270.sock) != 1) { + if(SSL_set_fd(h3270.ssl_con, h3270.sock) != 1) + { trace_dsn("Can't set fd!\n"); } @@ -3382,7 +3383,7 @@ continue_tls(unsigned char *sbbuf, int len) // (void) non_blocking(False); //#endif - rv = SSL_connect(ssl_con); + rv = SSL_connect(h3270.ssl_con); //#if defined(_WIN32) // // Make the socket non-blocking again for event processing diff --git a/src/pw3270/v3270/genmarshal b/src/pw3270/v3270/genmarshal index d615b87..1360dca 100644 --- a/src/pw3270/v3270/genmarshal +++ b/src/pw3270/v3270/genmarshal @@ -9,3 +9,4 @@ BOOL:VOID,UINT,ENUM VOID:VOID,BOOL BOOL:VOID,BOOL,BOOL,POINTER VOID:VOID,UINT,UINT +VOID:VOID,UINT,POINTER,POINTER,POINTER diff --git a/src/pw3270/v3270/iocallback.c b/src/pw3270/v3270/iocallback.c index ab42921..d3f080f 100644 --- a/src/pw3270/v3270/iocallback.c +++ b/src/pw3270/v3270/iocallback.c @@ -251,10 +251,10 @@ struct bgParameter gpointer BgCall(struct bgParameter *p) { - trace("%s starts",__FUNCTION__); +// trace("%s starts",__FUNCTION__); p->rc = p->callback(p->session, p->parm); p->running = FALSE; - trace("%s ends",__FUNCTION__); +// trace("%s ends",__FUNCTION__); return 0; } @@ -263,7 +263,7 @@ static int static_CallAndWait(int(*callback)(H3270 *session, void *), H3270 *ses struct bgParameter p = { TRUE, session, -1, callback, parm }; GThread *thread; - trace("Starting auxiliary thread for callback %p",callback); +// trace("Starting auxiliary thread for callback %p",callback); p.running = TRUE; thread = g_thread_create( (GThreadFunc) BgCall, &p, 0, NULL); diff --git a/src/pw3270/v3270/oia.c b/src/pw3270/v3270/oia.c index 9435051..978ea6a 100644 --- a/src/pw3270/v3270/oia.c +++ b/src/pw3270/v3270/oia.c @@ -276,7 +276,7 @@ static void draw_undera(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, void v3270_draw_connection(cairo_t *cr, H3270 *host, struct v3270_metrics *metrics, GdkColor *color, GdkRectangle *rect) { cairo_text_extents_t extents; - gchar *str = "?"; + const gchar *str; gdk_cairo_set_source_color(cr,color+V3270_COLOR_OIA_FOREGROUND); cairo_rectangle(cr, rect->x, rect->y, rect->width, rect->height); @@ -290,9 +290,11 @@ void v3270_draw_connection(cairo_t *cr, H3270 *host, struct v3270_metrics *metri } if(lib3270_in_ansi(host)) - *str = 'N'; + str = "N"; else if(lib3270_in_sscp(host)) - *str = 'S'; + str = "S"; + else + str = "?"; cairo_text_extents(cr,str,&extents); cairo_move_to(cr,rect->x+((rect->width/2)-(extents.width/2)),rect->y+extents.height+( (rect->height/2) - (extents.height/2))); diff --git a/src/pw3270/v3270/private.h b/src/pw3270/v3270/private.h index 49024ff..a4fe1fc 100644 --- a/src/pw3270/v3270/private.h +++ b/src/pw3270/v3270/private.h @@ -53,6 +53,7 @@ G_BEGIN_DECLS void (*toggle_changed)(v3270 *widget,LIB3270_TOGGLE toggle_id,gboolean toggle_state,const gchar *toggle_name); void (*message_changed)(v3270 *widget, LIB3270_MESSAGE id); void (*luname_changed)(GtkWidget *widget,const gchar *luname); + void (*popup_message)(GtkWidget *widget, LIB3270_NOTIFY id , const gchar *title, const gchar *message, const gchar *text); gboolean (*keypress)(GtkWidget *widget,guint keyval,GdkModifierType state); }; @@ -79,6 +80,7 @@ G_BEGIN_DECLS SIGNAL_PASTENEXT, SIGNAL_CLIPBOARD, SIGNAL_CHANGED, + SIGNAL_MESSAGE, LAST_SIGNAL }; diff --git a/src/pw3270/v3270/v3270.h b/src/pw3270/v3270/v3270.h index fb39726..ec62fd0 100644 --- a/src/pw3270/v3270/v3270.h +++ b/src/pw3270/v3270/v3270.h @@ -181,6 +181,7 @@ // Misc GtkIMContext * v3270_get_im_context(GtkWidget *widget); gboolean v3270_get_toggle(GtkWidget *widget, LIB3270_TOGGLE ix); + void v3270_popup_message(GtkWidget *widget, LIB3270_NOTIFY type, const gchar *title, const gchar *message, const gchar *text); void v3270_set_host(GtkWidget *widget, const gchar *uri); diff --git a/src/pw3270/v3270/widget.c b/src/pw3270/v3270/widget.c index 63f1d93..793efc5 100644 --- a/src/pw3270/v3270/widget.c +++ b/src/pw3270/v3270/widget.c @@ -215,6 +215,46 @@ static void get_preferred_width_for_height(GtkWidget *widget,gint height, gint * #endif // GTK(3,0,0) +void v3270_popup_message(GtkWidget *widget, LIB3270_NOTIFY type , const gchar *title, const gchar *message, const gchar *text) +{ + GtkWidget * dialog; + GtkWidget * toplevel = NULL; + GtkMessageType msgtype = GTK_MESSAGE_WARNING; + GtkButtonsType buttons = GTK_BUTTONS_OK; + + if(widget && GTK_IS_WIDGET(widget)) + toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget)); + + if(type == LIB3270_NOTIFY_CRITICAL) + { + msgtype = GTK_MESSAGE_ERROR; + buttons = GTK_BUTTONS_CLOSE; + } + + if(!title) + title = _( "Error" ); + + if(message) + { + dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",message); + if(text) + gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",text); + } + else if(text) + { + dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",text); + } + else + { + dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",title); + } + + gtk_window_set_title(GTK_WINDOW(dialog),title); + gtk_widget_show_all(dialog); + gtk_dialog_run(GTK_DIALOG (dialog)); + gtk_widget_destroy(dialog); +} + static void v3270_class_init(v3270Class *klass) { GObjectClass * gobject_class = G_OBJECT_CLASS(klass); @@ -240,6 +280,7 @@ static void v3270_class_init(v3270Class *klass) klass->toggle_changed = v3270_toggle_changed; klass->message_changed = v3270_update_message; klass->luname_changed = v3270_update_luname; + klass->popup_message = v3270_popup_message; #if GTK_CHECK_VERSION(3,0,0) @@ -443,6 +484,15 @@ static void v3270_class_init(v3270Class *klass) pw3270_VOID__VOID_UINT_UINT, G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT); + v3270_widget_signal[SIGNAL_MESSAGE] = + g_signal_new( "popup_message", + G_OBJECT_CLASS_TYPE (gobject_class), + G_SIGNAL_RUN_FIRST, + G_STRUCT_OFFSET (v3270Class, popup_message), + NULL, NULL, + pw3270_VOID__VOID_UINT_POINTER_POINTER_POINTER, + G_TYPE_NONE, 4, G_TYPE_UINT, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); + } void v3270_update_font_metrics(v3270 *terminal, cairo_t *cr, int width, int height) @@ -677,6 +727,16 @@ static void update_selection(H3270 *session, int start, int end) } +static void message(H3270 *session, LIB3270_NOTIFY id , const char *title, const char *message, const char *text) +{ + g_signal_emit( GTK_WIDGET(session->widget), v3270_widget_signal[SIGNAL_MESSAGE], 0, + (int) id, + (gchar *) title, + (gchar *) message, + (gchar *) text ); + +} + static void v3270_init(v3270 *widget) { trace("%s",__FUNCTION__); @@ -708,7 +768,7 @@ static void v3270_init(v3270 *widget) widget->host->update_model = update_model; widget->host->changed = changed; widget->host->ctlr_done = ctlr_done; - + widget->host->message = message; // Setup input method widget->input_method = gtk_im_multicontext_new(); diff --git a/src/pw3270/window.c b/src/pw3270/window.c index cf684d6..bdf7470 100644 --- a/src/pw3270/window.c +++ b/src/pw3270/window.c @@ -128,11 +128,25 @@ static int popup_handler(H3270 *session, void *widget, LIB3270_NOTIFY type, const char *title, const char *msg, const char *fmt, va_list args) { + if(fmt) + { + gchar *text = g_strdup_vprintf(fmt,args); + v3270_popup_message(GTK_WIDGET(widget),type,title,msg,text); + g_free(text); + } + else + { + v3270_popup_message(GTK_WIDGET(widget),type,title,msg,NULL); + } +/* GtkWidget * dialog; GtkWidget * toplevel = NULL; GtkMessageType msgtype = GTK_MESSAGE_WARNING; GtkButtonsType buttons = GTK_BUTTONS_OK; - gchar * text = g_strdup_vprintf(fmt,args); + gchar * text = NULL; + + if(fmt) + text = g_strdup_vprintf(fmt,args); if(widget && GTK_IS_WIDGET(widget)) toplevel = gtk_widget_get_toplevel(GTK_WIDGET(widget)); @@ -143,23 +157,33 @@ buttons = GTK_BUTTONS_CLOSE; } + if(!title) + title = _( "Error" ); + if(msg) { dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",msg); - gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",text); + + if(text) + gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),"%s",text); } - else + else if(text) { dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",text); } + else + { + dialog = gtk_message_dialog_new_with_markup(GTK_WINDOW(toplevel),GTK_DIALOG_MODAL|GTK_DIALOG_DESTROY_WITH_PARENT,msgtype,buttons,"%s",title); + } - g_free(text); - - gtk_window_set_title(GTK_WINDOW(dialog),title ? title : "Error"); + if(text) + g_free(text); + gtk_window_set_title(GTK_WINDOW(dialog),title); + gtk_widget_show_all(dialog); gtk_dialog_run(GTK_DIALOG (dialog)); gtk_widget_destroy(dialog); - +*/ return 0; } -- libgit2 0.21.2