author | Ryan C. Gordon <icculus@icculus.org> |
Mon, 23 Dec 2013 20:44:04 -0500 | |
changeset 14 | f359fb8eec3c |
parent 12 | 6a2d5b34d5ca |
child 15 | e2973f4fb366 |
permissions | -rw-r--r-- |
0 | 1 |
#include <stdio.h> |
2 |
#include <stdlib.h> |
|
3 |
#include <string.h> |
|
4 |
#include <assert.h> |
|
5 |
#include "lua.h" |
|
6 |
#include "lauxlib.h" |
|
7 |
#include "lualib.h" |
|
8 |
#include "pkcs5_pbkdf2.h" |
|
9 |
#include "aes.h" |
|
10 |
#include "base64.h" |
|
11 |
#include "md5.h" |
|
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
12 |
#include <gtk/gtk.h> |
0 | 13 |
|
14 |
#define STATICARRAYLEN(x) ( (sizeof ((x))) / (sizeof ((x)[0])) ) |
|
15 |
||
16 |
static lua_State *luaState = NULL; |
|
17 |
static const uint8_t zero16[16] = { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 }; |
|
18 |
static const char saltprefix[] = { 'S', 'a', 'l', 't', 'e', 'd', '_', '_' }; |
|
19 |
||
20 |
static inline int retvalStringBytes(lua_State *L, const uint8_t *str, size_t len) |
|
21 |
{ |
|
22 |
if (str != NULL) |
|
23 |
lua_pushlstring(L, (const char *) str, len); |
|
24 |
else |
|
25 |
lua_pushnil(L); |
|
26 |
return 1; |
|
27 |
} // retvalStringBytes |
|
28 |
||
12
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
29 |
static inline int retvalString(lua_State *L, const char *str) |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
30 |
{ |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
31 |
return retvalStringBytes(L, (const uint8_t *) str, strlen(str)); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
32 |
} // retvalString |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
33 |
|
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
34 |
static inline int retvalPointer(lua_State *L, void *ptr) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
35 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
36 |
if (ptr != NULL) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
37 |
lua_pushlightuserdata(L, ptr); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
38 |
else |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
39 |
lua_pushnil(L); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
40 |
return 1; |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
41 |
} // retvalPointer |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
42 |
|
0 | 43 |
static inline void xorBlock(uint8_t *dst, const uint8_t *src) |
44 |
{ |
|
45 |
int i; |
|
46 |
for (i = 0; i < 16; i++, dst++, src++) |
|
47 |
*dst ^= *src; |
|
48 |
} // xorBlock |
|
49 |
||
50 |
static int decryptUsingKeyAndIvec(uint8_t *data, size_t *datalen, const uint8_t *key, const uint8_t *iv) |
|
51 |
{ |
|
52 |
const size_t blocks = *datalen / 16; |
|
53 |
uint8_t *block = data + ((blocks-1) * 16); // start at final block, work backwards |
|
54 |
const uint8_t *padding = &block[15]; |
|
55 |
uint8_t expkey[aesExpandedKeySize]; |
|
56 |
size_t i; |
|
57 |
||
58 |
if (blocks == 0) |
|
59 |
return 1; // nothing to do. |
|
60 |
||
61 |
aesExpandKey(key, expkey); |
|
62 |
||
63 |
for (i = 0; i < blocks-1; i++) |
|
64 |
{ |
|
65 |
aesDecrypt(block, expkey, block); // decrypt in place. |
|
66 |
xorBlock(block, block-16); |
|
67 |
block -= 16; |
|
68 |
} |
|
69 |
aesDecrypt(block, expkey, block); // decrypt in place. |
|
70 |
xorBlock(block, iv); // xor against initial vector for final block. |
|
71 |
||
72 |
if (*padding > 16) |
|
73 |
return 0; // bad data? |
|
74 |
||
75 |
*datalen -= *padding; |
|
76 |
||
77 |
return 1; |
|
78 |
} // decryptBinaryUsingKeyAndIvec |
|
79 |
||
80 |
||
81 |
static inline int isSalted(const uint8_t *data, const size_t datalen) |
|
82 |
{ |
|
83 |
return ( (datalen > sizeof (saltprefix)) && |
|
84 |
(memcmp(data, saltprefix, sizeof (saltprefix)) == 0) ); |
|
85 |
} // isSalted |
|
86 |
||
87 |
||
88 |
static int decryptUsingPBKDF2(lua_State *L) |
|
89 |
{ |
|
90 |
const char *base64 = luaL_checkstring(L, 1); |
|
91 |
const char *password = luaL_checkstring(L, 2); |
|
92 |
const int iterations = luaL_checkinteger(L, 3); |
|
93 |
size_t datalen = strlen(base64); |
|
94 |
uint8_t *dataptr = (uint8_t *) malloc(datalen); |
|
95 |
uint8_t *data = dataptr; |
|
96 |
base64_decodestate base64state; |
|
97 |
||
98 |
base64_init_decodestate(&base64state); |
|
99 |
datalen = base64_decode_block(base64, (int) datalen, data, &base64state); |
|
100 |
||
101 |
const uint8_t *salt = zero16; |
|
102 |
int saltlen = sizeof (zero16); |
|
103 |
if (isSalted(data, datalen)) |
|
104 |
{ |
|
105 |
salt = data + 8; |
|
106 |
saltlen = 8; |
|
107 |
data += 16; |
|
108 |
datalen -= 16; |
|
109 |
} // if |
|
110 |
||
111 |
uint8_t output[32]; |
|
112 |
pkcs5_pbkdf2(password, strlen(password), salt, saltlen, output, sizeof (output), (unsigned int) iterations); |
|
113 |
||
114 |
const uint8_t *aeskey = &output[0]; |
|
115 |
const uint8_t *aesiv = &output[16]; |
|
116 |
if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv)) |
|
117 |
retvalStringBytes(L, data, datalen); |
|
118 |
else |
|
119 |
lua_pushnil(L); |
|
120 |
||
121 |
free(dataptr); |
|
122 |
return 1; |
|
123 |
} // decryptUsingPBKDF2 |
|
124 |
||
125 |
||
126 |
static int decryptBase64UsingKey(lua_State *L) |
|
127 |
{ |
|
128 |
size_t keylen = 0; |
|
129 |
const char *base64 = luaL_checkstring(L, 1); |
|
130 |
const uint8_t *key = (const uint8_t *) luaL_checklstring(L, 2, &keylen); |
|
131 |
size_t datalen = strlen(base64); |
|
132 |
uint8_t *dataptr = (uint8_t *) malloc(datalen); |
|
133 |
uint8_t *data = dataptr; |
|
134 |
base64_decodestate base64state; |
|
135 |
||
136 |
base64_init_decodestate(&base64state); |
|
137 |
datalen = base64_decode_block(base64, (int) datalen, data, &base64state); |
|
138 |
||
139 |
uint8_t aeskey[16]; |
|
140 |
uint8_t aesiv[16]; |
|
141 |
MD5_CTX md5; |
|
142 |
||
143 |
if (isSalted(data, datalen)) |
|
144 |
{ |
|
145 |
const uint8_t *salt = data + 8; |
|
146 |
const size_t saltlen = 8; |
|
147 |
data += 16; |
|
148 |
datalen -= 16; |
|
149 |
||
150 |
assert(aesNr == 10); // AES-256 needs more rounds. |
|
151 |
assert(aesNk == 4); // hashing size is hardcoded later. |
|
152 |
uint8_t hashing[32]; |
|
153 |
||
154 |
MD5_init(&md5); |
|
155 |
MD5_append(&md5, key, keylen); |
|
156 |
MD5_append(&md5, salt, saltlen); |
|
157 |
MD5_finish(&md5, hashing); |
|
158 |
||
159 |
MD5_init(&md5); |
|
160 |
MD5_append(&md5, hashing, 16); |
|
161 |
MD5_append(&md5, key, keylen); |
|
162 |
MD5_append(&md5, salt, saltlen); |
|
163 |
MD5_finish(&md5, &hashing[16]); |
|
164 |
||
165 |
memcpy(aeskey, hashing, 4 * aesNk); |
|
166 |
memcpy(aesiv, &hashing[4 * aesNk], 16); |
|
167 |
} // if |
|
168 |
else |
|
169 |
{ |
|
170 |
MD5_init(&md5); |
|
171 |
MD5_append(&md5, key, keylen); |
|
172 |
MD5_finish(&md5, aeskey); |
|
173 |
memset(aesiv, '\0', sizeof (aesiv)); |
|
174 |
} // else |
|
175 |
||
176 |
if (decryptUsingKeyAndIvec(data, &datalen, aeskey, aesiv)) |
|
177 |
retvalStringBytes(L, data, datalen); |
|
178 |
else |
|
179 |
lua_pushnil(L); |
|
180 |
||
181 |
free(dataptr); |
|
182 |
return 1; |
|
183 |
} // decryptBase64UsingKey |
|
184 |
||
185 |
||
12
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
186 |
static int runGuiPasswordPrompt(lua_State *L) |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
187 |
{ |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
188 |
const char *hintstr = lua_tostring(L, 1); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
189 |
GtkWidget *dialog = gtk_dialog_new_with_buttons( |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
190 |
"Master Password", NULL, GTK_DIALOG_MODAL, |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
191 |
GTK_STOCK_CANCEL, GTK_RESPONSE_REJECT, |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
192 |
GTK_STOCK_OK, GTK_RESPONSE_ACCEPT, |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
193 |
NULL); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
194 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
195 |
GtkWidget *content_area = gtk_dialog_get_content_area(GTK_DIALOG(dialog)); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
196 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
197 |
if (hintstr != NULL) |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
198 |
{ |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
199 |
GtkWidget *label = gtk_label_new(hintstr); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
200 |
gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
201 |
gtk_container_add(GTK_CONTAINER(content_area), label); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
202 |
} // if |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
203 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
204 |
GtkWidget *entry = gtk_entry_new(); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
205 |
gtk_entry_set_visibility(GTK_ENTRY(entry), FALSE); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
206 |
gtk_entry_set_activates_default(GTK_ENTRY(entry), TRUE); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
207 |
gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_ACCEPT); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
208 |
gtk_container_add(GTK_CONTAINER(content_area), entry); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
209 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
210 |
gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
211 |
gtk_widget_show_all(dialog); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
212 |
const int ok = (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
213 |
retvalString(L, ok ? (const char *) gtk_entry_get_text(GTK_ENTRY(entry)) : NULL); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
214 |
gtk_widget_destroy(dialog); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
215 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
216 |
return 1; |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
217 |
} // runGuiPasswordPrompt |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
218 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
219 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
220 |
static int copyToClipboard(lua_State *L) |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
221 |
{ |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
222 |
const char *str = luaL_checkstring(L, 1); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
223 |
gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_PRIMARY), str, -1); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
224 |
gtk_clipboard_set_text(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD), str, -1); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
225 |
} // copyToClipboard |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
226 |
|
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
227 |
|
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
228 |
static int makeGuiMenu(lua_State *L) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
229 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
230 |
return retvalPointer(L, gtk_menu_new()); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
231 |
} // makeGuiMenu |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
232 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
233 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
234 |
static void clickedMenuItem(void *arg) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
235 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
236 |
// This is the callback from GTK+; now call into our actual Lua callback! |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
237 |
const int callback = (int) ((size_t)arg); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
238 |
lua_rawgeti(luaState, LUA_REGISTRYINDEX, callback); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
239 |
lua_call(luaState, 0, 0); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
240 |
} // clickedMenuItem |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
241 |
|
12
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
242 |
#if 0 // !!! FIXME: figure out how to fire this. |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
243 |
static void deletedMenuItem(void *arg) |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
244 |
{ |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
245 |
// Clean up the Lua function we referenced in the Registry. |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
246 |
const int callback = (int) ((size_t)arg); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
247 |
printf("unref callback %d\n", callback); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
248 |
luaL_unref(luaState, LUA_REGISTRYINDEX, callback); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
249 |
} // deletedMenuItem |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
250 |
#endif |
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
251 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
252 |
static int appendGuiMenuItem(lua_State *L) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
253 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
254 |
const int argc = lua_gettop(L); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
255 |
GtkWidget *menu = (GtkWidget *) lua_touserdata(L, 1); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
256 |
const char *label = luaL_checkstring(L, 2); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
257 |
GtkWidget *item = gtk_menu_item_new_with_label(label); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
258 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
259 |
if ((argc >= 3) && (!lua_isnil(L, 3))) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
260 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
261 |
assert(lua_isfunction(L, 3)); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
262 |
lua_pushvalue(L, 3); // copy the Lua callback (luaL_ref() pops it). |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
263 |
const int callback = luaL_ref(L, LUA_REGISTRYINDEX); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
264 |
gtk_signal_connect_object(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(clickedMenuItem), (gpointer) ((size_t)callback)); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
265 |
} // if |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
266 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
267 |
gtk_widget_show(item); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
268 |
gtk_menu_append(menu, item); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
269 |
return retvalPointer(L, item); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
270 |
} // appendGuiMenuItem |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
271 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
272 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
273 |
static int setGuiMenuItemSubmenu(lua_State *L) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
274 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
275 |
GtkMenuItem *item = (GtkMenuItem *) lua_touserdata(L, 1); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
276 |
GtkWidget *submenu = (GtkWidget *) lua_touserdata(L, 2); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
277 |
gtk_menu_item_set_submenu(item, submenu); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
278 |
return 0; |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
279 |
} // setGuiMenuItemSubmenu |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
280 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
281 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
282 |
static int popupGuiMenu(lua_State *L) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
283 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
284 |
GtkMenu *menu = (GtkMenu *) lua_touserdata(L, 1); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
285 |
gtk_menu_popup(menu, NULL, NULL, NULL, NULL, 0, gtk_get_current_event_time()); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
286 |
return 0; |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
287 |
} // popupGuiMenu |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
288 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
289 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
290 |
static int giveControlToGui(lua_State *L) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
291 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
292 |
gtk_main(); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
293 |
return 0; |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
294 |
} // giveControlToGui |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
295 |
|
7
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
296 |
|
0 | 297 |
static void *luaAlloc(void *ud, void *ptr, size_t osize, size_t nsize) |
298 |
{ |
|
299 |
if (nsize == 0) |
|
300 |
{ |
|
301 |
free(ptr); |
|
302 |
return NULL; |
|
303 |
} // if |
|
304 |
return realloc(ptr, nsize); |
|
305 |
} // luaAlloc |
|
306 |
||
307 |
||
308 |
static inline void luaSetCFunc(lua_State *L, lua_CFunction f, const char *sym) |
|
309 |
{ |
|
310 |
lua_pushcfunction(L, f); |
|
311 |
lua_setglobal(luaState, sym); |
|
312 |
} // luaSetCFunc |
|
313 |
||
314 |
||
315 |
static int luaFatal(lua_State *L) |
|
316 |
{ |
|
317 |
const char *errstr = lua_tostring(L, -1); |
|
318 |
fprintf(stderr, "Lua panic: %s\n", errstr ? errstr : "(?)"); |
|
319 |
fflush(stderr); |
|
320 |
exit(1); |
|
321 |
} // luaFatal |
|
322 |
||
323 |
||
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
324 |
static void deinitLua(void) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
325 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
326 |
if (luaState != NULL) |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
327 |
{ |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
328 |
lua_close(luaState); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
329 |
luaState = NULL; |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
330 |
} // if |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
331 |
} // deinitLua |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
332 |
|
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
333 |
|
7
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
334 |
static int initLua(const int argc, char **argv) |
0 | 335 |
{ |
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
336 |
atexit(deinitLua); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
337 |
|
0 | 338 |
assert(luaState == NULL); |
339 |
luaState = lua_newstate(luaAlloc, NULL); |
|
340 |
||
341 |
lua_atpanic(luaState, luaFatal); |
|
342 |
assert(lua_checkstack(luaState, 20)); // Just in case. |
|
2
16a2d269fd41
Just use the built-in luaL_openlibs()
Ryan C. Gordon <icculus@icculus.org>
parents:
1
diff
changeset
|
343 |
luaL_openlibs(luaState); |
0 | 344 |
|
345 |
// Set up initial C functions, etc we want to expose to Lua code... |
|
346 |
luaSetCFunc(luaState, decryptUsingPBKDF2, "decryptUsingPBKDF2"); |
|
347 |
luaSetCFunc(luaState, decryptBase64UsingKey, "decryptBase64UsingKey"); |
|
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
348 |
luaSetCFunc(luaState, makeGuiMenu, "makeGuiMenu"); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
349 |
luaSetCFunc(luaState, appendGuiMenuItem, "appendGuiMenuItem"); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
350 |
luaSetCFunc(luaState, setGuiMenuItemSubmenu, "setGuiMenuItemSubmenu"); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
351 |
luaSetCFunc(luaState, popupGuiMenu, "popupGuiMenu"); |
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
352 |
luaSetCFunc(luaState, giveControlToGui, "giveControlToGui"); |
12
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
353 |
luaSetCFunc(luaState, runGuiPasswordPrompt, "runGuiPasswordPrompt"); |
6a2d5b34d5ca
Whole bunch of GUI work.
Ryan C. Gordon <icculus@icculus.org>
parents:
11
diff
changeset
|
354 |
luaSetCFunc(luaState, copyToClipboard, "copyToClipboard"); |
0 | 355 |
|
7
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
356 |
// Set up argv table... |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
357 |
lua_newtable(luaState); |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
358 |
int i; |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
359 |
for (i = 0; i < argc; i++) |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
360 |
{ |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
361 |
lua_pushinteger(luaState, i+1); |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
362 |
lua_pushstring(luaState, argv[i]); |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
363 |
lua_settable(luaState, -3); |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
364 |
} // for |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
365 |
lua_setglobal(luaState, "argv"); |
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
366 |
|
3
32af809e8c0b
Corrected comment. It's basically just moving to Lua as the mainline.
Ryan C. Gordon <icculus@icculus.org>
parents:
2
diff
changeset
|
367 |
// Transfer control to Lua... |
0 | 368 |
if (luaL_dofile(luaState, "1pass.lua") != 0) |
369 |
{ |
|
370 |
const char *msg = lua_tostring(luaState, -1); |
|
371 |
fprintf(stderr, "1pass.lua didn't run: %s\n", msg); |
|
372 |
lua_pop(luaState, 1); |
|
373 |
return 0; |
|
374 |
} // if |
|
375 |
||
376 |
return 1; |
|
377 |
} // initLua |
|
378 |
||
379 |
||
380 |
int main(int argc, char **argv) |
|
381 |
{ |
|
11
b52e0f1798b8
Start building in GUI stuff.
Ryan C. Gordon <icculus@icculus.org>
parents:
7
diff
changeset
|
382 |
gtk_init(&argc, &argv); |
0 | 383 |
|
7
682d7ea1e7f3
Moved command lines into Lua.
Ryan C. Gordon <icculus@icculus.org>
parents:
4
diff
changeset
|
384 |
if (!initLua(argc, argv)) // this will move control to 1pass.lua |
0 | 385 |
return 1; |
386 |
||
387 |
return 0; |
|
388 |
} // main |
|
389 |
||
390 |
// end of 1pass.c ... |
|
391 |