#ifdef HAVE_CONFIG_H # include #endif #include "callbacks.h" #include "interface.h" #include "support.h" int authentication_attempts; int vpn_connection_active; pid_t vpnclient_pid; void on_vpnclient_main_window_show (GtkWidget *widget, gpointer user_data) { /* Initialize variables */ gchar *vpn_dir_path = "/etc/opt/cisco-vpnclient/Profiles/"; gchar *vpnclient_path = "/usr/bin"; GtkCombo *profile_entry = GTK_COMBO(lookup_widget(widget,"profile_entry")); GnomeAppBar *statusbar = GNOME_APPBAR(lookup_widget(widget,"statusbar")); gchar *vpn_default_status = "Status Message"; gchar *configkey; GConfClient *client; /* Set default status message */ gnome_appbar_set_default(statusbar,vpn_default_status); /* initialize vpndirpath config entry. If exists use it else create it */ client = gconf_client_get_default(); configkey = "/apps/gnome-settings/gvpndialer/profiledir"; if (gconf_client_get_string(client,configkey,NULL) == NULL ){ gconf_client_set_string(client,configkey,vpn_dir_path,NULL); }else{ vpn_dir_path = gconf_client_get_string(client,configkey,NULL); } configkey = "/apps/gnome-settings/gvpndialer/vpnclientdir"; if (gconf_client_get_string(client,configkey,NULL) == NULL){ gconf_client_set_string(client,configkey,vpnclient_path,NULL); }else { vpnclient_path = gconf_client_get_string(client,configkey,NULL); } /* load Profiles into Glist. If it update status bar */ if ( !(getProfiles(vpn_dir_path,profile_entry))){ gnome_appbar_push(statusbar,"Unable to load VPN Profiles"); } /*unreference gconfclient..always */ g_object_unref(client); } gboolean on_vpnclient_main_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { /* hide main window. if u want to close click quit */ gtk_widget_hide(widget); } void on_quit1_activate (GtkMenuItem *menuitem, gpointer user_data) { /* kill gvpn dialer */ gtk_main_quit(); } void on_preferences1_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *preference_window; GtkEntry *vpnclient_path_entry; GtkEntry *vpn_profile_path_entry; GConfClient *client; GtkEntry *vpnclient_default_user_entry; GtkCheckButton *vpnclient_start_hidden_cb; client = gconf_client_get_default(); preference_window = create_preference_window(); vpnclient_path_entry = GTK_ENTRY(lookup_widget(preference_window, "vpnclient_path_entry")); vpn_profile_path_entry = GTK_ENTRY(lookup_widget(preference_window, "vpn_profile_path_entry")); vpnclient_default_user_entry = GTK_ENTRY(lookup_widget(preference_window, "vpnclient_default_user_entry")); vpnclient_start_hidden_cb = GTK_CHECK_BUTTON(lookup_widget(preference_window, "vpnclient_start_hidden_cb")); gtk_entry_set_text(vpn_profile_path_entry, gconf_client_get_string(client, "/apps/gnome-settings/gvpndialer/profiledir", NULL)); gtk_entry_set_text(vpnclient_path_entry, gconf_client_get_string(client, "/apps/gnome-settings/gvpndialer/vpnclientdir", NULL)); gtk_entry_set_text(vpnclient_default_user_entry, gconf_client_get_string(client, "/apps/gnome-settings/gvpndialer/defaultuser", NULL)); gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(vpnclient_start_hidden_cb), gconf_client_get_bool(client, "/apps/gnome-settings/gvpndialer/starthidden", NULL)); gtk_widget_show(preference_window); g_object_unref(client); } void on_status2_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *status_window; GtkWidget *mainwindow; mainwindow = lookup_widget (GTK_WIDGET(menuitem),"vpnclient_main_window"); status_window = GTK_WIDGET(g_object_get_data(G_OBJECT(mainwindow),"statuswindow")); if ( vpn_connection_active == 1 ){ gtk_widget_show(status_window); updatestats(status_window); sleep(1); g_timeout_add_full(0,(guint)5000,updatestats,status_window,NULL); } else { if (! GTK_WIDGET_VISIBLE(mainwindow)){ gtk_widget_show(mainwindow); } update_statusbar(mainwindow,"Status is show only when a VPN connection is active"); } } void on_about1_activate (GtkMenuItem *menuitem, gpointer user_data) { GtkWidget *about_window; about_window = create_gvpn_dialer_about(); gtk_widget_show(about_window); } /* What happens when you click the Connect Button */ void on_execute_vpn_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *login_window; GtkWidget *main_window; GtkWidget *grouppw_window; GtkLabel *invalid_user_pass; GtkLabel *grouppw_warning_label; GtkEntry *username_entry; GConfClient *client; const gchar* username; main_window = gtk_widget_get_toplevel(GTK_WIDGET(button)); /* initialize authentication attempts */ authentication_attempts = 0; /* find the selected profile */ GtkCombo *profile_entry_combobox = GTK_COMBO(lookup_widget(main_window,"profile_entry")); const gchar *selected_profile = gtk_entry_get_text (GTK_ENTRY(profile_entry_combobox->entry)); /* execute VPNclient. if program starts..continue */ if (!(executeVpnClient(selected_profile,GTK_WIDGET(button)))){ if (! GTK_WIDGET_VISIBLE(main_window)){ gtk_widget_show(main_window); } update_statusbar(GTK_WIDGET(button),"Cannot start vpnclient.Manually run it to determine problem"); return; } /* Reset all password / username / label fields */ update_statusbar(GTK_WIDGET(button),"Logging in....."); login_window = GTK_WIDGET(g_object_get_data(G_OBJECT(main_window),"loginwindow_key")); invalid_user_pass = GTK_LABEL(lookup_widget(login_window,"invalid_user_pass")); gtk_label_set_text(invalid_user_pass, "" ); grouppw_window = GTK_WIDGET(g_object_get_data(G_OBJECT(main_window),"group_pass_win")); grouppw_warning_label = GTK_LABEL(lookup_widget(grouppw_window,"grouppw_warning")); gtk_label_set_text(grouppw_warning_label,""); client = gconf_client_get_default(); username_entry = GTK_ENTRY(lookup_widget(login_window, "enter_username")); gtk_entry_set_text(username_entry, gconf_client_get_string(client, "/apps/gnome-settings/gvpndialer/defaultuser", NULL)); /* put focus in password entry if username was defaulted */ username = gtk_entry_get_text(username_entry); if(username[0] != '\0') gtk_widget_grab_focus(GTK_WIDGET(lookup_widget(login_window, "enter_password"))); /*unreference gconfclient..always */ g_object_unref(client); } void on_disconnect_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *icon; GtkWidget *mainwindow; update_statusbar(GTK_WIDGET(button),"VPN Connection Terminated"); /* set vpn connection variable to 0 */ vpn_connection_active = 0; mainwindow = gtk_widget_get_toplevel(GTK_WIDGET(button)); icon = GTK_WIDGET(g_object_get_data(G_OBJECT(mainwindow),"icon")); tray_icon_load(icon,"gvpndialer/status_unlocked.png"); /* kill vpn connection */ kill_child(); } /* activate status window */ void on_status_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *status_window; GtkWidget *mainwindow; mainwindow = gtk_widget_get_toplevel(GTK_WIDGET(button)); status_window = GTK_WIDGET(g_object_get_data(G_OBJECT(mainwindow),"statuswindow")); if ( vpn_connection_active == 1 && is_network_connection_active()){ gtk_widget_show (status_window); updatestats(status_window); sleep(1); g_timeout_add_full(0,(guint)5000,updatestats,status_window,NULL); }else { if (! GTK_WIDGET_VISIBLE(mainwindow)){ gtk_widget_show(mainwindow); } update_statusbar(mainwindow,"Status is shown only when an active VPN Connection"); } } void on_quit_button_clicked (GtkButton *button, gpointer user_data) { /* kill gvpn dialer */ gtk_main_quit(); } void on_vpn_profile_entry_box_changed (GtkEditable *editable, gpointer user_data) { GtkWidget *mainwindow; mainwindow = lookup_widget(GTK_WIDGET(editable),"vpnclient_main_window"); if ( ! (getHostnamefromProfile(GTK_WIDGET(editable)))){ if (! GTK_WIDGET_VISIBLE(mainwindow)){ gtk_widget_show(mainwindow); } update_statusbar(GTK_WIDGET(editable),"Cannot Read Hostname from Profile"); } else { update_statusbar(GTK_WIDGET(editable),"Profile Selected"); } } gboolean on_login_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { return FALSE; } /* cancel button on the login window */ void on_cancel_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *main_window; GtkWidget *toplevel; GtkEntry *enter_password = NULL; toplevel = gtk_widget_get_toplevel(GTK_WIDGET(button)); main_window = GTK_WIDGET( g_object_get_data( G_OBJECT(toplevel), "mainwindow_key")); /* clear the password field of the login window */ enter_password = GTK_ENTRY(lookup_widget(GTK_WIDGET(button), "enter_password")); gtk_entry_set_text(enter_password,""); /* Close login window and kill vpnclient */ gtk_widget_hide(toplevel); update_statusbar(main_window,"Status Message"); /* for some reason sleep causes the app not to crash if u hit cancel too many times */ sleep(1); close_all_io_channels(main_window); kill_child(); } /* when someone clicks submit on the login window */ void on_submit_button_clicked (GtkButton *button, gpointer user_data) { GtkEntry *enter_password; GtkEntry *enter_username; GtkWidget *main_window; GIOChannel *ptychannel; GIOChannel *stdoutchannel; GtkWidget *login_window; GtkLabel *invalid_user_pass; const gchar *entry; const gchar *entry2; login_window = gtk_widget_get_toplevel(GTK_WIDGET(button)); invalid_user_pass = GTK_LABEL(lookup_widget(login_window,"invalid_user_pass")); main_window = GTK_WIDGET(g_object_get_data(G_OBJECT(login_window),"mainwindow_key")); enter_password = GTK_ENTRY(lookup_widget(login_window,"enter_password")); enter_username = GTK_ENTRY(lookup_widget(login_window,"enter_username")); ptychannel = (GIOChannel *)g_object_get_data(G_OBJECT(main_window),"pty"); stdoutchannel = (GIOChannel *)g_object_get_data(G_OBJECT(main_window),"stdout"); /* check to see if someone forgot to type a username/password add spaces if username/password is forgotten . client will reauthenticate */ if ( strlen(gtk_entry_get_text(enter_username)) == 0 ){ entry = "username"; }else { entry = gtk_entry_get_text(enter_username); } if ( strlen(gtk_entry_get_text(enter_password)) == 0){ entry2 = "password"; }else { entry2 = gtk_entry_get_text(enter_password); } write_text_into_fd (entry,ptychannel); sleep(1); write_text_into_fd (entry2,ptychannel); g_io_add_watch(stdoutchannel,G_IO_IN | G_IO_HUP, (GIOFunc)iofunc_stdout, (gpointer)main_window); gtk_widget_hide(login_window); } gboolean on_preference_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { return FALSE; } void on_preference_cancel_button_clicked (GtkButton *button, gpointer user_data) { /* kill window with no changes done */ gtk_widget_destroy(gtk_widget_get_toplevel(GTK_WIDGET(button))); } void on_preference_apply_button_clicked (GtkButton *button, gpointer user_data) { GtkEntry *vpnclient_path_entry; GtkEntry *vpn_profile_path_entry; GtkEntry *vpnclient_default_user_entry; GtkCheckButton *vpnclient_start_hidden_cb; const gchar *gtkentry_text; GtkWidget *main_window; GConfClient *client; client = gconf_client_get_default(); main_window = gtk_widget_get_toplevel(GTK_WIDGET(button)); vpnclient_path_entry = GTK_ENTRY(lookup_widget(GTK_WIDGET(button), "vpnclient_path_entry")); vpn_profile_path_entry = GTK_ENTRY(lookup_widget(GTK_WIDGET(button), "vpn_profile_path_entry")); vpnclient_default_user_entry = GTK_ENTRY(lookup_widget(GTK_WIDGET(button), "vpnclient_default_user_entry")); vpnclient_start_hidden_cb = GTK_CHECK_BUTTON(lookup_widget(GTK_WIDGET(button), "vpnclient_start_hidden_cb")); gtkentry_text = gtk_entry_get_text(vpnclient_path_entry); gconf_client_set_string(client,"/apps/gnome-settings/gvpndialer/vpnclientdir" ,gtkentry_text,NULL); gtkentry_text = gtk_entry_get_text(vpn_profile_path_entry); gconf_client_set_string(client, "/apps/gnome-settings/gvpndialer/profiledir", gtkentry_text, NULL); gtkentry_text = gtk_entry_get_text(vpnclient_default_user_entry); gconf_client_set_string(client, "/apps/gnome-settings/gvpndialer/defaultuser", gtkentry_text, NULL); gconf_client_set_bool(client, "/apps/gnome-settings/gvpndialer/starthidden", gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(vpnclient_start_hidden_cb)), NULL); gtk_widget_destroy(gtk_widget_get_toplevel(GTK_WIDGET(button))); g_object_unref(client); } gboolean on_status_window_delete_event (GtkWidget *widget, GdkEvent *event, gpointer user_data) { return FALSE; } void on_enter_username_activate (GtkEntry *entry, gpointer user_data) { } void on_enter_password_activate (GtkEntry *entry, gpointer user_data) { GtkButton *mybutton; mybutton = GTK_BUTTON(lookup_widget(GTK_WIDGET(entry),"submit_button")); on_submit_button_clicked(mybutton,user_data); } void on_submit_button_activate (GtkButton *button, gpointer user_data) { } void on_status_window_show (GtkWidget *widget, gpointer user_data) { } void on_close_status_window_button_clicked (GtkButton *button, gpointer user_data) { /* hide window */ gtk_widget_hide(gtk_widget_get_toplevel(GTK_WIDGET(button))); } /** BEGIN NON-GLADE FUNCTIONS **/ int kill_child(){ /* borrowed from http://www.linux-mag.com/2000-02/compile_03.html Kills the child process graciously */ pid_t rc; if (vpnclient_pid > 1 ){ kill(vpnclient_pid, SIGTERM); alarm(2); rc = waitpid(vpnclient_pid, NULL,0); alarm(0); if (rc) { /* we were interrupted by an alarm :-( */ kill(SIGKILL, SIGTERM); rc = waitpid(vpnclient_pid, NULL,0); } return 1; } return 0; } /* write text into stdin of forked process */ int write_text_into_fd (const gchar *my_text_entry,GIOChannel *ioc ){ GString *i_buffer = NULL; i_buffer = g_string_new(my_text_entry); /* if buffer is empty, return zero. Something must be written */ if ( i_buffer->len == 0 ){ g_string_free(i_buffer,TRUE); return 0; } i_buffer = g_string_append_c(i_buffer,'\r'); g_io_channel_write_chars(ioc,i_buffer->str,strlen(i_buffer->str),NULL,NULL); g_io_channel_flush(ioc,NULL); g_string_free(i_buffer,TRUE); return 1; } /* Read Vpnclient stdout and taken appropriate action depending on what it prints outs * returns 1 if you want to continue monitoring stdout activity * returns 0 if you don't want to monitor stdout activity. * read g_io_add_watch api for more details on return value of GIOFunc */ gboolean iofunc_stdout (GIOChannel *ioc, GIOCondition cond, gpointer data){ #define GROUP_PASSWORD 1 #define REAUTHENTICATE 2 #define ENTER_USERNAME 3 #define CONTACTING_GATEWAY 4 #define CONTINUE_YES 5 #define VPN_SECURE 6 #define CONNECTION_TERMINATED 7 #define REASON_FOR_FAILURE 8 #define SAVE_PASS 9 GtkWidget *main_window = GTK_WIDGET(data); GtkWidget *login_window; GtkWidget *grouppw_window; GtkLabel *invalid_user_pass; GtkEntry *enter_password; GtkEntry *enter_username; GtkEntry *enter_grouppw; gchar **reason = NULL; gchar *line; GIOStatus ret; GString *buf = g_string_new_len("",BUFSIZE); GtkWidget *vpn_profile_combolist; GConfClient *client; GtkWidget *icon; int count = 0; GIOChannel *pty_channel = (GIOChannel *)g_object_get_data(G_OBJECT(main_window),"pty"); /* if something is seriously wrong..kill process */ if ( cond & G_IO_HUP ){ close_all_io_channels(main_window); kill_child(); g_string_free(buf,TRUE); /* stop monitoring stdout of the process */ return 0; } /* Get relevant widgets */ login_window = GTK_WIDGET(g_object_get_data (G_OBJECT(main_window),"loginwindow_key")); grouppw_window = GTK_WIDGET(g_object_get_data (G_OBJECT(main_window),"group_pass_win")); enter_password = GTK_ENTRY(lookup_widget (login_window,"enter_password")); enter_username = GTK_ENTRY(lookup_widget (login_window,"enter_username")); invalid_user_pass = GTK_LABEL(lookup_widget (login_window,"invalid_user_pass")); enter_grouppw = GTK_ENTRY(lookup_widget (grouppw_window,"group_pw_entry")); /* there is something to read */ if ( cond & G_IO_IN ){ while ( ret != G_IO_STATUS_EOF ){ ret = g_io_channel_read_line_string(ioc,buf,NULL,NULL); if ( ret == G_IO_STATUS_AGAIN ){ /* print out a prompt */ g_string_free(buf,TRUE); buf = g_string_new_len("",BUFSIZE); ret = g_io_channel_read_chars(ioc,buf->str,BUFSIZE,NULL,NULL);} if ( ret == G_IO_STATUS_NORMAL ){ switch (check_for_events(buf)) { case GROUP_PASSWORD: /* show password group window exit iofunc_stdout, stop monitoring stdout activity */ gtk_widget_grab_focus(GTK_WIDGET(enter_grouppw)); gtk_widget_show(grouppw_window); g_string_free(buf,TRUE); return 0; break; case CONTACTING_GATEWAY: update_statusbar(main_window,buf->str); continue; case REAUTHENTICATE: /* show the invalid username field if authentication failed */ if ( authentication_attempts > 0 ){ gtk_label_set_text (invalid_user_pass, "Invalid Username or Password"); gtk_widget_grab_focus(GTK_WIDGET(enter_password)); } continue; case ENTER_USERNAME: gtk_entry_set_text(enter_password,""); /* set the focus back onto the username entry */ gtk_widget_grab_focus(GTK_WIDGET(enter_username)); authentication_attempts++; gtk_widget_show(login_window); g_string_free(buf,TRUE); return 0; break; case CONTINUE_YES: write_text_into_fd ("yes",pty_channel); break; case CONNECTION_TERMINATED: gtk_entry_set_text(enter_password,""); gtk_entry_set_text(enter_username,""); gtk_entry_set_text(enter_grouppw,""); count++; sleep(1); continue; case VPN_SECURE: gtk_entry_set_text(enter_password,""); gtk_entry_set_text(enter_username,""); update_statusbar(main_window,"VPN Connection Active"); vpn_connection_active = 1; /* save successfully used profile . Will default to this next time */ vpn_profile_combolist = lookup_widget(main_window,"profile_entry"); /* initialize gconfclient */ client = gconf_client_get_default(); gconf_client_set_string (client, "/apps/gnome-settings/gvpndialer/lastchosenprofile", gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(vpn_profile_combolist)->entry)),NULL); g_object_unref(client); /* change icon to be the closed padlock */ icon = GTK_WIDGET(g_object_get_data(G_OBJECT(main_window),"icon")); tray_icon_load (icon,"gvpndialer/status_lock.png"); gtk_widget_hide(main_window); /* no need to read stdout anymore. stop monitoring it. */ g_string_free(buf,TRUE); sleep(2); /* don't know why i need to do this. stops app from crashing */ /* Check VPN status now that connection is secure. Do something if something bad happens */ g_timeout_add((guint)1000,is_vpn_connection_active_full,(gpointer)main_window); return 0; break; case REASON_FOR_FAILURE: if (! GTK_WIDGET_VISIBLE(main_window)){ gtk_widget_show(main_window); } if ( count > 0 ){ reason = g_strsplit(g_strchomp(buf->str),"Reason:",2); update_statusbar(main_window,reason[1]); g_strfreev(reason); g_string_free(buf,TRUE); }else { g_string_free(buf,TRUE); update_statusbar(main_window, "VPNclient terminated for unknown reason"); } /* check to see if process is active. if not kill it */ if (is_vpn_connection_active() ){ close_all_io_channels(main_window); kill_child(); } return 0; break; case SAVE_PASS: write_text_into_fd ("n",pty_channel); break; default: continue; } } return 1; } } g_string_free(buf,TRUE); return 1; } void update_statusbar( GtkWidget *anywidget, gchar *status_message){ GnomeAppBar *statusbar = GNOME_APPBAR(lookup_widget(anywidget,"statusbar")); gnome_appbar_push(statusbar,status_message); } /* return 1 if successful, or 0 if not */ int executeVpnClient(const gchar *profile, GtkWidget *widget){ gchar *filename = NULL; gchar *vpn_args[4]; GConfClient *client; GtkWidget *mainwindow = gtk_widget_get_toplevel(widget); client = gconf_client_get_default(); filename = gconf_client_get_string(client,"/apps/gnome-settings/gvpndialer/vpnclientdir",NULL); if(filename != NULL ){ filename = g_strjoin("/",filename,"vpnclient",NULL); }else{ filename = "vpnclient"; } g_object_unref(client); vpn_args[0] = filename; vpn_args[1] = "connect"; vpn_args[2] = (gchar *)profile; vpn_args[3] = NULL; /* start vpnclient */ start_term(vpn_args,mainwindow); /* check to see if vpnclient was successfully activated */ if ( vpnclient_pid <= 1 ){ return 0; } return 1; } /* creates pty Used code from anjuta and gst projects. */ void start_term ( gchar **args, GtkWidget *main_window) { int pty_master_fd, md; int stdout_pipe[2],stderr_pipe[2]; GIOChannel *pty_channel = NULL; GIOChannel *stdout_channel = NULL; GIOChannel *stderr_channel = NULL; pipe (stderr_pipe); pipe (stdout_pipe); /* Fork the command */ vpnclient_pid = forkpty (&pty_master_fd, NULL, NULL, NULL); if (vpnclient_pid == 0) { unsetenv("LC_ALL"); unsetenv("LC_MESSAGES"); unsetenv("LANG"); unsetenv("LANGUAGE"); dup2 (stderr_pipe[1],2); dup2 (stdout_pipe[1],1); /* Close unnecessary pipes */ close (stderr_pipe[0]); close (stdout_pipe[0]); execvp (args[0], args); exit(255); } /* Close parent's side pipes */ close (stderr_pipe[1]); close (stdout_pipe[1]); if (vpnclient_pid < 0) { /* if fork failed */ /* Close parent's side pipes */ close (stderr_pipe[0]); close (stdout_pipe[0]); exit(255); } /* Initialize GIOChannels */ pty_channel = g_io_channel_unix_new(pty_master_fd); stderr_channel = g_io_channel_unix_new (stderr_pipe[0]); stdout_channel = g_io_channel_unix_new (stdout_pipe[0]); /* Set channels to not block */ g_io_channel_set_flags(stdout_channel,G_IO_FLAG_NONBLOCK,NULL); g_io_channel_set_flags(stderr_channel,G_IO_FLAG_NONBLOCK,NULL); g_io_channel_set_flags(pty_channel, G_IO_FLAG_NONBLOCK,NULL); /* track stdout and stderr channel using main_window widget */ g_object_set_data(G_OBJECT(main_window),"stdout",stdout_channel); g_object_set_data(G_OBJECT(main_window),"stderr",stderr_channel); g_object_set_data(G_OBJECT(main_window),"pty",pty_channel); /* Watch events for stdout stream */ g_io_add_watch (stdout_channel, G_IO_IN | G_IO_HUP , (GIOFunc)iofunc_stdout, (gpointer)main_window); /* Exit. Process created successfully! */ } int getHostnamefromProfile(GtkWidget *mywidget) { int profile_fd; GIOChannel *Mychannel = NULL; GError *error = NULL; GString *line = NULL; gboolean pending; gchar *matching_line = "Host"; gchar **host = NULL; gchar *filename = NULL; GConfClient *client ; GtkEntry *hostname_entry ; client = gconf_client_get_default(); hostname_entry = GTK_ENTRY(lookup_widget(mywidget, "hostname_entry" )); filename = gtk_editable_get_chars(GTK_EDITABLE(mywidget),0,-1); filename = g_strjoin(".",filename,"pcf",NULL); filename = g_strjoin("/", gconf_client_get_string( client, "/apps/gnome-settings/gvpndialer/profiledir", NULL), filename, NULL ); g_object_unref(client); /* Initialize GString */ line = g_string_new(""); /* Use open to create a file descriptor that points to an int */ profile_fd = open(filename,O_RDONLY); /* for some reason the widget chooses a filename that doesn't exist need to catch this */ if ( profile_fd == -1 ){ return 0; } Mychannel = g_io_channel_unix_new(profile_fd); if(Mychannel != NULL ) { /* read each line of the file, and find the line starting with Host split the line and only print out the hostname */ while(g_io_channel_read_line_string (Mychannel,line,NULL,&error) == G_IO_STATUS_NORMAL) { if (g_ascii_strncasecmp(line->str,matching_line,4) == 0 ) { host = g_strsplit(g_strchomp(line->str),"=",2); gtk_entry_set_text(hostname_entry,host[1]); break; } } } else { return 0; } g_io_channel_shutdown(Mychannel,pending,&error); g_free(filename); g_strfreev(host); g_string_free(line,TRUE); close(profile_fd); return 1; } /* according to GTK API GtkCombo is deprecated .. Need to work on using new way but also supporting old way */ int getProfiles (gchar *dir_path, GtkCombo *vpn_profile_entry){ GDir *directory = NULL; GList *vpn_profiles = NULL; GError **error = NULL; gchar *filename = NULL; gchar **split_string = NULL; gchar *lastprofile; GConfClient *client; int count = 0; int last_profile_exists = 0; client = gconf_client_get_default(); lastprofile = gconf_client_get_string(client,"/apps/gnome-settings/gvpndialer/lastchosenprofile",NULL); /*unreference gconfclient */ g_object_unref(client); directory = g_dir_open(dir_path,0,error); while ((filename = (gchar *) g_dir_read_name(directory)) != NULL ){ /*run for *.pcf file only */ if (g_str_has_suffix(filename,"pcf") == TRUE ){ /* save filename in Glist */ count++; split_string = g_strsplit(filename,".",2); /* put the default profile at the top of the list */ if(( lastprofile != NULL ) && (last_profile_exists == 0 ) ){ if ( ( g_ascii_strcasecmp(lastprofile,split_string[0])) == 0 ){ last_profile_exists = 1; }else { vpn_profiles = g_list_append (vpn_profiles,split_string[0]); } }else{ vpn_profiles = g_list_append (vpn_profiles, split_string[0]); } } } if ( count == 0 ) return 0; /* sort list alphabetically */ vpn_profiles = glist_strings_sort(vpn_profiles); /* add last used profile to the top */ if (last_profile_exists == 1 ){ vpn_profiles = g_list_prepend (vpn_profiles,lastprofile); } gtk_combo_set_popdown_strings(vpn_profile_entry,vpn_profiles); g_dir_close(directory); g_list_free(vpn_profiles); g_free(lastprofile); g_strfreev(split_string); return 1; } /* check if vpn connection is alive */ gboolean is_vpn_connection_active_full (gpointer mainwindow) { pid_t zombie; int is_process_died; GtkWidget *icon; is_process_died = kill(vpnclient_pid,0); zombie = waitpid(vpnclient_pid,NULL,WNOHANG); /* if the process is not there, please stop checking the vpn connection */ if (is_process_died){ return FALSE; } /* check if vpnclient is a zombie */ if (zombie){ if (! GTK_WIDGET_VISIBLE(mainwindow)){ gtk_widget_show(mainwindow); } update_statusbar(GTK_WIDGET(mainwindow) ,"VPN Connection Ended Abruptly or VPN Daemon is not active"); icon = GTK_WIDGET(g_object_get_data(G_OBJECT(mainwindow),"icon")); tray_icon_load(icon,"gvpndialer/status_unlocked.png"); close_all_io_channels(mainwindow); /* show main window if you get an abrupt failure */ if (! GTK_WIDGET_VISIBLE(mainwindow) ) gtk_widget_show(mainwindow); return FALSE; } else { return TRUE; } } gboolean is_vpn_connection_active () { pid_t zombie; int is_process_died; is_process_died = kill(vpnclient_pid,0); zombie = waitpid(vpnclient_pid,NULL,WNOHANG); /* if the process is not there, please stop checking the vpn connection */ if (is_process_died){ return FALSE; } /* check if vpnclient is a zombie */ if (zombie){ return FALSE; } else { return TRUE; } } /* Close all IO Channels before killing process */ void close_all_io_channels(gpointer mymain_window) { GIOChannel *stdout_channel = (GIOChannel *)g_object_get_data(G_OBJECT(mymain_window), "stdout"); GIOChannel *stderr_channel = (GIOChannel *)g_object_get_data(G_OBJECT(mymain_window), "stderr"); GIOChannel *pty_channel = (GIOChannel *)g_object_get_data(G_OBJECT(mymain_window), "pty"); GString *buf = g_string_new_len("",1024); GIOStatus ret; if (g_io_channel_get_flags(stderr_channel) & G_IO_FLAG_IS_READABLE){ ret = g_io_channel_read_line_string(stderr_channel, buf,NULL,NULL); if (ret == G_IO_STATUS_NORMAL ){ update_statusbar(GTK_WIDGET(mymain_window),buf->str); } } g_string_free(buf,TRUE); g_io_channel_shutdown(stdout_channel,TRUE,NULL); g_io_channel_shutdown(stderr_channel,TRUE,NULL); g_io_channel_shutdown(pty_channel,TRUE,NULL); } /* this function runs every second while the status window is up */ /* It updates the stats on the status/statistics window */ gboolean updatestats( gpointer data ){ #define TUNNELSTATS 1 #define TRAFFICSTATS 2 #define ROUTESTATS 3 GString *routestats; GString *trafficstats; GString *tunnelstats; GString *mybuffer; int statstype; GError *error; gint output_fd,child_pid; gchar *vpnfilename; GtkWidget *statuswindow; GtkWidget *mainwindow; GIOChannel *vpnstats_io; GtkTextView *tunnel; GtkTextView *route; GtkTextView *traffic; GConfClient *client; client = gconf_client_get_default(); vpnfilename = gconf_client_get_string(client,"/apps/gnome-settings/gvpndialer/vpnclientdir",NULL); vpnfilename = g_strjoin("/",vpnfilename,"vpnclient",NULL); g_object_unref(client); mybuffer = g_string_new(""); routestats = g_string_new(""); trafficstats = g_string_new(""); tunnelstats = g_string_new(""); statuswindow = GTK_WIDGET(data); traffic = (GtkTextView *)lookup_widget(statuswindow,"trafficstats_text"); route = (GtkTextView *)lookup_widget(statuswindow,"routestats_text"); tunnel = (GtkTextView *)lookup_widget(statuswindow,"tunnelstats_text"); gchar *executable[] = {vpnfilename,"stat",NULL}; /* if status window is visible, print the latest stats */ if ( GTK_WIDGET_VISIBLE(statuswindow) ){ /* create a new i/o pipe to capture data from vpnclient stat */ if ( g_spawn_async_with_pipes (NULL, executable, NULL, (G_SPAWN_SEARCH_PATH), NULL, NULL, &child_pid, NULL, &output_fd, NULL, &error)) { error = NULL; vpnstats_io = g_io_channel_unix_new(output_fd); while (g_io_channel_read_line_string (vpnstats_io,mybuffer,NULL,&error) == G_IO_STATUS_NORMAL){ if (g_ascii_strncasecmp ("VPN tunnel",mybuffer->str,10) == 0 ){ statstype = 1; continue; }else if (g_ascii_strncasecmp ("VPN traffic",mybuffer->str,11) == 0 ){ statstype = 2; continue; }else if (g_ascii_strncasecmp ("Configured routes",mybuffer->str,17) == 0 ){ statstype = 3; } switch(statstype) { case TUNNELSTATS: g_string_append(tunnelstats,mybuffer->str); break; case TRAFFICSTATS: g_string_append(trafficstats,mybuffer->str); break; case ROUTESTATS: g_string_append(routestats,mybuffer->str); break; } } /* update the vpnclient status window with the latest data */ gtk_text_buffer_set_text (gtk_text_view_get_buffer (traffic),trafficstats->str,-1); gtk_text_buffer_set_text (gtk_text_view_get_buffer (route),routestats->str,-1); gtk_text_buffer_set_text (gtk_text_view_get_buffer (tunnel),tunnelstats->str,-1); g_io_channel_shutdown(vpnstats_io,TRUE,NULL); g_string_free(mybuffer,TRUE); g_string_free(tunnelstats,TRUE); g_string_free(trafficstats,TRUE); g_string_free(routestats,TRUE); return TRUE; }else { /* for some reason can't execute vpnclient stat */ return FALSE; } } else /* status window is closed */ return FALSE; } /* creates the sys tray */ void tray_create (GtkWidget *mainwindow) { GtkWidget *box; EggTrayIcon *tray_icon; GtkWidget *icon = NULL ; GtkWidget *menu = NULL; /* create the menu, if it doesn't exist */ if (!menu){ /* create menu */ menu = gtk_menu_new(); /* associate menu and mainwindow */ g_object_set_data(G_OBJECT(menu),"mainwindow",mainwindow); /* add menuitems */ create_menu (menu); } /* create the system tray entry */ tray_icon = egg_tray_icon_new ("GvpnDialer System Tray"); box = gtk_event_box_new (); icon = gtk_image_new (); /* continue creating system tray entry */ gtk_container_add (GTK_CONTAINER (box), icon); gtk_container_add (GTK_CONTAINER (tray_icon), box); gtk_widget_show_all (GTK_WIDGET (tray_icon)); g_signal_connect (G_OBJECT (box), "button-press-event", G_CALLBACK (clicked), (gpointer)menu); /* associate icon with main window */ g_object_set_data(G_OBJECT(mainwindow),"icon",icon); /* load the icon */ tray_icon_load (icon,"gvpndialer/status_unlocked.png"); } void tray_icon_load (GtkWidget *icon, const gchar *file){ GdkPixbuf *pixbuf; /* pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (icon)); if (pixbuf) g_object_unref (G_OBJECT (pixbuf)); pixbuf = gdk_pixbuf_new_from_file (file, NULL); gtk_image_set_from_pixbuf (GTK_IMAGE (icon), pixbuf); */ pixbuf = create_pixbuf(file); gtk_image_set_from_pixbuf (GTK_IMAGE(icon),pixbuf); } void clicked (GtkWidget *widget, GdkEventButton *event, gpointer data) { GtkWidget *mainwindow; if (event->button == 3 ){ gtk_menu_popup (GTK_MENU (data), NULL, NULL, NULL, NULL, event->button, event->time); }else if (event->button == 1 ){ mainwindow = GTK_WIDGET(g_object_get_data(G_OBJECT(data),"mainwindow")); if ( GTK_WIDGET_VISIBLE(mainwindow)){ gtk_widget_hide(mainwindow); } else { gtk_widget_show(mainwindow); } } } void create_menu (GtkWidget *menu) { GtkWidget *menuitem; GtkWidget *mainwindow; GtkButton *connect; GtkButton *disconnect; GtkButton *status; /* get mainwindow pointer */ mainwindow = GTK_WIDGET(g_object_get_data(G_OBJECT(menu),"mainwindow")); /* create the menus */ menuitem = gtk_menu_item_new_with_label ("Connect"); g_signal_connect(G_OBJECT(menuitem),"activate", G_CALLBACK(tray_connect_selected),(gpointer)mainwindow); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_menu_item_new_with_label ("Disconnect"); g_signal_connect(G_OBJECT(menuitem),"activate", G_CALLBACK(tray_disconnect_selected),(gpointer)mainwindow); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_menu_item_new_with_label ("Status"); g_signal_connect(G_OBJECT(menuitem),"activate", G_CALLBACK(tray_status_selected),(gpointer)mainwindow); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_separator_menu_item_new (); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); menuitem = gtk_menu_item_new_with_label (_("Exit")); g_signal_connect (G_OBJECT (menuitem), "activate", G_CALLBACK (gtk_main_quit), 0); gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem); gtk_widget_show_all (menu); } void tray_status_selected(GtkMenuItem *menuitem,gpointer user_data){ GtkButton *status; status = (GtkButton *)lookup_widget(GTK_WIDGET (user_data),"status_button"); on_status_button_clicked(status,0); } void tray_disconnect_selected(GtkMenuItem *menuitem, gpointer user_data){ GtkButton *disconnect; disconnect = (GtkButton *)lookup_widget(GTK_WIDGET(user_data),"disconnect_button"); on_disconnect_button_clicked(disconnect,0); } void tray_connect_selected(GtkMenuItem *menuitem, gpointer user_data){ GtkButton *connect; connect = (GtkButton *)lookup_widget(GTK_WIDGET(user_data),"execute_vpn_button"); on_execute_vpn_button_clicked(connect,0); } /* Returns the following. If "group password" is found return 1 If "Username and Password" is found return 2 If "Username" is found return 3 If "Password" is found return 4 If "continue" is found return 5 If "terminated" is found return 6 If "VPN connection is secure" is found return 7 If "Reason:" is found return 8 If "Save Password" is found return 9 If no match return 0 */ int check_for_events(GString *buf){ if (check_for_string("group password", buf->str)) { return 1; } if (check_for_string("Username and Password",buf->str)){ return 2; } if (check_for_string("Username",buf->str)){ return 3;} if (check_for_string("Contacting the gateway",buf->str)){ return 4;} if (check_for_string("continue",buf->str)){ return 5;} if (check_for_string("VPN connection is secure",buf->str)) { return 6;} if (check_for_string("terminated",buf->str)){ return 7;} if (check_for_string("Reason:",buf->str)){ return 8;} if (check_for_string("Save Password",buf->str)){ return 9;} /* found nothing */ return 0; } /* return true if pattern is found returns -1 if pattern is bogus return 0 if pattern is not found Code from Apache 2.0 pcre demo */ int check_for_string(gchar *pattern, gchar *subject){ pcre *re; const char *error; int erroffset; int subject_length; int rc; int result = 0; int ovector[OVECCOUNT]; subject_length = strlen(subject); re = pcre_compile ( pattern, /*the pattern*/ 0, /* default options*/ &error, /* for error message */ &erroffset, /* for error offset */ NULL); /* if compilation failed: print critical message */ if (re == NULL){ g_critical("PCRE compilation failed at offset %d: %s\n", erroffset,error); return -1; } /************************************************************************* * If the compilation succeeded, we call PCRE again, in order to do a * * pattern match against the subject string. This does just ONE match. If * * further matching is needed, it will be done below. * *************************************************************************/ rc = pcre_exec( re, /* the compiled pattern */ NULL, /* no extra data - we didn't study the pattern */ subject, /* the subject string */ subject_length, /* the length of the subject */ 0, /* start at offset 0 in the subject */ 0, /* default options */ ovector, /* output vector for substring information */ OVECCOUNT); /* number of elements in the output vector */ if (rc <= 0 ){ free(re); /* debug no MATCH or some type of error*/ return 0; } free(re); /* release memory used for the compiled pattern */ return rc; } void on_enter_group_password_activate (GtkEntry *entry, gpointer user_data) { GtkButton *mybutton; mybutton = GTK_BUTTON(lookup_widget(GTK_WIDGET(entry),"group_pw_okay_button")); on_group_pw_submit_button_clicked(mybutton,user_data); } void on_group_pw_cancel_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *main_window; GtkWidget *toplevel; GtkEntry *enter_password = NULL; toplevel = gtk_widget_get_toplevel(GTK_WIDGET(button)); main_window = GTK_WIDGET( g_object_get_data( G_OBJECT(toplevel), "mainwindow_key")); /* clear the password field of the login window */ enter_password = GTK_ENTRY(lookup_widget(GTK_WIDGET(button), "group_pw_entry")); gtk_entry_set_text(enter_password,""); /* Close login window and kill vpnclient */ gtk_widget_hide(toplevel); update_statusbar(main_window,"Status Message"); close_all_io_channels(main_window); kill_child(); } void on_group_pw_submit_button_clicked (GtkButton *button, gpointer user_data) { GtkWidget *grouppw_window = gtk_widget_get_toplevel(GTK_WIDGET(button)); GtkEntry *grouppw_entry = GTK_ENTRY(lookup_widget(grouppw_window,"group_pw_entry")); GtkLabel *grouppw_warning = GTK_LABEL(lookup_widget(grouppw_window,"grouppw_warning")); GtkWidget *main_window = GTK_WIDGET(g_object_get_data(G_OBJECT(grouppw_window),"mainwindow_key")); GIOChannel *ptychannel = (GIOChannel *)g_object_get_data(G_OBJECT(main_window),"pty"); GIOChannel *stdoutchannel = (GIOChannel *)g_object_get_data(G_OBJECT(main_window),"stdout"); /* write group password to vpnclient */ if ( ! (write_text_into_fd (gtk_entry_get_text(grouppw_entry),ptychannel))){ gtk_label_set_text(grouppw_warning, "!!Group password cannot be empty!!"); return; } /*begin to watch stdout of vpnclient again */ g_io_add_watch(stdoutchannel,G_IO_IN | G_IO_HUP, (GIOFunc)iofunc_stdout, (gpointer)main_window); /*clear group password entry and label */ gtk_entry_set_text(grouppw_entry,""); gtk_label_set_text(grouppw_warning,""); /* hide group password window */ gtk_widget_hide(grouppw_window); } /* Code to sort VPN profiles. Obtained from the Anjuta Project */ static gint sort_node (gchar* a, gchar *b) { if ( !a && !b) return 0; else if (!a) return -1; else if (!b) return 1; return strcmp (a, b); } /* Sort the list alphabatically */ GList* glist_strings_sort (GList * list) { return g_list_sort(list, (GCompareFunc)sort_node); } /* Check to see if network interface is down. For some reason vpnclient doesn't detect right away that the NIC is down. If you attempt to view the status during this state, your PC will hang..yuck ! */ int is_network_connection_active(){ GIOChannel *procroute; GIOStatus ret; gint active = 0; GString *buf = g_string_new_len("",BUFSIZE); procroute = g_io_channel_new_file("/proc/net/route","r",NULL); while ( ret != G_IO_STATUS_EOF ){ ret = g_io_channel_read_line_string(procroute,buf,NULL,NULL); if (check_for_string("FFFFFFFF",buf->str)){ active = 1; } } g_io_channel_shutdown(procroute,TRUE,NULL); return active; }