tomb-gtk-tray.c (10764B)
1 /* Tomb - encrypted storage undertaker 2 * 3 * (c) Copyright 2007-2011 Denis Roio <jaromil@dyne.org> 4 * 5 * This source code is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Public License as published 7 * by the Free Software Foundation; either version 3 of the License, 8 * or (at your option) any later version. 9 * 10 * This source code is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 13 * Please refer to the GNU Public License for more details. 14 * 15 * You should have received a copy of the GNU Public License along with 16 * this source code; if not, write to: 17 * Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 18 */ 19 20 #include <stdio.h> 21 #include <stdlib.h> 22 #include <unistd.h> 23 #include <string.h> 24 #include <errno.h> 25 #include <libgen.h> 26 27 #include <sys/types.h> 28 #include <sys/wait.h> 29 30 #include <gtk/gtk.h> 31 #include <libnotify/notify.h> 32 33 /* The Tomb icon is an artwork by Jordi aka MonMort 34 a nomadic graffiti artist from Barcelona */ 35 #include <monmort.xpm> 36 37 GdkPixbuf *pb_monmort; 38 GtkStatusIcon *status_tomb; 39 GtkMenu *menu_left, *menu_right; 40 41 NotifyNotification *notice; 42 GError *error; 43 44 char mapper[256]; 45 char filename[256]; 46 char mountpoint[256]; 47 48 // forward declaration of callbacks 49 gboolean left_click(GtkWidget *w, GdkEvent *e); 50 gboolean cb_view(GtkWidget *w, GdkEvent *e); 51 gboolean cb_close(GtkWidget *w, GdkEvent *e); 52 gboolean cb_slam(GtkWidget *w, GdkEvent *e); 53 54 gboolean right_click(GtkWidget *w, GdkEvent *e); 55 gboolean cb_about(GtkWidget *w, GdkEvent *e); 56 57 58 int main(int argc, char **argv) { 59 GtkWidget *item_close, *item_slam; 60 GtkWidget *item_view, *item_about; 61 gint menu_x, menu_y; 62 gboolean push_in = TRUE; 63 64 char tomb_file[512]; 65 char tooltip[256]; 66 67 // gtk_set_locale(); 68 gtk_init(&argc, &argv); 69 70 // get the information from commandline 71 if(argc<2) { 72 fprintf(stderr, "error: need at least one argument, the name of an open tomb.\n"); 73 exit(1); 74 } else { 75 // TODO: check if mapper really exists 76 snprintf(mapper,255, "%s", argv[1]); 77 } 78 79 snprintf(filename,255, "%s", argv[1]); 80 snprintf(mountpoint,255, "/media/%s.tomb", argv[1]); 81 82 // libnotify 83 notify_init("Tomb"); 84 85 // set and show the status icon 86 pb_monmort = gdk_pixbuf_new_from_xpm_data(monmort); 87 status_tomb = gtk_status_icon_new_from_pixbuf(pb_monmort); 88 // gtk_status_icon_set_name(status_tomb, "tomb"); 89 gtk_status_icon_set_title(status_tomb, "Tomb"); 90 91 snprintf(tooltip,255,"%s",filename); 92 gtk_status_icon_set_tooltip_text (status_tomb, tooltip); 93 94 // LEFT click menu 95 menu_left = (GtkMenu*) gtk_menu_new(); 96 // view 97 item_view = gtk_menu_item_new_with_label("Explore"); 98 gtk_menu_attach(menu_left, item_view, 0, 1, 0, 1); 99 g_signal_connect_swapped(item_view, "activate", G_CALLBACK(cb_view), NULL); 100 gtk_widget_show(item_view); 101 // close 102 item_close = gtk_menu_item_new_with_label("Close"); 103 gtk_menu_attach(menu_left, item_close, 0, 1, 1, 2); 104 g_signal_connect_swapped(item_close, "activate", G_CALLBACK(cb_close), NULL); 105 gtk_widget_show(item_close); 106 // slam 107 item_slam = gtk_menu_item_new_with_label("Slam"); 108 gtk_menu_attach(menu_left, item_slam, 0, 1, 2, 3); 109 g_signal_connect_swapped(item_slam, "activate", G_CALLBACK(cb_slam), NULL); 110 gtk_widget_show(item_slam); 111 112 // connect it 113 g_signal_connect_swapped(status_tomb, "activate", G_CALLBACK(left_click), menu_left); 114 115 116 // RIGHT click menu 117 menu_right = (GtkMenu*) gtk_menu_new(); 118 // about 119 item_about = gtk_menu_item_new_with_label("About"); 120 gtk_menu_attach(menu_right, item_about, 0, 1, 0, 1); 121 g_signal_connect_swapped(item_about, "activate", G_CALLBACK(cb_about), NULL); 122 g_signal_connect_swapped(item_about, "popup-menu", G_CALLBACK(cb_about), NULL); 123 gtk_widget_show(item_about); 124 // connect it 125 g_signal_connect_swapped(status_tomb, "popup-menu", G_CALLBACK(right_click), menu_right); 126 127 // status icon 128 #if (HAVE_NOTIFY_NOTIFICATION_NEW_WITH_STATUS_ICON) 129 notice = notify_notification_new_with_status_icon 130 ("Tomb encrypted undertaker", 131 "We started digging out bones", 132 NULL, status_tomb); 133 #else 134 notice = notify_notification_new 135 ("Tomb encrypted undertaker", 136 "We started digging out bones", 137 NULL); 138 #endif 139 notify_notification_set_icon_from_pixbuf(notice, pb_monmort); 140 141 notify_notification_show(notice, &error); 142 143 gtk_main(); 144 145 notify_uninit(); 146 147 exit(0); 148 149 } 150 151 // callbacks left click 152 gboolean left_click(GtkWidget *w, GdkEvent *e) { 153 gtk_menu_popup(menu_left, NULL, NULL, 154 gtk_status_icon_position_menu, status_tomb, 155 1, gtk_get_current_event_time()); 156 return TRUE; 157 } 158 gboolean cb_view(GtkWidget *w, GdkEvent *e) { 159 int pipefd[2]; 160 pid_t cpid; 161 char buf; 162 int c, res; 163 char map[256]; 164 165 if (pipe(pipefd) <0) { 166 fprintf(stderr,"pipe creation error: %s\n", strerror(errno)); 167 return FALSE; 168 } 169 170 cpid = fork(); 171 if (cpid == -1) { 172 fprintf(stderr,"fork error: %s\n", strerror(errno)); 173 return FALSE; 174 } 175 if (cpid == 0) { // Child 176 close(pipefd[1]); // close unused write end 177 for(c=0; read(pipefd[0], &buf, 1) > 0; c++) 178 map[c] = buf; 179 close(pipefd[0]); 180 map[c] = 0; 181 execlp("xdg-open", "xdg-open", map, (char*)NULL); 182 _exit(1); 183 } 184 close(pipefd[0]); // close unused read end 185 write(pipefd[1], mountpoint, strlen(mountpoint)); 186 close(pipefd[1]); // reader will see EOF 187 188 return TRUE; 189 } 190 191 192 gboolean cb_close(GtkWidget *w, GdkEvent *e) { 193 int pipefd[2]; 194 pid_t cpid; 195 char buf; 196 int c, res; 197 char map[256]; 198 199 if (pipe(pipefd) <0) { 200 fprintf(stderr,"pipe creation error: %s\n", strerror(errno)); 201 return FALSE; 202 } 203 204 cpid = fork(); 205 if (cpid == -1) { 206 fprintf(stderr,"fork error: %s\n", strerror(errno)); 207 return FALSE; 208 } 209 if (cpid == 0) { // Child 210 close(pipefd[1]); // close unused write end 211 for(c=0; read(pipefd[0], &buf, 1) > 0; c++) 212 map[c] = buf; 213 close(pipefd[0]); 214 map[c] = 0; 215 execlp("tomb", "tomb", "close", map, (char*)NULL); 216 _exit(1); 217 } 218 close(pipefd[0]); // close unused read end 219 write(pipefd[1], mapper, strlen(mapper)); 220 close(pipefd[1]); // reader will see EOF 221 222 waitpid(cpid, &res, 0); 223 if(res==0) { 224 gtk_main_quit(); 225 notify_uninit(); 226 exit(0); 227 } 228 /* tomb-notify "Tomb '$tombname' is too busy." \ 229 "Close all applications and file managers, then try again." 230 */ 231 return TRUE; 232 } 233 234 235 gboolean cb_slam(GtkWidget *w, GdkEvent *e) { 236 int pipefd[2]; 237 pid_t cpid; 238 char buf; 239 int c, res; 240 char map[256]; 241 242 if (pipe(pipefd) <0) { 243 fprintf(stderr,"pipe creation error: %s\n", strerror(errno)); 244 return FALSE; 245 } 246 247 cpid = fork(); 248 if (cpid == -1) { 249 fprintf(stderr,"fork error: %s\n", strerror(errno)); 250 return FALSE; 251 } 252 if (cpid == 0) { // Child 253 close(pipefd[1]); // close unused write end 254 for(c=0; read(pipefd[0], &buf, 1) > 0; c++) 255 map[c] = buf; 256 close(pipefd[0]); 257 map[c] = 0; 258 execlp("tomb", "tomb", "slam", map, (char*)NULL); 259 _exit(1); 260 } 261 close(pipefd[0]); // close unused read end 262 write(pipefd[1], mapper, strlen(mapper)); 263 close(pipefd[1]); // reader will see EOF 264 265 waitpid(cpid, &res, 0); 266 if(res==0) { 267 gtk_main_quit(); 268 notify_uninit(); 269 exit(0); 270 } 271 /* tomb-notify "Tomb '$tombname' is too busy." \ 272 "Close all applications and file managers, then try again." 273 */ 274 return TRUE; 275 } 276 277 // callbacks right click 278 gboolean right_click(GtkWidget *w, GdkEvent *e) { 279 gtk_menu_popup(menu_right, NULL, NULL, 280 gtk_status_icon_position_menu, status_tomb, 281 1, gtk_get_current_event_time()); 282 return TRUE; 283 } 284 gboolean cb_about(GtkWidget *w, GdkEvent *e) { 285 const gchar *authors[] = {"Jaromil - http://jaromil.dyne.org", 286 "Code reviews and contributions by:", 287 "Dreamer, Hellekin O. Wolf, Shining, Mancausoft,", 288 "Anathema, Boyska and Nignux", NULL}; 289 const gchar *artists[] = {"Món Mort - http://monmort.blogspot.com", 290 "Asbesto Molesto - http://freaknet.org/asbesto", 291 NULL}; 292 GtkWidget *dialog = gtk_about_dialog_new(); 293 // gtk_about_dialog_set_name(GTK_ABOUT_DIALOG(dialog), "Tomb GTK Tray"); 294 gtk_about_dialog_set_version(GTK_ABOUT_DIALOG(dialog), "1.4"); 295 gtk_about_dialog_set_copyright(GTK_ABOUT_DIALOG(dialog), 296 "(C)2007-2013 Jaromil @ Dyne.org Foundation"); 297 gtk_about_dialog_set_artists(GTK_ABOUT_DIALOG(dialog), artists); 298 gtk_about_dialog_set_authors(GTK_ABOUT_DIALOG(dialog), authors); 299 300 gtk_about_dialog_set_comments(GTK_ABOUT_DIALOG(dialog), 301 "The Crypto Undertaker\n" 302 "\n" 303 "This program helps people keeping their bones together by taking care of their private data inside encrypted storage filesystems that are easy to access and transport.\n" 304 "\n" 305 "The level of security provided by this program is fairly strong: it uses AES/SHA256 (cbc-essiv) to access the encrypted volumes in realtime so that all what is physically stored on your disc is only in an encrypted form.\n" 306 "Tomb also encourages users to separate keys from data, for instance storing them on USB.\n" 307 "\n" 308 ); 309 gtk_about_dialog_set_website(GTK_ABOUT_DIALOG(dialog), "http://tomb.dyne.org"); 310 gtk_about_dialog_set_logo(GTK_ABOUT_DIALOG(dialog), pb_monmort); 311 gtk_about_dialog_set_logo_icon_name(GTK_ABOUT_DIALOG(dialog), "monmort"); 312 // this below is active since gtk 3.0 so too early for it now 313 // gtk_about_dialog_set_license_type(GTK_ABOUT_DIALOG(dialog), GtkLicense.GTK_LICENSE_GPL_3_0); 314 gtk_about_dialog_set_license(GTK_ABOUT_DIALOG(dialog), 315 "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 3 of the License, or (at your option) any later version.\n" 316 "\n" 317 "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.\n" 318 "\n" 319 "You should have received a copy of the GNU General Public License along with this program.\n" 320 "If not, see <http://www.gnu.org/licenses>\n" 321 "\n" 322 " The latest Tomb sourcecode is published on <http://tomb.dyne.org>\n"); 323 gtk_about_dialog_set_wrap_license(GTK_ABOUT_DIALOG(dialog), TRUE); 324 gtk_dialog_run(GTK_DIALOG (dialog)); 325 gtk_widget_destroy(dialog); 326 return TRUE; 327 } 328 329 330 // GtkWidget *dialog = 331 // gtk_message_dialog_new (NULL, 332 // GTK_DIALOG_DESTROY_WITH_PARENT, 333 // GTK_MESSAGE_INFO, 334 // GTK_BUTTONS_CLOSE, 335 // "Tomb '%s' open on '%s'\n" 336 // "device mapper: %s", filename, mountpoint, mapper); 337 // gtk_dialog_run (GTK_DIALOG (dialog)); 338 // gtk_widget_destroy (dialog);