Dillo v3.1.1-91-g6d5b3ee3
Loading...
Searching...
No Matches
bookmarks.c
Go to the documentation of this file.
1/*
2 * Bookmarks server (chat version).
3 *
4 * NOTE: this code illustrates how to make a dpi-program.
5 *
6 * Copyright 2002-2007 Jorge Arellano Cid <jcid@dillo.org>
7 * Copyright 2024 Rodrigo Arias Mallo <rodarima@gmail.com>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
13 *
14 */
15
16/* TODO: this server is not assembling the received packets.
17 * This means it currently expects dillo to send full dpi tags
18 * within the socket; if that fails, everything stops.
19 * This is not hard to fix, mainly is a matter of expecting the
20 * final '>' of a tag.
21 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <stddef.h>
26#include <string.h>
27#include <unistd.h>
28#include <errno.h>
29#include <ctype.h>
30#include <sys/socket.h>
31#include <sys/stat.h>
32#include <sys/types.h>
33#include <sys/un.h>
34#include <time.h>
35#include <netdb.h>
36#include <fcntl.h>
37#include <signal.h>
38#include "../dpip/dpip.h"
39#include "dpiutil.h"
40
41
42/*
43 * Debugging macros
44 */
45#define _MSG(...)
46#define MSG(...) printf("[bookmarks dpi]: " __VA_ARGS__)
47
48#define DOCTYPE \
49 "<!DOCTYPE html>\n"
50
51#define CSS_STYLE \
52 "<style type='text/css'>\n"\
53 "body { margin: 2em; background: white; font-size: 14px }\n" \
54 "ul { font-size: inherit; margin-left: 1em; margin-top: 0.5em; list-style-type: none; }\n" \
55 "ul.main { list-style-type: none; }\n" \
56 "li { min-height: 1.6em; }\n" \
57 "div.modify-menu { background-color: #f0f0f0; border: solid 1px #ccc; padding: 1em }\n" \
58 "nav ul { margin-top: 1em }\n" \
59 "nav li { display: inline; }\n" \
60 "a { color: black; }\n" \
61 "</style>\n"
62/*
63 * Notes on character escaping:
64 * - Basically things are saved unescaped and escaped when in memory.
65 * - &<>"' are escaped in titles and sections and saved unescaped.
66 * - ' is escaped as %27 in URLs and saved escaped.
67 */
68typedef struct {
69 int key;
70 int section;
71 char *url;
72 char *title;
73} BmRec;
74
75typedef struct {
76 int section;
77 char *title;
78
79 int o_sec; /* private, for normalization */
80} BmSec;
81
82
83/*
84 * Local data
85 */
86static char *Header = "Content-type: text/html\n\n";
87static char *BmFile = NULL;
88static time_t BmFileTimeStamp = 0;
89static Dlist *B_bms = NULL;
90static int bm_key = 0;
91
92static Dlist *B_secs = NULL;
93static int sec_key = 0;
94
95static int MODIFY_PAGE_NUM = 1;
96
97
98/*
99 * Forward declarations
100 */
101
102
103/* -- HTML templates ------------------------------------------------------- */
104
105static const char *mainpage_header =
107"<html>\n"
108"<head>\n"
109"<title>Bookmarks</title>\n"
111"</head>\n"
112"<body id='dillo_bm'>\n"
113"\n"
114" <h1>Bookmarks</h1>\n"
115" <div style='float: right; padding: 1em'>\n"
116" [<a href='dpi:/bm/modify'>Modify</a>]\n"
117" </div>\n";
118
119static const char *modifypage_header =
121"<html>\n"
122"<head>\n"
123"<title>Bookmarks</title>\n"
125"</head>\n"
126"<body id='dillo_bm'>\n"
127" <h1>Bookmarks</h1>\n"
128"\n"
129"<form action='modify'>\n"
130"<div class='modify-menu'>\n"
131" <div style='float: right'>\n"
132" [<a href='dpi:/bm/'>Dismiss</a>]\n"
133" </div>\n"
134" <p>Select an operation\n"
135" <select name='operation'>\n"
136" <option value='none' selected>--\n"
137" <option value='delete'>Delete\n"
138" <option value='move'>Move\n"
139" <option value='modify'>Modify\n"
140" <option value='add_sec'>Add Section\n"
141" <option value='add_url'>Add URL\n"
142" </select>\n"
143" , mark its operands and\n"
144" <input type='submit' name='submit' value='Submit'>\n"
145" <p>You can also modify the bookmarks by editting the\n"
146" <a href='file:~/.dillo/bm.txt'><code>~/.dillo/bm.txt</code></a> file.\n"
147"</div>\n";
148
149static const char *mainpage_sections_header =
150"<nav>\n"
151" <ul>\n";
152
153#define modifypage_sections_header mainpage_sections_header
154
155static const char *mainpage_sections_item =
156" <li><a href='#s%d'>%s</a></li>\n";
157
158static const char *sections_sep =
159" | \n";
160
161static const char *modifypage_sections_item =
162" <li><input type='checkbox' name='s%d'><a href='#s%d'>%s</a></li>\n";
163
164static const char *mainpage_sections_footer =
165" </ul>\n"
166"</nav>\n";
167
168#define modifypage_sections_footer mainpage_sections_footer
169
170static const char *mainpage_middle1 = "\n";
171
172static const char *modifypage_middle1 = "\n";
173
175"<h2 id='s%d'>%s</h2>\n"
176"<ul class='main'>\n";
177
179"<h2 id='s%d'>%s</h2>\n"
180"<ul class='main'>\n";
181
182static const char *mainpage_section_card_item =
183" <li>\n"
184" <a href='%s'>%s</a>\n"
185" </li>\n";
186
188" <li>\n"
189" <input type='checkbox' name='url%d'>\n"
190" <a href='%s'>%s</a>\n"
191" </li>\n";
192
194"</ul>\n";
195
196#define modifypage_section_card_footer mainpage_section_card_footer
197
198static const char *mainpage_footer =
199"</body>\n"
200"</html>\n";
201
202static const char *modifypage_footer =
203"</form>\n"
204"</body>\n"
205"</html>\n";
206
207/* ------------------------------------------------------------------------- */
208static const char *modifypage_add_section_page =
210"<html>\n"
211"<head>\n"
212"<title>Bookmarks</title>\n"
214"</head>\n"
215"<body id='dillo_bm'>\n"
216"<h1>Boorkmarks: New section</h1>\n"
217"<form action='modify'>\n"
218" <input type='hidden' name='operation' value='add_section'>\n"
219" <p>\n"
220" New section title:\n"
221" <input type='text' name='title' size='32'>\n"
222" <input type='submit' name='submit' value='Submit'>\n"
223" or <a href='dpi:/bm/'>Cancel</a>\n"
224" </p>\n"
225"</form>\n"
226"</body>\n"
227"</html>\n"
228"\n";
229
230/* ------------------------------------------------------------------------- */
231static const char *modifypage_update_header =
233"<html>\n"
234"<head>\n"
235"<title>Bookmarks</title>\n"
237"</head>\n"
238"<body id='dillo_bm'>\n"
239"<h1>Bookmarks: Update</h1>\n"
240"<form action='modify'>\n"
241"<input type='hidden' name='operation' value='modify2'>\n";
242
243static const char *modifypage_update_title =
244"<h2>%s</h2>\n";
245
247"<ul>\n";
248
249static const char *modifypage_update_item =
250"<li style='padding: 0.5em'>\n"
251" <input type='text' name='title%d' size='64'\n value='%s'>\n"
252" <br>URL: <code>%s</code>\n"
253"</li>\n";
254
255static const char *modifypage_update_item2 =
256"<li style='padding: 0.5em'>\n"
257" <input type='text' name='s%d' size='64' value='%s'>\n"
258"</li>\n";
259
261"</ul>\n";
262
263static const char *modifypage_update_footer =
264"<input type='submit' name='submit' value='Submit'>\n"
265"</form>\n"
266"</body>\n"
267"</html>\n";
268
269/* ------------------------------------------------------------------------- */
270static const char *modifypage_add_url =
272"<html>\n"
273"<head>\n"
274"<title>Bookmarks</title>\n"
276"</head>\n"
277"<body id='dillo_bm'>\n"
278"<h1>Bookmarks: Add URL</h1>\n"
279"<form action='modify'>\n"
280"<input type='hidden' name='operation' value='add_url2'>\n"
281"<p>Title:\n"
282" <input type='text' name='title' size='64'>\n"
283"</p>\n"
284"<p>URL:\n"
285" <input type='text' name='url' size='64'>\n"
286"</p>\n"
287"<p>\n"
288" <input type='submit' name='submit' value='Submit'>\n"
289" or <a href='dpi:/bm/'>Cancel</a>\n"
290"</p>\n"
291"</form>\n"
292"</body>\n"
293"</html>\n";
294
295
296/* ------------------------------------------------------------------------- */
297
298/*
299 * Return a new string with spaces changed with &nbsp;
300 */
301static char *make_one_line_str(char *str)
302{
303 char *new_str;
304 int i, j, n;
305
306 for (i = 0, n = 0; str[i]; ++i)
307 if (str[i] == ' ')
308 ++n;
309
310 new_str = dNew(char, strlen(str) + 6*n + 1);
311 new_str[0] = 0;
312
313 for (i = 0, j = 0; str[i]; ++i) {
314 if (str[i] == ' ') {
315 strcpy(new_str + j, "&nbsp;");
316 j += 6;
317 } else {
318 new_str[j] = str[i];
319 new_str[++j] = 0;
320 }
321 }
322
323 return new_str;
324}
325
326/*
327 * Given an urlencoded string, return it to the original version.
328 */
329static void Unencode_str(char *e_str)
330{
331 char *p, *e;
332
333 for (p = e = e_str; *e; e++, p++) {
334 if (*e == '+') {
335 *p = ' ';
336 } else if (*e == '%') {
337 if (dStrnAsciiCasecmp(e, "%0D%0A", 6) == 0) {
338 *p = '\n';
339 e += 5;
340 } else {
341 *p = (isdigit(e[1]) ? (e[1] - '0') : (e[1] - 'A' + 10)) * 16 +
342 (isdigit(e[2]) ? (e[2] - '0') : (e[2] - 'A' + 10));
343 e += 2;
344 }
345 } else {
346 *p = *e;
347 }
348 }
349 *p = 0;
350}
351
352/*
353 * Send a short message to dillo's status bar.
354 */
355static int Bmsrv_dpi_send_status_msg(Dsh *sh, char *str)
356{
357 int st;
358 char *d_cmd;
359
360 d_cmd = a_Dpip_build_cmd("cmd=%s msg=%s", "send_status_message", str);
361 st = a_Dpip_dsh_write_str(sh, 1, d_cmd);
362 dFree(d_cmd);
363 return st;
364}
365
366/* -- ADT for bookmarks ---------------------------------------------------- */
367/*
368 * Compare function for searching a bookmark by its key
369 */
370static int Bms_node_by_key_cmp(const void *node, const void *key)
371{
372 return ((BmRec *)node)->key - VOIDP2INT(key);
373}
374
375/*
376 * Compare function for searching a bookmark by section
377 */
378static int Bms_node_by_section_cmp(const void *node, const void *key)
379{
380 return ((BmRec *)node)->section - VOIDP2INT(key);
381}
382
383/*
384 * Compare function for searching a section by its number
385 */
386static int Bms_sec_by_number_cmp(const void *node, const void *key)
387{
388 return ((BmSec *)node)->section - VOIDP2INT(key);
389}
390
391/*
392 * Return the Bm record by key
393 */
394static BmRec *Bms_get(int key)
395{
397}
398
399/*
400 * Return the Section record by key
401 */
402static BmSec *Bms_get_sec(int key)
403{
405}
406
407/*
408 * Add a bookmark
409 */
410static void Bms_add(int section, char *url, char *title)
411{
412 BmRec *bm_node;
413
414 bm_node = dNew(BmRec, 1);
415 bm_node->key = ++bm_key;
416 bm_node->section = section;
417 bm_node->url = Escape_uri_str(url, "'");
418 bm_node->title = Escape_html_str(title);
419 dList_append(B_bms, bm_node);
420}
421
422/*
423 * Add a section
424 */
425static void Bms_sec_add(char *title)
426{
427 BmSec *sec_node;
428
429 sec_node = dNew(BmSec, 1);
430 sec_node->section = sec_key++;
431 sec_node->title = Escape_html_str(title);
432 dList_append(B_secs, sec_node);
433}
434
435/*
436 * Delete a bookmark by its key
437 */
438static void Bms_del(int key)
439{
440 BmRec *bm_node;
441
443 if (bm_node) {
444 dList_remove(B_bms, bm_node);
445 dFree(bm_node->title);
446 dFree(bm_node->url);
447 dFree(bm_node);
448 }
449 if (dList_length(B_bms) == 0)
450 bm_key = 0;
451}
452
453/*
454 * Delete a section and its bookmarks by section number
455 */
456static void Bms_sec_del(int section)
457{
458 BmSec *sec_node;
459 BmRec *bm_node;
460
461 sec_node = dList_find_custom(B_secs, INT2VOIDP(section),
463 if (sec_node) {
464 dList_remove(B_secs, sec_node);
465 dFree(sec_node->title);
466 dFree(sec_node);
467
468 /* iterate B_bms and remove those that match the section */
469 while ((bm_node = dList_find_custom(B_bms, INT2VOIDP(section),
471 Bms_del(bm_node->key);
472 }
473 }
474 if (dList_length(B_secs) == 0)
475 sec_key = 0;
476}
477
478/*
479 * Move a bookmark to another section
480 */
481static void Bms_move(int key, int target_section)
482{
483 BmRec *bm_node;
484
486 if (bm_node) {
487 bm_node->section = target_section;
488 }
489}
490
491/*
492 * Update a bookmark title by key
493 */
494static void Bms_update_title(int key, char *n_title)
495{
496 BmRec *bm_node;
497
499 if (bm_node) {
500 dFree(bm_node->title);
501 bm_node->title = Escape_html_str(n_title);
502 }
503}
504
505/*
506 * Update a section title by key
507 */
508static void Bms_update_sec_title(int key, char *n_title)
509{
510 BmSec *sec_node;
511
513 if (sec_node) {
514 dFree(sec_node->title);
515 sec_node->title = Escape_html_str(n_title);
516 }
517}
518
519/*
520 * Free all the bookmarks data (bookmarks and sections)
521 */
522static void Bms_free(void)
523{
524 BmRec *bm_node;
525 BmSec *sec_node;
526
527 /* free B_bms */
528 while ((bm_node = dList_nth_data(B_bms, 0))) {
529 Bms_del(bm_node->key);
530 }
531 /* free B_secs */
532 while ((sec_node = dList_nth_data(B_secs, 0))) {
533 Bms_sec_del(sec_node->section);
534 }
535}
536
537/*
538 * Enforce increasing correlative section numbers with no jumps.
539 */
540static void Bms_normalize(void)
541{
542 BmRec *bm_node;
543 BmSec *sec_node;
544 int i, j;
545
546 /* we need at least one section */
547 if (dList_length(B_secs) == 0)
548 Bms_sec_add("Unclassified");
549
550 /* make correlative section numbers */
551 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
552 sec_node->o_sec = sec_node->section;
553 sec_node->section = i;
554 }
555
556 /* iterate B_secs and make the changes in B_bms */
557 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
558 if (sec_node->section != sec_node->o_sec) {
559 /* update section numbers */
560 for (j = 0; (bm_node = dList_nth_data(B_bms, j)); ++j) {
561 if (bm_node->section == sec_node->o_sec)
562 bm_node->section = sec_node->section;
563 }
564 }
565 }
566}
567
568/* -- Load bookmarks file -------------------------------------------------- */
569
570/*
571 * If there's no "bm.txt", create one from "bookmarks.html".
572 */
573static void Bms_check_import(void)
574{
575 char *OldBmFile;
576 char *cmd1 =
577 "echo \":s0: Unclassified\" > %s";
578 char *cmd2 =
579 "grep -i \"href\" %s | "
580 "sed -e 's/<li><A HREF=\"/s0 /' -e 's/\">/ /' -e 's/<.*$//' >> %s";
581 Dstr *dstr = dStr_new("");
582 int rc;
583
584
585 if (access(BmFile, F_OK) != 0) {
586 OldBmFile = dStrconcat(dGethomedir(), "/.dillo/bookmarks.html", NULL);
587 if (access(OldBmFile, F_OK) == 0) {
588 dStr_sprintf(dstr, cmd1, BmFile);
589 rc = system(dstr->str);
590 if (rc == 127) {
591 MSG("Bookmarks: /bin/sh could not be executed\n");
592 } else if (rc == -1) {
593 MSG("Bookmarks: process creation failure: %s\n",
594 dStrerror(errno));
595 }
596 dStr_sprintf(dstr, cmd2, OldBmFile, BmFile);
597 rc = system(dstr->str);
598 if (rc == 127) {
599 MSG("Bookmarks: /bin/sh could not be executed\n");
600 } else if (rc == -1) {
601 MSG("Bookmarks: process creation failure: %s\n",
602 dStrerror(errno));
603 }
604
605 dStr_free(dstr, TRUE);
606 dFree(OldBmFile);
607 }
608 }
609}
610
611/*
612 * Load bookmarks data from a file
613 */
614static int Bms_load(void)
615{
616 FILE *BmTxt;
617 char *buf, *p, *url, *title, *u_title;
618 int section;
619 struct stat TimeStamp;
620
621 /* clear current bookmarks */
622 Bms_free();
623
624 /* open bm file */
625 if (!(BmTxt = fopen(BmFile, "r"))) {
626 perror("[fopen]");
627 return 1;
628 }
629
630 /* load bm file into memory */
631 while ((buf = dGetline(BmTxt)) != NULL) {
632 if (buf[0] == 's') {
633 /* get section, url and title */
634 section = strtol(buf + 1, NULL, 10);
635 p = strchr(buf, ' ');
636 if (!p)
637 goto error;
638 *p = 0;
639 url = ++p;
640 p = strchr(p, ' ');
641 if (!p)
642 goto error;
643 *p = 0;
644 title = ++p;
645 p = strchr(p, '\n');
646 if (!p)
647 goto error;
648 *p = 0;
649 u_title = Unescape_html_str(title);
650 Bms_add(section, url, u_title);
651 dFree(u_title);
652
653 } else if (buf[0] == ':' && buf[1] == 's') {
654 /* section = strtol(buf + 2, NULL, 10); */
655 p = strchr(buf + 2, ' ');
656 if (!p)
657 goto error;
658 title = ++p;
659 p = strchr(p, '\n'); *p = 0;
660 if (!p)
661 goto error;
662 Bms_sec_add(title);
663 } else {
664 goto error;
665 }
666
667 dFree(buf);
668 continue;
669
670error:
671 MSG("Syntax error in bookmarks file:\n %s", buf);
672 dFree(buf);
673 }
674 fclose(BmTxt);
675
676 /* keep track of the timestamp */
677 stat(BmFile, &TimeStamp);
678 BmFileTimeStamp = TimeStamp.st_mtime;
679
680 return 0;
681}
682
683/*
684 * Load bookmarks data if:
685 * - file timestamp is newer than ours or
686 * - we haven't loaded anything yet :)
687 */
688static int Bms_cond_load(void)
689{
690 int st = 0;
691 struct stat TimeStamp;
692
693 if (stat(BmFile, &TimeStamp) != 0) {
694 /* try to import... */
696 if (stat(BmFile, &TimeStamp) != 0)
697 TimeStamp.st_mtime = 0;
698 }
699
701 BmFileTimeStamp < TimeStamp.st_mtime) {
702 Bms_load();
703 st = 1;
704 }
705 return st;
706}
707
708/* -- Save bookmarks file -------------------------------------------------- */
709
710/*
711 * Update the bookmarks file from memory contents
712 * Return code: { 0:OK, 1:Abort }
713 */
714static int Bms_save(void)
715{
716 FILE *BmTxt;
717 BmRec *bm_node;
718 BmSec *sec_node;
719 struct stat BmStat;
720 char *u_title;
721 int i, j;
722 Dstr *dstr = dStr_new("");
723
724 /* make a safety backup */
725 if (stat(BmFile, &BmStat) == 0 && BmStat.st_size > 256) {
726 char *BmFileBak = dStrconcat(BmFile, ".bak", NULL);
727 rename(BmFile, BmFileBak);
728 dFree(BmFileBak);
729 }
730
731 /* open bm file */
732 if (!(BmTxt = fopen(BmFile, "w"))) {
733 perror("[fopen]");
734 return 1;
735 }
736
737 /* normalize */
739
740 /* save sections */
741 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
742 u_title = Unescape_html_str(sec_node->title);
743 dStr_sprintf(dstr, ":s%d: %s\n", sec_node->section, u_title);
744 fwrite(dstr->str, (size_t)dstr->len, 1, BmTxt);
745 dFree(u_title);
746 }
747
748 /* save bookmarks (section url title) */
749 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
750 for (j = 0; (bm_node = dList_nth_data(B_bms, j)); ++j) {
751 if (bm_node->section == sec_node->section) {
752 u_title = Unescape_html_str(bm_node->title);
753 dStr_sprintf(dstr, "s%d %s %s\n",
754 bm_node->section, bm_node->url, u_title);
755 fwrite(dstr->str, (size_t)dstr->len, 1, BmTxt);
756 dFree(u_title);
757 }
758 }
759 }
760
761 dStr_free(dstr, TRUE);
762 fclose(BmTxt);
763
764 /* keep track of the timestamp */
765 stat(BmFile, &BmStat);
766 BmFileTimeStamp = BmStat.st_mtime;
767
768 return 0;
769}
770
771/* -- Add bookmark --------------------------------------------------------- */
772
773/*
774 * Add a new bookmark to DB :)
775 */
776static int Bmsrv_add_bm(Dsh *sh, char *url, char *title)
777{
778 char *u_title;
779 char *msg="Added bookmark!";
780 int section = 0;
781
782 /* Add in memory */
783 u_title = Unescape_html_str(title);
784 Bms_add(section, url, u_title);
785 dFree(u_title);
786
787 /* Write to file */
788 Bms_save();
789
791 return 1;
792
793 return 0;
794}
795
796/* -- Modify --------------------------------------------------------------- */
797
798/*
799 * Count how many sections and urls were marked in a request
800 */
801static void Bmsrv_count_urls_and_sections(char *url, int *n_sec, int *n_url)
802{
803 char *p, *q;
804 int i;
805
806 /* Check marked urls and sections */
807 *n_sec = *n_url = 0;
808 if ((p = strchr(url, '?'))) {
809 for (q = p; (q = strstr(q, "&url")); ++q) {
810 for (i = 0; isdigit(q[4+i]); ++i);
811 *n_url += (q[4+i] == '=') ? 1 : 0;
812 }
813 for (q = p; (q = strstr(q, "&s")); ++q) {
814 for (i = 0; isdigit(q[2+i]); ++i);
815 *n_sec += (q[2+i] == '=') ? 1 : 0;
816 }
817 }
818}
819
820/*
821 * Send a dpi reload request
822 * Return code: { 0:OK, 1:Abort, 2:Close }
823 */
824static int Bmsrv_send_reload_request(Dsh *sh, char *url)
825{
826 int st;
827 char *d_cmd;
828
829 d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "reload_request", url);
830 st = a_Dpip_dsh_write_str(sh, 1, d_cmd) ? 1 : 0;
831 dFree(d_cmd);
832 return st;
833}
834
835/*
836 * Send the HTML for the modify page
837 * Return code: { 0:OK, 1:Abort, 2:Close }
838 */
840{
841 static Dstr *dstr = NULL;
842 char *l_title;
843 BmSec *sec_node;
844 BmRec *bm_node;
845 int i, j;
846
847 if (!dstr)
848 dstr = dStr_new("");
849
850 /* send modify page header */
852 return 1;
853
854 /* write sections header */
856 return 1;
857 /* write sections */
858 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
859 if (i > 0) {
861 return 1;
862 }
863
865 sec_node->section, sec_node->section, sec_node->title);
866 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
867 return 1;
868 }
869 /* write sections footer */
871 return 1;
872
873 /* send page middle */
875 return 1;
876
877 /* send bookmark cards */
878 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
879 /* send card header */
880 l_title = make_one_line_str(sec_node->title);
882 sec_node->section, l_title);
883 dFree(l_title);
884 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
885 return 1;
886
887 /* send section's bookmarks */
888 for (j = 0; (bm_node = dList_nth_data(B_bms, j)); ++j) {
889 if (bm_node->section == sec_node->section) {
891 bm_node->key, bm_node->url, bm_node->title);
892 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
893 return 1;
894 }
895 }
896
897 /* send card footer */
899 return 1;
900 }
901
902 /* finish page */
904 return 1;
905
906 return 2;
907}
908
909/*
910 * Send the HTML for the modify page for "add section"
911 * Return code: { 0:OK, 1:Abort, 2:Close }
912 */
914{
915 /* send modify page2 */
917 return 1;
918
919 return 2;
920}
921
922/*
923 * Send the HTML for the modify page for "add url"
924 * Return code: { 0:OK, 1:Abort, 2:Close }
925 */
927{
929 return 1;
930 return 2;
931}
932
933/*
934 * Parse a modify urls request and either:
935 * - make a local copy of the url
936 * or
937 * - send the modify page for the marked urls and sections
938 * Return code: { 0:OK, 1:Abort, 2:Close }
939 */
940static int Bmsrv_send_modify_update(Dsh *sh, char *url)
941{
942 static char *url1 = NULL;
943 static Dstr *dstr = NULL;
944 char *p, *q;
945 int i, key, n_sec, n_url;
946 BmRec *bm_node;
947 BmSec *sec_node;
948
949 /* bookmarks were loaded before */
950
951 if (!dstr)
952 dstr = dStr_new("");
953
954 if (sh == NULL) {
955 /* just copy url */
956 dFree(url1);
957 url1 = dStrdup(url);
958 return 0;
959 }
960
961 /* send HTML here */
963 return 1;
964
965 /* Count number of marked urls and sections */
966 Bmsrv_count_urls_and_sections(url1, &n_sec, &n_url);
967
968 if (n_sec) {
969 dStr_sprintf(dstr, modifypage_update_title, "Update sections");
970 a_Dpip_dsh_write_str(sh, 0, dstr->str);
972 /* send items here */
973 p = strchr(url1, '?');
974 for (q = p; (q = strstr(q, "&s")); ++q) {
975 for (i = 0; isdigit(q[2+i]); ++i);
976 if (q[2+i] == '=') {
977 key = strtol(q + 2, NULL, 10);
978 if ((sec_node = Bms_get_sec(key))) {
980 sec_node->section, sec_node->title);
981 a_Dpip_dsh_write_str(sh, 0, dstr->str);
982 }
983 }
984 }
986 }
987
988 if (n_url) {
989 dStr_sprintf(dstr, modifypage_update_title, "Update titles");
990 a_Dpip_dsh_write_str(sh, 0, dstr->str);
992 /* send items here */
993 p = strchr(url1, '?');
994 for (q = p; (q = strstr(q, "&url")); ++q) {
995 for (i = 0; isdigit(q[4+i]); ++i);
996 if (q[4+i] == '=') {
997 key = strtol(q + 4, NULL, 10);
998 bm_node = Bms_get(key);
1000 bm_node->key, bm_node->title, bm_node->url);
1001 a_Dpip_dsh_write_str(sh, 0, dstr->str);
1002 }
1003 }
1005 }
1006
1008
1009 return 2;
1010}
1011
1012/*
1013 * Make the modify-page and send it back
1014 * Return code: { 0:OK, 1:Abort, 2:Close }
1015 */
1016static int Bmsrv_send_modify_answer(Dsh *sh, char *url)
1017{
1018 char *d_cmd;
1019 int st;
1020
1021 d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url);
1022 st = a_Dpip_dsh_write_str(sh, 1, d_cmd);
1023 dFree(d_cmd);
1024 if (st != 0)
1025 return 1;
1026
1027 /* Send HTTP header */
1028 if (a_Dpip_dsh_write_str(sh, 0, Header) != 0) {
1029 return 1;
1030 }
1031
1032 if (MODIFY_PAGE_NUM == 2) {
1033 MODIFY_PAGE_NUM = 1;
1035 } else if (MODIFY_PAGE_NUM == 3) {
1036 MODIFY_PAGE_NUM = 1;
1037 return Bmsrv_send_modify_update(sh, NULL);
1038 } else if (MODIFY_PAGE_NUM == 4) {
1039 MODIFY_PAGE_NUM = 1;
1041 } else {
1042 return Bmsrv_send_modify_page(sh);
1043 }
1044}
1045
1046
1047/* Operations */
1048
1049/*
1050 * Parse a delete bms request, delete them, and update bm file.
1051 * Return code: { 0:OK, 1:Abort }
1052 */
1053static int Bmsrv_modify_delete(char *url)
1054{
1055 char *p;
1056 int nb, ns, key;
1057
1058 /* bookmarks were loaded before */
1059
1060 /* Remove marked sections */
1061 p = strchr(url, '?');
1062 for (ns = 0; (p = strstr(p, "&s")); ++p) {
1063 if (isdigit(p[2])) {
1064 key = strtol(p + 2, NULL, 10);
1065 Bms_sec_del(key);
1066 ++ns;
1067 }
1068 }
1069
1070 /* Remove marked urls */
1071 p = strchr(url, '?');
1072 for (nb = 0; (p = strstr(p, "&url")); ++p) {
1073 if (isdigit(p[4])) {
1074 key = strtol(p + 4, NULL, 10);
1075 Bms_del(key);
1076 ++nb;
1077 }
1078 }
1079
1080/* -- This doesn't work because dillo erases the message upon the
1081 * receipt of the first data stream.
1082 *
1083 sprintf(msg, "Deleted %d bookmark%s!>", n, (n > 1) ? "s" : "");
1084 if (Bmsrv_dpi_send_status_msg(sh, msg))
1085 return 1;
1086*/
1087
1088 /* Write new bookmarks file */
1089 if (nb || ns)
1090 Bms_save();
1091
1092 return 0;
1093}
1094
1095/*
1096 * Parse a move urls request, move and update bm file.
1097 * Return code: { 0:OK, 1:Abort }
1098 */
1099static int Bmsrv_modify_move(char *url)
1100{
1101 char *p;
1102 int n, section = 0, key;
1103
1104 /* bookmarks were loaded before */
1105
1106 /* get target section */
1107 for (p = url; (p = strstr(p, "&s")); ++p) {
1108 if (isdigit(p[2])) {
1109 section = strtol(p + 2, NULL, 10);
1110 break;
1111 }
1112 }
1113 if (!p)
1114 return 1;
1115
1116 /* move marked urls */
1117 p = strchr(url, '?');
1118 for (n = 0; (p = strstr(p, "&url")); ++p) {
1119 if (isdigit(p[4])) {
1120 key = strtol(p + 4, NULL, 10);
1121 Bms_move(key, section);
1122 ++n;
1123 }
1124 }
1125
1126 /* Write new bookmarks file */
1127 if (n) {
1128 Bms_save();
1129 }
1130
1131 return 0;
1132}
1133
1134/*
1135 * Parse a modify request: update urls and sections, then save.
1136 * Return code: { 0:OK, 1:Abort }
1137 */
1138static int Bmsrv_modify_update(char *url)
1139{
1140 char *p, *q, *title;
1141 int i, key;
1142
1143 /* bookmarks were loaded before */
1144
1145 p = strchr(url, '?');
1146 for ( ; (p = strstr(p, "s")); ++p) {
1147 if (p[-1] == '&' || p[-1] == '?' ) {
1148 for (i = 0; isdigit(p[1 + i]); ++i);
1149 if (i && p[1 + i] == '=') {
1150 /* we have a title/key to change */
1151 key = strtol(p + 1, NULL, 10);
1152 if ((q = strchr(p + 1, '&')))
1153 title = dStrndup(p + 2 + i, (uint_t)(q - (p + 2 + i)));
1154 else
1155 title = dStrdup(p + 2 + i);
1156
1157 Unencode_str(title);
1158 Bms_update_sec_title(key, title);
1159 dFree(title);
1160 }
1161 }
1162 }
1163
1164 p = strchr(url, '?');
1165 for ( ; (p = strstr(p, "title")); ++p) {
1166 if (p[-1] == '&' || p[-1] == '?' ) {
1167 for (i = 0; isdigit(p[5 + i]); ++i);
1168 if (i && p[5 + i] == '=') {
1169 /* we have a title/key to change */
1170 key = strtol(p + 5, NULL, 10);
1171 if ((q = strchr(p + 5, '&')))
1172 title = dStrndup(p + 6 + i, (uint_t)(q - (p + 6 + i)));
1173 else
1174 title = dStrdup(p + 6 + i);
1175
1176 Unencode_str(title);
1177 Bms_update_title(key, title);
1178 dFree(title);
1179 }
1180 }
1181 }
1182
1183 /* Write new bookmarks file */
1184 Bms_save();
1185
1186 return 0;
1187}
1188
1189/*
1190 * Parse an "add section" request, and update the bm file.
1191 * Return code: { 0:OK, 1:Abort }
1192 */
1193static int Bmsrv_modify_add_section(char *url)
1194{
1195 char *p, *title = NULL;
1196
1197 /* bookmarks were loaded before */
1198
1199 /* get new section's title */
1200 if ((p = strstr(url, "&title="))) {
1201 title = dStrdup (p + 7);
1202 if ((p = strchr(title, '&')))
1203 *p = 0;
1204 Unencode_str(title);
1205 } else
1206 return 1;
1207
1208 Bms_sec_add(title);
1209 dFree(title);
1210
1211 /* Write new bookmarks file */
1212 Bms_save();
1213
1214 return 0;
1215}
1216
1217/*
1218 * Parse an "add url" request, and update the bm file.
1219 * Return code: { 0:OK, 1:Abort }
1220 */
1221static int Bmsrv_modify_add_url(Dsh *sh, char *s_url)
1222{
1223 char *p, *q, *title, *u_title, *url;
1224 int i;
1225 static int section = 0;
1226
1227 /* bookmarks were loaded before */
1228
1229 if (sh == NULL) {
1230 /* look for section */
1231 for (q = s_url; (q = strstr(q, "&s")); ++q) {
1232 for (i = 0; isdigit(q[2+i]); ++i);
1233 if (q[2+i] == '=')
1234 section = strtol(q + 2, NULL, 10);
1235 }
1236 return 1;
1237 }
1238
1239 if (!(p = strstr(s_url, "&title=")) ||
1240 !(q = strstr(s_url, "&url=")))
1241 return 1;
1242
1243 title = dStrdup (p + 7);
1244 if ((p = strchr(title, '&')))
1245 *p = 0;
1246 url = dStrdup (q + 5);
1247 if ((p = strchr(url, '&')))
1248 *p = 0;
1249 if (strlen(title) && strlen(url)) {
1250 Unencode_str(title);
1251 Unencode_str(url);
1252 u_title = Unescape_html_str(title);
1253 Bms_add(section, url, u_title);
1254 dFree(u_title);
1255 }
1256 dFree(title);
1257 dFree(url);
1258 section = 0;
1259
1260 /* TODO: we should send an "Bookmark added" message, but the
1261 msg-after-HTML functionallity is still pending, not hard though. */
1262
1263 /* Write new bookmarks file */
1264 Bms_save();
1265
1266 return 0;
1267}
1268
1269/*
1270 * Check the parameters of a modify request, and return an error message
1271 * when it's wrong.
1272 * Return code: { 0:OK, 2:Close }
1273 */
1274static int Bmsrv_check_modify_request(Dsh *sh, char *url)
1275{
1276 char *p, *msg;
1277 int n_sec, n_url;
1278
1279 /* Count number of marked urls and sections */
1280 Bmsrv_count_urls_and_sections(url, &n_sec, &n_url);
1281
1282 p = strchr(url, '?');
1283 if (strstr(p, "operation=delete&")) {
1284 if (n_url || n_sec)
1285 return 0;
1286 msg = "Delete: you must mark what to delete!";
1287
1288 } else if (strstr(url, "operation=move&")) {
1289 if (n_url && n_sec)
1290 return 0;
1291 else if (n_url)
1292 msg = "Move: you must mark a target section!";
1293 else if (n_sec)
1294 msg = "Move: can not move a section (yet).";
1295 else
1296 msg = "Move: you must mark some urls, and a target section!";
1297
1298 } else if (strstr(url, "operation=modify&")) {
1299 if (n_url || n_sec)
1300 return 0;
1301 msg = "Modify: you must mark what to update!";
1302
1303 } else if (strstr(url, "operation=modify2&")) {
1304 /* nothing to check here */
1305 return 0;
1306
1307 } else if (strstr(url, "operation=add_sec&")) {
1308 /* nothing to check here */
1309 return 0;
1310
1311 } else if (strstr(url, "operation=add_section&")) {
1312 /* nothing to check here */
1313 return 0;
1314
1315 } else if (strstr(url, "operation=add_url&")) {
1316 if (n_sec <= 1)
1317 return 0;
1318 msg = "Add url: only one target section is allowed!";
1319
1320 } else if (strstr(url, "operation=add_url2&")) {
1321 /* nothing to check here */
1322 return 0;
1323
1324 } else if (strstr(url, "operation=none&")) {
1325 msg = "No operation, just do nothing!";
1326
1327 } else {
1328 msg = "Sorry, not implemented yet.";
1329 }
1330
1332 return 2;
1333}
1334
1335/*
1336 * Parse a and process a modify request.
1337 * Return code: { 0:OK, 1:Abort, 2:Close }
1338 */
1339static int Bmsrv_process_modify_request(Dsh *sh, char *url)
1340{
1341 /* check the provided parameters */
1342 if (Bmsrv_check_modify_request(sh, url) != 0)
1343 return 2;
1344
1345 if (strstr(url, "operation=delete&")) {
1346 if (Bmsrv_modify_delete(url) == 1)
1347 return 1;
1348 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1349 return 1;
1350
1351 } else if (strstr(url, "operation=move&")) {
1352 if (Bmsrv_modify_move(url) == 1)
1353 return 1;
1354 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1355 return 1;
1356
1357 } else if (strstr(url, "operation=modify&")) {
1358 /* make a local copy of 'url' */
1359 Bmsrv_send_modify_update(NULL, url);
1360 MODIFY_PAGE_NUM = 3;
1361 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1362 return 1;
1363
1364 } else if (strstr(url, "operation=modify2&")) {
1365 if (Bmsrv_modify_update(url) == 1)
1366 return 1;
1367 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1368 return 1;
1369
1370 } else if (strstr(url, "operation=add_sec&")) {
1371 /* this global variable tells which page to send (--hackish...) */
1372 MODIFY_PAGE_NUM = 2;
1373 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1374 return 1;
1375
1376 } else if (strstr(url, "operation=add_section&")) {
1377 if (Bmsrv_modify_add_section(url) == 1)
1378 return 1;
1379 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1380 return 1;
1381
1382 } else if (strstr(url, "operation=add_url&")) {
1383 /* this global variable tells which page to send (--hackish...) */
1384 MODIFY_PAGE_NUM = 4;
1385 /* parse section if present */
1386 Bmsrv_modify_add_url(NULL, url);
1387 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1388 return 1;
1389
1390 } else if (strstr(url, "operation=add_url2&")) {
1391 if (Bmsrv_modify_add_url(sh, url) == 1)
1392 return 1;
1393 if (Bmsrv_send_reload_request(sh, "dpi:/bm/modify") == 1)
1394 return 1;
1395 }
1396
1397 return 2;
1398}
1399
1400/* -- Bookmarks ------------------------------------------------------------ */
1401
1402/*
1403 * Send the current bookmarks page (in HTML)
1404 */
1405static int send_bm_page(Dsh *sh)
1406{
1407 static Dstr *dstr = NULL;
1408 char *l_title;
1409 BmSec *sec_node;
1410 BmRec *bm_node;
1411 int i, j;
1412
1413 if (!dstr)
1414 dstr = dStr_new("");
1415
1417 return 1;
1418
1419 /* write sections header */
1421 return 1;
1422 /* write sections */
1423 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
1424 if (i > 0) {
1426 return 1;
1427 }
1428
1430 sec_node->section, sec_node->title);
1431 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
1432 return 1;
1433 }
1434 /* write sections footer */
1436 return 1;
1437
1438 /* send page middle */
1440 return 1;
1441
1442 /* send bookmark cards */
1443 for (i = 0; (sec_node = dList_nth_data(B_secs, i)); ++i) {
1444 /* send card header */
1445 l_title = make_one_line_str(sec_node->title);
1447 sec_node->section, l_title);
1448 dFree(l_title);
1449 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
1450 return 1;
1451
1452 /* send section's bookmarks */
1453 for (j = 0; (bm_node = dList_nth_data(B_bms, j)); ++j) {
1454 if (bm_node->section == sec_node->section) {
1456 bm_node->url, bm_node->title);
1457 if (a_Dpip_dsh_write_str(sh, 0, dstr->str))
1458 return 1;
1459 }
1460 }
1461
1462 /* send card footer */
1464 return 1;
1465 }
1466
1467 /* finish page */
1469 return 1;
1470
1471 return 0;
1472}
1473
1474
1475/* -- Dpi parser ----------------------------------------------------------- */
1476
1477/*
1478 * Parse a data stream (dpi protocol)
1479 * Note: Buf is a dpip token (zero terminated string)
1480 * Return code: { 0:OK, 1:Abort, 2:Close }
1481 */
1482static int Bmsrv_parse_token(Dsh *sh, char *Buf)
1483{
1484 static char *msg1=NULL, *msg2=NULL, *msg3=NULL;
1485 char *cmd, *d_cmd, *url, *title, *msg;
1486 size_t BufSize;
1487 int st;
1488
1489 if (!msg1) {
1490 /* Initialize data for the "chat" command. */
1491 msg1 = a_Dpip_build_cmd("cmd=%s msg=%s", "chat", "Hi browser");
1492 msg2 = a_Dpip_build_cmd("cmd=%s msg=%s", "chat", "Is it worth?");
1493 msg3 = a_Dpip_build_cmd("cmd=%s msg=%s", "chat", "Ok, send it");
1494 }
1495
1496 if (sh->mode & DPIP_RAW) {
1497 MSG("ERROR: Unhandled DPIP_RAW mode!\n");
1498 return 1;
1499 }
1500
1501 BufSize = strlen(Buf);
1502 cmd = a_Dpip_get_attr_l(Buf, BufSize, "cmd");
1503
1504 if (cmd && strcmp(cmd, "chat") == 0) {
1505 dFree(cmd);
1506 msg = a_Dpip_get_attr_l(Buf, BufSize, "msg");
1507 if (*msg == 'H') {
1508 /* "Hi server" */
1509 if (a_Dpip_dsh_write_str(sh, 1, msg1))
1510 return 1;
1511 } else if (*msg == 'I') {
1512 /* "I want to set abookmark" */
1513 if (a_Dpip_dsh_write_str(sh, 1, msg2))
1514 return 1;
1515 } else if (*msg == 'S') {
1516 /* "Sure" */
1517 if (a_Dpip_dsh_write_str(sh, 1, msg3))
1518 return 1;
1519 }
1520 dFree(msg);
1521 return 0;
1522 }
1523
1524 /* sync with the bookmarks file */
1525 Bms_cond_load();
1526
1527 if (cmd && strcmp(cmd, "DpiBye") == 0) {
1528 MSG("(pid %d): Got DpiBye.\n", (int)getpid());
1529 exit(0);
1530
1531 } else if (cmd && strcmp(cmd, "add_bookmark") == 0) {
1532 dFree(cmd);
1533 url = a_Dpip_get_attr_l(Buf, BufSize, "url");
1534 title = a_Dpip_get_attr_l(Buf, BufSize, "title");
1535 if (strlen(title) == 0) {
1536 dFree(title);
1537 title = dStrdup("(Untitled)");
1538 }
1539 if (url && title)
1540 Bmsrv_add_bm(sh, url, title);
1541 dFree(url);
1542 dFree(title);
1543 return 2;
1544
1545 } else if (cmd && strcmp(cmd, "open_url") == 0) {
1546 dFree(cmd);
1547 url = a_Dpip_get_attr_l(Buf, BufSize, "url");
1548
1549 if (dStrnAsciiCasecmp(url, "dpi:", 4) == 0) {
1550 if (strcmp(url+4, "/bm/modify") == 0) {
1551 st = Bmsrv_send_modify_answer(sh, url);
1552 dFree(url);
1553 return st;
1554 } else if (strncmp(url+4, "/bm/modify?", 11) == 0) {
1555 /* process request */
1557 dFree(url);
1558 return st;
1559 }
1560 }
1561
1562
1563 d_cmd = a_Dpip_build_cmd("cmd=%s url=%s", "start_send_page", url);
1564 dFree(url);
1565 st = a_Dpip_dsh_write_str(sh, 1, d_cmd);
1566 dFree(d_cmd);
1567 if (st != 0)
1568 return 1;
1569
1570 /* Send HTTP header */
1571 if (a_Dpip_dsh_write_str(sh, 1, Header) != 0) {
1572 return 1;
1573 }
1574
1575 st = send_bm_page(sh);
1576 if (st != 0) {
1577 char *err =
1578 DOCTYPE
1579 "<HTML><body id='dillo_bm'> Error on the bookmarks server..."
1580 " </body></html>";
1581 if (a_Dpip_dsh_write_str(sh, 1, err) != 0) {
1582 return 1;
1583 }
1584 }
1585 return 2;
1586 }
1587
1588 return 0;
1589}
1590
1591/* -- Termination handlers ----------------------------------------------- */
1592/*
1593 * (was to delete the local namespace socket),
1594 * but this is handled by 'dpid' now.
1595 */
1596static void cleanup(void)
1597{
1598 /* no cleanup required */
1599}
1600
1601/*
1602 * Perform any necessary cleanups upon abnormal termination
1603 */
1604static void termination_handler(int signum)
1605{
1606 exit(signum);
1607}
1608
1609
1610/*
1611 * -- MAIN -------------------------------------------------------------------
1612 */
1613int main(void) {
1614 struct sockaddr_un spun;
1615 int sock_fd, code;
1616 socklen_t address_size;
1617 char *tok;
1618 Dsh *sh;
1619
1620 /* Arrange the cleanup function for terminations via exit() */
1621 atexit(cleanup);
1622
1623 /* Arrange the cleanup function for abnormal terminations */
1624 if (signal (SIGINT, termination_handler) == SIG_IGN)
1625 signal (SIGINT, SIG_IGN);
1626 if (signal (SIGHUP, termination_handler) == SIG_IGN)
1627 signal (SIGHUP, SIG_IGN);
1628 if (signal (SIGTERM, termination_handler) == SIG_IGN)
1629 signal (SIGTERM, SIG_IGN);
1630
1631 /* We may receive SIGPIPE (e.g. socket is closed early by our client) */
1632 signal(SIGPIPE, SIG_IGN);
1633
1634 /* Initialize local data */
1635 B_bms = dList_new(512);
1636 B_secs = dList_new(32);
1637 BmFile = dStrconcat(dGethomedir(), "/.dillo/bm.txt", NULL);
1638 /* some OSes may need this... */
1639 address_size = sizeof(struct sockaddr_un);
1640
1641 MSG("(v.13): accepting connections...\n");
1642
1643 while (1) {
1644 sock_fd = accept(STDIN_FILENO, (struct sockaddr *)&spun, &address_size);
1645 if (sock_fd == -1) {
1646 perror("[accept]");
1647 exit(1);
1648 }
1649
1650 /* create the Dsh structure */
1651 sh = a_Dpip_dsh_new(sock_fd, sock_fd, 8*1024);
1652
1653 /* Authenticate our client... */
1654 if (!(tok = a_Dpip_dsh_read_token(sh, 1)) ||
1655 a_Dpip_check_auth(tok) < 0) {
1656 MSG("can't authenticate request: %s\n", dStrerror(errno));
1658 exit(1);
1659 }
1660 dFree(tok);
1661
1662 while (1) {
1663 code = 1;
1664 if ((tok = a_Dpip_dsh_read_token(sh, 1)) != NULL) {
1665 /* Let's see what we fished... */
1666 code = Bmsrv_parse_token(sh, tok);
1667 }
1668 dFree(tok);
1669
1670 if (code != 0) {
1671 /* socket is not operative (e.g. closed by client) */
1672 break;
1673 }
1674 }
1675
1678
1679 }/*while*/
1680}
static int Bmsrv_send_reload_request(Dsh *sh, char *url)
Definition bookmarks.c:824
static int Bms_sec_by_number_cmp(const void *node, const void *key)
Definition bookmarks.c:386
static int Bmsrv_parse_token(Dsh *sh, char *Buf)
Definition bookmarks.c:1482
static void Bms_add(int section, char *url, char *title)
Definition bookmarks.c:410
static char * Header
Definition bookmarks.c:86
static const char * modifypage_section_card_header
Definition bookmarks.c:178
static int sec_key
Definition bookmarks.c:93
static Dlist * B_secs
Definition bookmarks.c:92
static int Bmsrv_send_modify_update(Dsh *sh, char *url)
Definition bookmarks.c:940
static const char * mainpage_sections_header
Definition bookmarks.c:149
static int Bmsrv_send_modify_page_add_section(Dsh *sh)
Definition bookmarks.c:913
static Dlist * B_bms
Definition bookmarks.c:89
static const char * modifypage_update_footer
Definition bookmarks.c:263
static int Bms_save(void)
Definition bookmarks.c:714
#define modifypage_sections_footer
Definition bookmarks.c:168
static const char * modifypage_middle1
Definition bookmarks.c:172
static int Bmsrv_modify_delete(char *url)
Definition bookmarks.c:1053
static const char * modifypage_footer
Definition bookmarks.c:202
#define MSG(...)
Definition bookmarks.c:46
static int Bmsrv_send_modify_page(Dsh *sh)
Definition bookmarks.c:839
static const char * mainpage_section_card_footer
Definition bookmarks.c:193
static const char * modifypage_add_url
Definition bookmarks.c:270
static int MODIFY_PAGE_NUM
Definition bookmarks.c:95
static const char * modifypage_update_item
Definition bookmarks.c:249
static int Bmsrv_check_modify_request(Dsh *sh, char *url)
Definition bookmarks.c:1274
static const char * mainpage_footer
Definition bookmarks.c:198
static void Bms_check_import(void)
Definition bookmarks.c:573
static const char * modifypage_sections_item
Definition bookmarks.c:161
static BmSec * Bms_get_sec(int key)
Definition bookmarks.c:402
static time_t BmFileTimeStamp
Definition bookmarks.c:88
static void Bms_move(int key, int target_section)
Definition bookmarks.c:481
static void cleanup(void)
Definition bookmarks.c:1596
static const char * modifypage_update_item_header
Definition bookmarks.c:246
static void Bms_free(void)
Definition bookmarks.c:522
static void Bmsrv_count_urls_and_sections(char *url, int *n_sec, int *n_url)
Definition bookmarks.c:801
static int send_bm_page(Dsh *sh)
Definition bookmarks.c:1405
static void Bms_update_title(int key, char *n_title)
Definition bookmarks.c:494
static int Bmsrv_add_bm(Dsh *sh, char *url, char *title)
Definition bookmarks.c:776
static const char * mainpage_sections_footer
Definition bookmarks.c:164
static int Bmsrv_modify_update(char *url)
Definition bookmarks.c:1138
static int Bmsrv_modify_move(char *url)
Definition bookmarks.c:1099
static void Bms_sec_add(char *title)
Definition bookmarks.c:425
static const char * mainpage_header
Definition bookmarks.c:105
static int Bmsrv_dpi_send_status_msg(Dsh *sh, char *str)
Definition bookmarks.c:355
int main(void)
Definition bookmarks.c:1613
#define modifypage_sections_header
Definition bookmarks.c:153
static const char * modifypage_update_item2
Definition bookmarks.c:255
static int Bms_load(void)
Definition bookmarks.c:614
static const char * modifypage_update_header
Definition bookmarks.c:231
static void termination_handler(int signum)
Definition bookmarks.c:1604
static const char * mainpage_section_card_header
Definition bookmarks.c:174
static const char * mainpage_section_card_item
Definition bookmarks.c:182
static void Unencode_str(char *e_str)
Definition bookmarks.c:329
static int Bms_node_by_key_cmp(const void *node, const void *key)
Definition bookmarks.c:370
static int Bmsrv_modify_add_url(Dsh *sh, char *s_url)
Definition bookmarks.c:1221
static void Bms_sec_del(int section)
Definition bookmarks.c:456
static const char * modifypage_update_title
Definition bookmarks.c:243
static const char * sections_sep
Definition bookmarks.c:158
static void Bms_update_sec_title(int key, char *n_title)
Definition bookmarks.c:508
static int Bmsrv_send_modify_answer(Dsh *sh, char *url)
Definition bookmarks.c:1016
static BmRec * Bms_get(int key)
Definition bookmarks.c:394
static const char * modifypage_section_card_item
Definition bookmarks.c:187
static int Bmsrv_modify_add_section(char *url)
Definition bookmarks.c:1193
static const char * modifypage_update_item_footer
Definition bookmarks.c:260
static int bm_key
Definition bookmarks.c:90
static char * BmFile
Definition bookmarks.c:87
static const char * mainpage_middle1
Definition bookmarks.c:170
#define DOCTYPE
Definition bookmarks.c:48
static const char * modifypage_add_section_page
Definition bookmarks.c:208
static const char * modifypage_header
Definition bookmarks.c:119
#define modifypage_section_card_footer
Definition bookmarks.c:196
static int Bmsrv_process_modify_request(Dsh *sh, char *url)
Definition bookmarks.c:1339
static void Bms_normalize(void)
Definition bookmarks.c:540
static char * make_one_line_str(char *str)
Definition bookmarks.c:301
static int Bmsrv_send_modify_page_add_url(Dsh *sh)
Definition bookmarks.c:926
static const char * mainpage_sections_item
Definition bookmarks.c:155
static int Bms_cond_load(void)
Definition bookmarks.c:688
static void Bms_del(int key)
Definition bookmarks.c:438
#define CSS_STYLE
Definition bookmarks.c:51
static int Bms_node_by_section_cmp(const void *node, const void *key)
Definition bookmarks.c:378
unsigned int uint_t
Definition d_size.h:20
static Dsh * sh
Definition datauri.c:39
char * dGetline(FILE *stream)
Get a line from a FILE stream.
Definition dlib.c:928
char * dStrconcat(const char *s1,...)
Concatenate a NULL-terminated list of strings.
Definition dlib.c:102
void dFree(void *mem)
Definition dlib.c:68
char * dStrdup(const char *s)
Definition dlib.c:77
Dlist * dList_new(int size)
Create a new empty list.
Definition dlib.c:548
int dStrnAsciiCasecmp(const char *s1, const char *s2, size_t n)
Definition dlib.c:215
int dList_length(Dlist *lp)
For completing the ADT.
Definition dlib.c:613
void * dList_nth_data(Dlist *lp, int n0)
Return the nth data item, NULL when not found or 'n0' is out of range.
Definition dlib.c:662
void dStr_free(Dstr *ds, int all)
Free a dillo string.
Definition dlib.c:337
char * dStrndup(const char *s, size_t sz)
Definition dlib.c:88
void dStr_sprintf(Dstr *ds, const char *format,...)
Printf-like function.
Definition dlib.c:450
Dstr * dStr_new(const char *s)
Create a new string.
Definition dlib.c:325
void dList_append(Dlist *lp, void *data)
Append a data item to the list.
Definition dlib.c:597
void * dList_find_custom(Dlist *lp, const void *data, dCompareFunc func)
Search a data item using a custom function.
Definition dlib.c:704
void dList_remove(Dlist *lp, const void *data)
Definition dlib.c:641
char * dGethomedir(void)
Return the home directory in a static string (don't free)
Definition dlib.c:906
#define dStrerror
Definition dlib.h:95
#define VOIDP2INT(p)
Definition dlib.h:43
#define TRUE
Definition dlib.h:23
#define INT2VOIDP(i)
Definition dlib.h:44
#define dNew(type, count)
Definition dlib.h:49
static void error(char *msg)
Definition dpidc.c:39
void a_Dpip_dsh_free(Dsh *dsh)
Free the SockHandler structure.
Definition dpip.c:525
char * a_Dpip_build_cmd(const char *format,...)
Printf like function for building dpip commands.
Definition dpip.c:83
int a_Dpip_dsh_write_str(Dsh *dsh, int flush, const char *str)
Convenience function.
Definition dpip.c:374
char * a_Dpip_dsh_read_token(Dsh *dsh, int blocking)
Return a newlly allocated string with the next dpip token in the socket.
Definition dpip.c:493
void a_Dpip_dsh_close(Dsh *dsh)
Close this socket for reading and writing.
Definition dpip.c:504
char * a_Dpip_get_attr_l(const char *tag, size_t tagsize, const char *attrname)
Task: given a tag, its size and an attribute name, return the attribute value (stuffing of ' is remov...
Definition dpip.c:134
int a_Dpip_check_auth(const char *auth_tag)
Check whether the given 'auth' string equals what dpid saved.
Definition dpip.c:201
Dsh * a_Dpip_dsh_new(int fd_in, int fd_out, int flush_sz)
Create and initialize a dpip socket handler.
Definition dpip.c:247
#define DPIP_RAW
Raw data in the socket
Definition dpip.h:19
char * Escape_html_str(const char *str)
Definition dpiutil.c:93
char * Unescape_html_str(const char *str)
Definition dpiutil.c:115
char * Escape_uri_str(const char *str, const char *p_esc_set)
Definition dpiutil.c:36
Definition dlib.h:131
Dpip socket handler type.
Definition dpip.h:31
int mode
mode flags: DPIP_TAG | DPIP_LAST_TAG | DPIP_RAW
Definition dpip.h:41
Definition dlib.h:102
Dstr_char_t * str
Definition dlib.h:105
int len
Definition dlib.h:104