/* LinPopUp - A Linux enhanced port of Winpopup, running over Samba. * Copyright (c)1998-2000 Jean-Marc Jacquet * Little Igloo Org http://www.LittleIgloo.org * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include #include #include #include #include #include #include "protos.h" static GtkWidget *msg_file_sel; static GtkWidget *send_header; static GtkWidget *send_combo; static GList *combo_items; static void save_send_history (void); static void update_send_history (char *this_name); static int samba_post (gchar * header_text, char *temp_filename) { FILE *output; gchar command_line[2048]; gchar prefix[128]; gchar *head_copy = g_strdup (header_text); gchar *head_text = head_copy; gchar buf_line[80]; gchar *header_master, *header_end, *quote; int i; int hlen = strlen (header_text); char MULTI_RECIPIENTS = (strchr (header_text, ',') != NULL); if (hlen > 100) /* -- substantially less than "prefix" size -- */ { alert_ok ("Error", "Send-to list is too long.", "Ok"); g_free (head_copy); return FALSE; } header_end = (gchar *) (head_text + hlen); /* -- destroy erroneous embedded single-quotes. -- */ while ((quote = strchr (head_text, '\'')) != NULL) *quote = '-'; if (MULTI_RECIPIENTS) sprintf (prefix, "echo '[ To: %s ]\n' ; ", head_copy); while (head_text < header_end) { if ((header_master = strchr (head_text, ',')) != NULL) *header_master = '\0'; else header_master = header_end; /* -- launch smbclient and read output from pipe -- */ //sprintf (command_line, "( %s cat %s ) | smbclient -M \"%s\" -U \"%s\" -n \"%s\" \"%s\"", (MULTI_RECIPIENTS ? prefix : ""), temp_filename, head_text, user_rc.samba_username, user_rc.samba_nbiosname, user_rc.samba_misc); sprintf (command_line, "( %s cat %s ) | smbclient -M \"%s\" -U \"%s\" -n \"%s\" \"%s\" 2>&1", (MULTI_RECIPIENTS ? prefix : ""), temp_filename, head_text, user_rc.samba_username, user_rc.samba_nbiosname, user_rc.samba_misc); output = popen (command_line, "r"); i = fread (command_line, 1, sizeof (command_line), output); pclose (output); command_line[i] = 0; /* -- sommaire investigation of the output -- */ if (strstr (command_line, "sh: smbclient: ")) { /* * don't check for "command not found", as that message can be * different if another LANGuage is used than C / english */ sprintf (buf_line, "\n`smbclient' command cannot be run;\nnot installed?"); alert_ok ("Error", buf_line, "Ok"); g_free (head_copy); return FALSE; } if (strstr (command_line, "nknown host")) { sprintf (buf_line, "\n\nUnknown host : %s", head_text); alert_ok ("Error", buf_line, "Ok"); g_free (head_copy); return FALSE; } if (strstr (command_line, "error connecting to") || (strstr (command_line, "onnection to") && strstr (command_line, "failed"))) { sprintf (buf_line, "\n\nHost unreachable :\n %s", head_text); alert_ok ("Error", buf_line, "Ok"); g_free (head_copy); return FALSE; } if (strstr (command_line, "ERRmsgoff")) { sprintf (buf_line, "\n\n%s can't receive\nwinpopup messages.", head_text); alert_ok ("Error", buf_line, "Ok"); g_free (head_copy); return FALSE; } if (strstr (command_line, "Control-D\nsent") && strstr (command_line, "bytes")) { if (!MULTI_RECIPIENTS && user_rc.confirm) alert_ok ("LinPopUp", "\n\nMessage succesfully sent.", "Ok"); } else if (!MULTI_RECIPIENTS) alert_ok_text ("LinPopup -smbclient output", command_line); head_text = header_master + 1; } g_free (head_copy); return TRUE; } void send_send (GtkWidget * widget, gpointer * data) { gchar *header_text; gchar message_text[2048]; guint message_length; char IS_TRUNCATED = FALSE; static char temp_filename[]="/tmp/LinPopUpXXXXXX"; int file_handle_temp; gchar new_header[256]; /* -- retrieving header text, and checking for a destination -- */ if (!strlen (header_text = gtk_entry_get_text (GTK_ENTRY (send_header)))) { alert_ok (" Error", "\nPlease enter a destination.", "Ok"); return; } /* -- retrieving message text, cut big texts in parts -- */ message_length = gtk_text_get_length (GTK_TEXT (send_text)); if (message_length > 1400) { IS_TRUNCATED = TRUE; strcpy (message_text, gtk_editable_get_chars (GTK_EDITABLE (send_text), 0, 1400)); message_length = 1400; while (message_text[message_length] != 10) --message_length; message_text[message_length] = 0; strcat (message_text, "\n=== TO BE CONTINUED ==="); gtk_text_freeze (GTK_TEXT (send_text)); gtk_text_set_point (GTK_TEXT (send_text), message_length); gtk_text_backward_delete (GTK_TEXT (send_text), message_length); gtk_text_set_point (GTK_TEXT (send_text), 0); gtk_text_thaw (GTK_TEXT (send_text)); } else { gchar *pc; pc = gtk_editable_get_chars (GTK_EDITABLE (send_text), 0, -1); strcpy (message_text, pc); g_free (pc); } /* -- write message text to a tempory file -- */ if ( (file_handle_temp = mkstemp(temp_filename)) == -1 ) return; write (file_handle_temp, message_text, strlen (message_text)); close (file_handle_temp); /* -- add self? -- */ if (user_rc.self_send) sprintf (new_header, "%s,%s", user_rc.samba_nbiosname, header_text); else sprintf (new_header, "%s", header_text); /* -- cowardly posting it via samba, * update and save send history, * and close the send window in many case-- */ if (samba_post (new_header, temp_filename) && !IS_TRUNCATED) { update_send_history (header_text); save_send_history (); gtk_widget_destroy (send_window); send_window = NULL; } /* -- then remove the tempory file -- */ unlink (temp_filename); } static void send_cancel (GtkWidget * widget, gpointer * data) { /* -- if a message was entered, asking for confirmation -- */ if (gtk_text_get_length (GTK_TEXT (send_text))) if (alert_dialog ("", "\nA new message was entered.\n\nCancel anyway ?", "Yes", "No", 2) == 2) return; gtk_widget_destroy (send_window); send_window = NULL; } static void message_load_ok (GtkWidget * widget, GtkFileSelection * file_sel) { char *filename; filename = gtk_file_selection_get_filename (GTK_FILE_SELECTION (file_sel)); if (filename != NULL) { FILE *in; char buf[1024]; in = fopen (filename, "r"); if (in == NULL) { sprintf (buf, "\n Unable to Open '%s' \n", filename); alert_ok ("File Error", buf, "ok"); } else { gtk_text_freeze (GTK_TEXT (send_text)); while (fgets (buf, 1024, in)) gtk_text_insert (GTK_TEXT (send_text), NULL, &send_text->style->black, NULL, buf, strlen (buf)); gtk_text_thaw (GTK_TEXT (send_text)); fclose (in); } } gtk_widget_destroy (GTK_WIDGET (file_sel)); msg_file_sel = NULL; } static void message_load_cancel (GtkWidget * widget, GtkFileSelection * file_sel) { gtk_widget_destroy (GTK_WIDGET (file_sel)); msg_file_sel = NULL; } void message_load (GtkWidget * widget, gpointer data) { if (msg_file_sel == NULL) { msg_file_sel = gtk_file_selection_new ("Load Message text..."); gtk_signal_connect (GTK_OBJECT (msg_file_sel), "destroy", GTK_SIGNAL_FUNC (gtk_widget_destroy), msg_file_sel); gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (msg_file_sel)->ok_button), "clicked", GTK_SIGNAL_FUNC (message_load_ok), msg_file_sel); gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (msg_file_sel)->cancel_button), "clicked", GTK_SIGNAL_FUNC (message_load_cancel), msg_file_sel); } if (GTK_WIDGET_VISIBLE (msg_file_sel)) return; else gtk_widget_show (msg_file_sel); } void reply_message (void) { if (current_showed_message) { is_it_a_reply = TRUE; send_message (); } } static void update_send_history (char *this_name) { char *ptr; GList *list = combo_items; while (list) { ptr = list->data; if (!strcmp (ptr, this_name)) { gtk_entry_set_text (GTK_ENTRY (send_header), this_name); return; } list = list->next; } if (combo_items == NULL) combo_items = g_list_append (combo_items, strdup (this_name)); else combo_items = g_list_insert (combo_items, strdup (this_name), 0); gtk_combo_set_popdown_strings (GTK_COMBO (send_combo), combo_items); } static void load_send_history (void) { FILE *history_file; char this_path[1024]; char this_line[256]; char *ptr; if (!(ptr = getenv ("HOME"))) fatal_error (2, "HOME"); sprintf (this_path, "%s/.linpopup.history", ptr); if (access (this_path, F_OK)) return; if ((history_file = fopen (this_path, "r")) == NULL) return; while (fgets (this_line, sizeof (this_line), history_file) != NULL) { if (this_line[strlen (this_line) - 1] == '\n') this_line[strlen (this_line) - 1] = 0; if (strlen (this_line)) combo_items = g_list_append (combo_items, strdup (this_line)); } fclose (history_file); gtk_combo_set_popdown_strings (GTK_COMBO (send_combo), combo_items); } static void save_send_history (void) { FILE *history_file; char this_path[1024]; GList *list = combo_items; char *ptr; int compt = MAX_SEND_HISTORY_LINES; if (!(ptr = getenv ("HOME"))) fatal_error (2, "HOME"); sprintf (this_path, "%s/.linpopup.history", ptr); if ((history_file = fopen (this_path, "w")) == NULL) return; while (list && compt--) { ptr = list->data; fprintf (history_file, "%s\n", ptr); list = list->next; } fflush (history_file); fclose (history_file); } void send_message (void) { GtkWidget *send_vbox; GtkWidget *send_statusbar; GtkWidget *send_frame; GtkWidget *send_table; GtkWidget *send_button_send; GtkWidget *send_button_cancel; int send_context_id; gint x, y, w, h; msg_file_sel = NULL; if (send_window != NULL) { gtk_widget_show (send_window); return; } /* -- First, the window -- */ send_window = create_dialog_window (GTK_WINDOW_TOPLEVEL, 0, "LinPopUp", &send_vbox); gdk_window_get_origin (window->window, &x, &y); gtk_widget_set_uposition (send_window, x, y); gdk_window_get_size (window->window, &w, &h); gtk_window_set_default_size (GTK_WINDOW (send_window), w, h); gdk_window_set_decorations (send_window->window, GDK_DECOR_BORDER | GDK_DECOR_TITLE | GDK_DECOR_RESIZEH); send_text = gtk_text_new (NULL, NULL); /* -- Top frame first packed to the vbox -- */ send_frame = create_frame (send_vbox, " Send to :", FALSE, TRUE, GTK_SHADOW_ETCHED_IN); gtk_container_border_width (GTK_CONTAINER (send_frame), 2); /* -- Creating frame's widgets -- */ send_combo = gtk_combo_new (); gtk_combo_set_use_arrows_always (GTK_COMBO (send_combo), TRUE); gtk_widget_show (send_combo); combo_items = NULL; send_header = GTK_COMBO (send_combo)->entry; gtk_entry_set_editable (GTK_ENTRY (send_header), 1); load_send_history (); send_button_send = gtk_button_new_with_label ("Send"); gtk_signal_connect (GTK_OBJECT (send_button_send), "clicked", GTK_SIGNAL_FUNC (send_send), NULL); gtk_widget_show (send_button_send); send_button_cancel = gtk_button_new_with_label ("Cancel"); gtk_signal_connect (GTK_OBJECT (send_button_cancel), "clicked", GTK_SIGNAL_FUNC (send_cancel), NULL); gtk_widget_show (send_button_cancel); /*-- attaching frame's widget to a table, and packing it to the frame --*/ send_table = gtk_table_new (2, 4, TRUE); gtk_table_set_col_spacings (GTK_TABLE (send_table), 5); gtk_table_set_row_spacings (GTK_TABLE (send_table), 5); gtk_container_border_width (GTK_CONTAINER (send_table), 10); gtk_table_attach (GTK_TABLE (send_table), send_combo, 0, 3, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach (GTK_TABLE (send_table), send_button_send, 3, 4, 0, 1, GTK_FILL, GTK_FILL, 0, 0); gtk_table_attach (GTK_TABLE (send_table), send_button_cancel, 3, 4, 1, 2, GTK_FILL | GTK_EXPAND, GTK_FILL, 0, 0); gtk_container_add (GTK_CONTAINER (send_frame), send_table); gtk_widget_show (send_table); gtk_widget_show (send_frame); /* -- create a menu below the top frame via create_send_menu defined in menu.c-- */ create_send_menu (send_vbox); /* -- and a text area via create_text defined in text.c -- */ create_text_area (send_text, send_vbox); gtk_text_set_editable (GTK_TEXT (send_text), 1); /* -- and finally a statusbar -- */ send_statusbar = gtk_statusbar_new (); gtk_box_pack_start (GTK_BOX (send_vbox), send_statusbar, FALSE, TRUE, 0); gtk_widget_show (send_statusbar); send_context_id = gtk_statusbar_get_context_id (GTK_STATUSBAR (send_statusbar), " "); /* -- show the window -- */ gtk_widget_show (send_window); /* -- connecting the send_cancel function to the delete event -- */ gtk_signal_connect (GTK_OBJECT (send_window), "delete_event", GTK_SIGNAL_FUNC (send_cancel), NULL); /* -- fill the deliver adress if required -- */ switch (user_rc.deliver) { case DHOST: gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.deliver_adr); break; case GUESS: if (!strcmp (user_rc.guess_adr, "?")) gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.deliver_adr); else gtk_entry_set_text (GTK_ENTRY (send_header), user_rc.guess_adr); break; case BLANK: default: break; } /* -- If this is a reply, fill the destination and text field -- */ if (is_it_a_reply) { struct linpopup_message this_message; char buf[2045]; int char_pos_text, char_pos_buf; GdkColormap *colormap; colormap = gtk_widget_get_colormap (send_window); gdk_color_alloc (colormap, &user_rc.quoted_text_col); read_message (current_showed_message, &this_message); gtk_entry_set_text (GTK_ENTRY (send_header), this_message.host); //We answer to a host not to a user sprintf (buf, "%c %s \n%c ---\n", user_rc.quote, user_rc.quote_string, user_rc.quote); strexpand (buf, "HOST", this_message.host); strexpand (buf, "USER", this_message.sender); gtk_text_freeze (GTK_TEXT (send_text)); gtk_text_insert (GTK_TEXT (send_text), NULL, &user_rc.quoted_text_col, NULL, buf, -1); char_pos_buf = 0; buf[char_pos_buf++] = user_rc.quote; buf[char_pos_buf++] = 32; for (char_pos_text = 0; char_pos_text < strlen (this_message.text); char_pos_text++) { buf[char_pos_buf++] = this_message.text[char_pos_text]; if (this_message.text[char_pos_text] == 10) { buf[char_pos_buf++] = user_rc.quote; buf[char_pos_buf++] = 32; } } buf[char_pos_buf++] = 10; buf[char_pos_buf++] = user_rc.quote; buf[char_pos_buf] = 0; /* -- quoted text appears in user defined color -- */ strcat (buf, " ---"); gtk_text_insert (GTK_TEXT (send_text), NULL, &user_rc.quoted_text_col, NULL, buf, -1); gtk_text_insert (GTK_TEXT (send_text), NULL, &send_text->style->black, NULL, "\n", -1); gtk_text_thaw (GTK_TEXT (send_text)); gtk_text_set_editable (GTK_TEXT (send_text), 1); gtk_widget_grab_focus (send_text); is_it_a_reply = FALSE; } } /* EOF */