1pass.c
branchgtkui
changeset 45 cf6a06f368e6
parent 39 ddb45e88adc9
child 46 fe4f59680246
equal deleted inserted replaced
44:2150bce729df 45:cf6a06f368e6
    15 #include "pkcs5_pbkdf2.h"
    15 #include "pkcs5_pbkdf2.h"
    16 #include "aes.h"
    16 #include "aes.h"
    17 #include "base64.h"
    17 #include "base64.h"
    18 #include "md5.h"
    18 #include "md5.h"
    19 #include "keyhook.h"
    19 #include "keyhook.h"
       
    20 
    20 #include <gtk/gtk.h>
    21 #include <gtk/gtk.h>
       
    22 #include <gdk/gdk.h>
       
    23 #include <gdk/gdkx.h>
       
    24 #include <gdk/gdkkeysyms.h>
       
    25 #include <X11/Xlib.h>
       
    26 #include <X11/Xlibint.h>
    21 
    27 
    22 #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
    28 #define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) )
    23 
    29 
    24 // plug in a Griffin Powermate, make sure you have access to it, and run with
    30 // plug in a Griffin Powermate, make sure you have access to it, and run with
    25 //  --powermate=/dev/input/eventX
    31 //  --powermate=/dev/input/eventX
   182 
   188 
   183 static lua_State *luaState = NULL;
   189 static lua_State *luaState = NULL;
   184 static const uint8_t zero16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
   190 static const uint8_t zero16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 };
   185 static const char saltprefix[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' };
   191 static const char saltprefix[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' };
   186 
   192 
       
   193 static int makeLuaCallback(lua_State *L, const int idx)
       
   194 {
       
   195     assert(lua_isfunction(L, idx));
       
   196     lua_pushvalue(L, idx);  // copy the Lua callback (luaL_ref() pops it).
       
   197     return luaL_ref(L, LUA_REGISTRYINDEX);
       
   198 } // makeLuaCallback
       
   199 
   187 static inline int retvalStringBytes(lua_State *L, const uint8_t *str, size_t len)
   200 static inline int retvalStringBytes(lua_State *L, const uint8_t *str, size_t len)
   188 {
   201 {
   189     if (str != NULL)
   202     if (str != NULL)
   190         lua_pushlstring(L, (const char *) str, len);
   203         lua_pushlstring(L, (const char *) str, len);
   191     else
   204     else
   373     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
   386     gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE);
   374     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
   387     gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT);
   375     gtk_container_add(GTK_CONTAINER(content_area), entry);
   388     gtk_container_add(GTK_CONTAINER(content_area), entry);
   376 
   389 
   377     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
   390     gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
       
   391     gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
       
   392     gtk_window_set_skip_taskbar_hint(GTK_WINDOW(dialog), TRUE);
       
   393     gtk_window_set_skip_pager_hint(GTK_WINDOW(dialog), TRUE);
   378     gtk_widget_show_all(dialog);
   394     gtk_widget_show_all(dialog);
   379     gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
   395     gtk_window_set_keep_above(GTK_WINDOW(dialog), TRUE);
   380     const int ok = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT);
   396     const int ok = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT);
   381     retvalString(L, ok ? (const char *) gtk_entry_get_text(GTK_ENTRY(entry)) : NULL);
   397     retvalString(L, ok ? (const char *) gtk_entry_get_text(GTK_ENTRY(entry)) : NULL);
   382     gtk_widget_destroy(dialog);
   398     gtk_widget_destroy(dialog);
   390     const char *str = luaL_checkstring(L, 1);
   406     const char *str = luaL_checkstring(L, 1);
   391     gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), str, -1);
   407     gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), str, -1);
   392     gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, -1);
   408     gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, -1);
   393 } // copyToClipboard
   409 } // copyToClipboard
   394 
   410 
   395 
   411 static gboolean checkForEscapeKey(GtkWidget *widget, GdkEvent *event, gpointer arg)
   396 static int makeGuiMenu(lua_State *L)
   412 {
   397 {
   413     if ((event->type == GDK_KEY_PRESS) && (event->key.keyval == GDK_KEY_Escape))
   398     return retvalPointer(L, gtk_menu_new());
   414     {
   399 } // makeGuiMenu
   415         // !!! FIXME: this is a little hacky
   400 
   416         lua_getglobal(luaState, "escapePressed");
   401 
   417         lua_call(luaState, 0, 0);
   402 static void clickedMenuItem(void *arg)
   418         return TRUE;
   403 {
   419     } // if
   404     // This is the callback from GTK+; now call into our actual Lua callback!
   420 
       
   421     return FALSE;  // pass this to other event handlers.
       
   422 } // checkForEscapeKey
       
   423 
       
   424 static gboolean wasSearchDeleteText = FALSE;  // HACK to workaround gtk+ nonsense.
       
   425 static void searchChanged(GtkEditable *editable, gpointer arg)
       
   426 {
   405     const int callback = (int) ((size_t)arg);
   427     const int callback = (int) ((size_t)arg);
       
   428     GtkWidget *vbox = gtk_widget_get_parent(GTK_WIDGET(editable));
   406     lua_rawgeti(luaState, LUA_REGISTRYINDEX, callback);
   429     lua_rawgeti(luaState, LUA_REGISTRYINDEX, callback);
       
   430     lua_pushlightuserdata(luaState, vbox);
       
   431     lua_pushstring(luaState, gtk_entry_get_text(GTK_ENTRY(editable)));
       
   432     lua_call(luaState, 2, 0);
       
   433     gtk_widget_grab_focus(GTK_WIDGET(editable));
       
   434     if (wasSearchDeleteText)  // HACK to workaround gtk+ nonsense.
       
   435     {
       
   436         gtk_editable_set_position(editable, -1);
       
   437         wasSearchDeleteText = FALSE;
       
   438     } // if
       
   439 } // searchChanged
       
   440 
       
   441 // HACK to workaround gtk+ nonsense.
       
   442 static void searchDeleteText(GtkEditable *editable, gint start_pos, gint end_pos, gpointer user_data)
       
   443 {
       
   444     wasSearchDeleteText = TRUE;
       
   445 } // searchDeleteText
       
   446 
       
   447 static void destroyLuaCallback(const int callback)
       
   448 {
       
   449     //printf("unref callback %d\n", callback);
       
   450     luaL_unref(luaState, LUA_REGISTRYINDEX, callback);
       
   451 } // destroyLuaCallback
       
   452 
       
   453 static void destroyCallback(GtkWidget *widget, gpointer arg)
       
   454 {
       
   455     destroyLuaCallback((int) ((size_t)arg));
       
   456 } // destroyCallback
       
   457 
       
   458 static void destroyTopLevelMenu(GtkWidget *widget, gpointer arg)
       
   459 {
       
   460     // !!! FIXME: hack
       
   461     int *cbs = (int *) arg;
       
   462     lua_rawgeti(luaState, LUA_REGISTRYINDEX, cbs[1]);
   407     lua_call(luaState, 0, 0);
   463     lua_call(luaState, 0, 0);
       
   464     destroyLuaCallback(cbs[0]);
       
   465     destroyLuaCallback(cbs[1]);
       
   466     free(cbs);
       
   467 } // destroyTopLevelMenu
       
   468 
       
   469 #if 0
       
   470 static gboolean
       
   471 mappedWindow(GtkWidget *widget, GdkEvent *event, gpointer user_data)
       
   472 {
       
   473     GdkEventClient e;
       
   474     memset(&e, '\0', sizeof (e));
       
   475     e.type = GDK_CLIENT_EVENT;
       
   476     e.window = gtk_widget_get_window(widget);
       
   477     e.send_event = 1;
       
   478     e.message_type = gdk_atom_intern_static_string("_NET_ACTIVE_WINDOW");
       
   479     e.data_format = 32;
       
   480     e.data.l[0] = 1;
       
   481     e.data.l[1] = (long) gdk_x11_get_server_time(e.window);
       
   482     e.data.l[2] = 0;
       
   483 
       
   484     gdk_window_raise (e.window);
       
   485     gdk_event_send_client_message((GdkEvent *) &e, gdk_x11_drawable_get_xid(gtk_widget_get_root_window(widget)));
       
   486     return TRUE;
       
   487 }
       
   488 #endif
       
   489 
       
   490 static int guiCreateTopLevelMenu(lua_State *L)
       
   491 {
       
   492     const char *title = luaL_checkstring(L, 1);
       
   493     const int changedCallback = makeLuaCallback(L, 2);
       
   494     const int destroyedCallback = makeLuaCallback(L, 3);
       
   495 
       
   496     int *cbs = (int *) malloc(sizeof (int) * 2);  // !!! FIXME: hack
       
   497     cbs[0] = changedCallback;
       
   498     cbs[1] = destroyedCallback;
       
   499 
       
   500     GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
       
   501     gtk_window_set_keep_above(window, TRUE);
       
   502     gtk_window_set_skip_taskbar_hint(window, TRUE);
       
   503     gtk_window_set_skip_pager_hint(window, TRUE);
       
   504     g_signal_connect(window, "destroy", G_CALLBACK(destroyTopLevelMenu), cbs);
       
   505     gtk_window_set_title(window, title);
       
   506     gtk_window_set_position(window, GTK_WIN_POS_MOUSE);
       
   507     gtk_window_set_decorated(window, FALSE);
       
   508     gtk_window_set_resizable(window, FALSE);
       
   509     GtkEntry *search = GTK_ENTRY(gtk_entry_new());
       
   510     g_signal_connect(search, "key-press-event", G_CALLBACK(checkForEscapeKey), window);
       
   511     gtk_entry_set_text(search, "Search...");
       
   512     g_signal_connect(search, "changed", G_CALLBACK(searchChanged), (gpointer) ((size_t)changedCallback));
       
   513     g_signal_connect(search, "delete-text", G_CALLBACK(searchDeleteText), 0); // HACK to workaround gtk+ nonsense.
       
   514 
       
   515 //    g_signal_connect(window, "map-event", G_CALLBACK(mappedWindow), NULL);
       
   516 
       
   517 
       
   518     GtkVBox *vbox = GTK_VBOX(gtk_vbox_new(FALSE, 0));
       
   519     gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
       
   520 
       
   521     gtk_box_pack_start(GTK_BOX(vbox), GTK_WIDGET(search), FALSE, FALSE, 0);
       
   522     gtk_widget_show(GTK_WIDGET(search));
       
   523 
       
   524     GtkWidget *vsep = GTK_WIDGET(gtk_vseparator_new());
       
   525     gtk_box_pack_start(GTK_BOX(vbox), vsep, FALSE, FALSE, 0);
       
   526     gtk_widget_show(vsep);
       
   527 
       
   528     return retvalPointer(L, vbox);
       
   529 } // guiCreateTopLevelMenu
       
   530 
       
   531 static void clickedMenuItem(GtkButton *button, gpointer arg)
       
   532 {
       
   533     lua_rawgeti(luaState, LUA_REGISTRYINDEX, (int) ((size_t)arg));
       
   534     lua_pushlightuserdata(luaState, button);
       
   535     lua_call(luaState, 1, 0);
   408 } // clickedMenuItem
   536 } // clickedMenuItem
   409 
   537 
   410 #if 0  // !!! FIXME: figure out how to fire this.
   538 static int guiAddMenuItem(lua_State *L)
   411 static void deletedMenuItem(void *arg)
   539 {
   412 {
   540     GtkWidget *vbox = (GtkWidget *) lua_touserdata(L, 1);
   413     // Clean up the Lua function we referenced in the Registry.
       
   414     const int callback = (int) ((size_t)arg);
       
   415 printf("unref callback %d\n", callback);
       
   416     luaL_unref(luaState, LUA_REGISTRYINDEX, callback);
       
   417 } // deletedMenuItem
       
   418 #endif
       
   419 
       
   420 static int appendGuiMenuItem(lua_State *L)
       
   421 {
       
   422     const int argc = lua_gettop(L);
       
   423     GtkWidget *menu = (GtkWidget *) lua_touserdata(L, 1);
       
   424     const char *label = luaL_checkstring(L, 2);
   541     const char *label = luaL_checkstring(L, 2);
   425     GtkWidget *item = gtk_menu_item_new_with_label(label);
   542     const int callback = makeLuaCallback(L, 3);
   426 
   543     GtkWidget *item = GTK_WIDGET(gtk_button_new_with_label(label));
   427     if ((argc >= 3) && (!lua_isnil(L, 3)))
   544     g_signal_connect(item, "key-press-event", G_CALLBACK(checkForEscapeKey), NULL);
   428     {
   545     g_signal_connect(item, "clicked", G_CALLBACK(clickedMenuItem), (gpointer) ((size_t)callback));
   429         assert(lua_isfunction(L, 3));
   546     g_signal_connect(item, "destroy", G_CALLBACK(destroyCallback), (gpointer) ((size_t)callback));
   430         lua_pushvalue(L, 3);  // copy the Lua callback (luaL_ref() pops it).
   547 
   431         const int callback = luaL_ref(L, LUA_REGISTRYINDEX);
   548     //gtk_button_set_image(button, gtk_image_new_from_stock(GTK_STOCK_OPEN, GTK_ICON_SIZE_MENU));
   432         gtk_signal_connect_object(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(clickedMenuItem), (gpointer) ((size_t)callback));
   549     gtk_button_set_alignment (GTK_BUTTON(item), 0.0f, 0.5f);
   433     } // if
   550     gtk_button_set_relief(GTK_BUTTON(item), GTK_RELIEF_NONE);
   434 
   551     gtk_box_pack_start(GTK_BOX(vbox), item, FALSE, FALSE, 0);
   435     gtk_widget_show(item);
   552     gtk_widget_show(item);
   436     gtk_menu_append(menu, item);
       
   437     return retvalPointer(L, item);
   553     return retvalPointer(L, item);
   438 } // appendGuiMenuItem
   554 } // guiAddMenuItem
   439 
   555 
   440 
   556 static int guiRemoveAllMenuItems(lua_State *L)
   441 static int setGuiMenuItemSubmenu(lua_State *L)
   557 {
   442 {
   558     GtkWidget *vbox = (GtkWidget *) lua_touserdata(L, 1);
   443     GtkMenuItem *item = (GtkMenuItem *) lua_touserdata(L, 1);
   559     GList *children = gtk_container_get_children(GTK_CONTAINER(vbox));
   444     GtkWidget *submenu = (GtkWidget *) lua_touserdata(L, 2);
   560     GList *iter;
   445     gtk_menu_item_set_submenu(item, submenu);
   561 
       
   562     gtk_widget_hide(vbox);
       
   563     for (iter = children; iter != NULL; iter = g_list_next(iter))
       
   564     {
       
   565         if (G_OBJECT_TYPE(iter->data) == GTK_TYPE_BUTTON)
       
   566              gtk_widget_destroy(GTK_WIDGET(iter->data));
       
   567     } // for
       
   568     g_list_free(children);
       
   569 
   446     return 0;
   570     return 0;
   447 } // setGuiMenuItemSubmenu
   571 } // guiRemoveAllMenuItems
   448 
   572 
   449 
   573 static int guiDestroyMenu(lua_State *L)
   450 static int popupGuiMenu(lua_State *L)
   574 {
   451 {
   575     GtkWidget *widget = (GtkWidget *) lua_touserdata(L, 1);
   452     GtkMenu *menu = (GtkMenu *) lua_touserdata(L, 1);
   576     gtk_widget_destroy(gtk_widget_get_toplevel(widget));
   453     gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time());
       
   454     return 0;
   577     return 0;
   455 } // popupGuiMenu
   578 } // guiDestroyMenu
       
   579 
       
   580 static int guiShowWindow(lua_State *L)
       
   581 {
       
   582     GtkWidget *widget = (GtkWidget *) lua_touserdata(L, 1);
       
   583     //gtk_container_resize_children(GTK_CONTAINER(vbox));
       
   584     gtk_widget_show(widget);
       
   585     GtkWidget *toplevel = gtk_widget_get_toplevel(widget);
       
   586     gtk_window_present(GTK_WINDOW(toplevel));
       
   587     return 0;
       
   588 } // guiShowWindow
       
   589 
       
   590 static int guiCreateSubMenu(lua_State *L)
       
   591 {
       
   592     GtkWidget *widget = (GtkWidget *) lua_touserdata(L, 1);
       
   593     GtkWidget *topwindow = gtk_widget_get_toplevel(widget);
       
   594     GtkWindow *window = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
       
   595     gtk_window_set_keep_above(window, TRUE);
       
   596     gtk_window_set_skip_taskbar_hint(window, TRUE);
       
   597     gtk_window_set_skip_pager_hint(window, TRUE);
       
   598     //g_signal_connect(window, "destroy", G_CALLBACK(destroySubMenu), topwindow);
       
   599     gtk_window_set_decorated(window, FALSE);
       
   600 
       
   601     GtkVBox *vbox = GTK_VBOX(gtk_vbox_new(FALSE, 0));
       
   602     gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(vbox));
       
   603 
       
   604     // line the new submenu up...
       
   605     //  !!! FIXME: if overflow off right end of screen, go to the left of (widget) instead.
       
   606     gint basex, basey, x, y;
       
   607     gtk_window_get_position(GTK_WINDOW(topwindow), &basex, &basey);
       
   608     gtk_widget_translate_coordinates(widget, topwindow, 0, 0, &x, &y);
       
   609     x += basex;
       
   610     y += basey;
       
   611     x += widget->allocation.width;
       
   612     gtk_window_move(window, x, y);
       
   613 
       
   614     return retvalPointer(L, vbox);
       
   615 } // guiCreateSubMenu
   456 
   616 
   457 
   617 
   458 static int setPowermateLED_Lua(lua_State *L)
   618 static int setPowermateLED_Lua(lua_State *L)
   459 {
   619 {
   460     const int enable = lua_toboolean(L, 1);
   620     const int enable = lua_toboolean(L, 1);
   551     luaL_openlibs(luaState);
   711     luaL_openlibs(luaState);
   552 
   712 
   553     // Set up initial C functions, etc we want to expose to Lua code...
   713     // Set up initial C functions, etc we want to expose to Lua code...
   554     luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2");
   714     luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2");
   555     luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey");
   715     luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey");
   556     luaSetCFunc(luaState, makeGuiMenu, "makeGuiMenu");
       
   557     luaSetCFunc(luaState, appendGuiMenuItem, "appendGuiMenuItem");
       
   558     luaSetCFunc(luaState, setGuiMenuItemSubmenu, "setGuiMenuItemSubmenu");
       
   559     luaSetCFunc(luaState, popupGuiMenu, "popupGuiMenu");
       
   560     luaSetCFunc(luaState, giveControlToGui, "giveControlToGui");
   716     luaSetCFunc(luaState, giveControlToGui, "giveControlToGui");
   561     luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt");
   717     luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt");
   562     luaSetCFunc(luaState, copyToClipboard, "copyToClipboard");
   718     luaSetCFunc(luaState, copyToClipboard, "copyToClipboard");
   563     luaSetCFunc(luaState, setPowermateLED_Lua, "setPowermateLED");
   719     luaSetCFunc(luaState, setPowermateLED_Lua, "setPowermateLED");
       
   720 
       
   721     luaSetCFunc(luaState, guiCreateTopLevelMenu, "guiCreateTopLevelMenu");
       
   722     luaSetCFunc(luaState, guiCreateSubMenu, "guiCreateSubMenu");
       
   723     luaSetCFunc(luaState, guiAddMenuItem, "guiAddMenuItem");
       
   724     luaSetCFunc(luaState, guiRemoveAllMenuItems, "guiRemoveAllMenuItems");
       
   725     luaSetCFunc(luaState, guiDestroyMenu, "guiDestroyMenu");
       
   726     luaSetCFunc(luaState, guiShowWindow, "guiShowWindow");
   564 
   727 
   565     // Set up argv table...
   728     // Set up argv table...
   566     lua_newtable(luaState);
   729     lua_newtable(luaState);
   567     int i;
   730     int i;
   568     int luai = 1;
   731     int luai = 1;