1
2 1142a1143,1146
3 > Note: If you are using Firefox 3.x, the cookie is saved in a
4 > SQLite database file instead, see @samp{--load-cookies-sqlite} for more
5 > information.
6 >
7 1166a1171,1174
8 > @item Firefox 3.x.
9 > If you are using Firefox 3.x, you should use the
10 > @samp{--load-cookies-sqlite} option instead
11 >
12 1187a1196,1208
13 > @cindex loading cookies
14 > @cindex cookies, loading
15 > @item --load-cookies-sqlite @var{file}
16 > Load cookies from SQLite database @var{file} before the first HTTP
17 > retrieval.
18 >
19 > This option is similar to @samp{--load-cookies}, except that @var{file}
20 > is a database file in SQLite format instead of a textual file.
21 > This cookie file format is used by Firefox 3.x.
22 >
23 > For Firefox 3.x, the full path to the cookie file typically looks like this
24 > @file{~/.mozilla/firefox/@var{some-weird-string}.default/cookies.sqlite}
25 >
26 1194a1216,1228
27 > Note: This will save cookies in a plain textual file. If you want
28 > to save cookies into a SQLite database file as used by Firefox 3.x,
29 > you should use @samp{--save-cookies-sqlite} instead.
30 >
31 > @cindex saving cookies
32 > @cindex cookies, saving
33 > @item --save-cookies-sqlite @var{file}
34 > Save cookies to SQLite database @var{file} before exiting.
35 >
36 > This option is similar to @samp{--save-cookies}, except that
37 > cookies will be saved in the SQLite database format used by
38 > Firefox 3.x.
39 >
40
41 98c98,103
42 < #: src/cookies.c:1292
43 ---
44 > #: src/cookies.c:1289 src/cookies.c:1378
45 > #, c-format
46 > msgid "Error loading from `%s': %s\n"
47 > msgstr ""
48 >
49 > #: src/cookies.c:1292 src/cookies.c:1456
50
51 53a54,56
52 > #include <limits.h>
53 >
54 > #include <sqlite3.h>
55 1092a1096,1111
56 > /*
57 > * Firefox save cookies in a SQLite database file, namely
58 > * 'cookies.sqlite'. The schema of this database can be
59 > * described with the following SQL statement
60 > * CREATE TABLE moz_cookies (
61 > * id INTEGER PRIMARY KEY,
62 > * name TEXT,
63 > * value TEXT,
64 > * host TEXT,
65 > * path TEXT,
66 > * expiry INTEGER,
67 > * lastAccessed INTEGER,
68 > * isSecure INTEGER,
69 > * isHttpOnly INTEGER);
70 > */
71 >
72 1236a1256,1399
73 > /* Load cookies from SQLite database file. */
74 >
75 > void
76 > cookie_jar_load_sqlite (struct cookie_jar *jar, const char *file)
77 > {
78 > const char statement[] = "SELECT name, value, host, path, expiry, "
79 > "isSecure, isHttpOnly"
80 > " FROM moz_cookies;";
81 > struct sqlite3 *db;
82 > struct sqlite3_stmt *stmt;
83 > const char *tail;
84 > int debug_n_found = 0, debug_n_accepted = 0;
85 >
86 > DEBUGP (("loading cookies from SQLite database: '%s'\n", file));
87 > /* fixme: sounds like sqlite3_open_v2 not available in current
88 > * Ubuntu installation
89 > */
90 > /* fixme: convert filename to UTF-8 */
91 > /* int rc = sqlite3_open_v2(file, &db, SQLITE_OPEN_READONLY, NULL); */
92 > int rc = sqlite3_open(file, &db);
93 > if (rc != SQLITE_OK)
94 > {
95 > logprintf (LOG_NOTQUIET,
96 > _("Cannot open cookies file `%s': %s\n"),
97 > file, sqlite3_errmsg (db));
98 > return;
99 > }
100 >
101 > rc = sqlite3_prepare_v2(db, statement, -1, &stmt, &tail);
102 > if (rc != SQLITE_OK)
103 > {
104 > const char *errmsg = sqlite3_errmsg(db);
105 > DEBUGP (("SQL statement SELECT compilation failed: %s\n", errmsg));
106 > logprintf (LOG_NOTQUIET, _("Error loading from `%s': %s\n"),
107 > file, errmsg);
108 > if (sqlite3_close(db) != SQLITE_OK)
109 > logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
110 > file, sqlite3_errmsg (db));
111 > return;
112 > }
113 >
114 > cookies_now = time(NULL);
115 >
116 > while (1)
117 > {
118 > struct cookie *pcookie = NULL;
119 > const char *attr = NULL, *attr_e = NULL;
120 > const char *value = NULL, *value_e = NULL;
121 > const char *host = NULL, *host_e = NULL;
122 > const char *path = NULL, *path_e = NULL;
123 > int port;
124 > sqlite_int64 expiry_time;
125 > rc = sqlite3_step(stmt);
126 > switch (rc)
127 > {
128 > case SQLITE_DONE:
129 > goto iteration_done;
130 > case SQLITE_BUSY:
131 > /* fixme: eliminate busy-waiting */
132 > continue;
133 > case SQLITE_ROW:
134 > ++debug_n_found;
135 > pcookie = cookie_new();
136 > attr = (const char *)sqlite3_column_text(stmt, 0);
137 > value = (const char *)sqlite3_column_text(stmt, 1);
138 > host = (const char *)sqlite3_column_text(stmt, 2);
139 > path = (const char *)sqlite3_column_text(stmt, 3);
140 > attr_e = attr + strlen(attr);
141 > value_e = value + strlen(value);
142 > host_e = host + strlen(host);
143 > path_e = path + strlen(path);
144 > pcookie->attr = strdupdelim(attr, attr_e);
145 > pcookie->value = strdupdelim(value, value_e);
146 > port = domain_port(host, host_e, &host_e);
147 > if (port)
148 > {
149 > pcookie->port = port;
150 > }
151 > if (*host == '.')
152 > {
153 > ++host; /* remove leading dot internally */
154 > /* fixme: does a leading dot in the domain name
155 > * that it's not exact? I'm not quite sure
156 > * yet.
157 > */
158 > pcookie->domain_exact = 0;
159 > }
160 > else
161 > {
162 > pcookie->domain_exact = 1;
163 > }
164 > pcookie->domain = strdupdelim(host, host_e);
165 > pcookie->path = strdupdelim(path, path_e);
166 > expiry_time = sqlite3_column_int64(stmt, 4);
167 > pcookie->secure = sqlite3_column_int(stmt, 5);
168 > /* fixme: what to do with isHttpOnly? I don't know */
169 > if (expiry_time != 0)
170 > {
171 > if (expiry_time < cookies_now)
172 > {
173 > DEBUGP (("cookie %s from %s expired (expiry: %lld; now: %ld), "
174 > "discard\n",
175 > attr, pcookie->domain, expiry_time, cookies_now));
176 > delete_cookie(pcookie);
177 > continue;
178 > }
179 > else
180 > {
181 > /* fixme: type mismatch here! */
182 > pcookie->expiry_time = (time_t)expiry_time;
183 > /* fixme: dirty hack, not portable */
184 > if (pcookie->expiry_time < 0)
185 > pcookie->expiry_time = ~(1 << (sizeof(time_t)*CHAR_BIT-1));
186 > pcookie->permanent = 1;
187 > }
188 > }
189 > ++debug_n_accepted;
190 > store_cookie(jar, pcookie);
191 > break;
192 > case SQLITE_MISUSE:
193 > assert (0);
194 > default:
195 > logprintf (LOG_NOTQUIET, _("Error loading from `%s': %s\n"),
196 > file, sqlite3_errmsg(db));
197 > goto iteration_done;
198 > }
199 > }
200 >
201 > iteration_done:
202 > DEBUGP (("%d cookies found, %d accepted\n",
203 > debug_n_found, debug_n_accepted));
204 > if (sqlite3_finalize(stmt) != SQLITE_OK)
205 > {
206 > DEBUGP (("SQL statement finalization failed: %s\n",
207 > sqlite3_errmsg(db)));
208 > }
209 > rc = sqlite3_close(db);
210 > if (rc != SQLITE_OK)
211 > {
212 > logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
213 > file, sqlite3_errmsg(db));
214 > }
215 > }
216 >
217 1268a1432
218 >
219 1297a1462,1614
220 > /* Save cookies, into SQLite database file */
221 >
222 > #define BIND_SQL_PARAMETER(func, db) \
223 > if((func) != SQLITE_OK) \
224 > { \
225 > DEBUGP (("Bind value into SQL statement INSERT failed: %s", \
226 > sqlite3_errmsg(db))); \
227 > goto ignore_one; \
228 > }
229 >
230 > void
231 > cookie_jar_save_sqlite (struct cookie_jar *jar, const char *file)
232 > {
233 > struct sqlite3 *db;
234 > struct sqlite3_stmt *stmt;
235 > const char initizlize_stmt[] = "DROP TABLE IF EXISTS moz_cookies;"
236 > "VACUUM;"
237 > "CREATE TABLE moz_cookies ("
238 > "id INTEGER PRIMARY KEY,"
239 > "name TEXT,"
240 > "value TEXT,"
241 > "host TEXT,"
242 > "path TEXT,"
243 > "expiry INTEGER,"
244 > "lastAccessed INTEGER,"
245 > "isSecure INTEGER,"
246 > "isHttpOnly INTEGER);";
247 > const char insert_stmt[] = "INSERT INTO moz_cookies (name, value, "
248 > "host, path, expiry, "
249 > "lastAccessed, isSecure, "
250 > "isHttpOnly) "
251 > "VALUES (@name, "
252 > "@value, @host, @path, @expiry, "
253 > "@lastAccessed, @isSecure, "
254 > "@isHttpOnly);";
255 > const char *tail;
256 > hash_table_iterator iter;
257 > int rc;
258 > char *errmsg = NULL;
259 >
260 > DEBUGP (("Saving cookies to %s.\n", file));
261 >
262 > cookies_now = time (NULL);
263 >
264 > /* fixme: use sqlite3_open_v2() if available */
265 > /* fixme: convert filename to UTF-8 */
266 > rc = sqlite3_open(file, &db);
267 > if (rc != SQLITE_OK)
268 > {
269 > logprintf (LOG_NOTQUIET, _("Cannot open cookies file `%s': %s\n"),
270 > file, sqlite3_errmsg(db));
271 > return;
272 > }
273 > rc = sqlite3_exec(db, initizlize_stmt, NULL, NULL, &errmsg);
274 > if (rc != SQLITE_OK)
275 > {
276 > DEBUGP (("Cannot initialize database: %s\n", errmsg));
277 > logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
278 > file, errmsg);
279 > sqlite3_free(errmsg);
280 > if (sqlite3_close(db) != SQLITE_OK)
281 > logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
282 > file, sqlite3_errmsg (db));
283 > return;
284 > }
285 >
286 > rc = sqlite3_prepare_v2(db, insert_stmt, -1, &stmt, &tail);
287 > if (rc != SQLITE_OK)
288 > {
289 > const char *errmsg = sqlite3_errmsg(db);
290 > DEBUGP (("SQL statment INSERT compilation failed: %s\n", errmsg));
291 > logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
292 > file, errmsg);
293 > if (sqlite3_close(db) != SQLITE_OK)
294 > logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
295 > file, sqlite3_errmsg (db));
296 > return;
297 > }
298 >
299 > for (hash_table_iterate (jar->chains, &iter);
300 > hash_table_iter_next (&iter);
301 > )
302 > {
303 > const char *domain = iter.key;
304 > const int MAX_PORT = 65535;
305 > const int MAX_PORT_DIGITS = 5;
306 > int offset = 0;
307 > char *domain_buffer = (char *)malloc(strlen(domain)+MAX_PORT_DIGITS+3);
308 > struct cookie *cookie = iter.value;
309 > for (; cookie; cookie = cookie->next)
310 > {
311 > if (!cookie->permanent && !opt.keep_session_cookies)
312 > continue;
313 > if (cookie_expired_p (cookie))
314 > continue;
315 > if (!cookie->domain_exact)
316 > offset = sprintf(domain_buffer, ".%s", domain);
317 > else
318 > offset = sprintf(domain_buffer, "%s", domain);
319 > if (cookie->port != PORT_ANY)
320 > {
321 > if (cookie->port > MAX_PORT)
322 > continue; /* if port number is illegal, I discard the cookie */
323 > sprintf (domain_buffer + offset, ":%d", cookie->port);
324 > }
325 > BIND_SQL_PARAMETER(
326 > sqlite3_bind_text(stmt, 1, cookie->attr, -1, SQLITE_STATIC),
327 > db);
328 > BIND_SQL_PARAMETER(
329 > sqlite3_bind_text(stmt, 2, cookie->value, -1, SQLITE_STATIC),
330 > db);
331 > BIND_SQL_PARAMETER(
332 > sqlite3_bind_text(stmt, 3, domain_buffer, -1, SQLITE_STATIC),
333 > db);
334 > BIND_SQL_PARAMETER(
335 > sqlite3_bind_text(stmt, 4, cookie->path, -1, SQLITE_STATIC),
336 > db);
337 > /* fixme: note a type mismatch here!
338 > * cookie->expiry_time is time_t */
339 > BIND_SQL_PARAMETER(sqlite3_bind_int(stmt, 5, cookie->expiry_time), db);
340 > BIND_SQL_PARAMETER(sqlite3_bind_int(stmt, 6, cookies_now), db);
341 > BIND_SQL_PARAMETER(sqlite3_bind_int(stmt, 7, cookie->secure), db);
342 > /* fixme: I really don't know what to fill into isHttpOnly */
343 > BIND_SQL_PARAMETER(sqlite3_bind_int(stmt, 8, 0), db);
344 > rc = sqlite3_step(stmt);
345 > if (rc != SQLITE_DONE)
346 > {
347 > DEBUGP (("Failure inserting values into database: %s",
348 > sqlite3_errmsg(db)));
349 > goto out;
350 > }
351 > ignore_one:
352 > if (sqlite3_reset(stmt) != SQLITE_OK)
353 > {
354 > DEBUGP (("Failed to reset statement: %s", sqlite3_errmsg(db)));
355 > goto out;
356 > }
357 > }
358 > free(domain_buffer);
359 > }
360 > out:
361 > if (sqlite3_errcode(db) != SQLITE_OK)
362 > logprintf (LOG_NOTQUIET, _("Error writing to `%s': %s\n"),
363 > file, sqlite3_errmsg(db));
364 > if (sqlite3_finalize(stmt) != SQLITE_OK)
365 > DEBUGP (("Error finalizing INSERT statment: %s\n", sqlite3_errmsg(db)));
366 > if (sqlite3_close(db) != SQLITE_OK)
367 > logprintf (LOG_NOTQUIET, _("Error closing `%s': %s\n"),
368 > file, sqlite3_errmsg (db));
369 >
370 > DEBUGP (("Done saving cookies.\n"));
371 > }
372 >
373
374 44a45
375 > void cookie_jar_load_sqlite (struct cookie_jar *, const char *);
376 45a47
377 > void cookie_jar_save_sqlite (struct cookie_jar *, const char *);
378
379 3174c3174,3175
380 < if (opt.cookies_input && !cookies_loaded_p)
381 ---
382 > if (!cookies_loaded_p) {
383 > if (opt.cookies_input)
384 3178a3180,3186
385 > if (opt.cookies_input_sqlite)
386 > {
387 > cookie_jar_load_sqlite(wget_cookie_jar,
388 > opt.cookies_input_sqlite);
389 > cookies_loaded_p = true;
390 > }
391 > }
392 3184a3193,3194
393 > {
394 > if (opt.cookies_output)
395 3185a3196,3198
396 > if (opt.cookies_output_sqlite)
397 > cookie_jar_save_sqlite (wget_cookie_jar, opt.cookies_output_sqlite);
398 > }
399
400 186a187
401 > { "loadcookiessqlite", &opt.cookies_input_sqlite, cmd_file },
402 231a233
403 > { "savecookiessqlite", &opt.cookies_output_sqlite, cmd_file },
404
405 195a196
406 > { "load-cookies-sqlite", 0, OPT_VALUE, "loadcookiessqlite", -1 },
407 233a235
408 > { "save-cookies-sqlite", 0, OPT_VALUE, "savecookiessqlite", -1},
409 1071c1073
410 < if (opt.cookies_output)
411 ---
412 > if (opt.cookies_output || opt.cookies_output_sqlite)
413
414 54a55
415 > # fixme: use autoconf for sqlite3 here.
416 92c93
417 < $(LINK) $(OBJ) $(LIBS)
418 ---
419 > $(LINK) $(OBJ) $(LIBS) -lsqlite3
420
421 198a199,200
422 > char *cookies_input_sqlite; /* SQLite database we're loading the
423 > cookies from. */
424 199a202,203
425 > char *cookies_output_sqlite; /* SQLite database we're saving
426 > the cookies to */
427