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